From 90ac0c4d890c2580ed345ccd57950dede9a6ca8f Mon Sep 17 00:00:00 2001 From: Braqzen <103777923+Braqzen@users.noreply.github.com> Date: Fri, 26 Apr 2024 16:17:52 +0100 Subject: [PATCH 01/10] Initial commit --- Cargo.lock | 235 +++++++++++--------- Cargo.toml | 61 ++---- Forc.lock | 27 --- Forc.toml | 2 - contract/fuel-toolchain.toml | 6 + scripts/Cargo.toml | 58 +++++ scripts/cancel_order.rs | 28 +-- scripts/create_accounts_with_tokens.rs | 28 ++- scripts/create_market.rs | 29 +-- scripts/create_order.rs | 37 ++-- scripts/deploy.rs | 26 +-- scripts/fill_orderbook.rs | 31 +-- scripts/init_system.rs | 92 ++++---- scripts/match_orders.rs | 50 +++-- spark-market-sdk/Cargo.toml | 17 ++ spark-market-sdk/src/lib.rs | 218 +++++++++++++++++++ src/orderbook_utils.rs | 216 ------------------- tests/Cargo.toml | 22 ++ tests/harness.rs | 2 - tests/main_test.rs | 287 +++++++++++-------------- tests/match_orders.rs | 233 ++++++++++---------- utils/Cargo.toml | 13 ++ {src => utils}/constants.rs | 4 +- utils/lib.rs | 2 + src/lib.rs => utils/title.rs | 3 - 25 files changed, 892 insertions(+), 835 deletions(-) delete mode 100644 Forc.lock delete mode 100644 Forc.toml create mode 100644 contract/fuel-toolchain.toml create mode 100644 scripts/Cargo.toml create mode 100644 spark-market-sdk/Cargo.toml create mode 100644 spark-market-sdk/src/lib.rs delete mode 100644 src/orderbook_utils.rs create mode 100644 tests/Cargo.toml delete mode 100644 tests/harness.rs create mode 100644 utils/Cargo.toml rename {src => utils}/constants.rs (89%) create mode 100644 utils/lib.rs rename src/lib.rs => utils/title.rs (98%) diff --git a/Cargo.lock b/Cargo.lock index b613b35..fda89be 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -61,9 +61,9 @@ dependencies = [ [[package]] name = "allocator-api2" -version = "0.2.16" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" [[package]] name = "android-tzdata" @@ -232,18 +232,18 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] name = "async-trait" -version = "0.1.79" +version = "0.1.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507401cad91ec6a857ed5513a2073c82a9b9048762b885bb98655b306964681" +checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -423,9 +423,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.92" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2678b2e3449475e95b0aa6f9b506a28e61b3dc8996592b983695e8ebb58a8b41" +checksum = "d32a725bc159af97c3e629873bb9f88fb8cf8a4867175f76dc987815ea07c83b" [[package]] name = "cfg-if" @@ -435,16 +435,16 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.37" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a0d04d43504c61aa6c7531f1871dd0d418d91130162063b789da00fd7057a5e" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" dependencies = [ "android-tzdata", "iana-time-zone", "js-sys", "num-traits", "wasm-bindgen", - "windows-targets 0.52.4", + "windows-targets 0.52.5", ] [[package]] @@ -488,7 +488,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -749,7 +749,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -966,9 +966,9 @@ dependencies = [ [[package]] name = "either" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" +checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" [[package]] name = "elliptic-curve" @@ -1015,13 +1015,13 @@ dependencies = [ [[package]] name = "enum-iterator-derive" -version = "1.3.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03cdc46ec28bd728e67540c528013c6a10eb69a02eb31078a1bda695438cbfb8" +checksum = "c19cbb53d33b57ac4df1f0af6b92c38c107cded663c4aea9fae1189dcfc17cf5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -1101,9 +1101,9 @@ dependencies = [ [[package]] name = "fiat-crypto" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c007b1ae3abe1cb6f85a16305acd418b7ca6343b953633fee2b76d8f108b830f" +checksum = "38793c55593b33412e3ae40c2c9781ffaa6f438f6f8c10f24e71846fbd7ae01e" [[package]] name = "fixed-hash" @@ -1142,7 +1142,7 @@ dependencies = [ "regex", "serde", "serde_json", - "syn 2.0.58", + "syn 2.0.60", "thiserror", ] @@ -1442,7 +1442,7 @@ checksum = "ff58cf4d01a4fb9440c63a8764154dfd3b07c74e4b3639cce8eea77d67e63a7a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", "synstructure", ] @@ -1587,7 +1587,7 @@ dependencies = [ "quote", "regex", "serde_json", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -1628,7 +1628,7 @@ dependencies = [ "proc-macro2", "quote", "rand", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -1673,7 +1673,7 @@ dependencies = [ "rand", "serde", "serde_json", - "serde_with 3.7.0", + "serde_with 3.8.0", "tempfile", "tokio", "which", @@ -1741,7 +1741,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -2027,7 +2027,7 @@ dependencies = [ "http", "hyper", "log", - "rustls 0.21.10", + "rustls 0.21.11", "rustls-native-certs 0.6.3", "tokio", "tokio-rustls 0.24.1", @@ -2329,18 +2329,6 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" -[[package]] -name = "orderbook" -version = "0.1.0" -dependencies = [ - "dotenv", - "fuels", - "hex", - "rand", - "src20_sdk", - "tokio", -] - [[package]] name = "p256" version = "0.13.2" @@ -2435,7 +2423,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -2530,9 +2518,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.79" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" +checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" dependencies = [ "unicode-ident", ] @@ -2569,7 +2557,7 @@ checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -2727,7 +2715,7 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", - "rustls 0.21.10", + "rustls 0.21.11", "rustls-pemfile", "serde", "serde_json", @@ -2811,9 +2799,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.32" +version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65e04861e65f21776e67888bfbea442b3642beaa0138fdb1dd7a84a52dffdb89" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ "bitflags 2.5.0", "errno", @@ -2837,9 +2825,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.21.10" +version = "0.21.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" +checksum = "7fecbfb7b1444f477b345853b1fce097a2c6fb637b2bfb87e6bc5db0f043fae4" dependencies = [ "log", "ring 0.17.8", @@ -2952,6 +2940,21 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "scripts" +version = "0.1.0" +dependencies = [ + "anyhow", + "dotenv", + "fuels", + "hex", + "rand", + "spark-market-sdk", + "src20_sdk", + "tokio", + "utils", +] + [[package]] name = "scrypt" version = "0.10.0" @@ -3057,29 +3060,29 @@ checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" [[package]] name = "serde" -version = "1.0.197" +version = "1.0.198" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +checksum = "9846a40c979031340571da2545a4e5b7c4163bdae79b301d5f86d03979451fcc" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.197" +version = "1.0.198" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +checksum = "e88edab869b01783ba905e7d0153f9fc1a6505a96e4ad3018011eedb838566d9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] name = "serde_json" -version = "1.0.115" +version = "1.0.116" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd" +checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813" dependencies = [ "itoa", "ryu", @@ -3110,9 +3113,9 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.7.0" +version = "3.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee80b0e361bbf88fd2f6e242ccd19cfda072cb0faa6ae694ecee08199938569a" +checksum = "2c85f8e96d1d6857f13768fcbd895fcb06225510022a2774ed8b5150581847b0" dependencies = [ "serde", "serde_derive", @@ -3153,9 +3156,9 @@ dependencies = [ [[package]] name = "signal-hook-registry" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" dependencies = [ "libc", ] @@ -3195,6 +3198,16 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "spark-market-sdk" +version = "0.1.0" +dependencies = [ + "anyhow", + "fuels", + "rand", + "tokio", +] + [[package]] name = "spin" version = "0.5.2" @@ -3223,7 +3236,7 @@ dependencies = [ [[package]] name = "src20_sdk" version = "0.0.3" -source = "git+https://github.com/compolabs/src-20.git?branch=master#b424fdd6d8a11bcdbfe4be55dea8ac81edea67de" +source = "git+https://github.com/compolabs/src-20.git?branch=master#da1900d2881d44208064111ad4f3bccd8b37338b" dependencies = [ "dotenv", "fuels", @@ -3300,9 +3313,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.58" +version = "2.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687" +checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" dependencies = [ "proc-macro2", "quote", @@ -3323,7 +3336,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -3374,24 +3387,35 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "tests" +version = "0.1.0" +dependencies = [ + "anyhow", + "fuels", + "spark-market-sdk", + "src20_sdk", + "tokio", +] + [[package]] name = "thiserror" -version = "1.0.58" +version = "1.0.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" +checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.58" +version = "1.0.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" +checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -3477,7 +3501,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -3507,7 +3531,7 @@ version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" dependencies = [ - "rustls 0.21.10", + "rustls 0.21.11", "tokio", ] @@ -3623,7 +3647,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -3736,6 +3760,10 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +[[package]] +name = "utils" +version = "0.1.0" + [[package]] name = "uuid" version = "0.8.2" @@ -3803,7 +3831,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", "wasm-bindgen-shared", ] @@ -3837,7 +3865,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3915,7 +3943,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.52.4", + "windows-targets 0.52.5", ] [[package]] @@ -3933,7 +3961,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.4", + "windows-targets 0.52.5", ] [[package]] @@ -3953,17 +3981,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" dependencies = [ - "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", + "windows_aarch64_gnullvm 0.52.5", + "windows_aarch64_msvc 0.52.5", + "windows_i686_gnu 0.52.5", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.5", + "windows_x86_64_gnu 0.52.5", + "windows_x86_64_gnullvm 0.52.5", + "windows_x86_64_msvc 0.52.5", ] [[package]] @@ -3974,9 +4003,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" [[package]] name = "windows_aarch64_msvc" @@ -3986,9 +4015,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" [[package]] name = "windows_i686_gnu" @@ -3998,9 +4027,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.4" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" [[package]] name = "windows_i686_msvc" @@ -4010,9 +4045,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" [[package]] name = "windows_x86_64_gnu" @@ -4022,9 +4057,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" [[package]] name = "windows_x86_64_gnullvm" @@ -4034,9 +4069,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" [[package]] name = "windows_x86_64_msvc" @@ -4046,9 +4081,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" [[package]] name = "winnow" @@ -4095,7 +4130,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -4115,5 +4150,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] diff --git a/Cargo.toml b/Cargo.toml index 39918ef..dea653d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,53 +1,22 @@ -[package] -name = "orderbook" -description = "A cargo-generate template for Rust + Sway integration testing." +[workspace] +resolver = "1" +members = [ + "spark-market-sdk", + "scripts", + "tests", + "utils", +] + +[workspace.package] +authors = ["alexey "] version = "0.1.0" edition = "2021" -authors = ["alexey "] license = "Apache-2.0" +rust-version = "1.75.0" -[dependencies] +[workspace.dependencies] +anyhow = "1.0.81" fuels = { version = "0.55.1", features = ["fuel-core-lib"] } -rand = "0.8.5" tokio = { version = "1.12", features = ["rt", "macros"] } src20_sdk = { git = "https://github.com/compolabs/src-20.git", branch = "master" } -dotenv = "0.15.0" -hex = "0.4" - -[[test]] -harness = true -name = "integration_tests" -path = "tests/harness.rs" - - -[[bin]] -name = "create_market" -path = "scripts/create_market.rs" - -[[bin]] -name = "create_order" -path = "scripts/create_order.rs" - -[[bin]] -name = "cancel_order" -path = "scripts/cancel_order.rs" - -[[bin]] -name = "deploy" -path = "scripts/deploy.rs" - -[[bin]] -name = "match_orders" -path = "scripts/match_orders.rs" - -[[bin]] -name = "create_accounts_with_tokens" -path = "scripts/create_accounts_with_tokens.rs" - -[[bin]] -name = "init_system" -path = "scripts/init_system.rs" - -[[bin]] -name = "fill_orderbook" -path = "scripts/fill_orderbook.rs" \ No newline at end of file +rand = "0.8.5" diff --git a/Forc.lock b/Forc.lock deleted file mode 100644 index 74e0598..0000000 --- a/Forc.lock +++ /dev/null @@ -1,27 +0,0 @@ -[[package]] -name = "core" -source = "path+from-root-566CA1D5F8BEAFBF" - -[[package]] -name = "i64" -source = "git+https://github.com/compolabs/i64?default-branch#b983e37ec72b60a3544bde52babebec61b15c710" -dependencies = ["std"] - -[[package]] -name = "orderbook" -source = "member" -dependencies = [ - "i64", - "reentrancy", - "std", -] - -[[package]] -name = "reentrancy" -source = "git+https://github.com/FuelLabs/sway-libs?tag=v0.18.0#8d196e9379463d4596ac582a20a84ed52ff58c69" -dependencies = ["std"] - -[[package]] -name = "std" -source = "git+https://github.com/fuellabs/sway?tag=v0.49.3#0dc6570377ee9c4a6359ade597fa27351e02a728" -dependencies = ["core"] diff --git a/Forc.toml b/Forc.toml deleted file mode 100644 index d7fbaaa..0000000 --- a/Forc.toml +++ /dev/null @@ -1,2 +0,0 @@ -[workspace] -members = ["contract"] diff --git a/contract/fuel-toolchain.toml b/contract/fuel-toolchain.toml new file mode 100644 index 0000000..ae7d2a7 --- /dev/null +++ b/contract/fuel-toolchain.toml @@ -0,0 +1,6 @@ +[toolchain] +channel = "beta-5" + +[components] +forc = "0.49.3" +fuel-core = "0.22.1" diff --git a/scripts/Cargo.toml b/scripts/Cargo.toml new file mode 100644 index 0000000..be5263e --- /dev/null +++ b/scripts/Cargo.toml @@ -0,0 +1,58 @@ +[package] +name = "scripts" +authors = { workspace = true } +version = { workspace = true } +edition = { workspace = true } +license = { workspace = true } +rust-version = { workspace = true } + +[dependencies] +anyhow = { workspace = true } +fuels = { workspace = true } +tokio = { workspace = true } +spark-market-sdk = { path = "../spark-market-sdk" } +utils = { path = "../utils" } +src20_sdk = { workspace = true } +dotenv = "0.15.0" +hex = "0.4" +rand = { workspace = true } + +[[bin]] +name = "create_market" +path = "create_market.rs" +test = false + +[[bin]] +name = "create_order" +path = "create_order.rs" +test = false + +[[bin]] +name = "cancel_order" +path = "cancel_order.rs" +test = false + +[[bin]] +name = "deploy" +path = "deploy.rs" +test = false + +[[bin]] +name = "match_orders" +path = "match_orders.rs" +test = false + +[[bin]] +name = "create_accounts_with_tokens" +path = "create_accounts_with_tokens.rs" +test = false + +[[bin]] +name = "init_system" +path = "init_system.rs" +test = false + +[[bin]] +name = "fill_orderbook" +path = "fill_orderbook.rs" +test = false diff --git a/scripts/cancel_order.rs b/scripts/cancel_order.rs index 8e04781..75dfc19 100644 --- a/scripts/cancel_order.rs +++ b/scripts/cancel_order.rs @@ -1,35 +1,39 @@ +use std::str::FromStr; + use dotenv::dotenv; use fuels::{ prelude::{Provider, WalletUnlocked}, - types::Bits256, + types::{Bits256, ContractId}, }; -use orderbook::{ +use spark_market_sdk::OrderbookContract; +use utils::{ constants::{ORDERBOOK_CONTRACT_ID, RPC}, - orderbook_utils::Orderbook, - print_title, + title::print_title, }; const ORDER_ID: &str = "0x2b04ddb4fe13fd38f0edf10c347ba059f8404bc9063e76857df31a414163db38"; #[tokio::main] -async fn main() { +async fn main() -> anyhow::Result<()> { print_title("Cancel order"); dotenv().ok(); let provider = Provider::connect(RPC).await.unwrap(); let secret = std::env::var("ADMIN").unwrap(); - let wallet = - WalletUnlocked::new_from_private_key(secret.parse().unwrap(), Some(provider.clone())); + let wallet = WalletUnlocked::new_from_private_key(secret.parse().unwrap(), Some(provider)); - let orderbook = Orderbook::new(&wallet, ORDERBOOK_CONTRACT_ID).await; + let orderbook = + OrderbookContract::new(ContractId::from_str(ORDERBOOK_CONTRACT_ID).unwrap(), wallet) + .await?; - let id = &Bits256::from_hex_str(ORDER_ID).unwrap(); + let id = &Bits256::from_hex_str(ORDER_ID)?; - let order = orderbook.order_by_id(id).await.unwrap().value; + let order = orderbook.order_by_id(id).await?.value; assert!(order.is_some()); orderbook .cancel_order(id) //fixme TransferZeroCoins - .await - .unwrap(); + .await?; + + Ok(()) } diff --git a/scripts/create_accounts_with_tokens.rs b/scripts/create_accounts_with_tokens.rs index c0213f7..56239f1 100644 --- a/scripts/create_accounts_with_tokens.rs +++ b/scripts/create_accounts_with_tokens.rs @@ -6,10 +6,10 @@ use fuels::{ prelude::{Provider, WalletUnlocked}, types::{transaction::TxPolicies, ContractId}, }; -use orderbook::constants::{RPC, TOKEN_CONTRACT_ID}; use rand::{rngs::StdRng, SeedableRng}; use src20_sdk::token_utils::{Asset, TokenContract}; use std::str::FromStr; +use utils::constants::{RPC, TOKEN_CONTRACT_ID}; const AMOUNT_OF_WALLETS: u64 = 5; // const AMOUNT_OF_WALLETS: u64 = 1; @@ -19,15 +19,14 @@ const BASE_SIZE: f64 = 1.; const QUOTE_SIZE: f64 = 70000.; #[tokio::main] -async fn main() { +async fn main() -> anyhow::Result<()> { dotenv().ok(); - let provider = Provider::connect(RPC).await.unwrap(); - let secret = std::env::var("ADMIN").unwrap(); - let admin = - WalletUnlocked::new_from_private_key(secret.parse().unwrap(), Some(provider.clone())); + let provider = Provider::connect(RPC).await?; + let secret = std::env::var("ADMIN")?; + let admin = WalletUnlocked::new_from_private_key(secret.parse()?, Some(provider.clone())); let token_contract = TokenContract::new( - &ContractId::from_str(TOKEN_CONTRACT_ID).unwrap().into(), + ContractId::from_str(TOKEN_CONTRACT_ID).unwrap(), admin.clone(), ); @@ -62,17 +61,14 @@ async fn main() { BASE_ASSET_ID, TxPolicies::default(), ) - .await - .unwrap(); + .await?; - base_asset - .mint(wallet.address().into(), base_size) - .await - .unwrap(); + base_asset.mint(wallet.address().into(), base_size).await?; quote_asset .mint(wallet.address().into(), quote_size as u64) - .await - .unwrap(); + .await?; } -} \ No newline at end of file + + Ok(()) +} diff --git a/scripts/create_market.rs b/scripts/create_market.rs index a2b111a..6ffb8db 100644 --- a/scripts/create_market.rs +++ b/scripts/create_market.rs @@ -1,30 +1,28 @@ -use std::str::FromStr; - use dotenv::dotenv; use fuels::{ prelude::{Provider, WalletUnlocked}, types::ContractId, }; -use orderbook::{ +use spark_market_sdk::OrderbookContract; +use src20_sdk::token_utils::{Asset, TokenContract}; +use std::str::FromStr; +use utils::{ constants::{ORDERBOOK_CONTRACT_ID, RPC, TOKEN_CONTRACT_ID}, - orderbook_utils::Orderbook, - print_title, + title::print_title, }; -use src20_sdk::token_utils::{Asset, TokenContract}; const MARKET_SYMBOL: &str = "BTC"; #[tokio::main] -async fn main() { +async fn main() -> anyhow::Result<()> { print_title("Create market"); dotenv().ok(); let provider = Provider::connect(RPC).await.unwrap(); let secret = std::env::var("ADMIN").unwrap(); - let wallet = - WalletUnlocked::new_from_private_key(secret.parse().unwrap(), Some(provider.clone())); + let wallet = WalletUnlocked::new_from_private_key(secret.parse().unwrap(), Some(provider)); let token_contarct = TokenContract::new( - &ContractId::from_str(TOKEN_CONTRACT_ID).unwrap().into(), + ContractId::from_str(TOKEN_CONTRACT_ID).unwrap(), wallet.clone(), ); @@ -34,10 +32,13 @@ async fn main() { MARKET_SYMBOL, ); - let orderbook = Orderbook::new(&wallet, ORDERBOOK_CONTRACT_ID).await; + let orderbook = + OrderbookContract::new(ContractId::from_str(ORDERBOOK_CONTRACT_ID).unwrap(), wallet) + .await?; orderbook - ._create_market(asset.asset_id, asset.decimals as u32) - .await - .unwrap(); + .create_market(asset.asset_id, asset.decimals as u32) + .await?; + + Ok(()) } diff --git a/scripts/create_order.rs b/scripts/create_order.rs index b120743..569e572 100644 --- a/scripts/create_order.rs +++ b/scripts/create_order.rs @@ -3,29 +3,28 @@ use fuels::{ prelude::{Provider, WalletUnlocked}, types::{Address, ContractId}, }; -use orderbook::{ - constants::{ORDERBOOK_CONTRACT_ID, RPC, TOKEN_CONTRACT_ID}, - orderbook_utils::Orderbook, - print_title, -}; +use spark_market_sdk::OrderbookContract; use src20_sdk::token_utils::{Asset, TokenContract}; use std::str::FromStr; +use utils::{ + constants::{ORDERBOOK_CONTRACT_ID, RPC, TOKEN_CONTRACT_ID}, + title::print_title, +}; const MARKET_SYMBOL: &str = "UNI"; const BASE_SIZE: i64 = -100; //units const BASE_PRICE: u64 = 10; //units #[tokio::main] -async fn main() { +async fn main() -> anyhow::Result<()> { print_title("Create Order"); dotenv().ok(); - let provider = Provider::connect(RPC).await.unwrap(); - let secret = std::env::var("ADMIN").unwrap(); - let wallet = - WalletUnlocked::new_from_private_key(secret.parse().unwrap(), Some(provider.clone())); + let provider = Provider::connect(RPC).await?; + let secret = std::env::var("ADMIN")?; + let wallet = WalletUnlocked::new_from_private_key(secret.parse()?, Some(provider)); let token_contract = TokenContract::new( - &ContractId::from_str(TOKEN_CONTRACT_ID).unwrap().into(), + ContractId::from_str(TOKEN_CONTRACT_ID).unwrap(), wallet.clone(), ); @@ -33,20 +32,20 @@ async fn main() { let base_asset = Asset::new(wallet.clone(), token_contract_id, MARKET_SYMBOL); let quote_asset = Asset::new(wallet.clone(), token_contract_id, "USDC"); - let orderbook = Orderbook::new(&wallet, ORDERBOOK_CONTRACT_ID).await; + let orderbook = OrderbookContract::new( + ContractId::from_str(ORDERBOOK_CONTRACT_ID).unwrap(), + wallet.clone(), + ) + .await?; if BASE_SIZE > 0 { let quote_size = quote_asset.parse_units(BASE_SIZE as f64 * BASE_PRICE as f64); quote_asset .mint(wallet.address().into(), quote_size as u64) - .await - .unwrap(); + .await?; } else { let base_size = base_asset.parse_units(BASE_SIZE.abs() as f64) as u64; - base_asset - .mint(wallet.address().into(), base_size) - .await - .unwrap(); + base_asset.mint(wallet.address().into(), base_size).await?; } let price = BASE_PRICE * 10u64.pow(orderbook.price_decimals as u32); let result = orderbook @@ -67,4 +66,6 @@ async fn main() { eprintln!("Failed to open order: {:?}", error); } } + + Ok(()) } diff --git a/scripts/deploy.rs b/scripts/deploy.rs index 33bca57..847b1d3 100644 --- a/scripts/deploy.rs +++ b/scripts/deploy.rs @@ -1,40 +1,42 @@ -use std::str::FromStr; - use dotenv::dotenv; use fuels::{ prelude::{Provider, WalletUnlocked}, types::ContractId, }; -use orderbook::{ +use spark_market_sdk::OrderbookContract; +use src20_sdk::token_utils::{Asset, TokenContract}; +use std::str::FromStr; +use utils::{ constants::{RPC, TOKEN_CONTRACT_ID}, - orderbook_utils::Orderbook, - print_title, + title::print_title, }; -use src20_sdk::token_utils::{Asset, TokenContract}; #[tokio::main] -async fn main() { +async fn main() -> anyhow::Result<()> { print_title("Deploy"); dotenv().ok(); - let provider = Provider::connect(RPC).await.unwrap(); + let provider = Provider::connect(RPC).await?; let secret = std::env::var("ADMIN").unwrap(); let wallet = WalletUnlocked::new_from_private_key(secret.parse().unwrap(), Some(provider.clone())); println!("admin address = {:?}", wallet.address().to_string()); let token_contarct = TokenContract::new( - &ContractId::from_str(TOKEN_CONTRACT_ID).unwrap().into(), + ContractId::from_str(TOKEN_CONTRACT_ID).unwrap(), wallet.clone(), ); let usdc = Asset::new(wallet.clone(), token_contarct.contract_id().into(), "USDC"); - let contract = Orderbook::deploy(&wallet, usdc.asset_id, usdc.decimals, 9).await; + let contract = + OrderbookContract::deploy(&wallet, usdc.asset_id, usdc.decimals as u32, 9).await?; - let block = provider.latest_block_height().await.unwrap(); + let block = provider.latest_block_height().await?; println!("🏁 Start_block: {block}"); println!( "The orderbook contract has been deployed {}\n", - contract.instance.contract_id().hash + contract.id() ); + + Ok(()) } diff --git a/scripts/fill_orderbook.rs b/scripts/fill_orderbook.rs index 45a4807..c433302 100644 --- a/scripts/fill_orderbook.rs +++ b/scripts/fill_orderbook.rs @@ -3,13 +3,13 @@ use fuels::{ prelude::{Provider, WalletUnlocked}, types::ContractId, }; -use orderbook::{ - constants::{ORDERBOOK_CONTRACT_ID, RPC, TOKEN_CONTRACT_ID}, - orderbook_utils::Orderbook, - print_title, -}; +use spark_market_sdk::OrderbookContract; use src20_sdk::token_utils::{Asset, TokenContract}; use std::str::FromStr; +use utils::{ + constants::{ORDERBOOK_CONTRACT_ID, RPC, TOKEN_CONTRACT_ID}, + title::print_title, +}; const MARKET_SYMBOL: &str = "BTC"; const BASE_SIZE: f64 = 0.01; //units @@ -17,16 +17,15 @@ const START_PRICE: f64 = 65500.; //units const STEP: f64 = 100.; #[tokio::main] -async fn main() { +async fn main() -> anyhow::Result<()> { print_title("Fill orderbook Orders"); dotenv().ok(); let provider = Provider::connect(RPC).await.unwrap(); let secret = std::env::var("ADMIN").unwrap(); - let wallet = - WalletUnlocked::new_from_private_key(secret.parse().unwrap(), Some(provider.clone())); + let wallet = WalletUnlocked::new_from_private_key(secret.parse().unwrap(), Some(provider)); let token_contract = TokenContract::new( - &ContractId::from_str(TOKEN_CONTRACT_ID).unwrap().into(), + ContractId::from_str(TOKEN_CONTRACT_ID).unwrap(), wallet.clone(), ); @@ -34,9 +33,13 @@ async fn main() { let base_asset = Asset::new(wallet.clone(), token_contract_id, MARKET_SYMBOL); let quote_asset = Asset::new(wallet.clone(), token_contract_id, "USDC"); - let orderbook = Orderbook::new(&wallet, ORDERBOOK_CONTRACT_ID).await; + let orderbook = OrderbookContract::new( + ContractId::from_str(ORDERBOOK_CONTRACT_ID).unwrap(), + wallet.clone(), + ) + .await?; - let base_size = base_asset.parse_units(BASE_SIZE as f64) as u64; + let base_size = base_asset.parse_units(BASE_SIZE) as u64; for i in 1..41 { let diff = STEP * i as f64; //sell @@ -46,7 +49,7 @@ async fn main() { let mint_tx = base_asset.mint(wallet.address().into(), base_size).await; if mint_tx.is_ok() { let order_tx = orderbook - .open_order(base_asset.asset_id, -1 * base_size as i64, sell_price - 1) + .open_order(base_asset.asset_id, -(base_size as i64), sell_price - 1) .await; if order_tx.is_err() { @@ -58,7 +61,7 @@ async fn main() { //buy let buy_price = ((START_PRICE - diff) * 10f64.powf(orderbook.price_decimals as f64)) as u64; - let quote_size = quote_asset.parse_units(BASE_SIZE as f64 * (START_PRICE - diff) as f64); + let quote_size = quote_asset.parse_units(BASE_SIZE * (START_PRICE - diff)); let mint_tx = quote_asset .mint(wallet.address().into(), quote_size as u64) @@ -75,4 +78,6 @@ async fn main() { } } } + + Ok(()) } diff --git a/scripts/init_system.rs b/scripts/init_system.rs index 880202d..dfa0e51 100644 --- a/scripts/init_system.rs +++ b/scripts/init_system.rs @@ -3,38 +3,38 @@ use fuels::{ prelude::{Provider, WalletUnlocked}, types::ContractId, }; -use orderbook::{ - constants::{RPC, TOKEN_CONTRACT_ID}, - orderbook_utils::Orderbook, - print_title, -}; +use hex::ToHex; +use spark_market_sdk::OrderbookContract; use src20_sdk::token_utils::{Asset, TokenContract}; use std::str::FromStr; -use hex::ToHex; +use utils::{ + constants::{RPC, TOKEN_CONTRACT_ID}, + title::print_title, +}; const MARKET_SYMBOL: &str = "UNI"; const BASE_SIZE: u64 = 100; //units const BASE_PRICE: u64 = 10; //units #[tokio::main] -async fn main() { +async fn main() -> anyhow::Result<()> { print_title("Match Orders"); dotenv().ok(); let provider = Provider::connect(RPC).await.unwrap(); let secret = std::env::var("ADMIN").unwrap(); - let wallet = - WalletUnlocked::new_from_private_key(secret.parse().unwrap(), Some(provider.clone())); + let wallet = WalletUnlocked::new_from_private_key(secret.parse().unwrap(), Some(provider)); println!("admin address = {:?}", wallet.address().to_string()); let token_contract = TokenContract::new( - &ContractId::from_str(TOKEN_CONTRACT_ID).unwrap().into(), + ContractId::from_str(TOKEN_CONTRACT_ID).unwrap(), wallet.clone(), ); - + // deploy let usdc = Asset::new(wallet.clone(), token_contract.contract_id().into(), "USDC"); - let contract = Orderbook::deploy(&wallet, usdc.asset_id, usdc.decimals, 9).await; - - let contract_id_str = contract.instance.contract_id().hash.encode_hex::(); + let contract = + OrderbookContract::deploy(&wallet, usdc.asset_id, usdc.decimals as u32, 9).await?; + + let contract_id_str = contract.id().encode_hex::(); println!( "The orderbook contract has been deployed with contract id: {}\n", contract_id_str @@ -47,76 +47,64 @@ async fn main() { MARKET_SYMBOL, ); - let orderbook = Orderbook::new(&wallet, &contract_id_str).await; + let orderbook = OrderbookContract::new( + ContractId::from_str(&contract_id_str).unwrap(), + wallet.clone(), + ) + .await?; orderbook - ._create_market(asset.asset_id, asset.decimals as u32) - .await - .unwrap(); + .create_market(asset.asset_id, asset.decimals as u32) + .await?; - println!( - "Market created on contract id: {}\n", - contract_id_str - ); - + println!("Market created on contract id: {}\n", contract_id_str); let token_contract_id = token_contract.contract_id().into(); let base_asset = Asset::new(wallet.clone(), token_contract_id, MARKET_SYMBOL); let quote_asset = Asset::new(wallet.clone(), token_contract_id, "USDC"); - let orderbook = Orderbook::new(&wallet, &contract_id_str).await; - let price = BASE_PRICE * 10u64.pow(orderbook.price_decimals as u32); + let orderbook = OrderbookContract::new( + ContractId::from_str(&contract_id_str).unwrap(), + wallet.clone(), + ) + .await?; + let price = BASE_PRICE * 10u64.pow(orderbook.price_decimals); //mint base asset to sell let base_size = base_asset.parse_units(BASE_SIZE as f64) as u64; - base_asset - .mint(wallet.address().into(), base_size) - .await - .unwrap(); + base_asset.mint(wallet.address().into(), base_size).await?; // sell let sell_order_id = orderbook - .open_order(base_asset.asset_id, -1 * base_size as i64, price - 1) - .await - .unwrap() + .open_order(base_asset.asset_id, -(base_size as i64), price - 1) + .await? .value; //mint quote asset to buy let quote_size = quote_asset.parse_units(BASE_SIZE as f64 * BASE_PRICE as f64); quote_asset .mint(wallet.address().into(), quote_size as u64) - .await - .unwrap(); + .await?; //buy let buy_order_id = orderbook .open_order(base_asset.asset_id, base_size as i64, price) - .await - .unwrap() + .await? .value; println!( "buy_order = {:?}", - orderbook - .order_by_id(&buy_order_id) - .await - .unwrap() - .value - .unwrap() + orderbook.order_by_id(&buy_order_id).await?.value.unwrap() ); - + println!( "sell_order = {:?}", - orderbook - .order_by_id(&sell_order_id) - .await - .unwrap() - .value - .unwrap() + orderbook.order_by_id(&sell_order_id).await?.value.unwrap() ); orderbook .match_orders(&sell_order_id, &buy_order_id) - .await - .unwrap(); -} \ No newline at end of file + .await?; + + Ok(()) +} diff --git a/scripts/match_orders.rs b/scripts/match_orders.rs index bf1f7d7..6b3cd0a 100644 --- a/scripts/match_orders.rs +++ b/scripts/match_orders.rs @@ -3,20 +3,20 @@ use fuels::{ prelude::{Provider, WalletUnlocked}, types::ContractId, }; -use orderbook::{ - constants::{ORDERBOOK_CONTRACT_ID, RPC, TOKEN_CONTRACT_ID}, - orderbook_utils::Orderbook, - print_title, -}; +use spark_market_sdk::OrderbookContract; use src20_sdk::token_utils::{Asset, TokenContract}; use std::str::FromStr; +use utils::{ + constants::{ORDERBOOK_CONTRACT_ID, RPC, TOKEN_CONTRACT_ID}, + title::print_title, +}; const MARKET_SYMBOL: &str = "BTC"; const BASE_SIZE: f64 = 0.01; //units const BASE_PRICE: f64 = 65500.; //units #[tokio::main] -async fn main() { +async fn main() -> anyhow::Result<()> { print_title("Match Orders"); dotenv().ok(); let provider = Provider::connect(RPC).await.unwrap(); @@ -25,7 +25,7 @@ async fn main() { WalletUnlocked::new_from_private_key(secret.parse().unwrap(), Some(provider.clone())); let token_contract = TokenContract::new( - &ContractId::from_str(TOKEN_CONTRACT_ID).unwrap().into(), + ContractId::from_str(TOKEN_CONTRACT_ID).unwrap(), wallet.clone(), ); @@ -33,49 +33,47 @@ async fn main() { let base_asset = Asset::new(wallet.clone(), token_contract_id, MARKET_SYMBOL); let quote_asset = Asset::new(wallet.clone(), token_contract_id, "USDC"); - let orderbook = Orderbook::new(&wallet, ORDERBOOK_CONTRACT_ID).await; + let orderbook = OrderbookContract::new( + ContractId::from_str(ORDERBOOK_CONTRACT_ID).unwrap(), + wallet.clone(), + ) + .await?; let price = (BASE_PRICE * 10f64.powf(orderbook.price_decimals as f64)) as u64; //mint base asset to sell - let base_size = base_asset.parse_units(BASE_SIZE as f64) as u64; - base_asset - .mint(wallet.address().into(), base_size) - .await - .unwrap(); + let base_size = base_asset.parse_units(BASE_SIZE) as u64; + base_asset.mint(wallet.address().into(), base_size).await?; // sell let sell_order_id = orderbook - .open_order(base_asset.asset_id, -1 * base_size as i64, price - 1) - .await - .unwrap() + .open_order(base_asset.asset_id, -(base_size as i64), price - 1) + .await? .value; //mint quote asset to buy - let quote_size = quote_asset.parse_units(BASE_SIZE as f64 * BASE_PRICE as f64); + let quote_size = quote_asset.parse_units(BASE_SIZE * BASE_PRICE); quote_asset .mint(wallet.address().into(), quote_size as u64) - .await - .unwrap(); + .await?; //buy let buy_order_id = orderbook .open_order(base_asset.asset_id, base_size as i64, price) - .await - .unwrap() + .await? .value; println!( "buy_order = {:?}\n", - orderbook.order_by_id(&buy_order_id).await.unwrap().value.unwrap() + orderbook.order_by_id(&buy_order_id).await?.value.unwrap() ); println!( "sell_order = {:?}", - orderbook.order_by_id(&sell_order_id).await.unwrap().value.unwrap() + orderbook.order_by_id(&sell_order_id).await?.value.unwrap() ); - orderbook .match_orders(&sell_order_id, &buy_order_id) - .await - .unwrap(); + .await?; + + Ok(()) } diff --git a/spark-market-sdk/Cargo.toml b/spark-market-sdk/Cargo.toml new file mode 100644 index 0000000..439f3d9 --- /dev/null +++ b/spark-market-sdk/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "spark-market-sdk" +authors = { workspace = true } +version = { workspace = true } +edition = { workspace = true } +license = { workspace = true } +rust-version = { workspace = true } + +[dependencies] +anyhow = { workspace = true } +fuels = { workspace = true } +tokio = { workspace = true } +rand = { workspace = true } + +[lib] +doctest = false +test = false diff --git a/spark-market-sdk/src/lib.rs b/spark-market-sdk/src/lib.rs new file mode 100644 index 0000000..819fdd6 --- /dev/null +++ b/spark-market-sdk/src/lib.rs @@ -0,0 +1,218 @@ +use fuels::{ + prelude::{ + abigen, AssetId, CallParameters, Contract, ContractId, LoadConfiguration, + StorageConfiguration, TxPolicies, WalletUnlocked, + }, + programs::{call_response::FuelCallResponse, call_utils::TxDependencyExtension}, + tx::Bytes32, + types::{bech32::Bech32Address, Bits256}, +}; +use rand::Rng; + +abigen!(Contract( + name = "Orderbook", + abi = "./contract/out/debug/orderbook-abi.json" +)); + +const ORDERBOOK_CONTRACT_BINARY_PATH: &str = "../contract/out/debug/orderbook.bin"; +const ORDERBOOK_CONTRACT_STORAGE_PATH: &str = "../contract/out/debug/orderbook-storage_slots.json"; + +pub struct OrderbookContract { + instance: Orderbook, + pub quote_token: AssetId, + pub quote_token_decimals: u32, + pub price_decimals: u32, +} + +impl OrderbookContract { + pub async fn deploy( + wallet: &WalletUnlocked, + quote_token: AssetId, + quote_token_decimals: u32, + price_decimals: u32, + ) -> anyhow::Result { + let mut rng = rand::thread_rng(); + let salt = rng.gen::<[u8; 32]>(); + + let storage_configuration = StorageConfiguration::default() + .add_slot_overrides_from_file(ORDERBOOK_CONTRACT_STORAGE_PATH); + + let configurables = OrderbookConfigurables::default() + .with_QUOTE_TOKEN(quote_token) + .with_QUOTE_TOKEN_DECIMALS(quote_token_decimals) + .with_PRICE_DECIMALS(price_decimals); + + let contract_configuration = LoadConfiguration::default() + .with_storage_configuration(storage_configuration?) + .with_configurables(configurables); + + let id = Contract::load_from(ORDERBOOK_CONTRACT_BINARY_PATH, contract_configuration)? + .with_salt(salt) + .deploy(wallet, TxPolicies::default()) + .await?; + + let instance = Orderbook::new(id, wallet.clone()); + + Ok(Self { + instance, + quote_token, + quote_token_decimals, + price_decimals, + }) + } + + pub async fn new(contract_id: ContractId, wallet: WalletUnlocked) -> anyhow::Result { + let instance = Orderbook::new(contract_id, wallet); + let (quote_token, quote_token_decimals, price_decimals) = instance + .methods() + .get_configurables() + .simulate() + .await? + .value; + + Ok(Self { + instance, + quote_token, + quote_token_decimals, + price_decimals, + }) + } + + pub fn id(&self) -> Bytes32 { + self.instance.contract_id().hash + } + + pub fn with_account(&self, account: &WalletUnlocked) -> anyhow::Result { + Ok(Self { + instance: self.instance.with_account(account.clone())?, + quote_token: self.quote_token, + quote_token_decimals: self.quote_token_decimals, + price_decimals: self.price_decimals, + }) + } + + pub async fn create_market( + &self, + asset_id: AssetId, + decimal: u32, + ) -> anyhow::Result> { + Ok(self + .instance + .methods() + .create_market(asset_id, decimal) + .call() + .await?) + } + + pub async fn open_order( + &self, + base_token: AssetId, + base_size: i64, + base_price: u64, + ) -> anyhow::Result> { + let call_params: CallParameters = if base_size.is_negative() { + CallParameters::default() + .with_asset_id(base_token) + .with_amount(base_size.unsigned_abs()) + } else { + let market = self.get_market_by_id(base_token).await?.value; + let quote_size = base_size.unsigned_abs() as u128 * base_price as u128 + / 10u128 + .pow(self.price_decimals + market.asset_decimals - self.quote_token_decimals); + CallParameters::default() + .with_asset_id(self.quote_token) + .with_amount(quote_size as u64) + }; + + Ok(self + .instance + .methods() + .open_order( + base_token, + I64::new(base_size.unsigned_abs(), base_size < 0), + base_price, + ) + .append_variable_outputs(2) + .call_params(call_params)? + .with_tx_policies(TxPolicies::default().with_gas_price(1)) + .call() + .await?) + } + + pub async fn cancel_order(&self, order_id: &Bits256) -> anyhow::Result> { + Ok(self + .instance + .methods() + .cancel_order(*order_id) + .append_variable_outputs(1) + .call() + .await?) + } + + pub async fn match_orders( + &self, + sell_order_id: &Bits256, + buy_order_id: &Bits256, + ) -> anyhow::Result> { + Ok(self + .instance + .methods() + .match_orders(*sell_order_id, *buy_order_id) + .append_variable_outputs(2) + // .with_tx_policies(TxPolicies::default()) + .call() + .await?) + } + + pub async fn get_market_by_id( + &self, + asset_id: AssetId, + ) -> anyhow::Result> { + Ok(self + .instance + .methods() + .get_market_by_id(asset_id) + .simulate() + .await?) + } + + pub async fn market_exists(&self, asset_id: AssetId) -> anyhow::Result> { + Ok(self + .instance + .methods() + .market_exists(asset_id) + .simulate() + .await?) + } + + pub async fn order_by_id( + &self, + id: &Bits256, + ) -> anyhow::Result>> { + Ok(self + .instance + .methods() + .order_by_id(*id) + // .with_tx_policies(TxPolicies::default()) + .simulate() + .await?) + } + + pub async fn orders_by_trader( + &self, + trader: &Bech32Address, + ) -> anyhow::Result>> { + Ok(self + .instance + .methods() + .orders_by_trader(trader) + .simulate() + .await?) + } +} + +impl I64 { + pub fn as_i64(self) -> i64 { + self.value as i64 * if self.negative { -1 } else { 1 } + } +} diff --git a/src/orderbook_utils.rs b/src/orderbook_utils.rs deleted file mode 100644 index 07b6f77..0000000 --- a/src/orderbook_utils.rs +++ /dev/null @@ -1,216 +0,0 @@ -use std::str::FromStr; - -use fuels::{ - accounts::wallet::WalletUnlocked, - macros::abigen, - programs::{ - call_response::FuelCallResponse, - call_utils::TxDependencyExtension, - contract::{CallParameters, Contract, LoadConfiguration}, - }, - types::{bech32::Bech32Address, transaction::TxPolicies, AssetId, Bits256, ContractId}, -}; -use rand::Rng; - -use self::abigen_bindings::orderbook_contract_mod; - -abigen!(Contract( - name = "OrderbookContract", - abi = "contract/out/debug/orderbook-abi.json" -)); - -pub struct Orderbook { - pub instance: OrderbookContract, - pub quote_token: AssetId, - pub quote_token_decimals: u64, - pub price_decimals: u64, -} - -impl Orderbook { - pub async fn _create_market( - &self, - asset_id: AssetId, - decimal: u32, - ) -> Result, fuels::types::errors::Error> { - self.instance - .methods() - .create_market(asset_id, decimal) - .call() - .await - } - - pub async fn get_market_by_id( - &self, - asset_id: AssetId, - ) -> Result, fuels::types::errors::Error> { - self.instance - .methods() - .get_market_by_id(asset_id) - .simulate() - .await - } - - pub async fn market_exists( - &self, - asset_id: AssetId, - ) -> Result, fuels::types::errors::Error> { - self.instance - .methods() - .market_exists(asset_id) - .simulate() - .await - } - - pub async fn order_by_id( - &self, - id: &Bits256, - ) -> Result>, fuels::types::errors::Error> { - self.instance - .methods() - .order_by_id(*id) - .with_tx_policies(TxPolicies::default()) - .simulate() - .await - } - - pub async fn orders_by_trader( - &self, - trader: &Bech32Address, - ) -> Result>, fuels::types::errors::Error> { - self.instance - .methods() - .orders_by_trader(trader) - .simulate() - .await - } - - pub async fn open_order( - &self, - base_token: AssetId, - base_size: i64, - base_price: u64, - ) -> Result, fuels::types::errors::Error> { - let call_params: CallParameters = if base_size.is_negative() { - CallParameters::default() - .with_asset_id(base_token) - .with_amount(base_size.abs() as u64) - } else { - let market = self.get_market_by_id(base_token).await.unwrap().value; - let quote_size = base_size.abs() as u128 * base_price as u128 - / 10u128.pow( - self.price_decimals as u32 + market.asset_decimals - - self.quote_token_decimals as u32, - ); - CallParameters::default() - .with_asset_id(self.quote_token) - .with_amount(quote_size as u64) - }; - - self.instance - .methods() - .open_order( - base_token, - I64::new(base_size.unsigned_abs(), base_size < 0), - base_price, - ) - .append_variable_outputs(2) - .call_params(call_params) - .unwrap() - .with_tx_policies(TxPolicies::default().with_gas_price(1)) - .call() - .await - } - - pub async fn cancel_order( - &self, - order_id: &Bits256, - ) -> Result, fuels::types::errors::Error> { - self.instance - .methods() - .cancel_order(*order_id) - .append_variable_outputs(1) - .call() - .await - } - - pub async fn match_orders( - &self, - sell_order_id: &Bits256, - buy_order_id: &Bits256, - ) -> Result, fuels::types::errors::Error> { - self.instance - .methods() - .match_orders(*sell_order_id, *buy_order_id) - .append_variable_outputs(2) - .with_tx_policies(TxPolicies::default()) - .call() - .await - } - - pub fn with_account(&self, account: &WalletUnlocked) -> Self { - Self { - instance: self.instance.with_account(account.clone()).unwrap(), - quote_token: self.quote_token, - quote_token_decimals: self.quote_token_decimals, - price_decimals: self.price_decimals, - } - } - - pub async fn new(wallet: &WalletUnlocked, contract_id: &str) -> Self { - let instance = OrderbookContract::new( - &ContractId::from_str(contract_id).unwrap().into(), - wallet.clone(), - ); - let (quote_token, quote_token_decimals, price_decimals) = instance - .methods() - .get_configurables() - .simulate() - .await - .unwrap() - .value; - Orderbook { - instance, - quote_token, - quote_token_decimals: quote_token_decimals as u64, - price_decimals: price_decimals as u64, - } - } - - pub async fn deploy( - wallet: &WalletUnlocked, - quote_token: AssetId, - quote_token_decimals: u64, - price_decimals: u64, - ) -> Self { - let mut rng = rand::thread_rng(); - let salt = rng.gen::<[u8; 32]>(); - - let configurables = OrderbookContractConfigurables::default() - .with_QUOTE_TOKEN(quote_token) - .with_QUOTE_TOKEN_DECIMALS(quote_token_decimals.try_into().unwrap()) - .with_PRICE_DECIMALS(price_decimals.try_into().unwrap()); - let config = LoadConfiguration::default().with_configurables(configurables); - - let id = Contract::load_from("contract/out/debug/orderbook.bin", config) - .unwrap() - .with_salt(salt) - .deploy(wallet, TxPolicies::default().with_gas_price(1)) - .await - .unwrap(); - - let instance = OrderbookContract::new(id, wallet.clone()); - - Orderbook { - instance, - quote_token, - quote_token_decimals, - price_decimals, - } - } -} - -impl I64 { - pub fn as_i64(self) -> i64 { - self.value as i64 * if self.negative { -1 } else { 1 } - } -} diff --git a/tests/Cargo.toml b/tests/Cargo.toml new file mode 100644 index 0000000..85a8a59 --- /dev/null +++ b/tests/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "tests" +authors = { workspace = true } +version = { workspace = true } +edition = { workspace = true } +license = { workspace = true } +rust-version = { workspace = true } + +[dependencies] +anyhow = { workspace = true } +fuels = { workspace = true } +tokio = { workspace = true } +spark-market-sdk = { path = "../spark-market-sdk" } +src20_sdk = { workspace = true } + +[[test]] +name = "main_test" +path = "main_test.rs" + +[[test]] +name = "match_orders" +path = "match_orders.rs" \ No newline at end of file diff --git a/tests/harness.rs b/tests/harness.rs deleted file mode 100644 index 2e49ea1..0000000 --- a/tests/harness.rs +++ /dev/null @@ -1,2 +0,0 @@ -mod main_test; -mod match_orders; diff --git a/tests/main_test.rs b/tests/main_test.rs index 21bb784..7d627ea 100644 --- a/tests/main_test.rs +++ b/tests/main_test.rs @@ -1,86 +1,83 @@ use fuels::prelude::*; -use orderbook::orderbook_utils::Orderbook; +use spark_market_sdk::OrderbookContract; use src20_sdk::token_utils::{deploy_token_contract, Asset}; -const PRICE_DECIMALS: u64 = 9; +const PRICE_DECIMALS: u32 = 9; #[tokio::test] -async fn open_base_token_order_cancel_test() { +async fn open_base_token_order_cancel_test() -> anyhow::Result<()> { //--------------- WALLETS --------------- let wallets_config = WalletsConfig::new(Some(5), Some(1), Some(1_000_000_000)); - let wallets = launch_custom_provider_and_get_wallets(wallets_config, None, None) - .await - .unwrap(); + let wallets = launch_custom_provider_and_get_wallets(wallets_config, None, None).await?; let admin = &wallets[0]; let user = &wallets[1]; - let token_contract = deploy_token_contract(&admin).await; + let token_contract = deploy_token_contract(admin).await; let btc = Asset::new(admin.clone(), token_contract.contract_id().into(), "BTC"); - let token_contract = deploy_token_contract(&admin).await; + let token_contract = deploy_token_contract(admin).await; let usdc = Asset::new(admin.clone(), token_contract.contract_id().into(), "USDC"); - let orderbook = Orderbook::deploy(&admin, usdc.asset_id, usdc.decimals, PRICE_DECIMALS).await; + let orderbook = + OrderbookContract::deploy(admin, usdc.asset_id, usdc.decimals as u32, PRICE_DECIMALS) + .await?; // Create Market orderbook - ._create_market(btc.asset_id, btc.decimals as u32) - .await - .unwrap(); + .create_market(btc.asset_id, btc.decimals as u32) + .await?; - let response = orderbook.market_exists(btc.asset_id).await.unwrap(); - assert_eq!(true, response.value); + let response = orderbook.market_exists(btc.asset_id).await?; + assert!(response.value); - let response = orderbook.orders_by_trader(admin.address()).await.unwrap(); + let response = orderbook.orders_by_trader(admin.address()).await?; assert_eq!(0, response.value.len()); // SELL 5btc, price 50000 let price = 50000; let btcv: f64 = -5.0; - let base_price = price * 10u64.pow(PRICE_DECIMALS as u32); + let base_price = price * 10u64.pow(PRICE_DECIMALS); let base_size_sell1 = btc.parse_units(btcv) as i64; //? Ρ‚ΡƒΡ‚ ΠΌΡ‹ ΠΈΠΌΠ΅Π΅ΠΌ i64 Π° Π½Π΅ f64 ΠΏΠΎΡ‚ΠΎΠΌΡƒ Ρ‡Ρ‚ΠΎ ΠΌΡ‹ ΡƒΠΆΠ΅ Π΄ΠΎΠΌΠ½Π»ΠΆΠΈΠ»ΠΈ Π½Π° scale - let amount_btc = base_size_sell1.abs() as u64; + let amount_btc = base_size_sell1.unsigned_abs() as u64; // Mint BTC - btc.mint(admin.address().into(), amount_btc).await.unwrap(); - let balance = admin.get_asset_balance(&btc.asset_id).await.unwrap(); + btc.mint(admin.address().into(), amount_btc).await?; + let balance = admin.get_asset_balance(&btc.asset_id).await?; assert_eq!(balance, amount_btc); // Open order orderbook .open_order(btc.asset_id, base_size_sell1, base_price) - .await - .unwrap(); + .await?; - assert_eq!(admin.get_asset_balance(&btc.asset_id).await.unwrap(), 0); + assert_eq!(admin.get_asset_balance(&btc.asset_id).await?, 0); - let response = orderbook.orders_by_trader(admin.address()).await.unwrap(); + let response = orderbook.orders_by_trader(admin.address()).await?; assert_eq!(1, response.value.len()); - let order_id = response.value.get(0).unwrap(); - let response = orderbook.order_by_id(order_id).await.unwrap(); + let order_id = response.value.first().unwrap(); + let response = orderbook.order_by_id(order_id).await?; let order = response.value.unwrap(); assert_eq!(base_price, order.base_price); assert_eq!(base_size_sell1, order.base_size.as_i64()); // Add btc value to order - btc.mint(admin.address().into(), amount_btc).await.unwrap(); + btc.mint(admin.address().into(), amount_btc).await?; orderbook .open_order(btc.asset_id, base_size_sell1, base_price) - .await - .unwrap(); + .await?; - assert_eq!(admin.get_asset_balance(&btc.asset_id).await.unwrap(), 0); + assert_eq!(admin.get_asset_balance(&btc.asset_id).await?, 0); - let response = orderbook.orders_by_trader(admin.address()).await.unwrap(); + let response = orderbook.orders_by_trader(admin.address()).await?; assert_eq!(1, response.value.len()); - let order_id = response.value.get(0).unwrap(); - let response = orderbook.order_by_id(order_id).await.unwrap(); + let order_id = response.value.first().unwrap(); + let response = orderbook.order_by_id(order_id).await?; let base_size_sell2 = base_size_sell1 * 2; @@ -97,63 +94,57 @@ async fn open_base_token_order_cancel_test() { let amount_usdc = quote_size_buy1 as u64; // Mint USDC - usdc.mint(admin.address().into(), amount_usdc) - .await - .unwrap(); + usdc.mint(admin.address().into(), amount_usdc).await?; - let balance = admin.get_asset_balance(&usdc.asset_id).await.unwrap(); + let balance = admin.get_asset_balance(&usdc.asset_id).await?; assert_eq!(balance, amount_usdc); // Add usdc value to order orderbook .open_order(btc.asset_id, base_size_buy1, base_price) - .await - .unwrap(); + .await?; - let balance = admin.get_asset_balance(&usdc.asset_id).await.unwrap(); + let balance = admin.get_asset_balance(&usdc.asset_id).await?; assert_eq!(balance, amount_usdc); - let balance = admin.get_asset_balance(&btc.asset_id).await.unwrap(); + let balance = admin.get_asset_balance(&btc.asset_id).await?; assert_eq!(balance, amount_btc); - let response = orderbook.orders_by_trader(admin.address()).await.unwrap(); + let response = orderbook.orders_by_trader(admin.address()).await?; assert_eq!(1, response.value.len()); - let order_id = response.value.get(0).unwrap(); - let response = orderbook.order_by_id(order_id).await.unwrap(); + let order_id = response.value.first().unwrap(); + let response = orderbook.order_by_id(order_id).await?; let order = response.value.unwrap(); assert_eq!(base_price, order.base_price); assert_eq!(base_size_sell1, order.base_size.as_i64()); // Mint USDC - usdc.mint(admin.address().into(), amount_usdc) - .await - .unwrap(); + usdc.mint(admin.address().into(), amount_usdc).await?; - let balance = admin.get_asset_balance(&usdc.asset_id).await.unwrap(); + let balance = admin.get_asset_balance(&usdc.asset_id).await?; assert_eq!(balance, amount_usdc * 2); // Add more usdc value to order let base_size_buy2 = base_size_buy1 * 2; orderbook - .open_order(btc.asset_id, base_size_buy2.clone(), base_price) - .await - .unwrap(); + .open_order(btc.asset_id, base_size_buy2, base_price) + .await?; - let balance = admin.get_asset_balance(&usdc.asset_id).await.unwrap(); + let balance = admin.get_asset_balance(&usdc.asset_id).await?; assert_eq!(balance, amount_usdc); - let balance = admin.get_asset_balance(&btc.asset_id).await.unwrap(); + let balance = admin.get_asset_balance(&btc.asset_id).await?; assert_eq!(balance, amount_btc * 2); - let response = orderbook.orders_by_trader(admin.address()).await.unwrap(); + let response = orderbook.orders_by_trader(admin.address()).await?; assert_eq!(1, response.value.len()); - let order_id = response.value.get(0).unwrap(); - let response = orderbook.order_by_id(order_id).await.unwrap(); + let order_id = response.value.first().unwrap(); + let response = orderbook.order_by_id(order_id).await?; let order = response.value.unwrap(); assert_eq!(base_price, order.base_price); @@ -161,53 +152,53 @@ async fn open_base_token_order_cancel_test() { // Cancel by not order owner orderbook - .with_account(user) + .with_account(user)? .cancel_order(order_id) .await .expect_err("Order cancelled by another user"); // Cancel order - orderbook.cancel_order(order_id).await.unwrap(); + orderbook.cancel_order(order_id).await?; - let response = orderbook.orders_by_trader(admin.address()).await.unwrap(); + let response = orderbook.orders_by_trader(admin.address()).await?; assert_eq!(0, response.value.len()); - let response = orderbook.order_by_id(order_id).await.unwrap(); + let response = orderbook.order_by_id(order_id).await?; assert!(response.value.is_none()); - let balance = admin.get_asset_balance(&btc.asset_id).await.unwrap(); + let balance = admin.get_asset_balance(&btc.asset_id).await?; assert_eq!(balance, 2 * amount_btc); - let balance = admin.get_asset_balance(&usdc.asset_id).await.unwrap(); + let balance = admin.get_asset_balance(&usdc.asset_id).await?; assert_eq!(balance, 2 * amount_usdc); + Ok(()) } #[tokio::test] -async fn open_quote_token_order_cancel_by_reverse_order_test() { +async fn open_quote_token_order_cancel_by_reverse_order_test() -> anyhow::Result<()> { //--------------- WALLETS --------------- let wallets_config = WalletsConfig::new(Some(5), Some(1), Some(1_000_000_000)); - let wallets = launch_custom_provider_and_get_wallets(wallets_config, None, None) - .await - .unwrap(); + let wallets = launch_custom_provider_and_get_wallets(wallets_config, None, None).await?; let admin = &wallets[0]; - let token_contract = deploy_token_contract(&admin).await; + let token_contract = deploy_token_contract(admin).await; let btc = Asset::new(admin.clone(), token_contract.contract_id().into(), "BTC"); - let token_contract = deploy_token_contract(&admin).await; + let token_contract = deploy_token_contract(admin).await; let usdc = Asset::new(admin.clone(), token_contract.contract_id().into(), "USDC"); - let orderbook = Orderbook::deploy(&admin, usdc.asset_id, usdc.decimals, PRICE_DECIMALS).await; + let orderbook = + OrderbookContract::deploy(admin, usdc.asset_id, usdc.decimals as u32, PRICE_DECIMALS) + .await?; // Create Market orderbook - ._create_market(btc.asset_id, btc.decimals as u32) - .await - .unwrap(); + .create_market(btc.asset_id, btc.decimals as u32) + .await?; - let response = orderbook.market_exists(btc.asset_id).await.unwrap(); - assert_eq!(true, response.value); + let response = orderbook.market_exists(btc.asset_id).await?; + assert!(response.value); - let response = orderbook.orders_by_trader(admin.address()).await.unwrap(); + let response = orderbook.orders_by_trader(admin.address()).await?; assert_eq!(0, response.value.len()); @@ -216,41 +207,32 @@ async fn open_quote_token_order_cancel_by_reverse_order_test() { let usdv = 250000.0; let btcv = 5.0; let price = 50000; - let base_price = price * 10u64.pow(PRICE_DECIMALS as u32); + let base_price = price * 10u64.pow(PRICE_DECIMALS); let base_size_buy1 = btc.parse_units(btcv) as i64; - let amount_btc = base_size_buy1.abs() as u64; + let amount_btc = base_size_buy1.unsigned_abs() as u64; let base_size_sell1 = -base_size_buy1; let amount_usdc = usdc.parse_units(usdv) as u64; - usdc.mint(admin.address().into(), amount_usdc) - .await - .unwrap(); - btc.mint(admin.address().into(), amount_btc).await.unwrap(); - - assert_eq!( - admin.get_asset_balance(&usdc.asset_id).await.unwrap(), - amount_usdc - ); - assert_eq!( - admin.get_asset_balance(&btc.asset_id).await.unwrap(), - amount_btc - ); + usdc.mint(admin.address().into(), amount_usdc).await?; + btc.mint(admin.address().into(), amount_btc).await?; + + assert_eq!(admin.get_asset_balance(&usdc.asset_id).await?, amount_usdc); + assert_eq!(admin.get_asset_balance(&btc.asset_id).await?, amount_btc); // Open order orderbook - .open_order(btc.asset_id, base_size_buy1.clone(), base_price) - .await - .unwrap(); + .open_order(btc.asset_id, base_size_buy1, base_price) + .await?; - assert_eq!(admin.get_asset_balance(&usdc.asset_id).await.unwrap(), 0); + assert_eq!(admin.get_asset_balance(&usdc.asset_id).await?, 0); - let response = orderbook.orders_by_trader(admin.address()).await.unwrap(); + let response = orderbook.orders_by_trader(admin.address()).await?; assert_eq!(1, response.value.len()); - let order_id = response.value.get(0).unwrap(); - let response = orderbook.order_by_id(order_id).await.unwrap(); + let order_id = response.value.first().unwrap(); + let response = orderbook.order_by_id(order_id).await?; let order = response.value.unwrap(); assert_eq!(base_price, order.base_price); @@ -258,93 +240,78 @@ async fn open_quote_token_order_cancel_by_reverse_order_test() { assert!(!order.base_size.negative); orderbook - .open_order(btc.asset_id, base_size_sell1.clone(), base_price) - .await - .unwrap(); + .open_order(btc.asset_id, base_size_sell1, base_price) + .await?; - let response = orderbook.orders_by_trader(admin.address()).await.unwrap(); + let response = orderbook.orders_by_trader(admin.address()).await?; assert_eq!(0, response.value.len()); - let response = orderbook.order_by_id(order_id).await.unwrap(); + let response = orderbook.order_by_id(order_id).await?; assert!(response.value.is_none()); - assert_eq!( - admin.get_asset_balance(&usdc.asset_id).await.unwrap(), - amount_usdc - ); - assert_eq!( - admin.get_asset_balance(&btc.asset_id).await.unwrap(), - amount_btc - ); + assert_eq!(admin.get_asset_balance(&usdc.asset_id).await?, amount_usdc); + assert_eq!(admin.get_asset_balance(&btc.asset_id).await?, amount_btc); + + Ok(()) } #[tokio::test] -async fn match_orders_test() { +async fn match_orders_test() -> anyhow::Result<()> { //--------------- WALLETS --------------- let wallets_config = WalletsConfig::new(Some(5), Some(1), Some(1_000_000_000)); - let wallets = launch_custom_provider_and_get_wallets(wallets_config, None, None) - .await - .unwrap(); + let wallets = launch_custom_provider_and_get_wallets(wallets_config, None, None).await?; let admin = &wallets[0]; let user1 = &wallets[1]; let user2 = &wallets[2]; - let token_contract = deploy_token_contract(&admin).await; + let token_contract = deploy_token_contract(admin).await; let btc = Asset::new(admin.clone(), token_contract.contract_id().into(), "BTC"); - let token_contract = deploy_token_contract(&admin).await; + let token_contract = deploy_token_contract(admin).await; let usdc = Asset::new(admin.clone(), token_contract.contract_id().into(), "USDC"); - let orderbook = Orderbook::deploy(&admin, usdc.asset_id, usdc.decimals, PRICE_DECIMALS).await; + let orderbook = + OrderbookContract::deploy(admin, usdc.asset_id, usdc.decimals as u32, PRICE_DECIMALS) + .await?; // Create Market orderbook - ._create_market(btc.asset_id, btc.decimals as u32) - .await - .unwrap(); + .create_market(btc.asset_id, btc.decimals as u32) + .await?; // Mint BTC & USDC let usdv = 250000.0; let btcv = 5.0; let price = 50000; - let base_price = price * 10u64.pow(PRICE_DECIMALS as u32); + let base_price = price * 10u64.pow(PRICE_DECIMALS); let base_size_buy1 = btc.parse_units(btcv) as i64; - let amount_btc = base_size_buy1.abs() as u64; + let amount_btc = base_size_buy1.unsigned_abs() as u64; let base_size_sell1 = -base_size_buy1; let amount_usdc = usdc.parse_units(usdv) as u64; - usdc.mint(user1.address().into(), amount_usdc) - .await - .unwrap(); - btc.mint(user2.address().into(), amount_btc).await.unwrap(); - - assert_eq!( - user1.get_asset_balance(&usdc.asset_id).await.unwrap(), - amount_usdc - ); - assert_eq!( - user2.get_asset_balance(&btc.asset_id).await.unwrap(), - amount_btc - ); + usdc.mint(user1.address().into(), amount_usdc).await?; + btc.mint(user2.address().into(), amount_btc).await?; + + assert_eq!(user1.get_asset_balance(&usdc.asset_id).await?, amount_usdc); + assert_eq!(user2.get_asset_balance(&btc.asset_id).await?, amount_btc); // Open USDC order orderbook - .with_account(user1) - .open_order(btc.asset_id, base_size_buy1.clone(), base_price) - .await - .unwrap(); + .with_account(user1)? + .open_order(btc.asset_id, base_size_buy1, base_price) + .await?; - assert_eq!(user1.get_asset_balance(&usdc.asset_id).await.unwrap(), 0); + assert_eq!(user1.get_asset_balance(&usdc.asset_id).await?, 0); - let response = orderbook.orders_by_trader(user1.address()).await.unwrap(); + let response = orderbook.orders_by_trader(user1.address()).await?; assert_eq!(1, response.value.len()); - let order_id_1 = response.value.get(0).unwrap(); - let response = orderbook.order_by_id(order_id_1).await.unwrap(); + let order_id_1 = response.value.first().unwrap(); + let response = orderbook.order_by_id(order_id_1).await?; let order = response.value.unwrap(); assert_eq!(base_price, order.base_price); @@ -354,19 +321,18 @@ async fn match_orders_test() { // Open BTC order orderbook - .with_account(user2) - .open_order(btc.asset_id, base_size_sell1.clone(), base_price) - .await - .unwrap(); + .with_account(user2)? + .open_order(btc.asset_id, base_size_sell1, base_price) + .await?; - assert_eq!(user2.get_asset_balance(&btc.asset_id).await.unwrap(), 0); + assert_eq!(user2.get_asset_balance(&btc.asset_id).await?, 0); - let response = orderbook.orders_by_trader(user2.address()).await.unwrap(); + let response = orderbook.orders_by_trader(user2.address()).await?; assert_eq!(1, response.value.len()); - let order_id_2 = response.value.get(0).unwrap(); - let response = orderbook.order_by_id(order_id_2).await.unwrap(); + let order_id_2 = response.value.first().unwrap(); + let response = orderbook.order_by_id(order_id_2).await?; let order = response.value.unwrap(); assert_eq!(base_price, order.base_price); @@ -374,25 +340,18 @@ async fn match_orders_test() { assert!(order.base_size.negative); // Match orders - orderbook - .match_orders(order_id_2, order_id_1) - .await - .unwrap(); + orderbook.match_orders(order_id_2, order_id_1).await?; - let response = orderbook.orders_by_trader(user1.address()).await.unwrap(); + let response = orderbook.orders_by_trader(user1.address()).await?; assert_eq!(0, response.value.len()); - let response = orderbook.orders_by_trader(user2.address()).await.unwrap(); + let response = orderbook.orders_by_trader(user2.address()).await?; assert_eq!(0, response.value.len()); - assert_eq!( - user2.get_asset_balance(&usdc.asset_id).await.unwrap(), - amount_usdc - ); - assert_eq!( - user1.get_asset_balance(&btc.asset_id).await.unwrap(), - amount_btc - ); + assert_eq!(user2.get_asset_balance(&usdc.asset_id).await?, amount_usdc); + assert_eq!(user1.get_asset_balance(&btc.asset_id).await?, amount_btc); + + Ok(()) } diff --git a/tests/match_orders.rs b/tests/match_orders.rs index 2fc7f4a..b65ca0f 100644 --- a/tests/match_orders.rs +++ b/tests/match_orders.rs @@ -1,9 +1,8 @@ use fuels::types::Bits256; use fuels::{accounts::wallet::Wallet, prelude::*}; -use orderbook::orderbook_utils::Orderbook; +use spark_market_sdk::OrderbookContract; use src20_sdk::token_utils::{deploy_token_contract, Asset}; -use std::result::Result; -const PRICE_DECIMALS: u64 = 9; +const PRICE_DECIMALS: u32 = 9; const TOLERANCE: f64 = 0.0005; fn tolerance_eq(expected: u64, actual: u64) -> bool { @@ -35,7 +34,13 @@ fn tolerance_eq(expected: u64, actual: u64) -> bool { } } -async fn init() -> (WalletUnlocked, WalletUnlocked, Asset, Asset, Orderbook) { +async fn init() -> anyhow::Result<( + WalletUnlocked, + WalletUnlocked, + Asset, + Asset, + OrderbookContract, +)> { //--------------- WALLETS --------------- let wallets_config = WalletsConfig::new(Some(5), Some(1), Some(1_000_000_000)); let wallets = launch_custom_provider_and_get_wallets(wallets_config, None, None) @@ -59,15 +64,17 @@ async fn init() -> (WalletUnlocked, WalletUnlocked, Asset, Asset, Orderbook) { "USDC", ); - let orderbook = Orderbook::deploy(&admin, usdc.asset_id, usdc.decimals, PRICE_DECIMALS).await; + let orderbook = + OrderbookContract::deploy(&admin, usdc.asset_id, usdc.decimals as u32, PRICE_DECIMALS) + .await?; // Create Market orderbook - ._create_market(btc.asset_id, btc.decimals as u32) + .create_market(btc.asset_id, btc.decimals as u32) .await .expect("Failed to create market"); - (alice, bob, btc, usdc, orderbook) + Ok((alice, bob, btc, usdc, orderbook)) } async fn mint_tokens( @@ -77,17 +84,16 @@ async fn mint_tokens( bob: &Wallet, usdc_mint_amount: u64, btc_mint_amount: u64, -) { - usdc.mint(alice.address().into(), usdc_mint_amount) - .await - .unwrap(); - btc.mint(bob.address().into(), btc_mint_amount) - .await - .unwrap(); +) -> anyhow::Result<()> { + usdc.mint(alice.address().into(), usdc_mint_amount).await?; + btc.mint(bob.address().into(), btc_mint_amount).await?; + + Ok(()) } +#[allow(clippy::too_many_arguments)] async fn open_orders_match( - orderbook: &Orderbook, + orderbook: &OrderbookContract, alice: &WalletUnlocked, bob: &WalletUnlocked, btc: &Asset, @@ -95,27 +101,25 @@ async fn open_orders_match( buy_price: f64, sell_size: f64, sell_price: f64, -) -> Result<(Bits256, Bits256), fuels::types::errors::Error> { +) -> anyhow::Result<(Bits256, Bits256)> { let alice_order_id = orderbook - .with_account(&alice) + .with_account(alice)? .open_order( btc.asset_id, (buy_size * 1e8) as i64, (buy_price * 1e9) as u64, ) - .await - .unwrap() + .await? .value; let bob_order_id = orderbook - .with_account(&bob) + .with_account(bob)? .open_order( btc.asset_id, (sell_size * 1e8) as i64, (sell_price * 1e9) as u64, ) - .await - .unwrap() + .await? .value; let res = orderbook.match_orders(&bob_order_id, &alice_order_id).await; @@ -129,52 +133,47 @@ async fn open_orders_match( const BASE_SIZE: u64 = 1; //units const BASE_PRICE: u64 = 70000; //units #[tokio::test] -async fn match0() { - let (alice, _bob, base_asset, quote_asset, orderbook) = init().await; +async fn match0() -> anyhow::Result<()> { + let (alice, _bob, base_asset, quote_asset, orderbook) = init().await?; - let price = BASE_PRICE * 10u64.pow(orderbook.price_decimals as u32); + let price = BASE_PRICE * 10u64.pow(orderbook.price_decimals); //mint base asset to sell let base_size = base_asset.parse_units(BASE_SIZE as f64) as u64; - base_asset - .mint(alice.address().into(), base_size) - .await - .unwrap(); + base_asset.mint(alice.address().into(), base_size).await?; // sell let sell_order_id = orderbook - .with_account(&alice) - .open_order(base_asset.asset_id, -1 * base_size as i64, price - 1) - .await - .unwrap() + .with_account(&alice)? + .open_order(base_asset.asset_id, -(base_size as i64), price - 1) + .await? .value; //mint quote asset to buy let quote_size = quote_asset.parse_units(BASE_SIZE as f64 * BASE_PRICE as f64); quote_asset .mint(alice.address().into(), quote_size as u64) - .await - .unwrap(); + .await?; //buy let buy_order_id = orderbook - .with_account(&alice) + .with_account(&alice)? .open_order(base_asset.asset_id, base_size as i64, price) - .await - .unwrap() + .await? .value; //todo match orders orderbook .match_orders(&sell_order_id, &buy_order_id) - .await - .unwrap(); + .await?; + + Ok(()) } // βœ… buyOrder.orderPrice > sellOrder.orderPrice & buyOrder.baseSize > sellOrder.baseSize #[tokio::test] -async fn match1() { - let (alice, bob, btc, usdc, orderbook) = init().await; +async fn match1() -> anyhow::Result<()> { + let (alice, bob, btc, usdc, orderbook) = init().await?; let buy_price = 46_000_f64; // Higher buy price let sell_price = 45_000_f64; // Lower sell price @@ -184,7 +183,7 @@ async fn match1() { // Mint BTC & USDC let usdc_mint_amount = usdc.parse_units(92_000_f64) as u64; let btc_mint_amount = btc.parse_units(1_f64) as u64; - mint_tokens(&usdc, &btc, &alice, &bob, usdc_mint_amount, btc_mint_amount).await; + mint_tokens(&usdc, &btc, &alice, &bob, usdc_mint_amount, btc_mint_amount).await?; // Open and match orders let (alice_order_id, _bob_order_id) = open_orders_match( @@ -195,35 +194,36 @@ async fn match1() { // ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡΠ΅ΠΌ, Ρ‡Ρ‚ΠΎ Ρƒ Alice Π΅ΡΡ‚ΡŒ 1 BTC послС ΡΠΎΠ²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ сдСлки let expected_balance = (1_f64 * 1e8) as u64; - let actual_balance = alice.get_asset_balance(&btc.asset_id).await.unwrap(); + let actual_balance = alice.get_asset_balance(&btc.asset_id).await?; tolerance_eq(expected_balance, actual_balance); orderbook - .with_account(&alice) + .with_account(&alice)? .cancel_order(&alice_order_id) - .await - .unwrap(); + .await?; // ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡΠ΅ΠΌ, Ρ‡Ρ‚ΠΎ Ρƒ Alice ΠΎΡΡ‚Π°Π»ΠΎΡΡŒ 47,000 USDC послС ΠΏΠΎΠΊΡƒΠΏΠΊΠΈ 1 BTC ΠΏΠΎ Ρ†Π΅Π½Π΅ 45,000 USDC let expected_balance = (47_000_f64 * 1e6) as u64; - let actual_balance = alice.get_asset_balance(&usdc.asset_id).await.unwrap(); + let actual_balance = alice.get_asset_balance(&usdc.asset_id).await?; tolerance_eq(expected_balance, actual_balance); // ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡΠ΅ΠΌ, Ρ‡Ρ‚ΠΎ Ρƒ Bob Π΅ΡΡ‚ΡŒ 0 BTC послС ΠΏΡ€ΠΎΠ΄Π°ΠΆΠΈ let expected_balance = 0; - let actual_balance = bob.get_asset_balance(&btc.asset_id).await.unwrap(); + let actual_balance = bob.get_asset_balance(&btc.asset_id).await?; tolerance_eq(expected_balance, actual_balance); // ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡΠ΅ΠΌ, Ρ‡Ρ‚ΠΎ Ρƒ Bob Π΅ΡΡ‚ΡŒ 45,000 USDC послС ΠΏΡ€ΠΎΠ΄Π°ΠΆΠΈ своСго BTC let expected_balance = (45_000_f64 * 1e6) as u64; - let actual_balance = bob.get_asset_balance(&usdc.asset_id).await.unwrap(); + let actual_balance = bob.get_asset_balance(&usdc.asset_id).await?; tolerance_eq(expected_balance, actual_balance); + + Ok(()) } // βœ… buyOrder.orderPrice > sellOrder.orderPrice & buyOrder.baseSize < sellOrder.baseSize #[tokio::test] -async fn match2() { - let (alice, bob, btc, usdc, orderbook) = init().await; +async fn match2() -> anyhow::Result<()> { + let (alice, bob, btc, usdc, orderbook) = init().await?; let buy_price = 46_000_f64; // Higher buy price let sell_price = 45_000_f64; // Lower sell price @@ -233,7 +233,7 @@ async fn match2() { // Mint BTC & USDC let usdc_mint_amount = usdc.parse_units(46_000_f64) as u64; let btc_mint_amount = btc.parse_units(2_f64) as u64; - mint_tokens(&usdc, &btc, &alice, &bob, usdc_mint_amount, btc_mint_amount).await; + mint_tokens(&usdc, &btc, &alice, &bob, usdc_mint_amount, btc_mint_amount).await?; // Open and match orders let (_alice_order_id, bob_order_id) = open_orders_match( @@ -243,36 +243,37 @@ async fn match2() { .expect("Failed to open and match orders"); // ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡΠ΅ΠΌ, Ρ‡Ρ‚ΠΎ Ρƒ Alice Π΅ΡΡ‚ΡŒ 1 BTC послС ΡΠΎΠ²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ сдСлки - let expected_balance = 102222222 as u64; - let actual_balance = alice.get_asset_balance(&btc.asset_id).await.unwrap(); + let expected_balance = 102222222; + let actual_balance = alice.get_asset_balance(&btc.asset_id).await?; tolerance_eq(expected_balance, actual_balance); // ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡΠ΅ΠΌ, Ρ‡Ρ‚ΠΎ Ρƒ Alice ΠΎΡΡ‚Π°Π»ΠΎΡΡŒ 1000 USDC сдачи послС ΠΏΠΎΠΊΡƒΠΏΠΊΠΈ 1 BTC ΠΏΠΎ Ρ†Π΅Π½Π΅ 45,000 USDC - let expected_balance = 0 as u64; - let actual_balance = alice.get_asset_balance(&usdc.asset_id).await.unwrap(); + let expected_balance = 0; + let actual_balance = alice.get_asset_balance(&usdc.asset_id).await?; tolerance_eq(expected_balance, actual_balance); orderbook - .with_account(&bob) + .with_account(&bob)? .cancel_order(&bob_order_id) - .await - .unwrap(); + .await?; // ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡΠ΅ΠΌ, Ρ‡Ρ‚ΠΎ Ρƒ Bob остался 1 BTC послС ΠΏΡ€ΠΎΠ΄Π°ΠΆΠΈ 1 BTC ΠΈΠ· 2 - let expected_balance = 97777778 as u64; - let actual_balance = bob.get_asset_balance(&btc.asset_id).await.unwrap(); + let expected_balance = 97777778; + let actual_balance = bob.get_asset_balance(&btc.asset_id).await?; tolerance_eq(expected_balance, actual_balance); // ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡΠ΅ΠΌ, Ρ‡Ρ‚ΠΎ Ρƒ Bob Π΅ΡΡ‚ΡŒ 45,000 USDC послС ΠΏΡ€ΠΎΠ΄Π°ΠΆΠΈ своСго BTC - let expected_balance = 45999999900 as u64; - let actual_balance = bob.get_asset_balance(&usdc.asset_id).await.unwrap(); + let expected_balance = 45999999900; + let actual_balance = bob.get_asset_balance(&usdc.asset_id).await?; tolerance_eq(expected_balance, actual_balance); + + Ok(()) } // βœ… buyOrder.orderPrice > sellOrder.orderPrice & buyOrder.baseSize = sellOrder.baseSize #[tokio::test] -async fn match3() { - let (alice, bob, btc, usdc, orderbook) = init().await; +async fn match3() -> anyhow::Result<()> { + let (alice, bob, btc, usdc, orderbook) = init().await?; let buy_price = 46_000_f64; let sell_price = 45_000_f64; @@ -282,7 +283,7 @@ async fn match3() { // Mint BTC & USDC let usdc_mint_amount = usdc.parse_units(46_000_f64) as u64; let btc_mint_amount = btc.parse_units(1_f64) as u64; - mint_tokens(&usdc, &btc, &alice, &bob, usdc_mint_amount, btc_mint_amount).await; + mint_tokens(&usdc, &btc, &alice, &bob, usdc_mint_amount, btc_mint_amount).await?; // Open and match orders let (alice_order_id, _bob_order_id) = open_orders_match( @@ -291,35 +292,37 @@ async fn match3() { .await .expect("Failed to open and match orders"); orderbook - .with_account(&alice) + .with_account(&alice)? .cancel_order(&alice_order_id) - .await - .unwrap(); + .await?; + // ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡΠ΅ΠΌ, Ρ‡Ρ‚ΠΎ Ρƒ Alice Π΅ΡΡ‚ΡŒ 1 BTC послС ΡΠΎΠ²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ сдСлки let expected_balance = (1_f64 * 1e8) as u64; - let actual_balance = alice.get_asset_balance(&btc.asset_id).await.unwrap(); + let actual_balance = alice.get_asset_balance(&btc.asset_id).await?; tolerance_eq(expected_balance, actual_balance); // Ρƒ Alice Π΄ΠΎΠ»ΠΆΠ½ΠΎ ΠΎΡΡ‚Π°Ρ‚ΡŒΡΡ 1000 USDC послС ΠΏΠΎΠΊΡƒΠΏΠΊΠΈ 1 BTC let expected_balance = (1000_f64 * 1e6) as u64; - let actual_balance = alice.get_asset_balance(&usdc.asset_id).await.unwrap(); + let actual_balance = alice.get_asset_balance(&usdc.asset_id).await?; tolerance_eq(expected_balance, actual_balance); // ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡΠ΅ΠΌ, Ρ‡Ρ‚ΠΎ Ρƒ Bob остался 0 BTC послС ΠΏΡ€ΠΎΠ΄Π°ΠΆΠΈ 1 BTC let expected_balance = 0; - let actual_balance = bob.get_asset_balance(&btc.asset_id).await.unwrap(); + let actual_balance = bob.get_asset_balance(&btc.asset_id).await?; tolerance_eq(expected_balance, actual_balance); // ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡΠ΅ΠΌ, Ρ‡Ρ‚ΠΎ Ρƒ Bob Π΅ΡΡ‚ΡŒ 45,000 USDC послС ΠΏΡ€ΠΎΠ΄Π°ΠΆΠΈ своСго BTC let expected_balance = (45_000_f64 * 1e6) as u64; - let actual_balance = bob.get_asset_balance(&usdc.asset_id).await.unwrap(); + let actual_balance = bob.get_asset_balance(&usdc.asset_id).await?; tolerance_eq(expected_balance, actual_balance); + + Ok(()) } // ❌ buyOrder.orderPrice < sellOrder.orderPrice & buyOrder.baseSize > sellOrder.baseSize #[tokio::test] -async fn match4() { - let (alice, bob, btc, usdc, orderbook) = init().await; +async fn match4() -> anyhow::Result<()> { + let (alice, bob, btc, usdc, orderbook) = init().await?; let buy_price = 44_000_f64; let sell_price = 45_000_f64; @@ -329,7 +332,7 @@ async fn match4() { // Mint BTC & USDC let usdc_mint_amount = usdc.parse_units(88_000_f64) as u64; let btc_mint_amount = btc.parse_units(1_f64) as u64; - mint_tokens(&usdc, &btc, &alice, &bob, usdc_mint_amount, btc_mint_amount).await; + mint_tokens(&usdc, &btc, &alice, &bob, usdc_mint_amount, btc_mint_amount).await?; // Open and match orders let res = open_orders_match( @@ -342,12 +345,14 @@ async fn match4() { .unwrap() .to_string() .contains("OrdersCantBeMatched")); + + Ok(()) } // ❌ buyOrder.orderPrice < sellOrder.orderPrice & buyOrder.baseSize < sellOrder.baseSize #[tokio::test] -async fn match5() { - let (alice, bob, btc, usdc, orderbook) = init().await; +async fn match5() -> anyhow::Result<()> { + let (alice, bob, btc, usdc, orderbook) = init().await?; let buy_price = 44_000_f64; let sell_price = 45_000_f64; @@ -357,7 +362,7 @@ async fn match5() { // Mint BTC & USDC let usdc_mint_amount = usdc.parse_units(44_000_f64) as u64; let btc_mint_amount = btc.parse_units(2_f64) as u64; - mint_tokens(&usdc, &btc, &alice, &bob, usdc_mint_amount, btc_mint_amount).await; + mint_tokens(&usdc, &btc, &alice, &bob, usdc_mint_amount, btc_mint_amount).await?; // Open and match orders let res = open_orders_match( @@ -370,12 +375,14 @@ async fn match5() { .unwrap() .to_string() .contains("OrdersCantBeMatched")); + + Ok(()) } // ❌ buyOrder.orderPrice < sellOrder.orderPrice & buyOrder.baseSize = sellOrder.baseSize #[tokio::test] -async fn match6() { - let (alice, bob, btc, usdc, orderbook) = init().await; +async fn match6() -> anyhow::Result<()> { + let (alice, bob, btc, usdc, orderbook) = init().await?; let buy_price = 44_000_f64; let sell_price = 45_000_f64; @@ -385,7 +392,7 @@ async fn match6() { // Mint BTC & USDC let usdc_mint_amount = usdc.parse_units(44_000_f64) as u64; let btc_mint_amount = btc.parse_units(1_f64) as u64; - mint_tokens(&usdc, &btc, &alice, &bob, usdc_mint_amount, btc_mint_amount).await; + mint_tokens(&usdc, &btc, &alice, &bob, usdc_mint_amount, btc_mint_amount).await?; // Open and match orders let res = open_orders_match( @@ -398,13 +405,15 @@ async fn match6() { .unwrap() .to_string() .contains("OrdersCantBeMatched")); + + Ok(()) } // βœ… buyOrder.orderPrice = sellOrder.orderPrice & buyOrder.baseSize > sellOrder.baseSize #[tokio::test] -async fn match7() { +async fn match7() -> anyhow::Result<()> { //--------------- WALLETS --------------- - let (alice, bob, btc, usdc, orderbook) = init().await; + let (alice, bob, btc, usdc, orderbook) = init().await?; let buy_price = 45_000_f64; let sell_price = 45_000_f64; @@ -414,7 +423,7 @@ async fn match7() { // Mint BTC & USDC let usdc_mint_amount = usdc.parse_units(90_000_f64) as u64; let btc_mint_amount = btc.parse_units(1_f64) as u64; - mint_tokens(&usdc, &btc, &alice, &bob, usdc_mint_amount, btc_mint_amount).await; + mint_tokens(&usdc, &btc, &alice, &bob, usdc_mint_amount, btc_mint_amount).await?; // Open and match orders let (alice_order_id, _bob_order_id) = open_orders_match( @@ -424,36 +433,37 @@ async fn match7() { .expect("Failed to open and match orders"); orderbook - .with_account(&alice) + .with_account(&alice)? .cancel_order(&alice_order_id) - .await - .unwrap(); + .await?; // ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡΠ΅ΠΌ, Ρ‡Ρ‚ΠΎ Ρƒ Alice Π΅ΡΡ‚ΡŒ 1 BTC послС ΡΠΎΠ²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ сдСлки let expected_balance = (1_f64 * 1e8) as u64; - let actual_balance = alice.get_asset_balance(&btc.asset_id).await.unwrap(); + let actual_balance = alice.get_asset_balance(&btc.asset_id).await?; tolerance_eq(expected_balance, actual_balance); // Ρƒ Alice Π΄ΠΎΠ»ΠΆΠ½ΠΎ ΠΎΡΡ‚Π°Ρ‚ΡŒΡΡ 45,000 USDC послС ΠΏΠΎΠΊΡƒΠΏΠΊΠΈ 1 BTC let expected_balance = (45_000_f64 * 1e6) as u64; - let actual_balance = alice.get_asset_balance(&usdc.asset_id).await.unwrap(); + let actual_balance = alice.get_asset_balance(&usdc.asset_id).await?; tolerance_eq(expected_balance, actual_balance); // ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡΠ΅ΠΌ, Ρ‡Ρ‚ΠΎ Ρƒ Bob остался 0 BTC послС ΠΏΡ€ΠΎΠ΄Π°ΠΆΠΈ 1 BTC let expected_balance = 0; - let actual_balance = bob.get_asset_balance(&btc.asset_id).await.unwrap(); + let actual_balance = bob.get_asset_balance(&btc.asset_id).await?; tolerance_eq(expected_balance, actual_balance); // ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡΠ΅ΠΌ, Ρ‡Ρ‚ΠΎ Ρƒ Bob Π΅ΡΡ‚ΡŒ 45,000 USDC послС ΠΏΡ€ΠΎΠ΄Π°ΠΆΠΈ своСго BTC let expected_balance = (45_000_f64 * 1e6) as u64; - let actual_balance = bob.get_asset_balance(&usdc.asset_id).await.unwrap(); + let actual_balance = bob.get_asset_balance(&usdc.asset_id).await?; tolerance_eq(expected_balance, actual_balance); + + Ok(()) } // βœ… buyOrder.orderPrice = sellOrder.orderPrice & buyOrder.baseSize < sellOrder.baseSize #[tokio::test] -async fn match8() { - let (alice, bob, btc, usdc, orderbook) = init().await; +async fn match8() -> anyhow::Result<()> { + let (alice, bob, btc, usdc, orderbook) = init().await?; let buy_price = 45_000_f64; let sell_price = 45_000_f64; @@ -463,7 +473,7 @@ async fn match8() { // Mint BTC & USDC let usdc_mint_amount = usdc.parse_units(45_000_f64) as u64; let btc_mint_amount = btc.parse_units(2_f64) as u64; - mint_tokens(&usdc, &btc, &alice, &bob, usdc_mint_amount, btc_mint_amount).await; + mint_tokens(&usdc, &btc, &alice, &bob, usdc_mint_amount, btc_mint_amount).await?; // Open and match orders let (_alice_order_id, bob_order_id) = open_orders_match( @@ -474,35 +484,36 @@ async fn match8() { // ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡΠ΅ΠΌ, Ρ‡Ρ‚ΠΎ Ρƒ Alice Π΅ΡΡ‚ΡŒ 1 BTC послС ΡΠΎΠ²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ сдСлки let expected_balance = (1_f64 * 1e8) as u64; - let actual_balance = alice.get_asset_balance(&btc.asset_id).await.unwrap(); + let actual_balance = alice.get_asset_balance(&btc.asset_id).await?; tolerance_eq(expected_balance, actual_balance); // Ρƒ Alice Π΄ΠΎΠ»ΠΆΠ½ΠΎ ΠΎΡΡ‚Π°Ρ‚ΡŒΡΡ 0,000 USDC послС ΠΏΠΎΠΊΡƒΠΏΠΊΠΈ 1 BTC let expected_balance = 0; - let actual_balance = alice.get_asset_balance(&usdc.asset_id).await.unwrap(); + let actual_balance = alice.get_asset_balance(&usdc.asset_id).await?; tolerance_eq(expected_balance, actual_balance); orderbook - .with_account(&bob) + .with_account(&bob)? .cancel_order(&bob_order_id) - .await - .unwrap(); + .await?; // ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡΠ΅ΠΌ, Ρ‡Ρ‚ΠΎ Ρƒ Bob остался 1 BTC послС ΠΏΡ€ΠΎΠ΄Π°ΠΆΠΈ 1 BTC ΠΈΠ· 2 let expected_balance = (1_f64 * 1e8) as u64; - let actual_balance = bob.get_asset_balance(&btc.asset_id).await.unwrap(); + let actual_balance = bob.get_asset_balance(&btc.asset_id).await?; tolerance_eq(expected_balance, actual_balance); // ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡΠ΅ΠΌ, Ρ‡Ρ‚ΠΎ Ρƒ Bob Π΅ΡΡ‚ΡŒ 45,000 USDC послС ΠΏΡ€ΠΎΠ΄Π°ΠΆΠΈ своСго BTC let expected_balance = (45_000_f64 * 1e6) as u64; - let actual_balance = bob.get_asset_balance(&usdc.asset_id).await.unwrap(); + let actual_balance = bob.get_asset_balance(&usdc.asset_id).await?; tolerance_eq(expected_balance, actual_balance); + + Ok(()) } //βœ… buyOrder.orderPrice = sellOrder.orderPrice & buyOrder.baseSize = sellOrder.baseSize #[tokio::test] -async fn match9() { - let (alice, bob, btc, usdc, orderbook) = init().await; +async fn match9() -> anyhow::Result<()> { + let (alice, bob, btc, usdc, orderbook) = init().await?; let buy_price = 45_000_f64; let sell_price = 45_000_f64; @@ -512,7 +523,7 @@ async fn match9() { // Mint BTC & USDC let usdc_mint_amount = usdc.parse_units(45_000_f64) as u64; let btc_mint_amount = btc.parse_units(1_f64) as u64; - mint_tokens(&usdc, &btc, &alice, &bob, usdc_mint_amount, btc_mint_amount).await; + mint_tokens(&usdc, &btc, &alice, &bob, usdc_mint_amount, btc_mint_amount).await?; // Open and match orders let (_alice_order_id, _bob_order_id) = open_orders_match( @@ -523,21 +534,23 @@ async fn match9() { // ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡΠ΅ΠΌ, Ρ‡Ρ‚ΠΎ Ρƒ Alice Π΅ΡΡ‚ΡŒ 1 BTC послС ΡΠΎΠ²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ сдСлки let expected_balance = (1_f64 * 1e8) as u64; - let actual_balance = alice.get_asset_balance(&btc.asset_id).await.unwrap(); + let actual_balance = alice.get_asset_balance(&btc.asset_id).await?; tolerance_eq(expected_balance, actual_balance); // Ρƒ Alice Π΄ΠΎΠ»ΠΆΠ½ΠΎ ΠΎΡΡ‚Π°Ρ‚ΡŒΡΡ 0,000 USDC послС ΠΏΠΎΠΊΡƒΠΏΠΊΠΈ 1 BTC let expected_balance = 0; - let actual_balance = alice.get_asset_balance(&usdc.asset_id).await.unwrap(); + let actual_balance = alice.get_asset_balance(&usdc.asset_id).await?; tolerance_eq(expected_balance, actual_balance); // ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡΠ΅ΠΌ, Ρ‡Ρ‚ΠΎ Ρƒ Bob остался 0 BTC послС ΠΏΡ€ΠΎΠ΄Π°ΠΆΠΈ 1 BTC let expected_balance = 0; - let actual_balance = bob.get_asset_balance(&btc.asset_id).await.unwrap(); + let actual_balance = bob.get_asset_balance(&btc.asset_id).await?; tolerance_eq(expected_balance, actual_balance); // ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡΠ΅ΠΌ, Ρ‡Ρ‚ΠΎ Ρƒ Bob Π΅ΡΡ‚ΡŒ 45,000 USDC послС ΠΏΡ€ΠΎΠ΄Π°ΠΆΠΈ своСго BTC let expected_balance = (45_000_f64 * 1e6) as u64; - let actual_balance = bob.get_asset_balance(&usdc.asset_id).await.unwrap(); + let actual_balance = bob.get_asset_balance(&usdc.asset_id).await?; tolerance_eq(expected_balance, actual_balance); + + Ok(()) } diff --git a/utils/Cargo.toml b/utils/Cargo.toml new file mode 100644 index 0000000..9915b5f --- /dev/null +++ b/utils/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "utils" +authors = { workspace = true } +version = { workspace = true } +edition = { workspace = true } +license = { workspace = true } +rust-version = { workspace = true } + +[lib] +name = "utils" +path = "lib.rs" +test = false +doctest = false diff --git a/src/constants.rs b/utils/constants.rs similarity index 89% rename from src/constants.rs rename to utils/constants.rs index aafee67..59807c2 100644 --- a/src/constants.rs +++ b/utils/constants.rs @@ -12,5 +12,5 @@ pub const BTC_ASSET_ID_STR: &str = pub const UNI_ASSET_ID_STR: &str = "0xae37bc0feb66e60a89e301d450bb4640aa9bd7cedd856e253e23989eae536e92"; - /* 🏁 Start_block: 10487767 -The orderbook contract has been deployed 0f0c1065a7b82d026069c5cf070b21ee65713fd1ac92ec1d25eacc3100187f78 */ \ No newline at end of file +/* 🏁 Start_block: 10487767 +The orderbook contract has been deployed 0f0c1065a7b82d026069c5cf070b21ee65713fd1ac92ec1d25eacc3100187f78 */ diff --git a/utils/lib.rs b/utils/lib.rs new file mode 100644 index 0000000..4c624de --- /dev/null +++ b/utils/lib.rs @@ -0,0 +1,2 @@ +pub mod constants; +pub mod title; diff --git a/src/lib.rs b/utils/title.rs similarity index 98% rename from src/lib.rs rename to utils/title.rs index 54ed73e..d5832d9 100644 --- a/src/lib.rs +++ b/utils/title.rs @@ -1,6 +1,3 @@ -pub mod constants; -pub mod orderbook_utils; - pub fn print_title(title: &str) { println!( r#" From c87f6a719fefc0bc71f30de9003a62d83570905e Mon Sep 17 00:00:00 2001 From: Braqzen <103777923+Braqzen@users.noreply.github.com> Date: Fri, 26 Apr 2024 16:59:54 +0100 Subject: [PATCH 02/10] Minor docs for SDK --- spark-market-sdk/README.md | 59 +++++++++++++++++++++++++++++++++++++ spark-market-sdk/src/lib.rs | 17 +++++++++++ 2 files changed, 76 insertions(+) create mode 100644 spark-market-sdk/README.md diff --git a/spark-market-sdk/README.md b/spark-market-sdk/README.md new file mode 100644 index 0000000..5861049 --- /dev/null +++ b/spark-market-sdk/README.md @@ -0,0 +1,59 @@ +## Introduction + +The spark market SDK is an interface which enables calls upon the Orderbook contract. + +It exposes a method for each function in the ABI in addition to some utility methods. + +## API + +### Utility methods + +#### Deploy + +The deploy method creates a new contract and deploys it to the network. It returns a wrapper for the contract instance which enables users to interact with the contract. + +### New + +The new method enables interaction with an existing / deployed contract without having to redeploy. + +### ID + +The ID method returns the contract ID + +### With Account + +The account method switches the user (equivalent to msg.sender in Solidity) who makes contract calls + +### Contract methods + +#### Create Market + +The method creates a new market for a specified asset ID + +#### Open Order + +The method opens a new order for the contract caller + +#### Cancel Order + +The method cancels an existing order for the contract caller + +#### Match Orders + +The method matches two orders, a sell order and a buy order, for any users + +#### Get Market ID + +The method returns the ID for the market of the asset + +#### Market Exists + +The method returns whether a market exists for an asset + +#### Order by ID + +The method returns information about an order for a specific order ID + +#### Orders by trader + +The method returns all orders for a user diff --git a/spark-market-sdk/src/lib.rs b/spark-market-sdk/src/lib.rs index 819fdd6..df5b76d 100644 --- a/spark-market-sdk/src/lib.rs +++ b/spark-market-sdk/src/lib.rs @@ -1,3 +1,5 @@ +//! Wrapper for the orderbook contract exposing an interface for simpler contract calls + use fuels::{ prelude::{ abigen, AssetId, CallParameters, Contract, ContractId, LoadConfiguration, @@ -9,14 +11,17 @@ use fuels::{ }; use rand::Rng; +// Import all components into scope using the Fuel Rust SDK abigen!(Contract( name = "Orderbook", abi = "./contract/out/debug/orderbook-abi.json" )); +// Specify the binary and storage paths for contract deployment const ORDERBOOK_CONTRACT_BINARY_PATH: &str = "../contract/out/debug/orderbook.bin"; const ORDERBOOK_CONTRACT_STORAGE_PATH: &str = "../contract/out/debug/orderbook-storage_slots.json"; +// Wrapper for the instance of the orderbook contract pub struct OrderbookContract { instance: Orderbook, pub quote_token: AssetId, @@ -25,6 +30,7 @@ pub struct OrderbookContract { } impl OrderbookContract { + /// Deploy a new instance of the orderbook contract and return the interface for contract calls pub async fn deploy( wallet: &WalletUnlocked, quote_token: AssetId, @@ -61,6 +67,7 @@ impl OrderbookContract { }) } + /// Create a new instance of a contract without redeploying pub async fn new(contract_id: ContractId, wallet: WalletUnlocked) -> anyhow::Result { let instance = Orderbook::new(contract_id, wallet); let (quote_token, quote_token_decimals, price_decimals) = instance @@ -78,10 +85,12 @@ impl OrderbookContract { }) } + /// Return the hash of the contract ID pub fn id(&self) -> Bytes32 { self.instance.contract_id().hash } + /// Change the owner of the wrapper to a new account pub fn with_account(&self, account: &WalletUnlocked) -> anyhow::Result { Ok(Self { instance: self.instance.with_account(account.clone())?, @@ -91,6 +100,7 @@ impl OrderbookContract { }) } + /// Create a new market in the orderbook pub async fn create_market( &self, asset_id: AssetId, @@ -104,6 +114,7 @@ impl OrderbookContract { .await?) } + /// Open a new order in the orderbook pub async fn open_order( &self, base_token: AssetId, @@ -139,6 +150,7 @@ impl OrderbookContract { .await?) } + /// Cancel an existing order in the orderbook pub async fn cancel_order(&self, order_id: &Bits256) -> anyhow::Result> { Ok(self .instance @@ -149,6 +161,7 @@ impl OrderbookContract { .await?) } + /// Match a sell order with a buy order in the orderbook pub async fn match_orders( &self, sell_order_id: &Bits256, @@ -164,6 +177,7 @@ impl OrderbookContract { .await?) } + /// Return the market ID for a specific asset pub async fn get_market_by_id( &self, asset_id: AssetId, @@ -176,6 +190,7 @@ impl OrderbookContract { .await?) } + /// Return whether a market exists for an asset pub async fn market_exists(&self, asset_id: AssetId) -> anyhow::Result> { Ok(self .instance @@ -185,6 +200,7 @@ impl OrderbookContract { .await?) } + /// Return the order information associated with a specific ID pub async fn order_by_id( &self, id: &Bits256, @@ -198,6 +214,7 @@ impl OrderbookContract { .await?) } + /// Return the orders for a user pub async fn orders_by_trader( &self, trader: &Bech32Address, From 78f4670b7b60f95a0e9b2b46d3422c6fe3d6b481 Mon Sep 17 00:00:00 2001 From: Braqzen <103777923+Braqzen@users.noreply.github.com> Date: Fri, 26 Apr 2024 17:00:06 +0100 Subject: [PATCH 03/10] CI --- .github/workflows/ci.yml | 177 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 177 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..3d4c191 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,177 @@ +name: CI + +on: + push: + branches: + - master + pull_request: + release: + types: [published] + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +env: + RUST_VERSION: 1.75.0 + +jobs: + lint-toml-files: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ env.RUST_VERSION }} + + - name: Install Cargo.toml linter + uses: baptiste0928/cargo-install@v2 + with: + crate: cargo-toml-lint + version: '0.1.1' + + - name: Run Cargo.toml linter + run: git ls-files | grep Cargo.toml$ | xargs --verbose -n 1 cargo-toml-lint + + orderbook-contract: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Install Rust toolchain + uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ env.RUST_VERSION }} + components: clippy, rustfmt + + - name: Init cache + uses: Swatinem/rust-cache@v2 + + - name: Install Fuel toolchain + uses: FuelLabs/action-fuel-toolchain@v0.6.0 + with: + toolchain: nightly + date: 2024-02-07 + + - name: Check Sway formatting + run: forc fmt --check --path contract + + - name: Build Sway + run: | + cd "contract" + forc build --locked + + tests: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Install Rust toolchain + uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ env.RUST_VERSION }} + components: clippy, rustfmt + + - name: Init cache + uses: Swatinem/rust-cache@v2 + + - name: Install Fuel toolchain + uses: FuelLabs/action-fuel-toolchain@v0.6.0 + with: + toolchain: nightly + date: 2024-02-07 + + - name: Build Sway + run: | + cd "contract" + forc build --locked + + - name: Check Rust formatting + run: cargo fmt --verbose --check --manifest-path tests/Cargo.toml + + - name: Check Clippy Linter + run: cargo clippy --manifest-path tests/Cargo.toml --all-features --all-targets -- -D warnings + + - name: Run Rust tests + run: cargo test --locked --manifest-path tests/Cargo.toml + + SDK: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Install Rust toolchain + uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ env.RUST_VERSION }} + components: clippy, rustfmt + + - name: Init cache + uses: Swatinem/rust-cache@v2 + + - name: Install Fuel toolchain + uses: FuelLabs/action-fuel-toolchain@v0.6.0 + with: + toolchain: nightly + date: 2024-02-07 + + - name: Build Sway + run: | + cd "contract" + forc build --locked + + - name: Build Rust files + run: cargo build --locked --manifest-path spark-market-sdk/Cargo.toml + + - name: Check Clippy Linter + run: cargo clippy --manifest-path spark-market-sdk/Cargo.toml --all-features --all-targets -- -D warnings + + utils: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Install Rust toolchain + uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ env.RUST_VERSION }} + components: clippy, rustfmt + + - name: Init cache + uses: Swatinem/rust-cache@v2 + + - name: Build Rust files + run: cargo build --locked --manifest-path utils/Cargo.toml + + - name: Check Clippy Linter + run: cargo clippy --manifest-path utils/Cargo.toml --all-features --all-targets -- -D warnings + + scripts: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Install Rust toolchain + uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ env.RUST_VERSION }} + components: clippy, rustfmt + + - name: Init cache + uses: Swatinem/rust-cache@v2 + + - name: Build Rust files + run: cargo build --locked --manifest-path scripts/Cargo.toml + + - name: Check Clippy Linter + run: cargo clippy --manifest-path scripts/Cargo.toml --all-features --all-targets -- -D warnings From 8e45ef97e682e0ca3c1b349f97b195178fde1cd8 Mon Sep 17 00:00:00 2001 From: Braqzen <103777923+Braqzen@users.noreply.github.com> Date: Fri, 26 Apr 2024 17:07:45 +0100 Subject: [PATCH 04/10] CI checks --- .github/workflows/ci.yml | 11 +++++++ Cargo.toml | 4 +-- contract/Forc.lock | 2 +- contract/Forc.toml | 2 +- contract/src/events.sw | 25 ++++++--------- contract/src/main.sw | 62 +++++++++++++++++++++++++++---------- contract/src/math.sw | 8 +++-- scripts/Cargo.toml | 10 +++--- spark-market-sdk/Cargo.toml | 2 +- tests/Cargo.toml | 2 +- 10 files changed, 82 insertions(+), 46 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3d4c191..4c2a377 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -170,6 +170,17 @@ jobs: - name: Init cache uses: Swatinem/rust-cache@v2 + - name: Install Fuel toolchain + uses: FuelLabs/action-fuel-toolchain@v0.6.0 + with: + toolchain: nightly + date: 2024-02-07 + + - name: Build Sway + run: | + cd "contract" + forc build --locked + - name: Build Rust files run: cargo build --locked --manifest-path scripts/Cargo.toml diff --git a/Cargo.toml b/Cargo.toml index dea653d..fd573ce 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,6 @@ rust-version = "1.75.0" [workspace.dependencies] anyhow = "1.0.81" fuels = { version = "0.55.1", features = ["fuel-core-lib"] } -tokio = { version = "1.12", features = ["rt", "macros"] } -src20_sdk = { git = "https://github.com/compolabs/src-20.git", branch = "master" } rand = "0.8.5" +src20_sdk = { git = "https://github.com/compolabs/src-20.git", branch = "master" } +tokio = { version = "1.12", features = ["rt", "macros"] } diff --git a/contract/Forc.lock b/contract/Forc.lock index 5a413d6..74e0598 100644 --- a/contract/Forc.lock +++ b/contract/Forc.lock @@ -18,7 +18,7 @@ dependencies = [ [[package]] name = "reentrancy" -source = "git+https://github.com/FuelLabs/sway-libs?default-branch#7765aff5ed9cf76c789a95b1fde9ff19462623fd" +source = "git+https://github.com/FuelLabs/sway-libs?tag=v0.18.0#8d196e9379463d4596ac582a20a84ed52ff58c69" dependencies = ["std"] [[package]] diff --git a/contract/Forc.toml b/contract/Forc.toml index 7b6c53e..cdf1eac 100644 --- a/contract/Forc.toml +++ b/contract/Forc.toml @@ -5,5 +5,5 @@ license = "Apache-2.0" name = "orderbook" [dependencies] -reentrancy = { git = "https://github.com/FuelLabs/sway-libs", tag = "v0.18.0" } i64 = { git = "https://github.com/compolabs/i64" } +reentrancy = { git = "https://github.com/FuelLabs/sway-libs", tag = "v0.18.0" } diff --git a/contract/src/events.sw b/contract/src/events.sw index b914ab6..12076c8 100644 --- a/contract/src/events.sw +++ b/contract/src/events.sw @@ -6,7 +6,7 @@ pub struct MarketCreateEvent { asset_id: AssetId, asset_decimals: u32, timestamp: u64, - tx_id: b256 + tx_id: b256, } pub struct TradeEvent { @@ -19,17 +19,15 @@ pub struct TradeEvent { sell_order_id: b256, buy_order_id: b256, timestamp: u64, - tx_id: b256 + tx_id: b256, } - -enum OrderChangeEventIdentifier{ +enum OrderChangeEventIdentifier { OrderOpenEvent: (), OrderCancelEvent: (), OrderMatchEvent: (), } - pub struct OrderChangeEvent { order_id: b256, sender: Identity, @@ -39,7 +37,7 @@ pub struct OrderChangeEvent { order: Option, } -impl OrderChangeEvent{ +impl OrderChangeEvent { pub fn open(id: b256, order: Option) -> self { Self { order_id: id, @@ -47,34 +45,29 @@ impl OrderChangeEvent{ sender: std::auth::msg_sender().unwrap(), identifier: OrderChangeEventIdentifier::OrderOpenEvent, timestamp: std::block::timestamp(), - tx_id: std::tx::tx_id() + tx_id: std::tx::tx_id(), } } - - pub fn cancel(order_id: b256, order: Option)-> self{ + pub fn cancel(order_id: b256, order: Option) -> self { Self { order_id, order, sender: std::auth::msg_sender().unwrap(), identifier: OrderChangeEventIdentifier::OrderCancelEvent, timestamp: std::block::timestamp(), - tx_id: std::tx::tx_id() + tx_id: std::tx::tx_id(), } } - - pub fn match_orders(id: b256, order: Option)-> self{ + pub fn match_orders(id: b256, order: Option) -> self { Self { order_id: id, order, sender: std::auth::msg_sender().unwrap(), identifier: OrderChangeEventIdentifier::OrderMatchEvent, timestamp: std::block::timestamp(), - tx_id: std::tx::tx_id() + tx_id: std::tx::tx_id(), } } - } - - diff --git a/contract/src/main.sw b/contract/src/main.sw index 7d91da5..054ace6 100644 --- a/contract/src/main.sw +++ b/contract/src/main.sw @@ -22,11 +22,10 @@ use std::hash::*; use std::storage::storage_vec::*; use std::tx::tx_id; - configurable { QUOTE_TOKEN: AssetId = BASE_ASSET_ID, QUOTE_TOKEN_DECIMALS: u32 = 9, - PRICE_DECIMALS: u32 = 9 + PRICE_DECIMALS: u32 = 9, } storage { @@ -34,7 +33,6 @@ storage { markets: StorageMap = StorageMap {}, orders_by_trader: StorageMap> = StorageMap {}, order_indexes_by_trader: StorageMap> = StorageMap {}, - order_change_events: StorageMap> = StorageMap {}, } @@ -59,7 +57,7 @@ abi OrderBook { #[storage(read)] fn market_exists(asset_id: AssetId) -> bool; - + #[storage(read)] fn get_market_by_id(asset_id: AssetId) -> Market; @@ -90,12 +88,12 @@ impl OrderBook for Contract { asset_id: asset_id, asset_decimals: asset_decimals, timestamp: timestamp(), - tx_id: tx_id() + tx_id: tx_id(), }); } #[storage(read)] - fn get_market_by_id(asset_id: AssetId) -> Market{ + fn get_market_by_id(asset_id: AssetId) -> Market { storage.markets.get(asset_id).read() } @@ -109,7 +107,7 @@ impl OrderBook for Contract { reentrancy_guard(); let market = storage.markets.get(base_token).try_read(); - require(base_size.value != 0,Error::BaseSizeIsZero); + require(base_size.value != 0, Error::BaseSizeIsZero); require(market.is_some(), Error::NoMarketFound); require(base_price != 0, Error::BadPrice); @@ -211,9 +209,17 @@ impl OrderBook for Contract { let mut tmp = order_sell; tmp.base_size = tmp.base_size.flip(); - let trade_size = min(order_sell.base_size.value, order_buy.base_size.value.mul_div(order_buy.base_price, order_sell.base_price)); + let trade_size = min( + order_sell + .base_size + .value, + order_buy + .base_size + .value + .mul_div(order_buy.base_price, order_sell.base_price), + ); tmp.base_size.value = trade_size; - + let seller: Address = order_sell.trader; let (sellerDealAssetId, sellerDealRefund) = order_return_asset_amount(tmp); remove_update_order_internal(order_sell, tmp.base_size); @@ -253,7 +259,7 @@ impl OrderBook for Contract { sell_order_id: order_sell.id, buy_order_id: order_buy.id, timestamp: timestamp(), - tx_id: tx_id() + tx_id: tx_id(), }); } @@ -269,10 +275,10 @@ impl OrderBook for Contract { #[storage(read)] fn get_order_change_events_by_order(order: b256) -> Vec { - storage.order_change_events.get(order).load_vec() + storage.order_change_events.get(order).load_vec() } - fn get_configurables() -> (AssetId, u32, u32){ + fn get_configurables() -> (AssetId, u32, u32) { (QUOTE_TOKEN, QUOTE_TOKEN_DECIMALS, PRICE_DECIMALS) } } @@ -311,7 +317,7 @@ fn update_order_internal(order: Order, base_size: I64) -> ((AssetId, u64), (Asse #[storage(read, write)] fn cancel_order_internal(order: Order) -> (AssetId, u64) { - require(order.base_size.value != 0,Error::BaseSizeIsZero); + require(order.base_size.value != 0, Error::BaseSizeIsZero); let refund = order_return_asset_amount(order); remove_update_order_internal(order, order.base_size.flip()); refund @@ -321,14 +327,36 @@ fn cancel_order_internal(order: Order) -> (AssetId, u64) { fn remove_update_order_internal(order: Order, base_size: I64) { if (order.base_size == base_size.flip()) { let pos_id = storage.order_indexes_by_trader.get(order.trader).get(order.id).read() - 1; // pos + 1 indexed - require(storage.order_indexes_by_trader.get(order.trader).remove(order.id), Error::CannotRemoveOrderIndex); + require( + storage + .order_indexes_by_trader + .get(order.trader) + .remove(order.id), + Error::CannotRemoveOrderIndex, + ); let last_pos = storage.orders_by_trader.get(order.trader).len() - 1; if last_pos != pos_id { let last_id = storage.orders_by_trader.get(order.trader).get(last_pos).unwrap().read(); - require(storage.orders_by_trader.get(order.trader).swap_remove(pos_id) == order.id, Error::CannotRemoveOrderByTrader); - storage.order_indexes_by_trader.get(order.trader).insert(last_id, pos_id + 1); + require( + storage + .orders_by_trader + .get(order.trader) + .swap_remove(pos_id) == order.id, + Error::CannotRemoveOrderByTrader, + ); + storage + .order_indexes_by_trader + .get(order.trader) + .insert(last_id, pos_id + 1); } else { - require(storage.orders_by_trader.get(order.trader).pop().unwrap() == order.id, Error::CannotRemoveOrderByTrader); + require( + storage + .orders_by_trader + .get(order.trader) + .pop() + .unwrap() == order.id, + Error::CannotRemoveOrderByTrader, + ); } require(storage.orders.remove(order.id), Error::CannotRemoveOrder); } else { diff --git a/contract/src/math.sw b/contract/src/math.sw index f806f84..7dfee2a 100644 --- a/contract/src/math.sw +++ b/contract/src/math.sw @@ -9,11 +9,15 @@ impl u64 { div_result.as_u64().unwrap() } - pub fn mul_div_rounding_up(self, mul_to: u64, div_to: u64) -> u64{ + pub fn mul_div_rounding_up(self, mul_to: u64, div_to: u64) -> u64 { let mul_result = U128::from((0, self)) * U128::from((0, mul_to)); let div_to = U128::from((0, div_to)); let div_result = mul_result / div_to; - let add = if div_result * div_to < mul_result {1} else {0}; + let add = if div_result * div_to < mul_result { + 1 + } else { + 0 + }; div_result.as_u64().unwrap() + add } diff --git a/scripts/Cargo.toml b/scripts/Cargo.toml index be5263e..4930559 100644 --- a/scripts/Cargo.toml +++ b/scripts/Cargo.toml @@ -8,14 +8,14 @@ rust-version = { workspace = true } [dependencies] anyhow = { workspace = true } -fuels = { workspace = true } -tokio = { workspace = true } -spark-market-sdk = { path = "../spark-market-sdk" } -utils = { path = "../utils" } -src20_sdk = { workspace = true } dotenv = "0.15.0" +fuels = { workspace = true } hex = "0.4" rand = { workspace = true } +spark-market-sdk = { path = "../spark-market-sdk" } +src20_sdk = { workspace = true } +tokio = { workspace = true } +utils = { path = "../utils" } [[bin]] name = "create_market" diff --git a/spark-market-sdk/Cargo.toml b/spark-market-sdk/Cargo.toml index 439f3d9..99289ba 100644 --- a/spark-market-sdk/Cargo.toml +++ b/spark-market-sdk/Cargo.toml @@ -9,8 +9,8 @@ rust-version = { workspace = true } [dependencies] anyhow = { workspace = true } fuels = { workspace = true } -tokio = { workspace = true } rand = { workspace = true } +tokio = { workspace = true } [lib] doctest = false diff --git a/tests/Cargo.toml b/tests/Cargo.toml index 85a8a59..47967d0 100644 --- a/tests/Cargo.toml +++ b/tests/Cargo.toml @@ -9,9 +9,9 @@ rust-version = { workspace = true } [dependencies] anyhow = { workspace = true } fuels = { workspace = true } -tokio = { workspace = true } spark-market-sdk = { path = "../spark-market-sdk" } src20_sdk = { workspace = true } +tokio = { workspace = true } [[test]] name = "main_test" From 9851510b5f167c99d3c8a1d5d17cbf0c5288e9d5 Mon Sep 17 00:00:00 2001 From: Braqzen <103777923+Braqzen@users.noreply.github.com> Date: Fri, 26 Apr 2024 17:14:30 +0100 Subject: [PATCH 05/10] clippy --- scripts/create_accounts_with_tokens.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/create_accounts_with_tokens.rs b/scripts/create_accounts_with_tokens.rs index 56239f1..d8184fc 100644 --- a/scripts/create_accounts_with_tokens.rs +++ b/scripts/create_accounts_with_tokens.rs @@ -66,7 +66,7 @@ async fn main() -> anyhow::Result<()> { base_asset.mint(wallet.address().into(), base_size).await?; quote_asset - .mint(wallet.address().into(), quote_size as u64) + .mint(wallet.address().into(), quote_size) .await?; } From 095d02d9c819baa96846e9653187bfc2321674fe Mon Sep 17 00:00:00 2001 From: Braqzen <103777923+Braqzen@users.noreply.github.com> Date: Fri, 26 Apr 2024 17:23:07 +0100 Subject: [PATCH 06/10] clippy --- scripts/create_order.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/create_order.rs b/scripts/create_order.rs index 569e572..6c2fccf 100644 --- a/scripts/create_order.rs +++ b/scripts/create_order.rs @@ -47,7 +47,7 @@ async fn main() -> anyhow::Result<()> { let base_size = base_asset.parse_units(BASE_SIZE.abs() as f64) as u64; base_asset.mint(wallet.address().into(), base_size).await?; } - let price = BASE_PRICE * 10u64.pow(orderbook.price_decimals as u32); + let price = BASE_PRICE * 10u64.pow(orderbook.price_decimals); let result = orderbook .open_order(base_asset.asset_id, BASE_SIZE, price) .await; From e8fd3705d8d94594d220e82008b9eec863e02599 Mon Sep 17 00:00:00 2001 From: Braqzen <103777923+Braqzen@users.noreply.github.com> Date: Fri, 26 Apr 2024 17:29:44 +0100 Subject: [PATCH 07/10] Testing abigen path change --- spark-market-sdk/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spark-market-sdk/src/lib.rs b/spark-market-sdk/src/lib.rs index df5b76d..d04d685 100644 --- a/spark-market-sdk/src/lib.rs +++ b/spark-market-sdk/src/lib.rs @@ -14,7 +14,7 @@ use rand::Rng; // Import all components into scope using the Fuel Rust SDK abigen!(Contract( name = "Orderbook", - abi = "./contract/out/debug/orderbook-abi.json" + abi = "contract/out/debug/orderbook-abi.json" )); // Specify the binary and storage paths for contract deployment From 064547ce2119b92914b05d63a011e565ba129fcd Mon Sep 17 00:00:00 2001 From: Braqzen <103777923+Braqzen@users.noreply.github.com> Date: Fri, 26 Apr 2024 18:10:14 +0100 Subject: [PATCH 08/10] SDK and paths --- Cargo.lock | 1 + contract/.gitignore | 2 +- contract/out/debug/orderbook-abi.json | 1161 +++++++++++++++++ .../out/debug/orderbook-storage_slots.json | 1 + scripts/README.md | 14 + scripts/deploy.rs | 12 +- scripts/init_system.rs | 12 +- spark-market-sdk/src/lib.rs | 20 +- tests/Cargo.toml | 1 + tests/main_test.rs | 34 +- tests/match_orders.rs | 14 +- utils/constants.rs | 3 + 12 files changed, 1242 insertions(+), 33 deletions(-) create mode 100644 contract/out/debug/orderbook-abi.json create mode 100644 contract/out/debug/orderbook-storage_slots.json create mode 100644 scripts/README.md diff --git a/Cargo.lock b/Cargo.lock index fda89be..1a2f282 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3396,6 +3396,7 @@ dependencies = [ "spark-market-sdk", "src20_sdk", "tokio", + "utils", ] [[package]] diff --git a/contract/.gitignore b/contract/.gitignore index 77d3844..91c7ba6 100644 --- a/contract/.gitignore +++ b/contract/.gitignore @@ -1,2 +1,2 @@ -out +out/debug/orderbook.bin target diff --git a/contract/out/debug/orderbook-abi.json b/contract/out/debug/orderbook-abi.json new file mode 100644 index 0000000..38ae32a --- /dev/null +++ b/contract/out/debug/orderbook-abi.json @@ -0,0 +1,1161 @@ +{ + "types": [ + { + "typeId": 0, + "type": "()", + "components": [], + "typeParameters": null + }, + { + "typeId": 1, + "type": "(_, _, _)", + "components": [ + { + "name": "__tuple_element", + "type": 12, + "typeArguments": null + }, + { + "name": "__tuple_element", + "type": 22, + "typeArguments": null + }, + { + "name": "__tuple_element", + "type": 22, + "typeArguments": null + } + ], + "typeParameters": null + }, + { + "typeId": 2, + "type": "b256", + "components": null, + "typeParameters": null + }, + { + "typeId": 3, + "type": "bool", + "components": null, + "typeParameters": null + }, + { + "typeId": 4, + "type": "enum Error", + "components": [ + { + "name": "AccessDenied", + "type": 0, + "typeArguments": null + }, + { + "name": "NoOrdersFound", + "type": 0, + "typeArguments": null + }, + { + "name": "NoMarketFound", + "type": 0, + "typeArguments": null + }, + { + "name": "OrdersCantBeMatched", + "type": 0, + "typeArguments": null + }, + { + "name": "FirstArgumentShouldBeOrderSellSecondOrderBuy", + "type": 0, + "typeArguments": null + }, + { + "name": "ZeroAssetAmountToSend", + "type": 0, + "typeArguments": null + }, + { + "name": "MarketAlreadyExists", + "type": 0, + "typeArguments": null + }, + { + "name": "BadAsset", + "type": 0, + "typeArguments": null + }, + { + "name": "BadValue", + "type": 0, + "typeArguments": null + }, + { + "name": "BadPrice", + "type": 0, + "typeArguments": null + }, + { + "name": "BaseSizeIsZero", + "type": 0, + "typeArguments": null + }, + { + "name": "CannotRemoveOrderIndex", + "type": 0, + "typeArguments": null + }, + { + "name": "CannotRemoveOrderByTrader", + "type": 0, + "typeArguments": null + }, + { + "name": "CannotRemoveOrder", + "type": 0, + "typeArguments": null + } + ], + "typeParameters": null + }, + { + "typeId": 5, + "type": "enum Identity", + "components": [ + { + "name": "Address", + "type": 11, + "typeArguments": null + }, + { + "name": "ContractId", + "type": 13, + "typeArguments": null + } + ], + "typeParameters": null + }, + { + "typeId": 6, + "type": "enum Option", + "components": [ + { + "name": "None", + "type": 0, + "typeArguments": null + }, + { + "name": "Some", + "type": 9, + "typeArguments": null + } + ], + "typeParameters": [ + 9 + ] + }, + { + "typeId": 7, + "type": "enum OrderChangeEventIdentifier", + "components": [ + { + "name": "OrderOpenEvent", + "type": 0, + "typeArguments": null + }, + { + "name": "OrderCancelEvent", + "type": 0, + "typeArguments": null + }, + { + "name": "OrderMatchEvent", + "type": 0, + "typeArguments": null + } + ], + "typeParameters": null + }, + { + "typeId": 8, + "type": "enum ReentrancyError", + "components": [ + { + "name": "NonReentrant", + "type": 0, + "typeArguments": null + } + ], + "typeParameters": null + }, + { + "typeId": 9, + "type": "generic T", + "components": null, + "typeParameters": null + }, + { + "typeId": 10, + "type": "raw untyped ptr", + "components": null, + "typeParameters": null + }, + { + "typeId": 11, + "type": "struct Address", + "components": [ + { + "name": "value", + "type": 2, + "typeArguments": null + } + ], + "typeParameters": null + }, + { + "typeId": 12, + "type": "struct AssetId", + "components": [ + { + "name": "value", + "type": 2, + "typeArguments": null + } + ], + "typeParameters": null + }, + { + "typeId": 13, + "type": "struct ContractId", + "components": [ + { + "name": "value", + "type": 2, + "typeArguments": null + } + ], + "typeParameters": null + }, + { + "typeId": 14, + "type": "struct I64", + "components": [ + { + "name": "value", + "type": 23, + "typeArguments": null + }, + { + "name": "negative", + "type": 3, + "typeArguments": null + } + ], + "typeParameters": null + }, + { + "typeId": 15, + "type": "struct Market", + "components": [ + { + "name": "asset_id", + "type": 12, + "typeArguments": null + }, + { + "name": "asset_decimals", + "type": 22, + "typeArguments": null + } + ], + "typeParameters": null + }, + { + "typeId": 16, + "type": "struct MarketCreateEvent", + "components": [ + { + "name": "asset_id", + "type": 12, + "typeArguments": null + }, + { + "name": "asset_decimals", + "type": 22, + "typeArguments": null + }, + { + "name": "timestamp", + "type": 23, + "typeArguments": null + }, + { + "name": "tx_id", + "type": 2, + "typeArguments": null + } + ], + "typeParameters": null + }, + { + "typeId": 17, + "type": "struct Order", + "components": [ + { + "name": "id", + "type": 2, + "typeArguments": null + }, + { + "name": "trader", + "type": 11, + "typeArguments": null + }, + { + "name": "base_token", + "type": 12, + "typeArguments": null + }, + { + "name": "base_size", + "type": 14, + "typeArguments": null + }, + { + "name": "base_price", + "type": 23, + "typeArguments": null + } + ], + "typeParameters": null + }, + { + "typeId": 18, + "type": "struct OrderChangeEvent", + "components": [ + { + "name": "order_id", + "type": 2, + "typeArguments": null + }, + { + "name": "sender", + "type": 5, + "typeArguments": null + }, + { + "name": "timestamp", + "type": 23, + "typeArguments": null + }, + { + "name": "identifier", + "type": 7, + "typeArguments": null + }, + { + "name": "tx_id", + "type": 2, + "typeArguments": null + }, + { + "name": "order", + "type": 6, + "typeArguments": [ + { + "name": "", + "type": 17, + "typeArguments": null + } + ] + } + ], + "typeParameters": null + }, + { + "typeId": 19, + "type": "struct RawVec", + "components": [ + { + "name": "ptr", + "type": 10, + "typeArguments": null + }, + { + "name": "cap", + "type": 23, + "typeArguments": null + } + ], + "typeParameters": [ + 9 + ] + }, + { + "typeId": 20, + "type": "struct TradeEvent", + "components": [ + { + "name": "base_token", + "type": 12, + "typeArguments": null + }, + { + "name": "order_matcher", + "type": 11, + "typeArguments": null + }, + { + "name": "seller", + "type": 11, + "typeArguments": null + }, + { + "name": "buyer", + "type": 11, + "typeArguments": null + }, + { + "name": "trade_size", + "type": 23, + "typeArguments": null + }, + { + "name": "trade_price", + "type": 23, + "typeArguments": null + }, + { + "name": "sell_order_id", + "type": 2, + "typeArguments": null + }, + { + "name": "buy_order_id", + "type": 2, + "typeArguments": null + }, + { + "name": "timestamp", + "type": 23, + "typeArguments": null + }, + { + "name": "tx_id", + "type": 2, + "typeArguments": null + } + ], + "typeParameters": null + }, + { + "typeId": 21, + "type": "struct Vec", + "components": [ + { + "name": "buf", + "type": 19, + "typeArguments": [ + { + "name": "", + "type": 9, + "typeArguments": null + } + ] + }, + { + "name": "len", + "type": 23, + "typeArguments": null + } + ], + "typeParameters": [ + 9 + ] + }, + { + "typeId": 22, + "type": "u32", + "components": null, + "typeParameters": null + }, + { + "typeId": 23, + "type": "u64", + "components": null, + "typeParameters": null + } + ], + "functions": [ + { + "inputs": [ + { + "name": "order_id", + "type": 2, + "typeArguments": null + } + ], + "name": "cancel_order", + "output": { + "name": "", + "type": 0, + "typeArguments": null + }, + "attributes": [ + { + "name": "storage", + "arguments": [ + "read", + "write" + ] + } + ] + }, + { + "inputs": [ + { + "name": "asset_id", + "type": 12, + "typeArguments": null + }, + { + "name": "asset_decimals", + "type": 22, + "typeArguments": null + } + ], + "name": "create_market", + "output": { + "name": "", + "type": 0, + "typeArguments": null + }, + "attributes": [ + { + "name": "storage", + "arguments": [ + "read", + "write" + ] + } + ] + }, + { + "inputs": [], + "name": "get_configurables", + "output": { + "name": "", + "type": 1, + "typeArguments": null + }, + "attributes": null + }, + { + "inputs": [ + { + "name": "asset_id", + "type": 12, + "typeArguments": null + } + ], + "name": "get_market_by_id", + "output": { + "name": "", + "type": 15, + "typeArguments": null + }, + "attributes": [ + { + "name": "storage", + "arguments": [ + "read" + ] + } + ] + }, + { + "inputs": [ + { + "name": "order", + "type": 2, + "typeArguments": null + } + ], + "name": "get_order_change_events_by_order", + "output": { + "name": "", + "type": 21, + "typeArguments": [ + { + "name": "", + "type": 18, + "typeArguments": null + } + ] + }, + "attributes": [ + { + "name": "storage", + "arguments": [ + "read" + ] + } + ] + }, + { + "inputs": [ + { + "name": "asset_id", + "type": 12, + "typeArguments": null + } + ], + "name": "market_exists", + "output": { + "name": "", + "type": 3, + "typeArguments": null + }, + "attributes": [ + { + "name": "storage", + "arguments": [ + "read" + ] + } + ] + }, + { + "inputs": [ + { + "name": "order_sell_id", + "type": 2, + "typeArguments": null + }, + { + "name": "order_buy_id", + "type": 2, + "typeArguments": null + } + ], + "name": "match_orders", + "output": { + "name": "", + "type": 0, + "typeArguments": null + }, + "attributes": [ + { + "name": "storage", + "arguments": [ + "read", + "write" + ] + } + ] + }, + { + "inputs": [ + { + "name": "base_token", + "type": 12, + "typeArguments": null + }, + { + "name": "base_size", + "type": 14, + "typeArguments": null + }, + { + "name": "base_price", + "type": 23, + "typeArguments": null + } + ], + "name": "open_order", + "output": { + "name": "", + "type": 2, + "typeArguments": null + }, + "attributes": [ + { + "name": "storage", + "arguments": [ + "read", + "write" + ] + }, + { + "name": "payable", + "arguments": [] + } + ] + }, + { + "inputs": [ + { + "name": "order", + "type": 2, + "typeArguments": null + } + ], + "name": "order_by_id", + "output": { + "name": "", + "type": 6, + "typeArguments": [ + { + "name": "", + "type": 17, + "typeArguments": null + } + ] + }, + "attributes": [ + { + "name": "storage", + "arguments": [ + "read" + ] + } + ] + }, + { + "inputs": [ + { + "name": "trader", + "type": 11, + "typeArguments": null + } + ], + "name": "orders_by_trader", + "output": { + "name": "", + "type": 21, + "typeArguments": [ + { + "name": "", + "type": 2, + "typeArguments": null + } + ] + }, + "attributes": [ + { + "name": "storage", + "arguments": [ + "read" + ] + } + ] + } + ], + "loggedTypes": [ + { + "logId": 0, + "loggedType": { + "name": "", + "type": 8, + "typeArguments": [] + } + }, + { + "logId": 1, + "loggedType": { + "name": "", + "type": 4, + "typeArguments": [] + } + }, + { + "logId": 2, + "loggedType": { + "name": "", + "type": 4, + "typeArguments": [] + } + }, + { + "logId": 3, + "loggedType": { + "name": "", + "type": 4, + "typeArguments": [] + } + }, + { + "logId": 4, + "loggedType": { + "name": "", + "type": 4, + "typeArguments": [] + } + }, + { + "logId": 5, + "loggedType": { + "name": "", + "type": 4, + "typeArguments": [] + } + }, + { + "logId": 6, + "loggedType": { + "name": "", + "type": 4, + "typeArguments": [] + } + }, + { + "logId": 7, + "loggedType": { + "name": "", + "type": 4, + "typeArguments": [] + } + }, + { + "logId": 8, + "loggedType": { + "name": "", + "type": 18, + "typeArguments": [] + } + }, + { + "logId": 9, + "loggedType": { + "name": "", + "type": 4, + "typeArguments": [] + } + }, + { + "logId": 10, + "loggedType": { + "name": "", + "type": 4, + "typeArguments": [] + } + }, + { + "logId": 11, + "loggedType": { + "name": "", + "type": 16, + "typeArguments": [] + } + }, + { + "logId": 12, + "loggedType": { + "name": "", + "type": 8, + "typeArguments": [] + } + }, + { + "logId": 13, + "loggedType": { + "name": "", + "type": 4, + "typeArguments": [] + } + }, + { + "logId": 14, + "loggedType": { + "name": "", + "type": 4, + "typeArguments": [] + } + }, + { + "logId": 15, + "loggedType": { + "name": "", + "type": 4, + "typeArguments": [] + } + }, + { + "logId": 16, + "loggedType": { + "name": "", + "type": 4, + "typeArguments": [] + } + }, + { + "logId": 17, + "loggedType": { + "name": "", + "type": 4, + "typeArguments": [] + } + }, + { + "logId": 18, + "loggedType": { + "name": "", + "type": 4, + "typeArguments": [] + } + }, + { + "logId": 19, + "loggedType": { + "name": "", + "type": 4, + "typeArguments": [] + } + }, + { + "logId": 20, + "loggedType": { + "name": "", + "type": 4, + "typeArguments": [] + } + }, + { + "logId": 21, + "loggedType": { + "name": "", + "type": 4, + "typeArguments": [] + } + }, + { + "logId": 22, + "loggedType": { + "name": "", + "type": 4, + "typeArguments": [] + } + }, + { + "logId": 23, + "loggedType": { + "name": "", + "type": 4, + "typeArguments": [] + } + }, + { + "logId": 24, + "loggedType": { + "name": "", + "type": 4, + "typeArguments": [] + } + }, + { + "logId": 25, + "loggedType": { + "name": "", + "type": 18, + "typeArguments": [] + } + }, + { + "logId": 26, + "loggedType": { + "name": "", + "type": 18, + "typeArguments": [] + } + }, + { + "logId": 27, + "loggedType": { + "name": "", + "type": 20, + "typeArguments": [] + } + }, + { + "logId": 28, + "loggedType": { + "name": "", + "type": 8, + "typeArguments": [] + } + }, + { + "logId": 29, + "loggedType": { + "name": "", + "type": 4, + "typeArguments": [] + } + }, + { + "logId": 30, + "loggedType": { + "name": "", + "type": 4, + "typeArguments": [] + } + }, + { + "logId": 31, + "loggedType": { + "name": "", + "type": 4, + "typeArguments": [] + } + }, + { + "logId": 32, + "loggedType": { + "name": "", + "type": 4, + "typeArguments": [] + } + }, + { + "logId": 33, + "loggedType": { + "name": "", + "type": 4, + "typeArguments": [] + } + }, + { + "logId": 34, + "loggedType": { + "name": "", + "type": 4, + "typeArguments": [] + } + }, + { + "logId": 35, + "loggedType": { + "name": "", + "type": 4, + "typeArguments": [] + } + }, + { + "logId": 36, + "loggedType": { + "name": "", + "type": 4, + "typeArguments": [] + } + }, + { + "logId": 37, + "loggedType": { + "name": "", + "type": 4, + "typeArguments": [] + } + }, + { + "logId": 38, + "loggedType": { + "name": "", + "type": 4, + "typeArguments": [] + } + }, + { + "logId": 39, + "loggedType": { + "name": "", + "type": 4, + "typeArguments": [] + } + }, + { + "logId": 40, + "loggedType": { + "name": "", + "type": 4, + "typeArguments": [] + } + }, + { + "logId": 41, + "loggedType": { + "name": "", + "type": 4, + "typeArguments": [] + } + }, + { + "logId": 42, + "loggedType": { + "name": "", + "type": 4, + "typeArguments": [] + } + }, + { + "logId": 43, + "loggedType": { + "name": "", + "type": 4, + "typeArguments": [] + } + }, + { + "logId": 44, + "loggedType": { + "name": "", + "type": 4, + "typeArguments": [] + } + }, + { + "logId": 45, + "loggedType": { + "name": "", + "type": 4, + "typeArguments": [] + } + }, + { + "logId": 46, + "loggedType": { + "name": "", + "type": 18, + "typeArguments": [] + } + } + ], + "messagesTypes": [], + "configurables": [ + { + "name": "QUOTE_TOKEN", + "configurableType": { + "name": "", + "type": 12, + "typeArguments": [] + }, + "offset": 115076 + }, + { + "name": "QUOTE_TOKEN_DECIMALS", + "configurableType": { + "name": "", + "type": 22, + "typeArguments": null + }, + "offset": 115012 + }, + { + "name": "PRICE_DECIMALS", + "configurableType": { + "name": "", + "type": 22, + "typeArguments": null + }, + "offset": 114996 + } + ] +} \ No newline at end of file diff --git a/contract/out/debug/orderbook-storage_slots.json b/contract/out/debug/orderbook-storage_slots.json new file mode 100644 index 0000000..0637a08 --- /dev/null +++ b/contract/out/debug/orderbook-storage_slots.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/scripts/README.md b/scripts/README.md new file mode 100644 index 0000000..538a966 --- /dev/null +++ b/scripts/README.md @@ -0,0 +1,14 @@ +## Running the scripts + +To run a script change into the `/scripts` directory and follow the example pattern to run your script. + +```bash +cargo run --bin