diff --git a/.github/workflows/Release-galactic-express.yml b/.github/workflows/Release-galactic-express.yml index cce54023b..d9ee7d022 100644 --- a/.github/workflows/Release-galactic-express.yml +++ b/.github/workflows/Release-galactic-express.yml @@ -71,6 +71,7 @@ jobs: tags: ${{ needs.prepair.outputs.image_name }} build-args: | REACT_APP_NODE_ADDRESS=${{ secrets.REACT_APP_NODE_ADDRESS }} + REACT_APP_CONTRACT_ADDRESS=${{ secrets.REACT_APP_CONTRACT_ADDRESS_GALACTIC }} REACT_APP_SENTRY_DSN=${{ secrets.REACT_SENTRY_DSN_GALEX }} deploy-to-k8s: diff --git a/.github/workflows/STG-galactic-express.yml b/.github/workflows/STG-galactic-express.yml index 61ecd052e..077fa766a 100644 --- a/.github/workflows/STG-galactic-express.yml +++ b/.github/workflows/STG-galactic-express.yml @@ -76,6 +76,7 @@ jobs: tags: ${{ needs.prepair.outputs.image_name }} build-args: | REACT_APP_NODE_ADDRESS=${{ secrets.REACT_APP_NODE_ADDRESS }} + REACT_APP_CONTRACT_ADDRESS=${{ secrets.REACT_APP_CONTRACT_ADDRESS_GALACTIC }} REACT_APP_SENTRY_DSN=${{ secrets.REACT_SENTRY_DSN_GALEX }} deploy-to-k8s: diff --git a/.github/workflows/STG-tictac.yml b/.github/workflows/STG-tictac.yml index df0dbd631..e88f08f81 100644 --- a/.github/workflows/STG-tictac.yml +++ b/.github/workflows/STG-tictac.yml @@ -47,7 +47,7 @@ jobs: - name: Set IMAGE_NAME id: image run: | - image_name=${{ env.REGISTRY }}:${{ env.branch_name }}-${{ env.sha_short }} + image_name=${{ env.REGISTRY }}-${{ env.KUBE_DEPLOYMENT_PREFIX }}:${{ env.branch_name }}-${{ env.sha_short }} echo "image_name=$image_name" >> $GITHUB_OUTPUT build-and-push-image: diff --git a/README.md b/README.md index 12565f691..d5e69951d 100644 --- a/README.md +++ b/README.md @@ -26,13 +26,13 @@

Hit the :star: button to keep up with our daily progress!

-:wave: This repository serves as a comprehensive collection of decentralized application (dApp) examples, showcasing various real-world use cases and implementations based on **[Gear Protocol](https://gear-tech.io/)**. Developers can explore and experiment with these examples to gain hands-on experience in building decentralized applications using cutting-edge technologies and industry best practices. +:wave: This repository serves as a comprehensive collection of decentralized application (dApp) examples, showcasing various real-world use cases and implementations based on **[Gear Protocol](https://gear-tech.io/)**. Developers can explore and experiment with these examples, running them in the **[Vara Network](http://vara.network/)** to gain hands-on experience in building decentralized applications using cutting-edge technologies and industry best practices. :scroll: A `contracts` folder houses the source codes of the smart contracts on Rust that power the decentralized applications. :computer: A dedicated `frontend` folder contains examples of React web applications. These applications serve as live demonstrations illustrating how the frontend interacts seamlessly with programs running on the blockchain. -:point_right: Anyone can build and upload their programs to the Vara Network Testnet via **[Gear Idea](https://idea.gear-tech.io/)** portal. It is recommended for testing and as a preparatory step prior to deploying your application on the Vara Network mainnet. +:point_right: Anyone can build and upload their programs to the Vara Network Testnet via **[Gear Idea](https://idea.gear-tech.io/programs?node=wss%3A%2F%2Ftestnet.vara.network)** portal. It is recommended for testing and as a preparatory step prior to deploying your application on the Vara Network mainnet. :globe_with_meridians: Join our [developer community](https://discord.gg/RyYBKXrrPn) and contribute to the evolution of the decentralized application landscape. diff --git a/contracts/Cargo.lock b/contracts/Cargo.lock index e8650ff30..37e6d2370 100644 --- a/contracts/Cargo.lock +++ b/contracts/Cargo.lock @@ -56,9 +56,9 @@ dependencies = [ [[package]] name = "aes" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac1f845298e95f983ff1944b728ae08b8cebab80d684f0a832ed0fc74dfa27e2" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" dependencies = [ "cfg-if", "cipher", @@ -81,9 +81,9 @@ dependencies = [ [[package]] name = "ahash" -version = "0.7.7" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a824f2aa7e75a0c98c5a504fceb80649e9c35265d44525b5f94de4771a395cd" +checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" dependencies = [ "getrandom 0.2.12", "once_cell", @@ -92,9 +92,9 @@ dependencies = [ [[package]] name = "ahash" -version = "0.8.7" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77c3a9648d43b9cd48db467b3f87fdd6e146bcc88ab0180006cef2179fe11d01" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ "cfg-if", "getrandom 0.2.12", @@ -105,9 +105,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] @@ -144,21 +144,15 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2faccea4cc4ab4a667ce676a30e8ec13922a692c99bb8f5b11f1502c72e04220" +checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" [[package]] name = "anyhow" -version = "1.0.79" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" - -[[package]] -name = "array-bytes" -version = "4.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f52f63c5c1316a16a4b35eaac8b76a98248961a533f061684cb2a7cb0eafb6c6" +checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" [[package]] name = "array-bytes" @@ -206,13 +200,13 @@ dependencies = [ [[package]] name = "async-channel" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ca33f4bc4ed1babef42cad36cc1f51fa88be00420404e5b1e80ab1b18f7678c" +checksum = "f28243a43d821d11341ab73c80bed182dc015c514b951616cf79bd4af39af0c3" dependencies = [ "concurrent-queue", - "event-listener 4.0.3", - "event-listener-strategy", + "event-listener 5.2.0", + "event-listener-strategy 0.5.0", "futures-core", "pin-project-lite", ] @@ -226,8 +220,8 @@ dependencies = [ "async-lock 3.3.0", "async-task", "concurrent-queue", - "fastrand 2.0.1", - "futures-lite 2.2.0", + "fastrand 2.0.2", + "futures-lite 2.3.0", "slab", ] @@ -265,18 +259,18 @@ dependencies = [ [[package]] name = "async-io" -version = "2.3.1" +version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f97ab0c5b00a7cdbe5a371b9a782ee7be1316095885c8a4ea1daf490eb0ef65" +checksum = "dcccb0f599cfa2f8ace422d3555572f47424da5648a4382a9dd0310ff8210884" dependencies = [ "async-lock 3.3.0", "cfg-if", "concurrent-queue", "futures-io", - "futures-lite 2.2.0", + "futures-lite 2.3.0", "parking", - "polling 3.3.2", - "rustix 0.38.31", + "polling 3.6.0", + "rustix 0.38.32", "slab", "tracing", "windows-sys 0.52.0", @@ -298,7 +292,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d034b430882f8381900d3fe6f0aaa3ad94f2cb4ac519b429692a1bc2dda4ae7b" dependencies = [ "event-listener 4.0.3", - "event-listener-strategy", + "event-listener-strategy 0.4.0", "pin-project-lite", ] @@ -326,7 +320,7 @@ dependencies = [ "cfg-if", "event-listener 3.1.0", "futures-lite 1.13.0", - "rustix 0.38.31", + "rustix 0.38.32", "windows-sys 0.48.0", ] @@ -336,13 +330,13 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e47d90f65a225c4527103a8d747001fc56e375203592b25ad103e1ca13124c5" dependencies = [ - "async-io 2.3.1", + "async-io 2.3.2", "async-lock 2.8.0", "atomic-waker", "cfg-if", "futures-core", "futures-io", - "rustix 0.38.31", + "rustix 0.38.32", "signal-hook-registry", "slab", "windows-sys 0.48.0", @@ -356,13 +350,13 @@ checksum = "fbb36e985947064623dbd357f727af08ffd077f93d696782f3c56365fa2e2799" [[package]] name = "async-trait" -version = "0.1.77" +version = "0.1.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" +checksum = "a507401cad91ec6a857ed5513a2073c82a9b9048762b885bb98655b306964681" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.55", ] [[package]] @@ -419,15 +413,15 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" [[package]] name = "backtrace" -version = "0.3.69" +version = "0.3.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" dependencies = [ "addr2line 0.21.0", "cc", @@ -475,7 +469,7 @@ dependencies = [ "battleship-bot", "battleship-io", "gclient", - "gear-core 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gear-core 1.1.1", "gear-wasm-builder", "gstd", "gtest", @@ -543,9 +537,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.2" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" [[package]] name = "bitvec" @@ -591,9 +585,9 @@ dependencies = [ [[package]] name = "blake3" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0231f06152bf547e9c2b5194f247cd97aacf6dcd8b15d8e5ec0663f64580da87" +checksum = "30cca6d3674597c30ddf2c587bf8d9d65c9a84d2326d941cc79c9842dfe0ef52" dependencies = [ "arrayref", "arrayvec 0.7.4", @@ -647,12 +641,12 @@ version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a37913e8dc4ddcc604f0c6d3bf2887c995153af3611de9e23c352b44c1b9118" dependencies = [ - "async-channel 2.1.1", + "async-channel 2.2.0", "async-lock 3.3.0", "async-task", - "fastrand 2.0.1", + "fastrand 2.0.2", "futures-io", - "futures-lite 2.2.0", + "futures-lite 2.3.0", "piper", "tracing", ] @@ -677,18 +671,18 @@ checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" [[package]] name = "bs58" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5353f36341f7451062466f0b755b96ac3a9547e4d7f6b70d603fc721a7d7896" +checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4" dependencies = [ "tinyvec", ] [[package]] name = "bumpalo" -version = "3.14.0" +version = "3.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa" [[package]] name = "byte-slice-cast" @@ -704,9 +698,9 @@ checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" [[package]] name = "bytecheck" -version = "0.6.11" +version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6372023ac861f6e6dc89c8344a8f398fb42aaba2b5dbc649ca0c0e9dbcb627" +checksum = "23cdc57ce23ac53c931e88a43d06d070a6fd142f2617be5855eb75efc9beb1c2" dependencies = [ "bytecheck_derive", "ptr_meta", @@ -715,9 +709,9 @@ dependencies = [ [[package]] name = "bytecheck_derive" -version = "0.6.11" +version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7ec4c6f261935ad534c0c22dbef2201b45918860eb1c574b972bd213a76af61" +checksum = "3db406d29fbcd95542e92559bed4d8ad92636d1ca8b3b72ede10b4bcc010e659" dependencies = [ "proc-macro2", "quote", @@ -732,9 +726,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" [[package]] name = "camino" @@ -784,7 +778,7 @@ dependencies = [ "car-3", "car-races-io", "gclient", - "gear-core 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gear-core 1.1.1", "gear-wasm-builder", "gstd", "gtest", @@ -806,9 +800,9 @@ dependencies = [ [[package]] name = "cargo-platform" -version = "0.1.6" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ceed8ef69d8518a5dda55c07425450b58a4e1946f4951eab6d7191ee86c2443d" +checksum = "24b1f0365a6c6bb4020cd05806fd0d33c44d38046b8bd7f0e40814b9763cabfc" dependencies = [ "serde", ] @@ -829,18 +823,15 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.83" +version = "1.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" -dependencies = [ - "libc", -] +checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" [[package]] name = "cfg-expr" -version = "0.15.6" +version = "0.15.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6100bc57b6209840798d95cb2775684849d332f7bd788db2a8c8caf7ef82a41a" +checksum = "fa50868b64a9a6fda9d593ce778849ea8715cd2a3d2cc17ffdb4a2f2f2f1961d" dependencies = [ "smallvec", ] @@ -877,16 +868,16 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.33" +version = "0.4.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f13690e35a5e4ace198e7beea2895d29f3a9cc55015fcebe6336bd2010af9eb" +checksum = "8eaf5903dcbc0a39312feb77df2ff4c76387d591b9fc7b04a238dcf8bb62639a" dependencies = [ "android-tzdata", "iana-time-zone", "js-sys", "num-traits", "wasm-bindgen", - "windows-targets 0.52.0", + "windows-targets 0.52.4", ] [[package]] @@ -902,18 +893,18 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.18" +version = "4.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e578d6ec4194633722ccf9544794b71b1385c3c027efe0c55db226fc880865c" +checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" dependencies = [ "clap_builder", ] [[package]] name = "clap_builder" -version = "4.4.18" +version = "4.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4df4df40ec50c46000231c914968278b1eb05098cf8f1b3a518a95030e71d1c7" +checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" dependencies = [ "anstyle", "clap_lex", @@ -921,9 +912,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" +checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" [[package]] name = "cmake" @@ -986,9 +977,9 @@ checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" [[package]] name = "const-random" -version = "0.1.17" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aaf16c9c2c612020bcfd042e170f6e32de9b9d75adb5277cdbbd2e2c8c8299a" +checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359" dependencies = [ "const-random-macro", ] @@ -1159,9 +1150,9 @@ dependencies = [ [[package]] name = "crc32fast" -version = "1.3.2" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" dependencies = [ "cfg-if", ] @@ -1321,13 +1312,14 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "4.1.1" +version = "4.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89b8c6a2e4b1f45971ad09761aafb85514a84744b67a95e32c3cc1352d1f65c" +checksum = "0a677b8922c94e01bdbb12126b0bc852f00447528dee1782229af9c720c3f348" dependencies = [ "cfg-if", "cpufeatures", "curve25519-dalek-derive", + "digest 0.10.7", "fiat-crypto", "platforms", "rustc_version", @@ -1343,7 +1335,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.55", ] [[package]] @@ -1436,12 +1428,12 @@ dependencies = [ [[package]] name = "darling" -version = "0.20.5" +version = "0.20.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc5d6b04b3fd0ba9926f945895de7d806260a2d7431ba82e7edaecb043c4c6b8" +checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391" dependencies = [ - "darling_core 0.20.5", - "darling_macro 0.20.5", + "darling_core 0.20.8", + "darling_macro 0.20.8", ] [[package]] @@ -1460,16 +1452,16 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.5" +version = "0.20.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04e48a959bcd5c761246f5d090ebc2fbf7b9cd527a492b07a67510c108f1e7e3" +checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", "strsim", - "syn 2.0.48", + "syn 2.0.55", ] [[package]] @@ -1485,13 +1477,13 @@ dependencies = [ [[package]] name = "darling_macro" -version = "0.20.5" +version = "0.20.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d1545d67a2149e1d93b7e5c7752dce5a7426eb5d1357ddcfd89336b94444f77" +checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" dependencies = [ - "darling_core 0.20.5", + "darling_core 0.20.8", "quote", - "syn 2.0.48", + "syn 2.0.55", ] [[package]] @@ -1660,7 +1652,7 @@ dependencies = [ "dex-io", "dex-state", "gclient", - "gear-core 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gear-core 1.1.1", "gear-lib", "gear-wasm-builder", "gstd", @@ -1839,9 +1831,9 @@ dependencies = [ [[package]] name = "dyn-clone" -version = "1.0.16" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "545b22097d44f8a9581187cdf93de7a71e4722bf51200cfaba810865b49a495d" +checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" [[package]] name = "dynamic-nft" @@ -1960,9 +1952,9 @@ dependencies = [ [[package]] name = "either" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" [[package]] name = "elliptic-curve" @@ -2020,7 +2012,7 @@ checksum = "03cdc46ec28bd728e67540c528013c6a10eb69a02eb31078a1bda695438cbfb8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.55", ] [[package]] @@ -2038,10 +2030,10 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e08b6c6ab82d70f08844964ba10c7babb716de2ecaeab9be5717918a5177d3af" dependencies = [ - "darling 0.20.5", + "darling 0.20.8", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.55", ] [[package]] @@ -2143,6 +2135,17 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "event-listener" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b5fb89194fa3cad959b833185b3063ba881dbfc7030680b314250779fb4cc91" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + [[package]] name = "event-listener-strategy" version = "0.4.0" @@ -2153,17 +2156,28 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "event-listener-strategy" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "feedafcaa9b749175d5ac357452a9d41ea2911da598fde46ce1fe02c37751291" +dependencies = [ + "event-listener 5.2.0", + "pin-project-lite", +] + [[package]] name = "expander" -version = "2.0.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f86a749cf851891866c10515ef6c299b5c69661465e9c3bbe7e07a2b77fb0f7" +checksum = "00e83c02035136f1592a47964ea60c05a50e4ed8b5892cfac197063850898d4d" dependencies = [ "blake2", "fs-err", + "prettier-please", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.55", ] [[package]] @@ -2189,9 +2203,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.0.1" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" +checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984" [[package]] name = "feeds" @@ -2264,9 +2278,9 @@ dependencies = [ [[package]] name = "fiat-crypto" -version = "0.2.5" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27573eac26f4dd11e2b1916c3fe1baa56407c83c71a773a8ba17ec0bca03b6b7" +checksum = "c007b1ae3abe1cb6f85a16305acd418b7ca6343b953633fee2b76d8f108b830f" [[package]] name = "fixed-hash" @@ -2321,7 +2335,7 @@ dependencies = [ [[package]] name = "frame-support" version = "4.0.0-dev" -source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#e4b3ebf0ed497e9d121a2e272d238fa87269b756" +source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#01d999dab4c70a4120084c21f6acad4bf2791f65" dependencies = [ "bitflags 1.3.2", "environmental", @@ -2337,25 +2351,25 @@ dependencies = [ "serde", "smallvec", "sp-api", - "sp-arithmetic 16.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", - "sp-core 21.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", + "sp-arithmetic 16.0.0", + "sp-core 21.0.0", "sp-core-hashing-proc-macro", - "sp-debug-derive 8.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", + "sp-debug-derive 8.0.0", "sp-inherents", - "sp-io 23.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", - "sp-runtime 24.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", + "sp-io 23.0.0", + "sp-runtime 24.0.0", "sp-staking", - "sp-state-machine 0.28.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", + "sp-state-machine 0.28.0", "sp-std 8.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", - "sp-tracing 10.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", - "sp-weights 20.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", + "sp-tracing 10.0.0", + "sp-weights 20.0.0", "tt-call", ] [[package]] name = "frame-support-procedural" version = "4.0.0-dev" -source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#e4b3ebf0ed497e9d121a2e272d238fa87269b756" +source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#01d999dab4c70a4120084c21f6acad4bf2791f65" dependencies = [ "Inflector", "cfg-expr", @@ -2367,35 +2381,35 @@ dependencies = [ "proc-macro-warning", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.55", ] [[package]] name = "frame-support-procedural-tools" version = "4.0.0-dev" -source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#e4b3ebf0ed497e9d121a2e272d238fa87269b756" +source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#01d999dab4c70a4120084c21f6acad4bf2791f65" dependencies = [ "frame-support-procedural-tools-derive", "proc-macro-crate 1.3.1", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.55", ] [[package]] name = "frame-support-procedural-tools-derive" version = "3.0.0" -source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#e4b3ebf0ed497e9d121a2e272d238fa87269b756" +source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#01d999dab4c70a4120084c21f6acad4bf2791f65" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.55", ] [[package]] name = "frame-system" version = "4.0.0-dev" -source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#e4b3ebf0ed497e9d121a2e272d238fa87269b756" +source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#01d999dab4c70a4120084c21f6acad4bf2791f65" dependencies = [ "cfg-if", "frame-support", @@ -2403,12 +2417,12 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-core 21.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", - "sp-io 23.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", - "sp-runtime 24.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", + "sp-core 21.0.0", + "sp-io 23.0.0", + "sp-runtime 24.0.0", "sp-std 8.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", "sp-version", - "sp-weights 20.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", + "sp-weights 20.0.0", ] [[package]] @@ -2521,11 +2535,11 @@ dependencies = [ [[package]] name = "futures-lite" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445ba825b27408685aaecefd65178908c36c6e96aaf6d8599419d46e624192ba" +checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" dependencies = [ - "fastrand 2.0.1", + "fastrand 2.0.2", "futures-core", "futures-io", "parking", @@ -2540,7 +2554,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.55", ] [[package]] @@ -2557,9 +2571,9 @@ checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" [[package]] name = "futures-timer" -version = "3.0.2" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" +checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" [[package]] name = "futures-util" @@ -2604,9 +2618,9 @@ dependencies = [ [[package]] name = "galloc" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73736b571eb1b9da624cfbb1b8b4e3216d8323f68ea80c2a014830b529a71947" +checksum = "050bc90f06336e79ee642c72f733dda79dba12832cb65ea57437689bdf865d4c" dependencies = [ "gear-dlmalloc", ] @@ -2641,16 +2655,16 @@ dependencies = [ [[package]] name = "gclient" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65738c8d8d51e8ef19b0e9865c5ea6a93642f4081cab2ea9b795a15a04865b61" +checksum = "571a60f20abf8232bdfe701c033d81e1995c6110ffeb854cd8b932ef09256ef6" dependencies = [ "anyhow", "async-trait", "futures", - "gear-core 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "gear-core-errors 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "gear-utils 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gear-core 1.1.1", + "gear-core-errors 1.2.0", + "gear-utils 1.1.1", "gsdk", "hex", "parity-scale-codec", @@ -2662,13 +2676,13 @@ dependencies = [ [[package]] name = "gcore" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2de53122c675b739d1548c7bfae56642975f0d95abd0b991bbc5844c1493f861" +checksum = "5018c42f6706b56ca0cce4aaa58f4f25fc3c79aa43c6abf9c988630affb250e1" dependencies = [ - "gear-core-errors 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gear-core-errors 1.2.0", "gear-stack-buffer", - "gsys 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gsys 1.1.1", "parity-scale-codec", ] @@ -2682,14 +2696,14 @@ dependencies = [ "frame-support", "frame-system", "gear-common-codegen", - "gear-core 1.1.0 (git+https://github.com/gear-tech/gear?tag=v1.1.0)", - "gear-wasm-instrument 1.1.0 (git+https://github.com/gear-tech/gear?tag=v1.1.0)", - "gsys 1.1.0 (git+https://github.com/gear-tech/gear?tag=v1.1.0)", + "gear-core 1.1.0", + "gear-wasm-instrument 1.1.0", + "gsys 1.1.0", "log", "primitive-types", - "sp-arithmetic 16.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", - "sp-core 21.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", - "sp-io 23.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", + "sp-arithmetic 16.0.0", + "sp-core 21.0.0", + "sp-io 23.0.0", "sp-std 8.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", ] @@ -2699,22 +2713,21 @@ version = "1.1.0" source = "git+https://github.com/gear-tech/gear?tag=v1.1.0#c8c09fc84385c17a1327033833acaba6a5a0d416" dependencies = [ "quote", - "syn 2.0.48", + "syn 2.0.55", ] [[package]] name = "gear-core" version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fbb3868ce89bb3d5ef4169a80059bd43580f6e53c594f1aa16825220ac814ec" +source = "git+https://github.com/gear-tech/gear?tag=v1.1.0#c8c09fc84385c17a1327033833acaba6a5a0d416" dependencies = [ "blake2-rfc", "byteorder", "derive_more", "enum-iterator 1.5.0", - "gear-core-errors 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "gear-wasm-instrument 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "gsys 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gear-core-errors 1.1.0", + "gear-wasm-instrument 1.1.0", + "gsys 1.1.0", "hashbrown 0.14.3", "hex", "log", @@ -2728,16 +2741,17 @@ dependencies = [ [[package]] name = "gear-core" -version = "1.1.0" -source = "git+https://github.com/gear-tech/gear?tag=v1.1.0#c8c09fc84385c17a1327033833acaba6a5a0d416" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b171e6947c247a71c5c82371ffdf55b14774d3708338d0b3cb9518ea0d69372" dependencies = [ "blake2-rfc", "byteorder", "derive_more", "enum-iterator 1.5.0", - "gear-core-errors 1.1.0 (git+https://github.com/gear-tech/gear?tag=v1.1.0)", - "gear-wasm-instrument 1.1.0 (git+https://github.com/gear-tech/gear?tag=v1.1.0)", - "gsys 1.1.0 (git+https://github.com/gear-tech/gear?tag=v1.1.0)", + "gear-core-errors 1.2.0", + "gear-wasm-instrument 1.1.1", + "gsys 1.1.1", "hashbrown 0.14.3", "hex", "log", @@ -2757,13 +2771,13 @@ dependencies = [ "actor-system-error", "blake2-rfc", "derive_more", - "gear-core 1.1.0 (git+https://github.com/gear-tech/gear?tag=v1.1.0)", - "gear-core-errors 1.1.0 (git+https://github.com/gear-tech/gear?tag=v1.1.0)", + "gear-core 1.1.0", + "gear-core-errors 1.1.0", "gear-lazy-pages-common", "gear-sandbox", "gear-sandbox-env", - "gear-wasm-instrument 1.1.0 (git+https://github.com/gear-tech/gear?tag=v1.1.0)", - "gsys 1.1.0 (git+https://github.com/gear-tech/gear?tag=v1.1.0)", + "gear-wasm-instrument 1.1.0", + "gsys 1.1.0", "log", "parity-scale-codec", ] @@ -2771,8 +2785,7 @@ dependencies = [ [[package]] name = "gear-core-errors" version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cdcbac6898186707a0efe05d56fcb6915ee3edb9313a941951789dcf9a92434" +source = "git+https://github.com/gear-tech/gear?tag=v1.1.0#c8c09fc84385c17a1327033833acaba6a5a0d416" dependencies = [ "derive_more", "enum-iterator 1.5.0", @@ -2781,8 +2794,9 @@ dependencies = [ [[package]] name = "gear-core-errors" -version = "1.1.0" -source = "git+https://github.com/gear-tech/gear?tag=v1.1.0#c8c09fc84385c17a1327033833acaba6a5a0d416" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d920a10789e3173957547393cd99d63c63550c3e77df10e6be7ca7e04531a81" dependencies = [ "derive_more", "enum-iterator 1.5.0", @@ -2796,13 +2810,13 @@ source = "git+https://github.com/gear-tech/gear?tag=v1.1.0#c8c09fc84385c17a13270 dependencies = [ "actor-system-error", "derive_more", - "gear-core 1.1.0 (git+https://github.com/gear-tech/gear?tag=v1.1.0)", + "gear-core 1.1.0", "gear-core-backend", - "gear-core-errors 1.1.0 (git+https://github.com/gear-tech/gear?tag=v1.1.0)", + "gear-core-errors 1.1.0", "gear-lazy-pages-common", "gear-lazy-pages-interface", - "gear-wasm-instrument 1.1.0 (git+https://github.com/gear-tech/gear?tag=v1.1.0)", - "gsys 1.1.0 (git+https://github.com/gear-tech/gear?tag=v1.1.0)", + "gear-wasm-instrument 1.1.0", + "gsys 1.1.0", "log", "scale-info", ] @@ -2828,7 +2842,7 @@ dependencies = [ "cfg-if", "derive_more", "errno", - "gear-core 1.1.0 (git+https://github.com/gear-tech/gear?tag=v1.1.0)", + "gear-core 1.1.0", "gear-lazy-pages-common", "gear-sandbox-host", "libc", @@ -2845,7 +2859,7 @@ name = "gear-lazy-pages-common" version = "1.1.0" source = "git+https://github.com/gear-tech/gear?tag=v1.1.0#c8c09fc84385c17a1327033833acaba6a5a0d416" dependencies = [ - "gear-core 1.1.0 (git+https://github.com/gear-tech/gear?tag=v1.1.0)", + "gear-core 1.1.0", "num_enum", "parity-scale-codec", ] @@ -2857,7 +2871,7 @@ source = "git+https://github.com/gear-tech/gear?tag=v1.1.0#c8c09fc84385c17a13270 dependencies = [ "byteorder", "gear-common", - "gear-core 1.1.0 (git+https://github.com/gear-tech/gear?tag=v1.1.0)", + "gear-core 1.1.0", "gear-lazy-pages-common", "gear-runtime-interface", "log", @@ -2868,9 +2882,9 @@ dependencies = [ name = "gear-lib" version = "1.1.0" dependencies = [ - "ahash 0.8.7", + "ahash 0.8.11", "gstd", - "indexmap 2.2.2", + "indexmap 2.2.6", "primitive-types", ] @@ -2879,7 +2893,7 @@ name = "gear-lib-derive" version = "1.1.0" dependencies = [ "quote", - "syn 2.0.48", + "syn 2.0.55", ] [[package]] @@ -2908,16 +2922,16 @@ version = "1.1.0" source = "git+https://github.com/gear-tech/gear?tag=v1.1.0#c8c09fc84385c17a1327033833acaba6a5a0d416" dependencies = [ "byteorder", - "gear-core 1.1.0 (git+https://github.com/gear-tech/gear?tag=v1.1.0)", + "gear-core 1.1.0", "gear-lazy-pages", "gear-lazy-pages-common", "gear-sandbox-host", "log", "parity-scale-codec", - "sp-io 23.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", - "sp-runtime-interface 17.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", + "sp-io 23.0.0", + "sp-runtime-interface 17.0.0", "sp-std 8.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", - "sp-wasm-interface 14.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", + "sp-wasm-interface 14.0.0", "winapi", ] @@ -2930,7 +2944,7 @@ dependencies = [ "gear-sandbox-env", "log", "parity-scale-codec", - "sp-core 21.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", + "sp-core 21.0.0", "sp-std 8.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", "sp-wasm-interface-common", "wasmi 0.30.0 (git+https://github.com/gear-tech/wasmi?branch=gear-v0.30.0)", @@ -2942,7 +2956,7 @@ version = "1.1.0" source = "git+https://github.com/gear-tech/gear?tag=v1.1.0#c8c09fc84385c17a1327033833acaba6a5a0d416" dependencies = [ "parity-scale-codec", - "sp-debug-derive 8.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", + "sp-debug-derive 8.0.0", "sp-std 8.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", "sp-wasm-interface-common", ] @@ -2968,18 +2982,17 @@ dependencies = [ [[package]] name = "gear-stack-buffer" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9de20087dedac00351769ac661113c527d3bbd8f98e03cc6440ecd3e7d3c07a" +checksum = "adffb2c28f467a03096d138f39c5b3c44d4cc3bbcdf1a94641651626ff5b39ca" [[package]] name = "gear-utils" version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "172c90a852b2d15abea371a24bc07834305446630a0a9189c34bb45666160b61" +source = "git+https://github.com/gear-tech/gear?tag=v1.1.0#c8c09fc84385c17a1327033833acaba6a5a0d416" dependencies = [ "env_logger", - "gear-core 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gear-core 1.1.0", "hex", "nonempty", "parity-scale-codec", @@ -2990,11 +3003,12 @@ dependencies = [ [[package]] name = "gear-utils" -version = "1.1.0" -source = "git+https://github.com/gear-tech/gear?tag=v1.1.0#c8c09fc84385c17a1327033833acaba6a5a0d416" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e54fd91242dbb99242a3002a1b9d6f2e60ba7ebe4880d8a422978d8c8b1c12e0" dependencies = [ "env_logger", - "gear-core 1.1.0 (git+https://github.com/gear-tech/gear?tag=v1.1.0)", + "gear-core 1.1.1", "hex", "nonempty", "parity-scale-codec", @@ -3011,18 +3025,18 @@ checksum = "bbfbfa701dc65e683fcd2fb24f046bcef22634acbdf47ad14724637dc39ad05b" [[package]] name = "gear-wasm-builder" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36aaf177668439764e3ee8cea226e48a9f44ade22bec5f138d4d22ac502715b8" +checksum = "90cacb0bf2bcb1b70ae4773b0a711e4c082789c301fc63b902440d2f6391b5df" dependencies = [ "anyhow", "cargo_metadata", "chrono", "colored", "dirs", - "gear-core 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gear-core 1.1.1", "gear-pwasm-utils", - "gear-wasm-instrument 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gear-wasm-instrument 1.1.1", "gmeta", "log", "once_cell", @@ -3037,8 +3051,7 @@ dependencies = [ [[package]] name = "gear-wasm-instrument" version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebea2216ebba27863df976a28d070e2aef86b099cd05b20bc5517e7b25bd7ae3" +source = "git+https://github.com/gear-tech/gear?tag=v1.1.0#c8c09fc84385c17a1327033833acaba6a5a0d416" dependencies = [ "derive_more", "enum-iterator 1.5.0", @@ -3047,8 +3060,9 @@ dependencies = [ [[package]] name = "gear-wasm-instrument" -version = "1.1.0" -source = "git+https://github.com/gear-tech/gear?tag=v1.1.0#c8c09fc84385c17a1327033833acaba6a5a0d416" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7d501ae30810c2aee710e0e74ee767c4f1274c00273b110433cc7d8291bbcd8" dependencies = [ "derive_more", "enum-iterator 1.5.0", @@ -3097,13 +3111,22 @@ dependencies = [ "wasi 0.11.0+wasi-snapshot-preview1", ] +[[package]] +name = "getrandom_or_panic" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea1015b5a70616b688dc230cfe50c8af89d972cb132d5a622814d29773b10b9" +dependencies = [ + "rand_core 0.6.4", +] + [[package]] name = "ghash" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d930750de5717d2dd0b8c0d42c076c0e884c81a73e6cab859bbd2339c71e3e40" +checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1" dependencies = [ - "opaque-debug 0.3.0", + "opaque-debug 0.3.1", "polyval", ] @@ -3143,9 +3166,9 @@ checksum = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" [[package]] name = "gmeta" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c0a1ed30a16d6f9bb5f6b871a8c102869ec151fe2700cf6dca2678bad39a719" +checksum = "f464cf8d902292e38cfa68fb0a42ca7249525e4358e4ed7e2521fc660ae21c22" dependencies = [ "blake2-rfc", "derive_more", @@ -3156,13 +3179,13 @@ dependencies = [ [[package]] name = "gmeta-codegen" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e3a341d27b765d12cff7968acf86ccc2085c89b8b656f63f1f7cdd3d3924c94" +checksum = "f6c5b9a168936d49be77437f06808509f0b4f36a2db79f46078afcc3be7683d7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.55", ] [[package]] @@ -3178,20 +3201,20 @@ dependencies = [ [[package]] name = "gsdk" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e87cc6647590399d918e46aea5d693857f0d4a78c28ba6913bbc1584c55353f1" +checksum = "a61807346a08dbd4a42247aeb7cdba844d5b42190019f1d94d341e7a1b746429" dependencies = [ "anyhow", "base64 0.21.7", "colored", "futures", "futures-util", - "gear-core 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "gear-core-errors 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gear-core 1.1.1", + "gear-core-errors 1.2.0", "gsdk-codegen", "hex", - "indexmap 2.2.2", + "indexmap 2.2.6", "jsonrpsee 0.16.3", "log", "parity-scale-codec", @@ -3201,36 +3224,36 @@ dependencies = [ "scale-value", "serde", "serde_json", - "sp-core 21.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-runtime 24.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 22.0.0", + "sp-runtime 25.0.0", "subxt", "thiserror", ] [[package]] name = "gsdk-codegen" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce25dd799a0ba1ec70839fb16ab0b93da1c8275bc093586c1b4154da032ca3c" +checksum = "2ca466389130e38806717264e103e958587d9eaeed52d19bcee31afe720ffe81" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.55", ] [[package]] name = "gstd" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d82601f8f5835c94a532415630591f773af07aab369bdf3dce2d3547a1dba581" +checksum = "81233e10d5a9f11f697b824be5474506918dc3d707223f10a102c1e01a1b4855" dependencies = [ "arrayvec 0.7.4", - "bs58 0.5.0", + "bs58 0.5.1", "const_format", "futures", "galloc", "gcore", - "gear-core-errors 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gear-core-errors 1.2.0", "gstd-codegen", "hashbrown 0.14.3", "hex", @@ -3241,25 +3264,25 @@ dependencies = [ [[package]] name = "gstd-codegen" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2555e0bd35a1b6a651e774d8d150a13f9ccab2658debe564344120c4acd170b0" +checksum = "a709957cf82f4a83ef4ed55ef4c4894d014142c1dfcf892abb93aeaff137273b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.55", ] [[package]] name = "gsys" version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a57ae1f6edfb4df9bfc5b8cd5147095a6cf186f6690d280f712d3834b18ce668" +source = "git+https://github.com/gear-tech/gear?tag=v1.1.0#c8c09fc84385c17a1327033833acaba6a5a0d416" [[package]] name = "gsys" -version = "1.1.0" -source = "git+https://github.com/gear-tech/gear?tag=v1.1.0#c8c09fc84385c17a1327033833acaba6a5a0d416" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4fed3acad7ecf119368534ab92245a41bb37477a4f14f3c14e5f011f72f4bda" [[package]] name = "gtest" @@ -3269,14 +3292,14 @@ dependencies = [ "colored", "derive_more", "env_logger", - "gear-core 1.1.0 (git+https://github.com/gear-tech/gear?tag=v1.1.0)", - "gear-core-errors 1.1.0 (git+https://github.com/gear-tech/gear?tag=v1.1.0)", + "gear-core 1.1.0", + "gear-core-errors 1.1.0", "gear-core-processor", "gear-lazy-pages", "gear-lazy-pages-common", - "gear-utils 1.1.0 (git+https://github.com/gear-tech/gear?tag=v1.1.0)", - "gear-wasm-instrument 1.1.0 (git+https://github.com/gear-tech/gear?tag=v1.1.0)", - "gsys 1.1.0 (git+https://github.com/gear-tech/gear?tag=v1.1.0)", + "gear-utils 1.1.0", + "gear-wasm-instrument 1.1.0", + "gsys 1.1.0", "hex", "log", "parity-scale-codec", @@ -3295,9 +3318,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.24" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb2c4422095b67ee78da96fbb51a4cc413b3b25883c7717ff7ca1ab31022c9c9" +checksum = "4fbd2820c5e49886948654ab546d0688ff24530286bdcf8fca3cefb16d4618eb" dependencies = [ "bytes", "fnv", @@ -3305,7 +3328,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap 2.2.2", + "indexmap 2.2.6", "slab", "tokio", "tokio-util", @@ -3333,7 +3356,7 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" dependencies = [ - "ahash 0.7.7", + "ahash 0.7.8", ] [[package]] @@ -3342,7 +3365,7 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" dependencies = [ - "ahash 0.7.7", + "ahash 0.7.8", ] [[package]] @@ -3351,7 +3374,7 @@ version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" dependencies = [ - "ahash 0.8.7", + "ahash 0.8.11", ] [[package]] @@ -3360,7 +3383,7 @@ version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" dependencies = [ - "ahash 0.8.7", + "ahash 0.8.11", "allocator-api2", "serde", ] @@ -3373,9 +3396,9 @@ checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" -version = "0.3.4" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d3d0e0f38255e7fa3cf31335b3a56f05febd18025f4db5ef7a0cfb4f8da651f" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "hex" @@ -3473,9 +3496,9 @@ dependencies = [ [[package]] name = "http" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" dependencies = [ "bytes", "fnv", @@ -3528,7 +3551,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2 0.5.5", + "socket2 0.5.6", "tokio", "tower-service", "tracing", @@ -3554,9 +3577,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.59" +version = "0.1.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6a67363e2aa4443928ce15e57ebae94fd8949958fd1223c4cfc0cd473ad7539" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -3665,9 +3688,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.2.2" +version = "2.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "824b2ae422412366ba479e8111fd301f7b5faece8149317bb81925979a53f520" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", "hashbrown 0.14.3", @@ -3725,12 +3748,12 @@ dependencies = [ [[package]] name = "is-terminal" -version = "0.4.10" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bad00257d07be169d870ab665980b06cdb366d792ad690bf2e76876dc503455" +checksum = "f23ff5ef2b80d608d61efee834934d862cd92461afc0560dedf493e4c033738b" dependencies = [ "hermit-abi", - "rustix 0.38.31", + "libc", "windows-sys 0.52.0", ] @@ -3745,15 +3768,15 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "js-sys" -version = "0.3.67" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a1d36f1235bc969acba30b7f5990b864423a6068a10f7c90ae8f0112e3a59d1" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" dependencies = [ "wasm-bindgen", ] @@ -4018,7 +4041,7 @@ version = "0.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "libc", "redox_syscall", ] @@ -4101,9 +4124,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.20" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" [[package]] name = "loupe" @@ -4141,6 +4164,15 @@ dependencies = [ "libc", ] +[[package]] +name = "mach2" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709" +dependencies = [ + "libc", +] + [[package]] name = "macro_magic" version = "0.4.2" @@ -4150,7 +4182,7 @@ dependencies = [ "macro_magic_core", "macro_magic_macros", "quote", - "syn 2.0.48", + "syn 2.0.55", ] [[package]] @@ -4164,7 +4196,7 @@ dependencies = [ "macro_magic_core_macros", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.55", ] [[package]] @@ -4175,7 +4207,7 @@ checksum = "d710e1214dffbab3b5dacb21475dde7d6ed84c69ff722b3a47a782668d44fbac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.55", ] [[package]] @@ -4186,7 +4218,7 @@ checksum = "b8fb85ec1620619edf2984a7693497d4ec88a9665d8b87e942856884c92dbf2a" dependencies = [ "macro_magic_core", "quote", - "syn 2.0.48", + "syn 2.0.55", ] [[package]] @@ -4210,7 +4242,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2cffa4ad52c6f791f4f8b15f0c05f9824b2ced1160e88cc393d64fff9a8ac64" dependencies = [ - "rustix 0.38.31", + "rustix 0.38.32", ] [[package]] @@ -4296,18 +4328,18 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" dependencies = [ "adler", ] [[package]] name = "mio" -version = "0.8.10" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", "wasi 0.11.0+wasi-snapshot-preview1", @@ -4376,7 +4408,7 @@ name = "nft" version = "1.1.0" dependencies = [ "gclient", - "gear-core 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gear-core 1.1.1", "gear-wasm-builder", "gmeta", "gstd", @@ -4616,11 +4648,10 @@ dependencies = [ [[package]] name = "num-integer" -version = "0.1.45" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "autocfg", "num-traits", ] @@ -4638,9 +4669,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.17" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" dependencies = [ "autocfg", ] @@ -4672,7 +4703,7 @@ checksum = "96667db765a921f7b295ffee8b60472b686a51d4f21c2ee4ffdb94c7013b65a6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.55", ] [[package]] @@ -4759,9 +4790,9 @@ checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" [[package]] name = "opaque-debug" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "openssl-probe" @@ -4960,22 +4991,22 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pin-project" -version = "1.1.4" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0302c4a0442c456bd56f841aee5c3bfd17967563f6fadc9ceb9f9c23cf3807e0" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.4" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266c042b60c9c76b8d53061e52b2e0d1116abc57cefc8c5cd671619a56ac3690" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.55", ] [[package]] @@ -5024,7 +5055,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "668d31b1c4eba19242f2088b2bf3316b82ca31082a8335764db4e083db7485d4" dependencies = [ "atomic-waker", - "fastrand 2.0.1", + "fastrand 2.0.2", "futures-io", ] @@ -5062,14 +5093,15 @@ dependencies = [ [[package]] name = "polling" -version = "3.3.2" +version = "3.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "545c980a3880efd47b2e262f6a4bb6daad6555cf3367aa9c4e52895f69537a41" +checksum = "e0c976a60b2d7e99d6f229e414670a9b85d13ac305cc6d1e9c134de58c5aaaf6" dependencies = [ "cfg-if", "concurrent-queue", + "hermit-abi", "pin-project-lite", - "rustix 0.38.31", + "rustix 0.38.32", "tracing", "windows-sys 0.52.0", ] @@ -5081,19 +5113,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" dependencies = [ "cpufeatures", - "opaque-debug 0.3.0", + "opaque-debug 0.3.1", "universal-hash", ] [[package]] name = "polyval" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52cff9d1d4dee5fe6d03729099f4a310a41179e0a10dbf542039873f2e826fb" +checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" dependencies = [ "cfg-if", "cpufeatures", - "opaque-debug 0.3.0", + "opaque-debug 0.3.1", "universal-hash", ] @@ -5103,6 +5135,16 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +[[package]] +name = "prettier-please" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22020dfcf177fcc7bf5deaf7440af371400c67c0de14c399938d8ed4fb4645d3" +dependencies = [ + "proc-macro2", + "syn 2.0.55", +] + [[package]] name = "primitive-types" version = "0.12.2" @@ -5167,14 +5209,14 @@ checksum = "3d1eaa7fa0aa1929ffdf7eeb6eac234dde6268914a14ad44d23521ab6a9b258e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.55", ] [[package]] name = "proc-macro2" -version = "1.0.78" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" dependencies = [ "unicode-ident", ] @@ -5305,9 +5347,9 @@ dependencies = [ [[package]] name = "rayon" -version = "1.8.1" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7237101a77a10773db45d62004a272517633fbcc3df19d96455ede1122e051" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" dependencies = [ "either", "rayon-core", @@ -5360,7 +5402,7 @@ checksum = "5fddb4f8d99b0a2ebafc65a87a69a7b9875e4b1ae1f00db265d300ef7f28bccc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.55", ] [[package]] @@ -5376,13 +5418,13 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.3" +version = "1.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" +checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.5", + "regex-automata 0.4.6", "regex-syntax 0.8.2", ] @@ -5397,9 +5439,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" dependencies = [ "aho-corasick", "memchr", @@ -5420,21 +5462,21 @@ checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] name = "region" -version = "3.0.0" +version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76e189c2369884dce920945e2ddf79b3dff49e071a167dd1817fa9c4c00d512e" +checksum = "e6b6ebd13bc009aef9cd476c1310d49ac354d36e240cf1bd753290f3dc7199a7" dependencies = [ "bitflags 1.3.2", "libc", - "mach", - "winapi", + "mach2", + "windows-sys 0.52.0", ] [[package]] name = "rend" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2571463863a6bd50c32f94402933f03457a3fbaf697a707c5be741e459f08fd" +checksum = "71fe3824f5629716b1589be05dacd749f6aa084c87e00e016714a8cdfccc997c" dependencies = [ "bytecheck", ] @@ -5491,23 +5533,24 @@ dependencies = [ [[package]] name = "ring" -version = "0.17.7" +version = "0.17.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" dependencies = [ "cc", + "cfg-if", "getrandom 0.2.12", "libc", "spin", "untrusted", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "rkyv" -version = "0.7.43" +version = "0.7.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "527a97cdfef66f65998b5f3b637c26f5a5ec09cc52a3f9932313ac645f4190f5" +checksum = "5cba464629b3394fc4dbc6f940ff8f5b4ff5c7aef40f29166fd4ad12acbc99c0" dependencies = [ "bitvec", "bytecheck", @@ -5523,9 +5566,9 @@ dependencies = [ [[package]] name = "rkyv_derive" -version = "0.7.43" +version = "0.7.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5c462a1328c8e67e4d6dbad1eb0355dd43e8ab432c6e227a43657f16ade5033" +checksum = "a7dddfff8de25e6f62b9d64e6e432bf1c6736c57d20323e15ee10435fbda7c65" dependencies = [ "proc-macro2", "quote", @@ -5736,11 +5779,11 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.31" +version = "0.38.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" +checksum = "65e04861e65f21776e67888bfbea442b3642beaa0138fdb1dd7a84a52dffdb89" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "errno", "libc", "linux-raw-sys 0.4.13", @@ -5809,9 +5852,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.16" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" [[package]] name = "scale-bits" @@ -5882,9 +5925,9 @@ dependencies = [ [[package]] name = "scale-info" -version = "2.10.0" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f7d66a1128282b7ef025a8ead62a4a9fcf017382ec53b8ffbf4d7bf77bd3c60" +checksum = "788745a868b0e751750388f4e6546eb921ef714a4317fa6954f7cde114eb2eb7" dependencies = [ "bitvec", "cfg-if", @@ -5896,9 +5939,9 @@ dependencies = [ [[package]] name = "scale-info-derive" -version = "2.10.0" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abf2c68b89cafb3b8d918dd07b42be0da66ff202cf1155c5739a4e0c1ea0dc19" +checksum = "7dc2f4e8bc344b9fc3d5f74f72c2e55bfc38d28dc2ebc69c194a3df424e4d9ac" dependencies = [ "proc-macro-crate 1.3.1", "proc-macro2", @@ -5941,7 +5984,7 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "772575a524feeb803e5b0fcbc6dd9f367e579488197c94c6e4023aad2305774d" dependencies = [ - "ahash 0.8.7", + "ahash 0.8.11", "cfg-if", "hashbrown 0.13.2", ] @@ -5980,6 +6023,23 @@ dependencies = [ "zeroize", ] +[[package]] +name = "schnorrkel" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de18f6d8ba0aad7045f5feae07ec29899c1112584a38509a84ad7b04451eaa0" +dependencies = [ + "arrayref", + "arrayvec 0.7.4", + "curve25519-dalek 4.1.2", + "getrandom_or_panic", + "merlin 3.0.0", + "rand_core 0.6.4", + "sha2 0.10.8", + "subtle", + "zeroize", +] + [[package]] name = "scopeguard" version = "1.2.0" @@ -6068,18 +6128,18 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.21" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0" +checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" dependencies = [ "serde", ] [[package]] name = "serde" -version = "1.0.196" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" dependencies = [ "serde_derive", ] @@ -6095,20 +6155,20 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.196" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.55", ] [[package]] name = "serde_json" -version = "1.0.113" +version = "1.0.115" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79" +checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd" dependencies = [ "itoa", "ryu", @@ -6134,7 +6194,7 @@ dependencies = [ "cfg-if", "cpufeatures", "digest 0.9.0", - "opaque-debug 0.3.0", + "opaque-debug 0.3.1", ] [[package]] @@ -6159,7 +6219,7 @@ dependencies = [ "cfg-if", "cpufeatures", "digest 0.9.0", - "opaque-debug 0.3.0", + "opaque-debug 0.3.1", ] [[package]] @@ -6381,9 +6441,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.13.1" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "smol" @@ -6414,7 +6474,7 @@ dependencies = [ "base64 0.21.7", "bip39", "blake2-rfc", - "bs58 0.5.0", + "bs58 0.5.1", "crossbeam-queue", "derive_more", "ed25519-zebra", @@ -6492,7 +6552,7 @@ dependencies = [ "aes-gcm", "blake2", "chacha20poly1305", - "curve25519-dalek 4.1.1", + "curve25519-dalek 4.1.2", "rand_core 0.6.4", "rustc_version", "sha2 0.10.8", @@ -6511,12 +6571,12 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.5" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" +checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" dependencies = [ "libc", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -6537,7 +6597,7 @@ dependencies = [ [[package]] name = "sp-allocator" version = "4.1.0-dev" -source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#e4b3ebf0ed497e9d121a2e272d238fa87269b756" +source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#01d999dab4c70a4120084c21f6acad4bf2791f65" dependencies = [ "log", "parity-scale-codec", @@ -6548,20 +6608,20 @@ dependencies = [ [[package]] name = "sp-api" version = "4.0.0-dev" -source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#e4b3ebf0ed497e9d121a2e272d238fa87269b756" +source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#01d999dab4c70a4120084c21f6acad4bf2791f65" dependencies = [ "hash-db", "log", "parity-scale-codec", "scale-info", "sp-api-proc-macro", - "sp-core 21.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", - "sp-externalities 0.19.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", + "sp-core 21.0.0", + "sp-externalities 0.19.0", "sp-metadata-ir", - "sp-runtime 24.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", - "sp-state-machine 0.28.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", + "sp-runtime 24.0.0", + "sp-state-machine 0.28.0", "sp-std 8.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", - "sp-trie 22.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", + "sp-trie 22.0.0", "sp-version", "thiserror", ] @@ -6569,7 +6629,7 @@ dependencies = [ [[package]] name = "sp-api-proc-macro" version = "4.0.0-dev" -source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#e4b3ebf0ed497e9d121a2e272d238fa87269b756" +source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#01d999dab4c70a4120084c21f6acad4bf2791f65" dependencies = [ "Inflector", "blake2", @@ -6577,72 +6637,71 @@ dependencies = [ "proc-macro-crate 1.3.1", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.55", ] [[package]] name = "sp-application-crypto" version = "23.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "899492ea547816d5dfe9a5a2ecc32f65a7110805af6da3380aa4902371b31dc2" +source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#01d999dab4c70a4120084c21f6acad4bf2791f65" dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-core 21.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-io 23.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-std 8.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 21.0.0", + "sp-io 23.0.0", + "sp-std 8.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", ] [[package]] name = "sp-application-crypto" -version = "23.0.0" -source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#e4b3ebf0ed497e9d121a2e272d238fa87269b756" +version = "24.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b49d62089ef6fdd52a6f90f670d533ccb365235258cf517dbd5bd571febcfbd" dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-core 21.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", - "sp-io 23.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", - "sp-std 8.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", + "sp-core 22.0.0", + "sp-io 24.0.0", + "sp-std 9.0.0", ] [[package]] name = "sp-arithmetic" version = "16.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb6020576e544c6824a51d651bc8df8e6ab67cd59f1c9ac09868bb81a5199ded" +source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#01d999dab4c70a4120084c21f6acad4bf2791f65" dependencies = [ "integer-sqrt", "num-traits", "parity-scale-codec", "scale-info", "serde", - "sp-std 8.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-std 8.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", "static_assertions", ] [[package]] name = "sp-arithmetic" -version = "16.0.0" -source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#e4b3ebf0ed497e9d121a2e272d238fa87269b756" +version = "17.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0241327405688cac3fcc29114fd35f99224e321daa37e19920e50e4b2fdd0645" dependencies = [ "integer-sqrt", "num-traits", "parity-scale-codec", "scale-info", "serde", - "sp-std 8.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", + "sp-std 9.0.0", "static_assertions", ] [[package]] name = "sp-core" version = "21.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f18d9e2f67d8661f9729f35347069ac29d92758b59135176799db966947a7336" +source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#01d999dab4c70a4120084c21f6acad4bf2791f65" dependencies = [ - "array-bytes 4.2.0", + "array-bytes", "bitflags 1.3.2", "blake2", "bounded-collections", @@ -6668,25 +6727,28 @@ dependencies = [ "secp256k1", "secrecy", "serde", - "sp-core-hashing 9.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-debug-derive 8.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-externalities 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-runtime-interface 17.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-std 8.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-storage 13.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-allocator", + "sp-core-hashing 9.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", + "sp-debug-derive 8.0.0", + "sp-externalities 0.19.0", + "sp-runtime-interface 17.0.0", + "sp-std 8.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", + "sp-storage 13.0.0", "ss58-registry", "substrate-bip39", "thiserror", "tiny-bip39", + "tracing", "zeroize", ] [[package]] name = "sp-core" -version = "21.0.0" -source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#e4b3ebf0ed497e9d121a2e272d238fa87269b756" +version = "22.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0de478e02efd547693b33ad02515e09933d5b69b7f3036fa890b92e50fd9dfc" dependencies = [ - "array-bytes 6.2.2", + "array-bytes", "bitflags 1.3.2", "blake2", "bounded-collections", @@ -6712,44 +6774,6 @@ dependencies = [ "secp256k1", "secrecy", "serde", - "sp-allocator", - "sp-core-hashing 9.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", - "sp-debug-derive 8.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", - "sp-externalities 0.19.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", - "sp-runtime-interface 17.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", - "sp-std 8.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", - "sp-storage 13.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", - "ss58-registry", - "substrate-bip39", - "thiserror", - "tiny-bip39", - "tracing", - "zeroize", -] - -[[package]] -name = "sp-core" -version = "22.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0de478e02efd547693b33ad02515e09933d5b69b7f3036fa890b92e50fd9dfc" -dependencies = [ - "array-bytes 6.2.2", - "bitflags 1.3.2", - "blake2", - "bounded-collections", - "ed25519-zebra", - "hash-db", - "hash256-std-hasher", - "libsecp256k1", - "log", - "merlin 2.0.1", - "parity-scale-codec", - "paste", - "primitive-types", - "scale-info", - "schnorrkel 0.9.1", - "secp256k1", - "secrecy", "sp-core-hashing 10.0.0", "sp-debug-derive 9.0.0", "sp-externalities 0.20.0", @@ -6757,6 +6781,10 @@ dependencies = [ "sp-std 9.0.0", "sp-storage 14.0.0", "ss58-registry", + "substrate-bip39", + "thiserror", + "tiny-bip39", + "tracing", "zeroize", ] @@ -6778,7 +6806,7 @@ dependencies = [ [[package]] name = "sp-core-hashing" version = "9.0.0" -source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#e4b3ebf0ed497e9d121a2e272d238fa87269b756" +source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#01d999dab4c70a4120084c21f6acad4bf2791f65" dependencies = [ "blake2b_simd", "byteorder", @@ -6805,32 +6833,21 @@ dependencies = [ [[package]] name = "sp-core-hashing-proc-macro" version = "9.0.0" -source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#e4b3ebf0ed497e9d121a2e272d238fa87269b756" +source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#01d999dab4c70a4120084c21f6acad4bf2791f65" dependencies = [ "quote", "sp-core-hashing 9.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", - "syn 2.0.48", + "syn 2.0.55", ] [[package]] name = "sp-debug-derive" version = "8.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7f531814d2f16995144c74428830ccf7d94ff4a7749632b83ad8199b181140c" +source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#01d999dab4c70a4120084c21f6acad4bf2791f65" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", -] - -[[package]] -name = "sp-debug-derive" -version = "8.0.0" -source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#e4b3ebf0ed497e9d121a2e272d238fa87269b756" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.48", + "syn 2.0.55", ] [[package]] @@ -6841,30 +6858,18 @@ checksum = "f12dae7cf6c1e825d13ffd4ce16bd9309db7c539929d0302b4443ed451a9f4e5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", -] - -[[package]] -name = "sp-externalities" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0f71c671e01a8ca60da925d43a1b351b69626e268b8837f8371e320cf1dd100" -dependencies = [ - "environmental", - "parity-scale-codec", - "sp-std 8.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-storage 13.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 2.0.55", ] [[package]] name = "sp-externalities" version = "0.19.0" -source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#e4b3ebf0ed497e9d121a2e272d238fa87269b756" +source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#01d999dab4c70a4120084c21f6acad4bf2791f65" dependencies = [ "environmental", "parity-scale-codec", "sp-std 8.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", - "sp-storage 13.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", + "sp-storage 13.0.0", ] [[package]] @@ -6882,13 +6887,13 @@ dependencies = [ [[package]] name = "sp-inherents" version = "4.0.0-dev" -source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#e4b3ebf0ed497e9d121a2e272d238fa87269b756" +source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#01d999dab4c70a4120084c21f6acad4bf2791f65" dependencies = [ "async-trait", "impl-trait-for-tuples", "parity-scale-codec", "scale-info", - "sp-runtime 24.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", + "sp-runtime 24.0.0", "sp-std 8.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", "thiserror", ] @@ -6896,34 +6901,33 @@ dependencies = [ [[package]] name = "sp-io" version = "23.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d597e35a9628fe7454b08965b2442e3ec0f264b0a90d41328e87422cec02e99" +source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#01d999dab4c70a4120084c21f6acad4bf2791f65" dependencies = [ "bytes", "ed25519", "ed25519-dalek", - "futures", "libsecp256k1", "log", "parity-scale-codec", "rustversion", "secp256k1", - "sp-core 21.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-externalities 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-keystore 0.27.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-runtime-interface 17.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-state-machine 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-std 8.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-tracing 10.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-trie 22.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 21.0.0", + "sp-externalities 0.19.0", + "sp-keystore 0.27.0", + "sp-runtime-interface 17.0.0", + "sp-state-machine 0.28.0", + "sp-std 8.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", + "sp-tracing 10.0.0", + "sp-trie 22.0.0", "tracing", "tracing-core", ] [[package]] name = "sp-io" -version = "23.0.0" -source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#e4b3ebf0ed497e9d121a2e272d238fa87269b756" +version = "24.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff6194309bfe055d93177c6c9d2ed4c7b66040617cf3003a15e509c432cf3b62" dependencies = [ "bytes", "ed25519", @@ -6933,14 +6937,14 @@ dependencies = [ "parity-scale-codec", "rustversion", "secp256k1", - "sp-core 21.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", - "sp-externalities 0.19.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", - "sp-keystore 0.27.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", - "sp-runtime-interface 17.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", - "sp-state-machine 0.28.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", - "sp-std 8.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", - "sp-tracing 10.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", - "sp-trie 22.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", + "sp-core 22.0.0", + "sp-externalities 0.20.0", + "sp-keystore 0.28.0", + "sp-runtime-interface 18.0.0", + "sp-state-machine 0.29.0", + "sp-std 9.0.0", + "sp-tracing 11.0.0", + "sp-trie 23.0.0", "tracing", "tracing-core", ] @@ -6948,33 +6952,32 @@ dependencies = [ [[package]] name = "sp-keystore" version = "0.27.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9be3cdd67cc1d9c1db17c5cbc4ec4924054a8437009d167f21f6590797e4aa45" +source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#01d999dab4c70a4120084c21f6acad4bf2791f65" dependencies = [ - "futures", "parity-scale-codec", "parking_lot", - "sp-core 21.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-externalities 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 21.0.0", + "sp-externalities 0.19.0", "thiserror", ] [[package]] name = "sp-keystore" -version = "0.27.0" -source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#e4b3ebf0ed497e9d121a2e272d238fa87269b756" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eda1d2572a15340927a9f7db75ffe74366b645eaf9212015b4a96ad8e9d4c46" dependencies = [ "parity-scale-codec", "parking_lot", - "sp-core 21.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", - "sp-externalities 0.19.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", + "sp-core 22.0.0", + "sp-externalities 0.20.0", "thiserror", ] [[package]] name = "sp-metadata-ir" version = "0.1.0" -source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#e4b3ebf0ed497e9d121a2e272d238fa87269b756" +source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#01d999dab4c70a4120084c21f6acad4bf2791f65" dependencies = [ "frame-metadata 16.0.0", "parity-scale-codec", @@ -6985,8 +6988,7 @@ dependencies = [ [[package]] name = "sp-panic-handler" version = "8.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebd2de46003fa8212426838ca71cd42ee36a26480ba9ffea983506ce03131033" +source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#01d999dab4c70a4120084c21f6acad4bf2791f65" dependencies = [ "backtrace", "lazy_static", @@ -6995,8 +6997,9 @@ dependencies = [ [[package]] name = "sp-panic-handler" -version = "8.0.0" -source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#e4b3ebf0ed497e9d121a2e272d238fa87269b756" +version = "9.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c67eb0a0d11d3017ef43c975068ba76c7b0e83aca1ee3d68ba0ce270ecebe7" dependencies = [ "backtrace", "lazy_static", @@ -7006,8 +7009,7 @@ dependencies = [ [[package]] name = "sp-runtime" version = "24.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21c5bfc764a1a8259d7e8f7cfd22c84006275a512c958d3ff966c92151e134d5" +source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#01d999dab4c70a4120084c21f6acad4bf2791f65" dependencies = [ "either", "hash256-std-hasher", @@ -7018,18 +7020,19 @@ dependencies = [ "rand 0.8.5", "scale-info", "serde", - "sp-application-crypto 23.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-arithmetic 16.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-core 21.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-io 23.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-std 8.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-weights 20.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-application-crypto 23.0.0", + "sp-arithmetic 16.0.0", + "sp-core 21.0.0", + "sp-io 23.0.0", + "sp-std 8.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", + "sp-weights 20.0.0", ] [[package]] name = "sp-runtime" -version = "24.0.0" -source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#e4b3ebf0ed497e9d121a2e272d238fa87269b756" +version = "25.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d056e4cccf36a45be5d471b47c09e8be91b825f1d8352f20aa01f9f693176e7" dependencies = [ "either", "hash256-std-hasher", @@ -7040,48 +7043,29 @@ dependencies = [ "rand 0.8.5", "scale-info", "serde", - "sp-application-crypto 23.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", - "sp-arithmetic 16.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", - "sp-core 21.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", - "sp-io 23.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", - "sp-std 8.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", - "sp-weights 20.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", -] - -[[package]] -name = "sp-runtime-interface" -version = "17.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e676128182f90015e916f806cba635c8141e341e7abbc45d25525472e1bbce8" -dependencies = [ - "bytes", - "impl-trait-for-tuples", - "parity-scale-codec", - "primitive-types", - "sp-externalities 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-runtime-interface-proc-macro 11.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-std 8.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-storage 13.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-tracing 10.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-wasm-interface 14.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "static_assertions", + "sp-application-crypto 24.0.0", + "sp-arithmetic 17.0.0", + "sp-core 22.0.0", + "sp-io 24.0.0", + "sp-std 9.0.0", + "sp-weights 21.0.0", ] [[package]] name = "sp-runtime-interface" version = "17.0.0" -source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#e4b3ebf0ed497e9d121a2e272d238fa87269b756" +source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#01d999dab4c70a4120084c21f6acad4bf2791f65" dependencies = [ "bytes", "impl-trait-for-tuples", "parity-scale-codec", "primitive-types", - "sp-externalities 0.19.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", - "sp-runtime-interface-proc-macro 11.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", + "sp-externalities 0.19.0", + "sp-runtime-interface-proc-macro 11.0.0", "sp-std 8.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", - "sp-storage 13.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", - "sp-tracing 10.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", - "sp-wasm-interface 14.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", + "sp-storage 13.0.0", + "sp-tracing 10.0.0", + "sp-wasm-interface 14.0.0", "static_assertions", ] @@ -7107,26 +7091,13 @@ dependencies = [ [[package]] name = "sp-runtime-interface-proc-macro" version = "11.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5d5bd5566fe5633ec48dfa35ab152fd29f8a577c21971e1c6db9f28afb9bbb9" +source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#01d999dab4c70a4120084c21f6acad4bf2791f65" dependencies = [ "Inflector", "proc-macro-crate 1.3.1", "proc-macro2", "quote", - "syn 2.0.48", -] - -[[package]] -name = "sp-runtime-interface-proc-macro" -version = "11.0.0" -source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#e4b3ebf0ed497e9d121a2e272d238fa87269b756" -dependencies = [ - "Inflector", - "proc-macro-crate 1.3.1", - "proc-macro2", - "quote", - "syn 2.0.48", + "syn 2.0.55", ] [[package]] @@ -7139,28 +7110,27 @@ dependencies = [ "proc-macro-crate 1.3.1", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.55", ] [[package]] name = "sp-staking" version = "4.0.0-dev" -source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#e4b3ebf0ed497e9d121a2e272d238fa87269b756" +source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#01d999dab4c70a4120084c21f6acad4bf2791f65" dependencies = [ "impl-trait-for-tuples", "parity-scale-codec", "scale-info", "serde", - "sp-core 21.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", - "sp-runtime 24.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", + "sp-core 21.0.0", + "sp-runtime 24.0.0", "sp-std 8.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", ] [[package]] name = "sp-state-machine" version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ef45d31f9e7ac648f8899a0cd038a3608f8499028bff55b6c799702592325b6" +source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#01d999dab4c70a4120084c21f6acad4bf2791f65" dependencies = [ "hash-db", "log", @@ -7168,19 +7138,21 @@ dependencies = [ "parking_lot", "rand 0.8.5", "smallvec", - "sp-core 21.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-externalities 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-panic-handler 8.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-std 8.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-trie 22.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 21.0.0", + "sp-externalities 0.19.0", + "sp-panic-handler 8.0.0", + "sp-std 8.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", + "sp-trie 22.0.0", "thiserror", "tracing", + "trie-db", ] [[package]] name = "sp-state-machine" -version = "0.28.0" -source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#e4b3ebf0ed497e9d121a2e272d238fa87269b756" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2e84d8ed3acc6aed5a3d5cfd500fb5b99c1e299c86086b2fe82c3e4be93178f" dependencies = [ "hash-db", "log", @@ -7188,11 +7160,11 @@ dependencies = [ "parking_lot", "rand 0.8.5", "smallvec", - "sp-core 21.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", - "sp-externalities 0.19.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", - "sp-panic-handler 8.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", - "sp-std 8.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", - "sp-trie 22.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", + "sp-core 22.0.0", + "sp-externalities 0.20.0", + "sp-panic-handler 9.0.0", + "sp-std 9.0.0", + "sp-trie 23.0.0", "thiserror", "tracing", "trie-db", @@ -7207,7 +7179,7 @@ checksum = "53458e3c57df53698b3401ec0934bea8e8cfce034816873c0b0abbd83d7bac0d" [[package]] name = "sp-std" version = "8.0.0" -source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#e4b3ebf0ed497e9d121a2e272d238fa87269b756" +source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#01d999dab4c70a4120084c21f6acad4bf2791f65" [[package]] name = "sp-std" @@ -7218,27 +7190,13 @@ checksum = "2d5bbc9339227d1b6a9b7ccd9b2920c818653d40eef1512f1e2e824d72e7a336" [[package]] name = "sp-storage" version = "13.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94294be83f11d4958cfea89ed5798f0b6605f5defc3a996948848458abbcc18e" -dependencies = [ - "impl-serde", - "parity-scale-codec", - "ref-cast", - "serde", - "sp-debug-derive 8.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-std 8.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "sp-storage" -version = "13.0.0" -source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#e4b3ebf0ed497e9d121a2e272d238fa87269b756" +source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#01d999dab4c70a4120084c21f6acad4bf2791f65" dependencies = [ "impl-serde", "parity-scale-codec", "ref-cast", "serde", - "sp-debug-derive 8.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", + "sp-debug-derive 8.0.0", "sp-std 8.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", ] @@ -7259,20 +7217,7 @@ dependencies = [ [[package]] name = "sp-tracing" version = "10.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357f7591980dd58305956d32f8f6646d0a8ea9ea0e7e868e46f53b68ddf00cec" -dependencies = [ - "parity-scale-codec", - "sp-std 8.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tracing", - "tracing-core", - "tracing-subscriber", -] - -[[package]] -name = "sp-tracing" -version = "10.0.0" -source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#e4b3ebf0ed497e9d121a2e272d238fa87269b756" +source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#01d999dab4c70a4120084c21f6acad4bf2791f65" dependencies = [ "parity-scale-codec", "sp-std 8.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", @@ -7291,15 +7236,15 @@ dependencies = [ "sp-std 9.0.0", "tracing", "tracing-core", + "tracing-subscriber", ] [[package]] name = "sp-trie" version = "22.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48e4eeb7ef23f79eba8609db79ef9cef242f994f1f87a3c0387b4b5f177fda74" +source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#01d999dab4c70a4120084c21f6acad4bf2791f65" dependencies = [ - "ahash 0.8.7", + "ahash 0.8.11", "hash-db", "hashbrown 0.13.2", "lazy_static", @@ -7309,8 +7254,8 @@ dependencies = [ "parking_lot", "scale-info", "schnellru", - "sp-core 21.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-std 8.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 21.0.0", + "sp-std 8.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", "thiserror", "tracing", "trie-db", @@ -7319,10 +7264,11 @@ dependencies = [ [[package]] name = "sp-trie" -version = "22.0.0" -source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#e4b3ebf0ed497e9d121a2e272d238fa87269b756" +version = "23.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf63ea90ffb5d61048d8fb2fac669114dac198fc2739e913e615f0fd2c36c3e7" dependencies = [ - "ahash 0.8.7", + "ahash 0.8.11", "hash-db", "hashbrown 0.13.2", "lazy_static", @@ -7332,8 +7278,8 @@ dependencies = [ "parking_lot", "scale-info", "schnellru", - "sp-core 21.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", - "sp-std 8.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", + "sp-core 22.0.0", + "sp-std 9.0.0", "thiserror", "tracing", "trie-db", @@ -7343,7 +7289,7 @@ dependencies = [ [[package]] name = "sp-version" version = "22.0.0" -source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#e4b3ebf0ed497e9d121a2e272d238fa87269b756" +source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#01d999dab4c70a4120084c21f6acad4bf2791f65" dependencies = [ "impl-serde", "parity-scale-codec", @@ -7351,7 +7297,7 @@ dependencies = [ "scale-info", "serde", "sp-core-hashing-proc-macro", - "sp-runtime 24.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", + "sp-runtime 24.0.0", "sp-std 8.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", "sp-version-proc-macro", "thiserror", @@ -7360,32 +7306,18 @@ dependencies = [ [[package]] name = "sp-version-proc-macro" version = "8.0.0" -source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#e4b3ebf0ed497e9d121a2e272d238fa87269b756" +source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#01d999dab4c70a4120084c21f6acad4bf2791f65" dependencies = [ "parity-scale-codec", "proc-macro2", "quote", - "syn 2.0.48", -] - -[[package]] -name = "sp-wasm-interface" -version = "14.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19c122609ca5d8246be6386888596320d03c7bc880959eaa2c36bcd5acd6846" -dependencies = [ - "anyhow", - "impl-trait-for-tuples", - "log", - "parity-scale-codec", - "sp-std 8.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "wasmtime", + "syn 2.0.55", ] [[package]] name = "sp-wasm-interface" version = "14.0.0" -source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#e4b3ebf0ed497e9d121a2e272d238fa87269b756" +source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#01d999dab4c70a4120084c21f6acad4bf2791f65" dependencies = [ "anyhow", "impl-trait-for-tuples", @@ -7403,15 +7335,18 @@ version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d07945f592d2792632e6f030108769757e928a0fd78cf8659c9c210a5e341e55" dependencies = [ + "anyhow", "impl-trait-for-tuples", + "log", "parity-scale-codec", "sp-std 9.0.0", + "wasmtime", ] [[package]] name = "sp-wasm-interface-common" version = "7.0.0" -source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#e4b3ebf0ed497e9d121a2e272d238fa87269b756" +source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#01d999dab4c70a4120084c21f6acad4bf2791f65" dependencies = [ "parity-scale-codec", "sp-std 8.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", @@ -7421,32 +7356,32 @@ dependencies = [ [[package]] name = "sp-weights" version = "20.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45d084c735544f70625b821c3acdbc7a2fc1893ca98b85f1942631284692c75b" +source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#01d999dab4c70a4120084c21f6acad4bf2791f65" dependencies = [ "parity-scale-codec", "scale-info", "serde", "smallvec", - "sp-arithmetic 16.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-core 21.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-debug-derive 8.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-std 8.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-arithmetic 16.0.0", + "sp-core 21.0.0", + "sp-debug-derive 8.0.0", + "sp-std 8.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", ] [[package]] name = "sp-weights" -version = "20.0.0" -source = "git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary#e4b3ebf0ed497e9d121a2e272d238fa87269b756" +version = "21.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7699b853471c2eb5dc06ea1d8ea847bfa1415371218ebb4c86325c9d0232bc" dependencies = [ "parity-scale-codec", "scale-info", "serde", "smallvec", - "sp-arithmetic 16.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", - "sp-core 21.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", - "sp-debug-derive 8.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", - "sp-std 8.0.0 (git+https://github.com/gear-tech/substrate.git?branch=gear-polkadot-v1.0.0-canary)", + "sp-arithmetic 17.0.0", + "sp-core 22.0.0", + "sp-debug-derive 9.0.0", + "sp-std 9.0.0", ] [[package]] @@ -7467,9 +7402,9 @@ dependencies = [ [[package]] name = "ss58-registry" -version = "1.46.0" +version = "1.47.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1114ee5900b8569bbc8b1a014a942f937b752af4b44f4607430b5f86cedaac0" +checksum = "4743ce898933fbff7bbf414f497c459a782d496269644b3d650a398ae6a487ba" dependencies = [ "Inflector", "num-format", @@ -7569,13 +7504,13 @@ dependencies = [ [[package]] name = "substrate-bip39" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e620c7098893ba667438b47169c00aacdd9e7c10e042250ce2b60b087ec97328" +checksum = "6a7590dc041b9bc2825e52ce5af8416c73dbe9d0654402bfd4b4941938b94d8f" dependencies = [ "hmac 0.11.0", "pbkdf2 0.8.0", - "schnorrkel 0.9.1", + "schnorrkel 0.11.4", "sha2 0.9.9", "zeroize", ] @@ -7640,7 +7575,7 @@ dependencies = [ "quote", "scale-info", "subxt-metadata", - "syn 2.0.48", + "syn 2.0.55", "thiserror", "tokio", ] @@ -7668,10 +7603,10 @@ version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12e8be9ab6fe88b8c13edbe15911e148482cfb905a8b8d5b8d766a64c54be0bd" dependencies = [ - "darling 0.20.5", + "darling 0.20.8", "proc-macro-error", "subxt-codegen", - "syn 2.0.48", + "syn 2.0.55", ] [[package]] @@ -7758,9 +7693,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.48" +version = "2.0.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" +checksum = "002a1b3dbf967edfafc32655d0f377ab0bb7b994aa1d32c8cc7e9b8bf3ebb8f0" dependencies = [ "proc-macro2", "quote", @@ -7873,20 +7808,19 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "target-lexicon" -version = "0.12.13" +version = "0.12.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69758bda2e78f098e4ccb393021a0963bb3442eac05f135c30f61b7370bbafae" +checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f" [[package]] name = "tempfile" -version = "3.9.0" +version = "3.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01ce4141aa927a6d1bd34a041795abd0db1cccba5d5f24b009f694bdf3a1f3fa" +checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" dependencies = [ "cfg-if", - "fastrand 2.0.1", - "redox_syscall", - "rustix 0.38.31", + "fastrand 2.0.2", + "rustix 0.38.32", "windows-sys 0.52.0", ] @@ -7922,9 +7856,9 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.56" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" +checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" dependencies = [ "thiserror-impl", ] @@ -7946,25 +7880,25 @@ checksum = "e4c60d69f36615a077cc7663b9cb8e42275722d23e58a7fa3d2c7f2915d09d04" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.55", ] [[package]] name = "thiserror-impl" -version = "1.0.56" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" +checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.55", ] [[package]] name = "thread_local" -version = "1.1.7" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" dependencies = [ "cfg-if", "once_cell", @@ -7975,7 +7909,7 @@ name = "tic-tac-toe" version = "1.1.0" dependencies = [ "gclient", - "gear-core 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gear-core 1.1.1", "gear-wasm-builder", "gmeta", "gstd", @@ -8051,7 +7985,7 @@ dependencies = [ "mio", "num_cpus", "pin-project-lite", - "socket2 0.5.5", + "socket2 0.5.6", "tokio-macros", "windows-sys 0.48.0", ] @@ -8064,7 +7998,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.55", ] [[package]] @@ -8079,9 +8013,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.14" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" +checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" dependencies = [ "futures-core", "pin-project-lite", @@ -8130,7 +8064,7 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.2.2", + "indexmap 2.2.6", "serde", "serde_spanned", "toml_datetime", @@ -8143,7 +8077,7 @@ version = "0.20.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" dependencies = [ - "indexmap 2.2.2", + "indexmap 2.2.6", "toml_datetime", "winnow", ] @@ -8195,7 +8129,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.55", ] [[package]] @@ -8329,9 +8263,9 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" dependencies = [ "tinyvec", ] @@ -8377,9 +8311,9 @@ dependencies = [ [[package]] name = "uuid" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a" +checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" [[package]] name = "valuable" @@ -8392,10 +8326,15 @@ name = "vara-man" version = "1.1.0" dependencies = [ "blake2-rfc", + "fungible-token", + "fungible-token-io", "gclient", + "gear-core 1.1.1", "gear-wasm-builder", "gstd", "gtest", + "hex", + "sp-core 22.0.0", "tokio", "vara-man-io", ] @@ -8416,7 +8355,7 @@ version = "1.1.0" dependencies = [ "fungible-token", "fungible-token-io", - "gear-core 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gear-core 1.1.1", "gear-wasm-builder", "gstd", "gtest", @@ -8443,6 +8382,7 @@ version = "1.1.0" dependencies = [ "gear-wasm-builder", "gstd", + "gtest", "w3bstreaming-io", ] @@ -8452,6 +8392,8 @@ version = "1.1.0" dependencies = [ "gmeta", "gstd", + "parity-scale-codec", + "scale-info", ] [[package]] @@ -8506,9 +8448,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.90" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1223296a201415c7fad14792dbefaace9bd52b62d33453ade1c5b5f07555406" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -8516,24 +8458,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.90" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcdc935b63408d58a32f8cc9738a0bffd8f05cc7c002086c6ef20b7312ad9dcd" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.55", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.90" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e4c238561b2d428924c49815533a8b9121c664599558a5d9ec51f8a1740a999" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -8541,28 +8483,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.90" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bae1abb6806dc1ad9e560ed242107c0f6c84335f1749dd4e8ddb012ebd5e25a7" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.55", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.90" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d91413b1c31d7539ba5ef2451af3f0b833a005eb27a631cec32bc0635a8602b" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] name = "wasm-encoder" -version = "0.41.0" +version = "0.201.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e09bca7d6388637d27fb5edbeab11f56bfabcef8743c55ae34370e1e5030a071" +checksum = "b9c7d2731df60006819b013f64ccc2019691deccf6e11a1804bc850cd6748f1a" dependencies = [ "leb128", ] @@ -9082,9 +9024,9 @@ dependencies = [ [[package]] name = "wast" -version = "70.0.2" +version = "201.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3d5061300042ff5065123dae1e27d00c03f567d34a2937c8472255148a216dc" +checksum = "1ef6e1ef34d7da3e2b374fd2b1a9c0227aff6cad596e1b24df9b58d0f6222faa" dependencies = [ "bumpalo", "leb128", @@ -9095,9 +9037,9 @@ dependencies = [ [[package]] name = "wat" -version = "1.0.85" +version = "1.201.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afd7357b6cc46d46a2509c43dcb1dd4131dafbf4e75562d87017b5a05ffad2d6" +checksum = "453d5b37a45b98dee4f4cb68015fc73634d7883bbef1c65e6e9c78d454cf3f32" dependencies = [ "wast", ] @@ -9117,7 +9059,7 @@ dependencies = [ "either", "home", "once_cell", - "rustix 0.38.31", + "rustix 0.38.32", ] [[package]] @@ -9157,7 +9099,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.52.0", + "windows-targets 0.52.4", ] [[package]] @@ -9197,7 +9139,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.0", + "windows-targets 0.52.4", ] [[package]] @@ -9232,17 +9174,17 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" dependencies = [ - "windows_aarch64_gnullvm 0.52.0", - "windows_aarch64_msvc 0.52.0", - "windows_i686_gnu 0.52.0", - "windows_i686_msvc 0.52.0", - "windows_x86_64_gnu 0.52.0", - "windows_x86_64_gnullvm 0.52.0", - "windows_x86_64_msvc 0.52.0", + "windows_aarch64_gnullvm 0.52.4", + "windows_aarch64_msvc 0.52.4", + "windows_i686_gnu 0.52.4", + "windows_i686_msvc 0.52.4", + "windows_x86_64_gnu 0.52.4", + "windows_x86_64_gnullvm 0.52.4", + "windows_x86_64_msvc 0.52.4", ] [[package]] @@ -9259,9 +9201,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" +checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" [[package]] name = "windows_aarch64_msvc" @@ -9283,9 +9225,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" +checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" [[package]] name = "windows_i686_gnu" @@ -9307,9 +9249,9 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" +checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" [[package]] name = "windows_i686_msvc" @@ -9331,9 +9273,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" +checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" [[package]] name = "windows_x86_64_gnu" @@ -9355,9 +9297,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" +checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" [[package]] name = "windows_x86_64_gnullvm" @@ -9373,9 +9315,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" +checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" [[package]] name = "windows_x86_64_msvc" @@ -9397,15 +9339,15 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" +checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" [[package]] name = "winnow" -version = "0.5.36" +version = "0.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "818ce546a11a9986bc24f93d0cdf38a8a1a400f1473ea8c82e59f6e0ffab9249" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" dependencies = [ "memchr", ] @@ -9465,7 +9407,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.55", ] [[package]] @@ -9485,5 +9427,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.55", ] diff --git a/contracts/auto-changed-nft/src/lib.rs b/contracts/auto-changed-nft/src/lib.rs index de456ff4c..652da3754 100644 --- a/contracts/auto-changed-nft/src/lib.rs +++ b/contracts/auto-changed-nft/src/lib.rs @@ -56,10 +56,9 @@ unsafe extern fn init() { } #[no_mangle] -unsafe extern fn handle() { +extern fn handle() { let action: NFTAction = msg::load().expect("Could not load NFTAction"); - let nft = CONTRACT.get_or_insert(Default::default()); - gstd::debug!("NFTAction: {:?}", &action); + let nft = unsafe { CONTRACT.get_or_insert(Default::default()) }; match action { NFTAction::Mint { transaction_id, @@ -194,11 +193,6 @@ unsafe extern fn handle() { rest_updates_count, token_ids, } => { - gstd::debug!( - "Update rest_updates_count: {}, token_ids: {:?}", - rest_updates_count, - token_ids - ); nft.rest_updates_count = rest_updates_count - 1; nft.update_media(&token_ids); if nft.rest_updates_count == 0 { @@ -209,9 +203,8 @@ unsafe extern fn handle() { token_ids, }; let gas_available = exec::gas_available(); - gstd::debug!("Update. gas_available: {}", gas_available); if gas_available <= GAS_FOR_UPDATE { - let reservations = unsafe { &mut RESERVATION }; + let reservations: &mut Vec = unsafe { RESERVATION.as_mut() }; let reservation_id = reservations.pop().expect("Need more gas"); send_delayed_from_reservation( reservation_id, @@ -240,16 +233,9 @@ unsafe extern fn handle() { rest_updates_count: updates_count, token_ids: token_ids.clone(), }; - let message_id = send_delayed(exec::program_id(), &payload, 0, update_period) + send_delayed(exec::program_id(), payload, 0, update_period) .expect("Can't send delayed"); nft.reserve_gas(); - gstd::debug!( - "send_delayed payload: message_id: {:?}, {:?}, update_period: {} token_ids: {:?}", - message_id, - payload, - update_period, - token_ids - ); } }; } @@ -325,19 +311,12 @@ impl AutoChangedNft { let urls_for_token = &self.urls[token_id]; let index = self.rest_updates_count as usize % urls_for_token.len(); let media = urls_for_token[index].clone(); - gstd::debug!( - "update_media(): urls.len(): {}, token_id: {}, index: {}, media: {}", - urls_for_token.len(), - token_id, - index, - media - ); meta.media = media } } } fn reserve_gas(&self) { - let reservations = unsafe { &mut RESERVATION }; + let reservations: &mut Vec = unsafe { RESERVATION.as_mut() }; let reservation_id = ReservationId::reserve(RESERVATION_AMOUNT, 600).expect("reservation across executions"); reservations.push(reservation_id); diff --git a/contracts/battleship/io/src/lib.rs b/contracts/battleship/io/src/lib.rs index debe66810..f76df9b81 100644 --- a/contracts/battleship/io/src/lib.rs +++ b/contracts/battleship/io/src/lib.rs @@ -14,7 +14,7 @@ pub struct BattleshipMetadata; impl Metadata for BattleshipMetadata { type Init = In; - type Handle = InOut; + type Handle = InOut>; type Others = (); type Reply = (); type Signal = (); @@ -130,12 +130,36 @@ pub struct Config { } #[derive(Debug, Clone, Encode, Decode, TypeInfo)] pub enum BattleshipReply { + GameFinished(BattleshipParticipants), MessageSentToBot, - EndGame(BattleshipParticipants), BotChanged(ActorId), SessionCreated, SessionDeleted, ConfigUpdated, + StateCleared, + GameDeleted, +} + +#[derive(Debug, Clone, Encode, Decode, TypeInfo)] +pub enum BattleshipError { + GameIsAlreadyStarted, + GameIsNotStarted, + IncorrectLocationShips, + OutOfBounds, + GameIsAlreadyOver, + ThisCellAlreadyKnown, + BotDidNotInitializeBoard, + NotYourTurn, + NotAdmin, + WrongLength, + AccessDenied, + AlreadyHaveActiveSession, + NoMessagesForApprovalWerePassed, + DurationIsSmall, + HasNotValidSession, + SessionHasAlreadyExpired, + MessageIsNotAllowed, + NotApproved, } #[derive(Debug, Clone, Encode, Decode, TypeInfo)] @@ -169,7 +193,7 @@ pub struct Game { impl Game { pub fn start_bot(&mut self, mut ships: Ships) { - let bot_board = ships.get_field(); + let bot_board = ships.get_field().unwrap(); self.bot_board = bot_board; ships.sort_by_length(); self.bot_ships = ships; @@ -332,20 +356,19 @@ impl Ships { let has_non_empty = !vectors.iter().any(|vector: &&Vec| !vector.is_empty()); has_non_empty } - pub fn get_field(&self) -> Vec { + pub fn get_field(&self) -> Result, BattleshipError> { let mut board = vec![Entity::Empty; 25]; for position in self.iter() { - assert!( - board[*position as usize] != Entity::Ship, - "Incorrect location of ships" - ); + if board[*position as usize] == Entity::Ship { + return Err(BattleshipError::IncorrectLocationShips); + } board[*position as usize] = Entity::Ship; } - board + Ok(board) } - pub fn check_correct_location(&self) -> bool { + pub fn check_correct_location(&self) -> Result<(), BattleshipError> { if self.iter().any(|&position| position > 24) { - return false; + return Err(BattleshipError::OutOfBounds); } // ship size check let mut vec_len = vec![ @@ -356,10 +379,11 @@ impl Ships { ]; vec_len.sort(); if vec_len != vec![1, 2, 2, 3] { - return false; + return Err(BattleshipError::WrongLength); } - let mut field = self.get_field(); - let mut ships = vec![ + + let mut field = self.get_field()?; + let mut ships = [ self.ship_1.clone(), self.ship_2.clone(), self.ship_3.clone(), @@ -372,13 +396,13 @@ impl Ships { match (ship.len(), distance) { (1, 0) | (2, 1) | (2, 5) => (), (3, 2) | (3, 10) if (ship[2] + ship[0]) % ship[1] == 0 => (), - _ => return false, + _ => return Err(BattleshipError::IncorrectLocationShips), } // checking the distance between ships let mut occupy_cells = vec![]; for position in ship { if field[*position as usize] == Entity::Occupied { - return false; + return Err(BattleshipError::IncorrectLocationShips); } let cells = match *position { 0 => vec![1, 5, 6], @@ -403,7 +427,7 @@ impl Ships { } } - true + Ok(()) } pub fn count_alive_ships(&self) -> Vec<(u8, u8)> { diff --git a/contracts/battleship/src/contract.rs b/contracts/battleship/src/contract.rs index 1015f9544..672fca5f2 100644 --- a/contracts/battleship/src/contract.rs +++ b/contracts/battleship/src/contract.rs @@ -25,11 +25,10 @@ impl Battleship { key: &ActorId, duration: u64, allowed_actions: Vec, - ) { - assert!( - duration >= MINIMUM_SESSION_SURATION_MS, - "Duration is too small" - ); + ) -> Result { + if duration < MINIMUM_SESSION_SURATION_MS { + return Err(BattleshipError::DurationIsSmall); + } let msg_source = msg::source(); let block_timestamp = exec::block_timestamp(); @@ -40,7 +39,7 @@ impl Battleship { }) = self.sessions.get(&msg_source) { if *expires > block_timestamp { - panic!("You already have an active session. If you want to create a new one, please delete this one.") + return Err(BattleshipError::AlreadyHaveActiveSession); } } @@ -49,10 +48,9 @@ impl Battleship { let number_of_blocks = u32::try_from(duration.div_ceil(self.config.block_duration_ms)) .expect("Duration is too large"); - assert!( - !allowed_actions.is_empty(), - "No messages for approval were passed." - ); + if allowed_actions.is_empty() { + return Err(BattleshipError::NoMessagesForApprovalWerePassed); + } self.sessions.entry(msg_source).insert(Session { key: *key, @@ -71,44 +69,46 @@ impl Battleship { ) .expect("Error in sending a delayed msg"); - msg::reply(BattleshipReply::SessionCreated, 0).expect("Error in sending a reply"); + Ok(BattleshipReply::SessionCreated) } - fn delete_session_from_program(&mut self, session_for_account: &ActorId) { - assert_eq!( - exec::program_id(), - msg::source(), - "The msg source must be the program" - ); + fn delete_session_from_program( + &mut self, + session_for_account: &ActorId, + ) -> Result { + if exec::program_id() != msg::source() { + return Err(BattleshipError::AccessDenied); + } if let Some(session) = self.sessions.remove(session_for_account) { - assert!( - session.expires <= exec::block_timestamp(), - "Too early to delete session" - ); + if session.expires > exec::block_timestamp() { + return Err(BattleshipError::AccessDenied); + } } - - msg::reply(BattleshipReply::SessionDeleted, 0).expect("Error in sending a reply"); + Ok(BattleshipReply::SessionDeleted) } - fn delete_session_from_account(&mut self) { - assert!(self.sessions.remove(&msg::source()).is_some(), "No session"); - - msg::reply(BattleshipReply::SessionDeleted, 0).expect("Error in sending a reply"); + fn delete_session_from_account(&mut self) -> Result { + self.sessions.remove(&msg::source()); + Ok(BattleshipReply::SessionDeleted) } - fn start_game(&mut self, mut ships: Ships, session_for_account: Option) { - let player = self.get_player(&session_for_account, ActionsForSession::StartGame); + fn start_game( + &mut self, + mut ships: Ships, + session_for_account: Option, + ) -> Result { + let player = self.get_player(&session_for_account, ActionsForSession::StartGame)?; + if let Some(game) = self.games.get(&player) { - assert!(game.game_over, "Please finish the previous game"); + if !game.game_over { + return Err(BattleshipError::GameIsAlreadyStarted); + } } - assert!( - ships.check_correct_location(), - "Incorrect location of ships" - ); + ships.check_correct_location()?; + let player_board = ships.get_field()?; - let player_board = ships.get_field(); ships.sort_by_length(); let game_instance = Game { player_board, @@ -131,32 +131,38 @@ impl Battleship { .expect("Error in sending a message"); self.msg_id_to_game_id.insert(msg_id, player); - msg::reply(BattleshipReply::MessageSentToBot, 0).expect("Error in sending a reply"); + Ok(BattleshipReply::MessageSentToBot) } - fn player_move(&mut self, step: u8, session_for_account: Option) { - let player = self.get_player(&session_for_account, ActionsForSession::Turn); - assert!(step < 25, "Step must be less than 24"); - - let game = self - .games - .get_mut(&player) - .expect("The player has no game, please start the game"); + fn player_move( + &mut self, + step: u8, + session_for_account: Option, + ) -> Result { + let player = self.get_player(&session_for_account, ActionsForSession::Turn)?; + if step > 24 { + return Err(BattleshipError::OutOfBounds); + } - assert!(!game.game_over, "Game is already over"); + let Some(game) = self.games.get_mut(&player) else { + return Err(BattleshipError::GameIsNotStarted); + }; + if game.game_over { + return Err(BattleshipError::GameIsAlreadyOver); + } if game.bot_board.is_empty() { - panic!("The bot did not initialize the board"); + return Err(BattleshipError::BotDidNotInitializeBoard); } if game.turn != Some(BattleshipParticipants::Player) { - panic!("Please wait your turn"); + return Err(BattleshipError::NotYourTurn); } if game.bot_board[step as usize] != Entity::Empty && game.bot_board[step as usize] != Entity::Ship { - panic!("The value of this cell is already known"); + return Err(BattleshipError::ThisCellAlreadyKnown); } let res = game.bot_ships.bang(step); @@ -166,13 +172,14 @@ impl Battleship { Step::Killed => game.dead_ship(step, 1), } game.total_shots += 1; + if game.bot_ships.check_end_game() { game.game_over = true; game.game_result = Some(BattleshipParticipants::Player); game.end_time = exec::block_timestamp(); - msg::reply(BattleshipReply::EndGame(BattleshipParticipants::Player), 0) - .expect("Error in sending a reply"); - return; + return Ok(BattleshipReply::GameFinished( + BattleshipParticipants::Player, + )); } game.turn = Some(BattleshipParticipants::Bot); @@ -186,67 +193,70 @@ impl Battleship { .expect("Error in sending a message"); self.msg_id_to_game_id.insert(msg_id, player); - msg::reply(BattleshipReply::MessageSentToBot, 0).expect("Error in sending a reply"); + Ok(BattleshipReply::MessageSentToBot) } - fn change_bot(&mut self, bot: ActorId) { - assert!( - msg::source() == self.admin, - "Only the admin can change the bot's contract address" - ); + fn change_bot(&mut self, bot: ActorId) -> Result { + if msg::source() != self.admin { + return Err(BattleshipError::NotAdmin); + } self.bot_address = bot; - msg::reply(BattleshipReply::BotChanged(bot), 0).expect("Error in sending a reply"); + Ok(BattleshipReply::BotChanged(bot)) } - fn clear_state(&mut self, leave_active_games: bool) { - assert!( - msg::source() == self.admin, - "Only the admin can change the contract state" - ); + fn clear_state( + &mut self, + leave_active_games: bool, + ) -> Result { + if msg::source() != self.admin { + return Err(BattleshipError::NotAdmin); + } if leave_active_games { self.games.retain(|_actor_id, game| !game.game_over); } else { self.games.clear(); } + Ok(BattleshipReply::StateCleared) } - fn delete_game(&mut self, player_address: ActorId) { - assert!( - msg::source() == self.admin, - "Only the admin can change the contract state" - ); + fn delete_game(&mut self, player_address: ActorId) -> Result { + if msg::source() != self.admin { + return Err(BattleshipError::NotAdmin); + } self.games.remove(&player_address); + Ok(BattleshipReply::GameDeleted) } fn get_player( &self, session_for_account: &Option, actions_for_session: ActionsForSession, - ) -> ActorId { + ) -> Result { let msg_source = msg::source(); let player = match session_for_account { Some(account) => { let session = self .sessions .get(account) - .expect("This account has no valid session"); - assert!( - session.expires > exec::block_timestamp(), - "The session has already expired" - ); - assert!( - session.allowed_actions.contains(&actions_for_session), - "This message is not allowed" - ); - assert_eq!( - session.key, msg_source, - "The account is not approved for this session" - ); + .ok_or(BattleshipError::HasNotValidSession)?; + + if session.expires <= exec::block_timestamp() { + return Err(BattleshipError::SessionHasAlreadyExpired); + } + if !session.allowed_actions.contains(&actions_for_session) { + return Err(BattleshipError::MessageIsNotAllowed); + } + if session.expires <= exec::block_timestamp() { + return Err(BattleshipError::SessionHasAlreadyExpired); + } + if session.key != msg_source { + return Err(BattleshipError::NotApproved); + } *account } None => msg_source, }; - player + Ok(player) } fn update_config( @@ -255,12 +265,10 @@ impl Battleship { gas_for_move: Option, gas_to_delete_session: Option, block_duration_ms: Option, - ) { - assert_eq!( - msg::source(), - self.admin, - "Only admin can change configurable parameters" - ); + ) -> Result { + if msg::source() != self.admin { + return Err(BattleshipError::NotAdmin); + } if let Some(gas_for_start) = gas_for_start { self.config.gas_for_start = gas_for_start; } @@ -276,8 +284,7 @@ impl Battleship { if let Some(block_duration_ms) = block_duration_ms { self.config.block_duration_ms = block_duration_ms; } - - msg::reply(BattleshipReply::ConfigUpdated, 0).expect("Error in sending a reply"); + Ok(BattleshipReply::ConfigUpdated) } } @@ -306,7 +313,7 @@ extern fn handle() { }; let action: BattleshipAction = msg::load().expect("Failed to decode `BattleshipAction` message."); - match action { + let reply = match action { BattleshipAction::StartGame { ships, session_for_account, @@ -340,7 +347,9 @@ extern fn handle() { gas_to_delete_session, block_duration_ms, ), - } + }; + msg::reply(reply, 0) + .expect("Failed to encode or reply with `Result`."); } #[no_mangle] @@ -376,7 +385,7 @@ extern fn handle_reply() { game.end_time = exec::block_timestamp(); msg::send( game_id, - BattleshipReply::EndGame(BattleshipParticipants::Bot), + BattleshipReply::GameFinished(BattleshipParticipants::Bot), 0, ) .expect("Unable to send the message about game over"); diff --git a/contracts/battleship/tests/test.rs b/contracts/battleship/tests/test.rs index 8c89bf44a..1a0cd86cb 100644 --- a/contracts/battleship/tests/test.rs +++ b/contracts/battleship/tests/test.rs @@ -1,6 +1,7 @@ use battleship_io::{ - ActionsForSession, BattleshipAction, BattleshipInit, BattleshipParticipants, BattleshipReply, - Config, Entity, GameState, Session, Ships, StateQuery, StateReply, MINIMUM_SESSION_SURATION_MS, + ActionsForSession, BattleshipAction, BattleshipError, BattleshipInit, BattleshipParticipants, + BattleshipReply, Config, Entity, GameState, Session, Ships, StateQuery, StateReply, + MINIMUM_SESSION_SURATION_MS, }; use gstd::prelude::*; use gtest::{Program, System}; @@ -51,7 +52,11 @@ fn failures_location_ships() { session_for_account: None, }, ); - assert!(res.main_failed()); + assert!(!res.main_failed()); + assert!(res.contains(&( + 3, + Err::(BattleshipError::OutOfBounds).encode() + ))); // wrong ship size let ships = Ships { ship_1: vec![19], @@ -66,7 +71,11 @@ fn failures_location_ships() { session_for_account: None, }, ); - assert!(res.main_failed()); + assert!(!res.main_failed()); + assert!(res.contains(&( + 3, + Err::(BattleshipError::WrongLength).encode() + ))); // ship crossing let ships = Ships { ship_1: vec![1], @@ -81,7 +90,11 @@ fn failures_location_ships() { session_for_account: None, }, ); - assert!(res.main_failed()); + assert!(!res.main_failed()); + assert!(res.contains(&( + 3, + Err::(BattleshipError::IncorrectLocationShips).encode() + ))); // the ship isn't solid let ships = Ships { ship_1: vec![19], @@ -96,7 +109,11 @@ fn failures_location_ships() { session_for_account: None, }, ); - assert!(res.main_failed()); + assert!(!res.main_failed()); + assert!(res.contains(&( + 3, + Err::(BattleshipError::IncorrectLocationShips).encode() + ))); // the distance between the ships is not maintained let ships = Ships { ship_1: vec![5], @@ -111,7 +128,11 @@ fn failures_location_ships() { session_for_account: None, }, ); - assert!(res.main_failed()); + assert!(!res.main_failed()); + assert!(res.contains(&( + 3, + Err::(BattleshipError::IncorrectLocationShips).encode() + ))); } #[test] @@ -129,7 +150,11 @@ fn failures_test() { session_for_account: None, }, ); - assert!(res.main_failed()); + assert!(!res.main_failed()); + assert!(res.contains(&( + 3, + Err::(BattleshipError::GameIsNotStarted).encode() + ))); let ships = Ships { ship_1: vec![19], @@ -159,7 +184,11 @@ fn failures_test() { session_for_account: None, }, ); - assert!(res.main_failed()); + assert!(!res.main_failed()); + assert!(res.contains(&( + 3, + Err::(BattleshipError::GameIsAlreadyStarted).encode() + ))); // outfield let res = battleship.send( 3, @@ -168,11 +197,19 @@ fn failures_test() { session_for_account: None, }, ); - assert!(res.main_failed()); + assert!(!res.main_failed()); + assert!(res.contains(&( + 3, + Err::(BattleshipError::OutOfBounds).encode() + ))); // only the admin can change the bot's contract address let res = battleship.send(4, BattleshipAction::ChangeBot { bot: 8.into() }); - assert!(res.main_failed()); + assert!(!res.main_failed()); + assert!(res.contains(&( + 4, + Err::(BattleshipError::NotAdmin).encode() + ))); let steps: Vec = (0..25).collect(); for step in steps { @@ -201,7 +238,12 @@ fn failures_test() { session_for_account: None, }, ); - assert!(res.main_failed()); + assert!(!res.main_failed()); + assert!(res.contains(&( + 3, + Err::(BattleshipError::GameIsAlreadyOver) + .encode() + ))); } } } @@ -280,7 +322,10 @@ fn create_session_success() { }, ); - assert!(res.contains(&(main_account, BattleshipReply::SessionCreated.encode()))); + assert!(res.contains(&( + main_account, + Ok::(BattleshipReply::SessionCreated).encode() + ))); check_session_in_state(&battleship, main_account, Some(session)); } @@ -329,7 +374,11 @@ fn create_session_failures() { }, ); - assert!(res.main_failed()); + assert!(!res.main_failed()); + assert!(res.contains(&( + main_account, + Err::(BattleshipError::DurationIsSmall).encode() + ))); // there are no allowed actions (empty array of allowed_actions). let duration = MINIMUM_SESSION_SURATION_MS; @@ -344,7 +393,12 @@ fn create_session_failures() { }, ); - assert!(res.main_failed()); + assert!(!res.main_failed()); + assert!(res.contains(&( + main_account, + Err::(BattleshipError::NoMessagesForApprovalWerePassed) + .encode() + ))); // The user already has a current active session. let allowed_actions = vec![ActionsForSession::StartGame, ActionsForSession::Turn]; @@ -358,7 +412,10 @@ fn create_session_failures() { }, ); - assert!(res.contains(&(main_account, BattleshipReply::SessionCreated.encode()))); + assert!(res.contains(&( + main_account, + Ok::(BattleshipReply::SessionCreated).encode() + ))); let res = battleship.send( main_account, BattleshipAction::CreateSession { @@ -367,7 +424,12 @@ fn create_session_failures() { allowed_actions, }, ); - assert!(res.main_failed()); + + assert!(!res.main_failed()); + assert!(res.contains(&( + main_account, + Err::(BattleshipError::AlreadyHaveActiveSession).encode() + ))); } // This function tests the mechanism where, upon creating a session, a delayed message is sent. @@ -399,7 +461,10 @@ fn session_deletion_on_expiration() { }, ); - assert!(res.contains(&(main_account, BattleshipReply::SessionCreated.encode()))); + assert!(res.contains(&( + main_account, + Ok::(BattleshipReply::SessionCreated).encode() + ))); system.spend_blocks((number_of_blocks as u32) + 1); @@ -436,7 +501,10 @@ fn disallow_game_without_required_actions() { }, ); - assert!(res.contains(&(main_account, BattleshipReply::SessionCreated.encode()))); + assert!(res.contains(&( + main_account, + Ok::(BattleshipReply::SessionCreated).encode() + ))); check_session_in_state(&battleship, main_account, Some(session)); @@ -456,11 +524,18 @@ fn disallow_game_without_required_actions() { }, ); - assert!(res.main_failed()); + assert!(!res.main_failed()); + assert!(res.contains(&( + proxy_account, + Err::(BattleshipError::MessageIsNotAllowed).encode() + ))); // delete session and create a new one let res = battleship.send(main_account, BattleshipAction::DeleteSessionFromAccount); - assert!(res.contains(&(main_account, BattleshipReply::SessionDeleted.encode()))); + assert!(res.contains(&( + main_account, + Ok::(BattleshipReply::SessionDeleted).encode() + ))); check_session_in_state(&battleship, main_account, None); @@ -479,7 +554,10 @@ fn disallow_game_without_required_actions() { }, ); - assert!(res.contains(&(main_account, BattleshipReply::SessionCreated.encode()))); + assert!(res.contains(&( + main_account, + Ok::(BattleshipReply::SessionCreated).encode() + ))); check_session_in_state(&battleship, main_account, Some(session)); @@ -492,7 +570,10 @@ fn disallow_game_without_required_actions() { }, ); - assert!(res.contains(&(proxy_account, BattleshipReply::MessageSentToBot.encode()))); + assert!(res.contains(&( + proxy_account, + Ok::(BattleshipReply::MessageSentToBot).encode() + ))); // must fail since `Turn` wasn't indicated in the `allowed_actions` let steps: Vec = (0..25).collect(); @@ -509,7 +590,12 @@ fn disallow_game_without_required_actions() { session_for_account: Some(main_account.into()), }, ); - assert!(res.main_failed()); + assert!(!res.main_failed()); + assert!(res.contains(&( + proxy_account, + Err::(BattleshipError::MessageIsNotAllowed) + .encode() + ))); } } } @@ -542,7 +628,10 @@ fn complete_session_game() { }, ); - assert!(res.contains(&(main_account, BattleshipReply::SessionCreated.encode()))); + assert!(res.contains(&( + main_account, + Ok::(BattleshipReply::SessionCreated).encode() + ))); check_session_in_state(&battleship, main_account, Some(session)); @@ -562,7 +651,10 @@ fn complete_session_game() { }, ); - assert!(res.contains(&(proxy_account, BattleshipReply::MessageSentToBot.encode()))); + assert!(res.contains(&( + proxy_account, + Ok::(BattleshipReply::MessageSentToBot).encode() + ))); let steps: Vec = (0..25).collect(); for step in steps { @@ -582,10 +674,17 @@ fn complete_session_game() { if game.game_over { assert!(res.contains(&( proxy_account, - BattleshipReply::EndGame(BattleshipParticipants::Player).encode() + Ok::(BattleshipReply::GameFinished( + BattleshipParticipants::Player + )) + .encode() ))); } else { - assert!(res.contains(&(proxy_account, BattleshipReply::MessageSentToBot.encode()))); + assert!(res.contains(&( + proxy_account, + Ok::(BattleshipReply::MessageSentToBot) + .encode() + ))); } } } @@ -620,19 +719,21 @@ fn premature_session_deletion_by_user() { }, ); - assert!(res.contains(&(main_account, BattleshipReply::SessionCreated.encode()))); + assert!(res.contains(&( + main_account, + Ok::(BattleshipReply::SessionCreated).encode() + ))); check_session_in_state(&battleship, main_account, Some(session)); // delete session let res = battleship.send(main_account, BattleshipAction::DeleteSessionFromAccount); - assert!(res.contains(&(main_account, BattleshipReply::SessionDeleted.encode()))); + assert!(res.contains(&( + main_account, + Ok::(BattleshipReply::SessionDeleted).encode() + ))); check_session_in_state(&battleship, main_account, None); - - // fails since a user is trying to delete a non-existent session - let res = battleship.send(main_account, BattleshipAction::DeleteSessionFromAccount); - assert!(res.main_failed()); } fn check_session_in_state(battleship: &Program<'_>, account: u64, session: Option) { diff --git a/contracts/battleship/tests/test_node.rs b/contracts/battleship/tests/test_node.rs index 43ae13f17..fcbd9dd3e 100644 --- a/contracts/battleship/tests/test_node.rs +++ b/contracts/battleship/tests/test_node.rs @@ -134,7 +134,6 @@ async fn gclient_turn_test() -> Result<()> { 0, ) .await?; - let init_battleship = BattleshipInit { bot_address: bot_actor_id.into(), config: Config { @@ -156,7 +155,6 @@ async fn gclient_turn_test() -> Result<()> { true, ) .await?; - let (message_id, program_id, _hash) = api .upload_program_bytes( gclient::code_from_os(path)?, @@ -169,50 +167,48 @@ async fn gclient_turn_test() -> Result<()> { assert!(listener.message_processed(message_id).await?.succeed()); - for _i in 1..3 { - let ships = Ships { - ship_1: vec![19], - ship_2: vec![0, 1, 2], - ship_3: vec![4, 9], - ship_4: vec![16, 21], - }; - let start_payload = BattleshipAction::StartGame { - ships, - session_for_account: None, - }; - - let gas_info = api - .calculate_handle_gas(None, program_id, start_payload.encode(), 0, true) - .await?; - - let (message_id, _) = api - .send_message(program_id, start_payload, gas_info.min_limit, 0) - .await?; - - assert!(listener.message_processed(message_id).await?.succeed()); - assert!(listener.blocks_running().await?); - let steps: Vec = (0..25).collect(); - for step in steps { - let state = get_all_state(&api, &program_id) - .await - .expect("Unexpected invalid state."); - if (state.games[0].1.bot_board[step as usize] == Entity::Empty - || state.games[0].1.bot_board[step as usize] == Entity::Ship) - && !state.games[0].1.game_over - { - let turn_payload = BattleshipAction::Turn { - step, - session_for_account: None, - }; - let gas_info = api - .calculate_handle_gas(None, program_id, turn_payload.encode(), 0, true) - .await?; - let (message_id, _) = api - .send_message(program_id, turn_payload, gas_info.min_limit, 0) - .await?; - assert!(listener.message_processed(message_id).await?.succeed()); - assert!(listener.blocks_running().await?); - } + let ships = Ships { + ship_1: vec![19], + ship_2: vec![0, 1, 2], + ship_3: vec![4, 9], + ship_4: vec![16, 21], + }; + let start_payload = BattleshipAction::StartGame { + ships, + session_for_account: None, + }; + + let gas_info = api + .calculate_handle_gas(None, program_id, start_payload.encode(), 0, true) + .await?; + + let (message_id, _) = api + .send_message(program_id, start_payload, gas_info.min_limit, 0) + .await?; + + assert!(listener.message_processed(message_id).await?.succeed()); + assert!(listener.blocks_running().await?); + let steps: Vec = (0..25).collect(); + for step in steps { + let state = get_all_state(&api, &program_id) + .await + .expect("Unexpected invalid state."); + if (state.games[0].1.bot_board[step as usize] == Entity::Empty + || state.games[0].1.bot_board[step as usize] == Entity::Ship) + && !state.games[0].1.game_over + { + let turn_payload = BattleshipAction::Turn { + step, + session_for_account: None, + }; + let gas_info = api + .calculate_handle_gas(None, program_id, turn_payload.encode(), 0, true) + .await?; + let (message_id, _) = api + .send_message(program_id, turn_payload, gas_info.min_limit, 0) + .await?; + assert!(listener.message_processed(message_id).await?.succeed()); + assert!(listener.blocks_running().await?); } } diff --git a/contracts/car-races/io/src/lib.rs b/contracts/car-races/io/src/lib.rs index 90e8892c0..2e53e8a8d 100644 --- a/contracts/car-races/io/src/lib.rs +++ b/contracts/car-races/io/src/lib.rs @@ -54,7 +54,7 @@ impl Metadata for ContractMetadata { /// /// We use the [`GameAction`] type for incoming and [`GameReply`] for outgoing /// messages. - type Handle = InOut; + type Handle = InOut>; /// Asynchronous handle message type. /// /// Describes incoming/outgoing types for the `main()` function in case of @@ -200,12 +200,26 @@ pub enum CarAction { #[derive(Encode, Decode, TypeInfo, PartialEq, Eq)] pub enum GameReply { - GameStarted, - NotEnoughGas, GameFinished, - GasReserved, + GameStarted, StrategyAdded, - PlayersMove, + MoveMade, + GameInstanceRemoved, + InstancesRemoved, + AdminAdded, + AdminRemoved, + ConfigUpdated, + StatusMessagesUpdated, +} + +#[derive(Debug, Clone, Encode, Decode, TypeInfo)] +pub enum GameError { + NotAdmin, + MustBeTwoStrategies, + GameAlreadyStarted, + NotPlayerTurn, + NotProgram, + MessageProcessingSuspended, } impl Game { diff --git a/contracts/car-races/src/lib.rs b/contracts/car-races/src/lib.rs index d76b7a454..4684a02a9 100644 --- a/contracts/car-races/src/lib.rs +++ b/contracts/car-races/src/lib.rs @@ -21,34 +21,40 @@ pub struct Contract { } impl Contract { - fn add_strategy_ids(&mut self, car_ids: Vec) { - assert!(self.admins.contains(&msg::source()), "You are not admin"); - - assert!(car_ids.len() == 2, "There must be 2 strategies of cars"); + fn add_strategy_ids( + &mut self, + msg_src: &ActorId, + car_ids: Vec, + ) -> Result { + if !self.admins.contains(msg_src) { + return Err(GameError::NotAdmin); + } + if car_ids.len() != 2 { + return Err(GameError::MustBeTwoStrategies); + } self.strategy_ids = car_ids; + Ok(GameReply::StrategyAdded) } - fn start_game(&mut self) { - let player = msg::source(); - + fn start_game(&mut self, msg_src: &ActorId) -> Result { let last_time_step = exec::block_timestamp(); - let game = if let Some(game) = self.games.get_mut(&player) { + let game = if let Some(game) = self.games.get_mut(msg_src) { if game.state != GameState::Finished { - panic!("Please complete the game"); + return Err(GameError::GameAlreadyStarted); } game.current_round = 0; game.result = None; game.last_time_step = last_time_step; game } else { - self.games.entry(player).or_insert_with(|| Game { + self.games.entry(*msg_src).or_insert_with(|| Game { last_time_step, ..Default::default() }) }; - game.car_ids = vec![player, self.strategy_ids[0], self.strategy_ids[1]]; + game.car_ids = vec![*msg_src, self.strategy_ids[0], self.strategy_ids[1]]; let initial_state = Car { position: 0, speed: self.config.initial_speed, @@ -56,24 +62,25 @@ impl Contract { round_result: None, }; - game.cars.insert(player, initial_state.clone()); + game.cars.insert(*msg_src, initial_state.clone()); game.cars .insert(self.strategy_ids[0], initial_state.clone()); game.cars.insert(self.strategy_ids[1], initial_state); game.state = GameState::PlayerAction; - msg::reply(GameReply::GameStarted, 0).expect("Error during reply"); + Ok(GameReply::GameStarted) } - fn player_move(&mut self, strategy_move: StrategyAction) { - let player = msg::source(); - let game = self.get_game(&player); + fn player_move( + &mut self, + msg_src: &ActorId, + strategy_move: StrategyAction, + ) -> Result { + let game = self.get_game(msg_src); - assert_eq!( - game.state, - GameState::PlayerAction, - "Not time for the player" - ); + if game.state != GameState::PlayerAction { + return Err(GameError::NotPlayerTurn); + } match strategy_move { StrategyAction::BuyAcceleration => { game.buy_acceleration(); @@ -100,15 +107,14 @@ impl Contract { ) .expect("Error in sending a message"); - self.msg_id_to_game_id.insert(msg_id, player); + self.msg_id_to_game_id.insert(msg_id, *msg_src); + Ok(GameReply::MoveMade) } - fn play(&mut self, account: &ActorId) { - assert_eq!( - msg::source(), - exec::program_id(), - "Only program can send this message" - ); + fn play(&mut self, msg_src: &ActorId, account: &ActorId) -> Result { + if *msg_src != exec::program_id() { + return Err(GameError::NotProgram); + } let game = self.get_game(account); @@ -118,7 +124,7 @@ impl Contract { let car_ids = game.car_ids.clone(); self.send_messages(account); send_message_round_info(&car_ids[0], &cars, &result); - return; + return Ok(GameReply::GameFinished); } if game.current_turn == 0 { game.state = GameState::PlayerAction; @@ -126,7 +132,7 @@ impl Contract { let cars = game.cars.clone(); let car_ids = game.car_ids.clone(); send_message_round_info(&car_ids[0], &cars, &result); - return; + return Ok(GameReply::MoveMade); } let car_id = game.get_current_car_id(); @@ -135,6 +141,7 @@ impl Contract { .expect("Error in sending a message"); self.msg_id_to_game_id.insert(msg_id, *account); + Ok(GameReply::MoveMade) } fn get_game(&mut self, account: &ActorId) -> &mut Game { @@ -154,12 +161,14 @@ impl Contract { .expect("Error in sending message"); } - fn remove_game_instance(&mut self, account: &ActorId) { - assert_eq!( - msg::source(), - exec::program_id(), - "This message can be sent only by the program" - ); + fn remove_game_instance( + &mut self, + msg_src: &ActorId, + account: &ActorId, + ) -> Result { + if *msg_src != exec::program_id() { + return Err(GameError::NotProgram); + } let game = self .games .get(account) @@ -168,13 +177,17 @@ impl Contract { if game.state == GameState::Finished { self.games.remove(account); } + Ok(GameReply::GameInstanceRemoved) } - fn remove_instances(&mut self, player_ids: Option>) { - assert!( - self.admins.contains(&msg::source()), - "Only admin can send this message" - ); + fn remove_instances( + &mut self, + msg_src: &ActorId, + player_ids: Option>, + ) -> Result { + if !self.admins.contains(msg_src) { + return Err(GameError::NotAdmin); + } match player_ids { Some(player_ids) => { for player_id in player_ids { @@ -188,6 +201,88 @@ impl Contract { }); } } + Ok(GameReply::InstancesRemoved) + } + fn add_admin(&mut self, msg_src: &ActorId, admin: ActorId) -> Result { + if !self.admins.contains(msg_src) { + return Err(GameError::NotAdmin); + } + self.admins.push(admin); + Ok(GameReply::AdminAdded) + } + fn remove_admin(&mut self, msg_src: &ActorId, admin: ActorId) -> Result { + if !self.admins.contains(msg_src) { + return Err(GameError::NotAdmin); + } + self.admins.retain(|id| *id != admin); + Ok(GameReply::AdminRemoved) + } + #[allow(clippy::too_many_arguments)] + fn update_config( + &mut self, + msg_src: &ActorId, + gas_to_remove_game: Option, + initial_speed: Option, + min_speed: Option, + max_speed: Option, + gas_for_round: Option, + time_interval: Option, + max_distance: Option, + time: Option, + time_for_game_storage: Option, + ) -> Result { + if !self.admins.contains(msg_src) { + return Err(GameError::NotAdmin); + } + + if let Some(gas_to_remove_game) = gas_to_remove_game { + self.config.gas_to_remove_game = gas_to_remove_game; + } + if let Some(initial_speed) = initial_speed { + self.config.initial_speed = initial_speed; + } + + if let Some(min_speed) = min_speed { + self.config.min_speed = min_speed; + } + + if let Some(max_speed) = max_speed { + self.config.max_speed = max_speed; + } + + if let Some(gas_for_round) = gas_for_round { + self.config.gas_for_round = gas_for_round; + } + if let Some(time_interval) = time_interval { + self.config.time_interval = time_interval; + } + + if let Some(max_distance) = max_distance { + self.config.max_distance = max_distance; + } + + if let Some(max_speed) = max_speed { + self.config.max_speed = max_speed; + } + + if let Some(time) = time { + self.config.time = time; + } + if let Some(time_for_game_storage) = time_for_game_storage { + self.config.time_for_game_storage = time_for_game_storage; + } + Ok(GameReply::ConfigUpdated) + } + fn allow_messages( + &mut self, + msg_src: &ActorId, + messages_allowed: bool, + ) -> Result { + if !self.admins.contains(msg_src) { + return Err(GameError::NotAdmin); + } + self.messages_allowed = messages_allowed; + Ok(GameReply::StatusMessagesUpdated) } } @@ -195,43 +290,32 @@ impl Contract { extern fn handle() { let action: GameAction = msg::load().expect("Unable to decode the message"); let contract = unsafe { CONTRACT.as_mut().expect("The game is not initialized") }; + let msg_src = msg::source(); - if let GameAction::AllowMessages(messages_allowed) = action { - assert!( - contract.admins.contains(&msg::source()), - "Only an admin can send this message" - ); - contract.messages_allowed = messages_allowed; + if !contract.messages_allowed && !contract.admins.contains(&msg_src) { + msg::reply( + Err::(GameError::MessageProcessingSuspended), + 0, + ) + .expect("Failed to encode or reply with `Result`."); return; } - assert!( - contract.messages_allowed, - "Message processing has been suspended for some time" - ); - - match action { - GameAction::AddStrategyIds { car_ids } => contract.add_strategy_ids(car_ids), - GameAction::StartGame => contract.start_game(), - GameAction::Play { account } => contract.play(&account), - GameAction::PlayerMove { strategy_action } => contract.player_move(strategy_action), - GameAction::RemoveGameInstance { account_id } => contract.remove_game_instance(&account_id), - GameAction::RemoveGameInstances { players_ids } => contract.remove_instances(players_ids), - GameAction::AddAdmin(admin) => { - assert!( - contract.admins.contains(&msg::source()), - "You are not admin" - ); - contract.admins.push(admin); - } - GameAction::RemoveAdmin(admin) => { - assert!( - contract.admins.contains(&msg::source()), - "You are not admin" - ); - - contract.admins.retain(|id| *id != admin); + let reply = match action { + GameAction::AddStrategyIds { car_ids } => contract.add_strategy_ids(&msg_src, car_ids), + GameAction::StartGame => contract.start_game(&msg_src), + GameAction::Play { account } => contract.play(&msg_src, &account), + GameAction::PlayerMove { strategy_action } => { + contract.player_move(&msg_src, strategy_action) } + GameAction::RemoveGameInstance { account_id } => { + contract.remove_game_instance(&msg_src, &account_id) + } + GameAction::RemoveGameInstances { players_ids } => { + contract.remove_instances(&msg_src, players_ids) + } + GameAction::AddAdmin(admin) => contract.add_admin(&msg_src, admin), + GameAction::RemoveAdmin(admin) => contract.remove_admin(&msg_src, admin), GameAction::UpdateConfig { gas_to_remove_game, initial_speed, @@ -242,51 +326,23 @@ extern fn handle() { max_distance, time, time_for_game_storage, - } => { - assert!( - contract.admins.contains(&msg::source()), - "You are not admin" - ); - - if let Some(gas_to_remove_game) = gas_to_remove_game { - contract.config.gas_to_remove_game = gas_to_remove_game; - } - if let Some(initial_speed) = initial_speed { - contract.config.initial_speed = initial_speed; - } - - if let Some(min_speed) = min_speed { - contract.config.min_speed = min_speed; - } - - if let Some(max_speed) = max_speed { - contract.config.max_speed = max_speed; - } - - if let Some(gas_for_round) = gas_for_round { - contract.config.gas_for_round = gas_for_round; - } - if let Some(time_interval) = time_interval { - contract.config.time_interval = time_interval; - } - - if let Some(max_distance) = max_distance { - contract.config.max_distance = max_distance; - } - - if let Some(max_speed) = max_speed { - contract.config.max_speed = max_speed; - } - - if let Some(time) = time { - contract.config.time = time; - } - if let Some(time_for_game_storage) = time_for_game_storage { - contract.config.time_for_game_storage = time_for_game_storage; - } + } => contract.update_config( + &msg_src, + gas_to_remove_game, + initial_speed, + min_speed, + max_speed, + gas_for_round, + time_interval, + max_distance, + time, + time_for_game_storage, + ), + GameAction::AllowMessages(messages_allowed) => { + contract.allow_messages(&msg_src, messages_allowed) } - _ => {} - } + }; + msg::reply(reply, 0).expect("Failed to encode or reply with `Result`."); } #[no_mangle] diff --git a/contracts/car-races/tests/test.rs b/contracts/car-races/tests/test.rs index 74eeebf34..e72ffa599 100644 --- a/contracts/car-races/tests/test.rs +++ b/contracts/car-races/tests/test.rs @@ -147,14 +147,22 @@ fn failures_test() { assert!(!game_init_result.main_failed()); // AllowMessages not true - let run_result = game.send(ADMIN, GameAction::AddAdmin(1.into())); - assert!(run_result.main_failed()); + let run_result = game.send(PLAYERS[0], GameAction::StartGame); + assert!(!run_result.main_failed()); + assert!(run_result.contains(&( + PLAYERS[0], + Err::(GameError::MessageProcessingSuspended).encode() + ))); let run_result = game.send(ADMIN, GameAction::AllowMessages(true)); assert!(!run_result.main_failed()); // not admin let run_result = game.send(PLAYERS[0], GameAction::AddAdmin(2.into())); - assert!(run_result.main_failed()); + assert!(!run_result.main_failed()); + assert!(run_result.contains(&( + PLAYERS[0], + Err::(GameError::NotAdmin).encode() + ))); let car_1 = Program::from_file( &system, @@ -178,7 +186,11 @@ fn failures_test() { // There must be 2 strategies of cars let car_ids: Vec = vec![1.into(), 2.into(), 3.into()]; let run_result = game.send(ADMIN, GameAction::AddStrategyIds { car_ids }); - assert!(run_result.main_failed()); + assert!(!run_result.main_failed()); + assert!(run_result.contains(&( + ADMIN, + Err::(GameError::MustBeTwoStrategies).encode() + ))); let car_ids: Vec = vec![2.into(), 3.into()]; let run_result = game.send(ADMIN, GameAction::AddStrategyIds { car_ids }); @@ -188,7 +200,11 @@ fn failures_test() { assert!(!run_result.main_failed()); // The game has already started let run_result = game.send(ADMIN, GameAction::StartGame); - assert!(run_result.main_failed()); + assert!(!run_result.main_failed()); + assert!(run_result.contains(&( + ADMIN, + Err::(GameError::GameAlreadyStarted).encode() + ))); for _i in 0..40 { let run_result = game.send( @@ -218,5 +234,9 @@ fn failures_test() { strategy_action: StrategyAction::BuyShell, }, ); - assert!(run_result.main_failed()); + assert!(!run_result.main_failed()); + assert!(run_result.contains(&( + ADMIN, + Err::(GameError::NotPlayerTurn).encode() + ))); } diff --git a/contracts/fungible-token/src/lib.rs b/contracts/fungible-token/src/lib.rs index 29a76b90b..1abaafb17 100644 --- a/contracts/fungible-token/src/lib.rs +++ b/contracts/fungible-token/src/lib.rs @@ -121,7 +121,7 @@ impl FungibleToken { fn can_transfer(&mut self, from: &ActorId, amount: u128) -> bool { let source = msg::source(); - if from == &source || self.balances.get(&source).unwrap_or(&0) >= &amount { + if from == &source && self.balances.get(&source).unwrap_or(&0) >= &amount { return true; } if let Some(allowed_amount) = self.allowances.get(from).and_then(|m| m.get(&source)) { diff --git a/contracts/galactic-express/.DS_Store b/contracts/galactic-express/.DS_Store index 9e29d53a6..866c1fe2f 100644 Binary files a/contracts/galactic-express/.DS_Store and b/contracts/galactic-express/.DS_Store differ diff --git a/contracts/galactic-express/io/src/lib.rs b/contracts/galactic-express/io/src/lib.rs index 2a86214ba..7554a08d9 100644 --- a/contracts/galactic-express/io/src/lib.rs +++ b/contracts/galactic-express/io/src/lib.rs @@ -12,10 +12,10 @@ impl Metadata for ContractMetadata { type Reply = (); type Others = (); type Signal = (); - type State = Out; + type State = InOut; } -pub const PARTICIPANTS: usize = 4; +pub const MAX_PARTICIPANTS: usize = 4; pub const TURNS: usize = 3; /// Represents a range of the minimum & the maximum reward for a session. @@ -31,26 +31,37 @@ pub const MAX_FUEL: u8 = 100; // maximum payload value that can be entered by the user pub const MAX_PAYLOAD: u8 = 100; +#[derive(Encode, Decode, TypeInfo)] +pub enum StateQuery { + All, + GetGame { player_id: ActorId }, +} + +#[derive(Encode, Decode, TypeInfo)] +pub enum StateReply { + All(State), + Game(Option), +} + #[derive(Encode, Decode, TypeInfo, Debug)] pub struct State { - pub admin: ActorId, - pub session: Session, - pub is_session_ended: bool, - pub participants: Vec<(ActorId, Participant)>, - pub turns: Vec>, - pub rankings: Vec<(ActorId, u128)>, + pub games: Vec<(ActorId, GameState)>, + pub player_to_game_id: Vec<(ActorId, ActorId)>, } -#[derive(Encode, Decode, TypeInfo, Debug, PartialEq, Eq)] -pub struct Session { - pub session_id: u128, +#[derive(Encode, Decode, TypeInfo, Debug)] +pub struct GameState { + pub admin: ActorId, + pub admin_name: String, pub altitude: u16, pub weather: Weather, pub reward: u128, + pub stage: StageState, + pub bid: u128, } #[derive(Encode, Decode, TypeInfo, Debug)] -pub enum Stage { +pub enum StageState { Registration(Vec<(ActorId, Participant)>), Results(Results), } @@ -59,26 +70,53 @@ pub enum Stage { pub struct Results { pub turns: Vec>, pub rankings: Vec<(ActorId, u128)>, + pub participants: Vec<(ActorId, Participant)>, } #[derive(Encode, Decode, TypeInfo)] pub enum Action { - ChangeAdmin(ActorId), - CreateNewSession, - Register(Participant), - StartGame(Participant), + CreateNewSession { + name: String, + }, + Register { + creator: ActorId, + participant: Participant, + }, + CancelRegistration, + DeletePlayer { + player_id: ActorId, + }, + CancelGame, + LeaveGame, + StartGame { + fuel_amount: u8, + payload_amount: u8, + }, } #[derive(Encode, Decode, TypeInfo, Debug, PartialEq, Eq)] pub enum Event { GameFinished(Results), AdminChanged(ActorId, ActorId), - NewSession(Session), + NewSessionCreated { + altitude: u16, + weather: Weather, + reward: u128, + bid: u128, + }, Registered(ActorId, Participant), + RegistrationCanceled, + PlayerDeleted { + player_id: ActorId, + }, + GameCanceled, + GameLeft, } -#[derive(Encode, Decode, TypeInfo, Clone, Copy, Debug, Default, PartialEq, Eq)] +#[derive(Encode, Decode, TypeInfo, Clone, Debug, Default, PartialEq, Eq)] pub struct Participant { + pub id: ActorId, + pub name: String, pub fuel_amount: u8, pub payload_amount: u8, } @@ -124,12 +162,18 @@ pub enum Weather { pub enum Error { StateUninitaliazed, GstdError(String), - AccessDenied, SessionEnded, FuelOrPayloadOverload, SessionFull, NotEnoughParticipants, TxManager(TransactionManagerError), + NoSuchGame, + WrongBid, + NoSuchPlayer, + Unregistered, + AlreadyRegistered, + SeveralRegistrations, + NotForAdmin, } impl From for Error { diff --git a/contracts/galactic-express/src/lib.rs b/contracts/galactic-express/src/lib.rs index 718f579b9..a5485997b 100644 --- a/contracts/galactic-express/src/lib.rs +++ b/contracts/galactic-express/src/lib.rs @@ -5,7 +5,7 @@ use gear_lib::tx_manager::TransactionManager; use gstd::{ collections::HashMap, errors::Error as GstdError, - exec, iter, msg, + exec, msg, ops::{Add, Rem, Sub}, prelude::*, ActorId, @@ -82,8 +82,15 @@ impl Default for Stage { #[derive(Default)] struct Contract { + games: HashMap, + player_to_game_id: HashMap, +} + +#[derive(Default)] +pub struct Game { admin: ActorId, - session_id: u128, + admin_name: String, + bid: u128, altitude: u16, weather: Weather, reward: u128, @@ -91,16 +98,25 @@ struct Contract { } impl Contract { - fn check_admin(&self) -> Result<(), Error> { - check_admin(self.admin) - } + fn create_new_session(&mut self, name: String) -> Result { + let msg_src = msg::source(); + let msg_value = msg::value(); + + if self.player_to_game_id.contains_key(&msg_src) { + return Err(Error::SeveralRegistrations); + } - fn create_new_session(&mut self) -> Result { - let stage = &mut self.stage; + let game = self.games.entry(msg_src).or_insert_with(|| Game { + admin: msg_src, + admin_name: name, + bid: msg_value, + ..Default::default() + }); + + let stage = &mut game.stage; match stage { Stage::Registration(participants) => { - check_admin(self.admin)?; participants.clear(); } Stage::Results { .. } => *stage = Stage::Registration(HashMap::new()), @@ -108,7 +124,7 @@ impl Contract { let mut random = Random::new()?; - self.weather = match random.next() % (Weather::Tornado as u8 + 1) { + game.weather = match random.next() % (Weather::Tornado as u8 + 1) { 0 => Weather::Clear, 1 => Weather::Cloudy, 2 => Weather::Rainy, @@ -117,57 +133,159 @@ impl Contract { 5 => Weather::Tornado, _ => unreachable!(), }; - self.altitude = random.generate(TURN_ALTITUDE.0, TURN_ALTITUDE.1) * TURNS as u16; - self.reward = random.generate(REWARD.0, REWARD.1); - - Ok(Event::NewSession(Session { - session_id: self.session_id, - altitude: self.altitude, - weather: self.weather, - reward: self.reward, - })) + game.altitude = random.generate(TURN_ALTITUDE.0, TURN_ALTITUDE.1) * TURNS as u16; + game.reward = random.generate(REWARD.0, REWARD.1); + self.player_to_game_id.insert(msg_src, msg_src); + + Ok(Event::NewSessionCreated { + altitude: game.altitude, + weather: game.weather, + reward: game.reward, + bid: msg_value, + }) } - fn register(&mut self, participant: Participant) -> Result { - let msg_source = msg::source(); + fn cancel_game(&mut self) -> Result { + let msg_src = msg::source(); + let game = self.games.get(&msg_src).ok_or(Error::NoSuchGame)?; - if msg_source == self.admin { - return Err(Error::AccessDenied); + match &game.stage { + Stage::Registration(players) => { + players.iter().for_each(|(id, _)| { + send_value(*id, game.bid); + self.player_to_game_id.remove(id); + }); + } + Stage::Results(results) => { + results.rankings.iter().for_each(|(id, _)| { + self.player_to_game_id.remove(id); + }); + } } - if let Stage::Results(_) = self.stage { - return Err(Error::SessionEnded); + + self.player_to_game_id.remove(&msg_src); + self.games.remove(&msg_src); + Ok(Event::GameCanceled) + } + + fn leave_game(&mut self) -> Result { + let msg_src = msg::source(); + self.player_to_game_id.remove(&msg_src); + Ok(Event::GameLeft) + } + + fn register( + &mut self, + creator: ActorId, + participant: Participant, + msg_source: ActorId, + msg_value: u128, + ) -> Result { + if self.player_to_game_id.contains_key(&msg_source) { + return Err(Error::SeveralRegistrations); + } + + if let Some(game) = self.games.get_mut(&creator) { + if msg_value != game.bid { + return Err(Error::WrongBid); + } + if let Stage::Results(_) = game.stage { + return Err(Error::SessionEnded); + } + + let participants = game.stage.mut_participants()?; + + if participants.contains_key(&msg_source) { + return Err(Error::AlreadyRegistered); + } + + if participants.len() >= MAX_PARTICIPANTS - 1 { + return Err(Error::SessionFull); + } + + participant.check()?; + participants.insert(msg_source, participant.clone()); + self.player_to_game_id.insert(msg_source, creator); + + Ok(Event::Registered(msg_source, participant)) + } else { + Err(Error::NoSuchGame) } + } - let participants = self.stage.mut_participants()?; + fn cancel_register(&mut self) -> Result { + let msg_source = msg::source(); - if participants.len() >= PARTICIPANTS - 1 { - return Err(Error::SessionFull); + let creator = self + .player_to_game_id + .get(&msg_source) + .ok_or(Error::Unregistered)?; + let game = self.games.get_mut(creator).ok_or(Error::NoSuchGame)?; + + if msg_source != game.admin { + let participants = game.stage.mut_participants()?; + if participants.contains_key(&msg_source) { + send_value(msg_source, game.bid); + participants.remove(&msg_source).expect("Critical error"); + self.player_to_game_id.remove(&msg_source); + } else { + return Err(Error::NoSuchPlayer); + } + Ok(Event::RegistrationCanceled) + } else { + Err(Error::NotForAdmin) } + } + fn delete_player(&mut self, player_id: ActorId) -> Result { + let msg_source = msg::source(); - participant.check()?; - participants.insert(msg_source, participant); + if let Some(game) = self.games.get_mut(&msg_source) { + if let Stage::Results(_) = game.stage { + return Err(Error::SessionEnded); + } + + let participants = game.stage.mut_participants()?; - Ok(Event::Registered(msg_source, participant)) + if participants.contains_key(&player_id) { + send_value(player_id, game.bid); + participants.remove(&player_id).expect("Critical error"); + self.player_to_game_id.remove(&player_id); + } else { + return Err(Error::NoSuchPlayer); + } + + Ok(Event::PlayerDeleted { player_id }) + } else { + Err(Error::NoSuchGame) + } } - async fn start_game(&mut self, mut participant: Participant) -> Result { - self.check_admin()?; + async fn start_game(&mut self, fuel_amount: u8, payload_amount: u8) -> Result { + let msg_source = msg::source(); + + let game = self.games.get_mut(&msg_source).ok_or(Error::NoSuchGame)?; + + if fuel_amount > MAX_FUEL || payload_amount > MAX_PAYLOAD { + return Err(Error::FuelOrPayloadOverload); + } + let participant = Participant { + id: msg_source, + name: game.admin_name.clone(), + fuel_amount, + payload_amount, + }; - let participants = self.stage.mut_participants()?; + let participants = game.stage.mut_participants()?; if participants.is_empty() { return Err(Error::NotEnoughParticipants); } - - participant.check()?; + participants.insert(msg_source, participant); let mut random = Random::new()?; let mut turns = HashMap::new(); - for (actor, participant) in participants - .into_iter() - .chain(iter::once((&msg::source(), &mut participant))) - { + for (actor, participant) in participants.into_iter() { let mut actor_turns = Vec::with_capacity(TURNS); let mut remaining_fuel = participant.fuel_amount; @@ -176,7 +294,7 @@ impl Contract { turn_index, remaining_fuel, &mut random, - self.weather, + game.weather, participant.payload_amount, ) { Ok(fuel_left) => { @@ -209,7 +327,7 @@ impl Contract { Turn::Alive { fuel_left, payload_amount, - } => (*payload_amount as u128 + *fuel_left as u128) * self.altitude as u128, + } => (*payload_amount as u128 + *fuel_left as u128) * game.altitude as u128, Turn::Destroyed(_) => 0, }, ) @@ -229,26 +347,40 @@ impl Contract { } } + let max_value = scores.iter().map(|(_, value)| value).max().unwrap(); + let winners: Vec<_> = scores + .iter() + .filter_map(|(actor_id, value)| { + if value == max_value { + Some(*actor_id) + } else { + None + } + }) + .collect(); + let prize = game.bid * scores.len() as u128 / winners.len() as u128; + + if game.bid != 0 { + winners.iter().for_each(|id| { + send_value(*id, prize); + }); + } + let participants = participants + .iter() + .map(|(id, participant)| (*id, participant.clone())) + .collect(); + let results = Results { turns: io_turns, - rankings: scores, + rankings: scores.clone(), + participants, }; - - self.session_id = self.session_id.wrapping_add(1); - self.stage = Stage::Results(results.clone()); + game.stage = Stage::Results(results.clone()); Ok(Event::GameFinished(results)) } } -fn check_admin(admin: ActorId) -> Result<(), Error> { - if msg::source() != admin { - Err(Error::AccessDenied) - } else { - Ok(()) - } -} - fn turn( turn: usize, remaining_fuel: u8, @@ -294,6 +426,12 @@ fn turn( Ok(new_remaining_fuel) } +fn send_value(destination: ActorId, value: u128) { + if value != 0 { + msg::send_with_gas(destination, "", 0, value).expect("Error in sending value"); + } +} + #[no_mangle] extern fn init() { msg::reply(process_init(), 0).expect("failed to encode or reply from `main()`"); @@ -303,7 +441,6 @@ fn process_init() -> Result<(), Error> { unsafe { STATE = Some(( Contract { - admin: msg::source(), ..Default::default() }, TransactionManager::new(), @@ -323,71 +460,101 @@ async fn process_main() -> Result { let (contract, _tx_manager) = state_mut()?; match action { - Action::ChangeAdmin(actor) => { - contract.check_admin()?; - - let old_admin = contract.admin; - - contract.admin = actor; - - Ok(Event::AdminChanged(old_admin, contract.admin)) + Action::CreateNewSession { name } => contract.create_new_session(name), + Action::Register { + creator, + participant, + } => { + let msg_source = msg::source(); + let msg_value = msg::value(); + let reply = contract.register(creator, participant, msg_source, msg_value); + if reply.is_err() { + send_value(msg_source, msg_value); + } + reply } - Action::CreateNewSession => contract.create_new_session(), - Action::Register(participant) => contract.register(participant), - Action::StartGame(participant) => contract.start_game(participant).await, + Action::CancelRegistration => contract.cancel_register(), + Action::DeletePlayer { player_id } => contract.delete_player(player_id), + Action::CancelGame => contract.cancel_game(), + Action::LeaveGame => contract.leave_game(), + Action::StartGame { + fuel_amount, + payload_amount, + } => contract.start_game(fuel_amount, payload_amount).await, } } #[no_mangle] extern fn state() { let (state, _tx_manager) = unsafe { STATE.take().expect("Unexpected error in taking state") }; - msg::reply::(state.into(), 0) - .expect("Failed to encode or reply with `State` from `state()`"); + let query: StateQuery = msg::load().expect("Unable to load the state query"); + let reply = match query { + StateQuery::All => StateReply::All(state.into()), + StateQuery::GetGame { player_id } => { + let game_state = state + .player_to_game_id + .get(&player_id) + .and_then(|creator_id| state.games.get(creator_id)) + .map(|game| { + let stage = match &game.stage { + Stage::Registration(participants_data) => StageState::Registration( + participants_data.clone().into_iter().collect(), + ), + Stage::Results(results) => StageState::Results(results.clone()), + }; + + GameState { + admin: game.admin, + admin_name: game.admin_name.clone(), + altitude: game.altitude, + weather: game.weather, + reward: game.reward, + stage, + bid: game.bid, + } + }); + + StateReply::Game(game_state) + } + }; + msg::reply(reply, 0).expect("Unable to share the state"); } impl From for State { fn from(value: Contract) -> Self { let Contract { - admin, - session_id, - altitude, - weather, - reward, - stage, + games, + player_to_game_id, } = value; - let is_session_ended: bool; - let participants: Vec<(ActorId, Participant)>; - let turns: Vec>; - let rankings: Vec<(ActorId, u128)>; + let games = games + .into_iter() + .map(|(id, game)| { + let stage = match game.stage { + Stage::Registration(participants_data) => { + StageState::Registration(participants_data.into_iter().collect()) + } + Stage::Results(results) => StageState::Results(results), + }; + + let game_state = GameState { + admin: game.admin, + admin_name: game.admin_name.clone(), + altitude: game.altitude, + weather: game.weather, + reward: game.reward, + stage, + bid: game.bid, + }; + (id, game_state) + }) + .collect(); - match stage { - Stage::Registration(participants_data) => { - is_session_ended = false; - participants = participants_data.into_iter().collect(); - turns = vec![vec![]]; - rankings = Vec::new(); - } - Stage::Results(results) => { - is_session_ended = true; - participants = Vec::new(); - turns = results.turns; - rankings = results.rankings; - } - }; + let player_to_game_id = player_to_game_id.into_iter().collect(); Self { - admin, - session: Session { - session_id, - altitude, - weather, - reward, - }, - is_session_ended, - participants, - turns, - rankings, + games, + player_to_game_id, } } } diff --git a/contracts/galactic-express/tests/test.rs b/contracts/galactic-express/tests/test.rs index c7f38d0ef..3df67eeec 100644 --- a/contracts/galactic-express/tests/test.rs +++ b/contracts/galactic-express/tests/test.rs @@ -5,123 +5,138 @@ mod utils; #[test] fn test() { let system = utils::initialize_system(); + let mut rockets = GalEx::initialize(&system, ADMIN); - for admin_id in ADMINS { - let mut rockets = GalEx::initialize(&system, admin_id); - if let State { - admin, - session: Session { session_id: 0, .. }, - is_session_ended: true, - participants, - turns, - rankings, - } = rockets.state() - { - assert_eq!(admin, admin_id.into()); - assert_eq!((participants, turns, rankings), (vec![], vec![], vec![])); - } else { - unreachable!() - } - - for (session_id, starter) in [admin_id, PLAYERS[0]].into_iter().enumerate() { - rockets - .create_new_session(starter) - .succeed(session_id as u128); - - let player = Participant { - fuel_amount: 42, - payload_amount: 20, - }; - - for player_id in PLAYERS { - rockets - .register(player_id, player) - .succeed((player_id, player)); - } - #[allow(irrefutable_let_patterns)] - if let State { participants, .. } = rockets.state() { - assert_eq!( - HashMap::from_iter( - PLAYERS - .into_iter() - .map(|player_id| (player_id.into(), player)) - ), - participants.into_iter().collect::>(), - ); - } else { - unreachable!() - } - - rockets - .start_game(admin_id, player) - .succeed(PLAYERS.into_iter().chain(iter::once(admin_id)).collect()); - } + let bid = 11_000_000_000_000; + system.mint_to(ADMIN, bid); + rockets + .create_new_session(ADMIN, "admin".to_string(), bid) + .succeed(0, 0); + + for player_id in PLAYERS { + let player = Participant { + id: player_id.into(), + name: "player".to_string(), + fuel_amount: 42, + payload_amount: 20, + }; + system.mint_to(player_id, bid); + rockets + .register(player_id, ADMIN.into(), player.clone(), bid) + .succeed((player_id, player), 0); + } + + let state = rockets.state().expect("Unexpected invalid state."); + + if let StageState::Registration(participants) = &state.games[0].1.stage { + assert_eq!(participants.len(), 3); + } + + rockets + .start_game(ADMIN, 42, 20) + .succeed(PLAYERS.into_iter().chain(iter::once(ADMIN)).collect(), 3); // 3 since three players win and msg::send_with_gas is sent to them + + let state = rockets.state().expect("Unexpected invalid state."); + + if let StageState::Results(results) = &state.games[0].1.stage { + assert_eq!(results.rankings.len(), 4); } } +#[test] +fn cancel_register_and_delete_player() { + let system = utils::initialize_system(); + let mut rockets = GalEx::initialize(&system, ADMIN); + + let bid = 11_000_000_000_000; + system.mint_to(ADMIN, bid); + rockets + .create_new_session(ADMIN, "admin".to_string(), bid) + .succeed(0_u128, 0); + + for player_id in PLAYERS { + let player = Participant { + id: player_id.into(), + name: "player".to_string(), + fuel_amount: 42, + payload_amount: 20, + }; + system.mint_to(player_id, bid); + rockets + .register(player_id, ADMIN.into(), player.clone(), bid) + .succeed((player_id, player), 0); + } + + let state = rockets.state().expect("Unexpected invalid state."); + + if let StageState::Registration(participants) = &state.games[0].1.stage { + assert_eq!(participants.len(), 3); + } + assert_eq!(state.player_to_game_id.len(), 4); + + drop(rockets.cancel_register(PLAYERS[0])); + + let state = rockets.state().expect("Unexpected invalid state."); + + if let StageState::Registration(participants) = &state.games[0].1.stage { + assert_eq!(participants.len(), 2); + } + assert_eq!(state.player_to_game_id.len(), 3); + + drop(rockets.delete_player(ADMIN, PLAYERS[1].into())); + + let state = rockets.state().expect("Unexpected invalid state."); + + if let StageState::Registration(participants) = &state.games[0].1.stage { + assert_eq!(participants.len(), 1); + } + assert_eq!(state.player_to_game_id.len(), 2); +} + #[test] fn errors() { let system = utils::initialize_system(); - let mut rockets = GalEx::initialize(&system, ADMINS[0]); + let mut rockets = GalEx::initialize(&system, ADMIN); rockets - .change_admin(PLAYERS[0], PLAYERS[0]) - .failed(Error::AccessDenied); - rockets - .change_admin(ADMINS[0], ADMINS[1]) - .succeed((ADMINS[0], ADMINS[1])); + .register(PLAYERS[0], ADMIN.into(), Default::default(), 0) + .failed(Error::NoSuchGame, 0); rockets - .register(PLAYERS[0], Default::default()) - .failed(Error::SessionEnded); + .create_new_session(ADMIN, "admin".to_string(), 0) + .succeed(0, 0); + rockets - .start_game(PLAYERS[0], Default::default()) - .failed(Error::AccessDenied); + .register(ADMIN, ADMIN.into(), Default::default(), 0) + .failed(Error::SeveralRegistrations, 0); - rockets.create_new_session(ADMINS[1]).succeed(0); + rockets + .start_game(PLAYERS[0], 42, 20) + .failed(Error::NoSuchGame, 0); rockets - .start_game(ADMINS[1], Default::default()) - .failed(Error::NotEnoughParticipants); + .start_game(ADMIN, 42, 20) + .failed(Error::NotEnoughParticipants, 0); for player in PLAYERS { rockets - .register(player, Default::default()) - .succeed((player, Default::default())); + .register(player, ADMIN.into(), Default::default(), 0) + .succeed((player, Default::default()), 0); } rockets - .start_game( - ADMINS[1], - Participant { - fuel_amount: 101, - payload_amount: 100, - }, - ) - .failed(Error::FuelOrPayloadOverload); - rockets - .start_game( - ADMINS[1], - Participant { - fuel_amount: 100, - payload_amount: 101, - }, - ) - .failed(Error::FuelOrPayloadOverload); + .start_game(ADMIN, 101, 100) + .failed(Error::FuelOrPayloadOverload, 0); + rockets - .start_game( - ADMINS[1], - Participant { - fuel_amount: 101, - payload_amount: 101, - }, - ) - .failed(Error::FuelOrPayloadOverload); + .start_game(ADMIN, 100, 101) + .failed(Error::FuelOrPayloadOverload, 0); rockets - .register(ADMINS[1], Default::default()) - .failed(Error::AccessDenied); + .start_game(ADMIN, 101, 101) + .failed(Error::FuelOrPayloadOverload, 0); + rockets - .register(FOREIGN_USER, Default::default()) - .failed(Error::SessionFull); + .register(FOREIGN_USER, ADMIN.into(), Default::default(), 0) + .failed(Error::SessionFull, 0); } diff --git a/contracts/galactic-express/tests/utils/common.rs b/contracts/galactic-express/tests/utils/common.rs index f2877fa8d..92b7ba32a 100644 --- a/contracts/galactic-express/tests/utils/common.rs +++ b/contracts/galactic-express/tests/utils/common.rs @@ -38,16 +38,19 @@ impl>(&self.result).unwrap_err(), + decode::>(&self.result, index).unwrap_err(), error ); } #[track_caller] - pub fn succeed(self, value: Check) -> CheckResult { - (self.check)(decode::>(&self.result).unwrap(), value) + pub fn succeed(self, value: Check, index: usize) -> CheckResult { + (self.check)( + decode::>(&self.result, index).unwrap(), + value, + ) } } @@ -87,8 +90,8 @@ fn assert_contains(result: &InnerRunResult, payload: impl Encode) { assert!(result.contains(&Log::builder().payload(payload))); } -fn decode(result: &InnerRunResult) -> T { - match T::decode(&mut result.log()[0].payload()) { +fn decode(result: &InnerRunResult, index: usize) -> T { + match T::decode(&mut result.log()[index].payload()) { Ok(ok) => ok, Err(_) => std::panic!("{}", String::from_utf8_lossy(result.log()[0].payload())), } diff --git a/contracts/galactic-express/tests/utils/mod.rs b/contracts/galactic-express/tests/utils/mod.rs index fd44d384a..1e75f0262 100644 --- a/contracts/galactic-express/tests/utils/mod.rs +++ b/contracts/galactic-express/tests/utils/mod.rs @@ -10,8 +10,8 @@ pub mod prelude; pub use common::initialize_system; pub const FOREIGN_USER: u64 = 1029384756123; -pub const ADMINS: [u64; 2] = [123, 321]; -pub const PLAYERS: [u64; 3] = [1234, 4321, 2332]; +pub const ADMIN: u64 = 10; +pub const PLAYERS: [u64; 3] = [12, 13, 14]; type GalExResult = RunResult; @@ -33,29 +33,25 @@ impl<'a> GalEx<'a> { InitResult::<_, Error>::new(Self(program), result, is_active).succeed() } - pub fn change_admin( + pub fn create_new_session( &mut self, from: u64, - actor: impl Into, - ) -> GalExResult<(u64, u64)> { + name: String, + bid: u128, + ) -> GalExResult { RunResult::new( - self.0.send(from, Action::ChangeAdmin(actor.into())), - |event, (old, new)| assert_eq!(Event::AdminChanged(old.into(), new.into()), event), - ) - } - - pub fn create_new_session(&mut self, from: u64) -> GalExResult { - RunResult::new( - self.0.send(from, Action::CreateNewSession), - |event, session_id| { - if let Event::NewSession(session) = event { - assert_eq!(session.session_id, session_id); + self.0 + .send_with_value(from, Action::CreateNewSession { name }, bid), + |event, _id| { + if let Event::NewSessionCreated { + altitude, reward, .. + } = event + { assert!(((TURN_ALTITUDE.0 * (TURNS as u16)) ..(TURN_ALTITUDE.1 * (TURNS as u16))) - .contains(&session.altitude)); - assert!((REWARD.0..REWARD.1).contains(&session.reward)); - - session + .contains(&altitude)); + assert!((REWARD.0..REWARD.1).contains(&reward)); + reward } else { unreachable!() } @@ -66,27 +62,65 @@ impl<'a> GalEx<'a> { pub fn register( &mut self, from: u64, + creator: ActorId, participant: Participant, + bid: u128, ) -> GalExResult<(u64, Participant)> { RunResult::new( - self.0.send(from, Action::Register(participant)), + self.0.send_with_value( + from, + Action::Register { + creator, + participant, + }, + bid, + ), |event, (actor, participant)| { assert_eq!(Event::Registered(actor.into(), participant), event) }, ) } - pub fn start_game(&mut self, from: u64, participant: Participant) -> GalExResult> { + pub fn cancel_register(&mut self, from: u64) -> GalExResult<(u64, Participant)> { + RunResult::new( + self.0.send(from, Action::CancelRegistration), + |event, (_actor, _participant)| assert_eq!(Event::RegistrationCanceled, event), + ) + } + + pub fn delete_player( + &mut self, + from: u64, + player_id: ActorId, + ) -> GalExResult<(u64, Participant)> { + RunResult::new( + self.0.send(from, Action::DeletePlayer { player_id }), + |_, _| {}, + ) + } + + pub fn start_game( + &mut self, + from: u64, + fuel_amount: u8, + payload_amount: u8, + ) -> GalExResult> { RunResult::new( - self.0.send(from, Action::StartGame(participant)), + self.0.send( + from, + Action::StartGame { + fuel_amount, + payload_amount, + }, + ), |event, players| { if let Event::GameFinished(results) = event { assert!(results.turns.len() == TURNS); - assert!(results.rankings.len() == PARTICIPANTS); + assert!(results.rankings.len() == MAX_PARTICIPANTS); assert!(results .turns .iter() - .all(|players| players.len() == PARTICIPANTS)); + .all(|players| players.len() == MAX_PARTICIPANTS)); let players: HashSet = players.into_iter().map(|p| p.into()).collect(); @@ -105,7 +139,15 @@ impl<'a> GalEx<'a> { ) } - pub fn state(&self) -> State { - self.0.read_state(0).unwrap() + pub fn state(&self) -> Option { + let reply = self + .0 + .read_state(StateQuery::All) + .expect("Unexpected invalid state."); + if let StateReply::All(state) = reply { + Some(state) + } else { + None + } } } diff --git a/contracts/galactic-express/tests/utils/prelude.rs b/contracts/galactic-express/tests/utils/prelude.rs index 8ba16b037..ed2994b73 100644 --- a/contracts/galactic-express/tests/utils/prelude.rs +++ b/contracts/galactic-express/tests/utils/prelude.rs @@ -1,6 +1,3 @@ -pub use super::{ - common::{initialize_system, Program}, - GalEx, ADMINS, FOREIGN_USER, PLAYERS, -}; +pub use super::{GalEx, ADMIN, FOREIGN_USER, PLAYERS}; pub use galactic_express_io::*; -pub use gstd::{collections::*, prelude::*, ActorId}; +pub use gstd::prelude::*; diff --git a/contracts/gear-lib/src/tokens.rs b/contracts/gear-lib/src/tokens.rs index e00a39121..ee62254eb 100644 --- a/contracts/gear-lib/src/tokens.rs +++ b/contracts/gear-lib/src/tokens.rs @@ -13,7 +13,7 @@ mod test_helper { use std::thread_local; thread_local! { - static SOURCE: Cell = Cell::new(ActorId::zero()); + static SOURCE: Cell = const { Cell::new(ActorId::zero()) }; } pub mod msg { diff --git a/contracts/nft-marketplace/tests/utils/nftoken.rs b/contracts/nft-marketplace/tests/utils/nftoken.rs index c5c830da8..d09898c6a 100644 --- a/contracts/nft-marketplace/tests/utils/nftoken.rs +++ b/contracts/nft-marketplace/tests/utils/nftoken.rs @@ -92,6 +92,7 @@ impl<'a> NonFungibleToken<'a> { } } +#[allow(dead_code)] pub struct NonFungibleTokenMetaState<'a>(&'a InnerProgram<'a>); impl NonFungibleTokenMetaState<'_> { diff --git a/contracts/nft-pixelboard/tests/utils/nftoken.rs b/contracts/nft-pixelboard/tests/utils/nftoken.rs index 32045e658..b0f44538a 100644 --- a/contracts/nft-pixelboard/tests/utils/nftoken.rs +++ b/contracts/nft-pixelboard/tests/utils/nftoken.rs @@ -5,7 +5,7 @@ use gtest::{Program as InnerProgram, System}; use non_fungible_token_io::{Collection, Config, InitNFT}; use std::fs; -pub struct NonFungibleToken<'a>(InnerProgram<'a>, u64); +pub struct NonFungibleToken<'a>(InnerProgram<'a>); impl Program for NonFungibleToken<'_> { fn inner_program(&self) -> &InnerProgram<'_> { @@ -31,7 +31,7 @@ impl<'a> NonFungibleToken<'a> { ) .main_failed()); - Self(program, 0) + Self(program) } pub fn meta_state(&self) -> NonFungibleTokenMetaState<'_> { diff --git a/contracts/non-fungible-token/io/src/lib.rs b/contracts/non-fungible-token/io/src/lib.rs index 8bdcc7651..1320729b6 100644 --- a/contracts/non-fungible-token/io/src/lib.rs +++ b/contracts/non-fungible-token/io/src/lib.rs @@ -145,6 +145,8 @@ pub struct IoNft { pub token_id: TokenId, pub owner: ActorId, pub transactions: Vec<(H256, NFTEvent)>, + pub collection: Collection, + pub config: Config, } impl From<&NFTState> for IoNFTState { diff --git a/contracts/non-fungible-token/src/lib.rs b/contracts/non-fungible-token/src/lib.rs index 79033ecf4..2637e33dc 100644 --- a/contracts/non-fungible-token/src/lib.rs +++ b/contracts/non-fungible-token/src/lib.rs @@ -257,7 +257,8 @@ impl From for IoNft { token_id, owner, transactions, - .. + collection, + config, } = value; let transactions = transactions @@ -269,6 +270,8 @@ impl From for IoNft { token_id, owner, transactions, + collection, + config, } } } diff --git a/contracts/ping/src/lib.rs b/contracts/ping/src/lib.rs index df15dcbca..9d2454bc0 100644 --- a/contracts/ping/src/lib.rs +++ b/contracts/ping/src/lib.rs @@ -1,6 +1,6 @@ #![no_std] -use gstd::{debug, msg, prelude::*}; +use gstd::{msg, prelude::*}; static mut MESSAGE_LOG: Vec = vec![]; @@ -14,12 +14,6 @@ extern fn handle() { unsafe { MESSAGE_LOG.push(new_msg); - - debug!("{:?} total message(s) stored: ", MESSAGE_LOG.len()); - - for log in &MESSAGE_LOG { - debug!("{log:?}"); - } } } diff --git a/contracts/roll-the-dice/io/src/lib.rs b/contracts/roll-the-dice/io/src/lib.rs index 698cfbbcc..5472ff5a1 100644 --- a/contracts/roll-the-dice/io/src/lib.rs +++ b/contracts/roll-the-dice/io/src/lib.rs @@ -1,6 +1,6 @@ #![no_std] -use gmeta::{In, InOut, Metadata}; +use gmeta::{In, InOut, Metadata, Out}; use gstd::{collections::BTreeMap, prelude::*, ActorId}; pub struct ContractMetadata; @@ -11,7 +11,7 @@ impl Metadata for ContractMetadata { type Reply = (); type Others = (); type Signal = (); - type State = InOut; + type State = Out; } #[derive(Debug, Default, Decode, Encode, TypeInfo)] diff --git a/contracts/tequila-train/io/src/lib.rs b/contracts/tequila-train/io/src/lib.rs index 5935ce178..a112a9634 100644 --- a/contracts/tequila-train/io/src/lib.rs +++ b/contracts/tequila-train/io/src/lib.rs @@ -1,36 +1,46 @@ #![no_std] -use gmeta::{In, InOut, Metadata, Out}; +use gmeta::{In, InOut, Metadata}; use gstd::{ collections::{BTreeMap, BTreeSet}, + exec, msg, prelude::*, ActorId, }; -#[cfg(not(test))] -use gstd::{exec, msg}; - pub struct ContractMetadata; impl Metadata for ContractMetadata { - type Init = In; + type Init = In; type Handle = InOut>; type Others = (); type Reply = (); type Signal = (); - type State = Out; + type State = InOut; } -#[derive(Encode, Decode, TypeInfo)] -pub struct Init { - pub players_limit: Option, -} #[derive(Debug, Clone, Encode, Decode, TypeInfo)] pub struct GameLauncherState { - pub game_state: Option, - pub players: Vec<(ActorId, String)>, - pub is_started: bool, - pub maybe_limit: Option, + pub games: Vec<(ActorId, Game)>, + pub players_to_game_id: Vec<(ActorId, ActorId)>, + pub config: Config, +} + +#[derive(Encode, Decode, TypeInfo)] +pub enum StateQuery { + All, + GetGame { player_id: ActorId }, +} +#[derive(Encode, Decode, TypeInfo)] +pub enum StateReply { + All(GameLauncherState), + Game(Option<(Game, Option)>), +} + +#[derive(Debug, Default, Clone, Encode, Decode, TypeInfo)] +pub struct Config { + pub time_to_move: u32, + pub gas_to_check_game: u64, } #[derive( @@ -100,58 +110,43 @@ pub fn build_tile_collection() -> Vec { .collect() } -#[derive(Encode, Decode, TypeInfo, Debug)] -pub struct Players { - pub players: Vec<(ActorId, String)>, -} - -impl Players { - pub fn get(&self) -> Vec<(ActorId, String)> { - self.players.clone() - } - - pub fn count(&self) -> u64 { - self.players.len() as u64 - } -} - -impl From<[(ActorId, String); N]> for Players { - fn from(s: [(ActorId, String); N]) -> Players { - Players { - players: s.to_vec(), - } - } -} - -impl From<&[(ActorId, String)]> for Players { - fn from(s: &[(ActorId, String)]) -> Players { - Players { - players: s.to_vec(), - } - } -} - -#[derive(Encode, Decode, TypeInfo, Debug)] +#[derive(Encode, Decode, TypeInfo, Debug, PartialEq, Eq)] pub enum Command { - Skip, + CreateGame, + Skip { + creator: ActorId, + }, Place { + creator: ActorId, tile_id: u32, track_id: u32, remove_train: bool, }, Register { - player: ActorId, - name: String, + creator: ActorId, + }, + CancelRegistration { + creator: ActorId, + }, + DeletePlayer { + player_id: ActorId, + }, + CheckGame { + game_id: ActorId, + last_activity_time: u64, }, StartGame, - RestartGame( - /// Optional players limit. - Option, - ), + CancelGame, + LeaveGame, } #[derive(Encode, Decode, TypeInfo, Clone, Debug)] pub enum Event { + GameFinished { + winners: Vec, + all_participants: Vec, + }, + GameCreated, Skipped, Placed { tile_id: u32, @@ -160,32 +155,41 @@ pub enum Event { }, Registered { player: ActorId, - name: String, - }, - GameStarted, - GameRestarted { - players_limit: Option, }, - GameFinished { - winner: ActorId, + RegistrationCanceled, + PlayerDeleted { + player_id: ActorId, }, - GameStalled, + GameStarted, + GameCanceled, + GameLeft, + Checked, } #[derive(Debug, Clone, Encode, Decode, TypeInfo)] pub enum Error { - WrongPlayersCount, GameHasAlreadyStarted, GameHasNotStartedYet, - NameAlreadyExistsOrYouRegistered, + YouAlreadyRegistered, LimitHasBeenReached, - GameStalled, GameFinished, - NotYourTurn, + NotYourTurnOrYouLose, InvalidTile, InvalidTileId, InvalidTileOwner, InvalidTrack, + AlreadyExists, + GameDoesNotExist, + NotRegistered, + YouLose, + WrongBid, + NoSuchPlayer, + StateIsNotPlaying, + SeveralGames, + YouAreAdmin, + NotEnoughPlayers, + GameIsGoing, + OnlyProgramCanSend, } #[derive(Debug, TypeInfo, Encode, Decode, Clone, Default)] @@ -195,8 +199,24 @@ pub struct TrackData { } #[derive(Debug, TypeInfo, Encode, Decode, Clone, Default)] +pub struct Game { + pub admin: ActorId, + pub game_state: Option, + pub initial_players: Vec, + pub state: State, + pub is_started: bool, + pub bid: u128, +} + +#[derive(Encode, Decode, TypeInfo, Debug, Clone)] +pub struct Player { + pub id: ActorId, + pub lose: bool, +} + +#[derive(Debug, TypeInfo, Encode, Decode, Clone)] pub struct GameState { - pub players: Vec<(ActorId, String)>, + pub players: Vec, pub tracks: Vec, pub shots: Vec, pub start_tile: u32, @@ -204,14 +224,14 @@ pub struct GameState { pub tile_to_player: BTreeMap, pub tiles: Vec, pub remaining_tiles: BTreeSet, - pub state: State, + pub time_to_move: u32, + pub last_activity_time: u64, } -#[derive(Clone, Debug, Encode, Decode, TypeInfo, Default)] +#[derive(Clone, Debug, Encode, Decode, Default, TypeInfo, PartialEq, Eq)] pub enum State { Playing, - Stalled, - Winner((ActorId, String)), + Winners(Vec), #[default] Registration, } @@ -300,15 +320,14 @@ fn give_tiles_until_double( impl GameState { // TODO: cover it with tests - pub fn new(initial_data: &Players) -> Option { - // Check that players amount is allowed - let players_amount = initial_data.players.len(); - if !(2..=8).contains(&players_amount) { - return None; - } + pub fn new( + initial_players: Vec, + time_to_move: u32, + block_timestamp: u64, + ) -> Option { + let players_amount = initial_players.len(); let mut tile_to_player: BTreeMap = Default::default(); - // Build all possible tiles let tiles = build_tile_collection(); let mut remaining_tiles: BTreeSet = Default::default(); @@ -318,7 +337,7 @@ impl GameState { // Spread tiles to players let tiles_per_person = tiles_per_person(players_amount); - for player_index in 0..initial_data.players.len() { + for player_index in 0..initial_players.len() { for _ in 1..=tiles_per_person { let tile_id = get_random_from_set(&remaining_tiles); remaining_tiles.remove(&tile_id); @@ -352,38 +371,57 @@ impl GameState { // Remove starting tile from set tile_to_player.remove(&start_tile); + let players = initial_players + .into_iter() + .map(|id| Player { id, lose: false }) + .collect(); + + let current_player = (start_player + 1) % players_amount as u32; + Some(GameState { - players: initial_data.players.clone(), + players, tracks: vec![Default::default(); players_amount], shots: vec![0u32; players_amount], start_tile, - current_player: Self::next_player_impl(players_amount, start_player), + current_player, tile_to_player, tiles, remaining_tiles, - state: State::Playing, + time_to_move, + last_activity_time: block_timestamp, }) } - pub fn state(&self) -> State { - self.state.clone() - } - - pub fn skip_turn(&mut self, player: ActorId) -> Result { + pub fn skip_turn(&mut self, player: ActorId, bid: u128) -> Result { let i = self.current_player as usize; - if self.players[i].0 != player { - return Err(Error::NotYourTurn); + + if self.players[i].id != player { + return Err(Error::NotYourTurnOrYouLose); + } + + let count_players_is_live = self.players.iter().filter(|&player| !player.lose).count(); + let time = exec::block_timestamp(); + if count_players_is_live == 1 { + self.last_activity_time = time; + send_value(player, bid * self.players.len() as u128); + let all_participants = self.players.iter().map(|player| player.id).collect(); + return Ok(Event::GameFinished { + winners: vec![player], + all_participants, + }); } self.tracks[i].has_train = true; - if let Some(event) = self.post_actions() { + if let Some(event) = self.post_actions(bid) { + self.last_activity_time = time; return Ok(event); } + self.last_activity_time = time; Ok(Event::Skipped) } - fn post_actions(&mut self) -> Option { + fn post_actions(&mut self, bid: u128) -> Option { // check if the current player wins let remaining_tiles = self .tile_to_player @@ -391,16 +429,21 @@ impl GameState { .filter(|&player| *player == self.current_player) .count(); if remaining_tiles == 0 { - let (winner, name) = self.players[self.current_player as usize].clone(); - self.state = State::Winner((winner, name)); - return Some(Event::GameFinished { winner }); + let player = self.players[self.current_player as usize].clone(); + send_value(player.id, bid * self.players.len() as u128); + let all_participants = self.players.iter().map(|player| player.id).collect(); + return Some(Event::GameFinished { + winners: vec![player.id], + all_participants, + }); } // check if any next player is able to make a turn let players_to_check = self.players.len(); let check_result = (0..players_to_check).try_fold(self.current_player, |player, _| { - let next_player = self.next_player(player); - + let next_player = self + .next_player(player) + .expect("Error: there is no next player"); let remaining_tiles = self .tile_to_player .iter() @@ -420,8 +463,7 @@ impl GameState { self.current_player = next_player; return None; } - - if self.tracks[player_index].has_train { + if !self.remaining_tiles.is_empty() && self.tracks[player_index].has_train { // give the player randomly chosen tile let tile_id = get_random_from_set(&self.remaining_tiles); self.remaining_tiles.remove(&tile_id); @@ -437,24 +479,34 @@ impl GameState { Some(next_player) }); - if check_result.is_some() { - // no one can make turn. Game is over - self.state = State::Stalled; - return Some(Event::GameStalled); + if check_result.is_some() && self.remaining_tiles.is_empty() { + // no one can make turn. Point scoring + let winners = self.point_scoring(); + + let prize = bid * self.players.len() as u128 / winners.len() as u128; + + if bid != 0 { + winners.iter().for_each(|player| { + send_value(*player, prize); + }); + } + let all_participants = self.players.iter().map(|player| player.id).collect(); + return Some(Event::GameFinished { + winners, + all_participants, + }); } None } - fn next_player(&self, current_player: u32) -> u32 { - Self::next_player_impl(self.players.len(), current_player) - } - - fn next_player_impl(player_count: usize, current_player: u32) -> u32 { - let i = current_player as usize + 1; - match i < player_count { - true => i as u32, - false => 0, + pub fn next_player(&self, current_player: u32) -> Option { + for i in 1..=self.players.len() { + let index = (current_player as usize + i) % self.players.len(); + if !self.players[index].lose { + return Some(index as u32); + } } + None } // Helper function to check if any of the tiles can be put on any track. @@ -477,10 +529,23 @@ impl GameState { tile_id: u32, track_id: u32, remove_train: bool, + bid: u128, ) -> Result { let i = self.current_player as usize; - if self.players[i].0 != player { - return Err(Error::NotYourTurn); + + if self.players[i].id != player { + return Err(Error::NotYourTurnOrYouLose); + } + let count_players_is_live = self.players.iter().filter(|&player| !player.lose).count(); + let time = exec::block_timestamp(); + if count_players_is_live == 1 { + self.last_activity_time = time; + send_value(player, bid * self.players.len() as u128); + let all_participants = self.players.iter().map(|player| player.id).collect(); + return Ok(Event::GameFinished { + winners: vec![player], + all_participants, + }); } // check player owns the tile @@ -517,10 +582,13 @@ impl GameState { // remove tile from player's set self.tile_to_player.remove(&tile_id); + self.last_activity_time = exec::block_timestamp(); - if let Some(event) = self.post_actions() { + if let Some(event) = self.post_actions(bid) { + self.last_activity_time = time; return Ok(event); } + self.last_activity_time = time; Ok(Event::Placed { tile_id, track_id, @@ -546,6 +614,39 @@ impl GameState { None } + fn point_scoring(&self) -> Vec { + let mut scores: BTreeMap = BTreeMap::new(); + + for (tile, player) in &self.tile_to_player { + if !self.players[*player as usize].lose { + let tile_score = + self.tiles[*tile as usize].left as u8 + self.tiles[*tile as usize].right as u8; + scores + .entry(self.players[*player as usize].id) + .and_modify(|scores| *scores += tile_score as u16) + .or_insert(tile_score as u16); + } + } + + let min_score = scores.values().min().cloned(); + + scores + .iter() + .filter_map(|(actor_id, &score)| { + if Some(score) == min_score { + Some(*actor_id) + } else { + None + } + }) + .collect() + } +} + +pub fn send_value(destination: ActorId, value: u128) { + if value != 0 { + msg::send_with_gas(destination, "", 0, value).expect("Error in sending value"); + } } #[cfg(test)] diff --git a/contracts/tequila-train/io/src/test.rs b/contracts/tequila-train/io/src/test.rs index 8d09b01cc..99e320cf6 100644 --- a/contracts/tequila-train/io/src/test.rs +++ b/contracts/tequila-train/io/src/test.rs @@ -139,6 +139,7 @@ fn test_give_tiles_until_double_2() { fn test_give_tiles_until_double_3() { let players_amount = 5; let mut remaining_tiles: BTreeSet = Default::default(); + // println!("!@#"); let tiles = vec![ Tile::new(Face::Zero, Face::One), @@ -174,31 +175,12 @@ fn test_give_tiles_until_double_3() { assert_eq!(matching_tile_id.unwrap().1, 4); } -#[test] -fn test_game_state_fail_init() { - let actor1 = ActorId::new([1u8; 32]); - let players = Players { - players: vec![(actor1, "A".to_owned())], - }; - let game_state = GameState::new(&players); - assert!(game_state.is_none()); - - let players = Players { - players: vec![(actor1, "B".to_owned()); 9], - }; - let game_state = GameState::new(&players); - assert!(game_state.is_none()); -} - #[test] fn test_game_state() { let actor1 = ActorId::new([1u8; 32]); let actor2 = ActorId::new([2u8; 32]); - let players = Players { - players: vec![(actor1, "A".to_owned()), (actor2, "B".to_owned())], - }; - - let game_state = GameState::new(&players).unwrap(); + let players = vec![actor1, actor2]; + let game_state = GameState::new(players, 30_000, 10).unwrap(); let mut counters = (0u32, 0u32); for player_id in game_state.tile_to_player.values() { diff --git a/contracts/tequila-train/src/lib.rs b/contracts/tequila-train/src/lib.rs index 3f6a546db..9a4ffdadf 100644 --- a/contracts/tequila-train/src/lib.rs +++ b/contracts/tequila-train/src/lib.rs @@ -1,108 +1,288 @@ #![no_std] -use gstd::{msg, prelude::*, ActorId}; +use gstd::{collections::HashMap, exec, msg, prelude::*, ActorId}; use tequila_train_io::*; #[derive(Debug, Default)] pub struct GameLauncher { - pub game_state: Option, - pub players: Vec<(ActorId, String)>, - pub is_started: bool, - pub maybe_limit: Option, + pub games: HashMap, + pub players_to_game_id: HashMap, + pub config: Config, } -/// All game initializing logic is inside `GameState` constructor. static mut GAME_LAUNCHER: Option = None; impl GameLauncher { - fn check_limit_range(maybe_limit: Option) -> Result<(), Error> { - if let Some(limit) = maybe_limit { - if !(2..=8).contains(&limit) { - return Err(Error::WrongPlayersCount); - } + // creating a game session, after this action other users can register to the game using the creator's address. + pub fn create_game(&mut self, msg_source: ActorId, msg_value: u128) -> Result { + if self.players_to_game_id.contains_key(&msg_source) { + return Err(Error::SeveralGames); } - Ok(()) + + let mut game = Game { + admin: msg_source, + bid: msg_value, + ..Default::default() + }; + game.initial_players.push(msg_source); + self.games.insert(msg_source, game); + self.players_to_game_id.insert(msg_source, msg_source); + Ok(Event::GameCreated) } - fn check_players_count(&self) -> Result<(), Error> { - if !(2..=8).contains(&(self.players.len() as u32)) { - return Err(Error::WrongPlayersCount); + // Start the game and send a delayed message to check the timer + pub fn start(&mut self) -> Result { + let msg_src = msg::source(); + let game = self + .games + .get_mut(&msg_src) + .ok_or(Error::GameDoesNotExist)?; + + if game.is_started { + return Err(Error::GameHasAlreadyStarted); + } + if game.initial_players.len() < 2 { + return Err(Error::NotEnoughPlayers); } - Ok(()) + + game.is_started = true; + game.game_state = GameState::new( + game.initial_players.clone(), + self.config.time_to_move, + exec::block_timestamp(), + ); + game.state = State::Playing; + + // send a delayed message to check if the current player has made a move within the `config.time_to_move` limit + msg::send_with_gas_delayed( + exec::program_id(), + Command::CheckGame { + game_id: msg_src, + last_activity_time: game.game_state.clone().unwrap().last_activity_time, + }, + self.config.gas_to_check_game, + 0, + self.config.time_to_move / 3000, + ) + .expect("Error in sending delayed message"); + Ok(Event::GameStarted) } - pub fn new_with_limit(limit: u64) -> Self { - Self::check_limit_range(Some(limit)).expect("The limit should lie in the range [2,8]"); + // This function can only be called by the program itself + // and is used to check if the player has made a move within the time limit. + // If the player has not made a move, we mark the player as lost, + // change the current player and send the same delayed message to check another player. + // If only one player survives, we make that player the winner + pub fn check_game( + &mut self, + game_id: ActorId, + last_activity_time: u64, + ) -> Result { + let program_id = exec::program_id(); + if msg::source() != program_id { + return Err(Error::OnlyProgramCanSend); + } + let game = self + .games + .get_mut(&game_id) + .ok_or(Error::GameDoesNotExist)?; - GameLauncher { - maybe_limit: Some(limit), - ..Default::default() + let game_state = game + .game_state + .as_mut() + .ok_or(Error::GameHasNotStartedYet)?; + + // use the `last_activity_time` variable as an identifier of whether a move has been made + if game_state.last_activity_time == last_activity_time { + let current_player = game_state.current_player; + game_state.players[current_player as usize].lose = true; + // count how many players are left in the game + let count_players_is_live = game_state + .players + .iter() + .filter(|&player| !player.lose) + .count(); + + if count_players_is_live > 1 { + // change the current player to the next player who has not dropped out of the game + game_state.current_player = game_state + .next_player(current_player) + .expect("Live players more than 0"); + // change the time of last activity + game_state.last_activity_time = exec::block_timestamp(); + msg::send_delayed( + program_id, + Command::CheckGame { + game_id, + last_activity_time: game_state.last_activity_time, + }, + 0, + self.config.time_to_move / 3000, + ) + .expect("Error in sending delayed message"); + } else { + let winner_index = game_state + .next_player(current_player) + .expect("Live players more than 0"); + let winner = game_state.players[winner_index as usize].id; + let prize = game.bid; + if game.bid != 0 { + send_value(winner, prize * game.initial_players.len() as u128); + } + + game.state = State::Winners(vec![winner]); + msg::send( + winner, + Ok::(Event::GameFinished { + winners: vec![winner], + all_participants: game.initial_players.clone(), + }), + 0, + ) + .expect("Error in sending message"); + } } + Ok(Event::Checked) } - pub fn start(&mut self) -> Result { - if self.is_started { + // Registration for the game with the rate specified by the admin at the create of the game + // The address of the game creator is used as a game identifier + pub fn register( + &mut self, + msg_source: ActorId, + msg_value: u128, + creator: ActorId, + ) -> Result { + if self.players_to_game_id.contains_key(&msg_source) { + return Err(Error::SeveralGames); + } + let game = self + .games + .get_mut(&creator) + .ok_or(Error::GameDoesNotExist)?; + + if game.is_started { return Err(Error::GameHasAlreadyStarted); } - self.check_players_count()?; - self.is_started = true; - self.game_state = GameState::new(&Players { - players: self.players.clone(), - }); + if msg_value != game.bid { + return Err(Error::WrongBid); + } - assert!(self.game_state.is_some()); - Ok(Event::GameStarted) + if game.initial_players.contains(&msg_source) { + return Err(Error::YouAlreadyRegistered); + } + + if game.initial_players.len() >= 8 { + return Err(Error::LimitHasBeenReached); + } + + game.initial_players.push(msg_source); + self.players_to_game_id.insert(msg_source, creator); + Ok(Event::Registered { player: msg_source }) } - pub fn restart(&mut self, maybe_limit: Option) -> Result { - if !self.is_started { - return Err(Error::GameHasNotStartedYet); + // A registered player has the opportunity to leave the game and get his bet back + pub fn cancel_register(&mut self, creator: ActorId) -> Result { + let game = self + .games + .get_mut(&creator) + .ok_or(Error::GameDoesNotExist)?; + + let msg_src = msg::source(); + + if msg_src == game.admin { + return Err(Error::YouAreAdmin); + } + + if game.is_started { + return Err(Error::GameHasAlreadyStarted); + } + if !game.initial_players.contains(&msg_src) { + return Err(Error::NoSuchPlayer); + } + + send_value(msg_src, game.bid); + + if let Some(index_to_remove) = game.initial_players.iter().position(|id| id == &msg_src) { + game.initial_players.remove(index_to_remove); } - Self::check_limit_range(maybe_limit)?; + self.players_to_game_id.remove(&msg_src); - self.is_started = false; - self.game_state = None; - self.maybe_limit = maybe_limit; - self.players.clear(); - Ok(Event::GameRestarted { - players_limit: maybe_limit, - }) + Ok(Event::RegistrationCanceled) } - pub fn register(&mut self, player: ActorId, name: String) -> Result { - if self.is_started { + // An admin can forcibly remove a player at the moment of registration after which the bet is refunded + pub fn delete_player(&mut self, player_id: ActorId) -> Result { + let msg_src = msg::source(); + + let game = self + .games + .get_mut(&msg_src) + .ok_or(Error::GameDoesNotExist)?; + + if msg_src == player_id { + return Err(Error::YouAreAdmin); + } + + if game.is_started { return Err(Error::GameHasAlreadyStarted); } - if self.players.iter().any(|(p, n)| p == &player || n == &name) { - return Err(Error::NameAlreadyExistsOrYouRegistered); + if !game.initial_players.contains(&player_id) { + return Err(Error::NoSuchPlayer); } - if let Some(limit) = self.maybe_limit { - if (self.players.len() as u64) >= limit { - return Err(Error::LimitHasBeenReached); + send_value(player_id, game.bid); + let index_to_remove = game + .initial_players + .iter() + .position(|x| x == &player_id) + .expect("Critical Error"); + game.initial_players.remove(index_to_remove); + self.players_to_game_id.remove(&player_id); + + Ok(Event::PlayerDeleted { player_id }) + } + // The admin can forcibly end the game with all the players' bets going back + pub fn cancel_game(&mut self) -> Result { + let msg_src = msg::source(); + + let game = self + .games + .get_mut(&msg_src) + .ok_or(Error::GameDoesNotExist)?; + + // if the game is at the registration stage or the game is still in progress, + // we must refund everyone their bets and and remove them from the list of games + game.initial_players.iter().for_each(|id| { + if (game.state == State::Playing || game.state == State::Registration) && game.bid != 0 + { + send_value(*id, game.bid); } - } else if self.players.len() >= 8 { - return Err(Error::LimitHasBeenReached); - } + self.players_to_game_id.remove(id); + }); + + self.games.remove(&msg_src); - self.players.push((player, name.clone())); - Ok(Event::Registered { player, name }) + Ok(Event::GameCanceled) + } + // leave the game (uses when the game has already passed to remove yourself from the list of `players_to_game_id`) + pub fn leave_game(&mut self) -> Result { + self.players_to_game_id.remove(&msg::source()); + Ok(Event::GameLeft) } } #[no_mangle] extern fn init() { - let Init { players_limit } = msg::load().expect("Unexpected invalid payload."); - - unsafe { - GAME_LAUNCHER = Some(if let Some(limit) = players_limit { - GameLauncher::new_with_limit(limit) - } else { - GameLauncher::default() - }) - } + let config: Config = msg::load().expect("Unable to decode the initial msg"); + let game_launcher = GameLauncher { + config, + ..Default::default() + }; + + unsafe { GAME_LAUNCHER = Some(game_launcher) }; } #[no_mangle] @@ -118,43 +298,139 @@ fn process_handle() -> Result { .expect("The contract is not initialized") }; - if let Some(game_state) = &game_launcher.game_state { - match game_state.state() { - State::Stalled => { - return Err(Error::GameStalled); - } - State::Winner(_winner) => { - return Err(Error::GameFinished); - } - _ => (), - }; - } - let command: Command = msg::load().expect("Unexpected invalid command payload."); - let player = msg::source(); match command { - Command::Skip => { - if let Some(game_state) = &mut game_launcher.game_state { - game_state.skip_turn(player) + Command::CreateGame => { + let msg_source = msg::source(); + let msg_value = msg::value(); + let reply = game_launcher.create_game(msg_source, msg_value); + if reply.is_err() { + send_value(msg_source, msg_value); + } + reply + } + Command::Skip { creator } => { + let game = game_launcher + .games + .get_mut(&creator) + .ok_or(Error::GameDoesNotExist)?; + + // a move can only be made with State::Playing + if game.state != State::Playing { + return Err(Error::StateIsNotPlaying); + } + let player = msg::source(); + // a non-registered player cannot make a move + if !game.initial_players.contains(&player) { + return Err(Error::NotRegistered); + } + if let Some(game_state) = &mut game.game_state { + let result = game_state.skip_turn(player, game.bid); + match result { + // if the game is over, we change the game state + Ok(Event::GameFinished { ref winners, .. }) => { + game.state = State::Winners(winners.clone()); + } + // if the move is successful, we must send a delayed message to check if the next player has made a move + Ok(Event::Skipped) => { + msg::send_with_gas_delayed( + exec::program_id(), + Command::CheckGame { + game_id: creator, + last_activity_time: game + .game_state + .clone() + .unwrap() + .last_activity_time, + }, + game_launcher.config.gas_to_check_game, + 0, + game_launcher.config.time_to_move / 3000, + ) + .expect("Error in sending delayed message"); + } + _ => (), + } + + result } else { Err(Error::GameHasNotStartedYet) } } Command::Place { + creator, tile_id, track_id, remove_train, } => { - if let Some(game_state) = &mut game_launcher.game_state { - game_state.make_turn(player, tile_id, track_id, remove_train) + let game = game_launcher + .games + .get_mut(&creator) + .ok_or(Error::GameDoesNotExist)?; + + // a move can only be made with State::Playing + if game.state != State::Playing { + return Err(Error::GameHasNotStartedYet); + } + + let player = msg::source(); + // a non-registered player cannot make a move + if !game.initial_players.contains(&player) { + return Err(Error::NotRegistered); + } + if let Some(game_state) = &mut game.game_state { + let result = + game_state.make_turn(player, tile_id, track_id, remove_train, game.bid); + match result { + // if the game is over, we change the game state + Ok(Event::GameFinished { ref winners, .. }) => { + game.state = State::Winners(winners.clone()); + } + // if the move is successful, we must send a delayed message to check if the next player has made a move + Ok(Event::Placed { .. }) => { + msg::send_with_gas_delayed( + exec::program_id(), + Command::CheckGame { + game_id: creator, + last_activity_time: game + .game_state + .clone() + .unwrap() + .last_activity_time, + }, + game_launcher.config.gas_to_check_game, + 0, + game_launcher.config.time_to_move / 3000, + ) + .expect("Error in sending delayed message"); + } + _ => (), + } + + result } else { Err(Error::GameHasNotStartedYet) } } - Command::Register { player, name } => game_launcher.register(player, name), + Command::Register { creator } => { + let msg_source = msg::source(); + let msg_value = msg::value(); + let reply = game_launcher.register(msg_source, msg_value, creator); + if reply.is_err() { + send_value(msg_source, msg_value); + } + reply + } + Command::CancelRegistration { creator } => game_launcher.cancel_register(creator), + Command::DeletePlayer { player_id } => game_launcher.delete_player(player_id), + Command::CheckGame { + game_id, + last_activity_time, + } => game_launcher.check_game(game_id, last_activity_time), Command::StartGame => game_launcher.start(), - Command::RestartGame(maybe_limit) => game_launcher.restart(maybe_limit), + Command::CancelGame => game_launcher.cancel_game(), + Command::LeaveGame => game_launcher.leave_game(), } } @@ -165,25 +441,47 @@ extern fn state() { .take() .expect("Game launcher is not initialized") }; + let query: StateQuery = msg::load().expect("Unable to load the state query"); + let reply = match query { + StateQuery::All => StateReply::All(game_launcher.into()), + StateQuery::GetGame { player_id } => { + if let Some(creator_id) = game_launcher.players_to_game_id.get(&player_id) { + let game_reply = game_launcher + .games + .get(creator_id) + .map(|game| { + let last_activity_time_diff = game.game_state.as_ref().and_then(|state| { + (game_launcher.config.time_to_move as u64) + .checked_sub(exec::block_timestamp() - state.last_activity_time) + }); + (game.clone(), last_activity_time_diff) + }) + .map(Some) + .unwrap_or(None); - msg::reply::(game_launcher.into(), 0) - .expect("Failed to encode or reply with the game state"); + StateReply::Game(game_reply) + } else { + StateReply::Game(None) + } + } + }; + msg::reply(reply, 0).expect("Failed to encode or reply with the game state"); } impl From for GameLauncherState { fn from( GameLauncher { - game_state, - players, - is_started, - maybe_limit, + games, + config, + players_to_game_id, }: GameLauncher, ) -> Self { + let games = games.into_iter().collect(); + let players_to_game_id = players_to_game_id.into_iter().collect(); Self { - game_state, - players, - is_started, - maybe_limit, + games, + config, + players_to_game_id, } } } diff --git a/contracts/tequila-train/tests/test.rs b/contracts/tequila-train/tests/test.rs index 92ab65c37..41e337839 100644 --- a/contracts/tequila-train/tests/test.rs +++ b/contracts/tequila-train/tests/test.rs @@ -2,77 +2,114 @@ use gstd::{ActorId, Encode}; use gtest::{Program, System}; use tequila_train_io::*; +pub const PLAYERS: [u64; 3] = [10, 11, 12]; + pub trait TestFunc { - fn register(&self, from: u64, player: ActorId, name: String, error: Option); + fn create_game(&self, from: u64, bid: u128, error: Option); + fn register(&self, from: u64, bid: u128, creator: ActorId, error: Option); + fn cancel_register(&self, from: u64, creator: ActorId, error: Option); + fn delete_player(&self, from: u64, player_id: ActorId, error: Option); + fn cancel_game(&self, from: u64, error: Option); fn start_game(&self, from: u64, error: Option); - fn restart_game(&self, from: u64, players_limit: Option, error: Option); - fn skip(&self, from: u64, error: Option); + fn skip(&self, from: u64, creator: ActorId, error: Option); fn place( &self, from: u64, + creator: ActorId, tile_id: u32, track_id: u32, remove_train: bool, error: Option, ); + fn get_all_state(&self) -> Option; + fn get_game_state(&self, creator_id: ActorId) -> Option<(Game, Option)>; } impl TestFunc for Program<'_> { - fn register(&self, from: u64, player: ActorId, name: String, error: Option) { - let result = self.send( - from, - Command::Register { - player, - name: name.clone(), - }, - ); + fn create_game(&self, from: u64, bid: u128, error: Option) { + let result = self.send_with_value(from, Command::CreateGame, bid); assert!(!result.main_failed()); let reply = if let Some(error) = error { Err(error) } else { - Ok(Event::Registered { player, name }) + Ok(Event::GameCreated) }; assert!(result.contains(&(from, reply.encode()))); } - fn start_game(&self, from: u64, error: Option) { - let result = self.send(from, Command::StartGame); + fn register(&self, from: u64, bid: u128, creator: ActorId, error: Option) { + let result = self.send_with_value(from, Command::Register { creator }, bid); assert!(!result.main_failed()); - let reply: Result; - if let Some(error) = error { - reply = Err(error); - assert!(result.contains(&(from, reply.encode()))); + let reply = if let Some(error) = error { + Err(error) } else { - reply = Ok(Event::GameStarted); - assert!(result.contains(&(from, reply.encode()))); - } + Ok(Event::Registered { + player: from.into(), + }) + }; + assert!(result.contains(&(from, reply.encode()))); } - fn restart_game(&self, from: u64, players_limit: Option, error: Option) { - let result = self.send(from, Command::RestartGame(players_limit)); + fn cancel_register(&self, from: u64, creator: ActorId, error: Option) { + let result = self.send(from, Command::CancelRegistration { creator }); assert!(!result.main_failed()); - let reply: Result; - if let Some(error) = error { - reply = Err(error); - assert!(result.contains(&(from, reply.encode()))); + let reply = if let Some(error) = error { + Err(error) } else { - reply = Ok(Event::GameRestarted { players_limit }); - assert!(result.contains(&(from, reply.encode()))); - } + Ok(Event::RegistrationCanceled) + }; + assert!(result.contains(&(from, reply.encode()))); } - fn skip(&self, from: u64, error: Option) { - let result = self.send(from, Command::Skip); + fn delete_player(&self, from: u64, player_id: ActorId, error: Option) { + let result = self.send(from, Command::DeletePlayer { player_id }); + let res = &result.decoded_log::>(); + println!("RES: {:?}", res); assert!(!result.main_failed()); - let reply: Result; - if let Some(error) = error { - reply = Err(error); - assert!(result.contains(&(from, reply.encode()))); + let reply = if let Some(error) = error { + Err(error) } else { - reply = Ok(Event::Skipped); - assert!(result.contains(&(from, reply.encode()))); - } + Ok(Event::PlayerDeleted { player_id }) + }; + assert!(result.contains(&(from, reply.encode()))); + } + fn cancel_game(&self, from: u64, error: Option) { + let result = self.send(from, Command::CancelGame); + let res = &result.decoded_log::>(); + println!("RES: {:?}", res); + assert!(!result.main_failed()); + let reply = if let Some(error) = error { + Err(error) + } else { + Ok(Event::GameCanceled) + }; + assert!(result.contains(&(from, reply.encode()))); + } + fn start_game(&self, from: u64, error: Option) { + let result = self.send(from, Command::StartGame); + assert!(!result.main_failed()); + let res = &result.decoded_log::>(); + println!("RES: {:?}", res); + let reply = if let Some(error) = error { + Err(error) + } else { + Ok(Event::GameStarted) + }; + assert!(result.contains(&(from, reply.encode()))); + } + fn skip(&self, from: u64, creator: ActorId, error: Option) { + let result = self.send(from, Command::Skip { creator }); + assert!(!result.main_failed()); + let res = &result.decoded_log::>(); + println!("RES: {:?}", res); + let reply = if let Some(error) = error { + Err(error) + } else { + Ok(Event::Skipped) + }; + assert!(result.contains(&(from, reply.encode()))); } fn place( &self, from: u64, + creator: ActorId, tile_id: u32, track_id: u32, remove_train: bool, @@ -81,23 +118,44 @@ impl TestFunc for Program<'_> { let result = self.send( from, Command::Place { + creator, tile_id, track_id, remove_train, }, ); + let res = &result.decoded_log::>(); + println!("RES: {:?}", res); assert!(!result.main_failed()); - let reply: Result; - if let Some(error) = error { - reply = Err(error); - assert!(result.contains(&(from, reply.encode()))); + let reply = if let Some(error) = error { + Err(error) } else { - reply = Ok(Event::Placed { + Ok(Event::Placed { tile_id, track_id, remove_train, - }); - assert!(result.contains(&(from, reply.encode()))); + }) + }; + assert!(result.contains(&(from, reply.encode()))); + } + fn get_all_state(&self) -> Option { + let reply = self + .read_state(StateQuery::All) + .expect("Unexpected invalid state."); + if let StateReply::All(state) = reply { + Some(state) + } else { + None + } + } + fn get_game_state(&self, player_id: ActorId) -> Option<(Game, Option)> { + let reply = self + .read_state(StateQuery::GetGame { player_id }) + .expect("Unexpected invalid state."); + if let StateReply::Game(state) = reply { + state + } else { + None } } } @@ -109,47 +167,174 @@ fn success_test() { let program = Program::current_opt(&system); - let result = program.send(2, 0); + let config = Config { + time_to_move: 30_000, + gas_to_check_game: 200_000_000_000, + }; + + let result = program.send(2, config); assert!(!result.main_failed()); - program.register(2, 0.into(), "A".to_owned(), None); - program.register(2, 1.into(), "B".to_owned(), None); - program.start_game(2, None); + program.create_game(PLAYERS[0], 0, None); + + program.register(PLAYERS[1], 0, PLAYERS[0].into(), None); + program.register(PLAYERS[2], 0, PLAYERS[0].into(), None); + program.start_game(PLAYERS[0], None); let state: GameLauncherState = program - .read_state(0) + .get_all_state() .expect("Unexpected invalid game state."); - assert_eq!( - state - .game_state - .expect("Invalid game state. Game is not initialized.") - .players, - vec![(0.into(), "A".to_owned()), (1.into(), "B".to_owned())] + println!("STATE: {:?}", state); + + let game = state.games[0].1.game_state.clone().unwrap(); + let current_player = game.current_player; + + program.skip(PLAYERS[current_player as usize], PLAYERS[0].into(), None); + + system.spend_blocks(3); + let current_player = (current_player + 1) as usize % PLAYERS.len(); + program.skip(PLAYERS[current_player], PLAYERS[0].into(), None); + + system.spend_blocks(8); + let state = program + .get_game_state(PLAYERS[0].into()) + .expect("Unexpected invalid game state."); + println!("STATE: {:?}", state); + system.spend_blocks(2); + let current_player = (current_player + 1) % PLAYERS.len(); + program.skip( + PLAYERS[current_player], + PLAYERS[0].into(), + Some(Error::NotYourTurnOrYouLose), ); +} +#[test] +fn cancel_register() { + let system = System::new(); + + system.init_logger(); + + let program = Program::current_opt(&system); + + let config = Config { + time_to_move: 30_000, + gas_to_check_game: 200_000_000_000, + }; + + let result = program.send(2, config); + assert!(!result.main_failed()); + + let bid = 11_000_000_000_000; + system.mint_to(PLAYERS[0], bid); + program.create_game(PLAYERS[0], bid, None); - program.restart_game(2, None, None); - program.register(2, 2.into(), "C".to_owned(), None); - program.register(2, 3.into(), "D".to_owned(), None); - program.start_game(2, None); + system.mint_to(PLAYERS[1], bid); + program.register(PLAYERS[1], bid, PLAYERS[0].into(), None); + let balance = system.balance_of(PLAYERS[1]); + assert_eq!(balance, 0); let state: GameLauncherState = program - .read_state(0) + .get_all_state() .expect("Unexpected invalid game state."); + assert_eq!(state.games[0].1.initial_players.len(), 2); + + program.cancel_register(PLAYERS[1], PLAYERS[0].into(), None); + system.claim_value_from_mailbox(PLAYERS[1]); + let balance = system.balance_of(PLAYERS[1]); + assert_eq!(balance, bid); + + let state: GameLauncherState = program + .get_all_state() + .expect("Unexpected invalid game state."); + assert_eq!(state.games[0].1.initial_players.len(), 1); + assert_eq!(state.players_to_game_id.len(), 1); +} + +#[test] +fn delete_player() { + let system = System::new(); + + system.init_logger(); + + let program = Program::current_opt(&system); + + let config = Config { + time_to_move: 30_000, + gas_to_check_game: 200_000_000_000, + }; + + let result = program.send(2, config); + assert!(!result.main_failed()); + + let bid = 11_000_000_000_000; + system.mint_to(PLAYERS[0], bid); + program.create_game(PLAYERS[0], bid, None); + + system.mint_to(PLAYERS[1], bid); + program.register(PLAYERS[1], bid, PLAYERS[0].into(), None); + let balance = system.balance_of(PLAYERS[1]); + assert_eq!(balance, 0); + + let state: GameLauncherState = program + .get_all_state() + .expect("Unexpected invalid game state."); + assert_eq!(state.games[0].1.initial_players.len(), 2); + + program.delete_player(PLAYERS[0], PLAYERS[1].into(), None); + system.claim_value_from_mailbox(PLAYERS[1]); + let balance = system.balance_of(PLAYERS[1]); + assert_eq!(balance, bid); - assert_eq!( - state - .game_state - .expect("Invalid game state. Game is not initialized.") - .players, - vec![(2.into(), "C".to_owned()), (3.into(), "D".to_owned())] - ); - program.place(2, 27, 0, false, None); let state: GameLauncherState = program - .read_state(0) + .get_all_state() .expect("Unexpected invalid game state."); - assert!(!state.game_state.unwrap().tracks[0].tiles.is_empty()); - program.skip(2, None); - program.skip(3, None); + assert_eq!(state.games[0].1.initial_players.len(), 1); + assert_eq!(state.players_to_game_id.len(), 1); +} + +#[test] +fn cancel_game() { + let system = System::new(); + + system.init_logger(); + + let program = Program::current_opt(&system); + + let config = Config { + time_to_move: 30_000, + gas_to_check_game: 200_000_000_000, + }; + + let result = program.send(2, config); + assert!(!result.main_failed()); + + let bid = 11_000_000_000_000; + system.mint_to(PLAYERS[0], bid); + program.create_game(PLAYERS[0], bid, None); + + system.mint_to(PLAYERS[1], bid); + program.register(PLAYERS[1], bid, PLAYERS[0].into(), None); + let balance = system.balance_of(PLAYERS[1]); + assert_eq!(balance, 0); + + let state: GameLauncherState = program + .get_all_state() + .expect("Unexpected invalid game state."); + assert!(!state.games.is_empty()); + + program.cancel_game(PLAYERS[0], None); + system.claim_value_from_mailbox(PLAYERS[1]); + let balance = system.balance_of(PLAYERS[1]); + assert_eq!(balance, bid); + system.claim_value_from_mailbox(PLAYERS[0]); + let balance = system.balance_of(PLAYERS[0]); + assert_eq!(balance, bid); + + let state: GameLauncherState = program + .get_all_state() + .expect("Unexpected invalid game state."); + assert!(state.games.is_empty()); + assert_eq!(state.players_to_game_id.len(), 0); } #[test] @@ -160,55 +345,80 @@ fn failures_test() { let program = Program::current_opt(&system); - let result = program.send(2, Some(2_u64)); + let config = Config { + time_to_move: 30_000, + gas_to_check_game: 200_000_000_000, + }; + + let result = program.send(2, config); assert!(!result.main_failed()); - program.start_game(2, Some(Error::WrongPlayersCount)); - program.restart_game(2, None, Some(Error::GameHasNotStartedYet)); - program.register(2, 0.into(), "A".to_owned(), None); + // After each error, a balance check will be made to verify the balance return + + // Сan't create multiple games + let bid = 11_000_000_000_000; + system.mint_to(PLAYERS[0], 2 * bid); + program.create_game(PLAYERS[0], bid, None); + program.create_game(PLAYERS[0], bid, Some(Error::SeveralGames)); + system.claim_value_from_mailbox(PLAYERS[0]); + assert_eq!(system.balance_of(PLAYERS[0]), bid); + + // You can't play one game and be an admin in another game + system.mint_to(PLAYERS[1], 2 * bid); + program.register(PLAYERS[1], bid, PLAYERS[0].into(), None); + program.create_game(PLAYERS[1], bid, Some(Error::SeveralGames)); + system.claim_value_from_mailbox(PLAYERS[1]); + assert_eq!(system.balance_of(PLAYERS[1]), bid); + + // A non-existent game id has been entered + system.mint_to(PLAYERS[2], 2 * bid); program.register( - 2, - 1.into(), - "A".to_owned(), - Some(Error::NameAlreadyExistsOrYouRegistered), + PLAYERS[2], + bid, + PLAYERS[1].into(), + Some(Error::GameDoesNotExist), ); + system.claim_value_from_mailbox(PLAYERS[2]); + assert_eq!(system.balance_of(PLAYERS[2]), 2 * bid); + // Wrong bid program.register( - 2, - 0.into(), - "B".to_owned(), - Some(Error::NameAlreadyExistsOrYouRegistered), + PLAYERS[2], + bid - 1, + PLAYERS[0].into(), + Some(Error::WrongBid), ); - program.register(2, 1.into(), "B".to_owned(), None); + system.claim_value_from_mailbox(PLAYERS[2]); + assert_eq!(system.balance_of(PLAYERS[2]), 2 * bid); + // Already registered program.register( - 2, - 3.into(), - "C".to_owned(), - Some(Error::LimitHasBeenReached), + PLAYERS[1], + bid, + PLAYERS[0].into(), + Some(Error::SeveralGames), ); - - program.start_game(2, None); + system.claim_value_from_mailbox(PLAYERS[1]); + assert_eq!(system.balance_of(PLAYERS[1]), bid); + // Registered In Another Game + program.create_game(PLAYERS[2], bid, None); program.register( - 2, - 3.into(), - "C".to_owned(), - Some(Error::GameHasAlreadyStarted), + PLAYERS[1], + bid, + PLAYERS[2].into(), + Some(Error::SeveralGames), ); - program.start_game(2, Some(Error::GameHasAlreadyStarted)); + system.claim_value_from_mailbox(PLAYERS[1]); + assert_eq!(system.balance_of(PLAYERS[1]), bid); - let state: GameLauncherState = program - .read_state(0) - .expect("Unexpected invalid game state."); - assert_eq!( - state - .game_state - .expect("Invalid game state. Game is not initialized.") - .players, - vec![(0.into(), "A".to_owned()), (1.into(), "B".to_owned())] - ); + // Admin try cancel register + program.cancel_register(PLAYERS[0], PLAYERS[0].into(), Some(Error::YouAreAdmin)); + + // No Such Player in registration list + program.cancel_register(PLAYERS[2], PLAYERS[0].into(), Some(Error::NoSuchPlayer)); + + // players less than 2 + program.start_game(PLAYERS[2], Some(Error::NotEnoughPlayers)); - program.restart_game(2, Some(10), Some(Error::WrongPlayersCount)); - program.place(3, 0, 0, false, Some(Error::NotYourTurn)); - program.place(0, 3, 0, false, Some(Error::InvalidTileId)); - program.place(0, 1, 1, false, Some(Error::InvalidTrack)); - program.place(0, 1, 0, false, Some(Error::InvalidTile)); + // the game has already started + program.start_game(PLAYERS[0], None); + program.start_game(PLAYERS[0], Some(Error::GameHasAlreadyStarted)); } diff --git a/contracts/vara-man/Cargo.toml b/contracts/vara-man/Cargo.toml index c2d81240c..5edc18108 100644 --- a/contracts/vara-man/Cargo.toml +++ b/contracts/vara-man/Cargo.toml @@ -5,8 +5,9 @@ edition.workspace = true publish.workspace = true [dependencies] -gstd.workspace = true +gstd = { workspace = true, features = ["debug"] } vara-man-io.workspace = true +fungible-token-io.workspace = true [dev-dependencies] gstd.workspace = true @@ -14,6 +15,12 @@ gtest.workspace = true gclient.workspace = true tokio.workspace = true blake2-rfc.workspace = true +gear-core.workspace = true +sp-core.workspace = true +hex = "0.4.3" + +# External binaries +fungible-token.workspace = true [build-dependencies] vara-man-io.workspace = true diff --git a/contracts/vara-man/io/Cargo.toml b/contracts/vara-man/io/Cargo.toml index 54cb59289..aacfe7c9a 100644 --- a/contracts/vara-man/io/Cargo.toml +++ b/contracts/vara-man/io/Cargo.toml @@ -5,7 +5,7 @@ edition.workspace = true publish.workspace = true [dependencies] -gstd.workspace = true +gstd = { workspace = true, features = ["debug"] } gmeta.workspace = true parity-scale-codec.workspace = true scale-info.workspace = true diff --git a/contracts/vara-man/io/src/lib.rs b/contracts/vara-man/io/src/lib.rs index 44205eb18..85fb5343e 100644 --- a/contracts/vara-man/io/src/lib.rs +++ b/contracts/vara-man/io/src/lib.rs @@ -6,14 +6,8 @@ use gmeta::{In, InOut, Metadata}; use gstd::{prelude::*, ActorId}; pub use rand::*; -pub const MAP_WIDTH: usize = 17; -pub const MAP_HEIGHT: usize = 12; -pub const MAP_CELLS: usize = MAP_WIDTH * MAP_HEIGHT; -pub const MAX_PERCENTAGE: u128 = 100; -pub const GAME_TIMEOUT_MS: i64 = 300_000; +pub const MAX_PARTICIPANTS: u16 = 10; -// pub type GameSeed = u64; // for random generation -pub type Map = [[Entity; MAP_WIDTH]; MAP_HEIGHT]; pub struct VaraManMetadata; impl Metadata for VaraManMetadata { @@ -30,26 +24,96 @@ pub struct VaraManInit { pub config: Config, } +#[derive(Debug, Clone, Encode, Decode, TypeInfo)] +pub struct TournamentState { + pub tournament_name: String, + pub admin: ActorId, + pub level: Level, + pub participants: Vec<(ActorId, Player)>, + pub bid: u128, + pub stage: Stage, + pub duration_ms: u32, +} +#[derive(Debug, Clone, Encode, Decode, TypeInfo)] +pub struct SingleGame { + pub level: Level, + pub points: u128, + pub start_time: u64, + pub game_over: bool, +} + #[derive(Debug, Encode, Decode, TypeInfo)] pub enum VaraManEvent { GameFinished { - player_address: ActorId, - silver_coins: u64, - gold_coins: u64, + winners: Vec, + participants: Vec, + prize: u128, + }, + SingleGameFinished { + prize: u128, + }, + NewTournamentCreated { + tournament_name: String, + name: String, + level: Level, + bid: u128, + }, + PlayerRegistered { + admin_id: ActorId, + name: String, + bid: u128, + }, + RegisterCanceled, + TournamentCanceled { + admin_id: ActorId, + }, + PlayerDeleted { + player_id: ActorId, + }, + ResultTournamentRecorded { + time: u128, + points: u128, }, GameStarted, AdminAdded(ActorId), - PlayerRegistered(ActorId), StatusChanged(Status), ConfigChanged(Config), - Error(String), + LeftGame, } #[derive(Debug, Clone, Encode, Decode, TypeInfo)] pub enum VaraManAction { - StartGame { level: Level }, - RegisterPlayer { name: String }, - ClaimReward { silver_coins: u64, gold_coins: u64 }, + CreateNewTournament { + tournament_name: String, + name: String, + level: Level, + duration_ms: u32, + }, + StartTournament, + RegisterForTournament { + admin_id: ActorId, + name: String, + }, + CancelRegister, + CancelTournament, + DeletePlayer { + player_id: ActorId, + }, + RecordTournamentResult { + time: u128, + gold_coins: u128, + silver_coins: u128, + }, + FinishTournament { + admin_id: ActorId, + time_start: u64, + }, + FinishSingleGame { + gold_coins: u128, + silver_coins: u128, + level: Level, + }, + LeaveGame, ChangeStatus(Status), ChangeConfig(Config), AddAdmin(ActorId), @@ -57,27 +121,34 @@ pub enum VaraManAction { #[derive(Debug, Clone, Encode, Decode, TypeInfo, PartialEq, Eq)] pub enum VaraManError { - WrongStatus, + GameIsPaused, EmptyName, - AlreadyRegistered, + AlreadyHaveTournament, + NoSuchGame, + NoSuchPlayer, + WrongBid, + SeveralRegistrations, + SeveralGames, NotRegistered, GameDoesNotExist, - AlreadyStartGame, - LivesEnded, AmountGreaterThanAllowed, - TransferFailed, + TransferNativeTokenFailed, + TransferFungibleTokenFailed, ThereIsNoSuchGame, NotAdmin, ConfigIsInvalid, + SessionFull, + WrongStage, + WrongTypeOfGame, + AccessDenied, + MultipleError, + GameOver, } #[derive(Encode, Decode, TypeInfo)] pub enum StateQuery { All, - AllGames, - AllPlayers, - Game { player_address: ActorId }, - Player { player_address: ActorId }, + GetTournament { player_id: ActorId }, Config, Admins, Status, @@ -85,20 +156,17 @@ pub enum StateQuery { #[derive(Encode, Decode, TypeInfo)] pub enum StateReply { - All(VaraMan), - AllGames(Vec<(ActorId, GameInstance)>), - AllPlayers(Vec<(ActorId, Player)>), - Game(Option), + All(VaraManState), + Tournament(Option<(TournamentState, Option)>), Config(Config), Admins(Vec), Status(Status), - Player(Option), } #[derive(Debug, Default, Clone, Encode, Decode, TypeInfo)] -pub struct VaraMan { - pub games: Vec<(ActorId, GameInstance)>, - pub players: Vec<(ActorId, Player)>, +pub struct VaraManState { + pub tournaments: Vec<(ActorId, TournamentState)>, + pub players_to_game_id: Vec<(ActorId, ActorId)>, pub status: Status, pub config: Config, pub admins: Vec, @@ -108,41 +176,48 @@ pub struct VaraMan { pub enum Status { #[default] Paused, - Started, + StartedUnrewarded, + StartedWithFungibleToken { + ft_address: ActorId, + }, + StartedWithNativeToken, +} + +#[derive(Debug, Default, Clone, PartialEq, Eq, Encode, Decode, TypeInfo)] +pub enum Stage { + #[default] + Registration, + Started(u64), + Finished(Vec), } #[derive(Debug, Default, Clone, Copy, Encode, Decode, TypeInfo)] pub struct Config { - pub one_coin_in_value: u64, - pub tokens_per_gold_coin_easy: u64, - pub tokens_per_silver_coin_easy: u64, - pub tokens_per_gold_coin_medium: u64, - pub tokens_per_silver_coin_medium: u64, - pub tokens_per_gold_coin_hard: u64, - pub tokens_per_silver_coin_hard: u64, - pub gold_coins: u64, - pub silver_coins: u64, - pub number_of_lives: u64, + pub one_point_in_value: u128, + pub points_per_gold_coin_easy: u128, + pub points_per_silver_coin_easy: u128, + pub points_per_gold_coin_medium: u128, + pub points_per_silver_coin_medium: u128, + pub points_per_gold_coin_hard: u128, + pub points_per_silver_coin_hard: u128, + pub gas_for_finish_tournament: u64, + pub time_for_single_round: u32, } impl Config { - pub fn is_valid(&self) -> bool { - self.gold_coins + self.silver_coins <= MAP_CELLS as u64 - } - - pub fn get_tokens_per_gold_coin_for_level(&self, level: Level) -> (u64, u64) { + pub fn get_points_per_gold_coin_for_level(&self, level: Level) -> (u128, u128) { match level { Level::Easy => ( - self.tokens_per_gold_coin_easy, - self.tokens_per_silver_coin_easy, + self.points_per_gold_coin_easy, + self.points_per_silver_coin_easy, ), Level::Medium => ( - self.tokens_per_gold_coin_medium, - self.tokens_per_silver_coin_medium, + self.points_per_gold_coin_medium, + self.points_per_silver_coin_medium, ), Level::Hard => ( - self.tokens_per_gold_coin_hard, - self.tokens_per_silver_coin_hard, + self.points_per_gold_coin_hard, + self.points_per_silver_coin_hard, ), } } @@ -151,19 +226,13 @@ impl Config { #[derive(Debug, Clone, PartialEq, Eq, Encode, Decode, TypeInfo)] pub struct Player { pub name: String, - pub lives: u64, - pub claimed_gold_coins: u64, - pub claimed_silver_coins: u64, -} - -impl Player { - pub fn is_have_lives(&self) -> bool { - self.lives > 0 - } + pub time: u128, + pub points: u128, } -#[derive(Debug, Clone, Copy, PartialEq, Eq, Encode, Decode, TypeInfo)] +#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Encode, Decode, TypeInfo)] pub enum Level { + #[default] Easy, Medium, Hard, @@ -175,207 +244,3 @@ pub enum Effect { Slow, Blind, } - -#[derive(Debug, Clone, Copy, PartialEq, Eq, Encode, Decode, TypeInfo)] -pub enum Entity { - /// 25% chance to spawn. - Empty, - /// 10% chance to spawn. - GoldCoin(Option), - /// 65% chance to spawn. - SilverCoin, - /// 25% chance to spawn. - ZombieCat, - /// 25% chance to spawn. - BatCat, - /// 10% chance to spawn. - BullyCat, -} - -#[derive(Debug, Clone, Encode, Decode, TypeInfo)] -pub struct GameInstance { - pub level: Level, - pub gold_coins: u64, - pub silver_coins: u64, - // pub map: Map, -} -// The following code is for generating the game map - -// impl GameInstance { -// pub fn new(level: Level, seed: GameSeed) -> GameInstance { -// let mut map: Map = [[Entity::Empty; MAP_WIDTH]; MAP_HEIGHT]; -// let mut rnd = Rand { seed }; - -// let mut gold_coins = 0u64; -// let mut silver_coins = 0u64; -// let mut effects = vec![Effect::Speed, Effect::Slow, Effect::Blind]; - -// #[allow(clippy::needless_range_loop)] -// for y in 0..MAP_HEIGHT { -// for x in 0..MAP_WIDTH { -// let entity = { -// let c: u64 = rnd.range(100); - -// if c <= 10 { -// if c % 2 == 0 { -// gold_coins += 1; -// Entity::GoldCoin(effects.pop()) -// } else { -// Entity::BullyCat -// } -// } else if c <= 25 { -// let p = [Entity::Empty, Entity::ZombieCat, Entity::BatCat]; -// p[c as usize % p.len()] -// } else { -// silver_coins += 1; -// Entity::SilverCoin -// } -// }; - -// map[y][x] = entity; -// } -// } - -// Self { -// level, -// gold_coins, -// silver_coins, -// map, -// is_claimed: false, -// } -// } - -// pub fn new_with_coins( -// level: Level, -// gold_coins: u64, -// silver_coins: u64, -// seed: GameSeed, -// ) -> GameInstance { -// let mut map: Map = [[Entity::Empty; MAP_WIDTH]; MAP_HEIGHT]; -// let mut effects = vec![Effect::Speed, Effect::Slow, Effect::Blind]; -// let mut rnd = Rand { seed }; - -// // 1. Transform game map -// let mut cells = Vec::new(); -// for y in 0..MAP_HEIGHT { -// for x in 0..MAP_WIDTH { -// cells.push((Entity::Empty, y, x)); -// } -// } - -// // 2. Pick N random positions for gold coins -// for _ in 0..=gold_coins { -// let i = rnd.range(cells.len() as u64) as usize; -// let (_, y, x) = cells.remove(i); - -// map[y][x] = Entity::GoldCoin(None); -// } - -// // 3. Pick N random positions for silver coins -// for _ in 0..=silver_coins { -// let i = rnd.range(cells.len() as u64) as usize; -// let (_, y, x) = cells.remove(i); - -// map[y][x] = Entity::SilverCoin; -// } - -// // 4. Fill remaining map with monsters and effects -// #[allow(clippy::needless_range_loop)] -// for y in 0..MAP_HEIGHT { -// for x in 0..MAP_WIDTH { -// let r = rnd.rand(); -// let entity = map[y][x]; - -// let new_entity = if entity == Entity::Empty { -// let p = [ -// Entity::Empty, -// Entity::ZombieCat, -// Entity::BatCat, -// Entity::BullyCat, -// ]; -// p[r as usize % p.len()] -// } else if entity == Entity::GoldCoin(None) { -// if r % 2 == 0 { -// Entity::GoldCoin(effects.pop()) -// } else { -// /* let p = [ -// Entity::GoldCoin(None), -// Entity::GoldCoin(Some(Effect::Speed)), -// Entity::GoldCoin(Some(Effect::Slow)), -// Entity::GoldCoin(Some(Effect::Blind)), -// ]; -// p[r as usize % p.len()] */ -// entity -// } -// } else { -// entity -// }; - -// map[y][x] = new_entity; -// } -// } - -// Self { -// level, -// gold_coins, -// silver_coins, -// map, -// is_claimed: false, -// } -// } -// } - -// #[cfg(test)] -// mod tests { -// extern crate std; - -// use super::*; - -// #[test] -// fn success_game_instance() { -// let game_instance = GameInstance::new(Level::Easy, 0); - -// for y in 0..MAP_HEIGHT { -// for x in 0..MAP_WIDTH { -// let e = game_instance.map[y][x]; -// let c = match e { -// Entity::Empty => ' ', -// Entity::ZombieCat => '🐱', -// Entity::BatCat => '😼', -// Entity::BullyCat => '😾', -// Entity::GoldCoin(_) => '🥇', -// Entity::SilverCoin => '🪙', -// }; -// std::print!("{c}"); -// } -// std::println!(); -// } -// } - -// #[test] -// fn success_game_instance_with_coins() { -// let game_instance = GameInstance::new_with_coins(Level::Easy, 5, 20, 0); - -// for y in 0..MAP_HEIGHT { -// for x in 0..MAP_WIDTH { -// let e = game_instance.map[y][x]; -// let c = match e { -// Entity::Empty => ' ', -// Entity::ZombieCat => '🐱', -// Entity::BatCat => '😼', -// Entity::BullyCat => '😾', -// Entity::GoldCoin(_) => '🥇', -// Entity::SilverCoin => '🪙', -// }; -// std::print!("{c}"); -// } -// std::println!(); -// } - -// std::println!( -// "gold_coins: {}, silver_coins: {}", -// game_instance.gold_coins, -// game_instance.silver_coins -// ); -// } -// } diff --git a/contracts/vara-man/src/lib.rs b/contracts/vara-man/src/lib.rs index aa9afffb6..95fe53dde 100644 --- a/contracts/vara-man/src/lib.rs +++ b/contracts/vara-man/src/lib.rs @@ -1,20 +1,29 @@ #![no_std] -use gstd::{collections::HashMap, msg, prelude::*, ActorId}; -use vara_man_io::{ - Config, GameInstance, Player, StateQuery, StateReply, Status, VaraMan as VaraManState, - VaraManAction, VaraManError, VaraManEvent, VaraManInit, -}; +use fungible_token_io::{FTAction, FTEvent}; +use gstd::{collections::HashMap, debug, exec, msg, prelude::*, ActorId}; +use vara_man_io::*; #[derive(Debug, Default)] struct VaraMan { - games: HashMap, - players: HashMap, + tournaments: HashMap, + players_to_game_id: HashMap, status: Status, config: Config, admins: Vec, } +#[derive(Default, Debug)] +pub struct Tournament { + tournament_name: String, + admin: ActorId, + level: Level, + participants: HashMap, + bid: u128, + stage: Stage, + duration_ms: u32, +} + static mut VARA_MAN: Option = None; #[gstd::async_main] @@ -23,143 +32,299 @@ async fn main() { let vara_man: &mut VaraMan = unsafe { VARA_MAN.get_or_insert(VaraMan::default()) }; let result = process_handle(action, vara_man).await; - + debug!("RESULT: {:?}", result); msg::reply(result, 0).expect("Unexpected invalid reply result."); } +#[allow(clippy::comparison_chain)] async fn process_handle( action: VaraManAction, vara_man: &mut VaraMan, ) -> Result { match action { - VaraManAction::RegisterPlayer { name } => { - let actor_id = msg::source(); - - if vara_man.status == Status::Paused { - return Err(VaraManError::WrongStatus); - } + VaraManAction::CreateNewTournament { + tournament_name, + name, + level, + duration_ms, + } => { + let msg_src = msg::source(); + let msg_value = msg::value(); - if name.is_empty() { - return Err(VaraManError::EmptyName); + if vara_man.tournaments.contains_key(&msg_src) { + msg::send_with_gas(msg_src, "", 0, msg_value).expect("Error in sending the value"); + return Err(VaraManError::AlreadyHaveTournament); } - - if vara_man.players.contains_key(&actor_id) { - Err(VaraManError::AlreadyRegistered) - } else { - vara_man.players.insert( - actor_id, - Player { - name, - lives: vara_man.config.number_of_lives, - claimed_gold_coins: 0, - claimed_silver_coins: 0, - }, - ); - - Ok(VaraManEvent::PlayerRegistered(actor_id)) + let mut participants = HashMap::new(); + participants.insert( + msg_src, + Player { + name: name.clone(), + time: 0, + points: 0, + }, + ); + let game = Tournament { + tournament_name: tournament_name.clone(), + admin: msg_src, + level, + participants, + bid: msg_value, + stage: Stage::Registration, + duration_ms, + }; + vara_man.tournaments.insert(msg_src, game); + vara_man.players_to_game_id.insert(msg_src, msg_src); + Ok(VaraManEvent::NewTournamentCreated { + tournament_name, + name, + level, + bid: msg_value, + }) + } + VaraManAction::RegisterForTournament { admin_id, name } => { + let msg_src = msg::source(); + let msg_value = msg::value(); + let reply = vara_man.register(msg_src, msg_value, admin_id, name); + if reply.is_err() { + msg::send_with_gas(msg_src, "", 0, msg_value).expect("Error in sending the value"); } + reply } - VaraManAction::StartGame { level } => { - let player_address = msg::source(); - - if vara_man.status == Status::Paused { - return Err(VaraManError::WrongStatus); + VaraManAction::CancelRegister => { + let msg_src = msg::source(); + let admin_id = vara_man + .players_to_game_id + .get(&msg_src) + .ok_or(VaraManError::NoSuchPlayer)?; + + let game = vara_man + .tournaments + .get_mut(admin_id) + .ok_or(VaraManError::NoSuchGame)?; + + if game.admin == msg_src { + return Err(VaraManError::AccessDenied); + } + if game.stage != Stage::Registration { + return Err(VaraManError::WrongStage); + } + if game.bid != 0 { + msg::send_with_gas(msg_src, "", 0, game.bid).expect("Error in sending the value"); } + game.participants.remove(&msg_src); + vara_man.players_to_game_id.remove(&msg_src); - let Some(player) = vara_man.players.get_mut(&player_address) else { - return Err(VaraManError::NotRegistered); - }; + Ok(VaraManEvent::RegisterCanceled) + } + VaraManAction::CancelTournament => { + let msg_src = msg::source(); + let game = vara_man + .tournaments + .get(&msg_src) + .ok_or(VaraManError::NoSuchGame)?; + + game.participants.iter().for_each(|(id, _)| { + if !matches!(game.stage, Stage::Finished(_)) && game.bid != 0 { + msg::send_with_gas(*id, "", 0, game.bid).expect("Error in sending the value"); + } + vara_man.players_to_game_id.remove(id); + }); - if vara_man.games.get(&player_address).is_some() { - return Err(VaraManError::AlreadyStartGame); - }; + vara_man.tournaments.remove(&msg_src); - if !player.is_have_lives() && !vara_man.admins.contains(&player_address) { - return Err(VaraManError::LivesEnded); + Ok(VaraManEvent::TournamentCanceled { admin_id: msg_src }) + } + VaraManAction::DeletePlayer { player_id } => { + let msg_src = msg::source(); + let game = vara_man + .tournaments + .get_mut(&msg_src) + .ok_or(VaraManError::NoSuchGame)?; + + if game.admin == player_id { + return Err(VaraManError::AccessDenied); } - vara_man.games.insert( - player_address, - GameInstance { - level, - gold_coins: vara_man.config.gold_coins, - silver_coins: vara_man.config.silver_coins, - }, - ); + if game.stage != Stage::Registration { + return Err(VaraManError::WrongStage); + } - Ok(VaraManEvent::GameStarted) + game.participants + .remove(&player_id) + .ok_or(VaraManError::NoSuchPlayer)?; + vara_man + .players_to_game_id + .remove(&player_id) + .ok_or(VaraManError::NoSuchPlayer)?; + if game.bid != 0 { + msg::send_with_gas(player_id, "", 0, game.bid).expect("Error in sending value"); + } + + Ok(VaraManEvent::PlayerDeleted { player_id }) } - VaraManAction::ClaimReward { - silver_coins, + VaraManAction::FinishSingleGame { gold_coins, + silver_coins, + level, } => { - let player_address = msg::source(); + let msg_src = msg::source(); + + let (points_for_gold, points_for_silver) = + vara_man.config.get_points_per_gold_coin_for_level(level); + let points = points_for_gold * gold_coins + points_for_silver * silver_coins; + let prize = vara_man.config.one_point_in_value * points; + + if vara_man.status == Status::StartedWithNativeToken { + msg::send_with_gas(msg_src, "", 0, prize).expect("Error in sending value"); + } else if let Status::StartedWithFungibleToken { ft_address } = vara_man.status { + let _transfer_response: FTEvent = msg::send_for_reply_as( + ft_address, + FTAction::Transfer { + from: exec::program_id(), + to: msg_src, + amount: prize, + }, + 0, + 0, + ) + .expect("Error in sending a message") + .await + .expect("Error in transfer Fungible Token"); + } + Ok(VaraManEvent::SingleGameFinished { prize }) + } + VaraManAction::StartTournament => { + let msg_src = msg::source(); + if vara_man.status == Status::Paused { + return Err(VaraManError::GameIsPaused); + } + let game = vara_man + .tournaments + .get_mut(&msg_src) + .ok_or(VaraManError::NoSuchGame)?; - if let Some(game) = vara_man.games.get(&player_address) { - // Check that game is not paused - if vara_man.status == Status::Paused { - return Err(VaraManError::WrongStatus); - } + if game.stage != Stage::Registration { + return Err(VaraManError::WrongStage); + } + let time_start = exec::block_timestamp(); + game.stage = Stage::Started(time_start); + msg::send_with_gas_delayed( + exec::program_id(), + VaraManAction::FinishTournament { + admin_id: msg_src, + time_start, + }, + vara_man.config.gas_for_finish_tournament, + 0, + game.duration_ms / 3_000 + 1, + ) + .expect("Error in sending delayed message"); + Ok(VaraManEvent::GameStarted) + } - // Check that player is registered - let Some(player) = vara_man.players.get_mut(&player_address) else { - return Err(VaraManError::NotRegistered); - }; + VaraManAction::FinishTournament { + admin_id, + time_start, + } => { + if msg::source() != exec::program_id() { + return Err(VaraManError::AccessDenied); + } + let game = vara_man + .tournaments + .get_mut(&admin_id) + .ok_or(VaraManError::NoSuchGame)?; - // Check passed coins range - if silver_coins > game.silver_coins || gold_coins > game.gold_coins { - return Err(VaraManError::AmountGreaterThanAllowed); - } + if game.stage != Stage::Started(time_start) { + return Err(VaraManError::WrongStage); + } - let (tokens_per_gold_coin, tokens_per_silver_coin) = vara_man - .config - .get_tokens_per_gold_coin_for_level(game.level); - - let tokens_amount = vara_man - .config - .one_coin_in_value - .checked_mul(tokens_per_gold_coin) - .expect("Math overflow!") - .checked_mul(gold_coins) - .expect("Math overflow!") - .checked_add( - vara_man - .config - .one_coin_in_value - .checked_mul(tokens_per_silver_coin) - .expect("Math overflow!") - .checked_mul(silver_coins) - .expect("Math overflow!"), - ) - .expect("Math overflow!"); - - if msg::send(player_address, 0u8, tokens_amount as u128).is_err() { - return Err(VaraManError::TransferFailed); + let mut winners = Vec::new(); + let mut max_points = 0; + let mut min_time = u128::MAX; + + for (actor_id, player) in game.participants.iter() { + if player.points > max_points { + max_points = player.points; + min_time = player.time; + winners.clear(); + winners.push(*actor_id); + } else if player.points == max_points { + if player.time < min_time { + min_time = player.time; + winners.clear(); + winners.push(*actor_id); + } else if player.time == min_time { + winners.push(*actor_id); + } } + } - player.claimed_gold_coins = player - .claimed_gold_coins - .checked_add(gold_coins) - .expect("Math overflow!"); - player.claimed_silver_coins = player - .claimed_silver_coins - .checked_add(silver_coins) - .expect("Math overflow!"); + let prize = game.bid * game.participants.len() as u128 / winners.len() as u128; + winners.iter().for_each(|id| { + msg::send_with_gas(*id, "", 0, prize).expect("Error in sending value"); + }); + game.stage = Stage::Finished(winners.clone()); + let participants: Vec<_> = game.participants.keys().cloned().collect(); + + msg::send( + game.admin, + Ok::(VaraManEvent::GameFinished { + winners: winners.clone(), + participants: participants.clone(), + prize, + }), + 0, + ) + .expect("Error in sending message"); + + Ok(VaraManEvent::GameFinished { + winners, + participants, + prize, + }) + } - vara_man.games.remove(&player_address); + VaraManAction::RecordTournamentResult { + time, + gold_coins, + silver_coins, + } => { + let msg_src = msg::source(); + let admin_id = vara_man + .players_to_game_id + .get(&msg_src) + .ok_or(VaraManError::NoSuchPlayer)?; + let game = vara_man + .tournaments + .get_mut(admin_id) + .ok_or(VaraManError::NoSuchGame)?; + + if !matches!(game.stage, Stage::Started(_)) { + return Err(VaraManError::WrongStage); + } - if !vara_man.admins.contains(&player_address) { - player.lives -= 1; - } + let player = game + .participants + .get_mut(&msg_src) + .ok_or(VaraManError::NoSuchPlayer)?; + + let (points_for_gold, points_for_silver) = vara_man + .config + .get_points_per_gold_coin_for_level(game.level); + let points = points_for_gold * gold_coins + points_for_silver * silver_coins; + player.time += time; + player.points += points; + + Ok(VaraManEvent::ResultTournamentRecorded { + time: player.time, + points: player.points, + }) + } - Ok(VaraManEvent::GameFinished { - player_address, - silver_coins, - gold_coins, - }) - } else { - Err(VaraManError::GameDoesNotExist) - } + VaraManAction::LeaveGame => { + vara_man.players_to_game_id.remove(&msg::source()); + Ok(VaraManEvent::LeftGame) } VaraManAction::ChangeStatus(status) => { if vara_man.admins.contains(&msg::source()) { @@ -172,8 +337,6 @@ async fn process_handle( VaraManAction::ChangeConfig(config) => { if !vara_man.admins.contains(&msg::source()) { Err(VaraManError::NotAdmin) - } else if !config.is_valid() { - return Err(VaraManError::ConfigIsInvalid); } else { vara_man.config = config; Ok(VaraManEvent::ConfigChanged(config)) @@ -190,10 +353,56 @@ async fn process_handle( } } +impl VaraMan { + fn register( + &mut self, + msg_src: ActorId, + msg_value: u128, + admin_id: ActorId, + name: String, + ) -> Result { + if self.status == Status::Paused { + return Err(VaraManError::GameIsPaused); + } + + if self.players_to_game_id.contains_key(&msg_src) { + return Err(VaraManError::SeveralRegistrations); + } + let game = self + .tournaments + .get_mut(&admin_id) + .ok_or(VaraManError::NoSuchGame)?; + + if game.stage != Stage::Registration { + return Err(VaraManError::WrongStage); + } + if game.participants.len() >= MAX_PARTICIPANTS.into() { + return Err(VaraManError::SessionFull); + } + if game.bid != msg_value { + return Err(VaraManError::WrongBid); + } + + game.participants.insert( + msg_src, + Player { + name: name.clone(), + time: 0, + points: 0, + }, + ); + self.players_to_game_id.insert(msg_src, admin_id); + Ok(VaraManEvent::PlayerRegistered { + admin_id, + name, + bid: msg_value, + }) + } +} + #[no_mangle] extern fn init() { let init: VaraManInit = msg::load().expect("Unexpected invalid init payload."); - assert!(init.config.is_valid()); unsafe { VARA_MAN = Some(VaraMan { config: init.config, @@ -211,21 +420,29 @@ extern fn state() { let reply = match query { StateQuery::All => StateReply::All(contract.into()), - StateQuery::AllGames => { - let games = contract.games.into_iter().collect(); - StateReply::AllGames(games) - } - StateQuery::AllPlayers => { - let players = contract.players.into_iter().collect(); - StateReply::AllPlayers(players) - } - StateQuery::Game { player_address } => { - let game: Option = contract.games.get(&player_address).cloned(); - StateReply::Game(game) - } - StateQuery::Player { player_address } => { - let player: Option = contract.players.get(&player_address).cloned(); - StateReply::Player(player) + StateQuery::GetTournament { player_id } => { + if let Some(admin_id) = contract.players_to_game_id.get(&player_id) { + if let Some(tournament) = contract.tournaments.get(admin_id) { + let tournament_state = TournamentState { + tournament_name: tournament.tournament_name.clone(), + admin: tournament.admin, + level: tournament.level, + participants: tournament.participants.clone().into_iter().collect(), + bid: tournament.bid, + stage: tournament.stage.clone(), + duration_ms: tournament.duration_ms, + }; + let time = match tournament.stage { + Stage::Started(start_time) => Some(exec::block_timestamp() - start_time), + _ => None, + }; + StateReply::Tournament(Some((tournament_state, time))) + } else { + StateReply::Tournament(None) + } + } else { + StateReply::Tournament(None) + } } StateQuery::Config => StateReply::Config(contract.config), StateQuery::Admins => StateReply::Admins(contract.admins), @@ -237,20 +454,34 @@ extern fn state() { impl From for VaraManState { fn from(value: VaraMan) -> Self { let VaraMan { - games, - players, + tournaments, + players_to_game_id, status, config, admins, } = value; - let games = games.into_iter().collect(); + let tournaments = tournaments + .into_iter() + .map(|(id, tournament)| { + let tournament_state = TournamentState { + tournament_name: tournament.tournament_name, + admin: tournament.admin, + level: tournament.level, + participants: tournament.participants.into_iter().collect(), + bid: tournament.bid, + stage: tournament.stage, + duration_ms: tournament.duration_ms, + }; + (id, tournament_state) + }) + .collect(); - let players = players.into_iter().collect(); + let players_to_game_id = players_to_game_id.into_iter().collect(); Self { - games, - players, + tournaments, + players_to_game_id, status, config, admins, diff --git a/contracts/vara-man/tests/claim_reward.rs b/contracts/vara-man/tests/claim_reward.rs deleted file mode 100644 index 9d74baa4c..000000000 --- a/contracts/vara-man/tests/claim_reward.rs +++ /dev/null @@ -1,175 +0,0 @@ -mod utils; -use crate::utils::ADMIN; -use gtest::{Program, System}; -use utils::VaraMan; -use vara_man_io::{Config, Level, Status, VaraManError}; - -#[test] -fn success() { - let system = System::new(); - system.init_logger(); - - let vara_man = Program::vara_man_with_config( - &system, - Config { - one_coin_in_value: 1_000_000_000_000, - tokens_per_gold_coin_easy: 5, - tokens_per_silver_coin_easy: 1, - tokens_per_gold_coin_medium: 8, - tokens_per_silver_coin_medium: 2, - tokens_per_gold_coin_hard: 10, - tokens_per_silver_coin_hard: 3, - gold_coins: 5, - silver_coins: 20, - number_of_lives: 3, - }, - ); - - system.mint_to(utils::VARA_MAN_ID, utils::VARA_MAN_FUND); - - vara_man.change_status(ADMIN, Status::Started); - - let state = vara_man.get_state().expect("Unexpected invalid state."); - assert!(state.players.is_empty() && state.games.is_empty()); - - vara_man.register_player(utils::PLAYERS[0], "John", None); - vara_man.start_game(utils::PLAYERS[0], Level::Easy, None); - - assert_eq!(system.balance_of(utils::PLAYERS[0]), 0); - vara_man.claim_reward(utils::PLAYERS[0], 10, 1, None); - - // 15 tokens total, with 12 decimals precision - system.claim_value_from_mailbox(utils::PLAYERS[0]); - assert_eq!(system.balance_of(utils::PLAYERS[0]), 15_000_000_000_000); - - let state = vara_man.get_state().expect("Unexpected invalid state."); - assert_eq!(state.players[0].1.claimed_gold_coins, 1); - assert_eq!(state.players[0].1.claimed_silver_coins, 10); -} - -#[test] -fn success_reward_scale() { - let system = System::new(); - system.init_logger(); - - let vara_man = Program::vara_man_with_config( - &system, - Config { - one_coin_in_value: 1_000_000_000_000, - tokens_per_gold_coin_easy: 5, - tokens_per_silver_coin_easy: 1, - tokens_per_gold_coin_medium: 8, - tokens_per_silver_coin_medium: 2, - tokens_per_gold_coin_hard: 10, - tokens_per_silver_coin_hard: 3, - gold_coins: 5, - silver_coins: 20, - number_of_lives: 3, - }, - ); - - system.mint_to(utils::VARA_MAN_ID, utils::VARA_MAN_FUND); - - vara_man.change_status(ADMIN, Status::Started); - - let state = vara_man.get_state().expect("Unexpected invalid state."); - assert!(state.players.is_empty() && state.games.is_empty()); - - vara_man.register_player(utils::PLAYERS[0], "John", None); - vara_man.start_game(utils::PLAYERS[0], Level::Easy, None); - - assert_eq!(system.balance_of(utils::PLAYERS[0]), 0); - vara_man.claim_reward(utils::PLAYERS[0], 10, 1, None); - - // 15 tokens total, with 12 decimals precision - system.claim_value_from_mailbox(utils::PLAYERS[0]); - assert_eq!(system.balance_of(utils::PLAYERS[0]), 15_000_000_000_000); -} - -#[test] -fn fail_rewards_already_claimed() { - let system = System::new(); - system.init_logger(); - - let vara_man = Program::vara_man_with_config( - &system, - Config { - one_coin_in_value: 1_000_000_000_000, - tokens_per_gold_coin_easy: 5, - tokens_per_silver_coin_easy: 1, - tokens_per_gold_coin_medium: 8, - tokens_per_silver_coin_medium: 2, - tokens_per_gold_coin_hard: 10, - tokens_per_silver_coin_hard: 3, - gold_coins: 5, - silver_coins: 20, - number_of_lives: 3, - }, - ); - - system.mint_to(utils::VARA_MAN_ID, utils::VARA_MAN_FUND); - - vara_man.change_status(ADMIN, Status::Started); - - let state = vara_man.get_state().expect("Unexpected invalid state."); - assert!(state.players.is_empty() && state.games.is_empty()); - - vara_man.register_player(utils::PLAYERS[0], "John", None); - vara_man.start_game(utils::PLAYERS[0], Level::Easy, None); - - assert_eq!(system.balance_of(utils::PLAYERS[0]), 0); - vara_man.claim_reward(utils::PLAYERS[0], 10, 1, None); - - system.claim_value_from_mailbox(utils::PLAYERS[0]); - assert_eq!(system.balance_of(utils::PLAYERS[0]), 15_000_000_000_000); - - vara_man.claim_reward( - utils::PLAYERS[0], - 10, - 1, - Some(VaraManError::GameDoesNotExist), - ); - - system.claim_value_from_mailbox(utils::PLAYERS[0]); - assert_eq!(system.balance_of(utils::PLAYERS[0]), 15_000_000_000_000); -} - -#[test] -fn fail_coin_amount_is_gt_than_allowed() { - let system = System::new(); - system.init_logger(); - - let vara_man = Program::vara_man_with_config( - &system, - Config { - one_coin_in_value: 1_000_000_000_000, - tokens_per_gold_coin_easy: 5, - tokens_per_silver_coin_easy: 1, - tokens_per_gold_coin_medium: 8, - tokens_per_silver_coin_medium: 2, - tokens_per_gold_coin_hard: 10, - tokens_per_silver_coin_hard: 3, - gold_coins: 5, - silver_coins: 20, - number_of_lives: 3, - }, - ); - - system.mint_to(utils::VARA_MAN_ID, utils::VARA_MAN_FUND); - - vara_man.change_status(ADMIN, Status::Started); - - let state = vara_man.get_state().expect("Unexpected invalid state."); - assert!(state.players.is_empty() && state.games.is_empty()); - - vara_man.register_player(utils::PLAYERS[0], "John", None); - vara_man.start_game(utils::PLAYERS[0], Level::Easy, None); - - assert_eq!(system.balance_of(utils::PLAYERS[0]), 0); - vara_man.claim_reward( - utils::PLAYERS[0], - 10000, - 10000, - Some(VaraManError::AmountGreaterThanAllowed), - ); -} diff --git a/contracts/vara-man/tests/node_tests.rs b/contracts/vara-man/tests/node_tests.rs index 7033c237f..d2749a68f 100644 --- a/contracts/vara-man/tests/node_tests.rs +++ b/contracts/vara-man/tests/node_tests.rs @@ -1,207 +1,78 @@ mod utils_gclient; - use gclient::GearApi; use gstd::prelude::*; -use vara_man_io::{Level, Status, VaraManError}; +use utils_gclient::{common::*, vara_man::*}; +use vara_man_io::{Level, Stage, Status}; #[tokio::test] -async fn gclient_success_register_player() -> gclient::Result<()> { +async fn gclient_success_play_tournament() -> gclient::Result<()> { let api = GearApi::dev_from_path("../target/tmp/gear").await?; + // let api = GearApi::dev().await?; let vara_man_id = utils_gclient::common::init(&api).await?; - utils_gclient::vara_man::change_status(&api, &vara_man_id, Status::Started, None).await?; + change_status(&api, &vara_man_id, Status::StartedWithNativeToken, None).await?; { let api = api.with("//Peter")?; - utils_gclient::vara_man::register_player(&api, &vara_man_id, "Peter", None).await?; - - let state = utils_gclient::vara_man::get_state(&api, &vara_man_id) - .await - .expect("Unexpected invalid state."); - assert!(!state.players.is_empty()); - assert!(state.games.is_empty()); - assert_eq!(state.players[0].1.name, "Peter".to_owned()); - } - - Ok(()) -} - -#[tokio::test] -async fn gclient_failures_register_player() -> gclient::Result<()> { - let api = GearApi::dev_from_path("../target/tmp/gear").await?; - let vara_man_id = utils_gclient::common::init(&api).await?; - - { - let player_api = api.clone().with("//Peter")?; - utils_gclient::vara_man::register_player( - &player_api, - &vara_man_id, - "Peter", - Some(VaraManError::WrongStatus), - ) - .await?; - utils_gclient::vara_man::change_status(&api, &vara_man_id, Status::Started, None).await?; - utils_gclient::vara_man::register_player( - &player_api, + create_tournament( + &api, &vara_man_id, - "", - Some(VaraManError::EmptyName), - ) - .await?; - utils_gclient::vara_man::register_player(&player_api, &vara_man_id, "Peter", None).await?; - utils_gclient::vara_man::register_player( - &player_api, - &vara_man_id, - "Peter", - Some(VaraManError::AlreadyRegistered), + "tournament_name".to_string(), + "tournament admin".to_string(), + Level::Easy, + 30_000, + None, ) .await?; - } - - Ok(()) -} - -#[tokio::test] -async fn gclient_success_start_game() -> gclient::Result<()> { - let api = GearApi::dev_from_path("../target/tmp/gear").await?; - let vara_man_id = utils_gclient::common::init(&api).await?; - utils_gclient::vara_man::change_status(&api, &vara_man_id, Status::Started, None).await?; - - { - let api = api.with("//Peter")?; - utils_gclient::vara_man::register_player(&api, &vara_man_id, "Peter", None).await?; - utils_gclient::vara_man::start_game(&api, &vara_man_id, Level::Easy, None).await?; - - let state = utils_gclient::vara_man::get_state(&api, &vara_man_id) + let state = get_state(&api, &vara_man_id) .await .expect("Unexpected invalid state."); - assert_eq!(state.games.len(), 1); - } - - Ok(()) -} + assert_eq!(state.tournaments.len(), 1); + assert_eq!(state.players_to_game_id.len(), 1); -#[tokio::test] -async fn gclient_failures_start_game() -> gclient::Result<()> { - let api = GearApi::dev_from_path("../target/tmp/gear").await?; - let vara_man_id = utils_gclient::common::init(&api).await?; - - { - let player_api = api.clone().with("//Peter")?; - utils_gclient::vara_man::start_game( - &player_api, - &vara_man_id, - Level::Easy, - Some(VaraManError::WrongStatus), - ) - .await?; - utils_gclient::vara_man::change_status(&api, &vara_man_id, Status::Started, None).await?; - utils_gclient::vara_man::start_game( - &player_api, + let api_alex = api.clone().with("//Alex")?; + let admin_id = get_user_to_actor_id("//Peter").await?; + register_for_tournament( + &api_alex, &vara_man_id, - Level::Easy, - Some(VaraManError::NotRegistered), + admin_id, + "player #1".to_string(), + 10_000_000_000_000, + None, ) .await?; - utils_gclient::vara_man::register_player(&player_api, &vara_man_id, "Peter", None).await?; - utils_gclient::vara_man::start_game(&player_api, &vara_man_id, Level::Easy, None).await?; - utils_gclient::vara_man::start_game( - &player_api, - &vara_man_id, - Level::Easy, - Some(VaraManError::AlreadyStartGame), - ) - .await?; - } - Ok(()) -} + let state = get_state(&api, &vara_man_id) + .await + .expect("Unexpected invalid state."); + assert_eq!(state.players_to_game_id.len(), 2); -#[tokio::test] -async fn gclient_success_claim_reward() -> gclient::Result<()> { - let api = GearApi::dev_from_path("../target/tmp/gear").await?; - let vara_man_id = utils_gclient::common::init(&api).await?; - utils_gclient::vara_man::change_status(&api, &vara_man_id, Status::Started, None).await?; - let balance = api.total_balance(api.account_id()).await?; - api.transfer(vara_man_id.encode().as_slice().into(), balance / 10) - .await?; + start_tournament(&api, &vara_man_id, None).await?; - { - let api = api.with("//Peter")?; - utils_gclient::vara_man::register_player(&api, &vara_man_id, "Peter", None).await?; - utils_gclient::vara_man::start_game(&api, &vara_man_id, Level::Easy, None).await?; - utils_gclient::vara_man::claim_reward(&api, &vara_man_id, 10, 1, None).await?; + record_tournament_result(&api_alex, &vara_man_id, 1_000, 1, 5, None).await?; + record_tournament_result(&api, &vara_man_id, 1_000, 1, 5, None).await?; - let state = utils_gclient::vara_man::get_state(&api, &vara_man_id) + let state = get_state(&api, &vara_man_id) .await .expect("Unexpected invalid state."); + println!("State: {:?}", state); + assert_eq!(state.tournaments[0].1.participants[0].1.points, 10); - assert_eq!(state.players[0].1.claimed_gold_coins, 1); - assert_eq!(state.players[0].1.claimed_silver_coins, 10); - assert_eq!(state.players[0].1.lives, 2); - } - - Ok(()) -} - -#[tokio::test] -async fn gclient_failures_claim_reward() -> gclient::Result<()> { - let api = GearApi::dev_from_path("../target/tmp/gear").await?; - let vara_man_id = utils_gclient::common::init(&api).await?; - utils_gclient::vara_man::change_status(&api, &vara_man_id, Status::Started, None).await?; + let old_balance = api.total_balance(api_alex.account_id()).await?; - { - let player_api = api.clone().with("//Peter")?; - utils_gclient::vara_man::claim_reward( - &player_api, - &vara_man_id, - 10, - 1, - Some(VaraManError::GameDoesNotExist), - ) - .await?; - utils_gclient::vara_man::register_player(&player_api, &vara_man_id, "Peter", None).await?; - utils_gclient::vara_man::start_game(&player_api, &vara_man_id, Level::Easy, None).await?; - utils_gclient::vara_man::change_status(&api, &vara_man_id, Status::Paused, None).await?; - utils_gclient::vara_man::claim_reward( - &player_api, - &vara_man_id, - 10, - 1, - Some(VaraManError::WrongStatus), - ) - .await?; - utils_gclient::vara_man::change_status(&api, &vara_man_id, Status::Started, None).await?; + std::thread::sleep(std::time::Duration::from_secs(15)); - utils_gclient::vara_man::claim_reward( - &player_api, - &vara_man_id, - 10, - 10, - Some(VaraManError::AmountGreaterThanAllowed), - ) - .await?; - utils_gclient::vara_man::claim_reward( - &player_api, - &vara_man_id, - 10, - 1, - Some(VaraManError::TransferFailed), - ) - .await?; + let state = get_state(&api, &vara_man_id) + .await + .expect("Unexpected invalid state."); + let alex_id = get_user_to_actor_id("//Alex").await?; + assert_eq!( + state.tournaments[0].1.stage, + Stage::Finished(vec![alex_id, admin_id]) + ); - let balance = api.total_balance(api.account_id()).await?; - api.transfer(vara_man_id.encode().as_slice().into(), balance / 10) - .await?; + let new_balance = api.total_balance(api_alex.account_id()).await?; - utils_gclient::vara_man::claim_reward(&player_api, &vara_man_id, 10, 1, None).await?; - utils_gclient::vara_man::claim_reward( - &player_api, - &vara_man_id, - 10, - 1, - Some(VaraManError::GameDoesNotExist), - ) - .await?; + assert_eq!(new_balance - old_balance, 10_000_000_000_000); } Ok(()) diff --git a/contracts/vara-man/tests/register_player.rs b/contracts/vara-man/tests/register_player.rs deleted file mode 100644 index d7ffb4a58..000000000 --- a/contracts/vara-man/tests/register_player.rs +++ /dev/null @@ -1,76 +0,0 @@ -mod utils; -use crate::utils::ADMIN; -use gstd::ActorId; -use gtest::{Program, System}; -use utils::VaraMan; -use vara_man_io::{Player, Status, VaraManError}; - -#[test] -fn success() { - let system = System::new(); - system.init_logger(); - - let vara_man = Program::vara_man(&system); - vara_man.change_status(ADMIN, Status::Started); - - let state = vara_man.get_state().expect("Unexpected invalid state."); - assert!(state.players.is_empty()); - - let player_0_id: ActorId = utils::PLAYERS[0].into(); - let player_1_id: ActorId = utils::PLAYERS[1].into(); - let player_2_id: ActorId = utils::PLAYERS[2].into(); - - vara_man.register_player(utils::PLAYERS[0], "John", None); - vara_man.register_player(utils::PLAYERS[1], "Jack", None); - vara_man.register_player(utils::PLAYERS[2], "James", None); - - let state = vara_man.get_state().expect("Unexpected invalid state."); - - assert_eq!(state.players.len(), 3); - assert!(state.players.contains(&( - player_0_id, - Player { - name: "John".to_owned(), - lives: 3, - claimed_gold_coins: 0, - claimed_silver_coins: 0, - } - ))); - assert!(state.players.contains(&( - player_1_id, - Player { - name: "Jack".to_owned(), - lives: 3, - claimed_gold_coins: 0, - claimed_silver_coins: 0, - } - ))); - assert!(state.players.contains(&( - player_2_id, - Player { - name: "James".to_owned(), - lives: 3, - claimed_gold_coins: 0, - claimed_silver_coins: 0, - } - ))); -} - -#[test] -fn fail_player_already_registered() { - let system = System::new(); - system.init_logger(); - - let vara_man = Program::vara_man(&system); - vara_man.change_status(ADMIN, Status::Started); - - vara_man.register_player(utils::PLAYERS[0], "John", None); - vara_man.register_player( - utils::PLAYERS[0], - "John", - Some(VaraManError::AlreadyRegistered), - ); - - let state = vara_man.get_state().expect("Unexpected invalid state."); - assert_eq!(state.players.len(), 1); -} diff --git a/contracts/vara-man/tests/start_game.rs b/contracts/vara-man/tests/start_game.rs index 89c51bd69..7c1ab1cac 100644 --- a/contracts/vara-man/tests/start_game.rs +++ b/contracts/vara-man/tests/start_game.rs @@ -1,113 +1,84 @@ mod utils; -use crate::utils::ADMIN; -use gstd::ActorId; +use crate::utils::*; use gtest::{Program, System}; use utils::VaraMan; -use vara_man_io::{Level, Status, VaraManError}; +use vara_man_io::{Level, Stage, Status}; #[test] -fn success() { +fn success_play_single_game() { let system = System::new(); system.init_logger(); let vara_man = Program::vara_man(&system); - vara_man.change_status(ADMIN, Status::Started); - - let state = vara_man.get_state().expect("Unexpected invalid state."); - assert!(state.games.is_empty()); - - let player_0_id: ActorId = utils::PLAYERS[0].into(); - - vara_man.register_player(utils::PLAYERS[0], "John", None); - vara_man.start_game(utils::PLAYERS[0], Level::Easy, None); - - let state = vara_man.get_state().expect("Unexpected invalid state."); - - assert_eq!(state.games.len(), 1); - assert_eq!(state.games[0].0, player_0_id); - assert_ne!(state.games[0].1.gold_coins, 0); - assert_ne!(state.games[0].1.silver_coins, 0); + system.mint_to(VARA_MAN_ID, VARA_MAN_FUND); + vara_man.change_status(ADMIN, Status::StartedWithNativeToken); + let old_balance = system.balance_of(PLAYERS[0]); + vara_man.finish_single_game(PLAYERS[0], 1, 5, None); + system.claim_value_from_mailbox(PLAYERS[0]); + let new_balance = system.balance_of(PLAYERS[0]); + assert_eq!(new_balance - old_balance, 100_000_000_000_000); } #[test] -fn fail_player_must_register() { +fn success_play_tournament() { let system = System::new(); system.init_logger(); let vara_man = Program::vara_man(&system); - vara_man.change_status(ADMIN, Status::Started); + system.mint_to(VARA_MAN_ID, VARA_MAN_FUND); + system.mint_to(PLAYERS[0], VARA_MAN_FUND); + system.mint_to(PLAYERS[1], VARA_MAN_FUND); - let state = vara_man.get_state().expect("Unexpected invalid state."); - assert!(state.games.is_empty()); + vara_man.change_status(ADMIN, Status::StartedWithNativeToken); - vara_man.start_game( - utils::PLAYERS[0], - Level::Hard, - Some(VaraManError::NotRegistered), + vara_man.create_tournament( + PLAYERS[0], + "TOURNAMENT".to_string(), + "Admin tournament".to_string(), + Level::Easy, + 180_000, + 10_000_000_000_000, + None, ); let state = vara_man.get_state().expect("Unexpected invalid state."); - assert_eq!(state.games.len(), 0); -} - -#[test] -fn fail_player_has_exhausted_all_attempts() { - let system = System::new(); - system.init_logger(); - - let vara_man = Program::vara_man(&system); - - vara_man.change_status(ADMIN, Status::Started); + assert_eq!(state.tournaments.len(), 1); + assert_eq!(state.players_to_game_id.len(), 1); + + vara_man.register( + PLAYERS[1], + PLAYERS[0].into(), + "player #1".to_string(), + 10_000_000_000_000, + None, + ); let state = vara_man.get_state().expect("Unexpected invalid state."); - assert!(state.games.is_empty()); - - vara_man.register_player(utils::PLAYERS[0], "John", None); - - vara_man.start_game(utils::PLAYERS[0], Level::Easy, None); - vara_man.claim_reward(utils::PLAYERS[0], 10, 1, None); - vara_man.start_game(utils::PLAYERS[0], Level::Easy, None); - vara_man.claim_reward(utils::PLAYERS[0], 10, 1, None); - vara_man.start_game(utils::PLAYERS[0], Level::Easy, None); - vara_man.claim_reward(utils::PLAYERS[0], 10, 1, None); - vara_man.start_game( - utils::PLAYERS[0], - Level::Easy, - Some(VaraManError::LivesEnded), + assert_eq!(state.tournaments[0].1.participants.len(), 2); + + let old_balance = system.balance_of(PLAYERS[1]); + vara_man.cancel_register(PLAYERS[1], None); + system.claim_value_from_mailbox(PLAYERS[1]); + let new_balance = system.balance_of(PLAYERS[1]); + assert_eq!(new_balance - old_balance, 10_000_000_000_000); + + vara_man.register( + PLAYERS[1], + PLAYERS[0].into(), + "player #1".to_string(), + 10_000_000_000_000, + None, ); + vara_man.start_tournament(PLAYERS[0], None); + vara_man.record_tournament_result(PLAYERS[0], 1_000, 1, 5, None); + vara_man.record_tournament_result(PLAYERS[1], 1_000, 1, 5, None); let state = vara_man.get_state().expect("Unexpected invalid state."); - assert_eq!(state.games.len(), 0); -} - -#[test] -fn success_add_admin() { - let system = System::new(); - system.init_logger(); - - let vara_man = Program::vara_man(&system); - vara_man.change_status(ADMIN, Status::Started); - - vara_man.register_player(utils::PLAYERS[0], "John", None); + assert_eq!(state.tournaments[0].1.participants[1].1.points, 10); - vara_man.start_game(utils::PLAYERS[0], Level::Easy, None); - vara_man.claim_reward(utils::PLAYERS[0], 10, 1, None); - vara_man.start_game(utils::PLAYERS[0], Level::Easy, None); - vara_man.claim_reward(utils::PLAYERS[0], 10, 1, None); - vara_man.start_game(utils::PLAYERS[0], Level::Easy, None); - vara_man.claim_reward(utils::PLAYERS[0], 10, 1, None); - vara_man.start_game( - utils::PLAYERS[0], - Level::Easy, - Some(VaraManError::LivesEnded), + system.spend_blocks(61); + let state = vara_man.get_state().expect("Unexpected invalid state."); + assert_eq!( + state.tournaments[0].1.stage, + Stage::Finished(vec![PLAYERS[1].into(), PLAYERS[0].into()]) ); - - vara_man.add_admin(ADMIN, utils::PLAYERS[0].into()); - - vara_man.start_game(utils::PLAYERS[0], Level::Easy, None); - vara_man.claim_reward(utils::PLAYERS[0], 10, 1, None); - vara_man.start_game(utils::PLAYERS[0], Level::Easy, None); - vara_man.claim_reward(utils::PLAYERS[0], 10, 1, None); - vara_man.start_game(utils::PLAYERS[0], Level::Easy, None); - vara_man.claim_reward(utils::PLAYERS[0], 10, 1, None); - vara_man.start_game(utils::PLAYERS[0], Level::Easy, None); } diff --git a/contracts/vara-man/tests/utils/mod.rs b/contracts/vara-man/tests/utils/mod.rs index c85ea7efe..564b0beb5 100644 --- a/contracts/vara-man/tests/utils/mod.rs +++ b/contracts/vara-man/tests/utils/mod.rs @@ -6,4 +6,4 @@ pub const ADMIN: u64 = 100; pub const VARA_MAN_ID: u64 = 200; pub const PLAYERS: [u64; 3] = [101, 102, 103]; #[allow(unused)] -pub const VARA_MAN_FUND: u128 = 100_000_000_000_000; +pub const VARA_MAN_FUND: u128 = 100_000_000_000_000_000; diff --git a/contracts/vara-man/tests/utils/vara_man.rs b/contracts/vara-man/tests/utils/vara_man.rs index 11a979abb..f0c3efbcb 100644 --- a/contracts/vara-man/tests/utils/vara_man.rs +++ b/contracts/vara-man/tests/utils/vara_man.rs @@ -1,24 +1,60 @@ use super::{ADMIN, VARA_MAN_ID}; +use fungible_token_io::{FTAction, InitConfig}; use gstd::{prelude::*, ActorId}; use gtest::{Program, System}; -use vara_man_io::{VaraMan as VaraManState, *}; +use vara_man_io::*; pub trait VaraMan { fn vara_man(system: &System) -> Program<'_>; fn vara_man_with_config(system: &System, config: Config) -> Program<'_>; - fn register_player(&self, from: u64, name: &str, error: Option); - fn start_game(&self, from: u64, level: Level, error: Option); - fn claim_reward( + fn record_tournament_result( &self, from: u64, - silver_coins: u64, - gold_coins: u64, + time: u128, + gold_coins: u128, + silver_coins: u128, error: Option, ); + fn finish_single_game( + &self, + from: u64, + gold_coins: u128, + silver_coins: u128, + error: Option, + ); + fn leave_game(&self, from: u64, error: Option); + #[allow(clippy::too_many_arguments)] + fn create_tournament( + &self, + from: u64, + tournament_name: String, + name: String, + level: Level, + duration_ms: u32, + value: u128, + error: Option, + ); + fn register( + &self, + from: u64, + admin: ActorId, + name: String, + value: u128, + error: Option, + ); + fn cancel_register(&self, from: u64, error: Option); fn change_status(&self, from: u64, status: Status); fn change_config(&self, from: u64, config: Config); + fn start_tournament(&self, from: u64, error: Option); fn add_admin(&self, from: u64, admin: ActorId); fn send_tx(&self, from: u64, action: VaraManAction, error: Option); + fn send_tx_with_value( + &self, + from: u64, + action: VaraManAction, + value: u128, + error: Option, + ); fn get_state(&self) -> Option; } @@ -27,10 +63,15 @@ impl VaraMan for Program<'_> { Self::vara_man_with_config( system, Config { - gold_coins: 5, - silver_coins: 20, - number_of_lives: 3, - ..Default::default() + one_point_in_value: 10_000_000_000_000, + points_per_gold_coin_easy: 5, + points_per_silver_coin_easy: 1, + points_per_gold_coin_medium: 8, + points_per_silver_coin_medium: 2, + points_per_gold_coin_hard: 10, + points_per_silver_coin_hard: 3, + gas_for_finish_tournament: 10_000_000_000, + time_for_single_round: 180_000, }, ) } @@ -38,41 +79,90 @@ impl VaraMan for Program<'_> { fn vara_man_with_config(system: &System, config: Config) -> Program<'_> { let vara_man = Program::current_with_id(system, VARA_MAN_ID); assert!(!vara_man.send(ADMIN, VaraManInit { config }).main_failed()); - vara_man } - fn register_player(&self, from: u64, name: &str, error: Option) { + fn finish_single_game( + &self, + from: u64, + gold_coins: u128, + silver_coins: u128, + error: Option, + ) { self.send_tx( from, - VaraManAction::RegisterPlayer { - name: name.to_owned(), + VaraManAction::FinishSingleGame { + gold_coins, + silver_coins, + level: Level::Easy, }, error, ); } - - fn start_game(&self, from: u64, level: Level, error: Option) { - self.send_tx(from, VaraManAction::StartGame { level }, error); - } - - fn claim_reward( + fn record_tournament_result( &self, from: u64, - silver_coins: u64, - gold_coins: u64, + time: u128, + gold_coins: u128, + silver_coins: u128, error: Option, ) { self.send_tx( from, - VaraManAction::ClaimReward { - silver_coins, + VaraManAction::RecordTournamentResult { + time, gold_coins, + silver_coins, }, error, ); } - + fn leave_game(&self, from: u64, error: Option) { + self.send_tx(from, VaraManAction::LeaveGame, error); + } + fn create_tournament( + &self, + from: u64, + tournament_name: String, + name: String, + level: Level, + duration_ms: u32, + value: u128, + error: Option, + ) { + self.send_tx_with_value( + from, + VaraManAction::CreateNewTournament { + tournament_name, + name, + level, + duration_ms, + }, + value, + error, + ); + } + fn register( + &self, + from: u64, + admin_id: ActorId, + name: String, + value: u128, + error: Option, + ) { + self.send_tx_with_value( + from, + VaraManAction::RegisterForTournament { admin_id, name }, + value, + error, + ); + } + fn cancel_register(&self, from: u64, error: Option) { + self.send_tx(from, VaraManAction::CancelRegister, error); + } + fn start_tournament(&self, from: u64, error: Option) { + self.send_tx(from, VaraManAction::StartTournament, error); + } fn change_status(&self, from: u64, status: Status) { self.send_tx(from, VaraManAction::ChangeStatus(status), None); } @@ -88,7 +178,19 @@ impl VaraMan for Program<'_> { fn send_tx(&self, from: u64, action: VaraManAction, error: Option) { let result = self.send(from, action); assert!(!result.main_failed()); - + if let Some(error) = error { + assert!(result.contains(&(from, Err::(error).encode()))); + } + } + fn send_tx_with_value( + &self, + from: u64, + action: VaraManAction, + value: u128, + error: Option, + ) { + let result = self.send_with_value(from, action, value); + assert!(!result.main_failed()); if let Some(error) = error { assert!(result.contains(&(from, Err::(error).encode()))); } @@ -105,3 +207,38 @@ impl VaraMan for Program<'_> { } } } + +#[allow(dead_code)] +pub fn init_mint_transfer_fungible_token(sys: &System, from: u64, to: u64) -> Program<'_> { + sys.init_logger(); + let ft = Program::from_file( + sys, + "../target/wasm32-unknown-unknown/debug/fungible_token.opt.wasm", + ); + + let res = ft.send( + from, + InitConfig { + name: String::from("MyToken"), + symbol: String::from("MTK"), + decimals: 18, + }, + ); + + assert!(!res.main_failed()); + + let res = ft.send(from, FTAction::Mint(100_000_000_000_000)); + assert!(!res.main_failed()); + + let res = ft.send( + from, + FTAction::Transfer { + from: from.into(), + to: to.into(), + amount: 100_000_000_000_000, + }, + ); + assert!(!res.main_failed()); + + ft +} diff --git a/contracts/vara-man/tests/utils_gclient/common.rs b/contracts/vara-man/tests/utils_gclient/common.rs index 1ddc240ba..1352fcc4d 100644 --- a/contracts/vara-man/tests/utils_gclient/common.rs +++ b/contracts/vara-man/tests/utils_gclient/common.rs @@ -1,7 +1,10 @@ -use super::vara_man; +use super::{common, vara_man}; use blake2_rfc::blake2b; -use gclient::{Error as GclientError, GearApi}; +use fungible_token_io::*; +use gclient::{Error as GclientError, EventProcessor, GearApi, Result}; +use gear_core::ids::{MessageId, ProgramId}; use gstd::{prelude::*, ActorId}; +use sp_core::H256; use vara_man_io::*; pub const HASH_LENGTH: usize = 32; @@ -16,9 +19,22 @@ pub async fn init(api: &GearApi) -> gclient::Result { .encode() .as_slice() .into(); - api.transfer(destination, api.total_balance(api.account_id()).await? / 2) + api.transfer(destination, api.total_balance(api.account_id()).await? / 5) .await?; - + let destination = get_user_to_actor_id("//Alex") + .await? + .encode() + .as_slice() + .into(); + api.transfer(destination, api.total_balance(api.account_id()).await? / 5) + .await?; + let program_id_vara_man = vara_man.as_ref(); + let program_id_vara_man: ProgramId = program_id_vara_man.into(); + api.transfer( + program_id_vara_man, + api.total_balance(api.account_id()).await? / 5, + ) + .await?; Ok(vara_man) } @@ -59,3 +75,79 @@ pub async fn upload_with_code_hash( Ok(code_hash) } + +pub async fn init_ft(api: &GearApi) -> Result<(MessageId, ProgramId, H256)> { + let mut listener = api.subscribe().await?; + assert!(listener.blocks_running().await?); + + let ft_init = InitConfig { + name: String::from("MyToken"), + symbol: String::from("MTK"), + decimals: 18, + } + .encode(); + + let path = "../target/wasm32-unknown-unknown/debug/fungible_token.opt.wasm"; + + let gas_info = api + .calculate_upload_gas(None, gclient::code_from_os(path)?, ft_init.clone(), 0, true) + .await?; + + api.upload_program_bytes( + gclient::code_from_os(path)?, + gclient::now_micros().to_le_bytes(), + ft_init, + gas_info.burned * 2, + 0, + ) + .await +} + +pub async fn init_mint_transfer_ft(api: &GearApi, to: ActorId) -> gclient::Result { + let mut listener = api.subscribe().await?; + assert!(listener.blocks_running().await?); + + let (message_id, program_ft_id, _hash) = init_ft(api).await?; + assert!(listener.message_processed(message_id).await?.succeed()); + + let ft_mint_payload = FTAction::Mint(100_000_000_000_000); + + let gas_info = api + .calculate_handle_gas(None, program_ft_id, ft_mint_payload.encode(), 0, true) + .await + .unwrap(); + + let (message_id, _) = api + .send_message(program_ft_id, ft_mint_payload, gas_info.burned * 2, 0) + .await?; + + assert!(listener.message_processed(message_id).await?.succeed()); + + let address = ActorId::new( + api.account_id() + .encode() + .try_into() + .expect("Unexpected invalid account id length."), + ); + + let ft_transfer_payload = FTAction::Transfer { + from: address, + to, + amount: 100_000_000_000_000, + }; + + let gas_info = api + .calculate_handle_gas(None, program_ft_id, ft_transfer_payload.encode(), 0, true) + .await + .unwrap(); + + let (message_id, _) = api + .send_message(program_ft_id, ft_transfer_payload, gas_info.burned * 2, 0) + .await?; + let program_ft_id: common::Hash = program_ft_id + .encode() + .try_into() + .expect("Unexpected invalid program id."); + + Ok(program_ft_id.into()) +} diff --git a/contracts/vara-man/tests/utils_gclient/vara_man.rs b/contracts/vara-man/tests/utils_gclient/vara_man.rs index 62bf1b355..252724fbe 100644 --- a/contracts/vara-man/tests/utils_gclient/vara_man.rs +++ b/contracts/vara-man/tests/utils_gclient/vara_man.rs @@ -9,16 +9,15 @@ pub async fn init(api: &GearApi) -> gclient::Result { init_with_config( api, Config { - one_coin_in_value: 1_000_000_000_000, - tokens_per_gold_coin_easy: 5, - tokens_per_silver_coin_easy: 1, - tokens_per_gold_coin_medium: 8, - tokens_per_silver_coin_medium: 2, - tokens_per_gold_coin_hard: 10, - tokens_per_silver_coin_hard: 3, - gold_coins: 5, - silver_coins: 20, - number_of_lives: 3, + one_point_in_value: 10_000_000_000_000, + points_per_gold_coin_easy: 5, + points_per_silver_coin_easy: 1, + points_per_gold_coin_medium: 8, + points_per_silver_coin_medium: 2, + points_per_gold_coin_hard: 10, + points_per_silver_coin_hard: 3, + gas_for_finish_tournament: 10_000_000_000, + time_for_single_round: 15_000, }, ) .await @@ -59,19 +58,25 @@ pub async fn init_with_config(api: &GearApi, config: Config) -> gclient::Result< Ok(program_id.into()) } -pub async fn register_player( +pub async fn create_tournament( api: &GearApi, program_id: &ActorId, - name: &str, + tournament_name: String, + name: String, + level: Level, + duration_ms: u32, error: Option, ) -> gclient::Result<()> { let result = send_message( api, program_id, - VaraManAction::RegisterPlayer { - name: name.to_owned(), + VaraManAction::CreateNewTournament { + tournament_name, + name, + level, + duration_ms, }, - 0, + 10_000_000_000_000, ) .await?; @@ -85,14 +90,21 @@ pub async fn register_player( Ok(()) } - -pub async fn start_game( +pub async fn register_for_tournament( api: &GearApi, program_id: &ActorId, - level: Level, + admin_id: ActorId, + name: String, + value: u128, error: Option, ) -> gclient::Result<()> { - let result = send_message(api, program_id, VaraManAction::StartGame { level }, 0).await?; + let result = send_message( + api, + program_id, + VaraManAction::RegisterForTournament { admin_id, name }, + value, + ) + .await?; let event: Result = Result::::decode(&mut result.as_ref()) @@ -104,20 +116,69 @@ pub async fn start_game( Ok(()) } +pub async fn start_tournament( + api: &GearApi, + program_id: &ActorId, + error: Option, +) -> gclient::Result<()> { + let result = send_message(api, program_id, VaraManAction::StartTournament, 0).await?; + + let event: Result = + Result::::decode(&mut result.as_ref()) + .expect("Unexpected invalid result payload."); + + if let Some(error) = error { + assert_eq!(event.unwrap_err(), error); + } -pub async fn claim_reward( + Ok(()) +} +pub async fn record_tournament_result( api: &GearApi, program_id: &ActorId, - silver_coins: u64, - gold_coins: u64, + time: u128, + gold_coins: u128, + silver_coins: u128, error: Option, ) -> gclient::Result<()> { let result = send_message( api, program_id, - VaraManAction::ClaimReward { + VaraManAction::RecordTournamentResult { + time, + gold_coins, silver_coins, + }, + 0, + ) + .await?; + + let event: Result = + Result::::decode(&mut result.as_ref()) + .expect("Unexpected invalid result payload."); + + println!("EVENT: {:?}", event); + + if let Some(error) = error { + assert_eq!(event.unwrap_err(), error); + } + + Ok(()) +} +pub async fn finish_single_game( + api: &GearApi, + program_id: &ActorId, + gold_coins: u128, + silver_coins: u128, + error: Option, +) -> gclient::Result<()> { + let result = send_message( + api, + program_id, + VaraManAction::FinishSingleGame { gold_coins, + silver_coins, + level: Level::Easy, }, 0, ) @@ -133,7 +194,23 @@ pub async fn claim_reward( Ok(()) } +pub async fn leave_game( + api: &GearApi, + program_id: &ActorId, + error: Option, +) -> gclient::Result<()> { + let result = send_message(api, program_id, VaraManAction::LeaveGame, 0).await?; + let event: Result = + Result::::decode(&mut result.as_ref()) + .expect("Unexpected invalid result payload."); + + if let Some(error) = error { + assert_eq!(event.unwrap_err(), error); + } + + Ok(()) +} pub async fn change_status( api: &GearApi, program_id: &ActorId, @@ -172,7 +249,7 @@ pub async fn change_config( Ok(()) } -pub async fn get_state(api: &GearApi, program_id: &ActorId) -> Option { +pub async fn get_state(api: &GearApi, program_id: &ActorId) -> Option { let program_id = program_id.encode().as_slice().into(); let reply = api .read_state(program_id, StateQuery::All.encode()) @@ -203,7 +280,7 @@ async fn send_message( .await?; let (message_id, _) = api - .send_message(program_id.into(), payload, gas_info.burned * 2, value) + .send_message(program_id.into(), payload, gas_info.min_limit, value) .await?; let (_, reply_data_result, _) = listener.reply_bytes_on(message_id).await?; diff --git a/contracts/w3bstreaming/Cargo.toml b/contracts/w3bstreaming/Cargo.toml index 1f2df0f19..43896bc2b 100644 --- a/contracts/w3bstreaming/Cargo.toml +++ b/contracts/w3bstreaming/Cargo.toml @@ -11,3 +11,7 @@ w3bstreaming-io.workspace = true [build-dependencies] w3bstreaming-io.workspace = true gear-wasm-builder.workspace = true + +[dev-dependencies] +gstd = { workspace = true, features = ["debug"] } +gtest.workspace = true diff --git a/contracts/w3bstreaming/io/Cargo.toml b/contracts/w3bstreaming/io/Cargo.toml index 394850f87..381c85e76 100644 --- a/contracts/w3bstreaming/io/Cargo.toml +++ b/contracts/w3bstreaming/io/Cargo.toml @@ -7,3 +7,5 @@ publish.workspace = true [dependencies] gstd.workspace = true gmeta.workspace = true +parity-scale-codec.workspace = true +scale-info.workspace = true diff --git a/contracts/w3bstreaming/io/src/lib.rs b/contracts/w3bstreaming/io/src/lib.rs index b1908265c..02d4c1c38 100644 --- a/contracts/w3bstreaming/io/src/lib.rs +++ b/contracts/w3bstreaming/io/src/lib.rs @@ -5,9 +5,7 @@ use gmeta::{InOut, Metadata, Out}; use gstd::{collections::BTreeMap, prelude::*, ActorId}; use scale_info::TypeInfo; -#[derive(Encode, Decode, TypeInfo, Clone)] -#[codec(crate = gstd::codec)] -#[scale_info(crate = gstd::scale_info)] +#[derive(Encode, Decode, TypeInfo, Clone, Debug, PartialEq, Eq)] pub struct Stream { pub broadcaster: ActorId, pub start_time: u64, @@ -15,12 +13,9 @@ pub struct Stream { pub title: String, pub img_link: String, pub description: Option, - pub watchers: Vec, } #[derive(Encode, Decode, TypeInfo, Clone)] -#[codec(crate = gstd::codec)] -#[scale_info(crate = gstd::scale_info)] pub struct Profile { pub name: Option, pub surname: Option, @@ -28,44 +23,27 @@ pub struct Profile { pub stream_ids: Vec, pub subscribers: Vec, pub subscriptions: Vec, - pub role: Role, } #[derive(Encode, Decode, Default, TypeInfo, Clone)] -#[codec(crate = gstd::codec)] -#[scale_info(crate = gstd::scale_info)] -pub struct Contract { +pub struct Program { pub streams: BTreeMap, pub users: BTreeMap, } #[derive(Encode, Decode, Default, TypeInfo, Clone)] -#[codec(crate = gstd::codec)] -#[scale_info(crate = gstd::scale_info)] pub struct State { pub streams: Vec<(String, Stream)>, pub users: Vec<(ActorId, Profile)>, } #[derive(Encode, Decode, TypeInfo, Clone)] -#[codec(crate = gstd::codec)] -#[scale_info(crate = gstd::scale_info)] -pub enum Role { - Speaker, -} - -#[derive(Encode, Decode, TypeInfo, Clone)] -#[codec(crate = gstd::codec)] -#[scale_info(crate = gstd::scale_info)] pub struct Subscription { pub account_id: ActorId, pub sub_date: u64, - pub next_write_off: Option, } #[derive(Encode, Decode, TypeInfo)] -#[codec(crate = gstd::codec)] -#[scale_info(crate = gstd::scale_info)] pub enum Action { NewStream { title: String, @@ -74,6 +52,17 @@ pub enum Action { end_time: u64, img_link: String, }, + DeleteStream { + stream_id: String, + }, + EditStream { + stream_id: String, + start_time: Option, + end_time: Option, + title: Option, + img_link: Option, + description: Option, + }, Subscribe { account_id: ActorId, }, @@ -85,33 +74,30 @@ pub enum Action { } #[derive(Encode, Decode, TypeInfo)] -#[codec(crate = gstd::codec)] -#[scale_info(crate = gstd::scale_info)] -pub enum ActionResult { +pub enum Event { StreamIsScheduled { id: String }, + StreamDeleted { id: String }, + StreamEdited, Subscribed, ProfileEdited, - StreamIsFinished { id: String }, - Error(String), } pub struct ProgramMetadata; impl Metadata for ProgramMetadata { - type Init = InOut<(), ()>; - type Handle = InOut; - type Reply = InOut<(), ()>; - type Others = InOut<(), ()>; + type Init = (); + type Handle = InOut; + type Reply = (); + type Others = (); type Signal = (); - type State = Out; + type State = Out; } -impl From for State { - fn from(contract: Contract) -> Self { +impl From for State { + fn from(program: Program) -> Self { Self { - streams: contract.streams.into_iter().collect(), - - users: contract.users.into_iter().collect(), + streams: program.streams.into_iter().collect(), + users: program.users.into_iter().collect(), } } } diff --git a/contracts/w3bstreaming/src/lib.rs b/contracts/w3bstreaming/src/lib.rs index c0e4f82d0..bb3496aa6 100644 --- a/contracts/w3bstreaming/src/lib.rs +++ b/contracts/w3bstreaming/src/lib.rs @@ -1,22 +1,22 @@ #![no_std] use gstd::{exec, msg, prelude::*}; -use w3bstreaming_io::{Action, ActionResult, Contract, Profile, Role, State, Stream, Subscription}; +use w3bstreaming_io::{Action, Event, Profile, Program, State, Stream, Subscription}; -static mut CONTRACT: Option = None; +static mut PROGRAM: Option = None; #[no_mangle] extern fn init() { - let contract = Contract { + let program = Program { ..Default::default() }; - unsafe { CONTRACT = Some(contract) }; + unsafe { PROGRAM = Some(program) }; } #[no_mangle] extern fn handle() { let input: Action = msg::load().expect("Unable to load message"); - let contract = unsafe { CONTRACT.as_mut().expect("The contract is not initialized") }; + let program = unsafe { PROGRAM.as_mut().expect("The program is not initialized") }; match input { Action::NewStream { @@ -27,56 +27,113 @@ extern fn handle() { img_link, } => { let stream_id = exec::block_timestamp().to_string() + &title; - if let Some(profile) = contract.users.get_mut(&msg::source()) { + let msg_src = msg::source(); + if let Some(profile) = program.users.get_mut(&msg_src) { profile.stream_ids.push(stream_id.clone()); } else { panic!("Account is no registered"); } - contract.streams.insert( + program.streams.insert( stream_id.clone(), Stream { - broadcaster: msg::source(), + broadcaster: msg_src, img_link, start_time, end_time, title, description, - watchers: Vec::new(), }, ); - msg::reply(ActionResult::StreamIsScheduled { id: stream_id }, 0) + msg::reply(Event::StreamIsScheduled { id: stream_id }, 0) .expect("Unable to send reply"); } + Action::DeleteStream { stream_id } => { + let msg_src = msg::source(); + let profile = program + .users + .get_mut(&msg_src) + .expect("Account is no registered"); + let index = profile + .stream_ids + .iter() + .position(|x| *x == stream_id) + .expect("Id is not exist"); + profile.stream_ids.remove(index); + + let stream = program.streams.get(&stream_id).expect("Id is not exist"); + if stream.broadcaster == msg_src { + program.streams.remove(&stream_id); + } else { + panic!("You are not broadcaster"); + } + + msg::reply(Event::StreamDeleted { id: stream_id }, 0).expect("Unable to send reply"); + } + Action::EditStream { + stream_id, + start_time, + end_time, + title, + img_link, + description, + } => { + let msg_src = msg::source(); + + if let Some(stream) = program.streams.get_mut(&stream_id) { + if stream.broadcaster == msg_src { + if let Some(start_time) = start_time { + stream.start_time = start_time; + } + if let Some(end_time) = end_time { + stream.end_time = end_time; + } + if let Some(title) = title { + stream.title = title; + } + if let Some(img_link) = img_link { + stream.img_link = img_link; + } + stream.description = description; + } else { + panic!("You are not broadcaster"); + } + } else { + panic!("Id is not exist"); + } + + msg::reply(Event::StreamEdited, 0).expect("Unable to send reply"); + } Action::Subscribe { account_id } => { - if contract.users.get(&account_id).is_none() { + if !program.users.contains_key(&account_id) { panic!("The user is not found"); } - if contract.users.get(&msg::source()).is_none() { + let msg_src = msg::source(); + + if !program.users.contains_key(&msg_src) { panic!("You are not registered"); } - contract + program .users .entry(account_id) - .and_modify(|profile| profile.subscribers.push(msg::source())); + .and_modify(|profile| profile.subscribers.push(msg_src)); - contract.users.entry(msg::source()).and_modify(|profile| { + program.users.entry(msg_src).and_modify(|profile| { profile.subscriptions.push(Subscription { account_id, sub_date: exec::block_timestamp(), - next_write_off: None, }) }); - msg::reply(ActionResult::Subscribed, 0).expect("Unable to send reply"); + msg::reply(Event::Subscribed, 0).expect("Unable to send reply"); } Action::EditProfile { name, surname, img_link, } => { - contract + program .users .entry(msg::source()) .and_modify(|profile| { @@ -91,16 +148,15 @@ extern fn handle() { stream_ids: Vec::new(), subscribers: Vec::new(), subscriptions: Vec::new(), - role: Role::Speaker, }); - msg::reply(ActionResult::ProfileEdited, 0).expect("Unable to send reply"); + msg::reply(Event::ProfileEdited, 0).expect("Unable to send reply"); } }; } #[no_mangle] extern fn state() { - let contract = unsafe { CONTRACT.take().expect("Unexpected error in taking state") }; - msg::reply::(contract.into(), 0).expect("Failed to share state"); + let program = unsafe { PROGRAM.take().expect("Unexpected error in taking state") }; + msg::reply::(program.into(), 0).expect("Failed to share state"); } diff --git a/contracts/w3bstreaming/tests/test.rs b/contracts/w3bstreaming/tests/test.rs new file mode 100644 index 000000000..13deacf03 --- /dev/null +++ b/contracts/w3bstreaming/tests/test.rs @@ -0,0 +1,196 @@ +use gtest::{Program, System}; +use w3bstreaming_io::*; + +pub const USERS: [u64; 3] = [10, 11, 12]; + +fn edit_profile( + web_stream: &Program<'_>, + from: u64, + name: Option, + surname: Option, + img_link: Option, + error: bool, +) { + let res = web_stream.send( + from, + Action::EditProfile { + name, + surname, + img_link, + }, + ); + + assert_eq!(error, res.main_failed()); +} + +#[allow(clippy::too_many_arguments)] +fn new_stream( + web_stream: &Program<'_>, + from: u64, + title: String, + description: Option, + start_time: u64, + end_time: u64, + img_link: String, + error: bool, +) { + let res = web_stream.send( + from, + Action::NewStream { + title, + description, + start_time, + end_time, + img_link, + }, + ); + assert_eq!(error, res.main_failed()); +} + +#[allow(clippy::too_many_arguments)] +fn edit_stream( + web_stream: &Program<'_>, + from: u64, + stream_id: String, + start_time: Option, + end_time: Option, + title: Option, + img_link: Option, + description: Option, + error: bool, +) { + let res = web_stream.send( + from, + Action::EditStream { + stream_id, + start_time, + end_time, + title, + img_link, + description, + }, + ); + assert_eq!(error, res.main_failed()); +} + +fn delete_stream(web_stream: &Program<'_>, from: u64, stream_id: String, error: bool) { + let res = web_stream.send(from, Action::DeleteStream { stream_id }); + assert_eq!(error, res.main_failed()); +} + +#[test] +fn success() { + let system = System::new(); + system.init_logger(); + let web_stream = Program::current(&system); + + let res = web_stream.send(USERS[0], 0); + assert!(!res.main_failed()); + + edit_profile(&web_stream, USERS[0], None, None, None, false); + + let state: State = web_stream.read_state(0).expect("Can't read state"); + assert_eq!(state.users[0].0, USERS[0].into()); + + new_stream( + &web_stream, + USERS[0], + "Title".to_string(), + None, + 10, + 100, + "img_link".to_string(), + false, + ); + + let state: State = web_stream.read_state(0).expect("Can't read state"); + assert_eq!(state.streams[0].1.broadcaster, USERS[0].into()); + let stream_id = state.streams[0].0.clone(); + + edit_stream( + &web_stream, + USERS[0], + stream_id.clone(), + Some(20), + Some(200), + Some("title_update".to_string()), + None, + None, + false, + ); + + let stream = Stream { + broadcaster: USERS[0].into(), + start_time: 20, + end_time: 200, + title: "title_update".to_string(), + img_link: "img_link".to_string(), + description: None, + }; + + let state: State = web_stream.read_state(0).expect("Can't read state"); + assert_eq!(state.streams[0].1, stream); + + delete_stream(&web_stream, USERS[0], stream_id, false); + + let state: State = web_stream.read_state(0).expect("Can't read state"); + assert!(state.streams.is_empty()); +} + +#[test] +fn failures() { + let system = System::new(); + system.init_logger(); + let web_stream = Program::current(&system); + + let res = web_stream.send(USERS[0], 0); + assert!(!res.main_failed()); + + // not registered + new_stream( + &web_stream, + USERS[0], + "Title".to_string(), + None, + 10, + 100, + "img_link".to_string(), + true, + ); + + edit_profile(&web_stream, USERS[0], None, None, None, false); + + let state: State = web_stream.read_state(0).expect("Can't read state"); + assert_eq!(state.users[0].0, USERS[0].into()); + + new_stream( + &web_stream, + USERS[0], + "Title".to_string(), + None, + 10, + 100, + "img_link".to_string(), + false, + ); + + let state: State = web_stream.read_state(0).expect("Can't read state"); + assert_eq!(state.streams[0].1.broadcaster, USERS[0].into()); + let stream_id = state.streams[0].0.clone(); + + // Not broadcaster + edit_stream( + &web_stream, + USERS[1], + stream_id.clone(), + Some(20), + Some(200), + Some("title_update".to_string()), + None, + None, + true, + ); + + // Account is no registered + delete_stream(&web_stream, USERS[1], stream_id, true); +} diff --git a/frontend/apps/battleship/package.json b/frontend/apps/battleship/package.json index f01ab9872..98855f4b4 100644 --- a/frontend/apps/battleship/package.json +++ b/frontend/apps/battleship/package.json @@ -4,30 +4,32 @@ "version": "1.0.2", "type": "module", "scripts": { - "start": "yarn build:packages && vite --open", - "build": "yarn build:packages && tsc && vite build", + "start": "yarn build:packages && yarn build:ez-transactions && vite --open", + "build": "yarn build:packages && yarn build:ez-transactions && tsc && vite build", "preview": "vite preview" }, "dependencies": { "@dapps-frontend/error-tracking": "workspace:*", - "@dapps-frontend/gasless-transactions": "workspace:*", + "@dapps-frontend/ez-transactions": "workspace:*", "@dapps-frontend/hooks": "workspace:*", - "@dapps-frontend/signless-transactions": "workspace:*", "@dapps-frontend/ui": "workspace:*", - "@gear-js/api": "0.35.2", - "@gear-js/react-hooks": "0.9.4", + "@gear-js/api": "0.36.5", + "@gear-js/react-hooks": "0.10.6", "@gear-js/ui": "0.5.21", "@gear-js/vara-ui": "0.0.6", "@mantine/form": "6.0.15", - "@polkadot/api": "10.10.1", + "@polkadot/api": "10.11.2", "@polkadot/extension-dapp": "0.46.5", - "@polkadot/react-identicon": "3.5.1", - "@polkadot/types": "10.10.1", + "@polkadot/react-identicon": "3.1.4", + "@polkadot/types": "10.11.2", "@polkadot/util": "12.3.2", "@radix-ui/react-dropdown-menu": "2.0.5", "@radix-ui/react-scroll-area": "1.0.4", "@radix-ui/react-select": "1.2.2", "@tanstack/react-table": "8.9.3", + "@types/node": "18.16.19", + "@types/react": "18.2.33", + "@types/react-dom": "18.2.14", "buffer": "6.0.3", "class-variance-authority": "0.6.1", "clsx": "1.2.1", @@ -39,12 +41,10 @@ "react-dom": "18.2.0", "react-hook-form": "7.48.2", "react-router-dom": "6.10.0", - "react-transition-group": "4.4.5" + "react-transition-group": "4.4.5", + "sass": "1.62.0" }, "devDependencies": { - "@types/node": "18.16.19", - "@types/react": "18.2.33", - "@types/react-dom": "18.2.14", "@vitejs/plugin-react-swc": "3.3.2", "autoprefixer": "10.4.14", "eslint": "8.43.0", @@ -52,11 +52,10 @@ "node-stdlib-browser": "1.2.0", "postcss": "8.4.24", "prettier": "2.8.8", - "sass": "1.62.0", "tailwindcss": "3.3.2", "typescript": "4.9.5", "vite": "4.3.9", - "vite-plugin-eslint": "1.8.1", + "vite-plugin-checker": "0.6.4", "vite-plugin-node-stdlib-browser": "0.2.1", "vite-plugin-svgr": "3.2.0", "vite-plugin-top-level-await": "1.3.1", diff --git a/frontend/apps/battleship/src/app.scss b/frontend/apps/battleship/src/app.scss index 7b34530a1..58486ede2 100644 --- a/frontend/apps/battleship/src/app.scss +++ b/frontend/apps/battleship/src/app.scss @@ -21,5 +21,5 @@ main { display: flex; flex-direction: column; flex: 1; - padding: 100px 16px; + padding: 80px 0 0; } diff --git a/frontend/apps/battleship/src/app.tsx b/frontend/apps/battleship/src/app.tsx index c18dcf713..221058eb6 100644 --- a/frontend/apps/battleship/src/app.tsx +++ b/frontend/apps/battleship/src/app.tsx @@ -7,6 +7,7 @@ import { Header } from '@/components/layout'; import { withProviders } from '@/app/hocs'; import { useAccountAvailableBalanceSync, useWalletSync } from '@/features/wallet/hooks'; +import { Container, Footer } from '@dapps-frontend/ui'; function Component() { const { isApiReady } = useApi(); @@ -23,6 +24,9 @@ function Component() { <>
+ +