diff --git a/CHANGELOG.md b/CHANGELOG.md index 4071702a..314dff82 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,23 @@ All notable changes to this project will be documented in this file. +## [1.44.0] – 2023-07-12 + +### New + +- Ability to call async functions via `tc_request_sync`. +- In rust API, the following functions become sync (slight breaking): + `abi::encode_internal_message`, `abi::attach_signature_to_message_body`, `abi::attach_signature`, + `abi::decode_message`, `abi::decode_message_body`, `abi::decode_account_data`, + `abi::update_initial_data`, `abi::encode_initial_data`, `abi::decode_initial_data`, + `abi::decode_boc`, `abi::encode_boc`, `boc::decode_tvc`, `boc::parse_message`, `boc::parse_transaction`, + `boc::parse_account`, `boc::parse_block`, `boc::parse_shardstate`, `boc::get_blockchain_config`, + `boc::get_boc_hash`, `boc::get_code_from_tvc`, `boc::cache_get`, `boc::cache_set`, `boc::cache_unpin`, + `boc::encode_boc`, `boc::get_code_salt`, `boc::set_code_salt`, `boc::decode_state_init`, `boc::encode_state_init`, + `boc::encode_external_in_message`, `boc::get_compiler_version`, `processing::monitor_messages`, + `processing::get_monitor_info`, `processing::cancel_monitor` +- Code generator for `modules.ts` produces `_sync` wrapper for all API functions. + ## [1.43.3] – 2023-06-24 ### Fixed diff --git a/Cargo.lock b/Cargo.lock index 34ec7ab9..026cc472 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -113,7 +113,7 @@ checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" [[package]] name = "api_derive" -version = "1.43.3" +version = "1.44.0" dependencies = [ "api_info", "proc-macro2", @@ -124,7 +124,7 @@ dependencies = [ [[package]] name = "api_info" -version = "1.43.3" +version = "1.44.0" dependencies = [ "serde", "serde_derive", @@ -133,7 +133,7 @@ dependencies = [ [[package]] name = "api_test" -version = "1.43.3" +version = "1.44.0" dependencies = [ "api_derive", "api_info", @@ -2601,7 +2601,7 @@ dependencies = [ [[package]] name = "ton_client" -version = "1.43.3" +version = "1.44.0" dependencies = [ "aes", "api_derive", @@ -2668,7 +2668,7 @@ dependencies = [ [[package]] name = "ton_client_processing" -version = "1.43.3" +version = "1.44.0" dependencies = [ "api_derive", "api_info", @@ -2700,7 +2700,7 @@ dependencies = [ [[package]] name = "ton_sdk" -version = "1.43.3" +version = "1.44.0" dependencies = [ "api_derive", "api_info", @@ -2807,7 +2807,7 @@ dependencies = [ [[package]] name = "toncli" -version = "1.43.3" +version = "1.44.0" dependencies = [ "api_info", "assert_cmd", diff --git a/api/derive/Cargo.toml b/api/derive/Cargo.toml index 3fdd0b80..88bac0ea 100644 --- a/api/derive/Cargo.toml +++ b/api/derive/Cargo.toml @@ -2,7 +2,7 @@ authors = [ 'TON Labs LTD ' ] edition = '2018' name = 'api_derive' -version = '1.43.3' +version = '1.44.0' [dependencies] quote = '1.0.26' diff --git a/api/info/Cargo.toml b/api/info/Cargo.toml index bf246596..c0caeae8 100644 --- a/api/info/Cargo.toml +++ b/api/info/Cargo.toml @@ -2,7 +2,7 @@ authors = [ 'TON Labs LTD ' ] edition = '2018' name = 'api_info' -version = '1.43.3' +version = '1.44.0' [dependencies] serde = '1.0.115' diff --git a/api/test/Cargo.toml b/api/test/Cargo.toml index 4e08034c..f0f9f086 100644 --- a/api/test/Cargo.toml +++ b/api/test/Cargo.toml @@ -2,7 +2,7 @@ authors = [ 'TON Labs LTD ' ] edition = '2018' name = 'api_test' -version = '1.43.3' +version = '1.44.0' [dependencies] serde = '1.0.115' diff --git a/ton_client/Cargo.toml b/ton_client/Cargo.toml index 9341defd..4cd46ba3 100644 --- a/ton_client/Cargo.toml +++ b/ton_client/Cargo.toml @@ -1,6 +1,6 @@ [package] name = 'ton_client' -version = '1.43.3' +version = '1.44.0' authors = [ 'TON Labs LTD ' ] edition = '2018' license = 'Apache-2.0' diff --git a/ton_client/src/abi/decode_boc.rs b/ton_client/src/abi/decode_boc.rs index 2587c6ce..6656c627 100644 --- a/ton_client/src/abi/decode_boc.rs +++ b/ton_client/src/abi/decode_boc.rs @@ -18,7 +18,7 @@ pub struct ParamsOfDecodeBoc { pub boc: String, // Do not check if all BOC data is parsed by provided parameters set // Set it to `true` if don't need to decode the whole BOC data or if you need - // to handle conditional parsing (when TLB constructor or flags should be + // to handle conditional parsing (when TLB constructor or flags should be // checked to decide how to parse remaining BOC data) pub allow_partial: bool, } @@ -30,29 +30,29 @@ pub struct ResultOfDecodeBoc { } /// Decodes BOC into JSON as a set of provided parameters. -/// -/// Solidity functions use ABI types for [builder encoding](https://github.com/tonlabs/TON-Solidity-Compiler/blob/master/API.md#tvmbuilderstore). -/// The simplest way to decode such a BOC is to use ABI decoding. -/// ABI has it own rules for fields layout in cells so manually encoded -/// BOC can not be described in terms of ABI rules. -/// -/// To solve this problem we introduce a new ABI type `Ref()` -/// which allows to store `ParamType` ABI parameter in cell reference and, thus, -/// decode manually encoded BOCs. This type is available only in `decode_boc` function +/// +/// Solidity functions use ABI types for [builder encoding](https://github.com/tonlabs/TON-Solidity-Compiler/blob/master/API.md#tvmbuilderstore). +/// The simplest way to decode such a BOC is to use ABI decoding. +/// ABI has it own rules for fields layout in cells so manually encoded +/// BOC can not be described in terms of ABI rules. +/// +/// To solve this problem we introduce a new ABI type `Ref()` +/// which allows to store `ParamType` ABI parameter in cell reference and, thus, +/// decode manually encoded BOCs. This type is available only in `decode_boc` function /// and will not be available in ABI messages encoding until it is included into some ABI revision. -/// -/// Such BOC descriptions covers most users needs. If someone wants to decode some BOC which -/// can not be described by these rules (i.e. BOC with TLB containing constructors of flags -/// defining some parsing conditions) then they can decode the fields up to fork condition, -/// check the parsed data manually, expand the parsing schema and then decode the whole BOC +/// +/// Such BOC descriptions covers most users needs. If someone wants to decode some BOC which +/// can not be described by these rules (i.e. BOC with TLB containing constructors of flags +/// defining some parsing conditions) then they can decode the fields up to fork condition, +/// check the parsed data manually, expand the parsing schema and then decode the whole BOC /// with the full schema. #[api_function] -pub async fn decode_boc( +pub fn decode_boc( context: Arc, params: ParamsOfDecodeBoc, ) -> ClientResult { - let (_, data) = deserialize_cell_from_boc(&context, ¶ms.boc, "").await?; + let (_, data) = deserialize_cell_from_boc(&context, ¶ms.boc, "")?; let mut abi_params = Vec::with_capacity(params.params.len()); for param in params.params { diff --git a/ton_client/src/abi/decode_data.rs b/ton_client/src/abi/decode_data.rs index 672b4f2a..262f3b8d 100644 --- a/ton_client/src/abi/decode_data.rs +++ b/ton_client/src/abi/decode_data.rs @@ -35,11 +35,11 @@ pub struct ResultOfDecodeAccountData { /// /// Note: this feature requires ABI 2.1 or higher. #[api_function] -pub async fn decode_account_data( +pub fn decode_account_data( context: Arc, params: ParamsOfDecodeAccountData, ) -> ClientResult { - let (_, data) = deserialize_cell_from_boc(&context, ¶ms.data, "contract data").await?; + let (_, data) = deserialize_cell_from_boc(&context, ¶ms.data, "contract data")?; let abi = params.abi.abi()?; let tokens = abi.decode_storage_fields(slice_from_cell(data)?, params.allow_partial) diff --git a/ton_client/src/abi/decode_message.rs b/ton_client/src/abi/decode_message.rs index b45c5819..dc4637ce 100644 --- a/ton_client/src/abi/decode_message.rs +++ b/ton_client/src/abi/decode_message.rs @@ -100,19 +100,19 @@ pub struct ParamsOfDecodeMessage { /// Function name or function id if is known in advance pub function_name: Option, - // For external (inbound and outbound) messages data_layout parameter is ignored. - // For internal: by default SDK tries to decode as output and then if decode is not successfull - tries as input. - // If explicitly specified then tries only the specified layout. + // For external (inbound and outbound) messages data_layout parameter is ignored. + // For internal: by default SDK tries to decode as output and then if decode is not successfull - tries as input. + // If explicitly specified then tries only the specified layout. pub data_layout: Option, } /// Decodes message body using provided message BOC and ABI. #[api_function] -pub async fn decode_message( +pub fn decode_message( context: Arc, params: ParamsOfDecodeMessage, ) -> ClientResult { - let (abi, message) = prepare_decode(&context, ¶ms).await?; + let (abi, message) = prepare_decode(&context, ¶ms)?; if let Some(body) = message.body() { let data_layout = match message.header() { ton_block::CommonMsgInfo::ExtInMsgInfo(_) => Some(DataLayout::Input), @@ -151,29 +151,28 @@ pub struct ParamsOfDecodeMessageBody { pub function_name: Option, // By default SDK tries to decode as output and then if decode is not successfull - tries as input. - // If explicitly specified then tries only the specified layout. + // If explicitly specified then tries only the specified layout. pub data_layout: Option, } /// Decodes message body using provided body BOC and ABI. #[api_function] -pub async fn decode_message_body( +pub fn decode_message_body( context: Arc, params: ParamsOfDecodeMessageBody, ) -> ClientResult { let abi = params.abi.abi()?; - let (_, body) = deserialize_cell_from_boc(&context, ¶ms.body, "message body").await?; + let (_, body) = deserialize_cell_from_boc(&context, ¶ms.body, "message body")?; let body = slice_from_cell(body)?; decode_body(abi, body, params.is_internal, params.allow_partial, params.function_name, params.data_layout) } -async fn prepare_decode( +fn prepare_decode( context: &ClientContext, params: &ParamsOfDecodeMessage, ) -> ClientResult<(AbiContract, ton_block::Message)> { let abi = params.abi.abi()?; let message = deserialize_object_from_boc(context, ¶ms.message, "message") - .await .map_err(|x| Error::invalid_message_for_decode(x))?; Ok((abi, message.object)) } @@ -300,7 +299,7 @@ fn decode_with_function( function_name, tokens: decoded, }; - DecodedMessageBody::new(MessageBodyType::Event, decoded, None) + DecodedMessageBody::new(MessageBodyType::Event, decoded, None) } } } @@ -358,7 +357,7 @@ pub async fn get_signature_data( params: ParamsOfGetSignatureData, ) -> ClientResult { let abi = params.abi.abi()?; - let message: ton_block::Message = deserialize_object_from_boc(&context, ¶ms.message, "message").await?.object; + let message: ton_block::Message = deserialize_object_from_boc(&context, ¶ms.message, "message")?.object; if let Some(body) = message.body() { let address = message.dst() .ok_or_else(|| Error::invalid_message_for_decode( @@ -367,8 +366,8 @@ pub async fn get_signature_data( let (signature, hash) = abi.get_signature_data(body, Some(address)) .map_err(|err| Error::invalid_message_for_decode(err))?; let unsigned = extend_data_to_sign(&context, params.signature_id, Some(hash)).await?; - Ok(ResultOfGetSignatureData { - signature: hex::encode(&signature), + Ok(ResultOfGetSignatureData { + signature: hex::encode(&signature), unsigned: base64::encode(&unsigned.unwrap()), }) } else { @@ -376,4 +375,4 @@ pub async fn get_signature_data( "The message body is empty", )) } -} \ No newline at end of file +} diff --git a/ton_client/src/abi/encode_account.rs b/ton_client/src/abi/encode_account.rs index 39384b6a..1a9c14c2 100644 --- a/ton_client/src/abi/encode_account.rs +++ b/ton_client/src/abi/encode_account.rs @@ -84,25 +84,25 @@ async fn state_init_from_message( let (message, _) = message.encode(context).await?; let message = deserialize_object_from_boc::( context, &message, "message" - ).await?.object; + )?.object; message .state_init() .map(|x| x.clone()) .ok_or(Error::invalid_message_for_decode("missing `state_init`")) } -async fn state_init_from_bocs( +fn state_init_from_bocs( context: &ClientContext, code: &String, data: &String, library: &Option, ) -> ClientResult { Ok(StateInit { - code: Some(deserialize_cell_from_boc(context, code, "account code").await?.1), - data: Some(deserialize_cell_from_boc(context, data, "account data").await?.1), + code: Some(deserialize_cell_from_boc(context, code, "account code")?.1), + data: Some(deserialize_cell_from_boc(context, data, "account data")?.1), library: if let Some(library) = library { StateInitLib::with_hashmap( - Some(deserialize_cell_from_boc(context, library, "library").await?.1) + Some(deserialize_cell_from_boc(context, library, "library")?.1) ) } else { StateInitLib::default() @@ -112,13 +112,13 @@ async fn state_init_from_bocs( }) } -async fn state_init_from_tvc( +fn state_init_from_tvc( context: &ClientContext, tvc: &String, public_key: &Option, init_params: &Option, ) -> ClientResult { - let (_, cell) = deserialize_cell_from_boc(context, tvc, "TVC image").await?; + let (_, cell) = deserialize_cell_from_boc(context, tvc, "TVC image")?; let public_key = public_key .as_ref() .map(|x| decode_public_key(x)) @@ -160,12 +160,12 @@ pub async fn encode_account( code, data, library, - } => state_init_from_bocs(&context, code, data, library).await, + } => state_init_from_bocs(&context, code, data, library), StateInitSource::Tvc { tvc, public_key, init_params, - } => state_init_from_tvc(&context, tvc, public_key, init_params).await, + } => state_init_from_tvc(&context, tvc, public_key, init_params), }?; let id = state_init.hash().map_err(|err| Error::invalid_tvc_image(err))?; let address = MsgAddressInt::with_standart(None, 0, id.clone().into()).unwrap(); @@ -175,7 +175,7 @@ pub async fn encode_account( .map_err(|err| Error::invalid_tvc_image(err))?; account.set_last_tr_time(params.last_trans_lt.unwrap_or(0)); Ok(ResultOfEncodeAccount { - account: serialize_object_to_boc(&context, &account, "account", params.boc_cache).await?, + account: serialize_object_to_boc(&context, &account, "account", params.boc_cache)?, id: id.as_hex_string(), }) } diff --git a/ton_client/src/abi/encode_boc.rs b/ton_client/src/abi/encode_boc.rs index 02fd6624..3cd1ea0d 100644 --- a/ton_client/src/abi/encode_boc.rs +++ b/ton_client/src/abi/encode_boc.rs @@ -30,7 +30,7 @@ pub struct ResultOfAbiEncodeBoc { /// Encodes given parameters in JSON into a BOC using param types from ABI. #[api_function] -pub async fn encode_boc( +pub fn encode_boc( context: Arc, params: ParamsOfAbiEncodeBoc, ) -> ClientResult { @@ -49,6 +49,6 @@ pub async fn encode_boc( .map_err(|err| Error::invalid_abi(err))?; Ok(ResultOfAbiEncodeBoc { - boc: serialize_cell_to_boc(&context, cell, "ABI params", params.boc_cache).await?, + boc: serialize_cell_to_boc(&context, cell, "ABI params", params.boc_cache)?, }) } diff --git a/ton_client/src/abi/encode_message.rs b/ton_client/src/abi/encode_message.rs index 14a0dbe7..3f3e0e20 100644 --- a/ton_client/src/abi/encode_message.rs +++ b/ton_client/src/abi/encode_message.rs @@ -60,19 +60,17 @@ impl DeploySet { }) } - pub async fn get_state_init(&self, context: &ClientContext) -> ClientResult { + pub fn get_state_init(&self, context: &ClientContext) -> ClientResult { let error = |err| Err(Error::encode_deploy_message_failed(err)); match (&self.tvc, &self.code, &self.state_init) { (Some(tvc_or_state_init), None, None) => { - resolve_state_init_cell(context, tvc_or_state_init).await + resolve_state_init_cell(context, tvc_or_state_init) } (None, Some(code), None) => { - state_init_with_code(deserialize_cell_from_boc(context, code, "code").await?.1) + state_init_with_code(deserialize_cell_from_boc(context, code, "code")?.1) } (None, None, Some(state_init)) => { - Ok(deserialize_cell_from_boc(context, state_init, "state init") - .await? - .1) + Ok(deserialize_cell_from_boc(context, state_init, "state init")?.1) } (None, None, None) => error( "at least one of the `tvc`, `code` or `state_init` value should be specified.", @@ -508,7 +506,7 @@ pub async fn encode_message( let mut image = create_tvc_image( &abi, deploy_set.initial_data.as_ref(), - deploy_set.get_state_init(&context).await?, + deploy_set.get_state_init(&context)?, )?; required_public_key(update_pubkey(&deploy_set, &mut image, &public)?)?; @@ -620,7 +618,7 @@ pub struct ResultOfEncodeInternalMessage { /// 2. Public key, specified in TVM file. #[api_function] -pub async fn encode_internal_message( +pub fn encode_internal_message( context: Arc, params: ParamsOfEncodeInternalMessage, ) -> ClientResult { @@ -652,7 +650,7 @@ pub async fn encode_internal_message( let mut image = create_tvc_image( &abi, deploy_set.initial_data.as_ref(), - deploy_set.get_state_init(&context).await?, + deploy_set.get_state_init(&context)?, )?; let public = update_pubkey(&deploy_set, &mut image, &None)?; @@ -892,11 +890,11 @@ pub struct ResultOfAttachSignature { /// Combines `hex`-encoded `signature` with `base64`-encoded `unsigned_message`. /// Returns signed message encoded in `base64`. #[api_function] -pub async fn attach_signature( +pub fn attach_signature( context: Arc, params: ParamsOfAttachSignature, ) -> ClientResult { - let (boc, _) = deserialize_cell_from_boc(&context, ¶ms.message, "message").await?; + let (boc, _) = deserialize_cell_from_boc(&context, ¶ms.message, "message")?; let signed = add_sign_to_message( ¶ms.abi.json_string()?, &hex_decode(¶ms.signature)?, @@ -933,11 +931,11 @@ pub struct ResultOfAttachSignatureToMessageBody { /// #[api_function] -pub async fn attach_signature_to_message_body( +pub fn attach_signature_to_message_body( context: Arc, params: ParamsOfAttachSignatureToMessageBody, ) -> ClientResult { - let (boc, _) = deserialize_cell_from_boc(&context, ¶ms.message, "message body").await?; + let (boc, _) = deserialize_cell_from_boc(&context, ¶ms.message, "message body")?; let signed = add_sign_to_message_body( ¶ms.abi.json_string()?, &hex_decode(¶ms.signature)?, diff --git a/ton_client/src/abi/init_data.rs b/ton_client/src/abi/init_data.rs index a663bf83..57e97ac9 100644 --- a/ton_client/src/abi/init_data.rs +++ b/ton_client/src/abi/init_data.rs @@ -36,16 +36,16 @@ pub struct ResultOfUpdateInitialData { /// This operation is applicable only for initial account data (before deploy). /// If the contract is already deployed, its data doesn't contain this data section any more. #[api_function] -pub async fn update_initial_data( +pub fn update_initial_data( context: Arc, params: ParamsOfUpdateInitialData, ) -> ClientResult { - let (_, mut data) = deserialize_cell_from_boc(&context, ¶ms.data, "contract data").await?; + let (_, mut data) = deserialize_cell_from_boc(&context, ¶ms.data, "contract data")?; data = update_initial_data_internal(¶ms.initial_data, ¶ms.abi, ¶ms.initial_pubkey, data)?; Ok(ResultOfUpdateInitialData { - data: serialize_cell_to_boc(&context, data, "contract data", params.boc_cache).await? + data: serialize_cell_to_boc(&context, data, "contract data", params.boc_cache)? }) } @@ -110,7 +110,7 @@ pub struct ResultOfEncodeInitialData { /// /// This function is analogue of `tvm.buildDataInit` function in Solidity. #[api_function] -pub async fn encode_initial_data( +pub fn encode_initial_data( context: Arc, params: ParamsOfEncodeInitialData, ) -> ClientResult { @@ -122,7 +122,7 @@ pub async fn encode_initial_data( )?; Ok(ResultOfEncodeInitialData { - data: serialize_cell_to_boc(&context, data, "contract data", params.boc_cache).await? + data: serialize_cell_to_boc(&context, data, "contract data", params.boc_cache)? }) } @@ -152,11 +152,11 @@ pub struct ResultOfDecodeInitialData { /// This operation is applicable only for initial account data (before deploy). /// If the contract is already deployed, its data doesn't contain this data section any more. #[api_function] -pub async fn decode_initial_data( +pub fn decode_initial_data( context: Arc, params: ParamsOfDecodeInitialData, ) -> ClientResult { - let (_, data) = deserialize_cell_from_boc(&context, ¶ms.data, "contract data").await?; + let (_, data) = deserialize_cell_from_boc(&context, ¶ms.data, "contract data")?; let data = slice_from_cell(data)?; let initial_pubkey = ton_abi::Contract::get_pubkey(&data) diff --git a/ton_client/src/abi/tests.rs b/ton_client/src/abi/tests.rs index 3be96475..1f7d6161 100644 --- a/ton_client/src/abi/tests.rs +++ b/ton_client/src/abi/tests.rs @@ -466,15 +466,15 @@ fn test_is_empty_pubkey() -> Result<()> { Ok(()) } -#[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn test_resolve_pubkey() -> Result<()> { +#[test] +fn test_resolve_pubkey() -> Result<()> { let context = crate::ClientContext::new(crate::ClientConfig::default()).unwrap(); let tvc = base64::encode(include_bytes!("../tests/contracts/abi_v2/Hello.tvc")); let mut deploy_set = DeploySet { tvc: Some(tvc.clone()), ..Default::default() }; - let mut image = create_tvc_image("", None, resolve_state_init_cell(&context, &tvc).await?)?; + let mut image = create_tvc_image("", None, resolve_state_init_cell(&context, &tvc)?)?; assert!(resolve_pubkey(&deploy_set, &image, &None)?.is_none()); let external_pub_key = @@ -591,7 +591,7 @@ async fn test_encode_message_pubkey_internal( let mut image = create_tvc_image( &abi.json_string()?, None, - resolve_state_init_cell(&context, tvc.as_ref().unwrap()).await?, + resolve_state_init_cell(&context, tvc.as_ref().unwrap())?, )?; if let Some(tvc_pubkey) = tvc_pubkey { image.set_public_key(tvc_pubkey)?; @@ -648,7 +648,7 @@ async fn test_encode_internal_message() -> Result<()> { let image = create_tvc_image( &abi.json_string()?, None, - resolve_state_init_cell(&context, tvc.as_ref().unwrap()).await?, + resolve_state_init_cell(&context, tvc.as_ref().unwrap())?, )?; let address = String::from("0:1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"); @@ -1345,7 +1345,7 @@ async fn test_deploy_code_variants_with_fn< secret: "cc8929d635719612a9478b9cd17675a39cfad52d8959e8a177389b8c0b9122a7".into(), }; let state_init_cell = - resolve_state_init_cell(&client.context(), &unknown_tvc.clone().unwrap()).await?; + resolve_state_init_cell(&client.context(), &unknown_tvc.clone().unwrap())?; let state_init = deserialize_object_from_cell::(state_init_cell.clone(), "state init")?; @@ -1448,7 +1448,6 @@ async fn encode_internal_deploy( boc: encoded.message, }, ) - .await .unwrap() .parsed } @@ -1486,7 +1485,6 @@ async fn encode_deploy( boc: encoded.message, }, ) - .await .unwrap() .parsed } diff --git a/ton_client/src/boc/blockchain_config.rs b/ton_client/src/boc/blockchain_config.rs index 7bb09b08..5f756d4f 100644 --- a/ton_client/src/boc/blockchain_config.rs +++ b/ton_client/src/boc/blockchain_config.rs @@ -31,18 +31,18 @@ pub struct ResultOfGetBlockchainConfig { /// Extract blockchain configuration from key block and also from zerostate. #[api_function] -pub async fn get_blockchain_config( +pub fn get_blockchain_config( context: std::sync::Arc, params: ParamsOfGetBlockchainConfig, ) -> ClientResult { - let config = if let Ok(block) = - deserialize_object_from_boc::(&context, ¶ms.block_boc, "block").await + let config = if let Ok(block) = + deserialize_object_from_boc::(&context, ¶ms.block_boc, "block") { extract_config_from_block(&block.object)? } else { let zerostate = deserialize_object_from_boc::( &context, ¶ms.block_boc, "zerostate" - ).await?; + )?; extract_config_from_zerostate(&zerostate.object)? }; diff --git a/ton_client/src/boc/cache.rs b/ton_client/src/boc/cache.rs index 36d12c09..950cbbe2 100644 --- a/ton_client/src/boc/cache.rs +++ b/ton_client/src/boc/cache.rs @@ -101,13 +101,13 @@ pub struct PinnedBoc { cell: Cell, } -pub struct CachedBoc { +pub struct InnerCachedBoc { size: usize, cell: Cell, } pub struct CachedBocs { - bocs: LruCache, + bocs: LruCache, cache_size: usize, } @@ -200,7 +200,7 @@ impl Bocs { .ok_or(Error::insufficient_cache_size(self.max_cache_size, size))?; lock.cache_size -= entry.size; } - lock.bocs.put(hash.clone(), CachedBoc { cell, size }); + lock.bocs.put(hash.clone(), InnerCachedBoc { cell, size }); lock.cache_size += size; Ok(()) @@ -322,11 +322,11 @@ pub struct ResultOfBocCacheSet { /// Save BOC into cache or increase pin counter for existing pinned BOC #[api_function] -pub async fn cache_set( +pub fn cache_set( context: Arc, params: ParamsOfBocCacheSet, ) -> ClientResult { - let (bytes, cell) = deserialize_cell_from_boc(&context, ¶ms.boc, "BOC").await?; + let (bytes, cell) = deserialize_cell_from_boc(&context, ¶ms.boc, "BOC")?; let size = match bytes { DeserializedBoc::Bytes(bytes) => Some(bytes.len()), _ => None, @@ -353,7 +353,7 @@ pub struct ResultOfBocCacheGet { /// Get BOC from cache #[api_function] -pub async fn cache_get( +pub fn cache_get( context: Arc, params: ParamsOfBocCacheGet, ) -> ClientResult { @@ -380,7 +380,7 @@ pub struct ParamsOfBocCacheUnpin { /// Decrease pin reference counter for BOCs with specified pin defined in the `cache_set`. /// BOCs which have only 1 pin and its reference counter become 0 will be removed from cache #[api_function] -pub async fn cache_unpin( +pub fn cache_unpin( context: Arc, params: ParamsOfBocCacheUnpin, ) -> ClientResult<()> { @@ -391,3 +391,43 @@ pub async fn cache_unpin( context.bocs.unpin(¶ms.pin, hash); Ok(()) } + +#[derive(Debug)] +pub struct CachedBoc { + context: Arc, + boc_ref: String, + pin: String, +} + +impl CachedBoc { + pub fn new(context: Arc, boc: String, pin: String) -> ClientResult { + let boc_ref = cache_set( + context.clone(), + ParamsOfBocCacheSet { + boc, + cache_type: BocCacheType::Pinned { pin: pin.clone() }, + })?.boc_ref; + + Ok(Self { context, boc_ref, pin }) + } + + pub fn boc_ref(&self) -> String { + self.boc_ref.clone() + } + + pub fn try_clone(&self) -> ClientResult { + CachedBoc::new(self.context.clone(), self.boc_ref.clone(), self.pin.clone()) + } +} + +impl Drop for CachedBoc { + fn drop(&mut self) { + let _ = cache_unpin( + self.context.clone(), + ParamsOfBocCacheUnpin { + pin: std::mem::take(&mut self.pin), + boc_ref: Some(std::mem::take(&mut self.boc_ref)) + } + ); + } +} diff --git a/ton_client/src/boc/common.rs b/ton_client/src/boc/common.rs index ea330336..d0417440 100644 --- a/ton_client/src/boc/common.rs +++ b/ton_client/src/boc/common.rs @@ -29,11 +29,11 @@ pub struct ResultOfGetBocHash { /// Calculates BOC root hash #[api_function] -pub async fn get_boc_hash( +pub fn get_boc_hash( context: std::sync::Arc, params: ParamsOfGetBocHash, ) -> ClientResult { - let (_, cell) = deserialize_cell_from_boc(&context, ¶ms.boc, "").await?; + let (_, cell) = deserialize_cell_from_boc(&context, ¶ms.boc, "")?; let hash = cell.repr_hash().as_hex_string(); Ok(ResultOfGetBocHash { hash }) } @@ -52,12 +52,12 @@ pub struct ResultOfGetBocDepth { /// Calculates BOC depth #[api_function] -pub async fn get_boc_depth( +pub fn get_boc_depth( context: std::sync::Arc, params: ParamsOfGetBocDepth, ) -> ClientResult { - let (_, cell) = deserialize_cell_from_boc(&context, ¶ms.boc, "").await?; - Ok(ResultOfGetBocDepth { + let (_, cell) = deserialize_cell_from_boc(&context, ¶ms.boc, "")?; + Ok(ResultOfGetBocDepth { depth: cell.repr_depth() as u32 }) } diff --git a/ton_client/src/boc/encode.rs b/ton_client/src/boc/encode.rs index 3ae6c0e7..c2701b47 100644 --- a/ton_client/src/boc/encode.rs +++ b/ton_client/src/boc/encode.rs @@ -8,10 +8,10 @@ use ton_types::{BuilderData, Cell, IBitstring}; use super::{internal::serialize_cell_to_boc, Error}; use crate::boc::internal::deserialize_cell_from_boc; use crate::boc::BocCacheType; +use crate::encoding::account_decode; use num_bigint::{BigInt, BigUint, Sign}; use num_traits::Num; use std::ops::ShlAssign; -use crate::encoding::account_decode; /// Cell builder operation. #[derive(Serialize, Deserialize, Clone, ApiType)] @@ -61,7 +61,7 @@ pub enum BuilderOp { Address { /// Address in a common `workchain:account` or base64 format. address: String, - } + }, } impl Default for BuilderOp { @@ -90,17 +90,17 @@ pub struct ResultOfEncodeBoc { /// Encodes bag of cells (BOC) with builder operations. /// This method provides the same functionality as Solidity TvmBuilder. -/// Resulting BOC of this method can be passed into +/// Resulting BOC of this method can be passed into /// Solidity and C++ contracts as TvmCell type. #[api_function] -pub async fn encode_boc( +pub fn encode_boc( context: std::sync::Arc, params: ParamsOfEncodeBoc, ) -> ClientResult { let mut stack = Vec::::new(); let mut builder = Builder::new(¶ms.builder); loop { - match builder.build(&context).await? { + match builder.build(&context)? { BuildResult::Nested { nested, prev } => { stack.push(prev); builder = nested; @@ -108,13 +108,18 @@ pub async fn encode_boc( BuildResult::Complete(cell) => { if let Some(prev) = stack.pop() { builder = prev; - builder.result.checked_append_reference(cell).map_err( - |err| Error::serialization_error(err, "encoded cell"), - )?; + builder + .result + .checked_append_reference(cell) + .map_err(|err| Error::serialization_error(err, "encoded cell"))?; } else { return Ok(ResultOfEncodeBoc { - boc: serialize_cell_to_boc(&context, cell, "encoded cell", params.boc_cache) - .await?, + boc: serialize_cell_to_boc( + &context, + cell, + "encoded cell", + params.boc_cache, + )?, }); } } @@ -145,7 +150,7 @@ impl<'a> Builder<'a> { /// Append data using operation iterator until the end or the nested cell operation. /// Returns resulting cell or nested Builder. - async fn build( + fn build( mut self, context: &std::sync::Arc, ) -> ClientResult> { @@ -158,13 +163,11 @@ impl<'a> Builder<'a> { append_bitstring(&mut self.result, &value)?; } BuilderOp::CellBoc { boc } => { - self.result.checked_append_reference( - deserialize_cell_from_boc(context, boc, "CellBoc") - .await? - .1, - ).map_err( - |err| Error::serialization_error(err, "encode_boc"), - )?; + self.result + .checked_append_reference( + deserialize_cell_from_boc(context, boc, "CellBoc")?.1, + ) + .map_err(|err| Error::serialization_error(err, "encode_boc"))?; } BuilderOp::Cell { ref builder } => { return Ok(BuildResult::Nested { diff --git a/ton_client/src/boc/encode_external_in_message.rs b/ton_client/src/boc/encode_external_in_message.rs index fe992480..5fd4f591 100644 --- a/ton_client/src/boc/encode_external_in_message.rs +++ b/ton_client/src/boc/encode_external_in_message.rs @@ -40,7 +40,7 @@ pub struct ResultOfEncodeExternalInMessage { /// Allows to encode any external inbound message. /// #[api_function] -pub async fn encode_external_in_message( +pub fn encode_external_in_message( context: std::sync::Arc, params: ParamsOfEncodeExternalInMessage, ) -> ClientResult { @@ -63,20 +63,18 @@ pub async fn encode_external_in_message( let mut msg = ton_block::Message::with_ext_in_header(header); if let Some(init) = params.init { msg.set_state_init( - deserialize_object_from_boc::(&context, &init, "state init") - .await? - .object, + deserialize_object_from_boc::(&context, &init, "state init")?.object, ); } if let Some(body) = params.body { - let (_, cell) = deserialize_cell_from_boc(&context, &body, "message body").await?; + let (_, cell) = deserialize_cell_from_boc(&context, &body, "message body")?; msg.set_body(slice_from_cell(cell)?); } let hash = msg .hash() .map_err(|err| crate::client::errors::Error::internal_error(err))?; - let boc = serialize_object_to_boc(&context, &msg, "message", params.boc_cache).await?; + let boc = serialize_object_to_boc(&context, &msg, "message", params.boc_cache)?; Ok(ResultOfEncodeExternalInMessage { message: boc, message_id: hex::encode(hash), diff --git a/ton_client/src/boc/internal.rs b/ton_client/src/boc/internal.rs index b7dad2d6..c04592f3 100644 --- a/ton_client/src/boc/internal.rs +++ b/ton_client/src/boc/internal.rs @@ -125,16 +125,16 @@ pub fn serialize_object_to_base64( Ok(serialize_cell_to_base64(&cell, name)?) } -pub async fn deserialize_cell_from_boc( +pub fn deserialize_cell_from_boc( context: &ClientContext, boc: &str, name: &str ) -> ClientResult<(DeserializedBoc, ton_types::Cell)> { context.bocs.deserialize_cell(boc, name) } -pub async fn deserialize_object_from_boc( +pub fn deserialize_object_from_boc( context: &ClientContext, boc: &str, name: &str, ) -> ClientResult> { - let (boc, cell) = deserialize_cell_from_boc(context, boc, name).await?; + let (boc, cell) = deserialize_cell_from_boc(context, boc, name)?; let object = deserialize_object_from_cell(cell.clone(), name)?; @@ -152,7 +152,7 @@ pub fn deserialize_object_from_boc_bin( Ok((object, root_hash)) } -pub async fn serialize_cell_to_boc( +pub fn serialize_cell_to_boc( context: &ClientContext, cell: ton_types::Cell, name: &str, boc_cache: Option, ) -> ClientResult { if let Some(cache_type) = boc_cache { @@ -165,9 +165,9 @@ pub async fn serialize_cell_to_boc( } } -pub async fn serialize_object_to_boc( +pub fn serialize_object_to_boc( context: &ClientContext, object: &S,name: &str, boc_cache: Option, ) -> ClientResult { let cell = serialize_object_to_cell(object, name)?; - serialize_cell_to_boc(context, cell, name, boc_cache).await + serialize_cell_to_boc(context, cell, name, boc_cache) } diff --git a/ton_client/src/boc/mod.rs b/ton_client/src/boc/mod.rs index 97fa664a..6683bee8 100644 --- a/ton_client/src/boc/mod.rs +++ b/ton_client/src/boc/mod.rs @@ -31,8 +31,8 @@ pub use blockchain_config::{ get_blockchain_config, ParamsOfGetBlockchainConfig, ResultOfGetBlockchainConfig, }; pub use cache::{ - cache_get, cache_set, cache_unpin, BocCacheType, ParamsOfBocCacheGet, ParamsOfBocCacheSet, - ParamsOfBocCacheUnpin, ResultOfBocCacheGet, ResultOfBocCacheSet, + cache_get, cache_set, cache_unpin, BocCacheType, CachedBoc, ParamsOfBocCacheGet, + ParamsOfBocCacheSet, ParamsOfBocCacheUnpin, ResultOfBocCacheGet, ResultOfBocCacheSet, }; pub use common::{ get_boc_depth, get_boc_hash, ParamsOfGetBocDepth, ParamsOfGetBocHash, ResultOfGetBocDepth, diff --git a/ton_client/src/boc/parse.rs b/ton_client/src/boc/parse.rs index 5bf965b0..76eaef4a 100644 --- a/ton_client/src/boc/parse.rs +++ b/ton_client/src/boc/parse.rs @@ -43,11 +43,11 @@ pub struct ResultOfParse { /// /// JSON structure is compatible with GraphQL API message object #[api_function] -pub async fn parse_message( +pub fn parse_message( context: std::sync::Arc, params: ParamsOfParse, ) -> ClientResult { - let object = deserialize_object_from_boc::(&context, ¶ms.boc, "message").await?; + let object = deserialize_object_from_boc::(&context, ¶ms.boc, "message")?; let set = ton_block_json::MessageSerializationSet { block_id: None, @@ -77,12 +77,12 @@ pub async fn parse_message( /// /// JSON structure is compatible with GraphQL API transaction object #[api_function] -pub async fn parse_transaction( +pub fn parse_transaction( context: std::sync::Arc, params: ParamsOfParse, ) -> ClientResult { let object = - deserialize_object_from_boc::(&context, ¶ms.boc, "transaction").await?; + deserialize_object_from_boc::(&context, ¶ms.boc, "transaction")?; let set = ton_block_json::TransactionSerializationSetEx { block_id: None, @@ -110,11 +110,11 @@ pub async fn parse_transaction( /// /// JSON structure is compatible with GraphQL API account object #[api_function] -pub async fn parse_account( +pub fn parse_account( context: std::sync::Arc, params: ParamsOfParse, ) -> ClientResult { - let object = deserialize_object_from_boc::(&context, ¶ms.boc, "account").await?; + let object = deserialize_object_from_boc::(&context, ¶ms.boc, "account")?; let set = ton_block_json::AccountSerializationSet { boc: object.boc.bytes("account")?, @@ -139,11 +139,11 @@ pub async fn parse_account( /// /// JSON structure is compatible with GraphQL API block object #[api_function] -pub async fn parse_block( +pub fn parse_block( context: std::sync::Arc, params: ParamsOfParse, ) -> ClientResult { - let object = deserialize_object_from_boc::(&context, ¶ms.boc, "block").await?; + let object = deserialize_object_from_boc::(&context, ¶ms.boc, "block")?; let set = ton_block_json::BlockSerializationSet { boc: object.boc.bytes("block")?, @@ -169,12 +169,12 @@ pub async fn parse_block( /// /// JSON structure is compatible with GraphQL API shardstate object #[api_function] -pub async fn parse_shardstate( +pub fn parse_shardstate( context: std::sync::Arc, params: ParamsOfParseShardstate, ) -> ClientResult { let object = - deserialize_object_from_boc::(&context, ¶ms.boc, "shardstate").await?; + deserialize_object_from_boc::(&context, ¶ms.boc, "shardstate")?; let set = ton_block_json::ShardStateSerializationSet { boc: object.boc.bytes("shardstate")?, diff --git a/ton_client/src/boc/state_init.rs b/ton_client/src/boc/state_init.rs index 3549d676..c9e8e159 100644 --- a/ton_client/src/boc/state_init.rs +++ b/ton_client/src/boc/state_init.rs @@ -14,6 +14,7 @@ use ton_block::{Number5, StateInit, StateInitLib, TickTock}; use ton_types::{BuilderData, Cell}; +use super::BocCacheType; use crate::boc::internal::{ deserialize_cell_from_boc, deserialize_object_from_boc, deserialize_object_from_cell, serialize_cell_to_boc, serialize_object_to_boc, @@ -24,8 +25,6 @@ use crate::client::ClientContext; use crate::encoding::slice_from_cell; use crate::error::ClientResult; -use super::BocCacheType; - const OLD_CPP_SELECTOR_DATA: &[u8] = &[ 0xff, 0x00, 0x20, 0xc1, 0x01, 0xf4, 0xa4, 0x20, 0x58, 0x92, 0xf4, 0xa0, 0xe0, 0x5f, 0x02, 0x8a, 0x20, 0xed, 0x53, 0xd9, @@ -54,11 +53,11 @@ pub struct ResultOfGetCodeFromTvc { /// Extracts code from TVC contract image #[api_function] -pub async fn get_code_from_tvc( +pub fn get_code_from_tvc( context: std::sync::Arc, params: ParamsOfGetCodeFromTvc, ) -> ClientResult { - let state_init_cell = resolve_state_init_cell(&context, ¶ms.tvc).await?; + let state_init_cell = resolve_state_init_cell(&context, ¶ms.tvc)?; let object = deserialize_object_from_cell::(state_init_cell, "TVC")?; let code = object @@ -129,16 +128,21 @@ pub struct ResultOfGetCodeSalt { /// Returns the contract code's salt if it is present. #[api_function] -pub async fn get_code_salt( +pub fn get_code_salt( context: std::sync::Arc, params: ParamsOfGetCodeSalt, ) -> ClientResult { - let (_, code) = deserialize_cell_from_boc(&context, ¶ms.code, "contract code").await?; + let (_, code) = deserialize_cell_from_boc(&context, ¶ms.code, "contract code")?; let (salt, _) = get_salt_and_ver(code)?; let salt = if let Some(salt) = salt { - Some(serialize_cell_to_boc(&context, salt, "code salt", params.boc_cache).await?) + Some(serialize_cell_to_boc( + &context, + salt, + "code salt", + params.boc_cache, + )?) } else { None }; @@ -220,12 +224,12 @@ pub struct ResultOfSetCodeSalt { /// Sets new salt to contract code. Returns the new contract code with salt. #[api_function] -pub async fn set_code_salt( +pub fn set_code_salt( context: std::sync::Arc, params: ParamsOfSetCodeSalt, ) -> ClientResult { - let (_, code) = deserialize_cell_from_boc(&context, ¶ms.code, "contract code").await?; - let (_, salt) = deserialize_cell_from_boc(&context, ¶ms.salt, "salt").await?; + let (_, code) = deserialize_cell_from_boc(&context, ¶ms.code, "contract code")?; + let (_, salt) = deserialize_cell_from_boc(&context, ¶ms.salt, "salt")?; let code = match code.data() { OLD_CPP_SELECTOR_DATA => set_old_selector_salt(code, salt), @@ -238,7 +242,7 @@ pub async fn set_code_salt( }?; Ok(ResultOfSetCodeSalt { - code: serialize_cell_to_boc(&context, code, "contract code", params.boc_cache).await?, + code: serialize_cell_to_boc(&context, code, "contract code", params.boc_cache)?, }) } @@ -269,11 +273,11 @@ pub fn get_compiler_version_from_cell(code: Cell) -> ClientResult /// Returns the compiler version used to compile the code. #[api_function] -pub async fn get_compiler_version( +pub fn get_compiler_version( context: std::sync::Arc, params: ParamsOfGetCompilerVersion, ) -> ClientResult { - let (_, code) = deserialize_cell_from_boc(&context, ¶ms.code, "contract code").await?; + let (_, code) = deserialize_cell_from_boc(&context, ¶ms.code, "contract code")?; let version = get_compiler_version_from_cell(code)?; Ok(ResultOfGetCompilerVersion { version }) @@ -307,25 +311,21 @@ pub struct ResultOfEncodeStateInit { /// Encodes initial contract state from code, data, libraries ans special options (see input params) #[api_function] -pub async fn encode_state_init( +pub fn encode_state_init( context: std::sync::Arc, params: ParamsOfEncodeStateInit, ) -> ClientResult { let get_cell = |name, boc| { let context = context.clone(); - async move { - if let Some(boc) = boc { - deserialize_cell_from_boc(&context, boc, name) - .await - .map(|val| Some(val.1)) - } else { - Ok(None) - } + if let Some(boc) = boc { + deserialize_cell_from_boc(&context, boc, name).map(|val| Some(val.1)) + } else { + Ok(None) } }; - let code = get_cell("code", params.code.as_deref()).await?; - let data = get_cell("data", params.data.as_deref()).await?; - let library = StateInitLib::with_hashmap(get_cell("library", params.library.as_deref()).await?); + let code = get_cell("code", params.code.as_deref())?; + let data = get_cell("data", params.data.as_deref())?; + let library = StateInitLib::with_hashmap(get_cell("library", params.library.as_deref())?); let special = if params.tick.is_some() || params.tock.is_some() { Some(TickTock { @@ -349,7 +349,7 @@ pub async fn encode_state_init( }; Ok(ResultOfEncodeStateInit { - state_init: serialize_object_to_boc(&context, &state, "TVC", params.boc_cache).await?, + state_init: serialize_object_to_boc(&context, &state, "TVC", params.boc_cache)?, }) } @@ -390,23 +390,18 @@ pub struct ResultOfDecodeStateInit { /// Decodes contract's initial state into code, data, libraries and special options. #[api_function] -pub async fn decode_state_init( +pub fn decode_state_init( context: std::sync::Arc, params: ParamsOfDecodeStateInit, ) -> ClientResult { - let state_init = - deserialize_object_from_boc::(&context, ¶ms.state_init, "TVC").await?; + let state_init = deserialize_object_from_boc::(&context, ¶ms.state_init, "TVC")?; let serialize = |name, cell, boc_cache| { let context = context.clone(); - async move { - if let Some(cell) = cell { - serialize_cell_to_boc(&context, cell, name, boc_cache) - .await - .map(Some) - } else { - Ok(None) - } + if let Some(cell) = cell { + serialize_cell_to_boc(&context, cell, name, boc_cache).map(Some) + } else { + Ok(None) } }; let code_depth = state_init @@ -426,7 +421,7 @@ pub async fn decode_state_init( .map(|cell| get_compiler_version_from_cell(cell).ok()) .flatten() .flatten(); - let code = serialize("code", state_init.object.code, params.boc_cache.clone()).await?; + let code = serialize("code", state_init.object.code, params.boc_cache.clone())?; let data_depth = state_init .object @@ -438,14 +433,13 @@ pub async fn decode_state_init( .data .as_ref() .map(|cell| cell.repr_hash().as_hex_string()); - let data = serialize("data", state_init.object.data, params.boc_cache.clone()).await?; + let data = serialize("data", state_init.object.data, params.boc_cache.clone())?; let library = serialize( "library", state_init.object.library.root().cloned(), params.boc_cache.clone(), - ) - .await?; + )?; Ok(ResultOfDecodeStateInit { code, diff --git a/ton_client/src/boc/tests.rs b/ton_client/src/boc/tests.rs index 63c95d49..b8679665 100644 --- a/ton_client/src/boc/tests.rs +++ b/ton_client/src/boc/tests.rs @@ -27,8 +27,8 @@ use std::str::FromStr; use ton_block::{MsgAddrStd, MsgAddressInt, Serializable}; use ton_types::{AccountId, BuilderData, IBitstring}; -#[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn test_encode_boc() { +#[test] +fn test_encode_boc() { fn write_b(value: u8) -> BuilderOp { BuilderOp::Integer { size: 1, @@ -69,7 +69,7 @@ async fn test_encode_boc() { } let client = TestClient::new(); - let encode_boc = client.wrap_async( + let encode_boc = client.wrap( encode_boc, BocModule::api(), super::encode::encode_boc_api(), @@ -154,7 +154,6 @@ async fn test_encode_boc() { ], boc_cache: None, }) - .await .unwrap(); assert_eq!(boc, response.boc); @@ -179,17 +178,16 @@ async fn test_encode_boc() { ], boc_cache: None, }) - .await .unwrap(); assert_eq!(boc, response.boc); } -#[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn test_pinned_cache() { +#[test] +fn test_pinned_cache() { let client = TestClient::new(); - let cache_set = client.wrap_async(cache_set, BocModule::api(), super::cache::cache_set_api()); - let cache_get = client.wrap_async(cache_get, BocModule::api(), super::cache::cache_get_api()); - let cache_unpin = client.wrap_async( + let cache_set = client.wrap(cache_set, BocModule::api(), super::cache::cache_set_api()); + let cache_get = client.wrap(cache_get, BocModule::api(), super::cache::cache_get_api()); + let cache_unpin = client.wrap( cache_unpin, BocModule::api(), super::cache::cache_unpin_api(), @@ -206,7 +204,6 @@ async fn test_pinned_cache() { boc: boc1.clone(), cache_type: BocCacheType::Pinned { pin: pin1.clone() }, }) - .await .unwrap() .boc_ref; @@ -217,7 +214,6 @@ async fn test_pinned_cache() { .call(ParamsOfBocCacheGet { boc_ref: ref1.clone(), }) - .await .unwrap(); assert_eq!(boc.boc, Some(boc1.clone())); @@ -226,7 +222,6 @@ async fn test_pinned_cache() { boc: boc2.clone(), cache_type: BocCacheType::Pinned { pin: pin1.clone() }, }) - .await .unwrap() .boc_ref; assert_ne!(ref2, ref1); @@ -236,7 +231,6 @@ async fn test_pinned_cache() { boc: boc1.clone(), cache_type: BocCacheType::Pinned { pin: pin2.clone() }, }) - .await .unwrap() .boc_ref; assert_eq!(ref3, ref1); @@ -248,14 +242,12 @@ async fn test_pinned_cache() { boc_ref: None, pin: pin1.clone(), }) - .await .unwrap(); let boc = cache_get .call(ParamsOfBocCacheGet { boc_ref: ref1.clone(), }) - .await .unwrap(); assert_eq!(boc.boc, Some(boc1.clone())); @@ -263,7 +255,6 @@ async fn test_pinned_cache() { .call(ParamsOfBocCacheGet { boc_ref: ref2.clone(), }) - .await .unwrap(); assert_eq!(boc.boc, None); @@ -272,7 +263,6 @@ async fn test_pinned_cache() { boc: boc2, cache_type: BocCacheType::Pinned { pin: pin2.clone() }, }) - .await .unwrap() .boc_ref; @@ -282,14 +272,12 @@ async fn test_pinned_cache() { boc_ref: Some(ref4.clone()), pin: pin2.clone(), }) - .await .unwrap(); let boc = cache_get .call(ParamsOfBocCacheGet { boc_ref: ref1.clone(), }) - .await .unwrap(); assert_eq!(boc.boc, Some(boc1.clone())); @@ -297,7 +285,6 @@ async fn test_pinned_cache() { .call(ParamsOfBocCacheGet { boc_ref: ref4.clone(), }) - .await .unwrap(); assert_eq!(boc.boc, None); @@ -308,7 +295,6 @@ async fn test_pinned_cache() { boc: ref1.clone(), cache_type: BocCacheType::Pinned { pin: pin2.clone() }, }) - .await .unwrap(); cache_unpin @@ -316,13 +302,11 @@ async fn test_pinned_cache() { boc_ref: None, pin: pin2.clone(), }) - .await .unwrap(); let boc = cache_get .call(ParamsOfBocCacheGet { boc_ref: ref1.clone(), }) - .await .unwrap(); assert_eq!(boc.boc, Some(boc1)); @@ -331,19 +315,17 @@ async fn test_pinned_cache() { boc_ref: None, pin: pin2.clone(), }) - .await .unwrap(); let boc = cache_get .call(ParamsOfBocCacheGet { boc_ref: ref1.clone(), }) - .await .unwrap(); assert_eq!(boc.boc, None); } -#[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn test_unpinned_cache() { +#[test] +fn test_unpinned_cache() { let boc1 = TestClient::tvc(crate::tests::TEST_DEBOT, None).unwrap(); let boc2 = TestClient::tvc(crate::tests::SUBSCRIBE, None).unwrap(); @@ -356,15 +338,14 @@ async fn test_unpinned_cache() { "cache_max_size": boc_max_size / 1024 + 1 } })); - let cache_set = client.wrap_async(cache_set, BocModule::api(), super::cache::cache_set_api()); - let cache_get = client.wrap_async(cache_get, BocModule::api(), super::cache::cache_get_api()); + let cache_set = client.wrap(cache_set, BocModule::api(), super::cache::cache_set_api()); + let cache_get = client.wrap(cache_get, BocModule::api(), super::cache::cache_get_api()); let ref1 = cache_set .call(ParamsOfBocCacheSet { boc: boc1.clone(), cache_type: BocCacheType::Unpinned, }) - .await .unwrap() .boc_ref; @@ -372,7 +353,6 @@ async fn test_unpinned_cache() { .call(ParamsOfBocCacheGet { boc_ref: ref1.clone(), }) - .await .unwrap(); assert_eq!(boc.boc, Some(boc1.clone())); @@ -382,7 +362,6 @@ async fn test_unpinned_cache() { boc: boc2.clone(), cache_type: BocCacheType::Unpinned, }) - .await .unwrap() .boc_ref; @@ -390,7 +369,6 @@ async fn test_unpinned_cache() { .call(ParamsOfBocCacheGet { boc_ref: ref1.clone(), }) - .await .unwrap(); assert_eq!(boc.boc, None); @@ -398,7 +376,6 @@ async fn test_unpinned_cache() { .call(ParamsOfBocCacheGet { boc_ref: ref2.clone(), }) - .await .unwrap(); assert_eq!(boc.boc, Some(boc2.clone())); } @@ -922,8 +899,8 @@ fn encode_external_in_message() { assert_eq!(boc_encoded.message, abi_encoded.message); } -#[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn test_decode_tvc() { +#[test] +fn test_decode_tvc() { let client = TestClient::new(); let tvc_boc = "te6ccgEBBQEAMgACCQFn9wzgAwEBAtACACZTb21lIFNtYXJ0IENvbnRyYWN0ART/APSkE/S88sgLBAAC0w=="; let code_boc = "te6ccgEBAgEAEAABFP8A9KQT9LzyyAsBAALT"; @@ -942,7 +919,6 @@ async fn test_decode_tvc() { tvc: tvc_boc.to_string(), }, ) - .await .unwrap(); assert_eq!(expected, decoded); @@ -957,13 +933,12 @@ async fn test_decode_tvc() { }); let decoded = client - .request_async::( + .request::( "boc.decode_tvc", json!({ "tvc": tvc_boc, }), ) - .await .unwrap(); assert_eq!(expected, decoded); } diff --git a/ton_client/src/boc/tvc.rs b/ton_client/src/boc/tvc.rs index aa9e96cc..f1997c6d 100644 --- a/ton_client/src/boc/tvc.rs +++ b/ton_client/src/boc/tvc.rs @@ -48,17 +48,15 @@ pub struct TvcV1 { pub description: Option, } -/// Decodes tvc according to the tvc spec. +/// Decodes tvc according to the tvc spec. /// Read more about tvc structure here https://github.com/tonlabs/ever-struct/blob/main/src/scheme/mod.rs#L30 #[api_function] -pub async fn decode_tvc( +pub fn decode_tvc( context: std::sync::Arc, params: ParamsOfDecodeTvc, ) -> ClientResult { - let tvc = deserialize_object_from_boc::(&context, ¶ms.tvc, "TVC") - .await? - .object; + let tvc = deserialize_object_from_boc::(&context, ¶ms.tvc, "TVC")?.object; let tvc = Tvc::V1(TvcV1 { code: tvc .code @@ -75,21 +73,17 @@ pub(crate) fn state_init_with_code(code: Cell) -> ClientResult { serialize_object_to_cell(&state_init, "state init") } -pub(crate) async fn resolve_state_init_cell( +pub(crate) fn resolve_state_init_cell( context: &ClientContext, tvc_or_state_init: &str, ) -> ClientResult { - if let Ok(tvc) = deserialize_object_from_boc::(context, tvc_or_state_init, "TVC").await { + if let Ok(tvc) = deserialize_object_from_boc::(context, tvc_or_state_init, "TVC") { if let Some(code) = tvc.object.code { state_init_with_code(code) } else { Err(crate::boc::Error::invalid_boc("TVC or StateInit"))? } } else { - Ok( - deserialize_cell_from_boc(context, tvc_or_state_init, "state init") - .await? - .1, - ) + Ok(deserialize_cell_from_boc(context, tvc_or_state_init, "state init")?.1) } } diff --git a/ton_client/src/client/client.rs b/ton_client/src/client/client.rs index 80cd706f..529b821a 100644 --- a/ton_client/src/client/client.rs +++ b/ton_client/src/client/client.rs @@ -83,6 +83,12 @@ pub struct ClientContext { pub(crate) debots: LockfreeMap>, } +impl std::fmt::Debug for ClientContext { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("ClientContext").finish() + } +} + impl ClientContext { pub(crate) fn get_server_link(&self) -> ClientResult<&ServerLink> { self.net.get_server_link() diff --git a/ton_client/src/client/tests.rs b/ton_client/src/client/tests.rs index e4015bf4..80cbf6bf 100644 --- a/ton_client/src/client/tests.rs +++ b/ton_client/src/client/tests.rs @@ -84,7 +84,7 @@ fn test_invalid_params_error_secret_stripped() { #[tokio::test] async fn test_memory_leak() { - for _ in 0..100 { + for _ in 0..1 { let config = json!({ "network": { "endpoints": TestClient::endpoints(), diff --git a/ton_client/src/debot/calltype.rs b/ton_client/src/debot/calltype.rs index c88ade46..3d9cf58f 100644 --- a/ton_client/src/debot/calltype.rs +++ b/ton_client/src/debot/calltype.rs @@ -3,10 +3,11 @@ use super::helpers::build_internal_message; use super::{BrowserCallbacks, DebotActivity, Spending, TonClient}; use crate::abi::Signer; use crate::boc::internal::{deserialize_object_from_base64, serialize_object_to_base64}; -use crate::boc::{get_boc_hash, parse_message, ParamsOfParse, ParamsOfGetBocHash}; +use crate::boc::{get_boc_hash, parse_message, ParamsOfGetBocHash, ParamsOfParse}; use crate::crypto::SigningBoxHandle; use crate::encoding::decode_abi_number; use crate::error::{ClientError, ClientResult}; +use crate::net::{query_transaction_tree, ParamsOfQueryTransactionTree}; use crate::processing::{ send_message, wait_for_transaction, ParamsOfSendMessage, ParamsOfWaitForTransaction, ProcessingEvent, @@ -17,7 +18,6 @@ use std::fmt::Display; use std::sync::Arc; use ton_block::{Message, MsgAddressExt, Serializable}; use ton_types::{BuilderData, IBitstring, SliceData}; -use crate::net::{query_transaction_tree, ParamsOfQueryTransactionTree}; const SUPPORTED_ABI_VERSION: u8 = 2; const ABI_2_3: u8 = 0x32; @@ -69,8 +69,7 @@ impl TryFrom for Metadata { let is_timestamp = slice.get_next_bit().map_err(msg_err)?; let is_expire = slice.get_next_bit().map_err(msg_err)?; let is_pubkey = slice.get_next_bit().map_err(msg_err)?; - let signing_box_handle = - match slice.get_next_bit().unwrap_or(false) { + let signing_box_handle = match slice.get_next_bit().unwrap_or(false) { true => Some(SigningBoxHandle(slice.get_next_u32().map_err(msg_err)?)), false => None, }; @@ -119,8 +118,7 @@ pub fn prepare_ext_in_message( let dst_addr: ton_block::MsgAddressInt = hdr.dst.clone(); let meta = Metadata::try_from(hdr.src.clone()).unwrap(); - let future = - decode_and_fix_ext_msg(msg, now_ms, &signer, true, &meta, &ton_client); + let future = decode_and_fix_ext_msg(msg, now_ms, &signer, true, &meta, &ton_client); let result = ton_client.env.block_on(future); @@ -135,7 +133,7 @@ async fn decode_and_fix_ext_msg( signer: &Signer, allow_no_signature: bool, meta: &Metadata, - ton: &TonClient + ton: &TonClient, ) -> ClientResult<(u32, Message)> { // find function id in message body: parse signature, pubkey and abi headers let mut message = msg.clone(); @@ -161,28 +159,28 @@ async fn decode_and_fix_ext_msg( // read `timestamp` header true => { let user_ts = in_body_slice.get_next_u64().map_err(msg_err)?; - Some(if meta.override_ts { user_ts } else {now_ms}) - }, + Some(if meta.override_ts { user_ts } else { now_ms }) + } false => None, }; let msg_exp = match meta.is_expire { // read `expire` header true => { let user_exp = in_body_slice.get_next_u32().map_err(msg_err)?; - Some(if meta.override_exp { - user_exp + Some(if meta.override_exp { + user_exp } else { ((now_ms / 1000) as u32) + ton.config.abi.message_expiration_timeout }) - }, + } false => None, }; // remember function id let func_id = in_body_slice.get_next_u32().map_err(msg_err)?; - // Rebuild msg body - insert correct `timestamp` and `expire` headers + // Rebuild msg body - insert correct `timestamp` and `expire` headers // if they are present, then sign body with signing box - + let mut new_body = BuilderData::new(); let pubkey = signer.resolve_public_key(ton.clone()).await?; if meta.is_pubkey { @@ -211,13 +209,22 @@ async fn decode_and_fix_ext_msg( match signer { Signer::SigningBox { handle: _ } => { let sdata = if meta.abi_ver >= ABI_2_3 { - let mut sdata = msg.dst().unwrap_or_default().write_to_new_cell().map_err(msg_err)?; + let mut sdata = msg + .dst() + .unwrap_or_default() + .write_to_new_cell() + .map_err(msg_err)?; sdata.append_builder(&new_body).map_err(msg_err)?; sdata } else { new_body.clone() }; - let hash = sdata.into_cell().map_err(msg_err)?.repr_hash().as_slice().to_vec(); + let hash = sdata + .into_cell() + .map_err(msg_err)? + .repr_hash() + .as_slice() + .to_vec(); let signature = signer.sign(ton.clone(), &hash).await?; if let Some(signature) = signature { signed_body @@ -227,14 +234,19 @@ async fn decode_and_fix_ext_msg( } else { signed_body.append_bit_zero().map_err(msg_err)?; } - }, + } _ => { signed_body.append_bit_zero().map_err(msg_err)?; } } signed_body.append_builder(&new_body).map_err(msg_err)?; - message.set_body(signed_body.into_cell().and_then(SliceData::load_cell).map_err(msg_err)?); + message.set_body( + signed_body + .into_cell() + .and_then(SliceData::load_cell) + .map_err(msg_err)?, + ); Ok((func_id, message)) } @@ -268,18 +280,30 @@ impl ContractCall { !local_run, signer, meta.signing_box_handle.clone(), - browser.clone() - ).await?; + browser.clone(), + ) + .await?; let dest_addr = msg .header() .get_dst_address() .map(|x| x.to_string()) .unwrap_or_default(); - Ok(Self { browser, ton, msg, signer, target_state, debot_addr, dest_addr, local_run, meta }) + Ok(Self { + browser, + ton, + msg, + signer, + target_state, + debot_addr, + dest_addr, + local_run, + meta, + }) } pub async fn execute(&self, wait_tx: bool) -> ClientResult { - let result = self.decode_and_fix_ext_msg() + let result = self + .decode_and_fix_ext_msg() .await .map_err(|e| Error::external_call_failed(e)); if let Err(e) = result { @@ -325,27 +349,39 @@ impl ContractCall { )); } let out_msg = messages.pop().unwrap(); - build_answer_msg(&out_msg, self.meta.answer_id, func_id, &self.dest_addr, &self.debot_addr) - .ok_or(Error::get_method_failed("failed to build answer message")) + build_answer_msg( + &out_msg, + self.meta.answer_id, + func_id, + &self.dest_addr, + &self.debot_addr, + ) + .ok_or(Error::get_method_failed("failed to build answer message")) } - async fn send_ext_msg(&self, func_id: u32, fixed_msg: String, wait_tx: bool) -> ClientResult { + async fn send_ext_msg( + &self, + func_id: u32, + fixed_msg: String, + wait_tx: bool, + ) -> ClientResult { let activity = emulate_transaction( self.ton.clone(), self.dest_addr.clone(), fixed_msg.clone(), self.target_state.clone(), self.signer.clone(), - ).await; + ) + .await; match activity { Ok(activity) => { if !self.browser.approve(activity).await? { return self.build_error_answer_msg(Error::operation_rejected()); } - }, + } Err(e) => { return self.build_error_answer_msg(e); - }, + } } let browser = self.browser.clone(); let callback = move |event| { @@ -376,8 +412,17 @@ impl ContractCall { callback.clone(), ) .await - .map(|e| { error!("{:?}", e); e })?; - let msg_id = get_boc_hash(self.ton.clone(), ParamsOfGetBocHash { boc: fixed_msg.clone() }).await?.hash; + .map(|e| { + error!("{:?}", e); + e + })?; + let msg_id = get_boc_hash( + self.ton.clone(), + ParamsOfGetBocHash { + boc: fixed_msg.clone(), + }, + )? + .hash; if wait_tx { let result = wait_for_transaction( self.ton.clone(), @@ -399,7 +444,8 @@ impl ContractCall { in_msg: msg_id, ..Default::default() }, - ).await; + ) + .await; if let Err(e) = result { return self.build_error_answer_msg(e); } @@ -409,7 +455,7 @@ impl ContractCall { self.meta.answer_id, func_id, &self.dest_addr, - &self.debot_addr + &self.debot_addr, ); if let Some(answer_msg) = res { return Ok(answer_msg); @@ -420,7 +466,10 @@ impl ContractCall { // answer message not found, build empty answer. let mut new_body = BuilderData::new(); new_body.append_u32(self.meta.answer_id).map_err(msg_err)?; - let new_body = new_body.into_cell().and_then(SliceData::load_cell).map_err(msg_err)?; + let new_body = new_body + .into_cell() + .and_then(SliceData::load_cell) + .map_err(msg_err)?; build_internal_message(&self.dest_addr, &self.debot_addr, new_body) } Err(e) => { @@ -435,7 +484,10 @@ impl ContractCall { .append_u32(self.meta.answer_id) .and_then(|b| b.append_raw(&msg_id, 256)) .map_err(msg_err)?; - let new_body = new_body.into_cell().and_then(SliceData::load_cell).map_err(msg_err)?; + let new_body = new_body + .into_cell() + .and_then(SliceData::load_cell) + .map_err(msg_err)?; build_internal_message(&self.dest_addr, &self.debot_addr, new_body) } } @@ -449,9 +501,11 @@ impl ContractCall { false, &self.meta, &self.ton, - ).await?; + ) + .await?; let (func_id, message) = result; - let msg = serialize_object_to_base64(&message, "message").map_err(|e| Error::invalid_msg(e))?; + let msg = + serialize_object_to_base64(&message, "message").map_err(|e| Error::invalid_msg(e))?; Ok((func_id, msg)) } @@ -473,7 +527,10 @@ fn build_onerror_body(onerror_id: u32, e: ClientError) -> ClientResult Option { - let out_message: Message = deserialize_object_from_base64(out_msg, "message").ok()?.object; + let out_message: Message = deserialize_object_from_base64(out_msg, "message") + .ok()? + .object; if out_message.is_internal() { return None; } @@ -496,9 +555,7 @@ fn build_answer_msg( if func_id != request_id { return None; } - new_body - .append_builder(&body_slice.as_builder()) - .ok()?; + new_body.append_builder(&body_slice.as_builder()).ok()?; } let new_body = new_body.into_cell().and_then(SliceData::load_cell).ok()?; @@ -509,15 +566,17 @@ async fn resolve_signer( sign: bool, signer: Signer, msg_signing_box: Option, - browser: Arc + browser: Arc, ) -> ClientResult { let new_signer = if sign { match signer { - Signer::SigningBox {handle: _} => signer, + Signer::SigningBox { handle: _ } => signer, _ => Signer::SigningBox { handle: match msg_signing_box { Some(signing_box_handle) => signing_box_handle, - None => browser.get_signing_box().await + None => browser + .get_signing_box() + .await .map_err(|e| Error::external_call_failed(e))?, }, }, @@ -566,7 +625,7 @@ async fn emulate_transaction( .unwrap_or(0); if exit_code != 0 { - let err = ClientError{ + let err = ClientError { code: 0, message: String::from(""), data: result.transaction, @@ -576,9 +635,7 @@ async fn emulate_transaction( let mut out = vec![]; for out_msg in result.out_messages { - let parsed = parse_message(client.clone(), ParamsOfParse { boc: out_msg }) - .await? - .parsed; + let parsed = parse_message(client.clone(), ParamsOfParse { boc: out_msg })?.parsed; let msg_type = parsed["msg_type"].as_u64().unwrap(); // if internal message if msg_type == 0 { @@ -592,7 +649,13 @@ async fn emulate_transaction( } let (signing_box_handle, signkey) = if let Signer::SigningBox { ref handle } = signer { - (handle.0, signer.resolve_public_key(client.clone()).await?.unwrap_or_default()) + ( + handle.0, + signer + .resolve_public_key(client.clone()) + .await? + .unwrap_or_default(), + ) } else { (0, String::new()) }; diff --git a/ton_client/src/debot/dengine.rs b/ton_client/src/debot/dengine.rs index ffe0ee44..23339c4b 100644 --- a/ton_client/src/debot/dengine.rs +++ b/ton_client/src/debot/dengine.rs @@ -135,7 +135,6 @@ impl DEngine { async fn fetch_info(ton: TonClient, addr: String, state: String) -> Result { let dabi_version = fetch_target_abi_version(ton.clone(), state.clone()) - .await .map_err(|e| e.to_string())?; let abi = load_abi(DEBOT_ABI).unwrap(); let result = Self::run( @@ -609,7 +608,6 @@ impl DEngine { ..Default::default() }, ) - .await .map_err(|e| format!("failed to decode msg body: {}", e))?; debug!("calling {} at address {}", res.name, dest); diff --git a/ton_client/src/debot/dinterface.rs b/ton_client/src/debot/dinterface.rs index fc644135..b5f0083b 100644 --- a/ton_client/src/debot/dinterface.rs +++ b/ton_client/src/debot/dinterface.rs @@ -20,14 +20,14 @@ use crate::boc::internal::deserialize_cell_from_boc; use ton_sdk::AbiContract; use ton_abi::token::Detokenizer; -async fn decode_msg( +fn decode_msg( client: TonClient, msg_body: String, abi: Abi, ) -> ClientResult<(String, Value)> { let abi = abi.json_string()?; let abi = AbiContract::load(abi.as_bytes()).map_err(|e| Error::invalid_json(e))?; - let (_, body) = deserialize_cell_from_boc(&client, &msg_body, "message body").await?; + let (_, body) = deserialize_cell_from_boc(&client, &msg_body, "message body")?; let body = slice_from_cell(body)?; let input = abi.decode_input(body, true, false) .map_err(|e| Error::invalid_message_for_decode(e))?; @@ -93,7 +93,6 @@ pub trait DebotInterfaceExecutor { abi_version: &str, ) -> InterfaceResult { let parsed = parse_message(client.clone(), ParamsOfParse { boc: msg.clone() }) - .await .map_err(|e| format!("{}", e))?; let body = parsed.parsed["body"] @@ -105,7 +104,6 @@ pub trait DebotInterfaceExecutor { Some(object) => { let abi = object.get_target_abi(abi_version); let (func, args) = decode_msg(client.clone(), body, abi.clone()) - .await .map_err(|e| e.to_string())?; let (answer_id, mut ret_args) = object.call(&func, &args) .await @@ -224,4 +222,4 @@ pub fn get_array_strings(args: &Value, name: &str) -> Result, String strings.push(string.to_owned()); } Ok(strings) -} \ No newline at end of file +} diff --git a/ton_client/src/debot/info.rs b/ton_client/src/debot/info.rs index 172a2789..988a4cca 100644 --- a/ton_client/src/debot/info.rs +++ b/ton_client/src/debot/info.rs @@ -58,18 +58,16 @@ pub(crate) fn parse_debot_info(value: Option) -> Result ClientResult { - let json_value = parse_account(ton.clone(), ParamsOfParse { boc: account_boc }) - .await? - .parsed; + let json_value = parse_account(ton.clone(), ParamsOfParse { boc: account_boc })?.parsed; let code = json_value["code"] .as_str() .ok_or(Error::debot_has_no_code())? .to_owned(); - let result = get_compiler_version(ton.clone(), ParamsOfGetCompilerVersion { code }).await; + let result = get_compiler_version(ton.clone(), ParamsOfGetCompilerVersion { code }); // If If DeBot's code does not contain version or SDK failed to read version, // then set empty string. diff --git a/ton_client/src/debot/msg_interface.rs b/ton_client/src/debot/msg_interface.rs index 9d20ab68..259d4e29 100644 --- a/ton_client/src/debot/msg_interface.rs +++ b/ton_client/src/debot/msg_interface.rs @@ -80,7 +80,6 @@ impl MsgInterface { .map_err(|e| format!("{}", e))? .handle; let parsed_msg = parse_message(self.ton.clone(), ParamsOfParse { boc: message.clone() }) - .await .map_err(|e| format!("{}", e))? .parsed; let dest = parsed_msg["dst"].as_str().ok_or(format!("failed to parse dst address"))?.to_owned(); @@ -108,7 +107,6 @@ impl MsgInterface { ..Default::default() }, ) - .await .map_err(|e| format!("failed to decode message: {}", e))?; let abi_str = self.debot_abi.json_string().unwrap(); let contract = Contract::load(abi_str.as_bytes()).map_err(|e| format!("{}", e))?; @@ -122,7 +120,6 @@ impl MsgInterface { async fn send_async(&self, args: &Value) -> InterfaceResult { let message = get_arg(args, "message")?; let parsed_msg = parse_message(self.ton.clone(), ParamsOfParse { boc: message.clone() }) - .await .map_err(|e| format!("{}", e))? .parsed; let dest = parsed_msg["dst"].as_str().ok_or(format!("failed to parse dst address"))?.to_owned(); @@ -150,7 +147,6 @@ impl MsgInterface { ..Default::default() }, ) - .await .map_err(|e| format!("failed to decode message: {}", e))?; let abi_str = self.debot_abi.json_string().unwrap(); let contract = Contract::load(abi_str.as_bytes()).map_err(|e| format!("{}", e))?; diff --git a/ton_client/src/debot/routines.rs b/ton_client/src/debot/routines.rs index 419441bb..4bbd7f11 100644 --- a/ton_client/src/debot/routines.rs +++ b/ton_client/src/debot/routines.rs @@ -311,7 +311,6 @@ pub(super) async fn get_account( boc: get_arg(&accounts.swap_remove(0), "boc")?, }, ) - .await .map_err(|e| format!("failed to parse account from boc: {}", e))? .parsed; diff --git a/ton_client/src/json_interface/interop.rs b/ton_client/src/json_interface/interop.rs index 74e09291..73235c23 100644 --- a/ton_client/src/json_interface/interop.rs +++ b/ton_client/src/json_interface/interop.rs @@ -35,7 +35,7 @@ pub enum ResponseType { Error = 1, Nop = 2, AppRequest = 3, - AppNotify = 4, + AppNotify = 4, Custom = 100, } diff --git a/ton_client/src/json_interface/modules.rs b/ton_client/src/json_interface/modules.rs index 0cfd5097..9e5d11a2 100644 --- a/ton_client/src/json_interface/modules.rs +++ b/ton_client/src/json_interface/modules.rs @@ -328,7 +328,7 @@ fn register_abi(handlers: &mut RuntimeHandlers) { crate::abi::encode_message_body, crate::abi::encode_message::encode_message_body_api, ); - module.register_async_fn( + module.register_sync_fn( crate::abi::attach_signature_to_message_body, crate::abi::encode_message::attach_signature_to_message_body_api, ); @@ -336,19 +336,19 @@ fn register_abi(handlers: &mut RuntimeHandlers) { crate::abi::encode_message, crate::abi::encode_message::encode_message_api, ); - module.register_async_fn( + module.register_sync_fn( crate::abi::encode_internal_message, crate::abi::encode_message::encode_internal_message_api, ); - module.register_async_fn( + module.register_sync_fn( crate::abi::attach_signature, crate::abi::encode_message::attach_signature_api, ); - module.register_async_fn( + module.register_sync_fn( crate::abi::decode_message, crate::abi::decode_message::decode_message_api, ); - module.register_async_fn( + module.register_sync_fn( crate::abi::decode_message_body, crate::abi::decode_message::decode_message_body_api, ); @@ -356,27 +356,27 @@ fn register_abi(handlers: &mut RuntimeHandlers) { crate::abi::encode_account, crate::abi::encode_account::encode_account_api, ); - module.register_async_fn( + module.register_sync_fn( crate::abi::decode_account_data, crate::abi::decode_data::decode_account_data_api, ); - module.register_async_fn( + module.register_sync_fn( crate::abi::update_initial_data, crate::abi::init_data::update_initial_data_api, ); - module.register_async_fn( + module.register_sync_fn( crate::abi::encode_initial_data, crate::abi::init_data::encode_initial_data_api, ); - module.register_async_fn( + module.register_sync_fn( crate::abi::decode_initial_data, crate::abi::init_data::decode_initial_data_api, ); - module.register_async_fn( + module.register_sync_fn( crate::abi::decode_boc, crate::abi::decode_boc::decode_boc_api, ); - module.register_async_fn( + module.register_sync_fn( crate::abi::encode_boc, crate::abi::encode_boc::encode_boc_api, ); @@ -404,65 +404,65 @@ fn register_boc(handlers: &mut RuntimeHandlers) { module.register_type::(); module.register_error_code::(); - module.register_async_fn(crate::boc::decode_tvc, crate::boc::tvc::decode_tvc_api); - module.register_async_fn( + module.register_sync_fn(crate::boc::decode_tvc, crate::boc::tvc::decode_tvc_api); + module.register_sync_fn( crate::boc::parse_message, crate::boc::parse::parse_message_api, ); - module.register_async_fn( + module.register_sync_fn( crate::boc::parse_transaction, crate::boc::parse::parse_transaction_api, ); - module.register_async_fn( + module.register_sync_fn( crate::boc::parse_account, crate::boc::parse::parse_account_api, ); - module.register_async_fn(crate::boc::parse_block, crate::boc::parse::parse_block_api); - module.register_async_fn( + module.register_sync_fn(crate::boc::parse_block, crate::boc::parse::parse_block_api); + module.register_sync_fn( crate::boc::parse_shardstate, crate::boc::parse::parse_shardstate_api, ); - module.register_async_fn( + module.register_sync_fn( crate::boc::get_blockchain_config, crate::boc::blockchain_config::get_blockchain_config_api, ); - module.register_async_fn( + module.register_sync_fn( crate::boc::get_boc_hash, crate::boc::common::get_boc_hash_api, ); - module.register_async_fn( + module.register_sync_fn( crate::boc::get_boc_depth, crate::boc::common::get_boc_depth_api, ); - module.register_async_fn( + module.register_sync_fn( crate::boc::get_code_from_tvc, crate::boc::state_init::get_code_from_tvc_api, ); - module.register_async_fn(crate::boc::cache_get, crate::boc::cache::cache_get_api); - module.register_async_fn(crate::boc::cache_set, crate::boc::cache::cache_set_api); - module.register_async_fn(crate::boc::cache_unpin, crate::boc::cache::cache_unpin_api); - module.register_async_fn(crate::boc::encode_boc, crate::boc::encode::encode_boc_api); - module.register_async_fn( + module.register_sync_fn(crate::boc::cache_get, crate::boc::cache::cache_get_api); + module.register_sync_fn(crate::boc::cache_set, crate::boc::cache::cache_set_api); + module.register_sync_fn(crate::boc::cache_unpin, crate::boc::cache::cache_unpin_api); + module.register_sync_fn(crate::boc::encode_boc, crate::boc::encode::encode_boc_api); + module.register_sync_fn( crate::boc::get_code_salt, crate::boc::state_init::get_code_salt_api, ); - module.register_async_fn( + module.register_sync_fn( crate::boc::set_code_salt, crate::boc::state_init::set_code_salt_api, ); - module.register_async_fn( + module.register_sync_fn( crate::boc::decode_state_init, crate::boc::state_init::decode_state_init_api, ); - module.register_async_fn( + module.register_sync_fn( crate::boc::encode_state_init, crate::boc::state_init::encode_state_init_api, ); - module.register_async_fn( + module.register_sync_fn( crate::boc::encode_external_in_message, crate::boc::encode_external_in_message::encode_external_in_message_api, ); - module.register_async_fn( + module.register_sync_fn( crate::boc::get_compiler_version, crate::boc::state_init::get_compiler_version_api, ); @@ -583,11 +583,11 @@ fn register_processing(handlers: &mut RuntimeHandlers) { module.register_type::(); module.register_type::(); - module.register_async_fn( + module.register_sync_fn( crate::processing::monitor_messages, crate::processing::monitor_messages_api, ); - module.register_async_fn( + module.register_sync_fn( crate::processing::get_monitor_info, crate::processing::get_monitor_info_api, ); @@ -595,7 +595,7 @@ fn register_processing(handlers: &mut RuntimeHandlers) { crate::processing::fetch_next_monitor_results, crate::processing::fetch_next_monitor_results_api, ); - module.register_async_fn( + module.register_sync_fn( crate::processing::cancel_monitor, crate::processing::cancel_monitor_api, ); diff --git a/ton_client/src/net/tests.rs b/ton_client/src/net/tests.rs index 11b2f91a..56626eaa 100644 --- a/ton_client/src/net/tests.rs +++ b/ton_client/src/net/tests.rs @@ -260,6 +260,35 @@ async fn query() { assert_eq!(version.split(".").count(), 3); } +#[test] +fn query_sync() { + let client = TestClient::new(); + + let info: ResultOfQuery = client + .request( + "net.query", + ParamsOfQuery { + query: "query{info{version}}".to_owned(), + variables: None, + }, + ) + .unwrap(); + + let version = info.result["data"]["info"]["version"].as_str().unwrap(); + assert_eq!(version.split(".").count(), 3); + + let result: ClientResult = client + .request( + "net.query", + ParamsOfQuery { + query: "query{info111{version}}".to_owned(), + variables: None, + }, + ); + + assert!(result.is_err()); +} + #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn block_signatures() { let client = TestClient::new(); diff --git a/ton_client/src/net/transaction_tree.rs b/ton_client/src/net/transaction_tree.rs index 373ecea4..7df1a573 100644 --- a/ton_client/src/net/transaction_tree.rs +++ b/ton_client/src/net/transaction_tree.rs @@ -58,7 +58,7 @@ pub struct ParamsOfQueryTransactionTree { /// Maximum transaction count to wait. If transaction tree contains more transaction then this /// parameter then only first `transaction_max_count` transaction are awaited and returned. - /// + /// /// Default value is 50. If `transaction_max_count` is set to 0 then no limitation on /// transaction count is used and all transaction are returned. pub transaction_max_count: Option, @@ -99,7 +99,7 @@ pub struct MessageNode { } impl MessageNode { - async fn from( + fn from( value: &Value, client: &Arc, abi_registry: &Option>, @@ -115,11 +115,11 @@ impl MessageNode { dst: get_string(value, "dst"), value: get_string(value, "value"), bounce: value["bounce"].as_bool().unwrap_or(false), - decoded_body: Self::try_decode_body(value, client, abi_registry).await, + decoded_body: Self::try_decode_body(value, client, abi_registry), }) } - async fn try_decode_body( + fn try_decode_body( message: &Value, client: &Arc, abi_registry: &Option>, @@ -137,9 +137,7 @@ impl MessageNode { is_internal, ..Default::default() }, - ) - .await - { + ) { return Some(result); } } @@ -316,16 +314,17 @@ pub async fn query_transaction_tree( let mut message_nodes = Vec::new(); let mut query_queue: Vec<(Option, String)> = vec![(None, params.in_msg.clone())]; let timeout = params.timeout.unwrap_or(DEFAULT_WAITING_TIMEOUT); - let transaction_max_count = params.transaction_max_count.unwrap_or(DEFAULT_TRANSACTION_MAX_COUNT) as usize; - while !query_queue.is_empty() && - (transaction_max_count == 0 || transaction_nodes.len() < transaction_max_count) + let transaction_max_count = params + .transaction_max_count + .unwrap_or(DEFAULT_TRANSACTION_MAX_COUNT) as usize; + while !query_queue.is_empty() + && (transaction_max_count == 0 || transaction_nodes.len() < transaction_max_count) { let (messages, src_transactions) = query_next_portion(server_link, timeout, &mut query_queue).await?; for message in messages { let message_node = - MessageNode::from(&message, &context, ¶ms.abi_registry, &src_transactions) - .await?; + MessageNode::from(&message, &context, ¶ms.abi_registry, &src_transactions)?; let transaction = &message["dst_transaction"]; if transaction.is_object() { let transaction_node = TransactionNode::from(&transaction, &message_node)?; diff --git a/ton_client/src/processing/fetching.rs b/ton_client/src/processing/fetching.rs index 1a7e1c40..4bfe36f0 100644 --- a/ton_client/src/processing/fetching.rs +++ b/ton_client/src/processing/fetching.rs @@ -247,9 +247,9 @@ pub async fn fetch_transaction_result( } })?; - let (transaction, out_messages) = parse_transaction_boc(context.clone(), transaction_boc).await?; + let (transaction, out_messages) = parse_transaction_boc(context.clone(), transaction_boc)?; let abi_decoded = if let Some(abi) = abi { - Some(decode_output(context, abi, out_messages.clone()).await?) + Some(decode_output(context, abi, out_messages.clone())?) } else { None }; diff --git a/ton_client/src/processing/internal.rs b/ton_client/src/processing/internal.rs index a206e023..71fd0f49 100644 --- a/ton_client/src/processing/internal.rs +++ b/ton_client/src/processing/internal.rs @@ -49,7 +49,7 @@ pub fn find_transactions( Ok(ids) } -pub(crate) async fn get_message_expiration_time( +pub(crate) fn get_message_expiration_time( context: Arc, abi: Option<&Abi>, message: &str, @@ -63,7 +63,6 @@ pub(crate) async fn get_message_expiration_time( ..Default::default() }, ) - .await .map(|x| x.header) .unwrap_or_default(), None => None, diff --git a/ton_client/src/processing/message_monitor.rs b/ton_client/src/processing/message_monitor.rs index 81cc3601..2ab63d2c 100644 --- a/ton_client/src/processing/message_monitor.rs +++ b/ton_client/src/processing/message_monitor.rs @@ -45,14 +45,12 @@ pub struct ParamsOfMonitorMessages { /// with specified unresolved messages. /// #[api_function] -pub async fn monitor_messages( +pub fn monitor_messages( context: Arc, params: ParamsOfMonitorMessages, ) -> ClientResult<()> { let monitor = context.message_monitor.clone(); - monitor - .monitor_messages(¶ms.queue, params.messages) - .await?; + monitor.monitor_messages(¶ms.queue, params.messages)?; Ok(()) } @@ -97,7 +95,7 @@ pub struct ParamsOfGetMonitorInfo { /// Returns summary information about current state of the specified monitoring queue. #[api_function] -pub async fn get_monitor_info( +pub fn get_monitor_info( context: Arc, params: ParamsOfGetMonitorInfo, ) -> ClientResult { @@ -113,7 +111,7 @@ pub struct ParamsOfCancelMonitor { /// Cancels all background activity and releases all allocated system resources /// for the specified monitoring queue. #[api_function] -pub async fn cancel_monitor( +pub fn cancel_monitor( context: Arc, params: ParamsOfCancelMonitor, ) -> ClientResult<()> { diff --git a/ton_client/src/processing/parsing.rs b/ton_client/src/processing/parsing.rs index 526ea55c..ea28cb78 100644 --- a/ton_client/src/processing/parsing.rs +++ b/ton_client/src/processing/parsing.rs @@ -7,7 +7,7 @@ use crate::processing::types::DecodedOutput; use serde_json::Value; use std::sync::Arc; -pub(crate) async fn parse_transaction_boc( +pub(crate) fn parse_transaction_boc( context: Arc, transaction: TransactionBoc, ) -> ClientResult<(Value, Vec)> { @@ -21,14 +21,13 @@ pub(crate) async fn parse_transaction_boc( ParamsOfParse { boc: transaction.boc, }, - ) - .await? + )? .parsed, messages, )) } -pub(crate) async fn decode_output( +pub(crate) fn decode_output( context: &Arc, abi: &Abi, messages: Vec, @@ -43,7 +42,7 @@ pub(crate) async fn decode_output( abi: abi.clone(), ..Default::default() }, - ).await; + ); let decoded = match decode_result { Ok(decoded) => { if decoded.body_type == MessageBodyType::Output { diff --git a/ton_client/src/processing/send_message.rs b/ton_client/src/processing/send_message.rs index 9d5f18a0..0351f127 100644 --- a/ton_client/src/processing/send_message.rs +++ b/ton_client/src/processing/send_message.rs @@ -74,14 +74,14 @@ struct SendingMessage { } impl SendingMessage { - async fn new( + fn new( context: &Arc, serialized: &str, abi: Option<&Abi>, ) -> ClientResult { // Check message let deserialized = - deserialize_object_from_boc::(&context, serialized, "message").await?; + deserialize_object_from_boc::(&context, serialized, "message")?; let id = deserialized.cell.repr_hash().as_hex_string(); let dst = deserialized .object @@ -89,7 +89,7 @@ impl SendingMessage { .ok_or(Error::message_has_not_destination_address())?; let message_expiration_time = - get_message_expiration_time(context.clone(), abi, &serialized).await?; + get_message_expiration_time(context.clone(), abi, &serialized)?; if let Some(message_expiration_time) = message_expiration_time { if message_expiration_time <= context.env.now_ms() { return Err(Error::message_already_expired()); @@ -222,7 +222,7 @@ pub async fn send_message + Send>( params: ParamsOfSendMessage, callback: impl Fn(ProcessingEvent) -> F + Send + Sync + Clone, ) -> ClientResult { - let message = SendingMessage::new(&context, ¶ms.message, params.abi.as_ref()).await?; + let message = SendingMessage::new(&context, ¶ms.message, params.abi.as_ref())?; let callback = if params.send_events { Some(callback) diff --git a/ton_client/src/processing/send_messages.rs b/ton_client/src/processing/send_messages.rs index 2810cf75..3114aaf6 100644 --- a/ton_client/src/processing/send_messages.rs +++ b/ton_client/src/processing/send_messages.rs @@ -83,8 +83,7 @@ pub async fn send_messages( if let Some(queue) = params.monitor_queue { context .message_monitor - .monitor_messages(&queue, messages.clone()) - .await?; + .monitor_messages(&queue, messages.clone())?; } Ok(ResultOfSendMessages { messages }) } diff --git a/ton_client/src/processing/tests.rs b/ton_client/src/processing/tests.rs index 0e5cbcd4..de7338de 100644 --- a/ton_client/src/processing/tests.rs +++ b/ton_client/src/processing/tests.rs @@ -669,9 +669,7 @@ async fn test_deploy_from_tvc_v1() { let client = TestClient::new(); let (events_abi, events_state_init) = TestClient::package(EVENTS_OLD, Some(2)); let state_init_cell = - resolve_state_init_cell(&client.context(), &events_state_init.clone().unwrap()) - .await - .unwrap(); + resolve_state_init_cell(&client.context(), &events_state_init.clone().unwrap()).unwrap(); let state_init = deserialize_object_from_cell::(state_init_cell.clone(), "state init").unwrap(); let tvc = base64::encode( diff --git a/ton_client/src/processing/wait_for_transaction.rs b/ton_client/src/processing/wait_for_transaction.rs index b5ab987f..613dec62 100644 --- a/ton_client/src/processing/wait_for_transaction.rs +++ b/ton_client/src/processing/wait_for_transaction.rs @@ -1,3 +1,4 @@ +use super::remp::{RempStatus, RempStatusData}; use crate::abi::Abi; use crate::boc::internal::deserialize_object_from_boc; use crate::client::ClientContext; @@ -6,14 +7,12 @@ use crate::net::{EndpointStat, ResultOfSubscription}; use crate::processing::internal::{get_message_expiration_time, resolve_error}; use crate::processing::{fetching, internal, Error}; use crate::processing::{ProcessingEvent, ResultOfProcessMessage}; +use futures::{FutureExt, StreamExt}; use std::convert::TryInto; use std::sync::Arc; -use futures::{FutureExt, StreamExt}; use tokio::sync::mpsc; use ton_block::{Message, MsgAddressInt}; -use super::remp::{RempStatus, RempStatusData}; - //--------------------------------------------------------------------------- wait_for_transaction #[derive(Serialize, Deserialize, ApiType, Default, Debug)] @@ -71,15 +70,15 @@ async fn wait_by_remp + Send>( let fallback_fut = async { notify.notified().await; wait_by_block_walking(context.clone(), ¶ms, callback.clone()).await - }.fuse(); + } + .fuse(); futures::pin_mut!(fallback_fut); // Prepare to wait - let message = - deserialize_object_from_boc::(&context, ¶ms.message, "message") - .await?; + let message = deserialize_object_from_boc::(&context, ¶ms.message, "message")?; let message_id = message.cell.repr_hash().as_hex_string(); - let message_dst = message.object + let message_dst = message + .object .dst() .ok_or(Error::message_has_not_destination_address())?; @@ -89,25 +88,30 @@ async fn wait_by_remp + Send>( let subscription_callback = move |event: ClientResult| { let sender = sender.clone(); async move { - let _ = sender.send(event.map(|mut result| result.result["rempReceipts"].take())).await; + let _ = sender + .send(event.map(|mut result| result.result["rempReceipts"].take())) + .await; } }; let subscription_result = crate::net::subscribe( context.clone(), crate::net::subscriptions::ParamsOfSubscribe { - subscription: format!(r#" + subscription: format!( + r#" subscription {{ rempReceipts(messageId: "{}") {{ messageId kind timestamp json }} }} "#, - message_id), + message_id + ), variables: None, }, - subscription_callback - ).await; + subscription_callback, + ) + .await; let subscription = match subscription_result { Ok(result) => Some(result), @@ -117,7 +121,8 @@ async fn wait_by_remp + Send>( error, message_id: message_id.clone(), message_dst: message_dst.to_string(), - }).await; + }) + .await; } notify.notify_one(); None @@ -176,10 +181,7 @@ async fn wait_by_remp + Send>( if let Some(result) = result { if let Some(subscription) = subscription { - let _ = crate::net::unsubscribe( - context.clone(), - subscription - ).await; + let _ = crate::net::unsubscribe(context.clone(), subscription).await; } return result; @@ -196,18 +198,26 @@ async fn process_remp_message + Send>( remp_message: ClientResult, ) -> ClientResult>> { let remp_message = remp_message?; - let status: RempStatus = serde_json::from_value(remp_message) - .map_err(|err| Error::invalid_remp_status(format!("can not parse REMP status message: {}", err)))?; + let status: RempStatus = serde_json::from_value(remp_message).map_err(|err| { + Error::invalid_remp_status(format!("can not parse REMP status message: {}", err)) + })?; match status { - RempStatus::RejectedByFullnode(data) => { - Ok(Some(process_rejected_status(context.clone(), params, &message_dst, data).await)) - }, - RempStatus::Finalized(data) => { - Ok(Some(Ok(process_finalized_status(context.clone(), params, message_id, &message_dst, data).await?))) - }, + RempStatus::RejectedByFullnode(data) => Ok(Some( + process_rejected_status(context.clone(), params, &message_dst, data).await, + )), + RempStatus::Finalized(data) => Ok(Some(Ok(process_finalized_status( + context.clone(), + params, + message_id, + &message_dst, + data, + ) + .await?))), _ => { - if params.send_events { callback(status.into_event(message_dst.to_string())).await; } + if params.send_events { + callback(status.into_event(message_dst.to_string())).await; + } Ok(None) } } @@ -220,8 +230,8 @@ async fn process_rejected_status( data: RempStatusData, ) -> ClientResult { let message_expiration_time = - get_message_expiration_time(context.clone(), params.abi.as_ref(), ¶ms.message).await? - .unwrap_or_else(|| context.env.now_ms()); + get_message_expiration_time(context.clone(), params.abi.as_ref(), ¶ms.message)? + .unwrap_or_else(|| context.env.now_ms()); let error = data.json["error"].as_str().unwrap_or("unknown error"); @@ -248,8 +258,8 @@ async fn process_finalized_status( data: RempStatusData, ) -> ClientResult { let message_expiration_time = - get_message_expiration_time(context.clone(), params.abi.as_ref(), ¶ms.message).await? - .unwrap_or_else(|| context.env.now_ms()); + get_message_expiration_time(context.clone(), params.abi.as_ref(), ¶ms.message)? + .unwrap_or_else(|| context.env.now_ms()); let block_id = data.json["block_id"] .as_str() @@ -258,19 +268,19 @@ async fn process_finalized_status( // Transaction has been found. // Let's fetch other stuff. let result = fetching::fetch_transaction_result( - &context, - block_id, - message_id, - ¶ms.message, - None, - ¶ms.abi, - message_dst.clone(), - (message_expiration_time / 1000) as u32, - (context.env.now_ms() / 1000) as u32, - ) - .await - .add_network_url_from_context(&context) - .await; + &context, + block_id, + message_id, + ¶ms.message, + None, + ¶ms.abi, + message_dst.clone(), + (message_expiration_time / 1000) as u32, + (context.env.now_ms() / 1000) as u32, + ) + .await + .add_network_url_from_context(&context) + .await; if result.is_ok() { if let Some(endpoints) = ¶ms.sending_endpoints { context @@ -290,17 +300,16 @@ async fn wait_by_block_walking + Send>( let net = context.get_server_link()?; // Prepare to wait - let message = - deserialize_object_from_boc::(&context, ¶ms.message, "message") - .await?; + let message = deserialize_object_from_boc::(&context, ¶ms.message, "message")?; let message_id = message.cell.repr_hash().as_hex_string(); let address = message .object - .dst_ref().cloned() + .dst_ref() + .cloned() .ok_or(Error::message_has_not_destination_address())?; let message_expiration_time = - get_message_expiration_time(context.clone(), params.abi.as_ref(), ¶ms.message).await?; + get_message_expiration_time(context.clone(), params.abi.as_ref(), ¶ms.message)?; let processing_timeout = net.config().message_processing_timeout; let max_block_time = message_expiration_time.unwrap_or(context.env.now_ms() + processing_timeout as u64); @@ -313,10 +322,8 @@ async fn wait_by_block_walking + Send>( // Block walking loop loop { let now = context.env.now_ms(); - let fetch_block_timeout = - (std::cmp::max(max_block_time, now) - now + processing_timeout as u64) - .try_into() - .unwrap_or(u32::MAX); + let timeout = std::cmp::max(max_block_time, now) - now + processing_timeout as u64; + let fetch_block_timeout = timeout.try_into().unwrap_or(u32::MAX); log::debug!("fetch_block_timeout {}", fetch_block_timeout); let block = fetching::fetch_next_shard_block( diff --git a/ton_client/src/proofs/trusted_key_blocks.bin b/ton_client/src/proofs/trusted_key_blocks.bin index 6b5b4761..df67b196 100644 Binary files a/ton_client/src/proofs/trusted_key_blocks.bin and b/ton_client/src/proofs/trusted_key_blocks.bin differ diff --git a/ton_client/src/tvm/run_get.rs b/ton_client/src/tvm/run_get.rs index d227042e..24caf208 100644 --- a/ton_client/src/tvm/run_get.rs +++ b/ton_client/src/tvm/run_get.rs @@ -60,7 +60,7 @@ pub async fn run_get( params: ParamsOfRunGet, ) -> ClientResult { let mut account: ton_block::Account = - deserialize_object_from_boc(&context, ¶ms.account, "account").await?.object; + deserialize_object_from_boc(&context, ¶ms.account, "account")?.object; let options = ResolvedExecutionOptions::from_options(&context, params.execution_options).await?; if account.is_none() { diff --git a/ton_client/src/tvm/run_message.rs b/ton_client/src/tvm/run_message.rs index fdeee9c0..ec676526 100644 --- a/ton_client/src/tvm/run_message.rs +++ b/ton_client/src/tvm/run_message.rs @@ -14,21 +14,23 @@ use super::stack::serialize_item; use super::types::{ExecutionOptions, ResolvedExecutionOptions}; -use crate::{abi::Abi, boc::BocCacheType}; use crate::boc::internal::{ deserialize_cell_from_boc, deserialize_object_from_boc, deserialize_object_from_cell, serialize_cell_to_boc, serialize_object_to_base64, serialize_object_to_boc, - serialize_object_to_cell + serialize_object_to_cell, }; use crate::client::ClientContext; use crate::error::ClientResult; use crate::processing::{parsing::decode_output, DecodedOutput}; use crate::tvm::{check_transaction::calc_transaction_fees, Error}; +use crate::{abi::Abi, boc::BocCacheType}; use serde_json::Value; use std::convert::TryFrom; use std::sync::{atomic::AtomicU64, Arc}; -use ton_block::{Account, Message, Serializable, MsgAddressInt, CurrencyCollection, Transaction}; -use ton_executor::{ExecutorError, ExecuteParams, OrdinaryTransactionExecutor, TransactionExecutor}; +use ton_block::{Account, CurrencyCollection, Message, MsgAddressInt, Serializable, Transaction}; +use ton_executor::{ + ExecuteParams, ExecutorError, OrdinaryTransactionExecutor, TransactionExecutor, +}; use ton_sdk::TransactionFees; use ton_types::{Cell, UInt256}; @@ -60,7 +62,7 @@ impl Default for AccountForExecutor { const UNLIMITED_BALANCE: u64 = u64::MAX; impl AccountForExecutor { - pub async fn get_account( + pub fn get_account( &self, context: &Arc, address: MsgAddressInt, @@ -82,12 +84,14 @@ impl AccountForExecutor { } => { if unlimited_balance.unwrap_or_default() { let mut account: Account = - deserialize_object_from_boc(context, &boc, "account").await?.object; + deserialize_object_from_boc(context, &boc, "account")?.object; let original_balance = account .balance() - .ok_or_else(|| Error::invalid_account_boc( - "can not set unlimited balance for non existed account", - ))? + .ok_or_else(|| { + Error::invalid_account_boc( + "can not set unlimited balance for non existed account", + ) + })? .clone(); let mut balance = original_balance.clone(); balance.grams = UNLIMITED_BALANCE.into(); @@ -95,7 +99,7 @@ impl AccountForExecutor { let account = serialize_object_to_cell(&account, "account")?; Ok((account, Some(original_balance))) } else { - let (_, account) = deserialize_cell_from_boc(context, &boc, "account").await?; + let (_, account) = deserialize_cell_from_boc(context, &boc, "account")?; Ok((account, None)) } } @@ -147,7 +151,7 @@ pub struct ParamsOfRunTvm { /// Cache type to put the result. The BOC itself returned if no cache type provided pub boc_cache: Option, /// Return updated account flag. Empty string is returned if the flag is `false` - pub return_updated_account: Option + pub return_updated_account: Option, } #[derive(Serialize, Deserialize, ApiType, Default, Debug, PartialEq, Clone)] @@ -187,7 +191,7 @@ pub struct ResultOfRunTvm { pub account: String, } -async fn parse_transaction( +fn parse_transaction( context: &Arc, transaction: &Transaction, ) -> ClientResult { @@ -196,8 +200,7 @@ async fn parse_transaction( crate::boc::ParamsOfParse { boc: serialize_object_to_base64(transaction, "transaction")?, }, - ) - .await? + )? .parsed) } @@ -240,11 +243,7 @@ pub async fn run_executor( context: Arc, params: ParamsOfRunExecutor, ) -> ClientResult { - run_executor_internal( - context, - params, - true, - ).await + run_executor_internal(context, params, true).await } pub async fn run_executor_internal( @@ -252,10 +251,15 @@ pub async fn run_executor_internal( params: ParamsOfRunExecutor, show_tips_on_error: bool, ) -> ClientResult { - let message = deserialize_object_from_boc::(&context, ¶ms.message, "message").await?.object; - let msg_address = message.dst_ref().ok_or_else(|| Error::invalid_message_type())?.clone(); - let (account, _) = params.account.get_account(&context, msg_address.clone()).await?; - let options = ResolvedExecutionOptions::from_options(&context, params.execution_options).await?; + let message = + deserialize_object_from_boc::(&context, ¶ms.message, "message")?.object; + let msg_address = message + .dst_ref() + .ok_or_else(|| Error::invalid_message_type())? + .clone(); + let (account, _) = params.account.get_account(&context, msg_address.clone())?; + let options = + ResolvedExecutionOptions::from_options(&context, params.execution_options).await?; let account_copy = account.clone(); let contract_info = move || async move { @@ -267,14 +271,14 @@ pub async fn run_executor_internal( } }; - let (transaction, modified_account) = - call_executor( - account.clone(), - message, - options, - contract_info.clone(), - show_tips_on_error, - ).await?; + let (transaction, modified_account) = call_executor( + account.clone(), + message, + options, + contract_info.clone(), + show_tips_on_error, + ) + .await?; let sdk_transaction = ton_sdk::Transaction::try_from(&transaction) .map_err(|err| Error::can_not_read_transaction(err))?; @@ -299,27 +303,26 @@ pub async fn run_executor_internal( // TODO decode Message object without converting to string let decoded = if let Some(abi) = params.abi.as_ref() { - Some(decode_output(&context, abi, out_messages.clone()).await?) + Some(decode_output(&context, abi, out_messages.clone())?) } else { None }; let account = if params.return_updated_account.unwrap_or_default() { - serialize_cell_to_boc(&context, modified_account, "account", params.boc_cache).await? + serialize_cell_to_boc(&context, modified_account, "account", params.boc_cache)? } else { String::new() }; Ok(ResultOfRunExecutor { out_messages, - transaction: parse_transaction(&context, &transaction).await?, + transaction: parse_transaction(&context, &transaction)?, account, decoded, fees, }) } - /// Executes get-methods of ABI-compatible contracts /// /// Performs only a part of compute phase of transaction execution @@ -339,29 +342,36 @@ pub async fn run_tvm( context: Arc, params: ParamsOfRunTvm, ) -> ClientResult { - let mut account = deserialize_object_from_boc::(&context, ¶ms.account, "account").await?; - let message = deserialize_object_from_boc::(&context, ¶ms.message, "message").await?.object; - let options = ResolvedExecutionOptions::from_options(&context, params.execution_options).await?; + let mut account = deserialize_object_from_boc::(&context, ¶ms.account, "account")?; + let message = + deserialize_object_from_boc::(&context, ¶ms.message, "message")?.object; + let options = + ResolvedExecutionOptions::from_options(&context, params.execution_options).await?; if account.object.is_none() { - return Err(Error::invalid_account_boc("Account is None")) + return Err(Error::invalid_account_boc("Account is None")); } let messages = super::call_tvm::call_tvm_msg(&mut account.object, options, &message)?; let mut out_messages = vec![]; for message in messages { - out_messages.push(serialize_object_to_boc(&context, &message, "message", params.boc_cache.clone()).await?); + out_messages.push(serialize_object_to_boc( + &context, + &message, + "message", + params.boc_cache.clone(), + )?); } // TODO decode Message object without converting to string let decoded = if let Some(abi) = params.abi.as_ref() { - Some(decode_output(&context, abi, out_messages.clone()).await?) + Some(decode_output(&context, abi, out_messages.clone())?) } else { None }; let account = if params.return_updated_account.unwrap_or_default() { - serialize_object_to_boc(&context, &account.object, "account", params.boc_cache).await? + serialize_object_to_boc(&context, &account.object, "account", params.boc_cache)? } else { String::new() }; @@ -384,8 +394,7 @@ where F: futures::Future>, { let executor = OrdinaryTransactionExecutor::new( - Arc::try_unwrap(options.blockchain_config) - .unwrap_or_else(|arc| arc.as_ref().clone()) + Arc::try_unwrap(options.blockchain_config).unwrap_or_else(|arc| arc.as_ref().clone()), ); let params = ExecuteParams { block_unixtime: options.block_time, @@ -396,39 +405,40 @@ where signature_id: options.signature_id, ..ExecuteParams::default() }; - let transaction = match executor.execute_with_libs_and_params(Some(&msg), &mut account_root, params) { - Ok(transaction) => transaction, - Err(err) => { - let err_message = err.to_string(); - let err = match contract_info().await { - Ok((address, balance)) => match &err.downcast_ref::() { - Some(ExecutorError::NoAcceptError(code, exit_arg)) => { - let exit_arg = exit_arg - .as_ref() - .map(|item| serialize_item(item)) - .transpose()?; - Error::tvm_execution_failed( - err_message, - *code, - exit_arg, - &address, - None, - show_tips_on_error, - ) - } - Some(ExecutorError::NoFundsToImportMsg) => { - Error::low_balance(&address, balance) - } - Some(ExecutorError::ExtMsgComputeSkipped(reason)) => { - Error::tvm_execution_skipped(reason, &address, balance) - } - _ => Error::unknown_execution_error(err), - }, - Err(err) => err, - }; - return Err(err); - } - }; + let transaction = + match executor.execute_with_libs_and_params(Some(&msg), &mut account_root, params) { + Ok(transaction) => transaction, + Err(err) => { + let err_message = err.to_string(); + let err = match contract_info().await { + Ok((address, balance)) => match &err.downcast_ref::() { + Some(ExecutorError::NoAcceptError(code, exit_arg)) => { + let exit_arg = exit_arg + .as_ref() + .map(|item| serialize_item(item)) + .transpose()?; + Error::tvm_execution_failed( + err_message, + *code, + exit_arg, + &address, + None, + show_tips_on_error, + ) + } + Some(ExecutorError::NoFundsToImportMsg) => { + Error::low_balance(&address, balance) + } + Some(ExecutorError::ExtMsgComputeSkipped(reason)) => { + Error::tvm_execution_skipped(reason, &address, balance) + } + _ => Error::unknown_execution_error(err), + }, + Err(err) => err, + }; + return Err(err); + } + }; Ok((transaction, account_root)) } diff --git a/ton_client/src/tvm/types.rs b/ton_client/src/tvm/types.rs index a33d4e31..6abee141 100644 --- a/ton_client/src/tvm/types.rs +++ b/ton_client/src/tvm/types.rs @@ -48,8 +48,8 @@ pub(crate) struct ResolvedExecutionOptions { pub behavior_modifiers: BehaviorModifiers, } -pub(crate) async fn blockchain_config_from_boc(context: &ClientContext, b64: &str) -> ClientResult { - let config_params = deserialize_object_from_boc(context, b64, "blockchain config").await?; +pub(crate) fn blockchain_config_from_boc(context: &ClientContext, b64: &str) -> ClientResult { + let config_params = deserialize_object_from_boc(context, b64, "blockchain config")?; BlockchainConfig::with_config(config_params.object) .map_err(|err| Error::can_not_read_blockchain_config(err)) } @@ -95,14 +95,14 @@ pub(crate) async fn resolve_network_params( match (provided_config, provided_global_id.or(context.config.network.signature_id)) { (Some(config), Some(global_id)) => { Ok(NetworkParams { - blockchain_config: Arc::new(blockchain_config_from_boc(context, &config).await?), + blockchain_config: Arc::new(blockchain_config_from_boc(context, &config)?), global_id, }) }, (Some(config), None) => { let default = get_default_params(context).await?; Ok(NetworkParams { - blockchain_config: Arc::new(blockchain_config_from_boc(context, &config).await?), + blockchain_config: Arc::new(blockchain_config_from_boc(context, &config)?), global_id: default.global_id, }) }, diff --git a/ton_client/src/utils/calc_storage_fee.rs b/ton_client/src/utils/calc_storage_fee.rs index fa35ed67..65816471 100644 --- a/ton_client/src/utils/calc_storage_fee.rs +++ b/ton_client/src/utils/calc_storage_fee.rs @@ -19,16 +19,16 @@ use std::sync::Arc; #[derive(Serialize, Deserialize, ApiType, Default, Debug)] pub struct ParamsOfCalcStorageFee { - // Account BOC or BOC cache reference - pub account: String, - // Time period in seconds - pub period: u32, + // Account BOC or BOC cache reference + pub account: String, + // Time period in seconds + pub period: u32, } #[derive(Serialize, Deserialize, ApiType, Default, Debug)] pub struct ResultOfCalcStorageFee { - // Storage fee over a period of time in nanotokens - pub fee: String + // Storage fee over a period of time in nanotokens + pub fee: String, } /// Calculates storage fee for an account over a specified time period @@ -37,28 +37,37 @@ pub async fn calc_storage_fee( context: Arc, params: ParamsOfCalcStorageFee, ) -> ClientResult { - let account = deserialize_object_from_boc::( - &context, ¶ms.account, "account" - ) - .await? - .object; + let account = + deserialize_object_from_boc::(&context, ¶ms.account, "account")? + .object; - let storage = account.storage_info().ok_or(Error::invalid_account_boc("Account is None"))?; - let addr = account.get_addr().ok_or(Error::invalid_account_boc("Account is None"))?; - let config = crate::net::network_params::get_default_params(&context).await?.blockchain_config; + let storage = account + .storage_info() + .ok_or(Error::invalid_account_boc("Account is None"))?; + let addr = account + .get_addr() + .ok_or(Error::invalid_account_boc("Account is None"))?; + let config = crate::net::network_params::get_default_params(&context) + .await? + .blockchain_config; if storage.last_paid() == 0 { - return Err(Error::invalid_account_boc("Account `last_paid` field is not initialized")); + return Err(Error::invalid_account_boc( + "Account `last_paid` field is not initialized", + )); } - let fee = config.calc_storage_fee( - storage, - addr.is_masterchain(), - storage.last_paid() + params.period, - ) - .map_err(|err| Error::invalid_account_boc(format!("can not calculate storage fee: {}", err)))?; + let fee = config + .calc_storage_fee( + storage, + addr.is_masterchain(), + storage.last_paid() + params.period, + ) + .map_err(|err| { + Error::invalid_account_boc(format!("can not calculate storage fee: {}", err)) + })?; Ok(ResultOfCalcStorageFee { - fee: format!("{}", fee.as_u128()) + fee: format!("{}", fee.as_u128()), }) -} \ No newline at end of file +} diff --git a/ton_client_processing/Cargo.toml b/ton_client_processing/Cargo.toml index 312804b3..b75e0a96 100644 --- a/ton_client_processing/Cargo.toml +++ b/ton_client_processing/Cargo.toml @@ -1,6 +1,6 @@ [package] name = 'ton_client_processing' -version = '1.43.3' +version = '1.44.0' authors = [ 'TON Labs LTD ' ] edition = '2018' license = 'Apache-2.0' diff --git a/ton_client_processing/src/message_monitor/monitor.rs b/ton_client_processing/src/message_monitor/monitor.rs index 6204044b..6f3f31a6 100644 --- a/ton_client_processing/src/message_monitor/monitor.rs +++ b/ton_client_processing/src/message_monitor/monitor.rs @@ -53,12 +53,12 @@ impl MessageMonitor, ) -> crate::error::Result<()> { - self.state.monitor_messages(queue, messages).await + self.state.monitor_messages(queue, messages) } pub async fn fetch_next_monitor_results( @@ -92,7 +92,7 @@ impl MonitorState { } } - async fn monitor_messages( + fn monitor_messages( self: &Arc, queue: &str, messages: Vec, diff --git a/ton_client_processing/src/tests.rs b/ton_client_processing/src/tests.rs index bdfbd8ee..1174a7ef 100644 --- a/ton_client_processing/src/tests.rs +++ b/ton_client_processing/src/tests.rs @@ -15,9 +15,7 @@ use ton_types::{AccountId, UInt256}; async fn test_fetch() { let api = sdk_services(); let mon = MessageMonitor::new(api.clone()); - mon.monitor_messages("1", vec![msg(1, 1), msg(2, 2)]) - .await - .unwrap(); + mon.monitor_messages("1", vec![msg(1, 1), msg(2, 2)]).unwrap(); let info = mon.get_queue_info("1").unwrap(); assert_eq!(info.resolved, 0); assert_eq!(info.unresolved, 2); @@ -47,9 +45,7 @@ async fn test_fetch() { async fn test_cancel_monitor() { let api = sdk_services(); let mon = MessageMonitor::new(api.clone()); - mon.monitor_messages("1", vec![msg(1, 1), msg(2, 2)]) - .await - .unwrap(); + mon.monitor_messages("1", vec![msg(1, 1), msg(2, 2)]).unwrap(); let info = mon.get_queue_info("1").unwrap(); assert_eq!(info.resolved, 0); assert_eq!(info.unresolved, 2); @@ -63,9 +59,7 @@ async fn test_cancel_monitor() { async fn test_fetch_at_least_one() { let api = sdk_services(); let mon = MessageMonitor::new(api.clone()); - mon.monitor_messages("1", vec![msg(1, 1), msg(2, 2)]) - .await - .unwrap(); + mon.monitor_messages("1", vec![msg(1, 1), msg(2, 2)]).unwrap(); let results = mon .fetch_next_monitor_results("1", MonitorFetchWaitMode::NoWait) .await @@ -99,9 +93,7 @@ async fn test_fetch_wait_all() { let mon = Arc::new(MessageMonitor::new(api.clone())); // Start monitoring for [1, 2] messages - mon.monitor_messages("1", vec![msg(1, 1), msg(2, 2)]) - .await - .unwrap(); + mon.monitor_messages("1", vec![msg(1, 1), msg(2, 2)]).unwrap(); sleep(Duration::from_millis(1100)).await; @@ -158,9 +150,7 @@ async fn test_mon_info() { let info = mon.get_queue_info("1").unwrap(); assert_eq!(info.resolved, 0); assert_eq!(info.unresolved, 0); - mon.monitor_messages("1", vec![msg(1, 1), msg(2, 2)]) - .await - .unwrap(); + mon.monitor_messages("1", vec![msg(1, 1), msg(2, 2)]).unwrap(); sleep(Duration::from_millis(1100)).await; let info = mon.get_queue_info("1").unwrap(); assert_eq!(info.resolved, 0); @@ -177,9 +167,7 @@ async fn test_buffering() { let api = sdk_services(); let mon = MessageMonitor::new(api.clone()); - mon.monitor_messages("1", vec![msg(1, 1), msg(2, 2)]) - .await - .unwrap(); + mon.monitor_messages("1", vec![msg(1, 1), msg(2, 2)]).unwrap(); tokio::time::sleep(Duration::from_millis(100)).await; assert_eq!( api.active_subscription_count(), @@ -194,9 +182,7 @@ async fn test_buffering() { "first subscription should be started after 1 second" ); - mon.monitor_messages("1", vec![msg(3, 3), msg(4, 4)]) - .await - .unwrap(); + mon.monitor_messages("1", vec![msg(3, 3), msg(4, 4)]).unwrap(); tokio::time::sleep(Duration::from_millis(100)).await; assert_eq!( api.active_subscription_count(), diff --git a/ton_sdk/Cargo.toml b/ton_sdk/Cargo.toml index f86f8519..4c40e8a7 100644 --- a/ton_sdk/Cargo.toml +++ b/ton_sdk/Cargo.toml @@ -1,6 +1,6 @@ [package] name = 'ton_sdk' -version = '1.43.3' +version = '1.44.0' edition = '2018' license = 'Apache-2.0' authors = [ 'TON Labs LTD ' ] diff --git a/toncli/Cargo.toml b/toncli/Cargo.toml index 5cf2c205..d18f275b 100644 --- a/toncli/Cargo.toml +++ b/toncli/Cargo.toml @@ -9,7 +9,7 @@ license = 'Apache-2.0' name = 'toncli' readme = 'README.md' repository = 'https://github.com/tonlabs/ever-sdk' -version = '1.43.3' +version = '1.44.0' [dependencies] base64 = '0.13.0' diff --git a/tools/api.json b/tools/api.json index 8065e832..5506a9ba 100644 --- a/tools/api.json +++ b/tools/api.json @@ -1,5 +1,5 @@ { - "version": "1.43.3", + "version": "1.44.0", "modules": [ { "name": "client", diff --git a/tools/package.json b/tools/package.json index de7b1e1f..6436882d 100644 --- a/tools/package.json +++ b/tools/package.json @@ -1,6 +1,6 @@ { "name": "tools", - "version": "1.43.3", + "version": "1.44.0", "description": "", "main": "index.js", "scripts": { diff --git a/tools/ts-code.ts b/tools/ts-code.ts index 53240061..07dfc608 100644 --- a/tools/ts-code.ts +++ b/tools/ts-code.ts @@ -36,6 +36,10 @@ interface IClient { functionParams?: any, responseHandler?: ResponseHandler ): Promise; + requestSync( + functionName: string, + functionParams?: any, + ): any; resolve_app_request(app_request_id: number | null, result: any): Promise; reject_app_request(app_request_id: number | null, error: any): Promise; } @@ -158,15 +162,20 @@ export class ${Code.upperFirst(module.name)}Module { `; for (const func of module.functions) { - ts += jsDocStart(func, INDENT); const info = this.getFunctionInfo(func); - if (info.params) { - ts += jsDoc("", INDENT); - ts += jsDoc(`@param {${getRefName(info.params)}} ${info.params.name}`, INDENT); + const funcDoc = () => { + ts += jsDocStart(func, INDENT); + if (info.params) { + ts += jsDoc("", INDENT); + ts += jsDoc(`@param {${getRefName(info.params)}} ${info.params.name}`, INDENT); + } + ts += jsDoc(`@returns ${getRefName(func.result)}`, INDENT); + ts += jsDocEnd(INDENT); } - ts += jsDoc(`@returns ${getRefName(func.result)}`, INDENT); - ts += jsDocEnd(INDENT); + funcDoc() ts += this.functionImpl(func); + funcDoc() + ts += this.syncFunctionImpl(func); } ts += "}\n\n"; @@ -289,6 +298,14 @@ export class ${Code.upperFirst(module.name)}Module { return decls; } + syncParamsDecls(paramsInfo: ApiFunctionInfo): string[] { + const decls: string[] = []; + if (paramsInfo.params) { + decls.push(`${paramsInfo.params.name}: ${this.type(paramsInfo.params, "")}`); + } + return decls; + } + functionInterface(func: ApiFunction): string { const paramsInfo = this.getFunctionInfo(func); const paramsDecls = this.paramsDecls(paramsInfo); @@ -378,6 +395,20 @@ async function dispatch${obj.name}(obj: ${obj.name}, params: ParamsOf${obj.name} }\n`; } + syncFunctionImpl(func: ApiFunction): string { + const paramsInfo = this.getFunctionInfo(func); + const paramsDecl = this.syncParamsDecls(paramsInfo).map(p => `${p}`).join(", "); + const calls = [`'${func.module.name}.${func.name}'`]; + if (paramsInfo.params) { + calls.push(`${paramsInfo.params.name}`); + } + const returnStatement = func.result.type !== ApiTypeIs.None ? "return " : ""; + return ` + ${func.name}_sync(${paramsDecl}): ${this.type(func.result, "")} { + ${returnStatement}this.client.requestSync(${calls.join(", ")}); + }\n`; + } + modules(): string { return ` ${MODULES_HEADER}