diff --git a/CHANGELOG.md b/CHANGELOG.md index bf69827b2..fec526d6d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,23 @@ All notable changes to this project will be documented in this file. +## [1.38.0] – 2022-10-06 + +### New + +- **Debot module**: + - ABI specification v2.3 is supported in DEngine. + - Supported flags `OVERRIDE_TS`, `OVERRIDE_EXPT`, `ASYNC_CALL` for external messages in DEngine. + +### Improvement + +- Support cookies in net module for std mode (not wasm) +- Remove network aliases (main, dev, main.ton.dev, net.ton.dev) +- No balancing logic in case of 1 endpoint + removed the check of REMP support on backend during client initialization. + These changes will make client initialization faster -> CLI tools that use SDK will work faster, web pages will load initial data faster. +- Changed 401 error message to response message from API +- Tests improvements: cryptobox tests made stable + ## [1.37.2] – 2022-08-10 ### New @@ -24,17 +41,17 @@ All notable changes to this project will be documented in this file. ### Improvement - `create_crypto_box` optimisation. - When a user creates a crypto box, library encrypts provided secret information using provided + When a user creates a crypto box, library encrypts provided secret information using provided password and salt. - When library encrypts the secret, it calculates encryption key from password and salt + When library encrypts the secret, it calculates encryption key from password and salt using `scrypt` function which takes a lot of CPU time (about 1 second). - So when a user creates many crypto boxes using the same password and salt, + So when a user creates many crypto boxes using the same password and salt, it takes a lot of time (about 12 seconds for 10 crypto boxes). - With the optimisations introduced in this version the library stores the + With the optimisations introduced in this version the library stores the pair (password+salt => encryption key) in internal cache for approximately 2 seconds. - So when a user creates many crypto boxes at a time using the same password and salt, - library uses cached information to skip heavy calculations. As a result now it takes only - a second to create 10 crypto boxes. + So when a user creates many crypto boxes at a time using the same password and salt, + library uses cached information to skip heavy calculations. As a result now it takes only + a second to create 10 crypto boxes. ### Fixed @@ -44,10 +61,10 @@ All notable changes to this project will be documented in this file. ### Fixed -- Pinned BOC cache now has reference counter for each pin in BOC. BOC can be pinned several times +- Pinned BOC cache now has reference counter for each pin in BOC. BOC can be pinned several times with the same pin. BOC is removed from cache after all references for all pins are unpinned with `cache_unpin` function calls. -- Fixed error resolving in case when account state was modified after message expiration time. Now +- Fixed error resolving in case when account state was modified after message expiration time. Now appropriate error text is added to error message instead of executor internal error ## [1.37.0] – 2022-07-28 @@ -55,7 +72,7 @@ appropriate error text is added to error message instead of executor internal er ### New - client sends `config.network.access_key` as `Authorization: Basic ...` or `Authorization: Bearer ...` header depending on the value passed: - if value is in hex, then it is processed as project secret (basic), if in base64 - then as JWT token (bearer). + if value is in hex, then it is processed as project secret (basic), if in base64 - then as JWT token (bearer). - client accepts endpoints with `/graphql` suffixes specified in config. ### Fixed @@ -66,9 +83,9 @@ appropriate error text is added to error message instead of executor internal er ### Improvement -- Time synchronization check between device and server improved: calculation of time-diff - with server is moved from batched query to send_message function and therefore now query - execution time does not affect this time diff. +- Time synchronization check between device and server improved: calculation of time-diff + with server is moved from batched query to send_message function and therefore now query + execution time does not affect this time diff. ## [1.36.0] – 2022-07-01 diff --git a/Cargo.lock b/Cargo.lock index 397d5773d..e8564b34f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -75,7 +75,7 @@ checksum = "98161a4e3e2184da77bb14f02184cdd111e83bbbcc9979dfee3c44b9a85f5602" [[package]] name = "api_derive" -version = "1.37.2" +version = "1.38.0" dependencies = [ "api_info", "quote", @@ -85,7 +85,7 @@ dependencies = [ [[package]] name = "api_info" -version = "1.37.2" +version = "1.38.0" dependencies = [ "serde", "serde_derive", @@ -94,7 +94,7 @@ dependencies = [ [[package]] name = "api_test" -version = "1.37.2" +version = "1.38.0" dependencies = [ "api_derive", "api_info", @@ -345,7 +345,7 @@ dependencies = [ "js-sys", "num-integer", "num-traits", - "time", + "time 0.1.44", "wasm-bindgen", "winapi", ] @@ -381,6 +381,33 @@ dependencies = [ "unreachable", ] +[[package]] +name = "cookie" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "344adc371239ef32293cb1c4fe519592fcf21206c79c02854320afcdf3ab4917" +dependencies = [ + "percent-encoding", + "time 0.3.15", + "version_check", +] + +[[package]] +name = "cookie_store" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e4b6aa369f41f5faa04bb80c9b1f4216ea81646ed6124d76ba5c49a7aafd9cd" +dependencies = [ + "cookie", + "idna 0.2.3", + "log", + "publicsuffix", + "serde", + "serde_json", + "time 0.3.15", + "url", +] + [[package]] name = "core-foundation" version = "0.9.3" @@ -547,9 +574,9 @@ dependencies = [ [[package]] name = "digest" -version = "0.10.3" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" +checksum = "adfbc57365a37acbd2ebf2b64d7e69bb766e2fea813521ed536f5d0520dcf86c" dependencies = [ "block-buffer 0.10.3", "crypto-common", @@ -937,7 +964,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "digest 0.10.3", + "digest 0.10.5", ] [[package]] @@ -1039,18 +1066,28 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.48" +version = "0.1.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "237a0714f28b1ee39ccec0770ccb544eb02c9ef2c82bb096230eefcffa6468b0" +checksum = "fd911b35d940d2bd0bea0f9100068e5b97b51a1cbe13d13382f132e0365257a0" dependencies = [ "android_system_properties", "core-foundation-sys", "js-sys", - "once_cell", "wasm-bindgen", "winapi", ] +[[package]] +name = "idna" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" +dependencies = [ + "matches", + "unicode-bidi", + "unicode-normalization", +] + [[package]] name = "idna" version = "0.3.0" @@ -1108,24 +1145,24 @@ checksum = "879d54834c8c76457ef4293a689b2a8c59b076067ad77b15efafbb05f92a592b" [[package]] name = "itertools" -version = "0.10.4" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8bf247779e67a9082a4790b45e71ac7cfd1321331a5c856a74a9faebdab78d0" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" dependencies = [ "either", ] [[package]] name = "itoa" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754" +checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc" [[package]] name = "jobserver" -version = "0.1.24" +version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa" +checksum = "068b1ee6743e4d11fb9c6a1e6064b3693a1b600e7f5f5988047d98b3dc9fb90b" dependencies = [ "libc", ] @@ -1158,9 +1195,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.132" +version = "0.2.134" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5" +checksum = "329c933548736bc49fd575ee68c89e8be4d260064184389a5b77517cddd99ffb" [[package]] name = "libsecp256k1" @@ -1218,9 +1255,9 @@ checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" [[package]] name = "lock_api" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f80bf5aacaf25cbfc8210d1cfb718f2bf3b11c4c54e5afe36c236853a8ec390" +checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" dependencies = [ "autocfg", "scopeguard", @@ -1285,6 +1322,12 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "matches" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" + [[package]] name = "memchr" version = "2.5.0" @@ -1439,6 +1482,15 @@ dependencies = [ "libc", ] +[[package]] +name = "num_threads" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" +dependencies = [ + "libc", +] + [[package]] name = "object" version = "0.29.0" @@ -1450,9 +1502,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.14.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f7254b99e31cad77da24b08ebf628882739a608578bb1bcdfc1f9c21260d7c0" +checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1" [[package]] name = "opaque-debug" @@ -1468,9 +1520,9 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "openssl" -version = "0.10.41" +version = "0.10.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "618febf65336490dfcf20b73f885f5651a0c89c64c2d4a8c3662585a70bf5bd0" +checksum = "12fc0523e3bd51a692c8850d075d74dc062ccf251c0110668cbd921917118a13" dependencies = [ "bitflags", "cfg-if 1.0.0", @@ -1500,9 +1552,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.75" +version = "0.9.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5f9bd0c2710541a3cda73d6f9ac4f1b240de4ae261065d309dbe73d9dceb42f" +checksum = "5230151e44c0f05157effb743e8d517472843121cf9243e8b81393edb5acd9ce" dependencies = [ "autocfg", "cc", @@ -1573,7 +1625,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" dependencies = [ - "digest 0.10.3", + "digest 0.10.5", ] [[package]] @@ -1584,9 +1636,9 @@ checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" [[package]] name = "pest" -version = "2.3.1" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb779fcf4bb850fbbb0edc96ff6cf34fd90c4b1a112ce042653280d9a7364048" +checksum = "dbc7bc69c062e492337d74d59b120c274fd3d261b6bf6d3207d499b4b379c41a" dependencies = [ "thiserror", "ucd-trie", @@ -1594,9 +1646,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.3.1" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "502b62a6d0245378b04ffe0a7fb4f4419a4815fce813bd8a0ec89a56e07d67b1" +checksum = "60b75706b9642ebcb34dab3bc7750f811609a0eb1dd8b88c2d15bf628c1c65b2" dependencies = [ "pest", "pest_generator", @@ -1604,9 +1656,9 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.3.1" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "451e629bf49b750254da26132f1a5a9d11fd8a95a3df51d15c4abd1ba154cb6c" +checksum = "f4f9272122f5979a6511a749af9db9bfc810393f63119970d7085fed1c4ea0db" dependencies = [ "pest", "pest_meta", @@ -1617,9 +1669,9 @@ dependencies = [ [[package]] name = "pest_meta" -version = "2.3.1" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcec162c71c45e269dfc3fc2916eaeb97feab22993a21bcce4721d08cd7801a6" +checksum = "4c8717927f9b79515e565a64fe46c38b8cd0427e64c40680b14a7365ab09ac8d" dependencies = [ "once_cell", "pest", @@ -1708,15 +1760,37 @@ dependencies = [ "yansi", ] +[[package]] +name = "proc-macro-hack" +version = "0.5.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" + [[package]] name = "proc-macro2" -version = "1.0.43" +version = "1.0.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab" +checksum = "94e2ef8dbfc347b10c094890f778ee2e36ca9bb4262e86dc99cd217e35f3470b" dependencies = [ "unicode-ident", ] +[[package]] +name = "psl-types" +version = "2.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33cb294fe86a74cbcf50d4445b37da762029549ebeea341421c7c70370f86cac" + +[[package]] +name = "publicsuffix" +version = "2.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aeeedb0b429dc462f30ad27ef3de97058b060016f47790c066757be38ef792b4" +dependencies = [ + "idna 0.2.3", + "psl-types", +] + [[package]] name = "quote" version = "1.0.21" @@ -1851,12 +1925,14 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.11" +version = "0.11.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b75aa69a3f06bbcc66ede33af2af253c6f7a86b1ca0033f60c580a27074fbf92" +checksum = "431949c384f4e2ae07605ccaa56d1d9d2ecdb5cadd4f9577ccfab29f2e5149fc" dependencies = [ "base64 0.13.0", "bytes", + "cookie", + "cookie_store", "encoding_rs", "futures-core", "futures-util", @@ -1867,12 +1943,13 @@ dependencies = [ "hyper-tls", "ipnet", "js-sys", - "lazy_static", "log", "mime", "native-tls", + "once_cell", "percent-encoding", "pin-project-lite", + "proc-macro-hack", "serde", "serde_json", "serde_urlencoded", @@ -1975,9 +2052,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.144" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f747710de3dcd43b88c9168773254e809d8ddbdf9653b84e2554ab219f17860" +checksum = "728eb6351430bccb993660dfffc5a72f91ccc1295abaa8ce19b27ebe4f75568b" dependencies = [ "serde_derive", ] @@ -1994,9 +2071,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.144" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94ed3a816fb1d101812f83e789f888322c34e291f894f19590dc310963e87a00" +checksum = "81fa1584d3d1bcacd84c277a0dfe21f5b0f6accf4a23d04d4c6d61f1af522b4c" dependencies = [ "proc-macro2", "quote", @@ -2058,18 +2135,18 @@ checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f" dependencies = [ "cfg-if 1.0.0", "cpufeatures", - "digest 0.10.3", + "digest 0.10.5", ] [[package]] name = "sha1" -version = "0.10.4" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "006769ba83e921b3085caa8334186b00cf92b4cb1a6cf4632fbccc8eff5c7549" +checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" dependencies = [ "cfg-if 1.0.0", "cpufeatures", - "digest 0.10.3", + "digest 0.10.5", ] [[package]] @@ -2099,20 +2176,20 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.5" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9db03534dff993187064c4e0c05a5708d2a9728ace9a8959b77bedf415dac5" +checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" dependencies = [ "cfg-if 1.0.0", "cpufeatures", - "digest 0.10.3", + "digest 0.10.5", ] [[package]] name = "signature" -version = "1.6.1" +version = "1.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e90531723b08e4d6d71b791108faf51f03e1b4a7784f96b2b87f852ebc247228" +checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" [[package]] name = "similar" @@ -2134,9 +2211,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" [[package]] name = "socket2" @@ -2165,9 +2242,9 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" [[package]] name = "syn" -version = "1.0.99" +version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13" +checksum = "3fcd952facd492f9be3ef0d0b7032a6e442ee9b361d4acc2b1d0c4aaa5f613a1" dependencies = [ "proc-macro2", "quote", @@ -2208,18 +2285,18 @@ checksum = "507e9898683b6c43a9aa55b64259b721b52ba226e0f3779137e50ad114a4c90b" [[package]] name = "thiserror" -version = "1.0.35" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c53f98874615aea268107765aa1ed8f6116782501d18e53d08b471733bea6c85" +checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.35" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8b463991b4eab2d801e724172285ec4195c650e8ec79b149e6c2a8e6dd3f783" +checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" dependencies = [ "proc-macro2", "quote", @@ -2248,6 +2325,24 @@ dependencies = [ "winapi", ] +[[package]] +name = "time" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d634a985c4d4238ec39cacaed2e7ae552fbd3c476b552c1deac3021b7d7eaf0c" +dependencies = [ + "itoa", + "libc", + "num_threads", + "time-macros", +] + +[[package]] +name = "time-macros" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42657b1a6f4d817cda8e7a0ace261fe0cc946cf3a80314390b22cc61ae080792" + [[package]] name = "tiny-bip39" version = "1.0.0" @@ -2260,7 +2355,7 @@ dependencies = [ "pbkdf2 0.11.0", "rand 0.8.5", "rustc-hash", - "sha2 0.10.5", + "sha2 0.10.6", "thiserror", "unicode-normalization", "wasm-bindgen", @@ -2284,9 +2379,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.21.1" +version = "1.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0020c875007ad96677dcc890298f4b942882c5d4eb7cc8f439fc3bf813dc9c95" +checksum = "a9e03c497dc955702ba729190dc4aac6f2a0ce97f913e5b1b5912fc5039d9099" dependencies = [ "autocfg", "bytes", @@ -2294,7 +2389,6 @@ dependencies = [ "memchr", "mio", "num_cpus", - "once_cell", "pin-project-lite", "socket2", "tokio-macros", @@ -2324,9 +2418,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df54d54117d6fdc4e4fea40fe1e4e566b3505700e148a6827e59b34b0d2600d9" +checksum = "f6edf2d6bc038a43d31353570e27270603f4648d18f5ed10c0e179abe43255af" dependencies = [ "futures-core", "pin-project-lite", @@ -2385,8 +2479,8 @@ dependencies = [ [[package]] name = "ton_api" -version = "0.2.131" -source = "git+https://github.com/tonlabs/ton-labs-tl.git?tag=0.2.131#f723789f6e48facdb53898c31f5c8ed2dda2df00" +version = "0.2.132" +source = "git+https://github.com/tonlabs/ton-labs-tl.git?tag=0.2.132#1b59c748469f85f53df7762be210334f531dd0a2" dependencies = [ "byteorder", "extfmt", @@ -2417,14 +2511,14 @@ dependencies = [ "log", "num", "num-traits", - "sha2 0.10.5", + "sha2 0.10.6", "ton_types", ] [[package]] name = "ton_block_json" -version = "0.7.31" -source = "git+https://github.com/tonlabs/ton-labs-block-json.git?tag=0.7.31#21e6c2d234672d3f2f12d72eaadfa571b44558fb" +version = "0.7.33" +source = "git+https://github.com/tonlabs/ton-labs-block-json.git?tag=0.7.33#04cd85e67446e0cdb78c163433c9fba01f074aaa" dependencies = [ "base64 0.13.0", "failure", @@ -2441,7 +2535,7 @@ dependencies = [ [[package]] name = "ton_client" -version = "1.37.2" +version = "1.38.0" dependencies = [ "aes", "api_derive", @@ -2519,7 +2613,7 @@ dependencies = [ [[package]] name = "ton_sdk" -version = "1.37.2" +version = "1.38.0" dependencies = [ "api_derive", "api_info", @@ -2545,7 +2639,7 @@ dependencies = [ [[package]] name = "ton_tl_codegen" version = "0.0.2" -source = "git+https://github.com/tonlabs/ton-labs-tl.git?tag=0.2.131#f723789f6e48facdb53898c31f5c8ed2dda2df00" +source = "git+https://github.com/tonlabs/ton-labs-tl.git?tag=0.2.132#1b59c748469f85f53df7762be210334f531dd0a2" dependencies = [ "crc 1.8.1", "failure", @@ -2601,7 +2695,7 @@ dependencies = [ [[package]] name = "toncli" -version = "1.37.2" +version = "1.38.0" dependencies = [ "api_info", "assert_cmd", @@ -2624,9 +2718,9 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.36" +version = "0.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fce9567bd60a67d08a16488756721ba392f24f29006402881e43b19aac64307" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" dependencies = [ "cfg-if 1.0.0", "pin-project-lite", @@ -2635,9 +2729,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.29" +version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aeea4303076558a00714b823f9ad67d58a3bbda1df83d8827d21193156e22f7" +checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" dependencies = [ "once_cell", ] @@ -2709,18 +2803,18 @@ checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd" [[package]] name = "unicode-normalization" -version = "0.1.21" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "854cbdc4f7bc6ae19c820d44abdc3277ac3e1b2b93db20a636825d9322fb60e6" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" dependencies = [ "tinyvec", ] [[package]] name = "unicode-xid" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" [[package]] name = "unreachable" @@ -2761,7 +2855,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" dependencies = [ "form_urlencoded", - "idna", + "idna 0.3.0", "percent-encoding", ] diff --git a/api/derive/Cargo.toml b/api/derive/Cargo.toml index 270892877..adf888ade 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.37.2' +version = '1.38.0' [dependencies] quote = '1.0' diff --git a/api/info/Cargo.toml b/api/info/Cargo.toml index 184f85acb..96a49c2a3 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.37.2' +version = '1.38.0' [dependencies] serde = '1.0.115' diff --git a/api/test/Cargo.toml b/api/test/Cargo.toml index 6eccf3f43..215eb280a 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.37.2' +version = '1.38.0' [dependencies] serde = '1.0.115' diff --git a/docs/reference/types-and-methods/mod_client.md b/docs/reference/types-and-methods/mod_client.md index c8e352166..f6965f234 100644 --- a/docs/reference/types-and-methods/mod_client.md +++ b/docs/reference/types-and-methods/mod_client.md @@ -1,23 +1,20 @@ # Module client -## Module client - Provides information about library. -### Functions -[get\_api\_reference](mod\_client.md#get\_api\_reference) – Returns Core Library API reference +## Functions +[get_api_reference](mod\_client.md#get_api_reference) – Returns Core Library API reference [version](mod\_client.md#version) – Returns Core Library version [config](mod\_client.md#config) – Returns Core Library API reference -[build\_info](mod\_client.md#build\_info) – Returns detailed information about this build. - -[resolve\_app\_request](mod\_client.md#resolve\_app\_request) – Resolves application request processing result +[build_info](mod\_client.md#build_info) – Returns detailed information about this build. -### Types +[resolve_app_request](mod\_client.md#resolve_app_request) – Resolves application request processing result +## Types [ClientErrorCode](mod\_client.md#clienterrorcode) [ClientError](mod\_client.md#clienterror) @@ -54,9 +51,9 @@ Provides information about library. [ParamsOfResolveAppRequest](mod\_client.md#paramsofresolveapprequest) -## Functions -### get\_api\_reference +# Functions +## get_api_reference Returns Core Library API reference @@ -68,11 +65,13 @@ type ResultOfGetApiReference = { function get_api_reference(): Promise; ``` -#### Result -* `api`: _API_ +### Result -### version +- `api`: _API_ + + +## version Returns Core Library version @@ -84,11 +83,13 @@ type ResultOfVersion = { function version(): Promise; ``` -#### Result -* `version`: _string_ – Core Library version +### Result + +- `version`: _string_ – Core Library version -### config + +## config Returns Core Library API reference @@ -105,16 +106,18 @@ type ClientConfig = { function config(): Promise; ``` -#### Result -* `network`?: [_NetworkConfig_](mod\_client.md#networkconfig) -* `crypto`?: [_CryptoConfig_](mod\_client.md#cryptoconfig) -* `abi`?: [_AbiConfig_](mod\_client.md#abiconfig) -* `boc`?: [_BocConfig_](mod\_client.md#bocconfig) -* `proofs`?: [_ProofsConfig_](mod\_client.md#proofsconfig) -* `local_storage_path`?: _string_ – For file based storage is a folder name where SDK will store its data. For browser based is a browser async storage key prefix. Default (recommended) value is "\~/.tonclient" for native environments and ".tonclient" for web-browser. +### Result + +- `network`?: _[NetworkConfig](mod\_client.md#networkconfig)_ +- `crypto`?: _[CryptoConfig](mod\_client.md#cryptoconfig)_ +- `abi`?: _[AbiConfig](mod\_client.md#abiconfig)_ +- `boc`?: _[BocConfig](mod\_client.md#bocconfig)_ +- `proofs`?: _[ProofsConfig](mod\_client.md#proofsconfig)_ +- `local_storage_path`?: _string_ – For file based storage is a folder name where SDK will store its data. For browser based is a browser async storage key prefix. Default (recommended) value is "~/.tonclient" for native environments and ".tonclient" for web-browser. -### build\_info + +## build_info Returns detailed information about this build. @@ -127,12 +130,14 @@ type ResultOfBuildInfo = { function build_info(): Promise; ``` -#### Result -* `build_number`: _number_ – Build number assigned to this build by the CI. -* `dependencies`: [_BuildInfoDependency_](mod\_client.md#buildinfodependency)_\[]_ – Fingerprint of the most important dependencies. +### Result + +- `build_number`: _number_ – Build number assigned to this build by the CI. +- `dependencies`: _[BuildInfoDependency](mod\_client.md#buildinfodependency)[]_ – Fingerprint of the most important dependencies. + -### resolve\_app\_request +## resolve_app_request Resolves application request processing result @@ -146,16 +151,13 @@ function resolve_app_request( params: ParamsOfResolveAppRequest, ): Promise; ``` +### Parameters +- `app_request_id`: _number_ – Request ID received from SDK +- `result`: _[AppRequestResult](mod\_client.md#apprequestresult)_ – Result of request processing -#### Parameters - -* `app_request_id`: _number_ – Request ID received from SDK -* `result`: [_AppRequestResult_](mod\_client.md#apprequestresult) – Result of request processing - -## Types - -### ClientErrorCode +# Types +## ClientErrorCode ```ts enum ClientErrorCode { NotImplemented = 1, @@ -195,47 +197,46 @@ enum ClientErrorCode { LocalStorageError = 35 } ``` - One of the following value: -* `NotImplemented = 1` -* `InvalidHex = 2` -* `InvalidBase64 = 3` -* `InvalidAddress = 4` -* `CallbackParamsCantBeConvertedToJson = 5` -* `WebsocketConnectError = 6` -* `WebsocketReceiveError = 7` -* `WebsocketSendError = 8` -* `HttpClientCreateError = 9` -* `HttpRequestCreateError = 10` -* `HttpRequestSendError = 11` -* `HttpRequestParseError = 12` -* `CallbackNotRegistered = 13` -* `NetModuleNotInit = 14` -* `InvalidConfig = 15` -* `CannotCreateRuntime = 16` -* `InvalidContextHandle = 17` -* `CannotSerializeResult = 18` -* `CannotSerializeError = 19` -* `CannotConvertJsValueToJson = 20` -* `CannotReceiveSpawnedResult = 21` -* `SetTimerError = 22` -* `InvalidParams = 23` -* `ContractsAddressConversionFailed = 24` -* `UnknownFunction = 25` -* `AppRequestError = 26` -* `NoSuchRequest = 27` -* `CanNotSendRequestResult = 28` -* `CanNotReceiveRequestResult = 29` -* `CanNotParseRequestResult = 30` -* `UnexpectedCallbackResponse = 31` -* `CanNotParseNumber = 32` -* `InternalError = 33` -* `InvalidHandle = 34` -* `LocalStorageError = 35` - -### ClientError - +- `NotImplemented = 1` +- `InvalidHex = 2` +- `InvalidBase64 = 3` +- `InvalidAddress = 4` +- `CallbackParamsCantBeConvertedToJson = 5` +- `WebsocketConnectError = 6` +- `WebsocketReceiveError = 7` +- `WebsocketSendError = 8` +- `HttpClientCreateError = 9` +- `HttpRequestCreateError = 10` +- `HttpRequestSendError = 11` +- `HttpRequestParseError = 12` +- `CallbackNotRegistered = 13` +- `NetModuleNotInit = 14` +- `InvalidConfig = 15` +- `CannotCreateRuntime = 16` +- `InvalidContextHandle = 17` +- `CannotSerializeResult = 18` +- `CannotSerializeError = 19` +- `CannotConvertJsValueToJson = 20` +- `CannotReceiveSpawnedResult = 21` +- `SetTimerError = 22` +- `InvalidParams = 23` +- `ContractsAddressConversionFailed = 24` +- `UnknownFunction = 25` +- `AppRequestError = 26` +- `NoSuchRequest = 27` +- `CanNotSendRequestResult = 28` +- `CanNotReceiveRequestResult = 29` +- `CanNotParseRequestResult = 30` +- `UnexpectedCallbackResponse = 31` +- `CanNotParseNumber = 32` +- `InternalError = 33` +- `InvalidHandle = 34` +- `LocalStorageError = 35` + + +## ClientError ```ts type ClientError = { code: number, @@ -243,13 +244,12 @@ type ClientError = { data: any } ``` +- `code`: _number_ +- `message`: _string_ +- `data`: _any_ -* `code`: _number_ -* `message`: _string_ -* `data`: _any_ - -### ClientConfig +## ClientConfig ```ts type ClientConfig = { network?: NetworkConfig, @@ -260,16 +260,15 @@ type ClientConfig = { local_storage_path?: string } ``` +- `network`?: _[NetworkConfig](mod\_client.md#networkconfig)_ +- `crypto`?: _[CryptoConfig](mod\_client.md#cryptoconfig)_ +- `abi`?: _[AbiConfig](mod\_client.md#abiconfig)_ +- `boc`?: _[BocConfig](mod\_client.md#bocconfig)_ +- `proofs`?: _[ProofsConfig](mod\_client.md#proofsconfig)_ +- `local_storage_path`?: _string_ – For file based storage is a folder name where SDK will store its data. For browser based is a browser async storage key prefix. Default (recommended) value is "~/.tonclient" for native environments and ".tonclient" for web-browser. -* `network`?: [_NetworkConfig_](mod\_client.md#networkconfig) -* `crypto`?: [_CryptoConfig_](mod\_client.md#cryptoconfig) -* `abi`?: [_AbiConfig_](mod\_client.md#abiconfig) -* `boc`?: [_BocConfig_](mod\_client.md#bocconfig) -* `proofs`?: [_ProofsConfig_](mod\_client.md#proofsconfig) -* `local_storage_path`?: _string_ – For file based storage is a folder name where SDK will store its data. For browser based is a browser async storage key prefix. Default (recommended) value is "\~/.tonclient" for native environments and ".tonclient" for web-browser. - -### NetworkConfig +## NetworkConfig ```ts type NetworkConfig = { server_address?: string, @@ -291,60 +290,40 @@ type NetworkConfig = { access_key?: string } ``` - -* `server_address`?: _string_ – **This field is deprecated, but left for backward-compatibility.** -* `endpoints`?: _string\[]_ – List of GraphQL endpoints.\ - Any correct URL format can be specified, including IP addresses. This parameter is prevailing over `server_address`.\ - Check the full list of [supported network endpoints](../ton-os-api/networks.md). -* `network_retries_count`?: _number_ – **This field is deprecated, but left for backward-compatibility.**\ - You must use `network.max_reconnect_timeout` that allows to specify maximum network resolving timeout. -* `max_reconnect_timeout`?: _number_ – Maximum time for sequential reconnections.\ - Must be specified in milliseconds. Default is 120000 (2 min). -* `reconnect_timeout`?: _number_ – Deprecated -* `message_retries_count`?: _number_ – The number of automatic message processing retries that SDK performs in case of `Message Expired (507)` error - but only for those messages which local emulation was successful or failed with replay protection error.\ - Default is 5. -* `message_processing_timeout`?: _number_ – Timeout that is used to process message delivery for the contracts which ABI does not include "expire" header. If the message is not delivered within the specified timeout the appropriate error occurs.\ - Must be specified in milliseconds. Default is 40000 (40 sec). -* `wait_for_timeout`?: _number_ – Maximum timeout that is used for query response.\ - Must be specified in milliseconds. Default is 40000 (40 sec). -* `out_of_sync_threshold`?: _number_ – Maximum time difference between server and client.\ - If client's device time is out of sync and difference is more than the threshold then error will occur. Also an error will occur if the specified threshold is more than\ - `message_processing_timeout/2`.\ - \ - Must be specified in milliseconds. Default is 15000 (15 sec). -* `sending_endpoint_count`?: _number_ – Maximum number of randomly chosen endpoints the library uses to broadcast a message.\ - Default is 1. -* `latency_detection_interval`?: _number_ – Frequency of sync latency detection.\ - Library periodically checks the current endpoint for blockchain data syncronization latency.\ - If the latency (time-lag) is less then `NetworkConfig.max_latency`\ - then library selects another endpoint.\ - \ - Must be specified in milliseconds. Default is 60000 (1 min). -* `max_latency`?: _number_ – Maximum value for the endpoint's blockchain data syncronization latency (time-lag). Library periodically checks the current endpoint for blockchain data synchronization latency. If the latency (time-lag) is less then `NetworkConfig.max_latency` then library selects another endpoint.\ - Must be specified in milliseconds. Default is 60000 (1 min). -* `query_timeout`?: _number_ – Default timeout for http requests.\ - Is is used when no timeout specified for the request to limit the answer waiting time. If no answer received during the timeout requests ends with\ - error.\ - \ - Must be specified in milliseconds. Default is 60000 (1 min). -* `queries_protocol`?: [_NetworkQueriesProtocol_](mod\_client.md#networkqueriesprotocol) – Queries protocol.\ - `HTTP` or `WS`.\ - Default is `HTTP`. -* `first_remp_status_timeout`?: _number_ – UNSTABLE.\ - First REMP status awaiting timeout. If no status recieved during the timeout than fallback transaction scenario is activated.\ - \ - Must be specified in milliseconds. Default is 1000 (1 sec). -* `next_remp_status_timeout`?: _number_ – UNSTABLE.\ - Subsequent REMP status awaiting timeout. If no status recieved during the timeout than fallback transaction scenario is activated.\ - \ - Must be specified in milliseconds. Default is 5000 (5 sec). -* `access_key`?: _string_ – Access key to GraphQL API.\ - You can specify here Basic Auth secret (Evercloud project secret) in hex string\ - or serialized JWT in base64 string.\ - Will be passed on as Authorization: Basic ... or Authorization: Bearer ... header. - -### NetworkQueriesProtocol - +- `server_address`?: _string_ – **This field is deprecated, but left for backward-compatibility.** Evernode endpoint. +- `endpoints`?: _string[]_ – List of Evernode endpoints. +
Any correct URL format can be specified, including IP addresses. This parameter is prevailing over `server_address`.
Check the full list of [supported network endpoints](https://docs.everos.dev/ever-sdk/reference/ever-os-api/networks). +- `network_retries_count`?: _number_ – Deprecated. +
You must use `network.max_reconnect_timeout` that allows to specify maximum network resolving timeout. +- `max_reconnect_timeout`?: _number_ – Maximum time for sequential reconnections. +
Must be specified in milliseconds. Default is 120000 (2 min). +- `reconnect_timeout`?: _number_ – Deprecated +- `message_retries_count`?: _number_ – The number of automatic message processing retries that SDK performs in case of `Message Expired (507)` error - but only for those messages which local emulation was successful or failed with replay protection error. +
Default is 5. +- `message_processing_timeout`?: _number_ – Timeout that is used to process message delivery for the contracts which ABI does not include "expire" header. If the message is not delivered within the specified timeout the appropriate error occurs. +
Must be specified in milliseconds. Default is 40000 (40 sec). +- `wait_for_timeout`?: _number_ – Maximum timeout that is used for query response. +
Must be specified in milliseconds. Default is 40000 (40 sec). +- `out_of_sync_threshold`?: _number_ – Maximum time difference between server and client. +
If client's device time is out of sync and difference is more than the threshold then error will occur. Also an error will occur if the specified threshold is more than
`message_processing_timeout/2`.

Must be specified in milliseconds. Default is 15000 (15 sec). +- `sending_endpoint_count`?: _number_ – Maximum number of randomly chosen endpoints the library uses to broadcast a message. +
Default is 1. +- `latency_detection_interval`?: _number_ – Frequency of sync latency detection. +
Library periodically checks the current endpoint for blockchain data syncronization latency.
If the latency (time-lag) is less then `NetworkConfig.max_latency`
then library selects another endpoint.

Must be specified in milliseconds. Default is 60000 (1 min). +- `max_latency`?: _number_ – Maximum value for the endpoint's blockchain data syncronization latency (time-lag). Library periodically checks the current endpoint for blockchain data synchronization latency. If the latency (time-lag) is less then `NetworkConfig.max_latency` then library selects another endpoint. +
Must be specified in milliseconds. Default is 60000 (1 min). +- `query_timeout`?: _number_ – Default timeout for http requests. +
Is is used when no timeout specified for the request to limit the answer waiting time. If no answer received during the timeout requests ends with
error.

Must be specified in milliseconds. Default is 60000 (1 min). +- `queries_protocol`?: _[NetworkQueriesProtocol](mod\_client.md#networkqueriesprotocol)_ – Queries protocol. +
`HTTP` or `WS`.
Default is `HTTP`. +- `first_remp_status_timeout`?: _number_ – UNSTABLE. +
First REMP status awaiting timeout. If no status recieved during the timeout than fallback transaction scenario is activated.

Must be specified in milliseconds. Default is 1000 (1 sec). +- `next_remp_status_timeout`?: _number_ – UNSTABLE. +
Subsequent REMP status awaiting timeout. If no status recieved during the timeout than fallback transaction scenario is activated.

Must be specified in milliseconds. Default is 5000 (5 sec). +- `access_key`?: _string_ – Access key to GraphQL API (Project secret) + + +## NetworkQueriesProtocol Network protocol used to perform GraphQL queries. ```ts @@ -353,14 +332,13 @@ enum NetworkQueriesProtocol { WS = "WS" } ``` - One of the following value: -* `HTTP = "HTTP"` – Each GraphQL query uses separate HTTP request. -* `WS = "WS"` – All GraphQL queries will be served using single web socket connection. +- `HTTP = "HTTP"` – Each GraphQL query uses separate HTTP request. +- `WS = "WS"` – All GraphQL queries will be served using single web socket connection. -### CryptoConfig +## CryptoConfig Crypto config. ```ts @@ -370,13 +348,12 @@ type CryptoConfig = { hdkey_derivation_path?: string } ``` +- `mnemonic_dictionary`?: _number_ – Mnemonic dictionary that will be used by default in crypto functions. If not specified, 1 dictionary will be used. +- `mnemonic_word_count`?: _number_ – Mnemonic word count that will be used by default in crypto functions. If not specified the default value will be 12. +- `hdkey_derivation_path`?: _string_ – Derivation path that will be used by default in crypto functions. If not specified `m/44'/396'/0'/0/0` will be used. -* `mnemonic_dictionary`?: _number_ – Mnemonic dictionary that will be used by default in crypto functions. If not specified, 1 dictionary will be used. -* `mnemonic_word_count`?: _number_ – Mnemonic word count that will be used by default in crypto functions. If not specified the default value will be 12. -* `hdkey_derivation_path`?: _string_ – Derivation path that will be used by default in crypto functions. If not specified `m/44'/396'/0'/0/0` will be used. - -### AbiConfig +## AbiConfig ```ts type AbiConfig = { workchain?: number, @@ -384,64 +361,56 @@ type AbiConfig = { message_expiration_timeout_grow_factor?: number } ``` +- `workchain`?: _number_ – Workchain id that is used by default in DeploySet +- `message_expiration_timeout`?: _number_ – Message lifetime for contracts which ABI includes "expire" header. The default value is 40 sec. +- `message_expiration_timeout_grow_factor`?: _number_ – Factor that increases the expiration timeout for each retry The default value is 1.5 -* `workchain`?: _number_ – Workchain id that is used by default in DeploySet -* `message_expiration_timeout`?: _number_ – Message lifetime for contracts which ABI includes "expire" header. The default value is 40 sec. -* `message_expiration_timeout_grow_factor`?: _number_ – Factor that increases the expiration timeout for each retry The default value is 1.5 - -### BocConfig +## BocConfig ```ts type BocConfig = { cache_max_size?: number } ``` +- `cache_max_size`?: _number_ – Maximum BOC cache size in kilobytes. +
Default is 10 MB -* `cache_max_size`?: _number_ – Maximum BOC cache size in kilobytes.\ - Default is 10 MB - -### ProofsConfig +## ProofsConfig ```ts type ProofsConfig = { cache_in_local_storage?: boolean } ``` +- `cache_in_local_storage`?: _boolean_ – Cache proofs in the local storage. +
Default is `true`. If this value is set to `true`, downloaded proofs and master-chain BOCs are saved into the
persistent local storage (e.g. file system for native environments or browser's IndexedDB
for the web); otherwise all the data is cached only in memory in current client's context
and will be lost after destruction of the client. -* `cache_in_local_storage`?: _boolean_ – Cache proofs in the local storage.\ - Default is `true`. If this value is set to `true`, downloaded proofs and master-chain BOCs are saved into the\ - persistent local storage (e.g. file system for native environments or browser's IndexedDB\ - for the web); otherwise all the data is cached only in memory in current client's context\ - and will be lost after destruction of the client. - -### BuildInfoDependency +## BuildInfoDependency ```ts type BuildInfoDependency = { name: string, git_commit: string } ``` +- `name`: _string_ – Dependency name. +
Usually it is a crate name. +- `git_commit`: _string_ – Git commit hash of the related repository. -* `name`: _string_ – Dependency name.\ - Usually it is a crate name. -* `git_commit`: _string_ – Git commit hash of the related repository. - -### ParamsOfAppRequest +## ParamsOfAppRequest ```ts type ParamsOfAppRequest = { app_request_id: number, request_data: any } ``` +- `app_request_id`: _number_ – Request ID. +
Should be used in `resolve_app_request` call +- `request_data`: _any_ – Request describing data -* `app_request_id`: _number_ – Request ID.\ - Should be used in `resolve_app_request` call -* `request_data`: _any_ – Request describing data - -### AppRequestResultErrorVariant +## AppRequestResultErrorVariant Error occurred during request processing ```ts @@ -449,11 +418,10 @@ type AppRequestResultErrorVariant = { text: string } ``` +- `text`: _string_ – Error description -* `text`: _string_ – Error description - -### AppRequestResultOkVariant +## AppRequestResultOkVariant Request processed successfully ```ts @@ -461,11 +429,10 @@ type AppRequestResultOkVariant = { result: any } ``` +- `result`: _any_ – Request processing result -* `result`: _any_ – Request processing result - -### AppRequestResult +## AppRequestResult ```ts type AppRequestResult = ({ type: 'Error' @@ -473,20 +440,20 @@ type AppRequestResult = ({ type: 'Ok' } & AppRequestResultOkVariant) ``` - -Depends on value of the `type` field. +Depends on value of the `type` field. When _type_ is _'Error'_ Error occurred during request processing -* `text`: _string_ – Error description +- `text`: _string_ – Error description When _type_ is _'Ok'_ Request processed successfully -* `result`: _any_ – Request processing result +- `result`: _any_ – Request processing result + Variant constructors: @@ -495,46 +462,43 @@ function appRequestResultError(text: string): AppRequestResult; function appRequestResultOk(result: any): AppRequestResult; ``` -### ResultOfGetApiReference - +## ResultOfGetApiReference ```ts type ResultOfGetApiReference = { api: any } ``` +- `api`: _API_ -* `api`: _API_ - -### ResultOfVersion +## ResultOfVersion ```ts type ResultOfVersion = { version: string } ``` +- `version`: _string_ – Core Library version -* `version`: _string_ – Core Library version - -### ResultOfBuildInfo +## ResultOfBuildInfo ```ts type ResultOfBuildInfo = { build_number: number, dependencies: BuildInfoDependency[] } ``` +- `build_number`: _number_ – Build number assigned to this build by the CI. +- `dependencies`: _[BuildInfoDependency](mod\_client.md#buildinfodependency)[]_ – Fingerprint of the most important dependencies. -* `build_number`: _number_ – Build number assigned to this build by the CI. -* `dependencies`: [_BuildInfoDependency_](mod\_client.md#buildinfodependency)_\[]_ – Fingerprint of the most important dependencies. - -### ParamsOfResolveAppRequest +## ParamsOfResolveAppRequest ```ts type ParamsOfResolveAppRequest = { app_request_id: number, result: AppRequestResult } ``` +- `app_request_id`: _number_ – Request ID received from SDK +- `result`: _[AppRequestResult](mod\_client.md#apprequestresult)_ – Result of request processing + -* `app_request_id`: _number_ – Request ID received from SDK -* `result`: [_AppRequestResult_](mod\_client.md#apprequestresult) – Result of request processing diff --git a/docs/reference/types-and-methods/mod_net.md b/docs/reference/types-and-methods/mod_net.md index 6b621a5f4..bbc62785b 100644 --- a/docs/reference/types-and-methods/mod_net.md +++ b/docs/reference/types-and-methods/mod_net.md @@ -980,7 +980,8 @@ enum NetErrorCode { NotSupported = 611, NoEndpointsProvided = 612, GraphqlWebsocketInitError = 613, - NetworkModuleResumed = 614 + NetworkModuleResumed = 614, + Unauthorized = 615 } ``` One of the following value: @@ -999,6 +1000,7 @@ One of the following value: - `NoEndpointsProvided = 612` - `GraphqlWebsocketInitError = 613` - `NetworkModuleResumed = 614` +- `Unauthorized = 615` ## OrderBy diff --git a/ton_client/Cargo.toml b/ton_client/Cargo.toml index a7ed2a6c2..b473106fa 100644 --- a/ton_client/Cargo.toml +++ b/ton_client/Cargo.toml @@ -1,6 +1,6 @@ [package] name = 'ton_client' -version = '1.37.2' +version = '1.38.0' authors = [ 'TON Labs LTD ' ] edition = '2018' license = 'Apache-2.0' @@ -22,7 +22,7 @@ ton_sdk = { default-features = false, path = '../ton_sdk' } ton_abi = { git = 'https://github.com/tonlabs/ton-labs-abi.git', tag = '2.3.7' } ton_block = { git = 'https://github.com/tonlabs/ton-labs-block.git', tag = '1.8.3' } -ton_block_json = { git = 'https://github.com/tonlabs/ton-labs-block-json.git', tag = '0.7.31' } +ton_block_json = { git = 'https://github.com/tonlabs/ton-labs-block-json.git', tag = '0.7.33' } ton_executor = { default-features = false, git = 'https://github.com/tonlabs/ton-labs-executor.git', tag = '1.15.89' } ton_types = { git = 'https://github.com/tonlabs/ton-labs-types.git', tag = '1.11.4' } ton_vm = { default-features = false, git = 'https://github.com/tonlabs/ton-labs-vm.git', tag = '1.8.44' } @@ -71,7 +71,7 @@ zeroize = { features = [ 'zeroize_derive' ], version = '1.3' } zstd = { default-features = false, optional = true, version = '0.11.0' } # optional for std -reqwest = { optional = true, version = '0.11.11' } +reqwest = { optional = true, version = '0.11.11', features = ["cookies"] } tokio-tungstenite = { features = [ 'native-tls' ], optional = true, version = '0.17.1' } # optional for wasm diff --git a/ton_client/src/client/network_mock.rs b/ton_client/src/client/network_mock.rs index 6dc989443..0ceae34a7 100644 --- a/ton_client/src/client/network_mock.rs +++ b/ton_client/src/client/network_mock.rs @@ -181,6 +181,17 @@ impl NetworkMock { .map(|x| x.len()) .unwrap_or(0) } + + #[cfg(not(feature = "wasm-base"))] + #[cfg(test)] + pub async fn assert_is_empty(client: &ClientContext) { + let mock = client.env.network_mock.read().await; + if let Some(fetches) = &mock.fetches { + if !fetches.is_empty() { + panic!("Mock fetches is not empty: {:?}", fetches); + } + } + } } pub(crate) struct NetworkMockBuilder { @@ -294,39 +305,20 @@ impl NetworkMockBuilder { network_mock.messages = Some(self.messages.clone()); } - pub fn schema(&mut self, time: u64) -> &mut Self { - self.ok(&json!({ - "data": { - "info": { - "version": "0.39.0", - "time": time, - } - } - }) - .to_string()) - } - - pub fn metrics(&mut self, time: u64, latency: u64) -> &mut Self { + pub fn info(&mut self, time: u64, latency: u64) -> &mut Self { self.ok(&json!({ "data": { "info": { - "version": "0.39.0", + "version": "0.54.0", "time": time, "latency": latency, + "rempEnabled": false, } } }) .to_string()) } - pub fn election(&mut self, time: u64, latency: u64) -> &mut Self { - self.schema(time).metrics(time, latency) - } - - pub fn election_loose(&mut self, time: u64) -> &mut Self { - self.schema(time) - } - pub fn blocks(&mut self, id: &str) -> &mut Self { self.ok(&json!({ "data": { diff --git a/ton_client/src/client/std_client_env.rs b/ton_client/src/client/std_client_env.rs index 1bb8a113c..e2f3c364e 100644 --- a/ton_client/src/client/std_client_env.rs +++ b/ton_client/src/client/std_client_env.rs @@ -12,10 +12,10 @@ */ use super::{Error, FetchMethod, FetchResult, WebSocket}; -use crate::client::{LOCAL_STORAGE_DEFAULT_DIR_NAME}; #[cfg(test)] use crate::client::network_mock::NetworkMock; use crate::client::storage::KeyValueStorage; +use crate::client::LOCAL_STORAGE_DEFAULT_DIR_NAME; use crate::error::ClientResult; use futures::{Future, SinkExt, StreamExt}; use lazy_static::lazy_static; @@ -27,6 +27,7 @@ use std::collections::HashMap; use std::convert::TryFrom; use std::path::PathBuf; use std::str::FromStr; +use std::sync::Arc; use tokio::runtime::Runtime; #[cfg(test)] use tokio::sync::RwLock; @@ -49,6 +50,7 @@ fn create_runtime() -> ClientResult { } pub(crate) struct ClientEnv { + cookies: Arc, http_client: HttpClient, async_runtime_handle: tokio::runtime::Handle, #[cfg(test)] @@ -57,7 +59,9 @@ pub(crate) struct ClientEnv { impl ClientEnv { pub fn new() -> ClientResult { + let cookies = Arc::new(reqwest::cookie::Jar::default()); let client = ClientBuilder::new() + .cookie_provider(cookies.clone()) .build() .map_err(|err| Error::http_client_create_error(err))?; @@ -71,6 +75,7 @@ impl ClientEnv { }; Ok(Self { + cookies, http_client: client, async_runtime_handle, #[cfg(test)] @@ -144,8 +149,9 @@ impl ClientEnv { return Ok(ws); } } - let mut request = tokio_tungstenite::tungstenite::client::IntoClientRequest::into_client_request(url) - .map_err(|err| Error::websocket_connect_error(url, err))?; + let mut request = + tokio_tungstenite::tungstenite::client::IntoClientRequest::into_client_request(url) + .map_err(|err| Error::websocket_connect_error(url, err))?; if let Some(headers) = headers { for (key, value) in headers { @@ -155,6 +161,14 @@ impl ClientEnv { .map_err(|err| Error::websocket_connect_error(url, err))?; request.headers_mut().insert(key, value); } + if let Ok(url) = reqwest::Url::parse(url) { + if let Some(cookies) = self.cookies.cookies(&url) { + request.headers_mut().insert( + tokio_tungstenite::tungstenite::http::header::COOKIE, + cookies, + ); + } + } } let (client, _) = tokio_tungstenite::connect_async(request) @@ -202,7 +216,8 @@ impl ClientEnv { let method = Method::from_str(method.as_str()) .map_err(|err| Error::http_request_create_error(err))?; - let mut request = self.http_client + let mut request = self + .http_client .request(method, url) .timeout(std::time::Duration::from_millis(timeout_ms as u64)); @@ -245,7 +260,8 @@ impl LocalStorage { local_storage_path: Option, storage_name: String, ) -> ClientResult { - tokio::fs::create_dir_all(Self::calc_storage_path(&local_storage_path, &storage_name)).await + tokio::fs::create_dir_all(Self::calc_storage_path(&local_storage_path, &storage_name)) + .await .map_err(|err| Error::local_storage_error(err))?; Ok(Self { @@ -254,10 +270,7 @@ impl LocalStorage { }) } - fn calc_storage_path( - local_storage_path: &Option, - storage_name: &str, - ) -> PathBuf { + fn calc_storage_path(local_storage_path: &Option, storage_name: &str) -> PathBuf { let local_storage_path = local_storage_path .clone() .map(|path| PathBuf::from(path)) @@ -267,8 +280,7 @@ impl LocalStorage { .join(LOCAL_STORAGE_DEFAULT_DIR_NAME) }); - local_storage_path - .join(storage_name) + local_storage_path.join(storage_name) } pub fn is_storage_key_correct(key: &str) -> bool { @@ -280,10 +292,7 @@ impl LocalStorage { return Err(Error::invalid_storage_key(key)); } - Ok( - Self::calc_storage_path(&self.local_storage_path, &self.storage_name) - .join(key) - ) + Ok(Self::calc_storage_path(&self.local_storage_path, &self.storage_name).join(key)) } } @@ -295,10 +304,12 @@ impl KeyValueStorage for LocalStorage { match tokio::fs::read(&path).await { Ok(value) => Ok(Some(value)), - Err(err) => if err.kind() == std::io::ErrorKind::NotFound { - Ok(None) - } else { - Err(Error::local_storage_error(err)) + Err(err) => { + if err.kind() == std::io::ErrorKind::NotFound { + Ok(None) + } else { + Err(Error::local_storage_error(err)) + } } } } @@ -307,13 +318,15 @@ impl KeyValueStorage for LocalStorage { async fn put_bin(&self, key: &str, value: &[u8]) -> ClientResult<()> { let path = self.key_to_path(key)?; - tokio::fs::write(&path, value).await + tokio::fs::write(&path, value) + .await .map_err(|err| Error::local_storage_error(err)) } /// Get string value by a given key from the storage async fn get_str(&self, key: &str) -> ClientResult> { - self.get_bin(key).await + self.get_bin(key) + .await .map(|opt| opt.map(|vec| String::from_utf8(vec)))? .transpose() .map_err(|err| Error::local_storage_error(err)) @@ -329,7 +342,8 @@ impl KeyValueStorage for LocalStorage { async fn remove(&self, key: &str) -> ClientResult<()> { let path = self.key_to_path(key)?; - tokio::fs::remove_file(&path).await + tokio::fs::remove_file(&path) + .await .map_err(|err| Error::local_storage_error(err)) } } diff --git a/ton_client/src/crypto/tests.rs b/ton_client/src/crypto/tests.rs index 8ede4d493..673ea5494 100644 --- a/ton_client/src/crypto/tests.rs +++ b/ton_client/src/crypto/tests.rs @@ -1653,6 +1653,6 @@ async fn test_crypto_box_derive_key_cache() -> ton_types::Result<()> { .await?; } let time2 = client.context().env.now_ms() - start2; - assert!(time1 * 3 < time2); + assert!(time1 * 2 < time2); Ok(()) } diff --git a/ton_client/src/debot/calltype.rs b/ton_client/src/debot/calltype.rs index b88898256..53645789a 100644 --- a/ton_client/src/debot/calltype.rs +++ b/ton_client/src/debot/calltype.rs @@ -15,11 +15,12 @@ use crate::tvm::{run_executor, run_tvm, AccountForExecutor, ParamsOfRunExecutor, use std::convert::TryFrom; use std::fmt::Display; use std::sync::Arc; -use ton_block::{Message, MsgAddressExt, MsgAddressInt}; +use ton_block::{Message, MsgAddressExt, MsgAddressInt, 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; pub(super) enum DebotCallType { Interface { msg: String, id: String }, @@ -36,10 +37,14 @@ fn msg_err(e: impl Display) -> ClientError { struct Metadata { answer_id: u32, onerror_id: u32, + abi_ver: u8, is_timestamp: bool, is_expire: bool, is_pubkey: bool, signing_box_handle: Option, + override_ts: bool, + override_exp: bool, + async_call: bool, } impl TryFrom for Metadata { @@ -54,30 +59,37 @@ impl TryFrom for Metadata { let mut slice = extern_addr.external_address; let answer_id = slice.get_next_u32().map_err(msg_err)?; let onerror_id = slice.get_next_u32().map_err(msg_err)?; - let abi_version = slice.get_next_byte().map_err(msg_err)?; - if abi_version != SUPPORTED_ABI_VERSION { + let abi_ver = slice.get_next_byte().map_err(msg_err)?; + if (abi_ver & 0x0F) != SUPPORTED_ABI_VERSION { return Err(msg_err(format!( - "unsupported ABI version in src address (must be {})", + "unsupported major ABI version in src address (must be {})", SUPPORTED_ABI_VERSION ))); } 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 is_sign_box_handle = slice.get_next_bit().unwrap_or(false); - let signing_box_handle = if is_sign_box_handle { - Some(SigningBoxHandle(slice.get_next_u32().map_err(msg_err)?)) - } else { - None + 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, }; + let ctrl_flags = slice.get_next_byte().unwrap_or_default(); + let override_ts = (ctrl_flags & 1) != 0; + let override_exp = (ctrl_flags & 2) != 0; + let async_call = (ctrl_flags & 4) != 0; Ok(Self { answer_id, onerror_id, + abi_ver, is_timestamp, is_expire, is_pubkey, signing_box_handle, + override_ts, + override_exp, + async_call, }) } } @@ -145,20 +157,32 @@ async fn decode_and_fix_ext_msg( in_body_slice.get_next_bits(256).map_err(msg_err)?; } } - if meta.is_timestamp { - // skip `timestamp` header - in_body_slice.get_next_u64().map_err(msg_err)?; - } - if meta.is_expire { - // skip `expire` header - in_body_slice.get_next_u32().map_err(msg_err)?; - } + let msg_ts = match meta.is_timestamp { + // 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}) + }, + 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 + } 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 if they are present, - // then sign body with signing box - + // 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 { @@ -172,12 +196,11 @@ async fn decode_and_fix_ext_msg( new_body.append_bit_zero().map_err(msg_err)?; } } - let expired_at = ((now_ms / 1000) as u32) + ton.config.abi.message_expiration_timeout; - if meta.is_timestamp { - new_body.append_u64(now_ms).map_err(msg_err)?; + if let Some(msg_ts) = msg_ts { + new_body.append_u64(msg_ts).map_err(msg_err)?; } - if meta.is_expire { - new_body.append_u32(expired_at).map_err(msg_err)?; + if let Some(msg_exp) = msg_exp { + new_body.append_u32(msg_exp).map_err(msg_err)?; } new_body .append_u32(func_id) @@ -187,7 +210,14 @@ async fn decode_and_fix_ext_msg( let mut signed_body = BuilderData::new(); match signer { Signer::SigningBox { handle: _ } => { - let hash = new_body.clone().into_cell().map_err(msg_err)?.repr_hash().as_slice().to_vec(); + 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)?; + 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 signature = signer.sign(ton.clone(), &hash).await?; if let Some(signature) = signature { signed_body @@ -262,6 +292,7 @@ impl ContractCall { if self.local_run { self.run_get_method(func_id, fixed_msg).await } else { + let wait_tx = !self.meta.async_call && wait_tx; self.send_ext_msg(func_id, fixed_msg, wait_tx).await } } @@ -316,7 +347,6 @@ impl ContractCall { return self.build_error_answer_msg(e); }, } - let browser = self.browser.clone(); let callback = move |event| { debug!("{:?}", event); @@ -347,7 +377,6 @@ impl ContractCall { .await .map(|e| { error!("{:?}", e); e })?; let msg_id = get_boc_hash(self.ton.clone(), ParamsOfGetBocHash { boc: fixed_msg.clone() }).await?.hash; - if wait_tx { let result = wait_for_transaction( self.ton.clone(), @@ -410,7 +439,14 @@ impl ContractCall { async fn decode_and_fix_ext_msg(&self) -> ClientResult<(u32, String)> { let now_ms = self.ton.env.now_ms(); - let result: (u32, Message) = decode_and_fix_ext_msg(&self.msg, now_ms, &self.signer, false, &self.meta, &self.ton).await?; + let result: (u32, Message) = decode_and_fix_ext_msg( + &self.msg, + now_ms, + &self.signer, + false, + &self.meta, + &self.ton, + ).await?; let (func_id, message) = result; let msg = serialize_object_to_base64(&message, "message").map_err(|e| Error::invalid_msg(e))?; Ok((func_id, msg)) diff --git a/ton_client/src/debot/msg_interface.rs b/ton_client/src/debot/msg_interface.rs index 1cff1d4f4..60310ad21 100644 --- a/ton_client/src/debot/msg_interface.rs +++ b/ton_client/src/debot/msg_interface.rs @@ -160,6 +160,7 @@ impl MsgInterface { .get_input_id(); Ok((answer_id, result.value.unwrap_or_default())) } + } #[async_trait::async_trait] diff --git a/ton_client/src/debot/tests.rs b/ton_client/src/debot/tests.rs index 686e23d09..14af1f40a 100644 --- a/ton_client/src/debot/tests.rs +++ b/ton_client/src/debot/tests.rs @@ -11,7 +11,7 @@ * limitations under the License. */ -use crate::abi::{CallSet, DeploySet, ParamsOfEncodeMessage, Signer, Abi, +use crate::abi::{CallSet, DeploySet, FunctionHeader, ParamsOfEncodeMessage, Signer, Abi, ParamsOfDecodeMessageBody, DecodedMessageBody, ResultOfEncodeInternalMessage, ParamsOfEncodeInternalMessage}; use crate::boc::{ParamsOfParse, ResultOfParse, ParamsOfGetCodeFromTvc, ResultOfGetCodeFromTvc, ResultOfGetBocHash, ParamsOfGetBocHash}; @@ -376,7 +376,11 @@ impl TestBrowser { } else if SUPPORTED_INTERFACES[1] == interface_id { Abi::Json(TERMINAL_ABI.to_owned()) } else if SUPPORTED_INTERFACES[2] == interface_id { - Abi::Json(SIGNING_BOX_ABI.to_owned()) + if state.info.dabi_version == "2.2" { + Abi::Json(SIGNING_BOX_ABI_2_2.to_owned()) + } else { + Abi::Json(SIGNING_BOX_ABI.to_owned()) + } } else if SUPPORTED_INTERFACES[3] == interface_id { Abi::Json(ENCRYPTION_BOX_ABI.to_owned()) } else { @@ -1421,6 +1425,66 @@ async fn test_debot_json_parse() { .await; } +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] +async fn test_debot_custom_header() { + let client = std::sync::Arc::new(TestClient::new()); + //deply CustomReplayProtection contract + let keys = client.generate_sign_keys(); + let abi = TestClient::abi("CustomReplayProtection", Some(2)); + let call_set = Some(CallSet { + function_name: "constructor".into(), + input: None, + header: Some(FunctionHeader { + expire: None, + time: Some(1), + pubkey: None, + }), + }); + let deploy_params = ParamsOfEncodeMessage { + abi: abi.clone(), + deploy_set: DeploySet::some_with_tvc(TestClient::tvc("CustomReplayProtection", Some(2))), + signer: Signer::Keys { keys: keys.clone() }, + processing_try_index: None, + address: None, + call_set, + }; + let replay_contract = client.deploy_with_giver_async(deploy_params, Some(1_000_000_000u64)).await; + //deploy debot + let DebotData { + debot_addr, + target_addr: _, + keys, + abi, + } = init_simple_debot(client.clone(), "testDebot20").await; + let info = build_info_abi2_2( + abi, + 20, + vec![ + format!("0xc13024e101c95e71afb1f5fa6d72f633d51e721de0320d73dfd6121a54e4d40a"), + format!("0x8796536366ee21852db56dccb60bc564598b618c865fc50c8b1ab740bba128e3"), + ]); + //set address of CustomReplayProtection to DeBot + let debot_abi = TestClient::abi("testDebot20", Some(2)); + let _ = client.net_process_function( + debot_addr.clone(), + debot_abi.clone(), + "setRollingId", + json!({ "a":replay_contract }), + Signer::Keys { keys: keys.clone() }, + ).await.unwrap(); + //run DeBot + TestBrowser::execute_with_details( + client.clone(), + debot_addr.clone(), + keys, + vec![], + vec![], + info, + vec![], + ) + .await; +} + #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn test_debot_target_abi() { let client = std::sync::Arc::new(TestClient::new()); @@ -1513,6 +1577,24 @@ fn build_info(abi: String, n: u32, interfaces: Vec) -> DebotInfo { } } +fn build_info_abi2_2(abi: String, n: u32, interfaces: Vec) -> DebotInfo { + let name = format!("TestDeBot{}", n); + DebotInfo { + name: Some(name.clone()), + version: Some("0.1.0".to_owned()), + publisher: Some("EverX".to_owned()), + caption: Some(name.clone()), + author: Some("EverX".to_owned()), + support: Some("0:0000000000000000000000000000000000000000000000000000000000000000".to_owned()), + hello: Some(name.clone()), + language: Some("en".to_owned()), + dabi: Some(abi), + icon: Some(format!("")), + interfaces, + dabi_version: format!("2.2"), + } +} + async fn download_account(client: &Arc, addr: &str) -> Option { let client = client.clone(); let accounts: ResultOfQueryCollection = client.request_async( diff --git a/ton_client/src/debot/tests_interfaces.rs b/ton_client/src/debot/tests_interfaces.rs index 7204adc74..88433ff3f 100644 --- a/ton_client/src/debot/tests_interfaces.rs +++ b/ton_client/src/debot/tests_interfaces.rs @@ -118,6 +118,43 @@ pub const SIGNING_BOX_ABI: &str = r#" } "#; +pub const SIGNING_BOX_ABI_2_2: &str = r#" +{ + "ABI version": 2, + "version": "2.2", + "header": ["time"], + "functions": [ + { + "name": "get", + "inputs": [ + {"name":"answerId","type":"uint32"}, + {"name":"prompt","type":"string"}, + {"name":"possiblePublicKeys","type":"uint256[]"} + ], + "outputs": [ + {"name":"handle","type":"uint32"} + ] + }, + { + "name": "constructor", + "inputs": [ + ], + "outputs": [ + ] + } + ], + "data": [ + ], + "events": [ + ], + "fields": [ + {"name":"_pubkey","type":"uint256"}, + {"name":"_timestamp","type":"uint64"}, + {"name":"_constructorFlag","type":"bool"} + ] +} +"#; + pub const ENCRYPTION_BOX_ABI: &str = r#"{ "ABI version": 2, diff --git a/ton_client/src/net/endpoint.rs b/ton_client/src/net/endpoint.rs index 186babdab..c9f8d0b2a 100644 --- a/ton_client/src/net/endpoint.rs +++ b/ton_client/src/net/endpoint.rs @@ -19,10 +19,6 @@ use serde_json::Value; use std::collections::HashMap; use std::sync::atomic::{AtomicBool, AtomicI64, AtomicU32, AtomicU64, Ordering}; -pub const V_0_39_0: u32 = 39000; -pub const V_SUPPORTS_LATENCY: u32 = V_0_39_0; -pub const V_0_51_0: u32 = 51000; -pub const V_SUPPORTS_REMP: u32 = V_0_51_0; pub const BOC_VERSION: &str = "2"; pub(crate) struct Endpoint { @@ -53,10 +49,7 @@ impl Clone for Endpoint { } } -const QUERY_INFO_VERSION_TIME: &str = "?query=%7Binfo%7Bversion%20time%7D%7D"; -const QUERY_INFO_VERSION_TIME_LATENCY: &str = "?query=%7Binfo%7Bversion%20time%20latency%7D%7D"; -const QUERY_INFO_VERSION_TIME_LATENCY_REMP: &str = - "?query=%7Binfo%7Bversion%20time%20latency%20rempEnabled%7D%7D"; +const QUERY_INFO: &str = "?query=%7Binfo%7Bversion%20time%20latency%20rempEnabled%7D%7D"; const HTTP_PROTOCOL: &str = "http://"; const HTTPS_PROTOCOL: &str = "https://"; @@ -116,7 +109,7 @@ impl Endpoint { ) .await?; if response.status == 401 { - return Err(Error::unauthorized()); + return Err(Error::unauthorized(&response)); } let query_url = response.url.trim_end_matches(query).to_owned(); let info = response.body_as_json()?["data"]["info"].to_owned(); @@ -133,7 +126,7 @@ impl Endpoint { let (info, query_url, ip_address) = Self::fetch_info_with_url( client_env, &address, - QUERY_INFO_VERSION_TIME, + QUERY_INFO, config.query_timeout, config, ) @@ -152,7 +145,6 @@ impl Endpoint { remp_enabled: AtomicBool::default(), }; endpoint.apply_server_info(client_env, config, info_request_time, &info)?; - endpoint.refresh(client_env, config).await?; Ok(endpoint) } @@ -161,23 +153,16 @@ impl Endpoint { client_env: &ClientEnv, config: &NetworkConfig, ) -> ClientResult<()> { - if self.version() >= V_SUPPORTS_LATENCY { - let query = if self.version() >= V_SUPPORTS_REMP { - QUERY_INFO_VERSION_TIME_LATENCY_REMP - } else { - QUERY_INFO_VERSION_TIME_LATENCY - }; - let info_request_time = client_env.now_ms(); - let (info, _, _) = Self::fetch_info_with_url( - client_env, - &self.query_url, - query, - config.query_timeout, - config, - ) - .await?; - self.apply_server_info(client_env, config, info_request_time, &info)?; - } + let info_request_time = client_env.now_ms(); + let (info, _, _) = Self::fetch_info_with_url( + client_env, + &self.query_url, + QUERY_INFO, + config.query_timeout, + config, + ) + .await?; + self.apply_server_info(client_env, config, info_request_time, &info)?; Ok(()) } @@ -230,10 +215,6 @@ impl Endpoint { self.server_latency.load(Ordering::Relaxed) } - pub fn version(&self) -> u32 { - self.server_version.load(Ordering::Relaxed) - } - pub fn time_delta(&self) -> i64 { self.server_time_delta.load(Ordering::Relaxed) } diff --git a/ton_client/src/net/errors.rs b/ton_client/src/net/errors.rs index 77c999e00..be8dae8a2 100644 --- a/ton_client/src/net/errors.rs +++ b/ton_client/src/net/errors.rs @@ -1,3 +1,4 @@ +use crate::client::FetchResult; use crate::error::{format_time, ClientError}; use serde_json::Value; use std::fmt::Display; @@ -28,8 +29,31 @@ fn error(code: ErrorCode, message: String) -> ClientError { } impl Error { - pub fn unauthorized() -> ClientError { - error(ErrorCode::Unauthorized, "Unauthorized".to_string()) + pub(crate) fn unauthorized(response: &FetchResult) -> ClientError { + let message = match serde_json::from_str(&response.body) { + Err(_) => response.body.clone(), + Ok(value) => match Self::try_extract_graphql_error(&value) { + Some(err) => err.message, + None => response.body.clone(), + }, + }; + error(ErrorCode::Unauthorized, message) + } + + pub fn try_extract_graphql_error(value: &Value) -> Option { + let errors = if let Some(payload) = value.get("payload") { + payload.get("errors") + } else { + value.get("errors") + }; + + if let Some(errors) = errors { + if let Some(errors) = errors.as_array() { + return Some(Self::graphql_server_error(None, errors)); + } + } + + return None; } pub fn queries_query_failed(err: E) -> ClientError { @@ -104,15 +128,15 @@ impl Error { pub fn graphql_server_error(operation: Option<&str>, errors: &[Value]) -> ClientError { let (message, code) = Self::try_get_message_and_code(errors); - let operation = operation.unwrap_or("server returned"); - let mut err = error( - ErrorCode::GraphqlError, - if let Some(message) = message { + let message = match (operation, message) { + (None, None) => "Graphql server returned error.".to_string(), + (None, Some(message)) => format!("Graphql server returned error: {}.", message), + (Some(operation), None) => format!("Graphql {} error.", operation), + (Some(operation), Some(message)) => { format!("Graphql {} error: {}.", operation, message) - } else { - format!("Graphql {} error.", operation) - }, - ); + } + }; + let mut err = error(ErrorCode::GraphqlError, message); if let Some(code) = code { err.data["server_code"] = code.into(); diff --git a/ton_client/src/net/server_link.rs b/ton_client/src/net/server_link.rs index cf8f3749a..d9f326de8 100644 --- a/ton_client/src/net/server_link.rs +++ b/ton_client/src/net/server_link.rs @@ -35,44 +35,6 @@ pub const MAX_TIMEOUT: u32 = i32::MAX as u32; pub const MIN_RESUME_TIMEOUT: u32 = 500; pub const MAX_RESUME_TIMEOUT: u32 = 3000; -struct EndpointsReplacement<'a> { - url: &'a str, - aliases: &'a [&'a str], -} - -const MAIN_ALIASES: [&str; 5] = [ - "eri01.main.everos.dev", - "gra01.main.everos.dev", - "gra02.main.everos.dev", - "lim01.main.everos.dev", - "rbx01.main.everos.dev", -]; - -const DEV_ALIASES: [&str; 3] = [ - "eri01.net.everos.dev", - "rbx01.net.everos.dev", - "gra01.net.everos.dev", -]; - -const ENDPOINTS_REPLACE: [EndpointsReplacement; 4] = [ - EndpointsReplacement { - url: "main.ton.dev", - aliases: &MAIN_ALIASES, - }, - EndpointsReplacement { - url: "net.ton.dev", - aliases: &DEV_ALIASES, - }, - EndpointsReplacement { - url: "main", - aliases: &MAIN_ALIASES, - }, - EndpointsReplacement { - url: "dev", - aliases: &DEV_ALIASES, - }, -]; - pub(crate) struct Subscription { pub unsubscribe: Pin + Send>>, pub data_stream: Pin> + Send>>, @@ -298,7 +260,7 @@ impl NetworkState { })); } let mut selected = Err(crate::client::Error::net_module_not_init()); - let mut unauthorised = true; + let mut unauthorised = None; while futures.len() != 0 { let (result, _, remain_futures) = futures::future::select_all(futures).await; if let Ok(endpoint) = &result { @@ -309,7 +271,7 @@ impl NetworkState { futures = remain_futures; if let Err(err) = &result { if !err.is_unauthorized() { - unauthorised = false; + unauthorised = Some(err.clone()); } } if is_better(&result, &selected) { @@ -319,8 +281,8 @@ impl NetworkState { if selected.is_ok() { return selected; } - if unauthorised { - return Err(Error::unauthorized()); + if let Some(unauthorised) = unauthorised { + return Err(unauthorised); } retry_count += 1; if retry_count > self.config.network_retries_count { @@ -373,28 +335,15 @@ fn strip_endpoint(endpoint: &str) -> &str { .trim_end_matches("\\") } -fn replace_endpoints(mut endpoints: Vec) -> Vec { - for entry in &ENDPOINTS_REPLACE { - let len = endpoints.len(); - endpoints.retain(|endpoint| strip_endpoint(&endpoint) != entry.url); - if len != endpoints.len() { - endpoints.extend_from_slice( - &entry - .aliases - .iter() - .map(|val| (*val).to_owned()) - .collect::>(), - ); - } - } +fn same_endpoint(a: &str, b: &str) -> bool { + strip_endpoint(a) == strip_endpoint(b) +} +fn replace_endpoints(endpoints: Vec) -> Vec { let mut result: Vec = vec![]; for endpoint in endpoints { - if !result - .iter() - .any(|val| strip_endpoint(val) == strip_endpoint(&endpoint)) - { + if !result.iter().any(|val| same_endpoint(val, &endpoint)) { result.push(endpoint); } } @@ -527,22 +476,6 @@ impl ServerLink { }) } - pub fn try_extract_error(value: &Value) -> Option { - let errors = if let Some(payload) = value.get("payload") { - payload.get("errors") - } else { - value.get("errors") - }; - - if let Some(errors) = errors { - if let Some(errors) = errors.as_array() { - return Some(Error::graphql_server_error(None, errors)); - } - } - - return None; - } - pub(crate) async fn query_http( &self, query: &GraphQLQuery, @@ -585,11 +518,11 @@ impl ServerLink { Err(err) => Err(err), Ok(response) => { if response.status == 401 { - Err(Error::unauthorized()) + Err(Error::unauthorized(&response)) } else { match response.body_as_json() { Err(err) => Err(err), - Ok(value) => match Self::try_extract_error(&value) { + Ok(value) => match Error::try_extract_graphql_error(&value) { Some(err) => Err(err), None => Ok(value), }, @@ -600,9 +533,17 @@ impl ServerLink { if let Err(err) = &result { if crate::client::Error::is_network_error(err) { - self.state.internal_suspend().await; - self.websocket_link.suspend().await; - self.websocket_link.resume().await; + let endpoint_count = self + .state + .get_all_endpoint_addresses() + .await + .map(|x| x.len()) + .unwrap_or(0); + if endpoint_count > 1 { + self.state.internal_suspend().await; + self.websocket_link.suspend().await; + self.websocket_link.resume().await; + } retry_count += 1; if retry_count <= network_retries_count { continue 'retries; @@ -655,20 +596,16 @@ impl ServerLink { params: &[ParamsOfQueryOperation], endpoint: Option, ) -> ClientResult> { - let (server_version, latency_detection_required) = if let Some(ref endpoint) = endpoint { - (endpoint.version(), false) + let latency_detection_required = if endpoint.is_some() { + false } else if self.state.has_multiple_endpoints() { let endpoint = self.state.get_query_endpoint().await?; - ( - endpoint.version(), - self.client_env.now_ms() > endpoint.next_latency_detection_time(), - ) + self.client_env.now_ms() > endpoint.next_latency_detection_time() } else { - (0, false) + false }; let mut query = GraphQLQuery::build( params, - server_version, latency_detection_required, self.config.wait_for_timeout, ); @@ -685,7 +622,7 @@ impl ServerLink { )?; if current_endpoint.latency() > self.config.max_latency as u64 { self.invalidate_querying_endpoint().await; - query = GraphQLQuery::build(params, 0, false, self.config.wait_for_timeout); + query = GraphQLQuery::build(params, false, self.config.wait_for_timeout); result = self.query(&query, endpoint.as_ref()).await?; } } diff --git a/ton_client/src/net/tests.rs b/ton_client/src/net/tests.rs index b3ab80507..dccca9709 100644 --- a/ton_client/src/net/tests.rs +++ b/ton_client/src/net/tests.rs @@ -15,21 +15,57 @@ use std::collections::HashSet; use std::sync::Arc; use std::vec; +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] +async fn not_authorized_response_text() { + // Query failed: Can not send http request: Server responded with code 401 + let client = TestClient::new_with_config(json!({ + "network": { + "endpoints": ["mainnet.evercloud.dev"] + } + })); + let context = client.context().clone(); + let link = context.net.server_link.as_ref().unwrap(); + let result = link + .query_http( + &GraphQLQuery { + query: "query { info { version } }".to_string(), + timeout: None, + variables: None, + is_batch: false, + }, + None, + ) + .await; + if let Err(err) = result { + println!("{}", err.message); + assert_ne!(err.message, "Unauthorized"); + assert_ne!(err.message, "Query failed: Can not send http request: Server responded with code 401"); + } else { + panic!("Error expected"); + } +} + #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn not_authorized() { let client = TestClient::new_with_config(json!({ "network": { - "endpoints": [TestClient::with_project("main")] + "endpoints": [TestClient::with_project("mainnet.evercloud.dev")] } })); let context = client.context().clone(); let link = context.net.server_link.as_ref().unwrap(); - let result = link.query_http(&GraphQLQuery { - query: "query { info { version } }".to_string(), - timeout: None, - variables: None, - is_batch: false, - }, None).await; + let result = link + .query_http( + &GraphQLQuery { + query: "query { info { version } }".to_string(), + timeout: None, + variables: None, + is_batch: false, + }, + None, + ) + .await + .unwrap(); println!("{:?}", result) } @@ -770,17 +806,13 @@ async fn retry_query_on_network_errors() { let now = client.env.now_ms(); NetworkMock::build() .url("a") - .election(now, 1000) - .repeat(2) + .info(now, 1000) .network_err() - .election(now, 1000) .blocks("1") .repeat(5) .network_err() - .election(now, 1000) .blocks("2") .status(502, "") - .election(now, 1000) .blocks("3") .ok(&json!({ "errors": [ @@ -809,7 +841,6 @@ async fn retry_query_on_network_errors() { } }) .to_string()) - .election(now, 1000) .blocks("4") .reset_client(&client) .await; @@ -839,10 +870,10 @@ async fn querying_endpoint_selection() { NetworkMock::build() .url("a") .delay(200) - .election(now, 500) // looser + .info(now, 500) // looser .url("b") .delay(100) - .election(now, 500) // winner + .info(now, 500) // winner .reset_client(&client) .await; assert_eq!(get_query_url(&client).await, "b"); @@ -852,10 +883,10 @@ async fn querying_endpoint_selection() { NetworkMock::build() .url("a") .delay(100) - .election(now, 1500) // looser + .info(now, 1500) // looser .url("b") .delay(200) - .election(now, 500) // winner + .info(now, 500) // winner .reset_client(&client) .await; assert_eq!(get_query_url(&client).await, "b"); @@ -865,10 +896,10 @@ async fn querying_endpoint_selection() { NetworkMock::build() .url("a") .delay(200) - .election(now, 1500) // winner (slower but better latency) + .info(now, 1500) // winner (slower but better latency) .url("b") .delay(100) - .election(now, 2000) // looser (faster but worse latency) + .info(now, 2000) // looser (faster but worse latency) .reset_client(&client) .await; assert_eq!(get_query_url(&client).await, "a"); @@ -932,10 +963,10 @@ async fn latency_detection_with_queries() { NetworkMock::build() .url("a") .delay(10) - .election(now, 500) // winner + .info(now, 500) // winner .url("b") .delay(20) - .election_loose(now) // looser + .info(now, 0) // looser .url("a") .delay(200) .blocks("1") // query @@ -948,17 +979,17 @@ async fn latency_detection_with_queries() { "version": "0.39.0", "time": 1000, "latency": 1000, + "rempEnabled": false, }, } }) .to_string()) // query with latency checking, returns bad latency - .metrics(1000, 900) .url("a") .delay(20) - .election_loose(now) // looser + .info(now, 0) // looser .url("b") .delay(10) - .election(now, 500) // winner + .info(now, 500) // winner .url("b") .blocks("2") // retry query .reset_client(&client) @@ -967,8 +998,8 @@ async fn latency_detection_with_queries() { assert_eq!(get_query_url(&client).await, "a"); assert_eq!(query_block_id(&client).await, "1"); assert_eq!(query_block_id(&client).await, "2"); - assert_eq!(NetworkMock::get_len(&client).await, 0); assert_eq!(get_query_url(&client).await, "b"); + NetworkMock::assert_is_empty(&client).await; } #[tokio::test(flavor = "multi_thread", worker_threads = 2)] @@ -992,10 +1023,10 @@ async fn latency_detection_with_websockets() { NetworkMock::build() .url("a") .delay(10) - .election(now, 500) // winner + .info(now, 500) // winner .url("b") .delay(20) - .election_loose(now) // looser + .info(now, 0) // looser .url("a") .delay(100) .ws_ack() @@ -1006,12 +1037,12 @@ async fn latency_detection_with_websockets() { .ws_ack() .url("a") .delay(20) - .metrics(now, 700) // check latency, bad + .info(now, 700) // check latency, bad .delay(20) - .election_loose(now) // looser + .info(now, 0) // looser .url("b") .delay(10) - .election(now, 500) // winner + .info(now, 500) // winner .reset_client(&client) .await; @@ -1052,10 +1083,10 @@ async fn get_endpoints() { NetworkMock::build() .url("a") .delay(10) - .election(now, 500) // winner + .info(now, 500) // winner .url("b") .delay(20) - .election_loose(now) // looser + .info(now, 0) // looser .reset_client(&client) .await; diff --git a/ton_client/src/net/ton_gql.rs b/ton_client/src/net/ton_gql.rs index fc33951e5..73a21e400 100644 --- a/ton_client/src/net/ton_gql.rs +++ b/ton_client/src/net/ton_gql.rs @@ -18,7 +18,6 @@ use crate::error::{ClientError, ClientResult}; use crate::net::gql::GraphQLMessageFromClient; use crate::net::ParamsOfWaitForCollection; use serde::{de::Error, Deserialize, Deserializer}; -use crate::net::endpoint::V_SUPPORTS_LATENCY; const COUNTERPARTIES_COLLECTION: &str = "counterparties"; const FETCH_ADDITIONAL_TIMEOUT: u32 = 5000; @@ -299,13 +298,9 @@ impl QueryOperationBuilder { self.end_op(&op.query_result()); } - fn add_info(&mut self, server_version: u32) { + fn add_info(&mut self) { self.start_op("info"); - self.end_op(if server_version >= V_SUPPORTS_LATENCY { - "version time latency" - } else { - "version time" - }); + self.end_op("version time latency rempEnabled"); } fn add_agg_op_params( @@ -406,7 +401,6 @@ pub(crate) struct GraphQLQuery { impl GraphQLQuery { pub fn build( params: &[ParamsOfQueryOperation], - server_version: u32, include_info: bool, default_wait_for_timeout: u32, ) -> GraphQLQuery { @@ -414,7 +408,7 @@ impl GraphQLQuery { let mut builder = QueryOperationBuilder::new(param_count > 1, default_wait_for_timeout); builder.add_operations(params); if include_info { - builder.add_info(server_version); + builder.add_info(); } builder.build() } diff --git a/ton_client/src/net/types.rs b/ton_client/src/net/types.rs index 16307da81..d7ac51ba2 100644 --- a/ton_client/src/net/types.rs +++ b/ton_client/src/net/types.rs @@ -175,12 +175,12 @@ pub enum NetworkQueriesProtocol { #[derive(Serialize, Deserialize, Debug, Clone, ApiType)] pub struct NetworkConfig { - /// **This field is deprecated, but left for backward-compatibility.** DApp Server public address. + /// **This field is deprecated, but left for backward-compatibility.** Evernode endpoint. pub server_address: Option, - /// List of DApp Server addresses. Any correct URL format can be specified, including IP addresses. + /// List of Evernode endpoints. Any correct URL format can be specified, including IP addresses. /// This parameter is prevailing over `server_address`. - /// Check the full list of [supported network endpoints](../ton-os-api/networks.md). + /// Check the full list of [supported network endpoints](https://docs.everos.dev/ever-sdk/reference/ever-os-api/networks). pub endpoints: Option>, /// Deprecated. You must use `network.max_reconnect_timeout` that allows to specify maximum network resolving timeout. @@ -323,11 +323,7 @@ pub struct NetworkConfig { )] pub next_remp_status_timeout: u32, - /// Access key to GraphQL API. - /// - /// You can specify here Basic Auth secret (Evercloud project secret) in hex string - /// or serialized JWT in base64 string. - /// Will be passed on as Authorization: Basic ... or Authorization: Bearer ... header. + /// Access key to GraphQL API (Project secret) pub access_key: Option, } diff --git a/ton_client/src/tests/contracts/abi_v2/CustomReplayProtection.abi.json b/ton_client/src/tests/contracts/abi_v2/CustomReplayProtection.abi.json new file mode 100644 index 000000000..948ea7374 --- /dev/null +++ b/ton_client/src/tests/contracts/abi_v2/CustomReplayProtection.abi.json @@ -0,0 +1,41 @@ +{ + "ABI version": 2, + "version": "2.3", + "header": ["pubkey", "time", "expire"], + "functions": [ + { + "name": "answer", + "inputs": [ + {"name":"dst","type":"address"} + ], + "outputs": [ + ] + }, + { + "name": "getData", + "inputs": [ + ], + "outputs": [ + {"name":"value0","type":"uint64"}, + {"name":"value1","type":"uint32"} + ] + }, + { + "name": "constructor", + "inputs": [ + ], + "outputs": [ + ] + } + ], + "data": [ + ], + "events": [ + ], + "fields": [ + {"name":"_pubkey","type":"uint256"}, + {"name":"_constructorFlag","type":"bool"}, + {"name":"m_timestamp","type":"uint64"}, + {"name":"m_expire","type":"uint32"} + ] +} diff --git a/ton_client/src/tests/contracts/abi_v2/CustomReplayProtection.sol b/ton_client/src/tests/contracts/abi_v2/CustomReplayProtection.sol new file mode 100644 index 000000000..a2f22d581 --- /dev/null +++ b/ton_client/src/tests/contracts/abi_v2/CustomReplayProtection.sol @@ -0,0 +1,31 @@ +pragma ton-solidity ^0.65.0; +pragma AbiHeader time; +pragma AbiHeader pubkey; +pragma AbiHeader expire; + +import "testDebot20.sol"; + +contract RollingIdsTest + { + uint64 m_timestamp; + uint32 m_expire; + + function answer(address dst) public view externalMsg { + tvm.accept(); + ARecieverDebot(dst).headerCalback(m_timestamp,m_expire); + } + + function afterSignatureCheck(TvmSlice body, TvmCell message) private inline returns (TvmSlice) { + //msgId = timestamp + message; + (uint64 msgId,uint32 exp) = body.decode(uint64, uint32); + require(msgId>m_timestamp,302); + m_timestamp = msgId; + m_expire = exp; + return body; + } + + function getData() external view returns (uint64,uint32) { + return (m_timestamp,m_expire); + } +} diff --git a/ton_client/src/tests/contracts/abi_v2/CustomReplayProtection.tvc b/ton_client/src/tests/contracts/abi_v2/CustomReplayProtection.tvc new file mode 100644 index 000000000..07d69171c Binary files /dev/null and b/ton_client/src/tests/contracts/abi_v2/CustomReplayProtection.tvc differ diff --git a/ton_client/src/tests/contracts/abi_v2/testDebot20.abi.json b/ton_client/src/tests/contracts/abi_v2/testDebot20.abi.json new file mode 100644 index 000000000..05f6ec5ed --- /dev/null +++ b/ton_client/src/tests/contracts/abi_v2/testDebot20.abi.json @@ -0,0 +1,196 @@ +{ + "ABI version": 2, + "version": "2.3", + "header": ["pubkey", "time", "expire"], + "functions": [ + { + "name": "getData", + "inputs": [ + ], + "outputs": [ + {"name":"value0","type":"uint64"}, + {"name":"value1","type":"uint32"} + ] + }, + { + "name": "setRollingId", + "inputs": [ + {"name":"a","type":"address"} + ], + "outputs": [ + ] + }, + { + "name": "headerCalback", + "inputs": [ + {"name":"timestamp","type":"uint64"}, + {"name":"expire","type":"uint32"} + ], + "outputs": [ + ] + }, + { + "name": "start", + "inputs": [ + ], + "outputs": [ + ] + }, + { + "name": "setRandom", + "inputs": [ + {"name":"buffer","type":"bytes"} + ], + "outputs": [ + ] + }, + { + "name": "setBoxHandle", + "inputs": [ + {"name":"handle","type":"uint32"} + ], + "outputs": [ + ] + }, + { + "name": "transferError", + "inputs": [ + {"name":"sdkError","type":"uint32"}, + {"name":"exitCode","type":"uint32"} + ], + "outputs": [ + ] + }, + { + "name": "transferSuccess", + "inputs": [ + {"name":"id","type":"uint256"} + ], + "outputs": [ + ] + }, + { + "name": "onFoo", + "inputs": [ + {"name":"addr","type":"address"} + ], + "outputs": [ + ] + }, + { + "name": "printQueryStatus", + "inputs": [ + {"name":"status","type":"uint8"} + ], + "outputs": [ + ] + }, + { + "name": "waitTransactionResult", + "inputs": [ + {"name":"status","type":"uint8"}, + {"components":[{"name":"kind","type":"uint8"},{"name":"value","type":"cell"},{"name":"object","type":"map(uint256,cell)"},{"components":[{"name":"cell","type":"cell"}],"name":"array","type":"tuple[]"}],"name":"object","type":"tuple"} + ], + "outputs": [ + ] + }, + { + "name": "getMsgDetails", + "inputs": [ + {"name":"value0","type":"uint64"}, + {"name":"value1","type":"uint32"} + ], + "outputs": [ + ] + }, + { + "name": "onGetMethodError", + "inputs": [ + {"name":"sdkError","type":"uint32"}, + {"name":"exitCode","type":"uint32"} + ], + "outputs": [ + ] + }, + { + "name": "getDebotInfo", + "id": "0xDEB", + "inputs": [ + ], + "outputs": [ + {"name":"name","type":"string"}, + {"name":"version","type":"string"}, + {"name":"publisher","type":"string"}, + {"name":"caption","type":"string"}, + {"name":"author","type":"string"}, + {"name":"support","type":"address"}, + {"name":"hello","type":"string"}, + {"name":"language","type":"string"}, + {"name":"dabi","type":"string"}, + {"name":"icon","type":"bytes"} + ] + }, + { + "name": "getRequiredInterfaces", + "inputs": [ + ], + "outputs": [ + {"name":"interfaces","type":"uint256[]"} + ] + }, + { + "name": "foo", + "inputs": [ + ], + "outputs": [ + {"name":"addr","type":"address"} + ] + }, + { + "name": "getDebotOptions", + "inputs": [ + ], + "outputs": [ + {"name":"options","type":"uint8"}, + {"name":"debotAbi","type":"string"}, + {"name":"targetAbi","type":"string"}, + {"name":"targetAddr","type":"address"} + ] + }, + { + "name": "setABI", + "inputs": [ + {"name":"dabi","type":"string"} + ], + "outputs": [ + ] + }, + { + "name": "constructor", + "inputs": [ + ], + "outputs": [ + ] + } + ], + "data": [ + ], + "events": [ + ], + "fields": [ + {"name":"_pubkey","type":"uint256"}, + {"name":"_timestamp","type":"uint64"}, + {"name":"_constructorFlag","type":"bool"}, + {"name":"m_options","type":"uint8"}, + {"name":"m_debotAbi","type":"optional(string)"}, + {"name":"m_targetAbi","type":"optional(string)"}, + {"name":"m_target","type":"optional(address)"}, + {"name":"m_rollingId","type":"address"}, + {"name":"m_sendMsg","type":"cell"}, + {"name":"m_timestamp","type":"uint64"}, + {"name":"m_expire","type":"uint32"}, + {"name":"m_sendTimestamp","type":"uint64"}, + {"name":"m_sendExpire","type":"uint32"}, + {"name":"m_handle","type":"uint32"} + ] +} diff --git a/ton_client/src/tests/contracts/abi_v2/testDebot20.sol b/ton_client/src/tests/contracts/abi_v2/testDebot20.sol new file mode 100644 index 000000000..424046d2e --- /dev/null +++ b/ton_client/src/tests/contracts/abi_v2/testDebot20.sol @@ -0,0 +1,189 @@ +pragma ton-solidity ^0.65.0; +pragma AbiHeader expire; +pragma AbiHeader time; +pragma AbiHeader pubkey; +// import required DeBot interfaces and basic DeBot contract. +import "https://raw.githubusercontent.com/tonlabs/debots/main/Debot.sol"; +import "https://raw.githubusercontent.com/tonlabs/DeBot-IS-consortium/main/SigningBoxInput/SigningBoxInput.sol"; +import "https://raw.githubusercontent.com/tonlabs/DeBot-IS-consortium/main/Terminal/Terminal.sol"; +import "https://raw.githubusercontent.com/tonlabs/DeBot-IS-consortium/main/Query/Query.sol"; +import "https://raw.githubusercontent.com/tonlabs/DeBot-IS-consortium/main/Sdk/Sdk.sol"; + +abstract contract ARollingId { + function answer(address dst) public {} +} + +abstract contract ARecieverDebot { + function headerCalback(uint64 timestamp, uint32 expire) virtual public {} +} + +contract MsgTestDebot is Debot, ARecieverDebot { + + using JsonLib for JsonLib.Value; + using JsonLib for mapping(uint256 => TvmCell); + + uint8 constant OVERRIDE_TS = 1; + uint8 constant OVERRIDE_EXPT = 2; + uint8 constant ASYNC_CALL = 4; + + address m_rollingId; + TvmCell m_sendMsg; + uint64 m_timestamp; + uint32 m_expire; + uint64 m_sendTimestamp; + uint32 m_sendExpire; + uint32 m_handle; + + function _abiver(uint8 maj, uint8 min) private pure inline returns (uint8) { + return (min << 4 | maj); + } + + function getData() external view returns (uint64,uint32) { + return (m_timestamp,m_expire); + } + + function setRollingId(address a) public { + require(msg.pubkey() == tvm.pubkey(), 101); + tvm.accept(); + m_rollingId = a; + } + + function headerCalback(uint64 timestamp, uint32 expire) override public { + tvm.accept(); + m_timestamp = timestamp; + m_expire = expire; + } + + function start() public override { + Sdk.genRandom(tvm.functionId(setRandom), 2); + } + + function setRandom(bytes buffer) public { + uint16 r = buffer.toSlice().decode(uint16); + m_sendTimestamp = r+500; + m_sendExpire = r+100; + SigningBoxInput.get(tvm.functionId(setBoxHandle), "", [tvm.pubkey()]); + } + + function setBoxHandle(uint32 handle) public { + m_handle = handle; + test1(); + test2(); + } + + function test1() private view { + ARollingId(m_rollingId).answer{ + callbackId: tvm.functionId(transferSuccess), + onErrorId: tvm.functionId(transferError), + time: m_sendTimestamp, + expire: m_sendExpire, + pubkey: tvm.pubkey(), + abiVer: _abiver(2, 3), + sign: true, + signBoxHandle: m_handle, + flags: OVERRIDE_TS | OVERRIDE_EXPT | ASYNC_CALL + }(address(this)).extMsg; + } + + function test2() private view { + this.foo{ + callbackId: tvm.functionId(onFoo), + onErrorId: tvm.functionId(transferError), + time: 0, + expire: 0, + pubkey: 0, + abiVer: _abiver(2, 3), + sign: true, + signBoxHandle: m_handle + }().extMsg; + } + + + function transferError(uint32 sdkError, uint32 exitCode) public pure { + Terminal.print(0, format("Transaction failed. Sdk error = {}, Error code = {}\nDo you want to retry?", sdkError, exitCode)); + require(false, 108); + } + + function transferSuccess(uint256 id) public pure { + id; + //wait for contract call our debot + Query.waitForCollection( + tvm.functionId(waitTransactionResult), + QueryCollection.Transactions, + format("{\"account_addr\":{\"eq\": \"{}\"},\"now\":{\"ge\": {}}}",address(this),now), + "id now", + 60000 + ); + } + + function onFoo(address addr) public view { + require(m_rollingId == addr, 110); + } + + function printQueryStatus(QueryStatus status) public pure { + if (status == QueryStatus.FilterError) + require(false, 102); + else if (status == QueryStatus.NetworkError) + require(false, 103); + else if (status == QueryStatus.UnknownError) + require(false, 104); + } + + function waitTransactionResult(QueryStatus status, JsonLib.Value object) public pure { + object; + if (status == QueryStatus.Success) { + MsgTestDebot(address(this)).getData{ + callbackId: getMsgDetails, + onErrorId: onGetMethodError, + time: 0, + expire: 0, + sign: false, + pubkey: null + }().extMsg; + } else { + printQueryStatus(status); + } + } + + function getMsgDetails(uint64 value0,uint32 value1) public view { + require(value0==m_sendTimestamp, 105); + require(value1==m_sendExpire, 106); + } + + function onGetMethodError(uint32 sdkError, uint32 exitCode) public pure { + Terminal.print(0, format("Get method error. Sdk error = {}, Error code = {}",sdkError, exitCode)); + require(false, 107); + } + + /* + * Implementation of DeBot + */ + function getDebotInfo() public functionID(0xDEB) override view returns( + string name, string version, string publisher, string caption, string author, + address support, string hello, string language, string dabi, bytes icon + ) { + name = "TestDeBot20"; + version = "0.1.0"; + publisher = "EverX"; + caption = "TestDeBot20"; + author = "EverX"; + support = address(0); + hello = "TestDeBot20"; + language = "en"; + dabi = m_debotAbi.get(); + icon = ""; + } + + function getRequiredInterfaces() public view override returns (uint256[] interfaces) { + return [ SigningBoxInput.ID, Terminal.ID ]; + } + + // + // Onchain functions + // + + function foo() external view externalMsg returns (address addr) { + tvm.accept(); + addr = m_rollingId; + } +} diff --git a/ton_client/src/tests/contracts/abi_v2/testDebot20.tvc b/ton_client/src/tests/contracts/abi_v2/testDebot20.tvc new file mode 100644 index 000000000..5a30be111 Binary files /dev/null and b/ton_client/src/tests/contracts/abi_v2/testDebot20.tvc differ diff --git a/ton_sdk/Cargo.toml b/ton_sdk/Cargo.toml index 84a83a510..dd7afbf49 100644 --- a/ton_sdk/Cargo.toml +++ b/ton_sdk/Cargo.toml @@ -1,6 +1,6 @@ [package] name = 'ton_sdk' -version = '1.37.2' +version = '1.38.0' edition = '2018' license = 'Apache-2.0' authors = [ 'TON Labs LTD ' ] diff --git a/toncli/Cargo.toml b/toncli/Cargo.toml index 9fb65a563..ad4a9ace0 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.37.2' +version = '1.38.0' [dependencies] base64 = '0.13.0' diff --git a/toncli/src/request.rs b/toncli/src/request.rs index 0e5195722..e9df7d0c6 100644 --- a/toncli/src/request.rs +++ b/toncli/src/request.rs @@ -93,7 +93,7 @@ fn get_api() -> ClientResult { } pub fn command(args: &[String]) -> Result<(), CliError> { - let mut network = "net.ton.dev".to_string(); + let mut network = "devnet.evercloud.dev".to_string(); let mut state = ParseState::OptionOrFunctionName; let mut option = String::new(); let mut function = String::new(); diff --git a/tools/api.json b/tools/api.json index 512b52544..3077bd745 100644 --- a/tools/api.json +++ b/tools/api.json @@ -1,5 +1,5 @@ { - "version": "1.37.2", + "version": "1.38.0", "modules": [ { "name": "client", @@ -365,7 +365,7 @@ "optional_inner": { "type": "String" }, - "summary": "**This field is deprecated, but left for backward-compatibility.** DApp Server public address.", + "summary": "**This field is deprecated, but left for backward-compatibility.** Evernode endpoint.", "description": null }, { @@ -377,8 +377,8 @@ "type": "String" } }, - "summary": "List of DApp Server addresses.", - "description": "Any correct URL format can be specified, including IP addresses. This parameter is prevailing over `server_address`.\nCheck the full list of [supported network endpoints](../ton-os-api/networks.md)." + "summary": "List of Evernode endpoints.", + "description": "Any correct URL format can be specified, including IP addresses. This parameter is prevailing over `server_address`.\nCheck the full list of [supported network endpoints](https://docs.everos.dev/ever-sdk/reference/ever-os-api/networks)." }, { "name": "network_retries_count", @@ -539,8 +539,8 @@ "optional_inner": { "type": "String" }, - "summary": "Access key to GraphQL API.", - "description": "You can specify here Basic Auth secret (Evercloud project secret) in hex string\nor serialized JWT in base64 string.\nWill be passed on as Authorization: Basic ... or Authorization: Bearer ... header." + "summary": "Access key to GraphQL API (Project secret)", + "description": null } ], "summary": null, @@ -11303,6 +11303,13 @@ "value": "614", "summary": null, "description": null + }, + { + "name": "Unauthorized", + "type": "Number", + "value": "615", + "summary": null, + "description": null } ], "summary": null, diff --git a/tools/update_trusted_blocks/src/main.rs b/tools/update_trusted_blocks/src/main.rs index d868e1501..01f725b06 100644 --- a/tools/update_trusted_blocks/src/main.rs +++ b/tools/update_trusted_blocks/src/main.rs @@ -99,8 +99,8 @@ async fn main() -> Result<()> { } let networks = [ - ("main.ton.dev", "58ffca1a178daff705de54216e5433c9bd2e7d850070d334d38997847ab9e845"), - ("net.ton.dev", "cd81dae0c23d78e7c3eb5903f2a7bd98889991d36a26812a9163ca0f29c47093"), + ("mainnet.evercloud.dev", "58ffca1a178daff705de54216e5433c9bd2e7d850070d334d38997847ab9e845"), + ("devnet.evercloud.dev", "cd81dae0c23d78e7c3eb5903f2a7bd98889991d36a26812a9163ca0f29c47093"), ]; let mut trusted_key_blocks = match std::fs::read(&args[1]) {