diff --git a/.gitignore b/.gitignore index 17b164d6..455cd629 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ # Build /target /Cargo.lock +/.cargo # Editors .DS_Store diff --git a/Cargo.toml b/Cargo.toml index 16228c03..497dfa9d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tonlib" -version = "0.5.4" +version = "0.6.1" edition = "2021" description = "Rust SDK for The Open Network" license = "MIT" diff --git a/README.md b/README.md index 4a70dcb3..527dceb6 100644 --- a/README.md +++ b/README.md @@ -197,7 +197,7 @@ let wallet_address = contract.get_wallet_address(&owner_address).await?; Create key pair from secret phrase (mnemonic) ```rust -let mnemonic_str = "" +let mnemonic_str = ""; let mnemonic: Mnemonic = Mnemonic::from_str(mnemonic_str, &None).unwrap(); let key_pair: KeyPair = mnemonic.to_key_pair().unwrap(); ``` @@ -255,7 +255,7 @@ let body = wallet.create_external_body(now + 60, SEQNO, transfer)?; let signed = wallet.sign_external_body(&body)?; let wrapped = wallet.wrap_signed_body(signed)?; let boc = BagOfCells::from_root(wrapped); -let tx = boc.serialize(true)? +let tx = boc.serialize(true)?; let hash = client.send_raw_message_return_hash(tx.as_slice()).await?; ``` diff --git a/src/client/types.rs b/src/client/types.rs index 1ad180a6..e116b155 100644 --- a/src/client/types.rs +++ b/src/client/types.rs @@ -1,6 +1,6 @@ -use crate::client::connection::TonConnection; use crate::config::MAINNET_CONFIG; use crate::tl::TonFunction; +use crate::{client::connection::TonConnection, tl::stack::TvmCell}; use anyhow::anyhow; use async_trait::async_trait; use lazy_static::lazy_static; @@ -232,6 +232,51 @@ pub trait TonFunctions { Ok(result) } + async fn smc_load_by_transaction( + &self, + account_address: &str, + transaction_id: &InternalTransactionId, + ) -> anyhow::Result<(TonConnection, i64)> { + let func = TonFunction::SmcLoadByTransaction { + account_address: AccountAddress { + account_address: String::from(account_address), + }, + transaction_id: transaction_id.clone(), + }; + let (conn, result) = self.invoke_on_connection(&func).await?; + match result { + TonResult::SmcInfo(smc_info) => Ok((conn, smc_info.id)), + r => Err(anyhow!("Expected SmcInfo, got: {:?}", r)), + } + } + + async fn smc_get_code(&self, id: i64) -> anyhow::Result { + let func = TonFunction::SmcGetCode { id: id }; + let result = self.invoke(&func).await?; + match result { + TonResult::TvmCell(cell) => Ok(cell), + r => Err(anyhow!("Expected TvmCell, got: {:?}", r)), + } + } + + async fn smc_get_data(&self, id: i64) -> anyhow::Result { + let func = TonFunction::SmcGetData { id: id }; + let result = self.invoke(&func).await?; + match result { + TonResult::TvmCell(cell) => Ok(cell), + r => Err(anyhow!("Expected TvmCell, got: {:?}", r)), + } + } + + async fn smc_get_state(&self, id: i64) -> anyhow::Result { + let func = TonFunction::SmcGetState { id: id }; + let result = self.invoke(&func).await?; + match result { + TonResult::TvmCell(cell) => Ok(cell), + r => Err(anyhow!("Expected TvmCell, got: {:?}", r)), + } + } + async fn get_masterchain_info(&self) -> anyhow::Result { let func = TonFunction::BlocksGetMasterchainInfo {}; let result = self.invoke(&func).await?; diff --git a/src/tl/function.rs b/src/tl/function.rs index 620cba84..4cf01eba 100644 --- a/src/tl/function.rs +++ b/src/tl/function.rs @@ -59,11 +59,29 @@ pub enum TonFunction { SmcLoad { account_address: AccountAddress, }, + #[serde(rename = "smc.loadByTransaction")] + SmcLoadByTransaction { + account_address: AccountAddress, + transaction_id: InternalTransactionId, + }, + // tonlib_api.tl, line 302 #[serde(rename = "smc.forget")] SmcForget { id: i64, }, + #[serde(rename = "smc.getCode")] + SmcGetCode { + id: i64, + }, + #[serde(rename = "smc.getData")] + SmcGetData { + id: i64, + }, + #[serde(rename = "smc.getState")] + SmcGetState { + id: i64, + }, // tonlib_api.tl, line 298 #[serde(rename = "smc.runGetMethod")] SmcRunGetMethod { diff --git a/src/tl/result.rs b/src/tl/result.rs index 8cf22906..63b3fa7b 100644 --- a/src/tl/result.rs +++ b/src/tl/result.rs @@ -2,6 +2,7 @@ use anyhow::anyhow; use serde::{Deserialize, Serialize}; use strum::IntoStaticStr; +use crate::tl::stack::TvmCell; use crate::tl::types::{ BlockIdExt, BlocksHeader, BlocksMasterchainInfo, BlocksShards, BlocksTransactions, FullAccountState, LogVerbosityLevel, OptionsInfo, RawExtMessageInfo, RawFullAccountState, @@ -36,28 +37,31 @@ pub enum TonResult { // tonlib_api.tl, line 88 #[serde(rename = "fullAccountState")] FullAccountState(FullAccountState), - // tonlib_api.tl, line 176 + // tonlib_api.tl, line 177 #[serde(rename = "smc.info")] SmcInfo(SmcInfo), - // tonlib_api.tl, line 181 + // tonlib_api.tl, line 182 #[serde(rename = "smc.runResult")] SmcRunResult(SmcRunResult), - // tonlib_api.tl, line 187 + // tonlib_api.tl, line 165 + #[serde(rename = "tvm.cell")] + TvmCell(TvmCell), + // tonlib_api.tl, line 188 #[serde(rename = "updateSyncState")] UpdateSyncState(UpdateSyncState), - // tonlib_api.tl, line 202 + // tonlib_api.tl, line 345 #[serde(rename = "logVerbosityLevel")] LogVerbosityLevel(LogVerbosityLevel), // tonlib_api.tl, line 212 #[serde(rename = "blocks.masterchainInfo")] BlocksMasterchainInfo(BlocksMasterchainInfo), - // tonlib_api.tl, line 213 + // tonlib_api.tl, line 214 #[serde(rename = "blocks.shards")] BlocksShards(BlocksShards), - // tonlib_api.tl, line 216 + // tonlib_api.tl, line 218 #[serde(rename = "blocks.transactions")] BlocksTransactions(BlocksTransactions), - // tonlib_api.tl, line 217 + // tonlib_api.tl, line 219 #[serde(rename = "blocks.header")] BlocksHeader(BlocksHeader), } diff --git a/tests/client_test.rs b/tests/client_test.rs index e722532c..f0c7ccbc 100644 --- a/tests/client_test.rs +++ b/tests/client_test.rs @@ -1,5 +1,5 @@ -use std::thread; use std::time::Duration; +use std::{str::FromStr, thread}; use tokio; use tokio::time::timeout; @@ -97,6 +97,60 @@ async fn client_smc_run_get_method_works() -> anyhow::Result<()> { Ok(()) } +#[tokio::test] +async fn client_smc_load_by_transaction_works() -> anyhow::Result<()> { + common::init_logging(); + + let client = common::new_test_client().await?; + let address = "EQCVx4vipWfDkf2uNhTUkpT97wkzRXHm-N1cNn_kqcLxecxT"; + let internal_transaction_id = InternalTransactionId::from_str( + "32016630000001:91485a21ba6eaaa91827e357378fe332228d11f3644e802f7e0f873a11ce9c6f", + )?; + + let state = client.get_raw_account_state(address).await.unwrap(); + + println!("TRANSACTION_ID{}", &state.last_transaction_id); + let res = client + .smc_load_by_transaction(address, &internal_transaction_id) + .await; + + assert!(res.is_ok()); + Ok(()) +} + +#[tokio::test] +async fn client_smc_get_code_works() -> anyhow::Result<()> { + common::init_logging(); + let client = common::new_test_client().await?; + let address = "EQDk2VTvn04SUKJrW7rXahzdF8_Qi6utb0wj43InCu9vdjrR"; + let (_, id1) = client.smc_load(address).await?; + let cell = client.smc_get_code(id1).await?; + println!("\n\r\x1b[1;35m-----------------------------------------CODE-----------------------------------------\x1b[0m:\n\r {:?}",cell); + Ok(()) +} + +#[tokio::test] +async fn client_smc_get_data_works() -> anyhow::Result<()> { + common::init_logging(); + let client = common::new_test_client().await?; + let address = "EQDk2VTvn04SUKJrW7rXahzdF8_Qi6utb0wj43InCu9vdjrR"; + let (_, id1) = client.smc_load(address).await?; + let cell = client.smc_get_data(id1).await?; + println!("\n\r\x1b[1;35m-----------------------------------------DATA-----------------------------------------\x1b[0m:\n\r {:?}",cell); + Ok(()) +} + +#[tokio::test] +async fn client_smc_get_state_works() -> anyhow::Result<()> { + common::init_logging(); + let client = common::new_test_client().await?; + let address = "EQDk2VTvn04SUKJrW7rXahzdF8_Qi6utb0wj43InCu9vdjrR"; + let (_, id1) = client.smc_load(address).await?; + let cell = client.smc_get_state(id1).await?; + println!("\n\r\x1b[1;35m-----------------------------------------STATE----------------------------------------\x1b[0m:\n\r {:?}",cell); + Ok(()) +} + #[tokio::test] async fn client_get_block_header_works() -> anyhow::Result<()> { common::init_logging();