diff --git a/Cargo.lock b/Cargo.lock index 953e678..979021f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -15,18 +15,18 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "0.7.20" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" +checksum = "67fc08ce920c31afb70f013dcce1bfc3a3195de6a228474e45e1f145b36f8d04" dependencies = [ "memchr", ] [[package]] name = "anyhow" -version = "1.0.68" +version = "1.0.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61" +checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" [[package]] name = "arrayvec" @@ -34,108 +34,12 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" -[[package]] -name = "assert_matches" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" - -[[package]] -name = "async-stream" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad445822218ce64be7a341abfb0b1ea43b5c23aa83902542a4542e78309d8e5e" -dependencies = [ - "async-stream-impl", - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "async-stream-impl" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4655ae1a7b0cdf149156f780c5bf3f1352bc53cbd9e0a361a7ef7b22947e965" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "async-trait" -version = "0.1.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd7fce9ba8c3c042128ce72d8b2ddbf3a05747efb67ea0313c635e10bda47a2" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi 0.1.19", - "libc", - "winapi", -] - [[package]] name = "autocfg" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" -[[package]] -name = "axum" -version = "0.6.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fb79c228270dcf2426e74864cabc94babb5dbab01a4314e702d2f16540e1591" -dependencies = [ - "async-trait", - "axum-core", - "bitflags", - "bytes", - "futures-util", - "http", - "http-body", - "hyper", - "itoa", - "matchit", - "memchr", - "mime", - "percent-encoding", - "pin-project-lite", - "rustversion", - "serde", - "sync_wrapper", - "tower", - "tower-http", - "tower-layer", - "tower-service", -] - -[[package]] -name = "axum-core" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cae3e661676ffbacb30f1a824089a8c9150e71017f7e1e38f2aa32009188d34" -dependencies = [ - "async-trait", - "bytes", - "futures-util", - "http", - "http-body", - "mime", - "rustversion", - "tower-layer", - "tower-service", -] - [[package]] name = "base-factory" version = "2.3.0" @@ -199,30 +103,6 @@ version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b645a089122eccb6111b4f81cbc1a49f5900ac4666bb93ac027feaecf15607bf" -[[package]] -name = "bip32" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b30ed1d6f8437a487a266c8293aeb95b61a23261273e3e02912cdb8b68bf798b" -dependencies = [ - "bs58", - "hmac", - "k256", - "once_cell", - "pbkdf2", - "rand_core 0.6.4", - "ripemd", - "sha2 0.10.6", - "subtle", - "zeroize", -] - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - [[package]] name = "bitvec" version = "0.17.4" @@ -253,19 +133,19 @@ dependencies = [ [[package]] name = "borsh" -version = "0.9.3" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15bf3650200d8bffa99015595e10f1fbd17de07abbc25bb067da79e769939bfa" +checksum = "4114279215a005bc675e386011e594e1d9b800918cea18fcadadcce864a2046b" dependencies = [ "borsh-derive", - "hashbrown 0.11.2", + "hashbrown", ] [[package]] name = "borsh-derive" -version = "0.9.3" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6441c552f230375d18e3cc377677914d2ca2b0d36e52129fe15450a2dce46775" +checksum = "0754613691538d51f329cce9af41d7b7ca150bc973056f1156611489475f54f7" dependencies = [ "borsh-derive-internal", "borsh-schema-derive-internal", @@ -276,9 +156,9 @@ dependencies = [ [[package]] name = "borsh-derive-internal" -version = "0.9.3" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5449c28a7b352f2d1e592a8a28bf139bc71afb0764a14f3c02500935d8c44065" +checksum = "afb438156919598d2c7bad7e1c0adf3d26ed3840dbc010db1a882a65583ca2fb" dependencies = [ "proc-macro2", "quote", @@ -287,45 +167,31 @@ dependencies = [ [[package]] name = "borsh-schema-derive-internal" -version = "0.9.3" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdbd5696d8bfa21d53d9fe39a714a18538bad11492a42d066dbbc395fb1951c0" +checksum = "634205cc43f74a1b9046ef87c4540ebda95696ec0f315024860cad7c5b0f5ccd" dependencies = [ "proc-macro2", "quote", "syn", ] -[[package]] -name = "bs58" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" -dependencies = [ - "sha2 0.9.9", -] - -[[package]] -name = "bumpalo" -version = "3.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" - [[package]] name = "bytecheck" -version = "0.6.9" +version = "0.6.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d11cac2c12b5adc6570dad2ee1b87eff4955dac476fe12d81e5fdd352e52406f" +checksum = "13fe11640a23eb24562225322cd3e452b93a3d4091d62fab69c70542fcd17d1f" dependencies = [ "bytecheck_derive", "ptr_meta", + "simdutf8", ] [[package]] name = "bytecheck_derive" -version = "0.6.9" +version = "0.6.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13e576ebe98e605500b3c8041bb888e966653577172df6dd97398714eb30b9bf" +checksum = "e31225543cb46f81a7e224762764f4a6a0f097b1db0b175f69e8065efaa42de5" dependencies = [ "proc-macro2", "quote", @@ -340,18 +206,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c" -dependencies = [ - "serde", -] - -[[package]] -name = "cc" -version = "1.0.79" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" [[package]] name = "cfg-if" @@ -359,111 +216,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "config" -version = "0.13.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d379af7f68bfc21714c6c7dea883544201741d2ce8274bb12fa54f89507f52a7" -dependencies = [ - "async-trait", - "json5", - "lazy_static", - "nom", - "pathdiff", - "ron", - "rust-ini", - "serde", - "serde_json", - "toml", - "yaml-rust", -] - [[package]] name = "const-oid" version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cec318a675afcb6a1ea1d4340e2d377e56e47c266f28043ceccbf4412ddfdd3b" -[[package]] -name = "core-foundation" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "core-foundation-sys" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" - -[[package]] -name = "cosm-orc" -version = "3.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09d7b3a13272e1fac3bea1f95bafff21f737052cbb8e47fff66550a2dc71ce63" -dependencies = [ - "config", - "cosm-tome", - "erased-serde", - "log", - "serde", - "serde_json", - "thiserror", - "tokio", -] - -[[package]] -name = "cosm-tome" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3daaf99d2364465e81ac948e6c27ecdc63aab74ab948d9f526793009dacd9d28" -dependencies = [ - "async-trait", - "cosmrs", - "regex", - "serde", - "serde_json", - "thiserror", - "tonic", -] - -[[package]] -name = "cosmos-sdk-proto" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "673d31bd830c0772d78545de20d975129b6ab2f7db4e4e9313c3b8777d319194" -dependencies = [ - "prost 0.11.6", - "prost-types", - "tendermint-proto", - "tonic", -] - -[[package]] -name = "cosmrs" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fa07096219b1817432b8f1e47c22e928c64bbfd231fc08f0a98f0e7ddd602b7" -dependencies = [ - "bip32", - "cosmos-sdk-proto", - "ecdsa", - "eyre", - "getrandom", - "k256", - "rand_core 0.6.4", - "serde", - "serde_json", - "subtle-encoding", - "tendermint", - "tendermint-rpc", - "thiserror", -] - [[package]] name = "cosmwasm-crypto" version = "1.2.3" @@ -577,15 +335,6 @@ dependencies = [ "typenum", ] -[[package]] -name = "ct-logs" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1a816186fa68d9e426e3cb4ae4dff1fcd8e4a2c34b781bf7a822574a0d0aac8" -dependencies = [ - "sct", -] - [[package]] name = "curve25519-dalek" version = "3.2.0" @@ -616,9 +365,9 @@ dependencies = [ [[package]] name = "cw-multi-test" -version = "0.16.2" +version = "0.16.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2eb84554bbfa6b66736abcd6a9bfdf237ee0ecb83910f746dff7f799093c80a" +checksum = "2a18afd2e201221c6d72a57f0886ef2a22151bbc9e6db7af276fde8a91081042" dependencies = [ "anyhow", "cosmwasm-std", @@ -627,7 +376,7 @@ dependencies = [ "derivative", "itertools", "k256", - "prost 0.9.0", + "prost", "schemars", "serde", "thiserror", @@ -828,12 +577,6 @@ dependencies = [ "subtle", ] -[[package]] -name = "dlv-list" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0688c2a7f92e427f44895cd63841bff7b29f8d7a1648b9e7e07a4a365b2e1257" - [[package]] name = "downcast" version = "0.11.0" @@ -846,34 +589,6 @@ version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c9b0705efd4599c15a38151f4721f7bc388306f61084d3bfd50bd07fbca5cb60" -[[package]] -name = "e2e-tests" -version = "0.1.0" -dependencies = [ - "assert_matches", - "base-factory", - "base-minter", - "cosm-orc", - "cosm-tome", - "cosmwasm-std", - "cw-utils 0.16.0", - "cw721", - "cw721-base", - "env_logger", - "infinity-swap", - "itertools", - "once_cell", - "rand", - "serde", - "serde_json", - "sg-marketplace", - "sg-std", - "sg2", - "sg721", - "sg721-base", - "test-context", -] - [[package]] name = "ecdsa" version = "0.14.8" @@ -886,27 +601,6 @@ dependencies = [ "signature", ] -[[package]] -name = "ed25519" -version = "1.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91cff35c70bba8a626e3185d8cd48cc11b5437e1a5bcd15b9b5fa3c64b6dfee7" -dependencies = [ - "signature", -] - -[[package]] -name = "ed25519-dalek" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d" -dependencies = [ - "curve25519-dalek", - "ed25519", - "sha2 0.9.9", - "zeroize", -] - [[package]] name = "ed25519-zebra" version = "3.1.0" @@ -914,7 +608,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c24f403d068ad0b359e577a77f92392118be3f3c927538f2bb544a5ecd828c6" dependencies = [ "curve25519-dalek", - "hashbrown 0.12.3", + "hashbrown", "hex", "rand_core 0.6.4", "serde", @@ -924,9 +618,9 @@ dependencies = [ [[package]] name = "either" -version = "1.8.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" +checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" [[package]] name = "elliptic-curve" @@ -948,28 +642,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "env_logger" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7" -dependencies = [ - "atty", - "humantime", - "log", - "regex", - "termcolor", -] - -[[package]] -name = "erased-serde" -version = "0.3.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4ca605381c017ec7a5fef5e548f1cfaa419ed0f6df6367339300db74c92aa7d" -dependencies = [ - "serde", -] - [[package]] name = "ethereum-verify" version = "2.3.0" @@ -983,16 +655,6 @@ dependencies = [ "sha3", ] -[[package]] -name = "eyre" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c2b6b5a29c02cdc822728b7d7b8ae1bab3e3b05d44522770ddd49722eeac7eb" -dependencies = [ - "indenter", - "once_cell", -] - [[package]] name = "ff" version = "0.12.1" @@ -1003,16 +665,6 @@ dependencies = [ "subtle", ] -[[package]] -name = "flex-error" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c606d892c9de11507fa0dcffc116434f94e105d0bbdc4e405b61519464c49d7b" -dependencies = [ - "eyre", - "paste", -] - [[package]] name = "float-cmp" version = "0.9.0" @@ -1022,12 +674,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - [[package]] name = "form_urlencoded" version = "1.1.0" @@ -1049,95 +695,6 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c2141d6d6c8512188a7891b4b01590a45f6dac67afb4f255c4124dbb86d4eaa" -[[package]] -name = "futures" -version = "0.3.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13e2792b0ff0340399d58445b88fd9770e3489eff258a4cbc1523418f12abf84" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e5317663a9089767a1ec00a487df42e0ca174b61b4483213ac24448e4664df5" -dependencies = [ - "futures-core", - "futures-sink", -] - -[[package]] -name = "futures-core" -version = "0.3.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec90ff4d0fe1f57d600049061dc6bb68ed03c7d2fbd697274c41805dcb3f8608" - -[[package]] -name = "futures-executor" -version = "0.3.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8de0a35a6ab97ec8869e32a2473f4b1324459e14c29275d14b10cb1fd19b50e" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-io" -version = "0.3.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfb8371b6fb2aeb2d280374607aeabfc99d95c72edfe51692e42d3d7f0d08531" - -[[package]] -name = "futures-macro" -version = "0.3.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95a73af87da33b5acf53acfebdc339fe592ecf5357ac7c0a7734ab9d8c876a70" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "futures-sink" -version = "0.3.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f310820bb3e8cfd46c80db4d7fb8353e15dfff853a127158425f31e0be6c8364" - -[[package]] -name = "futures-task" -version = "0.3.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf79a1bf610b10f42aea489289c5a2c478a786509693b80cd39c44ccd936366" - -[[package]] -name = "futures-util" -version = "0.3.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c1d6de3acfef38d2be4b1f543f553131788603495be83da675e180c8d6b7bd1" -dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-macro", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "pin-utils", - "slab", -] - [[package]] name = "generic-array" version = "0.14.6" @@ -1155,10 +712,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" dependencies = [ "cfg-if", - "js-sys", "libc", "wasi", - "wasm-bindgen", ] [[package]] @@ -1173,83 +728,12 @@ dependencies = [ ] [[package]] -name = "h2" -version = "0.3.15" +name = "hashbrown" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f9f29bc9dda355256b2916cf526ab02ce0aeaaaf2bad60d65ef3f12f11dd0f4" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http", - "indexmap", - "slab", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "hashbrown" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" -dependencies = [ - "ahash", -] - -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" -dependencies = [ - "ahash", -] - -[[package]] -name = "headers" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3e372db8e5c0d213e0cd0b9be18be2aca3d44cf2fe30a9d46a65581cd454584" -dependencies = [ - "base64", - "bitflags", - "bytes", - "headers-core", - "http", - "httpdate", - "mime", - "sha1", -] - -[[package]] -name = "headers-core" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429" -dependencies = [ - "http", -] - -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - -[[package]] -name = "hermit-abi" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" -dependencies = [ - "libc", + "ahash", ] [[package]] @@ -1267,125 +751,6 @@ dependencies = [ "digest 0.10.6", ] -[[package]] -name = "http" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - -[[package]] -name = "http-body" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" -dependencies = [ - "bytes", - "http", - "pin-project-lite", -] - -[[package]] -name = "http-range-header" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bfe8eed0a9285ef776bb792479ea3834e8b94e13d615c2f66d03dd50a435a29" - -[[package]] -name = "httparse" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" - -[[package]] -name = "httpdate" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" - -[[package]] -name = "humantime" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" - -[[package]] -name = "hyper" -version = "0.14.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e011372fa0b68db8350aa7a248930ecc7839bf46d8485577d69f117a75f164c" -dependencies = [ - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "socket2", - "tokio", - "tower-service", - "tracing", - "want", -] - -[[package]] -name = "hyper-proxy" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca815a891b24fdfb243fa3239c86154392b0953ee584aa1a2a1f66d20cbe75cc" -dependencies = [ - "bytes", - "futures", - "headers", - "http", - "hyper", - "hyper-rustls", - "rustls-native-certs", - "tokio", - "tokio-rustls", - "tower-service", - "webpki", -] - -[[package]] -name = "hyper-rustls" -version = "0.22.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f9f7a97316d44c0af9b0301e65010573a853a9fc97046d7331d7f6bc0fd5a64" -dependencies = [ - "ct-logs", - "futures-util", - "hyper", - "log", - "rustls", - "rustls-native-certs", - "tokio", - "tokio-rustls", - "webpki", - "webpki-roots", -] - -[[package]] -name = "hyper-timeout" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" -dependencies = [ - "hyper", - "pin-project-lite", - "tokio", - "tokio-io-timeout", -] - [[package]] name = "idna" version = "0.3.0" @@ -1397,19 +762,17 @@ dependencies = [ ] [[package]] -name = "indenter" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" - -[[package]] -name = "indexmap" -version = "1.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" +name = "infinity-index" +version = "0.1.0" dependencies = [ - "autocfg", - "hashbrown 0.12.3", + "cosmwasm-schema", + "cosmwasm-std", + "cw-storage-macro", + "cw-storage-plus 0.16.0", + "cw2 0.16.0", + "sg-std", + "sha2 0.10.6", + "thiserror", ] [[package]] @@ -1425,56 +788,42 @@ dependencies = [ ] [[package]] -name = "infinity-marketplace-adapter" +name = "infinity-pool" version = "0.1.0" dependencies = [ - "anyhow", "cosmwasm-schema", "cosmwasm-std", - "cosmwasm-storage", "cw-storage-plus 0.16.0", "cw-utils 0.16.0", "cw2 0.16.0", - "cw721", - "cw721-base", - "infinity-macros", + "infinity-index", "infinity-shared", - "infinity-swap", - "sg-marketplace", "sg-marketplace-common", "sg-std", - "sg1", - "sg2", - "sg721", - "sg721-base", "thiserror", ] [[package]] -name = "infinity-shared" +name = "infinity-router" version = "0.1.0" dependencies = [ - "anyhow", "cosmwasm-schema", "cosmwasm-std", - "cosmwasm-storage", + "cw-storage-macro", "cw-storage-plus 0.16.0", - "cw-utils 0.16.0", "cw2 0.16.0", "cw721", - "cw721-base", - "infinity-swap", - "sg-marketplace", + "infinity-index", + "infinity-pool", + "infinity-shared", + "sg-marketplace-common", "sg-std", - "sg1", - "sg2", - "sg721", - "sg721-base", + "sha2 0.10.6", "thiserror", ] [[package]] -name = "infinity-swap" +name = "infinity-shared" version = "0.1.0" dependencies = [ "anyhow", @@ -1510,26 +859,6 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" -[[package]] -name = "js-sys" -version = "0.3.61" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" -dependencies = [ - "wasm-bindgen", -] - -[[package]] -name = "json5" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96b0db21af676c1ce64250b5f40f3ce2cf27e4e47cb91ed91eb6fe9350b430c1" -dependencies = [ - "pest", - "pest_derive", - "serde", -] - [[package]] name = "k256" version = "0.11.6" @@ -1540,14 +869,13 @@ dependencies = [ "ecdsa", "elliptic-curve", "sha2 0.10.6", - "sha3", ] [[package]] name = "keccak" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3afef3b6eff9ce9d8ff9b3601125eec7f0c8cbac7abd14f355d053fa56c98768" +checksum = "8f6d5ed8676d904364de097082f4e7d240b571b67989ced0240f08b7f966f940" dependencies = [ "cpufeatures", ] @@ -1564,57 +892,12 @@ version = "0.2.139" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" -[[package]] -name = "linked-hash-map" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" - -[[package]] -name = "log" -version = "0.4.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "matchit" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b87248edafb776e59e6ee64a79086f65890d3510f2c656c000bf2a7e8a0aea40" - [[package]] name = "memchr" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" -[[package]] -name = "mime" -version = "0.3.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" - -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - -[[package]] -name = "mio" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" -dependencies = [ - "libc", - "log", - "wasi", - "windows-sys 0.45.0", -] - [[package]] name = "mockall" version = "0.11.4" @@ -1642,33 +925,12 @@ dependencies = [ "syn", ] -[[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - [[package]] name = "normalize-line-endings" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" -[[package]] -name = "num-derive" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "num-traits" version = "0.2.15" @@ -1678,16 +940,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "num_cpus" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" -dependencies = [ - "hermit-abi 0.2.6", - "libc", -] - [[package]] name = "once_cell" version = "1.17.0" @@ -1700,152 +952,12 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" -[[package]] -name = "openssl-probe" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" - -[[package]] -name = "ordered-multimap" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccd746e37177e1711c20dd619a1620f34f5c8b569c53590a72dedd5344d8924a" -dependencies = [ - "dlv-list", - "hashbrown 0.12.3", -] - -[[package]] -name = "paste" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d01a5bd0424d00070b0098dd17ebca6f961a959dead1dbcbbbc1d1cd8d3deeba" - -[[package]] -name = "pathdiff" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" - -[[package]] -name = "pbkdf2" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" -dependencies = [ - "digest 0.10.6", -] - -[[package]] -name = "peg" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07c0b841ea54f523f7aa556956fbd293bcbe06f2e67d2eb732b7278aaf1d166a" -dependencies = [ - "peg-macros", - "peg-runtime", -] - -[[package]] -name = "peg-macros" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5aa52829b8decbef693af90202711348ab001456803ba2a98eb4ec8fb70844c" -dependencies = [ - "peg-runtime", - "proc-macro2", - "quote", -] - -[[package]] -name = "peg-runtime" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c719dcf55f09a3a7e764c6649ab594c18a177e3599c467983cdf644bfc0a4088" - [[package]] name = "percent-encoding" version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" -[[package]] -name = "pest" -version = "2.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "028accff104c4e513bad663bbcd2ad7cfd5304144404c31ed0a77ac103d00660" -dependencies = [ - "thiserror", - "ucd-trie", -] - -[[package]] -name = "pest_derive" -version = "2.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ac3922aac69a40733080f53c1ce7f91dcf57e1a5f6c52f421fadec7fbdc4b69" -dependencies = [ - "pest", - "pest_generator", -] - -[[package]] -name = "pest_generator" -version = "2.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d06646e185566b5961b4058dd107e0a7f56e77c3f484549fb119867773c0f202" -dependencies = [ - "pest", - "pest_meta", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "pest_meta" -version = "2.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6f60b2ba541577e2a0c307c8f39d1439108120eb7903adeb6497fa880c59616" -dependencies = [ - "once_cell", - "pest", - "sha2 0.10.6", -] - -[[package]] -name = "pin-project" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - [[package]] name = "pkcs8" version = "0.9.0" @@ -1917,17 +1029,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "444879275cb4fd84958b1a1d5420d15e6fcf7c235fe47f053c9c2a80aceb6001" dependencies = [ "bytes", - "prost-derive 0.9.0", -] - -[[package]] -name = "prost" -version = "0.11.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21dc42e00223fc37204bd4aa177e69420c604ca4a183209a8f9de30c6d934698" -dependencies = [ - "bytes", - "prost-derive 0.11.6", + "prost-derive", ] [[package]] @@ -1943,29 +1045,6 @@ dependencies = [ "syn", ] -[[package]] -name = "prost-derive" -version = "0.11.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bda8c0881ea9f722eb9629376db3d0b903b462477c1aafcb0566610ac28ac5d" -dependencies = [ - "anyhow", - "itertools", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "prost-types" -version = "0.11.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e0526209433e96d83d750dd81a99118edbc55739e7e61a46764fd2ad537788" -dependencies = [ - "bytes", - "prost 0.11.6", -] - [[package]] name = "ptr_meta" version = "0.1.4" @@ -2048,9 +1127,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.7.1" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733" +checksum = "af83e617f331cc6ae2da5443c602dfa5af81e517212d9d611a5b3ba1777b5370" dependencies = [ "aho-corasick", "memchr", @@ -2059,15 +1138,15 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.28" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" +checksum = "a5996294f19bd3aae0453a862ad728f60e6600695733dd5df01da90c54363a3c" [[package]] name = "rend" -version = "0.3.6" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79af64b4b6362ffba04eef3a4e10829718a4896dac19daa741851c86781edf95" +checksum = "581008d2099240d37fb08d77ad713bcaec2c4d89d50b5b21a8bb1996bbab68ab" dependencies = [ "bytecheck", ] @@ -2083,49 +1162,14 @@ dependencies = [ "zeroize", ] -[[package]] -name = "ring" -version = "0.16.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" -dependencies = [ - "cc", - "libc", - "once_cell", - "spin", - "untrusted", - "web-sys", - "winapi", -] - -[[package]] -name = "ripemd" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f" -dependencies = [ - "digest 0.10.6", -] - -[[package]] -name = "ripemd160" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eca4ecc81b7f313189bf73ce724400a07da2a6dac19588b03c8bd76a2dcc251" -dependencies = [ - "block-buffer 0.9.0", - "digest 0.9.0", - "opaque-debug", -] - [[package]] name = "rkyv" -version = "0.7.39" +version = "0.7.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cec2b3485b07d96ddfd3134767b8a447b45ea4eb91448d0a35180ec0ffd5ed15" +checksum = "21499ed91807f07ae081880aabb2ccc0235e9d88011867d984525e9a4c3cfa3e" dependencies = [ "bytecheck", - "hashbrown 0.12.3", + "hashbrown", "ptr_meta", "rend", "rkyv_derive", @@ -2134,41 +1178,20 @@ dependencies = [ [[package]] name = "rkyv_derive" -version = "0.7.39" +version = "0.7.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6eaedadc88b53e36dd32d940ed21ae4d850d5916f2581526921f553a72ac34c4" +checksum = "ac1c672430eb41556291981f45ca900a0239ad007242d1cb4b4167af842db666" dependencies = [ "proc-macro2", "quote", "syn", ] -[[package]] -name = "ron" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88073939a61e5b7680558e6be56b419e208420c2adb92be54921fa6b72283f1a" -dependencies = [ - "base64", - "bitflags", - "serde", -] - -[[package]] -name = "rust-ini" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6d5f2436026b4f6e79dc829837d467cc7e9a55ee40e750d716713540715a2df" -dependencies = [ - "cfg-if", - "ordered-multimap", -] - [[package]] name = "rust_decimal" -version = "1.28.0" +version = "1.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fe32e8c89834541077a5c5bbe5691aa69324361e27e6aeb3552a737db4a70c8" +checksum = "26bd36b60561ee1fb5ec2817f198b6fd09fa571c897a5e86d1487cfc2b096dfc" dependencies = [ "arrayvec", "borsh", @@ -2182,61 +1205,12 @@ dependencies = [ "serde_json", ] -[[package]] -name = "rustls" -version = "0.19.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35edb675feee39aec9c99fa5ff985081995a06d594114ae14cbe797ad7b7a6d7" -dependencies = [ - "base64", - "log", - "ring", - "sct", - "webpki", -] - -[[package]] -name = "rustls-native-certs" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a07b7c1885bd8ed3831c289b7870b13ef46fe0e856d288c30d9cc17d75a2092" -dependencies = [ - "openssl-probe", - "rustls", - "schannel", - "security-framework", -] - -[[package]] -name = "rustversion" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5583e89e108996506031660fe09baa5011b9dd0341b89029313006d1fb508d70" - [[package]] name = "ryu" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "schannel" -version = "0.1.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3" -dependencies = [ - "windows-sys 0.42.0", -] - [[package]] name = "schemars" version = "0.8.11" @@ -2261,16 +1235,6 @@ dependencies = [ "syn", ] -[[package]] -name = "sct" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b362b83898e0e69f38515b82ee15aa80636befe47c3b6d3d89a911e78fc228ce" -dependencies = [ - "ring", - "untrusted", -] - [[package]] name = "seahash" version = "4.1.0" @@ -2291,29 +1255,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "security-framework" -version = "2.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a332be01508d814fed64bf28f798a146d73792121129962fdf335bb3c49a4254" -dependencies = [ - "bitflags", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31c9bb296072e961fcbd8853511dd39c2d8be2deb1e17c6860b1d30732b323b4" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "semver" version = "1.0.16" @@ -2338,15 +1279,6 @@ dependencies = [ "serde", ] -[[package]] -name = "serde_bytes" -version = "0.11.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "416bda436f9aab92e02c8e10d49a15ddd339cea90b6e340fe51ed97abb548294" -dependencies = [ - "serde", -] - [[package]] name = "serde_derive" version = "1.0.152" @@ -2380,17 +1312,6 @@ dependencies = [ "serde", ] -[[package]] -name = "serde_repr" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a5ec9fa74a20ebbe5d9ac23dac1fc96ba0ecfe9f50f2843b52e537b10fbcb4e" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "sg-controllers" version = "2.3.0" @@ -2436,7 +1357,6 @@ dependencies = [ [[package]] name = "sg-marketplace" version = "1.4.0" -source = "git+https://github.com/tasiov/marketplace?branch=infinity-marketplace-changes#5ad284b5e1dddf84a59f22457724043bc7d4a5bf" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -2460,7 +1380,6 @@ dependencies = [ [[package]] name = "sg-marketplace-common" version = "1.0.0" -source = "git+https://github.com/tasiov/marketplace?branch=infinity-marketplace-changes#5ad284b5e1dddf84a59f22457724043bc7d4a5bf" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -2643,17 +1562,6 @@ dependencies = [ "sg721-base", ] -[[package]] -name = "sha1" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest 0.10.6", -] - [[package]] name = "sha2" version = "0.9.9" @@ -2680,9 +1588,9 @@ dependencies = [ [[package]] name = "sha3" -version = "0.10.6" +version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdf0c33fae925bdc080598b84bc15c55e7b9a4a43b3c704da051f977469691c9" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" dependencies = [ "digest 0.10.6", "keccak", @@ -2709,29 +1617,10 @@ dependencies = [ ] [[package]] -name = "slab" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" -dependencies = [ - "autocfg", -] - -[[package]] -name = "socket2" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "spin" -version = "0.5.2" +name = "simdutf8" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a" [[package]] name = "spki" @@ -2755,176 +1644,22 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" -[[package]] -name = "subtle-encoding" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dcb1ed7b8330c5eed5441052651dd7a12c75e2ed88f2ec024ae1fa3a5e59945" -dependencies = [ - "zeroize", -] - [[package]] name = "syn" version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "sync_wrapper" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" - -[[package]] -name = "synstructure" -version = "0.12.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "unicode-xid", -] - -[[package]] -name = "tendermint" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baa1d2d0ec1b531ba7d196f0dbee5e78ed2a82bfba928e88dff64aeec0b26073" -dependencies = [ - "async-trait", - "bytes", - "ed25519", - "ed25519-dalek", - "flex-error", - "futures", - "k256", - "num-traits", - "once_cell", - "prost 0.11.6", - "prost-types", - "ripemd160", - "serde", - "serde_bytes", - "serde_json", - "serde_repr", - "sha2 0.9.9", - "signature", - "subtle", - "subtle-encoding", - "tendermint-proto", - "time", - "zeroize", -] - -[[package]] -name = "tendermint-config" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "202a2f19502c03b353d8157694ed24fbc58c3dd64a92a5b0cb80b79c82af5be4" -dependencies = [ - "flex-error", - "serde", - "serde_json", - "tendermint", - "toml", - "url", -] - -[[package]] -name = "tendermint-proto" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "974d6330a19dfa6720e9f663fc59101d207a817db3f9c730d3f31caaa565b574" -dependencies = [ - "bytes", - "flex-error", - "num-derive", - "num-traits", - "prost 0.11.6", - "prost-types", - "serde", - "serde_bytes", - "subtle-encoding", - "time", -] - -[[package]] -name = "tendermint-rpc" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5d87fa5429bd2ee39c4809dd546096daf432de9b71157bc12c182ab5bae7ea7" -dependencies = [ - "async-trait", - "bytes", - "flex-error", - "futures", - "getrandom", - "http", - "hyper", - "hyper-proxy", - "hyper-rustls", - "peg", - "pin-project", - "serde", - "serde_bytes", - "serde_json", - "subtle", - "subtle-encoding", - "tendermint", - "tendermint-config", - "tendermint-proto", - "thiserror", - "time", - "tokio", - "tracing", - "url", - "uuid", - "walkdir", -] - -[[package]] -name = "termcolor" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "termtree" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76" - -[[package]] -name = "test-context" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "055831a02a4f5aa28fede67f2902014273eb8c21b958ac5ebbd59b71ef30dbc3" -dependencies = [ - "async-trait", - "futures", - "test-context-macros", + "proc-macro2", + "quote", + "unicode-ident", ] [[package]] -name = "test-context-macros" -version = "0.1.4" +name = "termtree" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8901a55b0a7a06ebc4a674dcca925170da8e613fa3b163a1df804ed10afb154d" -dependencies = [ - "quote", - "syn", -] +checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76" [[package]] name = "test-suite" @@ -2977,32 +1712,6 @@ dependencies = [ "syn", ] -[[package]] -name = "time" -version = "0.3.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53250a3b3fed8ff8fd988587d8925d26a83ac3845d9e03b220b37f34c2b8d6c2" -dependencies = [ - "serde", - "time-core", - "time-macros", -] - -[[package]] -name = "time-core" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" - -[[package]] -name = "time-macros" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a460aeb8de6dcb0f381e1ee05f1cd56fcf5a5f6eb8187ff3d8f0b11078d38b7c" -dependencies = [ - "time-core", -] - [[package]] name = "tinyvec" version = "1.6.0" @@ -3018,81 +1727,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" -[[package]] -name = "tokio" -version = "1.25.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8e00990ebabbe4c14c08aca901caed183ecd5c09562a12c824bb53d3c3fd3af" -dependencies = [ - "autocfg", - "bytes", - "libc", - "memchr", - "mio", - "num_cpus", - "pin-project-lite", - "socket2", - "tokio-macros", - "windows-sys 0.42.0", -] - -[[package]] -name = "tokio-io-timeout" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf" -dependencies = [ - "pin-project-lite", - "tokio", -] - -[[package]] -name = "tokio-macros" -version = "1.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "tokio-rustls" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc6844de72e57df1980054b38be3a9f4702aba4858be64dd700181a8a6d0e1b6" -dependencies = [ - "rustls", - "tokio", - "webpki", -] - -[[package]] -name = "tokio-stream" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fb52b74f05dbf495a8fba459fdc331812b96aa086d9eb78101fa0d4569c3313" -dependencies = [ - "futures-core", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "tokio-util" -version = "0.7.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5427d89453009325de0d8f342c9490009f76e999cb7672d77e46267448f7e6b2" -dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "pin-project-lite", - "tokio", - "tracing", -] - [[package]] name = "toml" version = "0.5.11" @@ -3102,150 +1736,12 @@ dependencies = [ "serde", ] -[[package]] -name = "tonic" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f219fad3b929bef19b1f86fbc0358d35daed8f2cac972037ac0dc10bbb8d5fb" -dependencies = [ - "async-stream", - "async-trait", - "axum", - "base64", - "bytes", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "hyper", - "hyper-timeout", - "percent-encoding", - "pin-project", - "prost 0.11.6", - "prost-derive 0.11.6", - "tokio", - "tokio-stream", - "tokio-util", - "tower", - "tower-layer", - "tower-service", - "tracing", - "tracing-futures", -] - -[[package]] -name = "tower" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" -dependencies = [ - "futures-core", - "futures-util", - "indexmap", - "pin-project", - "pin-project-lite", - "rand", - "slab", - "tokio", - "tokio-util", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "tower-http" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f873044bf02dd1e8239e9c1293ea39dad76dc594ec16185d0a1bf31d8dc8d858" -dependencies = [ - "bitflags", - "bytes", - "futures-core", - "futures-util", - "http", - "http-body", - "http-range-header", - "pin-project-lite", - "tower", - "tower-layer", - "tower-service", -] - -[[package]] -name = "tower-layer" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" - -[[package]] -name = "tower-service" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" - -[[package]] -name = "tracing" -version = "0.1.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" -dependencies = [ - "cfg-if", - "log", - "pin-project-lite", - "tracing-attributes", - "tracing-core", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "tracing-core" -version = "0.1.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" -dependencies = [ - "once_cell", -] - -[[package]] -name = "tracing-futures" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" -dependencies = [ - "pin-project", - "tracing", -] - -[[package]] -name = "try-lock" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" - [[package]] name = "typenum" version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" -[[package]] -name = "ucd-trie" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81" - [[package]] name = "uint" version = "0.9.5" @@ -3279,12 +1775,6 @@ dependencies = [ "tinyvec", ] -[[package]] -name = "unicode-xid" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" - [[package]] name = "unit-tests" version = "0.1.0" @@ -3299,9 +1789,10 @@ dependencies = [ "cw2 0.16.0", "cw721", "cw721-base", - "infinity-marketplace-adapter", + "infinity-index", + "infinity-pool", + "infinity-router", "infinity-shared", - "infinity-swap", "itertools", "mockall", "sg-marketplace", @@ -3317,12 +1808,6 @@ dependencies = [ "vending-minter", ] -[[package]] -name = "untrusted" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" - [[package]] name = "url" version = "2.3.1" @@ -3334,12 +1819,6 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "uuid" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" - [[package]] name = "vending-factory" version = "2.3.0" @@ -3398,116 +1877,12 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" -[[package]] -name = "walkdir" -version = "2.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" -dependencies = [ - "same-file", - "winapi", - "winapi-util", -] - -[[package]] -name = "want" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" -dependencies = [ - "log", - "try-lock", -] - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" -[[package]] -name = "wasm-bindgen" -version = "0.2.84" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" -dependencies = [ - "cfg-if", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.84" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" -dependencies = [ - "bumpalo", - "log", - "once_cell", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.84" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.84" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.84" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" - -[[package]] -name = "web-sys" -version = "0.3.61" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "webpki" -version = "0.21.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8e38c0608262c46d4a56202ebabdeb094cef7e560ca7a226c6bf055188aa4ea" -dependencies = [ - "ring", - "untrusted", -] - -[[package]] -name = "webpki-roots" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aabe153544e473b775453675851ecc86863d2a81d786d741f6b76778f2a48940" -dependencies = [ - "webpki", -] - [[package]] name = "whitelist-immutable" version = "2.3.0" @@ -3527,144 +1902,8 @@ dependencies = [ "thiserror", ] -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-util" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" -dependencies = [ - "winapi", -] - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows-sys" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows-sys" -version = "0.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-targets" -version = "0.42.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" - -[[package]] -name = "windows_i686_gnu" -version = "0.42.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" - -[[package]] -name = "windows_i686_msvc" -version = "0.42.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" - -[[package]] -name = "yaml-rust" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" -dependencies = [ - "linked-hash-map", -] - [[package]] name = "zeroize" version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c394b5bd0c6f669e7275d9c20aa90ae064cb22e75a1cad54e1b34088034b149f" -dependencies = [ - "zeroize_derive", -] - -[[package]] -name = "zeroize_derive" -version = "1.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44bf07cb3e50ea2003396695d58bf46bc9887a1f362260446fad6bc4e79bd36c" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "synstructure", -] diff --git a/Cargo.toml b/Cargo.toml index 9dbf179..0e0ab7e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,25 +10,32 @@ authors = ["Tasio tasiovictoria@ujulabs.com"] license = "BUSL-1.1" [workspace.dependencies] -infinity-macros = { path = "./packages/infinity-macros" } +infinity-router = { path = "./contracts/infinity-router" } +infinity-index = { path = "./contracts/infinity-index" } +infinity-pool = { path = "./contracts/infinity-pool" } infinity-shared = { path = "./packages/infinity-shared" } -infinity-swap = { path = "./contracts/infinity-swap" } -infinity-marketplace-adapter = { path = "./contracts/infinity-marketplace-adapter" } -cosmwasm-schema = "1.2.1" -cosmwasm-std = "1.2.1" -cosmwasm-storage = "1.2.1" +# infinity-macros = { path = "./packages/infinity-macros" } +# infinity-swap = { path = "./contracts/infinity-swap" } +# infinity-marketplace-adapter = { path = "./contracts/infinity-marketplace-adapter" } +cosmwasm-std = { version = "1.2", features = ["staking", "stargate", "ibc3", "cosmwasm_1_1", "cosmwasm_1_2"] } +cosmwasm-schema = "1.2" +cosmwasm-storage = "1.2" cw-storage-plus = "0.16.0" +cw-storage-macro = "0.16.0" cw-utils = "0.16.0" cw2 = "0.16.0" cw721-base = { version = "0.16.0", features = ["library"] } cw721 = "0.16.0" -sg1 = "2.1.0" -sg2 = "2.1.0" -sg721-base = { version = "2.1.0", features = ["library"] } -sg721 = { version = "2.1.0", features = ["library"] } -sg-std = "2.1.0" -sg-marketplace = { git = "https://github.com/tasiov/marketplace", branch = "infinity-marketplace-changes", features = ["library"] } -sg-marketplace-common = { git = "https://github.com/tasiov/marketplace", branch = "infinity-marketplace-changes" } +sg1 = { version = "2.1" } +sg2 = { version = "2.1" } +sg721-base = { version = "2.1", features = ["library"] } +sg721 = { version = "2.1", features = ["library"] } +sg-std = { version = "2.1" } +# sg-marketplace = { git = "https://github.com/tasiov/marketplace", branch = "infinity-marketplace-changes", features = ["library"] } +# sg-marketplace-common = { git = "https://github.com/tasiov/marketplace", branch = "infinity-marketplace-changes" } +sg-marketplace = { path = "../marketplace/contracts/marketplace", features = ["library"] } +sg-marketplace-common = { path = "../marketplace/packages/sg-marketplace-common" } +sha2 = "0.10" thiserror = { version = "1.0.31" } anyhow = "1.0.51" proc-macro2 = "1.0" @@ -38,12 +45,13 @@ syn = { version = "1.0", features = ["derive"] } # dev-dependencies itertools = "0.10.5" cw-multi-test = "0.16.0" -sg-multi-test = "2.1.0" -test-suite = "2.1.0" -base-minter = "2.1.0" -base-factory = "2.1.0" -vending-minter = "2.1.0" -vending-factory = "2.1.0" +# sg-multi-test = "2.3" +sg-multi-test = { version = "2.1" } +test-suite = { version = "2.1" } +base-minter = { version = "2.1" } +base-factory = { version = "2.1" } +vending-minter = { version = "2.1" } +vending-factory = { version = "2.1" } mockall = "0.11.4" cosm-orc = { version = "3.0.1" } cosm-tome = { version = "0.1.1" } @@ -55,9 +63,9 @@ test-context = "0.1.4" once_cell = "1.13.0" rand = "0.8" -[profile.release.package.infinity-swap] -codegen-units = 1 -incremental = false +# [profile.release.package.infinity-swap] +# codegen-units = 1 +# incremental = false [profile.release] rpath = false diff --git a/contracts/infinity-swap/Cargo.toml b/contracts/infinity-index/Cargo.toml similarity index 55% rename from contracts/infinity-swap/Cargo.toml rename to contracts/infinity-index/Cargo.toml index 2a25696..8493159 100644 --- a/contracts/infinity-swap/Cargo.toml +++ b/contracts/infinity-index/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "infinity-swap" +name = "infinity-index" version = { workspace = true } edition = { workspace = true } repository = { workspace = true } @@ -21,20 +21,26 @@ backtraces = ["cosmwasm-std/backtraces"] library = [] [dependencies] +# infinity-macros = { workspace = true } +# infinity-shared = { workspace = true } +# infinity-swap = { workspace = true } +# infinity-pool = { workspace = true } cosmwasm-std = { workspace = true } cosmwasm-schema = { workspace = true } -cosmwasm-storage = { workspace = true } cw-storage-plus = { workspace = true } -cw-utils = { workspace = true } +cw-storage-macro = { workspace = true } +# cosmwasm-storage = { workspace = true } +# cw-utils = { workspace = true } cw2 = { workspace = true } thiserror = { workspace = true } -anyhow = { workspace = true } -sg1 = { workspace = true } -sg2 = { workspace = true } -sg721-base = { workspace = true } -sg721 = { workspace = true } +# anyhow = { workspace = true } +# sg1 = { workspace = true } +# sg2 = { workspace = true } +# sg721-base = { workspace = true } +# sg721 = { workspace = true } sg-std = { workspace = true } -sg-marketplace = { workspace = true } -cw721-base = { workspace = true } -cw721 = { workspace = true } - +# sg-marketplace = { workspace = true } +# sg-marketplace-common = { workspace = true } +sha2 = { workspace = true } +# cw721-base = { workspace = true } +# cw721 = { workspace = true } \ No newline at end of file diff --git a/contracts/infinity-index/src/error.rs b/contracts/infinity-index/src/error.rs new file mode 100644 index 0000000..7155f59 --- /dev/null +++ b/contracts/infinity-index/src/error.rs @@ -0,0 +1,8 @@ +use cosmwasm_std::StdError; +use thiserror::Error; + +#[derive(Error, Debug, PartialEq)] +pub enum ContractError { + #[error("{0}")] + Std(#[from] StdError), +} diff --git a/contracts/infinity-index/src/execute.rs b/contracts/infinity-index/src/execute.rs new file mode 100644 index 0000000..736a3fe --- /dev/null +++ b/contracts/infinity-index/src/execute.rs @@ -0,0 +1,93 @@ +use crate::msg::ExecuteMsg; +use crate::state::PoolQuote; +use crate::{ + error::ContractError, + state::{buy_from_pool_quotes, sell_to_pool_quotes}, +}; + +use cosmwasm_std::{Addr, DepsMut, Env, MessageInfo, Uint128}; +use sg_std::Response; + +#[cfg(not(feature = "library"))] +use cosmwasm_std::entry_point; + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn execute( + deps: DepsMut, + env: Env, + info: MessageInfo, + msg: ExecuteMsg, +) -> Result { + let api = deps.api; + + match msg { + ExecuteMsg::UpdateBuyFromPoolQuote { + collection, + quote_price, + } => execute_update_buy_from_pool_quote( + deps, + env, + info, + api.addr_validate(&collection)?, + quote_price, + ), + ExecuteMsg::UpdateSellToPoolQuote { + collection, + quote_price, + } => execute_update_sell_to_pool_quote( + deps, + env, + info, + api.addr_validate(&collection)?, + quote_price, + ), + } +} + +pub fn execute_update_buy_from_pool_quote( + deps: DepsMut, + env: Env, + info: MessageInfo, + collection: Addr, + quote_price: Option, +) -> Result { + if let Some(_quote_price) = quote_price { + buy_from_pool_quotes().save( + deps.storage, + info.sender.clone(), + &PoolQuote { + pool: info.sender, + collection, + quote_price: _quote_price, + }, + )?; + } else { + buy_from_pool_quotes().remove(deps.storage, info.sender)?; + } + + Ok(Response::default()) +} + +pub fn execute_update_sell_to_pool_quote( + deps: DepsMut, + env: Env, + info: MessageInfo, + collection: Addr, + quote_price: Option, +) -> Result { + if let Some(_quote_price) = quote_price { + sell_to_pool_quotes().save( + deps.storage, + info.sender.clone(), + &PoolQuote { + pool: info.sender, + collection, + quote_price: _quote_price, + }, + )?; + } else { + sell_to_pool_quotes().remove(deps.storage, info.sender)?; + } + + Ok(Response::default()) +} diff --git a/contracts/infinity-swap/src/instantiate.rs b/contracts/infinity-index/src/instantiate.rs similarity index 65% rename from contracts/infinity-swap/src/instantiate.rs rename to contracts/infinity-index/src/instantiate.rs index 30c5437..c1be9e0 100644 --- a/contracts/infinity-swap/src/instantiate.rs +++ b/contracts/infinity-index/src/instantiate.rs @@ -1,32 +1,31 @@ use crate::error::ContractError; use crate::msg::InstantiateMsg; -use crate::state::{Config, CONFIG, POOL_COUNTER}; +use crate::state::{Config, CONFIG}; -#[cfg(not(feature = "library"))] -use cosmwasm_std::entry_point; use cosmwasm_std::{DepsMut, Env, MessageInfo}; use cw2::set_contract_version; -use cw_utils::maybe_addr; use sg_std::Response; -pub const CONTRACT_NAME: &str = "crates.io:infinity-swap"; +pub const CONTRACT_NAME: &str = "crates.io:infinity-index"; pub const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); +#[cfg(not(feature = "library"))] +use cosmwasm_std::entry_point; + #[cfg_attr(not(feature = "library"), entry_point)] pub fn instantiate( deps: DepsMut, - _env: Env, + env: Env, _info: MessageInfo, msg: InstantiateMsg, ) -> Result { set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?; - POOL_COUNTER.save(deps.storage, &1)?; CONFIG.save( deps.storage, &Config { - marketplace_addr: deps.api.addr_validate(&msg.marketplace_addr)?, - developer: maybe_addr(deps.api, msg.developer)?, + global_gov: deps.api.addr_validate(&msg.global_gov)?, + infinity_factory: deps.api.addr_validate(&msg.infinity_factory)?, }, )?; @@ -34,6 +33,6 @@ pub fn instantiate( .add_attribute("action", "instantiate") .add_attribute("contract_name", CONTRACT_NAME) .add_attribute("contract_version", CONTRACT_VERSION) - .add_attribute("denom", msg.denom) - .add_attribute("marketplace_addr", msg.marketplace_addr)) + .add_attribute("global_gov", msg.global_gov) + .add_attribute("infinity_factory", msg.infinity_factory)) } diff --git a/contracts/infinity-marketplace-adapter/src/lib.rs b/contracts/infinity-index/src/lib.rs similarity index 79% rename from contracts/infinity-marketplace-adapter/src/lib.rs rename to contracts/infinity-index/src/lib.rs index 4df1470..33194e1 100644 --- a/contracts/infinity-marketplace-adapter/src/lib.rs +++ b/contracts/infinity-index/src/lib.rs @@ -1,9 +1,7 @@ pub mod execute; -pub mod helpers; pub mod instantiate; pub mod msg; pub mod query; -pub mod reply; pub mod state; mod error; diff --git a/contracts/infinity-index/src/msg.rs b/contracts/infinity-index/src/msg.rs new file mode 100644 index 0000000..f3c98bd --- /dev/null +++ b/contracts/infinity-index/src/msg.rs @@ -0,0 +1,39 @@ +use crate::state::PoolQuote; + +use cosmwasm_schema::{cw_serde, QueryResponses}; +use cosmwasm_std::Uint128; + +#[cw_serde] +pub struct InstantiateMsg { + /// The address of the global gov contract + pub global_gov: String, + /// The address of the infinity factory contract + pub infinity_factory: String, +} + +#[cw_serde] +pub enum ExecuteMsg { + UpdateBuyFromPoolQuote { + collection: String, + quote_price: Option, + }, + UpdateSellToPoolQuote { + collection: String, + quote_price: Option, + }, +} + +#[cw_serde] +#[derive(QueryResponses)] +pub enum QueryMsg { + #[returns(PoolQuoteResponse)] + QuoteSellToPool { + collection: String, + limit: u64, + }, +} + +#[cw_serde] +pub struct PoolQuoteResponse { + pub pool_quotes: Vec, +} diff --git a/contracts/infinity-index/src/query.rs b/contracts/infinity-index/src/query.rs new file mode 100644 index 0000000..382a0c9 --- /dev/null +++ b/contracts/infinity-index/src/query.rs @@ -0,0 +1,40 @@ +use crate::msg::{PoolQuoteResponse, QueryMsg}; +use crate::state::{sell_to_pool_quotes, PoolQuote}; + +use cosmwasm_std::{to_binary, Addr, Binary, Deps, Env, Order, StdResult}; + +#[cfg(not(feature = "library"))] +use cosmwasm_std::entry_point; + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { + match msg { + QueryMsg::QuoteSellToPool { + collection, + limit, + } => to_binary(&query_quotes_sell_to_pool( + deps, + deps.api.addr_validate(&collection)?, + limit, + )?), + } +} + +pub fn query_quotes_sell_to_pool( + deps: Deps, + collection: Addr, + limit: u64, +) -> StdResult { + let pool_quotes: Vec = sell_to_pool_quotes() + .idx + .collection_quote_price + .sub_prefix(collection) + .range(deps.storage, None, None, Order::Descending) + .take(limit as usize) + .map(|item| item.map(|(_, v)| v)) + .collect::>()?; + + Ok(PoolQuoteResponse { + pool_quotes, + }) +} diff --git a/contracts/infinity-index/src/state.rs b/contracts/infinity-index/src/state.rs new file mode 100644 index 0000000..304683b --- /dev/null +++ b/contracts/infinity-index/src/state.rs @@ -0,0 +1,51 @@ +use cosmwasm_schema::cw_serde; +use cosmwasm_std::{Addr, Uint128}; +use cw_storage_macro::index_list; +use cw_storage_plus::{IndexedMap, Item, Map, MultiIndex}; + +#[cw_serde] +pub struct Config { + pub global_gov: Addr, + pub infinity_factory: Addr, +} + +pub const CONFIG: Item = Item::new("cfg"); + +#[cw_serde] +pub struct PoolQuote { + pub pool: Addr, + pub collection: Addr, + pub quote_price: Uint128, +} + +#[index_list(PoolQuote)] +pub struct BuyPoolQuoteIndices<'a> { + pub collection_quote_price: MultiIndex<'a, (Addr, u128), PoolQuote, Addr>, +} + +pub fn buy_from_pool_quotes<'a>() -> IndexedMap<'a, Addr, PoolQuote, BuyPoolQuoteIndices<'a>> { + let indexes = BuyPoolQuoteIndices { + collection_quote_price: MultiIndex::new( + |_pk: &[u8], p: &PoolQuote| (p.collection.clone(), p.quote_price.u128()), + "bfpq", + "bfpq__cqp", + ), + }; + IndexedMap::new("bfpq", indexes) +} + +#[index_list(PoolQuote)] +pub struct SellPoolQuoteIndices<'a> { + pub collection_quote_price: MultiIndex<'a, (Addr, u128), PoolQuote, Addr>, +} + +pub fn sell_to_pool_quotes<'a>() -> IndexedMap<'a, Addr, PoolQuote, SellPoolQuoteIndices<'a>> { + let indexes = SellPoolQuoteIndices { + collection_quote_price: MultiIndex::new( + |_pk: &[u8], p: &PoolQuote| (p.collection.clone(), p.quote_price.u128()), + "stpq", + "stpq__cqp", + ), + }; + IndexedMap::new("stpq", indexes) +} diff --git a/contracts/infinity-marketplace-adapter/src/error.rs b/contracts/infinity-marketplace-adapter/src/error.rs deleted file mode 100644 index d208311..0000000 --- a/contracts/infinity-marketplace-adapter/src/error.rs +++ /dev/null @@ -1,24 +0,0 @@ -use cosmwasm_std::StdError; -use cw_utils::PaymentError; -use thiserror::Error; - -#[derive(Error, Debug, PartialEq)] -pub enum ContractError { - #[error("{0}")] - Std(#[from] StdError), - - #[error("{0}")] - PaymentError(#[from] PaymentError), - - #[error("Invalid ask: {0}")] - InvalidInput(String), - - #[error("Match error: {0}")] - MatchError(String), - - #[error("Price mismatch: {0}")] - PriceMismatch(String), - - #[error("Insufficient funds: {0}")] - InsufficientFunds(String), -} diff --git a/contracts/infinity-marketplace-adapter/src/execute.rs b/contracts/infinity-marketplace-adapter/src/execute.rs deleted file mode 100644 index f3dd314..0000000 --- a/contracts/infinity-marketplace-adapter/src/execute.rs +++ /dev/null @@ -1,297 +0,0 @@ -use crate::helpers::{ - buy_now, match_nfts_against_tokens, match_tokens_against_any_nfts, - match_tokens_against_specific_nfts, validate_nft_owner, MatchedBid, -}; -use crate::state::{CONFIG, FORWARD_NFTS}; -use crate::ContractError; -use crate::{helpers::validate_nft_orders, msg::ExecuteMsg}; -use cosmwasm_std::{coin, to_binary, Addr, DepsMut, Env, MessageInfo, SubMsg, Uint128, WasmMsg}; -use cw721::Cw721ExecuteMsg; -use cw_utils::must_pay; -use infinity_shared::interface::{transform_swap_params, NftOrder, SwapParamsInternal}; -use sg_marketplace::msg::ExecuteMsg as MarketplaceExecuteMsg; -use sg_marketplace_common::{bank_send, transfer_nft}; -use sg_std::{Response, NATIVE_DENOM}; - -#[cfg(not(feature = "library"))] -use cosmwasm_std::entry_point; - -#[cfg_attr(not(feature = "library"), entry_point)] -pub fn execute( - deps: DepsMut, - env: Env, - info: MessageInfo, - msg: ExecuteMsg, -) -> Result { - let api = deps.api; - - match msg { - ExecuteMsg::SwapNftsForTokens { - collection, - nft_orders, - swap_params, - } => execute_swap_nfts_for_tokens( - deps, - env, - info, - api.addr_validate(&collection)?, - nft_orders, - transform_swap_params(api, swap_params)?, - ), - ExecuteMsg::SwapTokensForSpecificNfts { - collection, - nft_orders, - swap_params, - } => execute_swap_tokens_for_specific_nfts( - deps, - env, - info, - api.addr_validate(&collection)?, - nft_orders, - transform_swap_params(api, swap_params)?, - ), - ExecuteMsg::SwapTokensForAnyNfts { - collection, - nft_orders, - swap_params, - } => execute_swap_tokens_for_any_nfts( - deps, - env, - info, - api.addr_validate(&collection)?, - nft_orders, - transform_swap_params(api, swap_params)?, - ), - } -} - -/// Execute a SwapNftsForTokens message -pub fn execute_swap_nfts_for_tokens( - deps: DepsMut, - env: Env, - info: MessageInfo, - collection: Addr, - nft_orders: Vec, - swap_params: SwapParamsInternal, -) -> Result { - let config = CONFIG.load(deps.storage)?; - - validate_nft_orders(&nft_orders, config.max_batch_size)?; - validate_nft_owner(&deps.querier, &info.sender, &collection, &nft_orders)?; - - let matches = match_nfts_against_tokens( - deps.as_ref(), - &env.block, - &config, - &collection, - nft_orders, - swap_params.robust, - )?; - - let sender_recipient = swap_params.asset_recipient.unwrap_or(info.sender); - let finder = swap_params.finder.map(|f| f.to_string()); - - let mut response = Response::new(); - - let approve_all_msg = Cw721ExecuteMsg::ApproveAll { - operator: config.marketplace.to_string(), - expires: None, - }; - response = response.add_submessage(SubMsg::new(WasmMsg::Execute { - contract_addr: collection.to_string(), - msg: to_binary(&approve_all_msg)?, - funds: vec![], - })); - - for matched_order in matches { - if matched_order.matched_bid.is_none() { - continue; - } - let matched_bid = matched_order.matched_bid.unwrap(); - - let transfer_nft_msg = transfer_nft( - &collection, - &matched_order.nft_order.token_id, - &env.contract.address, - ); - response = response.add_submessage(transfer_nft_msg); - - match matched_bid { - MatchedBid::Bid(bid) => { - let accept_bid_msg = MarketplaceExecuteMsg::AcceptBid { - collection: collection.to_string(), - token_id: bid.token_id, - bidder: bid.bidder.to_string(), - finder: finder.clone(), - funds_recipient: Some(sender_recipient.to_string()), - }; - response = response.add_submessage(SubMsg::new(WasmMsg::Execute { - contract_addr: config.marketplace.to_string(), - msg: to_binary(&accept_bid_msg)?, - funds: vec![], - })); - } - MatchedBid::CollectionBid(collection_bid) => { - let token_id_num = matched_order.nft_order.token_id.parse::().unwrap(); - let accept_collection_bid_msg = MarketplaceExecuteMsg::AcceptCollectionBid { - collection: collection.to_string(), - token_id: token_id_num, - bidder: collection_bid.bidder.to_string(), - finder: finder.clone(), - funds_recipient: Some(sender_recipient.to_string()), - }; - response = response.add_submessage(SubMsg::new(WasmMsg::Execute { - contract_addr: config.marketplace.to_string(), - msg: to_binary(&accept_collection_bid_msg)?, - funds: vec![], - })); - } - } - } - - Ok(response) -} - -/// Execute a SwapTokensForSpecificNfts message -pub fn execute_swap_tokens_for_specific_nfts( - deps: DepsMut, - _env: Env, - info: MessageInfo, - collection: Addr, - nft_orders: Vec, - swap_params: SwapParamsInternal, -) -> Result { - let config = CONFIG.load(deps.storage)?; - - validate_nft_orders(&nft_orders, config.max_batch_size)?; - - let expected_amount = nft_orders - .iter() - .fold(Uint128::zero(), |acc, nft_order| acc + nft_order.amount); - let received_amount = must_pay(&info, NATIVE_DENOM)?; - if received_amount != expected_amount { - return Err(ContractError::InsufficientFunds(format!( - "expected {} but received {}", - expected_amount, received_amount - ))); - } - let mut remaining_balance = received_amount; - - let matches = match_tokens_against_specific_nfts( - deps.as_ref(), - &config, - &collection, - nft_orders, - swap_params.robust, - )?; - - let finder = swap_params.finder.map(|f| f.to_string()); - - let mut response = Response::new(); - - for matched_order in matches { - if matched_order.matched_ask.is_none() { - continue; - } - let matched_ask = matched_order.matched_ask.unwrap(); - remaining_balance -= matched_ask.price; - - response = buy_now(response, &matched_ask, &finder, &config.marketplace)?; - - FORWARD_NFTS.save( - deps.storage, - ( - matched_ask.collection.clone(), - matched_ask.token_id.to_string(), - ), - &info.sender, - )?; - } - - // Refund remaining balance - if remaining_balance.u128() > 0 { - response = response.add_submessage(bank_send( - coin(remaining_balance.u128(), NATIVE_DENOM), - &info.sender, - )); - } - - Ok(response) -} - -/// Execute a SwapTokensForAnyNfts message -pub fn execute_swap_tokens_for_any_nfts( - deps: DepsMut, - env: Env, - info: MessageInfo, - collection: Addr, - nft_orders: Vec, - swap_params: SwapParamsInternal, -) -> Result { - let config = CONFIG.load(deps.storage)?; - - if nft_orders.is_empty() { - return Err(ContractError::InvalidInput( - "nft orders must not be empty".to_string(), - )); - } - if nft_orders.len() > config.max_batch_size as usize { - return Err(ContractError::InvalidInput( - "nft orders must not exceed max batch size".to_string(), - )); - } - - let expected_amount = nft_orders - .iter() - .fold(Uint128::zero(), |acc, nft_order| acc + nft_order); - let received_amount = must_pay(&info, NATIVE_DENOM)?; - if received_amount != expected_amount { - return Err(ContractError::InsufficientFunds(format!( - "expected {} but received {}", - expected_amount, received_amount - ))); - } - let mut remaining_balance = received_amount; - - let matches = match_tokens_against_any_nfts( - deps.as_ref(), - &env.block, - &config, - &collection, - nft_orders, - swap_params.robust, - )?; - - let finder = swap_params.finder.map(|f| f.to_string()); - - let mut response = Response::new(); - - for matched_order in matches { - if matched_order.matched_ask.is_none() { - continue; - } - let matched_ask = matched_order.matched_ask.unwrap(); - remaining_balance -= matched_ask.price; - - response = buy_now(response, &matched_ask, &finder, &config.marketplace)?; - - FORWARD_NFTS.save( - deps.storage, - ( - matched_ask.collection.clone(), - matched_ask.token_id.to_string(), - ), - &info.sender, - )?; - } - - // Refund remaining balance - if remaining_balance.u128() > 0 { - response = response.add_submessage(bank_send( - coin(remaining_balance.u128(), NATIVE_DENOM), - &info.sender, - )); - } - - Ok(response) -} diff --git a/contracts/infinity-marketplace-adapter/src/helpers.rs b/contracts/infinity-marketplace-adapter/src/helpers.rs deleted file mode 100644 index b630f34..0000000 --- a/contracts/infinity-marketplace-adapter/src/helpers.rs +++ /dev/null @@ -1,406 +0,0 @@ -use crate::reply::BUY_NOW_REPLY_ID; -use crate::state::Config; -use crate::ContractError; - -use cosmwasm_schema::cw_serde; -use cosmwasm_std::{ - coins, to_binary, Addr, BlockInfo, Deps, QuerierWrapper, SubMsg, Uint128, WasmMsg, -}; -use infinity_shared::interface::{NftOrder, NftPayment, Swap, TokenPayment, TransactionType}; -use sg_marketplace::msg::{ - AskOffset, AskResponse, AsksResponse, BidsResponse, CollectionBidOffset, - CollectionBidsResponse, ExecuteMsg as MarketplaceExecuteMsg, QueryMsg as MarketplaceQueryMsg, -}; -use sg_marketplace::state::{Ask, Bid, CollectionBid, Order}; -use sg_marketplace_common::{only_owner, TransactionFees}; -use sg_std::{Response, NATIVE_DENOM}; -use std::cmp::Ordering; -use std::collections::BTreeSet; - -pub fn validate_nft_owner( - querier: &QuerierWrapper, - sender: &Addr, - collection: &Addr, - nft_orders: &[NftOrder], -) -> Result<(), ContractError> { - for nft_order in nft_orders.iter() { - only_owner(querier, sender, collection, &nft_order.token_id)?; - } - Ok(()) -} - -/// Validate NftSwap vector token amounts, and NFT ownership -pub fn validate_nft_orders( - nft_orders: &Vec, - max_batch_size: u32, -) -> Result<(), ContractError> { - if nft_orders.is_empty() { - return Err(ContractError::InvalidInput( - "nft orders must not be empty".to_string(), - )); - } - if nft_orders.len() > max_batch_size as usize { - return Err(ContractError::InvalidInput( - "nft orders must not exceed max batch size".to_string(), - )); - } - - let mut uniq_token_ids: BTreeSet = BTreeSet::new(); - for nft_order in nft_orders.iter() { - if uniq_token_ids.contains(&nft_order.token_id) { - return Err(ContractError::InvalidInput( - "found duplicate nft token id".to_string(), - )); - } - uniq_token_ids.insert(nft_order.token_id.clone()); - } - Ok(()) -} - -// Fetch collection bids in a loop until a certain number are retrieved or there are no more to fetch, -// filters out invalid collection bids -pub fn fetch_collection_bids( - deps: Deps, - marketplace: &Addr, - collection: &Addr, - block: &BlockInfo, - limit: u32, -) -> Result, ContractError> { - let mut collection_bids: Vec = vec![]; - - loop { - let mut start_after: Option = None; - if let Some(last_collection_bid) = collection_bids.last() { - start_after = Some(CollectionBidOffset { - price: last_collection_bid.price, - collection: last_collection_bid.collection.to_string(), - bidder: last_collection_bid.bidder.to_string(), - }); - } - - let query_limit = limit - collection_bids.len() as u32; - let collection_bids_response: CollectionBidsResponse = deps.querier.query_wasm_smart( - marketplace, - &MarketplaceQueryMsg::CollectionBidsSortedByPrice { - collection: collection.to_string(), - start_after, - limit: Some(query_limit), - }, - )?; - let num_results = collection_bids_response.bids.len(); - - // Filter out expired collection bids - collection_bids.extend( - collection_bids_response - .bids - .into_iter() - .filter(|cb| !cb.is_expired(block)), - ); - - if num_results < query_limit as usize || collection_bids.len() >= limit as usize { - break; - } - } - - Ok(collection_bids) -} - -// Fetch asks in a loop until a certain number are retrieved or there are no more to fetch, -// filters out invalid asks -pub fn fetch_asks( - deps: Deps, - marketplace: &Addr, - collection: &Addr, - block: &BlockInfo, - limit: u32, -) -> Result, ContractError> { - let mut asks: Vec = vec![]; - - loop { - let mut start_after: Option = None; - if let Some(last_ask) = asks.last() { - start_after = Some(AskOffset { - price: last_ask.price, - token_id: last_ask.token_id, - }); - } - - let query_limit = limit - asks.len() as u32; - let asks_response: AsksResponse = deps.querier.query_wasm_smart( - marketplace, - &MarketplaceQueryMsg::AsksSortedByPrice { - collection: collection.to_string(), - include_inactive: Some(false), - start_after, - limit: Some(query_limit), - }, - )?; - let num_results = asks_response.asks.len(); - - // Filter out expired asks - asks.extend( - asks_response - .asks - .into_iter() - .filter(|ask| !ask.is_expired(block)), - ); - - if num_results < query_limit as usize || asks.len() >= limit as usize { - break; - } - } - - asks.reverse(); - Ok(asks) -} - -pub fn tx_fees_to_swap( - tx_fees: TransactionFees, - transaction_type: TransactionType, - token_id: &str, - sale_price: Uint128, - buyer: &Addr, - source: &Addr, -) -> Swap { - let mut token_payments: Vec = vec![]; - if let Some(finders_fee) = tx_fees.finders_fee { - token_payments.push(TokenPayment { - label: "finder".to_string(), - address: finders_fee.recipient.to_string(), - amount: finders_fee.coin.amount, - }); - } - if let Some(royalty_fee) = tx_fees.royalty_fee { - token_payments.push(TokenPayment { - label: "royalty".to_string(), - address: royalty_fee.recipient.to_string(), - amount: royalty_fee.coin.amount, - }); - } - token_payments.push(TokenPayment { - label: "seller".to_string(), - address: tx_fees.seller_payment.recipient.to_string(), - amount: tx_fees.seller_payment.coin.amount, - }); - - Swap { - source: source.to_string(), - transaction_type, - sale_price, - network_fee: tx_fees.fair_burn_fee, - nft_payments: vec![NftPayment { - label: "buyer".to_string(), - token_id: token_id.to_string(), - address: buyer.to_string(), - }], - token_payments, - } -} - -#[cw_serde] -pub enum MatchedBid { - Bid(Bid), - CollectionBid(CollectionBid), -} - -pub struct MatchedNftAgainstTokens { - pub nft_order: NftOrder, - pub matched_bid: Option, -} - -pub fn match_nfts_against_tokens( - deps: Deps, - block: &BlockInfo, - config: &Config, - collection: &Addr, - nft_orders: Vec, - robust: bool, -) -> Result, ContractError> { - let mut collection_bids = fetch_collection_bids( - deps, - &config.marketplace, - collection, - block, - config.max_batch_size, - )?; - - let mut matched_user_submitted_nfts: Vec = vec![]; - - for nft_order in nft_orders { - let token_id = nft_order.token_id.parse::().unwrap(); - let mut bid_response: BidsResponse = deps.querier.query_wasm_smart( - &config.marketplace, - &MarketplaceQueryMsg::BidsSortedByTokenPrice { - collection: collection.to_string(), - token_id, - start_after: None, - limit: Some(1), - descending: Some(true), - include_expired: Some(false), - }, - )?; - - let bid = bid_response.bids.pop(); - let collection_bid = collection_bids.pop(); - - let mut matched_bid: Option = match (bid, collection_bid) { - (Some(bid), Some(collection_bid)) => match bid.price.cmp(&collection_bid.price) { - Ordering::Greater | Ordering::Equal => { - collection_bids.push(collection_bid); - Some(MatchedBid::Bid(bid)) - } - Ordering::Less => Some(MatchedBid::CollectionBid(collection_bid)), - }, - (Some(bid), None) => Some(MatchedBid::Bid(bid)), - (None, Some(collection_bid)) => Some(MatchedBid::CollectionBid(collection_bid)), - (None, None) => None, - }; - - if let Some(_matched_bid) = &matched_bid { - let price = match _matched_bid { - MatchedBid::Bid(bid) => bid.price, - MatchedBid::CollectionBid(collection_bid) => collection_bid.price, - }; - if price < nft_order.amount { - matched_bid = None; - } - } - - if !robust && matched_bid.is_none() { - return Err(ContractError::MatchError( - "all nfts not matched with a bid".to_string(), - )); - } - - matched_user_submitted_nfts.push(MatchedNftAgainstTokens { - nft_order, - matched_bid, - }); - } - - Ok(matched_user_submitted_nfts) -} - -pub struct MatchedTokensAgainstSpecificNfts { - pub nft_order: NftOrder, - pub matched_ask: Option, -} - -pub fn match_tokens_against_specific_nfts( - deps: Deps, - config: &Config, - collection: &Addr, - nft_orders: Vec, - robust: bool, -) -> Result, ContractError> { - let mut matched_user_submitted_tokens: Vec = vec![]; - - for nft_order in nft_orders { - let token_id = nft_order.token_id.parse::().unwrap(); - let ask_response: AskResponse = deps.querier.query_wasm_smart( - &config.marketplace, - &MarketplaceQueryMsg::Ask { - collection: collection.to_string(), - token_id, - }, - )?; - let ask = match ask_response.ask { - Some(_ask) => { - if nft_order.amount >= _ask.price { - Some(_ask) - } else { - None - } - } - None => None, - }; - - if !robust && ask.is_none() { - return Err(ContractError::MatchError( - "all nft orders not matched with an ask".to_string(), - )); - } - - matched_user_submitted_tokens.push(MatchedTokensAgainstSpecificNfts { - nft_order, - matched_ask: ask, - }); - } - Ok(matched_user_submitted_tokens) -} - -pub struct MatchedTokensAgainstAnyNfts { - pub token_amount: Uint128, - pub matched_ask: Option, -} - -pub fn match_tokens_against_any_nfts( - deps: Deps, - block: &BlockInfo, - config: &Config, - collection: &Addr, - nft_orders: Vec, - robust: bool, -) -> Result, ContractError> { - let mut asks = fetch_asks( - deps, - &config.marketplace, - collection, - block, - config.max_batch_size, - )?; - - let mut matched_user_submitted_tokens: Vec = vec![]; - for nft_order in nft_orders { - let ask = match asks.pop() { - Some(_ask) => { - if nft_order >= _ask.price { - Some(_ask) - } else { - None - } - } - None => None, - }; - - if !robust && ask.is_none() { - return Err(ContractError::MatchError( - "all nft orders not matched with an ask".to_string(), - )); - } - - matched_user_submitted_tokens.push(MatchedTokensAgainstAnyNfts { - token_amount: nft_order, - matched_ask: ask, - }); - } - Ok(matched_user_submitted_tokens) -} - -pub fn buy_now( - response: Response, - ask: &Ask, - finder: &Option, - marketplace: &Addr, -) -> Result { - let mut response = response; - - let buy_now_msg = MarketplaceExecuteMsg::BuyNow { - collection: ask.collection.to_string(), - token_id: ask.token_id, - expires: ask.expires_at, - finder: finder.clone(), - finders_fee_bps: None, - }; - - response = response.add_submessage(SubMsg::reply_always( - WasmMsg::Execute { - contract_addr: marketplace.to_string(), - msg: to_binary(&buy_now_msg)?, - funds: coins(ask.price.u128(), NATIVE_DENOM), - }, - BUY_NOW_REPLY_ID, - )); - - Ok(response) -} diff --git a/contracts/infinity-marketplace-adapter/src/msg.rs b/contracts/infinity-marketplace-adapter/src/msg.rs deleted file mode 100644 index aed8a19..0000000 --- a/contracts/infinity-marketplace-adapter/src/msg.rs +++ /dev/null @@ -1,58 +0,0 @@ -use cosmwasm_schema::{cw_serde, QueryResponses}; -use cosmwasm_std::Uint128; -use infinity_shared::interface::{NftOrder, SwapParams, SwapResponse}; - -pub const MAX_QUERY_LIMIT: u32 = 100; - -#[cw_serde] -pub struct InstantiateMsg { - /// The address of the marketplace contract - pub marketplace: String, - /// The max number of NFT swaps that can be processed in a single message - pub max_batch_size: u32, -} - -#[cw_serde] -pub enum ExecuteMsg { - SwapNftsForTokens { - collection: String, - nft_orders: Vec, - swap_params: SwapParams, - }, - SwapTokensForSpecificNfts { - collection: String, - nft_orders: Vec, - swap_params: SwapParams, - }, - SwapTokensForAnyNfts { - collection: String, - nft_orders: Vec, - swap_params: SwapParams, - }, -} - -#[cw_serde] -#[derive(QueryResponses)] -pub enum QueryMsg { - #[returns(SwapResponse)] - SimSwapNftsForTokens { - sender: String, - collection: String, - nft_orders: Vec, - swap_params: SwapParams, - }, - #[returns(SwapResponse)] - SimSwapTokensForSpecificNfts { - sender: String, - collection: String, - nft_orders: Vec, - swap_params: SwapParams, - }, - #[returns(SwapResponse)] - SimSwapTokensForAnyNfts { - sender: String, - collection: String, - nft_orders: Vec, - swap_params: SwapParams, - }, -} diff --git a/contracts/infinity-marketplace-adapter/src/query.rs b/contracts/infinity-marketplace-adapter/src/query.rs deleted file mode 100644 index d285f05..0000000 --- a/contracts/infinity-marketplace-adapter/src/query.rs +++ /dev/null @@ -1,263 +0,0 @@ -use crate::helpers::{ - match_nfts_against_tokens, match_tokens_against_any_nfts, match_tokens_against_specific_nfts, - tx_fees_to_swap, validate_nft_orders, validate_nft_owner, MatchedBid, -}; -use crate::msg::QueryMsg; -use crate::state::CONFIG; -use cosmwasm_std::{to_binary, Addr, Binary, Deps, Env, StdError, StdResult, Uint128}; -use infinity_shared::interface::{ - transform_swap_params, NftOrder, Swap, SwapParamsInternal, SwapResponse, TransactionType, -}; - -#[cfg(not(feature = "library"))] -use cosmwasm_std::entry_point; -use infinity_shared::shared::load_marketplace_params; -use sg_marketplace_common::{calculate_nft_sale_fees, load_collection_royalties}; - -#[cfg_attr(not(feature = "library"), entry_point)] -pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { - let api = deps.api; - - match msg { - QueryMsg::SimSwapNftsForTokens { - sender, - collection, - nft_orders, - swap_params, - } => to_binary(&query_sim_swap_nfts_for_tokens( - deps, - env, - api.addr_validate(&sender)?, - api.addr_validate(&collection)?, - nft_orders, - transform_swap_params(api, swap_params)?, - )?), - QueryMsg::SimSwapTokensForSpecificNfts { - sender, - collection, - nft_orders, - swap_params, - } => to_binary(&query_sim_swap_tokens_for_specific_nfts( - deps, - env, - api.addr_validate(&sender)?, - api.addr_validate(&collection)?, - nft_orders, - transform_swap_params(api, swap_params)?, - )?), - QueryMsg::SimSwapTokensForAnyNfts { - sender, - collection, - nft_orders, - swap_params, - } => to_binary(&query_sim_swap_tokens_for_any_nfts( - deps, - env, - api.addr_validate(&sender)?, - api.addr_validate(&collection)?, - nft_orders, - transform_swap_params(api, swap_params)?, - )?), - } -} - -pub fn query_sim_swap_nfts_for_tokens( - deps: Deps, - env: Env, - sender: Addr, - collection: Addr, - nft_orders: Vec, - swap_params: SwapParamsInternal, -) -> StdResult { - let config = CONFIG.load(deps.storage)?; - - validate_nft_orders(&nft_orders, config.max_batch_size) - .map_err(|err| StdError::generic_err(err.to_string()))?; - validate_nft_owner(&deps.querier, &sender, &collection, &nft_orders) - .map_err(|err| StdError::generic_err(err.to_string()))?; - - let matches = match_nfts_against_tokens( - deps, - &env.block, - &config, - &collection, - nft_orders, - swap_params.robust, - ) - .map_err(|err| StdError::generic_err(err.to_string()))?; - - let sender_recipient = swap_params.asset_recipient.unwrap_or(sender); - - let mut swaps: Vec = vec![]; - - let marketplace_params = load_marketplace_params(&deps.querier, &config.marketplace)?; - let royalty_info = load_collection_royalties(&deps.querier, deps.api, &collection)?; - - for matched_order in matches { - if matched_order.matched_bid.is_none() { - continue; - } - let matched_bid = matched_order.matched_bid.unwrap(); - - let (sale_price, bidder, finders_fee_bps): (Uint128, Addr, Option) = match matched_bid - { - MatchedBid::Bid(bid) => (bid.price, bid.bidder, bid.finders_fee_bps), - MatchedBid::CollectionBid(collection_bid) => ( - collection_bid.price, - collection_bid.bidder, - collection_bid.finders_fee_bps, - ), - }; - - let token_id = matched_order.nft_order.token_id; - - let tx_fees = calculate_nft_sale_fees( - sale_price, - marketplace_params.trading_fee_percent, - &sender_recipient, - swap_params.finder.as_ref(), - finders_fee_bps, - royalty_info.as_ref(), - )?; - - swaps.push(tx_fees_to_swap( - tx_fees, - TransactionType::UserSubmitsNfts, - &token_id, - sale_price, - &bidder, - &config.marketplace, - )); - } - - Ok(SwapResponse { swaps }) -} - -pub fn query_sim_swap_tokens_for_specific_nfts( - deps: Deps, - _env: Env, - sender: Addr, - collection: Addr, - nft_orders: Vec, - swap_params: SwapParamsInternal, -) -> StdResult { - let config = CONFIG.load(deps.storage)?; - - validate_nft_orders(&nft_orders, config.max_batch_size) - .map_err(|err| StdError::generic_err(err.to_string()))?; - - let matches = match_tokens_against_specific_nfts( - deps, - &config, - &collection, - nft_orders, - swap_params.robust, - ) - .map_err(|err| StdError::generic_err(err.to_string()))?; - - let sender_recipient = swap_params.asset_recipient.unwrap_or(sender); - - let mut swaps: Vec = vec![]; - - let marketplace_params = load_marketplace_params(&deps.querier, &config.marketplace)?; - let royalty_info = load_collection_royalties(&deps.querier, deps.api, &collection)?; - - for matched_order in matches { - if matched_order.matched_ask.is_none() { - continue; - } - let token_id = matched_order.nft_order.token_id; - let matched_ask = matched_order.matched_ask.unwrap(); - - let ask_recipient = matched_ask.funds_recipient.unwrap_or(matched_ask.seller); - - let tx_fees = calculate_nft_sale_fees( - matched_ask.price, - marketplace_params.trading_fee_percent, - &ask_recipient, - swap_params.finder.as_ref(), - matched_ask.finders_fee_bps, - royalty_info.as_ref(), - )?; - - swaps.push(tx_fees_to_swap( - tx_fees, - TransactionType::UserSubmitsTokens, - &token_id, - matched_ask.price, - &sender_recipient, - &config.marketplace, - )); - } - - Ok(SwapResponse { swaps }) -} - -pub fn query_sim_swap_tokens_for_any_nfts( - deps: Deps, - env: Env, - sender: Addr, - collection: Addr, - nft_orders: Vec, - swap_params: SwapParamsInternal, -) -> StdResult { - let config = CONFIG.load(deps.storage)?; - - if nft_orders.is_empty() { - return Err(StdError::generic_err( - "nft orders must not be empty".to_string(), - )); - } - if nft_orders.len() > config.max_batch_size as usize { - return Err(StdError::generic_err( - "nft orders must not exceed max batch size".to_string(), - )); - } - - let matches = match_tokens_against_any_nfts( - deps, - &env.block, - &config, - &collection, - nft_orders, - swap_params.robust, - ) - .map_err(|err| StdError::generic_err(err.to_string()))?; - - let sender_recipient = swap_params.asset_recipient.unwrap_or(sender); - - let mut swaps: Vec = vec![]; - - let marketplace_params = load_marketplace_params(&deps.querier, &config.marketplace)?; - let royalty_info = load_collection_royalties(&deps.querier, deps.api, &collection)?; - - for matched_order in matches { - if matched_order.matched_ask.is_none() { - continue; - } - let matched_ask = matched_order.matched_ask.unwrap(); - let token_id = matched_ask.token_id.to_string(); - - let ask_recipient = matched_ask.funds_recipient.unwrap_or(matched_ask.seller); - - let tx_fees = calculate_nft_sale_fees( - matched_ask.price, - marketplace_params.trading_fee_percent, - &ask_recipient, - swap_params.finder.as_ref(), - matched_ask.finders_fee_bps, - royalty_info.as_ref(), - )?; - - swaps.push(tx_fees_to_swap( - tx_fees, - TransactionType::UserSubmitsTokens, - &token_id, - matched_ask.price, - &sender_recipient, - &config.marketplace, - )); - } - - Ok(SwapResponse { swaps }) -} diff --git a/contracts/infinity-marketplace-adapter/src/reply.rs b/contracts/infinity-marketplace-adapter/src/reply.rs deleted file mode 100644 index 697e8d8..0000000 --- a/contracts/infinity-marketplace-adapter/src/reply.rs +++ /dev/null @@ -1,48 +0,0 @@ -use crate::{state::FORWARD_NFTS, ContractError}; -use cosmwasm_std::{DepsMut, Env, Reply}; -use sg_marketplace_common::transfer_nft; -use sg_std::Response; - -pub const BUY_NOW_REPLY_ID: u64 = 1111; - -#[cfg(not(feature = "library"))] -use cosmwasm_std::entry_point; - -#[cfg_attr(not(feature = "library"), entry_point)] -pub fn reply(deps: DepsMut, env: Env, msg: Reply) -> Result { - match msg.id { - BUY_NOW_REPLY_ID => reply_buy_now(deps, env, msg), - id => unreachable!("unknown reply ID: `{id}`"), - } -} - -pub fn reply_buy_now(deps: DepsMut, _env: Env, msg: Reply) -> Result { - let result = msg.result.unwrap(); - - let event = result - .events - .iter() - .find(|e| e.ty == "wasm-finalize-sale") - .unwrap(); - - let collection_str = &event - .attributes - .iter() - .find(|a| a.key == "collection") - .unwrap() - .value; - - let collection = deps.api.addr_validate(collection_str)?; - - let token_id = &event - .attributes - .iter() - .find(|a| a.key == "token_id") - .unwrap() - .value; - - let forward_to = FORWARD_NFTS.load(deps.storage, (collection.clone(), token_id.to_string()))?; - FORWARD_NFTS.remove(deps.storage, (collection.clone(), token_id.to_string())); - - Ok(Response::new().add_submessage(transfer_nft(&collection, token_id, &forward_to))) -} diff --git a/contracts/infinity-marketplace-adapter/src/state.rs b/contracts/infinity-marketplace-adapter/src/state.rs deleted file mode 100644 index 8d4a5dc..0000000 --- a/contracts/infinity-marketplace-adapter/src/state.rs +++ /dev/null @@ -1,16 +0,0 @@ -use cosmwasm_schema::cw_serde; -use cosmwasm_std::Addr; -use cw_storage_plus::{Item, Map}; - -/// The global configuration object for the contract -#[cw_serde] -pub struct Config { - /// The address of the marketplace contract - pub marketplace: Addr, - /// The max number of NFT swaps that can be processed in a single message - pub max_batch_size: u32, -} - -pub const CONFIG: Item = Item::new("config"); - -pub const FORWARD_NFTS: Map<(Addr, String), Addr> = Map::new("forward_nfts"); diff --git a/contracts/infinity-marketplace-adapter/Cargo.toml b/contracts/infinity-pool/Cargo.toml similarity index 67% rename from contracts/infinity-marketplace-adapter/Cargo.toml rename to contracts/infinity-pool/Cargo.toml index d0497b6..9291ed7 100644 --- a/contracts/infinity-marketplace-adapter/Cargo.toml +++ b/contracts/infinity-pool/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "infinity-marketplace-adapter" +name = "infinity-pool" version = { workspace = true } edition = { workspace = true } repository = { workspace = true } @@ -21,23 +21,24 @@ backtraces = ["cosmwasm-std/backtraces"] library = [] [dependencies] -infinity-macros = { workspace = true } +# infinity-macros = { workspace = true } infinity-shared = { workspace = true } -infinity-swap = { workspace = true } +infinity-index = { workspace = true } +# infinity-swap = { workspace = true } cosmwasm-std = { workspace = true } cosmwasm-schema = { workspace = true } -cosmwasm-storage = { workspace = true } cw-storage-plus = { workspace = true } +# cosmwasm-storage = { workspace = true } cw-utils = { workspace = true } cw2 = { workspace = true } thiserror = { workspace = true } -anyhow = { workspace = true } -sg1 = { workspace = true } -sg2 = { workspace = true } -sg721-base = { workspace = true } -sg721 = { workspace = true } +# anyhow = { workspace = true } +# sg1 = { workspace = true } +# sg2 = { workspace = true } +# sg721-base = { workspace = true } +# sg721 = { workspace = true } sg-std = { workspace = true } -sg-marketplace = { workspace = true } +# sg-marketplace = { workspace = true } sg-marketplace-common = { workspace = true } -cw721-base = { workspace = true } -cw721 = { workspace = true } \ No newline at end of file +# cw721-base = { workspace = true } +# cw721 = { workspace = true } \ No newline at end of file diff --git a/contracts/infinity-pool/src/error.rs b/contracts/infinity-pool/src/error.rs new file mode 100644 index 0000000..92794d7 --- /dev/null +++ b/contracts/infinity-pool/src/error.rs @@ -0,0 +1,26 @@ +use cosmwasm_schema::schemars::_serde_json::error; +use cosmwasm_std::StdError; +use cw_utils::PaymentError; +use infinity_shared::InfinityError; +use thiserror::Error; + +#[derive(Error, Debug, PartialEq)] +pub enum ContractError { + #[error("{0}")] + Std(#[from] StdError), + + #[error("{0}")] + PaymentError(#[from] PaymentError), + + #[error("{0}")] + InfinityError(#[from] InfinityError), + + #[error("Unauthorized: {0}")] + Unauthorized(String), + + #[error("Invalid pool: {0}")] + InvalidPool(String), + + #[error("Invalid pool quote: {0}")] + InvalidPoolQuote(String), +} diff --git a/contracts/infinity-pool/src/execute.rs b/contracts/infinity-pool/src/execute.rs new file mode 100644 index 0000000..bf611e0 --- /dev/null +++ b/contracts/infinity-pool/src/execute.rs @@ -0,0 +1,164 @@ +use crate::msg::ExecuteMsg; +use crate::pool::Pool; +use crate::state::GLOBAL_GOV; +use crate::{ + error::ContractError, + state::{INFINITY_INDEX, POOL_CONFIG}, +}; + +use cosmwasm_std::{ + coin, ensure, to_binary, Addr, DepsMut, Env, MessageInfo, SubMsg, Uint128, WasmMsg, +}; +use cw_utils::{maybe_addr, nonpayable}; +use infinity_index::msg::ExecuteMsg as InfinityIndexExecuteMsg; +use infinity_shared::shared::{load_marketplace_params, only_nft_owner}; +use sg_marketplace_common::{ + calculate_nft_sale_fees, load_collection_royalties, payout_nft_sale_fees, transfer_nft, +}; +use sg_std::{Response, NATIVE_DENOM}; + +#[cfg(not(feature = "library"))] +use cosmwasm_std::entry_point; + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn execute( + deps: DepsMut, + env: Env, + info: MessageInfo, + msg: ExecuteMsg, +) -> Result { + let api = deps.api; + + match msg { + ExecuteMsg::SetIsActive { + is_active, + } => execute_set_is_active(deps, info, env, is_active), + ExecuteMsg::SwapNftsForTokens { + token_id, + min_output, + asset_recipient, + finder, + } => execute_swap_nfts_for_tokens( + deps, + info, + env, + token_id, + min_output, + api.addr_validate(&asset_recipient)?, + maybe_addr(api, finder)?, + ), + } +} + +/// Execute a SwapNftsForTokens message +pub fn execute_swap_nfts_for_tokens( + deps: DepsMut, + info: MessageInfo, + env: Env, + token_id: String, + min_output: Uint128, + seller_recipient: Addr, + finder: Option, +) -> Result { + nonpayable(&info)?; + + let mut pool = Pool::new(POOL_CONFIG.load(deps.storage)?); + + only_nft_owner(&deps.querier, deps.api, &info.sender, pool.collection(), &token_id)?; + + ensure!(pool.can_buy_nfts(), ContractError::InvalidPool("pool cannot buy nfts".to_string())); + ensure!(pool.is_active(), ContractError::InvalidPool("pool is not active".to_string())); + + let mut response = Response::new(); + + let marketplace = GLOBAL_GOV.load(deps.storage)?; + let marketplace_params = load_marketplace_params(&deps.querier, &marketplace)?; + let mut total_tokens = deps.querier.query_balance(&env.contract.address, NATIVE_DENOM)?.amount; + + let sale_price = pool.get_sell_to_pool_quote(total_tokens, marketplace_params.min_price)?; + + ensure!( + sale_price >= min_output, + ContractError::InvalidPoolQuote("sale price is below min output".to_string()) + ); + + total_tokens -= sale_price; + + let update_result = pool.update_spot_price_after_buy(total_tokens); + let next_sell_to_pool_quote = match update_result.is_ok() { + true => pool.get_sell_to_pool_quote(total_tokens, marketplace_params.min_price).ok(), + false => None, + }; + + let infinity_index = INFINITY_INDEX.load(deps.storage)?; + + response = response.add_submessage(SubMsg::new(WasmMsg::Execute { + contract_addr: infinity_index.to_string(), + msg: to_binary(&InfinityIndexExecuteMsg::UpdateSellToPoolQuote { + collection: pool.collection().to_string(), + quote_price: next_sell_to_pool_quote, + })?, + funds: vec![], + })); + + // Transfer NFT to pool recipient or reinvest into pool + let nft_recipient = match pool.reinvest_nfts() { + true => &env.contract.address, + false => pool.recipient(), + }; + response = response.add_submessage(transfer_nft(pool.collection(), &token_id, nft_recipient)); + + let royalty_info = load_collection_royalties(&deps.querier, deps.api, pool.collection())?; + let tx_fees = calculate_nft_sale_fees( + sale_price, + marketplace_params.trading_fee_percent, + &seller_recipient, + finder.as_ref(), + Some(pool.finders_fee_percent()), + royalty_info.as_ref(), + )?; + println!("tx_fees: {:?}", tx_fees); + response = payout_nft_sale_fees(response, tx_fees, None)?; + + pool.save(deps.storage)?; + + Ok(response) +} + +pub fn execute_set_is_active( + deps: DepsMut, + info: MessageInfo, + env: Env, + is_active: bool, +) -> Result { + let mut pool = Pool::new(POOL_CONFIG.load(deps.storage)?); + + ensure!( + &info.sender == pool.owner(), + ContractError::Unauthorized("sender is not owner".to_string()) + ); + + pool.set_is_active(is_active); + pool.save(deps.storage)?; + + let mut response = Response::new(); + + let marketplace = GLOBAL_GOV.load(deps.storage)?; + let marketplace_params = load_marketplace_params(&deps.querier, &marketplace)?; + let total_tokens = deps.querier.query_balance(&env.contract.address, NATIVE_DENOM)?.amount; + let next_sell_to_pool_quote = + pool.get_sell_to_pool_quote(total_tokens, marketplace_params.min_price).ok(); + + let infinity_index = INFINITY_INDEX.load(deps.storage)?; + + response = response.add_submessage(SubMsg::new(WasmMsg::Execute { + contract_addr: infinity_index.to_string(), + msg: to_binary(&InfinityIndexExecuteMsg::UpdateSellToPoolQuote { + collection: pool.collection().to_string(), + quote_price: next_sell_to_pool_quote, + })?, + funds: vec![], + })); + + Ok(response) +} diff --git a/contracts/infinity-pool/src/instantiate.rs b/contracts/infinity-pool/src/instantiate.rs new file mode 100644 index 0000000..19cbfc5 --- /dev/null +++ b/contracts/infinity-pool/src/instantiate.rs @@ -0,0 +1,61 @@ +use crate::error::ContractError; +use crate::msg::InstantiateMsg; +use crate::pool::Pool; +use crate::state::{PoolConfig, GLOBAL_GOV, INFINITY_INDEX, POOL_CONFIG}; +use cosmwasm_std::{Decimal, DepsMut, Env, MessageInfo}; +use cw2::set_contract_version; +use cw_utils::maybe_addr; +use sg_std::Response; + +pub const CONTRACT_NAME: &str = "crates.io:infinity-pool"; +pub const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); + +#[cfg(not(feature = "library"))] +use cosmwasm_std::entry_point; + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn instantiate( + deps: DepsMut, + _env: Env, + _info: MessageInfo, + msg: InstantiateMsg, +) -> Result { + set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?; + + let global_gov = deps.api.addr_validate(&msg.global_gov)?; + GLOBAL_GOV.save(deps.storage, &global_gov)?; + + let infinity_index = deps.api.addr_validate(&msg.infinity_index)?; + INFINITY_INDEX.save(deps.storage, &infinity_index)?; + + let pool_config = PoolConfig { + collection: deps.api.addr_validate(&msg.pool_info.collection)?, + owner: deps.api.addr_validate(&msg.pool_info.owner)?, + asset_recipient: maybe_addr(deps.api, msg.pool_info.asset_recipient)?, + pool_type: msg.pool_info.pool_type, + bonding_curve: msg.pool_info.bonding_curve, + spot_price: msg.pool_info.spot_price, + delta: msg.pool_info.delta, + total_nfts: 0u64, + finders_fee_percent: Decimal::percent(msg.pool_info.finders_fee_bps), + swap_fee_percent: Decimal::percent(msg.pool_info.swap_fee_bps), + is_active: false, + reinvest_tokens: msg.pool_info.reinvest_tokens, + reinvest_nfts: msg.pool_info.reinvest_nfts, + }; + POOL_CONFIG.save(deps.storage, &pool_config)?; + + let pool = Pool::new(pool_config); + pool.validate()?; + + let mut response = Response::new() + .add_attribute("action", "instantiate") + .add_attribute("contract_name", CONTRACT_NAME) + .add_attribute("contract_version", CONTRACT_VERSION) + .add_attribute("global_gov", msg.global_gov.to_string()) + .add_attribute("infinity_controller", msg.infinity_index.to_string()); + + response = response.add_event(pool.create_event_all_props("create-pool")?); + + Ok(response) +} diff --git a/contracts/infinity-swap/src/lib.rs b/contracts/infinity-pool/src/lib.rs similarity index 64% rename from contracts/infinity-swap/src/lib.rs rename to contracts/infinity-pool/src/lib.rs index bb4bbf4..602bd43 100644 --- a/contracts/infinity-swap/src/lib.rs +++ b/contracts/infinity-pool/src/lib.rs @@ -1,14 +1,10 @@ -#![allow(clippy::too_many_arguments)] - pub mod execute; pub mod instantiate; pub mod msg; pub mod pool; pub mod query; pub mod state; -pub mod swap_processor; mod error; -mod helpers; pub use error::ContractError; diff --git a/contracts/infinity-pool/src/msg.rs b/contracts/infinity-pool/src/msg.rs new file mode 100644 index 0000000..8274421 --- /dev/null +++ b/contracts/infinity-pool/src/msg.rs @@ -0,0 +1,62 @@ +use crate::state::{BondingCurve, PoolType}; + +use cosmwasm_schema::{cw_serde, QueryResponses}; +use cosmwasm_std::Uint128; + +#[cw_serde] +pub struct PoolInfo { + /// The address of the NFT collection contract + pub collection: String, + /// The address of the owner of the pool + pub owner: String, + /// The address of the recipient of assets traded into the pool + pub asset_recipient: Option, + /// The type of assets held by the pool + pub pool_type: PoolType, + /// The bonding curve used to calculate the spot price + pub bonding_curve: BondingCurve, + /// A moving value used to derive the price at which the pool will trade assets + /// Note: this value is not necessarily the final sale price for pool assets + pub spot_price: Uint128, + /// The amount by which the spot price will increment/decrement + /// For linear curves, this is the constant amount + /// For exponential curves, this is the percentage amount (treated as basis points) + pub delta: Uint128, + /// The percentage of the swap that will be paid to the finder of a trade + pub finders_fee_bps: u64, + /// The percentage of the swap that will be paid to the pool owner + /// Note: this only applies to Trade pools + pub swap_fee_bps: u64, + /// Whether or not the tokens sold into the pool will be reinvested + pub reinvest_tokens: bool, + /// Whether or not the NFTs sold into the pool will be reinvested + pub reinvest_nfts: bool, +} + +#[cw_serde] +pub struct InstantiateMsg { + // The address of the global gov contract + pub global_gov: String, + // The address of the infinity index contract + pub infinity_index: String, + /// The configuration object for the pool + pub pool_info: PoolInfo, +} + +#[cw_serde] +pub enum ExecuteMsg { + SetIsActive { + is_active: bool, + }, + /// Swap NFTs for tokens + SwapNftsForTokens { + token_id: String, + min_output: Uint128, + asset_recipient: String, + finder: Option, + }, +} + +#[cw_serde] +#[derive(QueryResponses)] +pub enum QueryMsg {} diff --git a/contracts/infinity-pool/src/pool.rs b/contracts/infinity-pool/src/pool.rs new file mode 100644 index 0000000..ee2038e --- /dev/null +++ b/contracts/infinity-pool/src/pool.rs @@ -0,0 +1,413 @@ +use crate::state::{BondingCurve, PoolConfig, PoolType, POOL_CONFIG}; +use crate::ContractError; + +use cosmwasm_std::{ + attr, ensure, Addr, Attribute, Decimal, DepsMut, Event, StdError, Storage, Uint128, +}; + +/// 100% represented as basis points +const MAX_BASIS_POINTS: u128 = 10000u128; + +pub struct Pool(PoolConfig); + +impl Pool { + /// Create a Pool object + pub fn new(config: PoolConfig) -> Self { + Self(config) + } + + // Save a Pool object to storage + pub fn save(&self, storage: &mut dyn Storage) -> Result<(), ContractError> { + self.validate()?; + POOL_CONFIG.save(storage, &self.0)?; + Ok(()) + } + + /// ---------------------------- + /// Getters + /// ---------------------------- + pub fn owner(&self) -> &Addr { + &self.0.owner + } + + pub fn collection(&self) -> &Addr { + &self.0.collection + } + + pub fn is_active(&self) -> bool { + self.0.is_active + } + + /// Get the recipient of assets for trades performed on this pool + pub fn recipient(&self) -> &Addr { + match &self.0.asset_recipient { + Some(addr) => addr, + None => &self.0.owner, + } + } + + pub fn finders_fee_percent(&self) -> Decimal { + self.0.finders_fee_percent + } + + pub fn reinvest_tokens(&self) -> bool { + self.0.reinvest_tokens + } + + pub fn reinvest_nfts(&self) -> bool { + self.0.reinvest_nfts + } + + /// ---------------------------- + /// Setters + /// ---------------------------- + + /// Activate the pool so that it may begin accepting trades + pub fn set_is_active(&mut self, is_active: bool) { + self.0.is_active = is_active; + } + + /// Verify that the pool is valid by checking invariants before save + pub fn validate(&self) -> Result<(), ContractError> { + ensure!( + !(self.0.bonding_curve == BondingCurve::Exponential + && self.0.delta.u128() >= MAX_BASIS_POINTS), + ContractError::InvalidPool( + "delta cannot exceed max basis points on exponential curves".to_string(), + ) + ); + + match self.0.pool_type { + PoolType::Token => { + ensure!( + self.0.total_nfts == 0, + ContractError::InvalidPool( + "total_nfts must be zero for token pool".to_string(), + ) + ); + ensure!( + self.0.spot_price != Uint128::zero(), + ContractError::InvalidPool( + "spot_price must be non-zero for token pool".to_string(), + ) + ); + ensure!( + self.0.swap_fee_percent == Decimal::zero(), + ContractError::InvalidPool( + "swap_fee_percent must be 0 for token pool".to_string(), + ) + ); + ensure!( + self.0.bonding_curve != BondingCurve::ConstantProduct, + ContractError::InvalidPool( + "constant product bonding curve cannot be used with token pools" + .to_string(), + ) + ); + ensure!( + !self.0.reinvest_tokens, + ContractError::InvalidPool( + "cannot reinvest tokens on one sided pools".to_string(), + ) + ); + ensure!( + !self.0.reinvest_nfts, + ContractError::InvalidPool( + "cannot reinvest nfts on one sided pools".to_string(), + ) + ); + }, + PoolType::Nft => { + ensure!( + self.0.spot_price != Uint128::zero(), + ContractError::InvalidPool( + "spot_price must be non-zero for nft pool".to_string(), + ) + ); + ensure!( + self.0.swap_fee_percent == Decimal::zero(), + ContractError::InvalidPool( + "swap_fee_percent must be 0 for nft pool".to_string(), + ) + ); + ensure!( + self.0.bonding_curve != BondingCurve::ConstantProduct, + ContractError::InvalidPool( + "constant product bonding curve cannot be used with nft pools".to_string(), + ) + ); + ensure!( + !self.0.reinvest_tokens, + ContractError::InvalidPool( + "cannot reinvest tokens on one sided pools".to_string(), + ) + ); + ensure!( + !self.0.reinvest_nfts, + ContractError::InvalidPool( + "cannot reinvest nfts on one sided pools".to_string(), + ) + ); + }, + PoolType::Trade => {}, + } + + Ok(()) + } + + // /// Deposit nfts into the pool + // pub fn deposit_nfts(&mut self, nft_token_ids: &Vec) -> Result<(), ContractError> { + // if self.pool_type == PoolType::Token { + // return Err(ContractError::InvalidPool( + // "cannot deposit nfts into token pool".to_string(), + // )); + // } + // self.total_nfts += nft_token_ids.len() as u64; + // Ok(()) + // } + + // /// Withdraw tokens from the pool + // pub fn withdraw_tokens(&mut self, amount: Uint128) -> Result<(), ContractError> { + // if self.pool_type == PoolType::Nft { + // return Err(ContractError::InvalidPool( + // "cannot withdraw tokens from nft pool".to_string(), + // )); + // } + // if self.total_tokens < amount { + // return Err(ContractError::Std(StdError::overflow(OverflowError { + // operation: cosmwasm_std::OverflowOperation::Sub, + // operand1: self.total_tokens.to_string(), + // operand2: amount.to_string(), + // }))); + // } + // self.total_tokens -= amount; + // Ok(()) + // } + + // /// Withdraw nfts from the pool + // pub fn withdraw_nfts(&mut self, nft_token_ids: &Vec) -> Result<(), ContractError> { + // if self.pool_type == PoolType::Token { + // return Err(ContractError::InvalidPool( + // "cannot withdraw nfts from token pool".to_string(), + // )); + // } + // if self.total_nfts < nft_token_ids.len() as u64 { + // return Err(ContractError::InternalError( + // "pool NFT overdraw".to_string(), + // )); + // } + // self.total_nfts -= nft_token_ids.len() as u64; + // Ok(()) + // } + + /// Returns whether or not the pool can buy NFTs + pub fn can_buy_nfts(&self) -> bool { + self.0.pool_type == PoolType::Trade || self.0.pool_type == PoolType::Token + } + + /// Returns whether or not the pool can sell NFTs + pub fn can_sell_nfts(&self) -> bool { + self.0.pool_type == PoolType::Trade || self.0.pool_type == PoolType::Nft + } + + // /// Returns the price at which this pool will sell NFTs + // /// Note: the buy_from_pool_quote is indexed by PoolQuote for future discovery + // pub fn get_buy_from_pool_quote( + // &self, + // min_quote: Uint128, + // ) -> Result, ContractError> { + // // Calculate the buy price with respect to pool types and bonding curves + // let buy_price = match self.pool_type { + // PoolType::Token => Err(ContractError::InvalidPool( + // "pool cannot sell nfts".to_string(), + // )), + // PoolType::Nft => Ok(self.spot_price), + // PoolType::Trade => match self.bonding_curve { + // BondingCurve::Linear => self + // .spot_price + // .checked_add(self.delta) + // .map_err(|e| ContractError::Std(StdError::overflow(e))), + // BondingCurve::Exponential => { + // let net_delta = Uint128::from(MAX_BASIS_POINTS) + // .checked_add(self.delta) + // .map_err(|e| ContractError::Std(StdError::overflow(e)))?; + // self.spot_price + // .checked_mul(net_delta) + // .map_err(|e| ContractError::Std(StdError::overflow(e)))? + // .checked_div(Uint128::from(MAX_BASIS_POINTS)) + // .map_err(|e| ContractError::Std(StdError::divide_by_zero(e)))? + // .checked_add(Uint128::one()) + // .map_err(|e| ContractError::Std(StdError::overflow(e))) + // } + // BondingCurve::ConstantProduct => { + // if self.total_nfts <= 1 { + // return Ok(None); + // } + // let buy_price = self + // .total_tokens + // .checked_div(Uint128::from(self.total_nfts - 1)) + // .map_err(|e| ContractError::Std(StdError::divide_by_zero(e)))? + // .checked_add(Uint128::one()) + // .map_err(|e| ContractError::Std(StdError::overflow(e)))?; + // Ok(buy_price) + // } + // }, + // }?; + // // If the pool has no NFTs to sell, or quote is below min, return None + // if self.total_nfts == 0 || buy_price < min_quote { + // return Ok(None); + // } + // Ok(Some(buy_price)) + // } + + /// Returns the price at which this pool will buy NFTs + pub fn get_sell_to_pool_quote( + &self, + total_tokens: Uint128, + min_price: Uint128, + ) -> Result { + let sell_quote = match self.0.bonding_curve { + BondingCurve::Linear | BondingCurve::Exponential => self.0.spot_price, + BondingCurve::ConstantProduct => { + total_tokens.checked_div(Uint128::from(self.0.total_nfts + 1)).unwrap() + }, + }; + ensure!( + sell_quote >= min_price, + ContractError::InvalidPoolQuote("sale price is below min price".to_string(),) + ); + ensure!( + sell_quote <= total_tokens, + ContractError::InvalidPoolQuote("pool has insufficient tokens".to_string(),) + ); + Ok(sell_quote) + } + + // /// Buy an NFT from the pool + // pub fn buy_nft_from_pool( + // &mut self, + // nft_swap: &NftSwap, + // sale_price: Uint128, + // ) -> Result<(), ContractError> { + // if !self.can_sell_nfts() { + // return Err(ContractError::InvalidPool( + // "pool cannot sell nfts".to_string(), + // )); + // } + // if !self.is_active { + // return Err(ContractError::InvalidPool("pool is not active".to_string())); + // } + + // // If sale price exceeds the max expected, return an error + // if sale_price > nft_swap.token_amount { + // return Err(ContractError::SwapError( + // "pool sale price is above max expected".to_string(), + // )); + // } + + // // Decrement total_nfts on pool + // if self.total_nfts == 0 { + // return Err(ContractError::SwapError( + // "pool does not own any NFTS".to_string(), + // )); + // } else { + // self.total_nfts -= 1; + // } + + // Ok(()) + // } + + /// Updates the spot price of the pool depending on the transaction type + pub fn update_spot_price_after_buy(&mut self, total_tokens: Uint128) -> Result<(), StdError> { + let result = match self.0.bonding_curve { + BondingCurve::Linear => { + self.0.spot_price.checked_sub(self.0.delta).map_err(StdError::overflow) + }, + BondingCurve::Exponential => { + let denominator = Uint128::from(MAX_BASIS_POINTS) + .checked_add(self.0.delta) + .map_err(StdError::overflow)?; + self.0 + .spot_price + .checked_mul(Uint128::from(MAX_BASIS_POINTS)) + .map_err(StdError::overflow)? + .checked_div(denominator) + .map_err(StdError::divide_by_zero) + }, + BondingCurve::ConstantProduct => total_tokens + .checked_div(Uint128::from(self.0.total_nfts)) + .map_err(StdError::divide_by_zero), + }; + match result { + Ok(new_spot_price) => { + self.0.spot_price = new_spot_price; + Ok(()) + }, + Err(e) => { + self.0.is_active = false; + Err(e) + }, + } + } + + /// Create an event with all the Pool properties + pub fn create_event_all_props(&self, event_type: &str) -> Result { + self.create_event( + event_type, + vec![ + "collection", + "owner", + "asset_recipient", + "pool_type", + "bonding_curve", + "spot_price", + "delta", + "total_nfts", + "is_active", + "swap_fee_percent", + "finders_fee_percent", + "reinvest_tokens", + "reinvest_nfts", + ], + ) + } + + /// Create an event with certain Pool properties + pub fn create_event( + &self, + event_type: &str, + attr_keys: Vec<&str>, + ) -> Result { + let mut attributes: Vec = vec![]; + for attr_keys in attr_keys { + let attribute = match attr_keys { + "collection" => attr("collection", self.0.collection.to_string()), + "owner" => attr("owner", self.0.owner.to_string()), + "asset_recipient" => attr( + "asset_recipient", + self.0 + .asset_recipient + .as_ref() + .map_or("None".to_string(), |addr| addr.to_string()), + ), + "pool_type" => attr("pool_type", self.0.pool_type.to_string()), + "bonding_curve" => attr("bonding_curve", self.0.bonding_curve.to_string()), + "spot_price" => attr("spot_price", self.0.spot_price.to_string()), + "delta" => attr("delta", self.0.delta.to_string()), + "total_nfts" => attr("total_nfts", self.0.total_nfts.to_string()), + "is_active" => attr("is_active", self.0.is_active.to_string()), + "swap_fee_percent" => attr("swap_fee_percent", self.0.swap_fee_percent.to_string()), + "finders_fee_percent" => { + attr("finders_fee_percent", self.0.finders_fee_percent.to_string()) + }, + "reinvest_tokens" => attr("reinvest_tokens", self.0.reinvest_tokens.to_string()), + "reinvest_nfts" => attr("reinvest_nfts", self.0.reinvest_nfts.to_string()), + _key => { + unreachable!("{} is not a valid attribute key", _key) + }, + }; + attributes.push(attribute); + } + Ok(Event::new(event_type).add_attributes(attributes)) + } +} diff --git a/contracts/infinity-pool/src/query.rs b/contracts/infinity-pool/src/query.rs new file mode 100644 index 0000000..0b02358 --- /dev/null +++ b/contracts/infinity-pool/src/query.rs @@ -0,0 +1,11 @@ +use crate::msg::QueryMsg; + +use cosmwasm_std::{Binary, Deps, Env, StdResult}; + +#[cfg(not(feature = "library"))] +use cosmwasm_std::entry_point; + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { + match msg {} +} diff --git a/contracts/infinity-pool/src/state.rs b/contracts/infinity-pool/src/state.rs new file mode 100644 index 0000000..f0ff21c --- /dev/null +++ b/contracts/infinity-pool/src/state.rs @@ -0,0 +1,81 @@ +use cosmwasm_schema::cw_serde; +use cosmwasm_std::{Addr, Decimal, Uint128}; +use cw_storage_plus::Item; +use std::fmt; + +/// PoolType refers to the assets held by the pool +/// * Token: A pool that holds fungible tokens +/// * Nft: A pool that holds NFTs +/// * Trade: A pool that holds both fungible tokens and NFTs +#[cw_serde] +pub enum PoolType { + Token, + Nft, + Trade, +} + +impl fmt::Display for PoolType { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{:?}", self) + } +} + +/// BondingCurve refers to the curve used to calculate the spot price for the pool +/// * Linear: A linear curve that increments by a constant amount (delta) +/// * Exponential: An exponential curve that increments by a percentage amount (delta) +/// * ConstantProduct: A constant product curve that maintains a constant product of the two assets +#[cw_serde] +pub enum BondingCurve { + Linear, + Exponential, + ConstantProduct, +} + +impl fmt::Display for BondingCurve { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{:?}", self) + } +} + +/// PoolConfig represents the configuration parameters for a pool +#[cw_serde] +pub struct PoolConfig { + /// The address of the NFT collection contract + pub collection: Addr, + /// The address of the pool owner + pub owner: Addr, + /// The address of the recipient of assets traded into the pool + pub asset_recipient: Option, + /// The type of assets held by the pool + pub pool_type: PoolType, + /// The bonding curve used to calculate the spot price + pub bonding_curve: BondingCurve, + /// A moving value used to derive the price at which the pool will trade assets + /// Note: this value is not necessarily the final sale price for pool assets + pub spot_price: Uint128, + /// The amount by which the spot price will increment/decrement + /// For linear curves, this is the constant amount + /// For exponential curves, this is the percentage amount (treated as basis points) + pub delta: Uint128, + /// The total number of NFTs held by the pool + pub total_nfts: u64, + /// The percentage of the swap that will be paid to the finder of a trade + pub finders_fee_percent: Decimal, + /// The percentage of the swap that will be paid to the pool owner + /// Note: this only applies to Trade pools + pub swap_fee_percent: Decimal, + /// Whether or not the pool is accepting trades + pub is_active: bool, + /// Whether or not the tokens sold into the pool will be reinvested + pub reinvest_tokens: bool, + /// Whether or not the NFTs sold into the pool will be reinvested + pub reinvest_nfts: bool, +} + +pub const POOL_CONFIG: Item = Item::new("pc"); + +// The address of the global gov contract +pub const GLOBAL_GOV: Item = Item::new("gg"); + +// The address of the infinity index contract +pub const INFINITY_INDEX: Item = Item::new("ii"); diff --git a/contracts/infinity-router/Cargo.toml b/contracts/infinity-router/Cargo.toml new file mode 100644 index 0000000..49f4eab --- /dev/null +++ b/contracts/infinity-router/Cargo.toml @@ -0,0 +1,47 @@ +[package] +name = "infinity-router" +version = { workspace = true } +edition = { workspace = true } +repository = { workspace = true } +license = { workspace = true } + +exclude = [ + # Those files are rust-optimizer artifacts. You might want to commit them for convenience but they should not be part of the source code publication. + "contract.wasm", + "hash.txt", +] + +[lib] +crate-type = ["cdylib", "rlib"] + +[features] +# for more explicit tests, cargo test --features=backtraces +backtraces = ["cosmwasm-std/backtraces"] +# use library feature to disable all instantiate/execute/query exports +library = [] + +[dependencies] +# infinity-macros = { workspace = true } +infinity-shared = { workspace = true } +infinity-index = { workspace = true } +# infinity-swap = { workspace = true } +infinity-pool = { workspace = true } +cosmwasm-std = { workspace = true } +cosmwasm-schema = { workspace = true } +cw-storage-plus = { workspace = true } +cw-storage-macro = { workspace = true } +# cosmwasm-storage = { workspace = true } +# cw-utils = { workspace = true } +cw2 = { workspace = true } +thiserror = { workspace = true } +# anyhow = { workspace = true } +# sg1 = { workspace = true } +# sg2 = { workspace = true } +# sg721-base = { workspace = true } +# sg721 = { workspace = true } +sg-std = { workspace = true } +# sg-marketplace = { workspace = true } +sg-marketplace-common = { workspace = true } +sha2 = { workspace = true } +# cw721-base = { workspace = true } +cw721 = { workspace = true } \ No newline at end of file diff --git a/contracts/infinity-router/src/error.rs b/contracts/infinity-router/src/error.rs new file mode 100644 index 0000000..14eb8fb --- /dev/null +++ b/contracts/infinity-router/src/error.rs @@ -0,0 +1,12 @@ +use cosmwasm_std::StdError; +use infinity_shared::InfinityError; +use thiserror::Error; + +#[derive(Error, Debug, PartialEq)] +pub enum ContractError { + #[error("{0}")] + Std(#[from] StdError), + + #[error("{0}")] + InfinityError(#[from] InfinityError), +} diff --git a/contracts/infinity-router/src/execute.rs b/contracts/infinity-router/src/execute.rs new file mode 100644 index 0000000..59659c2 --- /dev/null +++ b/contracts/infinity-router/src/execute.rs @@ -0,0 +1,114 @@ +use crate::msg::ExecuteMsg; +use crate::{error::ContractError, state::CONFIG}; + +use cosmwasm_std::{to_binary, Addr, DepsMut, Env, MessageInfo, SubMsg, WasmMsg}; +use cw721::Cw721ExecuteMsg; +use infinity_index::msg::{PoolQuoteResponse, QueryMsg}; +use infinity_pool::msg::ExecuteMsg as InfinityPoolExecuteMsg; +use infinity_shared::interface::NftOrder; +use infinity_shared::shared::only_nft_owner; +use sg_marketplace_common::transfer_nft; +use sg_std::Response; + +#[cfg(not(feature = "library"))] +use cosmwasm_std::entry_point; + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn execute( + deps: DepsMut, + env: Env, + info: MessageInfo, + msg: ExecuteMsg, +) -> Result { + let api = deps.api; + + match msg { + ExecuteMsg::SwapNftsForTokens { + collection, + sender, + nft_orders, + } => execute_swap_nfts_for_tokens( + deps, + env, + info, + api.addr_validate(&sender)?, + api.addr_validate(&collection)?, + nft_orders, + ), + } +} + +pub fn execute_swap_nfts_for_tokens( + deps: DepsMut, + env: Env, + info: MessageInfo, + sender: Addr, + collection: Addr, + mut nft_orders: Vec, +) -> Result { + let config = CONFIG.load(deps.storage)?; + + let mut response = Response::new(); + + let nft_order = nft_orders.remove(0); + + only_nft_owner(&deps.querier, deps.api, &sender, &collection, &nft_order.token_id)?; + + let sell_quote = deps + .querier + .query_wasm_smart::( + &config.infinity_index, + &QueryMsg::QuoteSellToPool { + collection: collection.to_string(), + limit: 1, + }, + )? + .pool_quotes + .pop(); + + if !sell_quote.is_some() { + return Ok(response); + } + + let sell_quote = sell_quote.unwrap(); + + response = response.add_submessage(SubMsg::new(WasmMsg::Execute { + contract_addr: collection.to_string(), + msg: to_binary(&Cw721ExecuteMsg::ApproveAll { + operator: sell_quote.pool.to_string(), + expires: None, + })?, + funds: vec![], + })); + + response = response.add_submessage(transfer_nft( + &collection, + &nft_order.token_id, + &env.contract.address, + )); + + response = response.add_submessage(SubMsg::new(WasmMsg::Execute { + contract_addr: sell_quote.pool.to_string(), + msg: to_binary(&InfinityPoolExecuteMsg::SwapNftsForTokens { + token_id: nft_order.token_id, + min_output: nft_order.amount, + asset_recipient: sender.to_string(), + finder: None, + })?, + funds: vec![], + })); + + if nft_orders.len() > 0 { + response = response.add_submessage(SubMsg::new(WasmMsg::Execute { + contract_addr: env.contract.address.to_string(), + msg: to_binary(&ExecuteMsg::SwapNftsForTokens { + collection: collection.to_string(), + sender: sender.to_string(), + nft_orders, + })?, + funds: vec![], + })); + } + + Ok(response) +} diff --git a/contracts/infinity-marketplace-adapter/src/instantiate.rs b/contracts/infinity-router/src/instantiate.rs similarity index 65% rename from contracts/infinity-marketplace-adapter/src/instantiate.rs rename to contracts/infinity-router/src/instantiate.rs index ef83f02..c98970c 100644 --- a/contracts/infinity-marketplace-adapter/src/instantiate.rs +++ b/contracts/infinity-router/src/instantiate.rs @@ -1,11 +1,12 @@ use crate::error::ContractError; use crate::msg::InstantiateMsg; use crate::state::{Config, CONFIG}; + use cosmwasm_std::{DepsMut, Env, MessageInfo}; use cw2::set_contract_version; use sg_std::Response; -pub const CONTRACT_NAME: &str = "crates.io:infinity-marketplace-adapter"; +pub const CONTRACT_NAME: &str = "crates.io:infinity-factory"; pub const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); #[cfg(not(feature = "library"))] @@ -14,23 +15,22 @@ use cosmwasm_std::entry_point; #[cfg_attr(not(feature = "library"), entry_point)] pub fn instantiate( deps: DepsMut, - _env: Env, + env: Env, _info: MessageInfo, msg: InstantiateMsg, ) -> Result { set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?; - let config = Config { - marketplace: deps.api.addr_validate(&msg.marketplace)?, - max_batch_size: msg.max_batch_size, - }; - - CONFIG.save(deps.storage, &config)?; + CONFIG.save( + deps.storage, + &Config { + infinity_index: deps.api.addr_validate(&msg.infinity_index)?, + }, + )?; Ok(Response::new() .add_attribute("action", "instantiate") .add_attribute("contract_name", CONTRACT_NAME) .add_attribute("contract_version", CONTRACT_VERSION) - .add_attribute("marketplace", config.marketplace) - .add_attribute("max_batch_size", config.max_batch_size.to_string())) + .add_attribute("infinity_index", msg.infinity_index)) } diff --git a/contracts/infinity-router/src/lib.rs b/contracts/infinity-router/src/lib.rs new file mode 100644 index 0000000..33194e1 --- /dev/null +++ b/contracts/infinity-router/src/lib.rs @@ -0,0 +1,9 @@ +pub mod execute; +pub mod instantiate; +pub mod msg; +pub mod query; +pub mod state; + +mod error; + +pub use error::ContractError; diff --git a/contracts/infinity-router/src/msg.rs b/contracts/infinity-router/src/msg.rs new file mode 100644 index 0000000..99a1043 --- /dev/null +++ b/contracts/infinity-router/src/msg.rs @@ -0,0 +1,22 @@ +use cosmwasm_schema::{cw_serde, QueryResponses}; +use cosmwasm_std::Uint128; +use infinity_shared::interface::NftOrder; + +#[cw_serde] +pub struct InstantiateMsg { + /// The address of the infinity index contract + pub infinity_index: String, +} + +#[cw_serde] +pub enum ExecuteMsg { + SwapNftsForTokens { + collection: String, + sender: String, + nft_orders: Vec, + }, +} + +#[cw_serde] +#[derive(QueryResponses)] +pub enum QueryMsg {} diff --git a/contracts/infinity-router/src/query.rs b/contracts/infinity-router/src/query.rs new file mode 100644 index 0000000..42cae80 --- /dev/null +++ b/contracts/infinity-router/src/query.rs @@ -0,0 +1,11 @@ +use crate::msg::QueryMsg; + +use cosmwasm_std::{to_binary, Addr, Binary, Deps, Env, Order, StdResult}; + +#[cfg(not(feature = "library"))] +use cosmwasm_std::entry_point; + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { + match msg {} +} diff --git a/contracts/infinity-router/src/state.rs b/contracts/infinity-router/src/state.rs new file mode 100644 index 0000000..a25b80d --- /dev/null +++ b/contracts/infinity-router/src/state.rs @@ -0,0 +1,11 @@ +use cosmwasm_schema::cw_serde; +use cosmwasm_std::{Addr, Uint128}; +use cw_storage_macro::index_list; +use cw_storage_plus::{IndexedMap, Item, Map, MultiIndex}; + +#[cw_serde] +pub struct Config { + pub infinity_index: Addr, +} + +pub const CONFIG: Item = Item::new("cfg"); diff --git a/contracts/infinity-swap/examples/schema.rs b/contracts/infinity-swap/examples/schema.rs deleted file mode 100644 index aa31701..0000000 --- a/contracts/infinity-swap/examples/schema.rs +++ /dev/null @@ -1,31 +0,0 @@ -use cosmwasm_schema::{export_schema, remove_schemas, schema_for}; -use cosmwasm_std::Uint128; -use infinity_swap::msg::{ - ConfigResponse, ExecuteMsg, InstantiateMsg, NftSwap, NftTokenIdsResponse, PoolNftSwap, - PoolQuoteResponse, PoolsByIdResponse, PoolsResponse, QueryMsg, QueryOptions, SwapParams, - SwapResponse, -}; -use std::env::current_dir; -use std::fs::create_dir_all; - -fn main() { - let mut out_dir = current_dir().unwrap(); - out_dir.push("schema"); - create_dir_all(&out_dir).unwrap(); - remove_schemas(&out_dir).unwrap(); - - export_schema(&schema_for!(ConfigResponse), &out_dir); - export_schema(&schema_for!(ExecuteMsg), &out_dir); - export_schema(&schema_for!(InstantiateMsg), &out_dir); - export_schema(&schema_for!(NftSwap), &out_dir); - export_schema(&schema_for!(PoolNftSwap), &out_dir); - export_schema(&schema_for!(PoolQuoteResponse), &out_dir); - export_schema(&schema_for!(PoolsByIdResponse), &out_dir); - export_schema(&schema_for!(NftTokenIdsResponse), &out_dir); - export_schema(&schema_for!(PoolsResponse), &out_dir); - export_schema(&schema_for!(QueryMsg), &out_dir); - export_schema(&schema_for!(QueryOptions), &out_dir); - export_schema(&schema_for!(QueryOptions<(Uint128, u64)>), &out_dir); - export_schema(&schema_for!(SwapParams), &out_dir); - export_schema(&schema_for!(SwapResponse), &out_dir); -} diff --git a/contracts/infinity-swap/schema/config_response.json b/contracts/infinity-swap/schema/config_response.json deleted file mode 100644 index f84608e..0000000 --- a/contracts/infinity-swap/schema/config_response.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ConfigResponse", - "type": "object", - "required": [ - "config" - ], - "properties": { - "config": { - "$ref": "#/definitions/Config" - } - }, - "additionalProperties": false, - "definitions": { - "Addr": { - "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", - "type": "string" - }, - "Config": { - "description": "The global configuration object for the protocol", - "type": "object", - "required": [ - "marketplace_addr" - ], - "properties": { - "developer": { - "description": "The address of the developer who will receive a portion of the fair burn", - "anyOf": [ - { - "$ref": "#/definitions/Addr" - }, - { - "type": "null" - } - ] - }, - "marketplace_addr": { - "description": "The address of the marketplace contract", - "allOf": [ - { - "$ref": "#/definitions/Addr" - } - ] - } - }, - "additionalProperties": false - } - } -} diff --git a/contracts/infinity-swap/schema/execute_msg.json b/contracts/infinity-swap/schema/execute_msg.json deleted file mode 100644 index d3b749e..0000000 --- a/contracts/infinity-swap/schema/execute_msg.json +++ /dev/null @@ -1,761 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ExecuteMsg", - "oneOf": [ - { - "description": "Create a new pool, defaults to an inactive state", - "type": "object", - "required": [ - "create_token_pool" - ], - "properties": { - "create_token_pool": { - "type": "object", - "required": [ - "bonding_curve", - "collection", - "delta", - "finders_fee_bps", - "spot_price" - ], - "properties": { - "asset_recipient": { - "type": [ - "string", - "null" - ] - }, - "bonding_curve": { - "$ref": "#/definitions/BondingCurve" - }, - "collection": { - "type": "string" - }, - "delta": { - "$ref": "#/definitions/Uint128" - }, - "finders_fee_bps": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, - "spot_price": { - "$ref": "#/definitions/Uint128" - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "type": "object", - "required": [ - "create_nft_pool" - ], - "properties": { - "create_nft_pool": { - "type": "object", - "required": [ - "bonding_curve", - "collection", - "delta", - "finders_fee_bps", - "spot_price" - ], - "properties": { - "asset_recipient": { - "type": [ - "string", - "null" - ] - }, - "bonding_curve": { - "$ref": "#/definitions/BondingCurve" - }, - "collection": { - "type": "string" - }, - "delta": { - "$ref": "#/definitions/Uint128" - }, - "finders_fee_bps": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, - "spot_price": { - "$ref": "#/definitions/Uint128" - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "type": "object", - "required": [ - "create_trade_pool" - ], - "properties": { - "create_trade_pool": { - "type": "object", - "required": [ - "bonding_curve", - "collection", - "delta", - "finders_fee_bps", - "reinvest_nfts", - "reinvest_tokens", - "spot_price", - "swap_fee_bps" - ], - "properties": { - "asset_recipient": { - "type": [ - "string", - "null" - ] - }, - "bonding_curve": { - "$ref": "#/definitions/BondingCurve" - }, - "collection": { - "type": "string" - }, - "delta": { - "$ref": "#/definitions/Uint128" - }, - "finders_fee_bps": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, - "reinvest_nfts": { - "type": "boolean" - }, - "reinvest_tokens": { - "type": "boolean" - }, - "spot_price": { - "$ref": "#/definitions/Uint128" - }, - "swap_fee_bps": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "Deposit tokens into a pool", - "type": "object", - "required": [ - "deposit_tokens" - ], - "properties": { - "deposit_tokens": { - "type": "object", - "required": [ - "pool_id" - ], - "properties": { - "pool_id": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "Deposit NFTs into a pool", - "type": "object", - "required": [ - "deposit_nfts" - ], - "properties": { - "deposit_nfts": { - "type": "object", - "required": [ - "collection", - "nft_token_ids", - "pool_id" - ], - "properties": { - "collection": { - "type": "string" - }, - "nft_token_ids": { - "type": "array", - "items": { - "type": "string" - } - }, - "pool_id": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "Withdraw tokens from a pool", - "type": "object", - "required": [ - "withdraw_tokens" - ], - "properties": { - "withdraw_tokens": { - "type": "object", - "required": [ - "amount", - "pool_id" - ], - "properties": { - "amount": { - "$ref": "#/definitions/Uint128" - }, - "asset_recipient": { - "type": [ - "string", - "null" - ] - }, - "pool_id": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "Withdraw all tokens from a pool", - "type": "object", - "required": [ - "withdraw_all_tokens" - ], - "properties": { - "withdraw_all_tokens": { - "type": "object", - "required": [ - "pool_id" - ], - "properties": { - "asset_recipient": { - "type": [ - "string", - "null" - ] - }, - "pool_id": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "Withdraw NFTs from a pool", - "type": "object", - "required": [ - "withdraw_nfts" - ], - "properties": { - "withdraw_nfts": { - "type": "object", - "required": [ - "nft_token_ids", - "pool_id" - ], - "properties": { - "asset_recipient": { - "type": [ - "string", - "null" - ] - }, - "nft_token_ids": { - "type": "array", - "items": { - "type": "string" - } - }, - "pool_id": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "Withdraw all NFTs from a pool", - "type": "object", - "required": [ - "withdraw_all_nfts" - ], - "properties": { - "withdraw_all_nfts": { - "type": "object", - "required": [ - "pool_id" - ], - "properties": { - "asset_recipient": { - "type": [ - "string", - "null" - ] - }, - "pool_id": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "Update the parameters of a pool", - "type": "object", - "required": [ - "update_pool_config" - ], - "properties": { - "update_pool_config": { - "type": "object", - "required": [ - "pool_id" - ], - "properties": { - "asset_recipient": { - "type": [ - "string", - "null" - ] - }, - "delta": { - "anyOf": [ - { - "$ref": "#/definitions/Uint128" - }, - { - "type": "null" - } - ] - }, - "finders_fee_bps": { - "type": [ - "integer", - "null" - ], - "format": "uint64", - "minimum": 0.0 - }, - "pool_id": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, - "reinvest_nfts": { - "type": [ - "boolean", - "null" - ] - }, - "reinvest_tokens": { - "type": [ - "boolean", - "null" - ] - }, - "spot_price": { - "anyOf": [ - { - "$ref": "#/definitions/Uint128" - }, - { - "type": "null" - } - ] - }, - "swap_fee_bps": { - "type": [ - "integer", - "null" - ], - "format": "uint64", - "minimum": 0.0 - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "type": "object", - "required": [ - "set_active_pool" - ], - "properties": { - "set_active_pool": { - "type": "object", - "required": [ - "is_active", - "pool_id" - ], - "properties": { - "is_active": { - "type": "boolean" - }, - "pool_id": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "Remove a pool from contract storage and indexing", - "type": "object", - "required": [ - "remove_pool" - ], - "properties": { - "remove_pool": { - "type": "object", - "required": [ - "pool_id" - ], - "properties": { - "asset_recipient": { - "type": [ - "string", - "null" - ] - }, - "pool_id": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "Swap NFTs for tokens directly with a specified pool", - "type": "object", - "required": [ - "direct_swap_nfts_for_tokens" - ], - "properties": { - "direct_swap_nfts_for_tokens": { - "type": "object", - "required": [ - "nfts_to_swap", - "pool_id", - "swap_params" - ], - "properties": { - "nfts_to_swap": { - "type": "array", - "items": { - "$ref": "#/definitions/NftSwap" - } - }, - "pool_id": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, - "swap_params": { - "$ref": "#/definitions/SwapParams" - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "Swap NFTs for tokens at optimal sale prices", - "type": "object", - "required": [ - "swap_nfts_for_tokens" - ], - "properties": { - "swap_nfts_for_tokens": { - "type": "object", - "required": [ - "collection", - "nfts_to_swap", - "swap_params" - ], - "properties": { - "collection": { - "type": "string" - }, - "nfts_to_swap": { - "type": "array", - "items": { - "$ref": "#/definitions/NftSwap" - } - }, - "swap_params": { - "$ref": "#/definitions/SwapParams" - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "Swap tokens for NFTs directly with a specified pool Note: client must specify which NFTs they want to swap for", - "type": "object", - "required": [ - "direct_swap_tokens_for_specific_nfts" - ], - "properties": { - "direct_swap_tokens_for_specific_nfts": { - "type": "object", - "required": [ - "nfts_to_swap_for", - "pool_id", - "swap_params" - ], - "properties": { - "nfts_to_swap_for": { - "type": "array", - "items": { - "$ref": "#/definitions/NftSwap" - } - }, - "pool_id": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, - "swap_params": { - "$ref": "#/definitions/SwapParams" - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "Swap tokens for specific NFTs at optimal purchase prices", - "type": "object", - "required": [ - "swap_tokens_for_specific_nfts" - ], - "properties": { - "swap_tokens_for_specific_nfts": { - "type": "object", - "required": [ - "collection", - "pool_nfts_to_swap_for", - "swap_params" - ], - "properties": { - "collection": { - "type": "string" - }, - "pool_nfts_to_swap_for": { - "type": "array", - "items": { - "$ref": "#/definitions/PoolNftSwap" - } - }, - "swap_params": { - "$ref": "#/definitions/SwapParams" - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "Swap tokens for any NFTs at optimal purchase prices", - "type": "object", - "required": [ - "swap_tokens_for_any_nfts" - ], - "properties": { - "swap_tokens_for_any_nfts": { - "type": "object", - "required": [ - "collection", - "max_expected_token_input", - "swap_params" - ], - "properties": { - "collection": { - "type": "string" - }, - "max_expected_token_input": { - "type": "array", - "items": { - "$ref": "#/definitions/Uint128" - } - }, - "swap_params": { - "$ref": "#/definitions/SwapParams" - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - } - ], - "definitions": { - "BondingCurve": { - "description": "BondingCurve refers to the curve used to calculate the spot price for the pool * Linear: A linear curve that increments by a constant amount (delta) * Exponential: An exponential curve that increments by a percentage amount (delta) * ConstantProduct: A constant product curve that maintains a constant product of the two assets", - "type": "string", - "enum": [ - "linear", - "exponential", - "constant_product" - ] - }, - "NftSwap": { - "description": "NftSwap contains the parameters for an NFT swap", - "type": "object", - "required": [ - "nft_token_id", - "token_amount" - ], - "properties": { - "nft_token_id": { - "description": "The id of the NFT to swap", - "type": "string" - }, - "token_amount": { - "description": "The amount of tokens to accept in exchange for the NFT Note: this could be the minimum acceptable amount for a sale or the maximum acceptable amount for a purchase", - "allOf": [ - { - "$ref": "#/definitions/Uint128" - } - ] - } - }, - "additionalProperties": false - }, - "PoolNftSwap": { - "description": "PoolNftSwap is the parent of NftSwap and organizes swaps by pool_id", - "type": "object", - "required": [ - "nft_swaps", - "pool_id" - ], - "properties": { - "nft_swaps": { - "description": "The NFT swaps to execute", - "type": "array", - "items": { - "$ref": "#/definitions/NftSwap" - } - }, - "pool_id": { - "description": "The id of the pool to swap in", - "type": "integer", - "format": "uint64", - "minimum": 0.0 - } - }, - "additionalProperties": false - }, - "SwapParams": { - "description": "SwapParams contains the parameters for a swap", - "type": "object", - "required": [ - "deadline", - "robust" - ], - "properties": { - "asset_recipient": { - "description": "The address to receive the assets from the swap, if not specified is set to sender", - "type": [ - "string", - "null" - ] - }, - "deadline": { - "description": "The deadline after which the swap will be rejected", - "allOf": [ - { - "$ref": "#/definitions/Timestamp" - } - ] - }, - "finder": { - "description": "The address of the finder, will receive a portion of the fees equal to percentage set by the pool", - "type": [ - "string", - "null" - ] - }, - "robust": { - "description": "Whether or not to revert the entire trade if one of the swaps fails", - "type": "boolean" - } - }, - "additionalProperties": false - }, - "Timestamp": { - "description": "A point in time in nanosecond precision.\n\nThis type can represent times from 1970-01-01T00:00:00Z to 2554-07-21T23:34:33Z.\n\n## Examples\n\n``` # use cosmwasm_std::Timestamp; let ts = Timestamp::from_nanos(1_000_000_202); assert_eq!(ts.nanos(), 1_000_000_202); assert_eq!(ts.seconds(), 1); assert_eq!(ts.subsec_nanos(), 202);\n\nlet ts = ts.plus_seconds(2); assert_eq!(ts.nanos(), 3_000_000_202); assert_eq!(ts.seconds(), 3); assert_eq!(ts.subsec_nanos(), 202); ```", - "allOf": [ - { - "$ref": "#/definitions/Uint64" - } - ] - }, - "Uint128": { - "description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```", - "type": "string" - }, - "Uint64": { - "description": "A thin wrapper around u64 that is using strings for JSON encoding/decoding, such that the full u64 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u64` to get the value out:\n\n``` # use cosmwasm_std::Uint64; let a = Uint64::from(42u64); assert_eq!(a.u64(), 42);\n\nlet b = Uint64::from(70u32); assert_eq!(b.u64(), 70); ```", - "type": "string" - } - } -} diff --git a/contracts/infinity-swap/schema/instantiate_msg.json b/contracts/infinity-swap/schema/instantiate_msg.json deleted file mode 100644 index 1c59e60..0000000 --- a/contracts/infinity-swap/schema/instantiate_msg.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "InstantiateMsg", - "type": "object", - "required": [ - "denom", - "marketplace_addr" - ], - "properties": { - "denom": { - "description": "The fungible token used in the pools", - "type": "string" - }, - "developer": { - "description": "The address of the developer who will receive a portion of the fair burn", - "type": [ - "string", - "null" - ] - }, - "marketplace_addr": { - "description": "The address of the marketplace contract", - "type": "string" - } - }, - "additionalProperties": false -} diff --git a/contracts/infinity-swap/schema/nft_swap.json b/contracts/infinity-swap/schema/nft_swap.json deleted file mode 100644 index ff4b946..0000000 --- a/contracts/infinity-swap/schema/nft_swap.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "NftSwap", - "description": "NftSwap contains the parameters for an NFT swap", - "type": "object", - "required": [ - "nft_token_id", - "token_amount" - ], - "properties": { - "nft_token_id": { - "description": "The id of the NFT to swap", - "type": "string" - }, - "token_amount": { - "description": "The amount of tokens to accept in exchange for the NFT Note: this could be the minimum acceptable amount for a sale or the maximum acceptable amount for a purchase", - "allOf": [ - { - "$ref": "#/definitions/Uint128" - } - ] - } - }, - "additionalProperties": false, - "definitions": { - "Uint128": { - "description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```", - "type": "string" - } - } -} diff --git a/contracts/infinity-swap/schema/nft_token_ids_response.json b/contracts/infinity-swap/schema/nft_token_ids_response.json deleted file mode 100644 index 903bb4b..0000000 --- a/contracts/infinity-swap/schema/nft_token_ids_response.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "NftTokenIdsResponse", - "type": "object", - "required": [ - "nft_token_ids", - "pool_id" - ], - "properties": { - "nft_token_ids": { - "type": "array", - "items": { - "type": "string" - } - }, - "pool_id": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - } - }, - "additionalProperties": false -} diff --git a/contracts/infinity-swap/schema/pool_nft_swap.json b/contracts/infinity-swap/schema/pool_nft_swap.json deleted file mode 100644 index bf30be8..0000000 --- a/contracts/infinity-swap/schema/pool_nft_swap.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "PoolNftSwap", - "description": "PoolNftSwap is the parent of NftSwap and organizes swaps by pool_id", - "type": "object", - "required": [ - "nft_swaps", - "pool_id" - ], - "properties": { - "nft_swaps": { - "description": "The NFT swaps to execute", - "type": "array", - "items": { - "$ref": "#/definitions/NftSwap" - } - }, - "pool_id": { - "description": "The id of the pool to swap in", - "type": "integer", - "format": "uint64", - "minimum": 0.0 - } - }, - "additionalProperties": false, - "definitions": { - "NftSwap": { - "description": "NftSwap contains the parameters for an NFT swap", - "type": "object", - "required": [ - "nft_token_id", - "token_amount" - ], - "properties": { - "nft_token_id": { - "description": "The id of the NFT to swap", - "type": "string" - }, - "token_amount": { - "description": "The amount of tokens to accept in exchange for the NFT Note: this could be the minimum acceptable amount for a sale or the maximum acceptable amount for a purchase", - "allOf": [ - { - "$ref": "#/definitions/Uint128" - } - ] - } - }, - "additionalProperties": false - }, - "Uint128": { - "description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```", - "type": "string" - } - } -} diff --git a/contracts/infinity-swap/schema/pool_quote_response.json b/contracts/infinity-swap/schema/pool_quote_response.json deleted file mode 100644 index e4709b7..0000000 --- a/contracts/infinity-swap/schema/pool_quote_response.json +++ /dev/null @@ -1,61 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "PoolQuoteResponse", - "type": "object", - "required": [ - "pool_quotes" - ], - "properties": { - "pool_quotes": { - "type": "array", - "items": { - "$ref": "#/definitions/PoolQuote" - } - } - }, - "additionalProperties": false, - "definitions": { - "Addr": { - "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", - "type": "string" - }, - "PoolQuote": { - "description": "PoolQuote represents a quote at which assets can be bought or sold from a pool", - "type": "object", - "required": [ - "collection", - "id", - "quote_price" - ], - "properties": { - "collection": { - "description": "The address of the NFT collection contract", - "allOf": [ - { - "$ref": "#/definitions/Addr" - } - ] - }, - "id": { - "description": "The unique id of the pool quote, also corresponds to a pool_id", - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, - "quote_price": { - "description": "The price at which assets can be bought or sold", - "allOf": [ - { - "$ref": "#/definitions/Uint128" - } - ] - } - }, - "additionalProperties": false - }, - "Uint128": { - "description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```", - "type": "string" - } - } -} diff --git a/contracts/infinity-swap/schema/pools_by_id_response.json b/contracts/infinity-swap/schema/pools_by_id_response.json deleted file mode 100644 index 784adab..0000000 --- a/contracts/infinity-swap/schema/pools_by_id_response.json +++ /dev/null @@ -1,198 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "PoolsByIdResponse", - "type": "object", - "required": [ - "pools" - ], - "properties": { - "pools": { - "type": "array", - "items": { - "type": "array", - "items": [ - { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, - { - "anyOf": [ - { - "$ref": "#/definitions/Pool" - }, - { - "type": "null" - } - ] - } - ], - "maxItems": 2, - "minItems": 2 - } - } - }, - "additionalProperties": false, - "definitions": { - "Addr": { - "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", - "type": "string" - }, - "BondingCurve": { - "description": "BondingCurve refers to the curve used to calculate the spot price for the pool * Linear: A linear curve that increments by a constant amount (delta) * Exponential: An exponential curve that increments by a percentage amount (delta) * ConstantProduct: A constant product curve that maintains a constant product of the two assets", - "type": "string", - "enum": [ - "linear", - "exponential", - "constant_product" - ] - }, - "Decimal": { - "description": "A fixed-point decimal value with 18 fractional digits, i.e. Decimal(1_000_000_000_000_000_000) == 1.0\n\nThe greatest possible value that can be represented is 340282366920938463463.374607431768211455 (which is (2^128 - 1) / 10^18)", - "type": "string" - }, - "Pool": { - "description": "Pool represents a pool of assets that can be swapped", - "type": "object", - "required": [ - "bonding_curve", - "collection", - "delta", - "finders_fee_percent", - "id", - "is_active", - "owner", - "pool_type", - "reinvest_nfts", - "reinvest_tokens", - "spot_price", - "swap_fee_percent", - "total_nfts", - "total_tokens" - ], - "properties": { - "asset_recipient": { - "description": "The address of the recipient of assets traded into the pool", - "anyOf": [ - { - "$ref": "#/definitions/Addr" - }, - { - "type": "null" - } - ] - }, - "bonding_curve": { - "description": "The bonding curve used to calculate the spot price", - "allOf": [ - { - "$ref": "#/definitions/BondingCurve" - } - ] - }, - "collection": { - "description": "The address of the NFT collection contract", - "allOf": [ - { - "$ref": "#/definitions/Addr" - } - ] - }, - "delta": { - "description": "The amount by which the spot price will increment/decrement For linear curves, this is the constant amount For exponential curves, this is the percentage amount (treated as basis points)", - "allOf": [ - { - "$ref": "#/definitions/Uint128" - } - ] - }, - "finders_fee_percent": { - "description": "The percentage of the swap that will be paid to the finder of a trade", - "allOf": [ - { - "$ref": "#/definitions/Decimal" - } - ] - }, - "id": { - "description": "The unique id of the pool", - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, - "is_active": { - "description": "Whether or not the pool is accepting trades", - "type": "boolean" - }, - "owner": { - "description": "The address of the pool owner", - "allOf": [ - { - "$ref": "#/definitions/Addr" - } - ] - }, - "pool_type": { - "description": "The type of assets held by the pool", - "allOf": [ - { - "$ref": "#/definitions/PoolType" - } - ] - }, - "reinvest_nfts": { - "description": "Whether or not the NFTs sold into the pool will be reinvested", - "type": "boolean" - }, - "reinvest_tokens": { - "description": "Whether or not the tokens sold into the pool will be reinvested", - "type": "boolean" - }, - "spot_price": { - "description": "A moving value used to derive the price at which the pool will trade assets Note: this value is not necessarily the final sale price for pool assets", - "allOf": [ - { - "$ref": "#/definitions/Uint128" - } - ] - }, - "swap_fee_percent": { - "description": "The percentage of the swap that will be paid to the pool owner Note: this only applies to Trade pools", - "allOf": [ - { - "$ref": "#/definitions/Decimal" - } - ] - }, - "total_nfts": { - "description": "The total number of NFTs held by the pool", - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, - "total_tokens": { - "description": "The total amount of tokens held by the pool", - "allOf": [ - { - "$ref": "#/definitions/Uint128" - } - ] - } - }, - "additionalProperties": false - }, - "PoolType": { - "description": "PoolType refers to the assets held by the pool * Token: A pool that holds fungible tokens * Nft: A pool that holds NFTs * Trade: A pool that holds both fungible tokens and NFTs", - "type": "string", - "enum": [ - "token", - "nft", - "trade" - ] - }, - "Uint128": { - "description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```", - "type": "string" - } - } -} diff --git a/contracts/infinity-swap/schema/pools_response.json b/contracts/infinity-swap/schema/pools_response.json deleted file mode 100644 index dc7f76c..0000000 --- a/contracts/infinity-swap/schema/pools_response.json +++ /dev/null @@ -1,179 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "PoolsResponse", - "type": "object", - "required": [ - "pools" - ], - "properties": { - "pools": { - "type": "array", - "items": { - "$ref": "#/definitions/Pool" - } - } - }, - "additionalProperties": false, - "definitions": { - "Addr": { - "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", - "type": "string" - }, - "BondingCurve": { - "description": "BondingCurve refers to the curve used to calculate the spot price for the pool * Linear: A linear curve that increments by a constant amount (delta) * Exponential: An exponential curve that increments by a percentage amount (delta) * ConstantProduct: A constant product curve that maintains a constant product of the two assets", - "type": "string", - "enum": [ - "linear", - "exponential", - "constant_product" - ] - }, - "Decimal": { - "description": "A fixed-point decimal value with 18 fractional digits, i.e. Decimal(1_000_000_000_000_000_000) == 1.0\n\nThe greatest possible value that can be represented is 340282366920938463463.374607431768211455 (which is (2^128 - 1) / 10^18)", - "type": "string" - }, - "Pool": { - "description": "Pool represents a pool of assets that can be swapped", - "type": "object", - "required": [ - "bonding_curve", - "collection", - "delta", - "finders_fee_percent", - "id", - "is_active", - "owner", - "pool_type", - "reinvest_nfts", - "reinvest_tokens", - "spot_price", - "swap_fee_percent", - "total_nfts", - "total_tokens" - ], - "properties": { - "asset_recipient": { - "description": "The address of the recipient of assets traded into the pool", - "anyOf": [ - { - "$ref": "#/definitions/Addr" - }, - { - "type": "null" - } - ] - }, - "bonding_curve": { - "description": "The bonding curve used to calculate the spot price", - "allOf": [ - { - "$ref": "#/definitions/BondingCurve" - } - ] - }, - "collection": { - "description": "The address of the NFT collection contract", - "allOf": [ - { - "$ref": "#/definitions/Addr" - } - ] - }, - "delta": { - "description": "The amount by which the spot price will increment/decrement For linear curves, this is the constant amount For exponential curves, this is the percentage amount (treated as basis points)", - "allOf": [ - { - "$ref": "#/definitions/Uint128" - } - ] - }, - "finders_fee_percent": { - "description": "The percentage of the swap that will be paid to the finder of a trade", - "allOf": [ - { - "$ref": "#/definitions/Decimal" - } - ] - }, - "id": { - "description": "The unique id of the pool", - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, - "is_active": { - "description": "Whether or not the pool is accepting trades", - "type": "boolean" - }, - "owner": { - "description": "The address of the pool owner", - "allOf": [ - { - "$ref": "#/definitions/Addr" - } - ] - }, - "pool_type": { - "description": "The type of assets held by the pool", - "allOf": [ - { - "$ref": "#/definitions/PoolType" - } - ] - }, - "reinvest_nfts": { - "description": "Whether or not the NFTs sold into the pool will be reinvested", - "type": "boolean" - }, - "reinvest_tokens": { - "description": "Whether or not the tokens sold into the pool will be reinvested", - "type": "boolean" - }, - "spot_price": { - "description": "A moving value used to derive the price at which the pool will trade assets Note: this value is not necessarily the final sale price for pool assets", - "allOf": [ - { - "$ref": "#/definitions/Uint128" - } - ] - }, - "swap_fee_percent": { - "description": "The percentage of the swap that will be paid to the pool owner Note: this only applies to Trade pools", - "allOf": [ - { - "$ref": "#/definitions/Decimal" - } - ] - }, - "total_nfts": { - "description": "The total number of NFTs held by the pool", - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, - "total_tokens": { - "description": "The total amount of tokens held by the pool", - "allOf": [ - { - "$ref": "#/definitions/Uint128" - } - ] - } - }, - "additionalProperties": false - }, - "PoolType": { - "description": "PoolType refers to the assets held by the pool * Token: A pool that holds fungible tokens * Nft: A pool that holds NFTs * Trade: A pool that holds both fungible tokens and NFTs", - "type": "string", - "enum": [ - "token", - "nft", - "trade" - ] - }, - "Uint128": { - "description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```", - "type": "string" - } - } -} diff --git a/contracts/infinity-swap/schema/query_msg.json b/contracts/infinity-swap/schema/query_msg.json deleted file mode 100644 index 044115a..0000000 --- a/contracts/infinity-swap/schema/query_msg.json +++ /dev/null @@ -1,567 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "QueryMsg", - "oneOf": [ - { - "description": "Get the global contract configuration object Return type: `ConfigResponse`", - "type": "object", - "required": [ - "config" - ], - "properties": { - "config": { - "type": "object", - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "Retrieve pools sorted by their pool id Return type: `PoolsResponse`", - "type": "object", - "required": [ - "pools" - ], - "properties": { - "pools": { - "type": "object", - "required": [ - "query_options" - ], - "properties": { - "query_options": { - "$ref": "#/definitions/QueryOptions_for_uint64" - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "Retrieve pools by their pool id Return type: `PoolsByIdResponse`", - "type": "object", - "required": [ - "pools_by_id" - ], - "properties": { - "pools_by_id": { - "type": "object", - "required": [ - "pool_ids" - ], - "properties": { - "pool_ids": { - "type": "array", - "items": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - } - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "Retrieve pools by their owner address Return type: `PoolsResponse`", - "type": "object", - "required": [ - "pools_by_owner" - ], - "properties": { - "pools_by_owner": { - "type": "object", - "required": [ - "owner", - "query_options" - ], - "properties": { - "owner": { - "type": "string" - }, - "query_options": { - "$ref": "#/definitions/QueryOptions_for_uint64" - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "Retrieve the NFT token ids in a pool Return type: `NftTokenIdsResponse`", - "type": "object", - "required": [ - "pool_nft_token_ids" - ], - "properties": { - "pool_nft_token_ids": { - "type": "object", - "required": [ - "pool_id", - "query_options" - ], - "properties": { - "pool_id": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, - "query_options": { - "$ref": "#/definitions/QueryOptions_for_String" - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "Retrieve pool quotes sorted by their buy quote price Return type: `PoolQuoteResponse`", - "type": "object", - "required": [ - "quotes_buy_from_pool" - ], - "properties": { - "quotes_buy_from_pool": { - "type": "object", - "required": [ - "collection", - "query_options" - ], - "properties": { - "collection": { - "type": "string" - }, - "query_options": { - "$ref": "#/definitions/QueryOptions_for_Tuple_of_Uint128_and_uint64" - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "Retrieve pool quotes sorted by their sell quote price Return type: `PoolQuoteResponse`", - "type": "object", - "required": [ - "quotes_sell_to_pool" - ], - "properties": { - "quotes_sell_to_pool": { - "type": "object", - "required": [ - "collection", - "query_options" - ], - "properties": { - "collection": { - "type": "string" - }, - "query_options": { - "$ref": "#/definitions/QueryOptions_for_Tuple_of_Uint128_and_uint64" - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "Simulate a DirectSwapNftsForTokens transaction Return type: `SwapResponse`", - "type": "object", - "required": [ - "sim_direct_swap_nfts_for_tokens" - ], - "properties": { - "sim_direct_swap_nfts_for_tokens": { - "type": "object", - "required": [ - "nfts_to_swap", - "pool_id", - "sender", - "swap_params" - ], - "properties": { - "nfts_to_swap": { - "type": "array", - "items": { - "$ref": "#/definitions/NftSwap" - } - }, - "pool_id": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, - "sender": { - "type": "string" - }, - "swap_params": { - "$ref": "#/definitions/SwapParams" - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "Simulate a SwapNftsForTokens transaction Return type: `SwapResponse`", - "type": "object", - "required": [ - "sim_swap_nfts_for_tokens" - ], - "properties": { - "sim_swap_nfts_for_tokens": { - "type": "object", - "required": [ - "collection", - "nfts_to_swap", - "sender", - "swap_params" - ], - "properties": { - "collection": { - "type": "string" - }, - "nfts_to_swap": { - "type": "array", - "items": { - "$ref": "#/definitions/NftSwap" - } - }, - "sender": { - "type": "string" - }, - "swap_params": { - "$ref": "#/definitions/SwapParams" - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "Simulate a DirectSwapTokensforSpecificNfts transaction Return type: `SwapResponse`", - "type": "object", - "required": [ - "sim_direct_swap_tokens_for_specific_nfts" - ], - "properties": { - "sim_direct_swap_tokens_for_specific_nfts": { - "type": "object", - "required": [ - "nfts_to_swap_for", - "pool_id", - "sender", - "swap_params" - ], - "properties": { - "nfts_to_swap_for": { - "type": "array", - "items": { - "$ref": "#/definitions/NftSwap" - } - }, - "pool_id": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, - "sender": { - "type": "string" - }, - "swap_params": { - "$ref": "#/definitions/SwapParams" - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "Simulate a SimSwapTokensForSpecificNfts transaction Return type: `SwapResponse`", - "type": "object", - "required": [ - "sim_swap_tokens_for_specific_nfts" - ], - "properties": { - "sim_swap_tokens_for_specific_nfts": { - "type": "object", - "required": [ - "collection", - "pool_nfts_to_swap_for", - "sender", - "swap_params" - ], - "properties": { - "collection": { - "type": "string" - }, - "pool_nfts_to_swap_for": { - "type": "array", - "items": { - "$ref": "#/definitions/PoolNftSwap" - } - }, - "sender": { - "type": "string" - }, - "swap_params": { - "$ref": "#/definitions/SwapParams" - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "Simulate a SwapTokensForAnyNfts transaction Return type: `SwapResponse`", - "type": "object", - "required": [ - "sim_swap_tokens_for_any_nfts" - ], - "properties": { - "sim_swap_tokens_for_any_nfts": { - "type": "object", - "required": [ - "collection", - "max_expected_token_input", - "sender", - "swap_params" - ], - "properties": { - "collection": { - "type": "string" - }, - "max_expected_token_input": { - "type": "array", - "items": { - "$ref": "#/definitions/Uint128" - } - }, - "sender": { - "type": "string" - }, - "swap_params": { - "$ref": "#/definitions/SwapParams" - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - } - ], - "definitions": { - "NftSwap": { - "description": "NftSwap contains the parameters for an NFT swap", - "type": "object", - "required": [ - "nft_token_id", - "token_amount" - ], - "properties": { - "nft_token_id": { - "description": "The id of the NFT to swap", - "type": "string" - }, - "token_amount": { - "description": "The amount of tokens to accept in exchange for the NFT Note: this could be the minimum acceptable amount for a sale or the maximum acceptable amount for a purchase", - "allOf": [ - { - "$ref": "#/definitions/Uint128" - } - ] - } - }, - "additionalProperties": false - }, - "PoolNftSwap": { - "description": "PoolNftSwap is the parent of NftSwap and organizes swaps by pool_id", - "type": "object", - "required": [ - "nft_swaps", - "pool_id" - ], - "properties": { - "nft_swaps": { - "description": "The NFT swaps to execute", - "type": "array", - "items": { - "$ref": "#/definitions/NftSwap" - } - }, - "pool_id": { - "description": "The id of the pool to swap in", - "type": "integer", - "format": "uint64", - "minimum": 0.0 - } - }, - "additionalProperties": false - }, - "QueryOptions_for_String": { - "description": "QueryOptions are used to paginate contract queries", - "type": "object", - "properties": { - "descending": { - "description": "Whether to sort items in ascending or descending order", - "type": [ - "boolean", - "null" - ] - }, - "limit": { - "type": [ - "integer", - "null" - ], - "format": "uint32", - "minimum": 0.0 - }, - "start_after": { - "description": "The key to start the query after", - "type": [ - "string", - "null" - ] - } - }, - "additionalProperties": false - }, - "QueryOptions_for_Tuple_of_Uint128_and_uint64": { - "description": "QueryOptions are used to paginate contract queries", - "type": "object", - "properties": { - "descending": { - "description": "Whether to sort items in ascending or descending order", - "type": [ - "boolean", - "null" - ] - }, - "limit": { - "type": [ - "integer", - "null" - ], - "format": "uint32", - "minimum": 0.0 - }, - "start_after": { - "description": "The key to start the query after", - "type": [ - "array", - "null" - ], - "items": [ - { - "$ref": "#/definitions/Uint128" - }, - { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - } - ], - "maxItems": 2, - "minItems": 2 - } - }, - "additionalProperties": false - }, - "QueryOptions_for_uint64": { - "description": "QueryOptions are used to paginate contract queries", - "type": "object", - "properties": { - "descending": { - "description": "Whether to sort items in ascending or descending order", - "type": [ - "boolean", - "null" - ] - }, - "limit": { - "type": [ - "integer", - "null" - ], - "format": "uint32", - "minimum": 0.0 - }, - "start_after": { - "description": "The key to start the query after", - "type": [ - "integer", - "null" - ], - "format": "uint64", - "minimum": 0.0 - } - }, - "additionalProperties": false - }, - "SwapParams": { - "description": "SwapParams contains the parameters for a swap", - "type": "object", - "required": [ - "deadline", - "robust" - ], - "properties": { - "asset_recipient": { - "description": "The address to receive the assets from the swap, if not specified is set to sender", - "type": [ - "string", - "null" - ] - }, - "deadline": { - "description": "The deadline after which the swap will be rejected", - "allOf": [ - { - "$ref": "#/definitions/Timestamp" - } - ] - }, - "finder": { - "description": "The address of the finder, will receive a portion of the fees equal to percentage set by the pool", - "type": [ - "string", - "null" - ] - }, - "robust": { - "description": "Whether or not to revert the entire trade if one of the swaps fails", - "type": "boolean" - } - }, - "additionalProperties": false - }, - "Timestamp": { - "description": "A point in time in nanosecond precision.\n\nThis type can represent times from 1970-01-01T00:00:00Z to 2554-07-21T23:34:33Z.\n\n## Examples\n\n``` # use cosmwasm_std::Timestamp; let ts = Timestamp::from_nanos(1_000_000_202); assert_eq!(ts.nanos(), 1_000_000_202); assert_eq!(ts.seconds(), 1); assert_eq!(ts.subsec_nanos(), 202);\n\nlet ts = ts.plus_seconds(2); assert_eq!(ts.nanos(), 3_000_000_202); assert_eq!(ts.seconds(), 3); assert_eq!(ts.subsec_nanos(), 202); ```", - "allOf": [ - { - "$ref": "#/definitions/Uint64" - } - ] - }, - "Uint128": { - "description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```", - "type": "string" - }, - "Uint64": { - "description": "A thin wrapper around u64 that is using strings for JSON encoding/decoding, such that the full u64 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u64` to get the value out:\n\n``` # use cosmwasm_std::Uint64; let a = Uint64::from(42u64); assert_eq!(a.u64(), 42);\n\nlet b = Uint64::from(70u32); assert_eq!(b.u64(), 70); ```", - "type": "string" - } - } -} diff --git a/contracts/infinity-swap/schema/query_options_for__tuple_of__uint128_and_uint64.json b/contracts/infinity-swap/schema/query_options_for__tuple_of__uint128_and_uint64.json deleted file mode 100644 index f4a85af..0000000 --- a/contracts/infinity-swap/schema/query_options_for__tuple_of__uint128_and_uint64.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "QueryOptions_for_Tuple_of_Uint128_and_uint64", - "description": "QueryOptions are used to paginate contract queries", - "type": "object", - "properties": { - "descending": { - "description": "Whether to sort items in ascending or descending order", - "type": [ - "boolean", - "null" - ] - }, - "limit": { - "type": [ - "integer", - "null" - ], - "format": "uint32", - "minimum": 0.0 - }, - "start_after": { - "description": "The key to start the query after", - "type": [ - "array", - "null" - ], - "items": [ - { - "$ref": "#/definitions/Uint128" - }, - { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - } - ], - "maxItems": 2, - "minItems": 2 - } - }, - "additionalProperties": false, - "definitions": { - "Uint128": { - "description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```", - "type": "string" - } - } -} diff --git a/contracts/infinity-swap/schema/query_options_for_uint64.json b/contracts/infinity-swap/schema/query_options_for_uint64.json deleted file mode 100644 index d079638..0000000 --- a/contracts/infinity-swap/schema/query_options_for_uint64.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "QueryOptions_for_uint64", - "description": "QueryOptions are used to paginate contract queries", - "type": "object", - "properties": { - "descending": { - "description": "Whether to sort items in ascending or descending order", - "type": [ - "boolean", - "null" - ] - }, - "limit": { - "type": [ - "integer", - "null" - ], - "format": "uint32", - "minimum": 0.0 - }, - "start_after": { - "description": "The key to start the query after", - "type": [ - "integer", - "null" - ], - "format": "uint64", - "minimum": 0.0 - } - }, - "additionalProperties": false -} diff --git a/contracts/infinity-swap/schema/swap_params.json b/contracts/infinity-swap/schema/swap_params.json deleted file mode 100644 index 255ba0c..0000000 --- a/contracts/infinity-swap/schema/swap_params.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "SwapParams", - "description": "SwapParams contains the parameters for a swap", - "type": "object", - "required": [ - "deadline", - "robust" - ], - "properties": { - "asset_recipient": { - "description": "The address to receive the assets from the swap, if not specified is set to sender", - "type": [ - "string", - "null" - ] - }, - "deadline": { - "description": "The deadline after which the swap will be rejected", - "allOf": [ - { - "$ref": "#/definitions/Timestamp" - } - ] - }, - "finder": { - "description": "The address of the finder, will receive a portion of the fees equal to percentage set by the pool", - "type": [ - "string", - "null" - ] - }, - "robust": { - "description": "Whether or not to revert the entire trade if one of the swaps fails", - "type": "boolean" - } - }, - "additionalProperties": false, - "definitions": { - "Timestamp": { - "description": "A point in time in nanosecond precision.\n\nThis type can represent times from 1970-01-01T00:00:00Z to 2554-07-21T23:34:33Z.\n\n## Examples\n\n``` # use cosmwasm_std::Timestamp; let ts = Timestamp::from_nanos(1_000_000_202); assert_eq!(ts.nanos(), 1_000_000_202); assert_eq!(ts.seconds(), 1); assert_eq!(ts.subsec_nanos(), 202);\n\nlet ts = ts.plus_seconds(2); assert_eq!(ts.nanos(), 3_000_000_202); assert_eq!(ts.seconds(), 3); assert_eq!(ts.subsec_nanos(), 202); ```", - "allOf": [ - { - "$ref": "#/definitions/Uint64" - } - ] - }, - "Uint64": { - "description": "A thin wrapper around u64 that is using strings for JSON encoding/decoding, such that the full u64 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u64` to get the value out:\n\n``` # use cosmwasm_std::Uint64; let a = Uint64::from(42u64); assert_eq!(a.u64(), 42);\n\nlet b = Uint64::from(70u32); assert_eq!(b.u64(), 70); ```", - "type": "string" - } - } -} diff --git a/contracts/infinity-swap/schema/swap_response.json b/contracts/infinity-swap/schema/swap_response.json deleted file mode 100644 index 8bec0fe..0000000 --- a/contracts/infinity-swap/schema/swap_response.json +++ /dev/null @@ -1,126 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "SwapResponse", - "type": "object", - "required": [ - "swaps" - ], - "properties": { - "swaps": { - "type": "array", - "items": { - "$ref": "#/definitions/Swap" - } - } - }, - "additionalProperties": false, - "definitions": { - "NftPayment": { - "description": "An NFT payment that needs to be executed at the end of a transaction", - "type": "object", - "required": [ - "address", - "nft_token_id" - ], - "properties": { - "address": { - "type": "string" - }, - "nft_token_id": { - "type": "string" - } - }, - "additionalProperties": false - }, - "Swap": { - "description": "A summary of an individual swap", - "type": "object", - "required": [ - "network_fee", - "nft_payment", - "pool_id", - "spot_price", - "transaction_type" - ], - "properties": { - "finder_payment": { - "anyOf": [ - { - "$ref": "#/definitions/TokenPayment" - }, - { - "type": "null" - } - ] - }, - "network_fee": { - "$ref": "#/definitions/Uint128" - }, - "nft_payment": { - "$ref": "#/definitions/NftPayment" - }, - "pool_id": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, - "royalty_payment": { - "anyOf": [ - { - "$ref": "#/definitions/TokenPayment" - }, - { - "type": "null" - } - ] - }, - "seller_payment": { - "anyOf": [ - { - "$ref": "#/definitions/TokenPayment" - }, - { - "type": "null" - } - ] - }, - "spot_price": { - "$ref": "#/definitions/Uint128" - }, - "transaction_type": { - "$ref": "#/definitions/TransactionType" - } - }, - "additionalProperties": false - }, - "TokenPayment": { - "description": "A token payment that needs to be executed at the end of a transaction", - "type": "object", - "required": [ - "address", - "amount" - ], - "properties": { - "address": { - "type": "string" - }, - "amount": { - "$ref": "#/definitions/Uint128" - } - }, - "additionalProperties": false - }, - "TransactionType": { - "description": "Defines whether the end user is buying or selling NFTs", - "type": "string", - "enum": [ - "user_submits_nfts", - "user_submits_tokens" - ] - }, - "Uint128": { - "description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```", - "type": "string" - } - } -} diff --git a/contracts/infinity-swap/src/error.rs b/contracts/infinity-swap/src/error.rs deleted file mode 100644 index b730ec2..0000000 --- a/contracts/infinity-swap/src/error.rs +++ /dev/null @@ -1,54 +0,0 @@ -use cosmwasm_std::{StdError, Uint128}; -use cw_utils::PaymentError; -use thiserror::Error; - -#[derive(Error, Debug, PartialEq)] -pub enum ContractError { - #[error("{0}")] - Std(#[from] StdError), - - #[error("{0}")] - PaymentError(#[from] PaymentError), - - #[error("Unauthorized: {0}")] - Unauthorized(String), - - #[error("Invalid pool: {0}")] - InvalidPool(String), - - #[error("Pool not found: {0}")] - PoolNotFound(String), - - #[error("NFT not found: token_id {0}")] - NftNotFound(String), - - #[error("No quote for pool: {0}")] - NoQuoteForPool(String), - - #[error("UnpaidListingFee: {0}")] - UnpaidListingFee(Uint128), - - #[error("Insufficient funds: {0}")] - InsufficientFunds(String), - - #[error("Unable to remove pool: {0}")] - UnableToRemovePool(String), - - #[error("Invalid input: {0}")] - InvalidInput(String), - - #[error("Invalid swap params: {0}")] - InvalidSwapParams(String), - - #[error("Internal error: {0}")] - InternalError(String), - - #[error("Deadline passed")] - DeadlinePassed, - - #[error("Swap error: {0}")] - SwapError(String), - - #[error("Invalid property key error: {0}")] - InvalidPropertyKeyError(String), -} diff --git a/contracts/infinity-swap/src/execute.rs b/contracts/infinity-swap/src/execute.rs deleted file mode 100644 index 86e013e..0000000 --- a/contracts/infinity-swap/src/execute.rs +++ /dev/null @@ -1,889 +0,0 @@ -use crate::error::ContractError; -use crate::helpers::{ - get_next_pool_counter, get_transaction_events, load_marketplace_params, only_owner, - prep_for_swap, remove_nft_deposit, remove_pool, save_pool, save_pools, store_nft_deposit, - transfer_nft, transfer_token, update_nft_deposits, validate_nft_swaps_for_buy, - validate_nft_swaps_for_sell, -}; -use crate::msg::{ExecuteMsg, NftSwap, PoolNftSwap, QueryOptions, SwapParams, TransactionType}; -use crate::query::query_pool_nft_token_ids; -use crate::state::{pools, BondingCurve, Pool, PoolType, CONFIG}; -use crate::swap_processor::{Swap, SwapProcessor}; - -#[cfg(not(feature = "library"))] -use cosmwasm_std::entry_point; -use cosmwasm_std::{attr, coin, Addr, Decimal, DepsMut, Env, Event, MessageInfo, Uint128}; -use cw_utils::{maybe_addr, must_pay, nonpayable}; -use sg1::fair_burn; -use sg_std::{Response, NATIVE_DENOM}; - -/// A convenience struct for creating Pools -pub struct PoolInfo { - pub collection: Addr, - pub asset_recipient: Option, - pub pool_type: PoolType, - pub bonding_curve: BondingCurve, - pub spot_price: Uint128, - pub delta: Uint128, - pub finders_fee_percent: Decimal, - pub swap_fee_percent: Decimal, - pub reinvest_tokens: bool, - pub reinvest_nfts: bool, -} - -#[cfg_attr(not(feature = "library"), entry_point)] -pub fn execute( - deps: DepsMut, - env: Env, - info: MessageInfo, - msg: ExecuteMsg, -) -> Result { - let api = deps.api; - - match msg { - ExecuteMsg::CreateTokenPool { - collection, - asset_recipient, - bonding_curve, - spot_price, - delta, - finders_fee_bps, - } => execute_create_pool( - deps, - info, - PoolInfo { - collection: api.addr_validate(&collection)?, - asset_recipient: maybe_addr(api, asset_recipient)?, - pool_type: PoolType::Token, - bonding_curve, - spot_price, - delta, - finders_fee_percent: Decimal::percent(finders_fee_bps), - swap_fee_percent: Decimal::percent(0u64), - reinvest_tokens: false, - reinvest_nfts: false, - }, - ), - ExecuteMsg::CreateNftPool { - collection, - asset_recipient, - bonding_curve, - spot_price, - delta, - finders_fee_bps, - } => execute_create_pool( - deps, - info, - PoolInfo { - collection: api.addr_validate(&collection)?, - asset_recipient: maybe_addr(api, asset_recipient)?, - pool_type: PoolType::Nft, - bonding_curve, - spot_price, - delta, - finders_fee_percent: Decimal::percent(finders_fee_bps), - swap_fee_percent: Decimal::percent(0), - reinvest_tokens: false, - reinvest_nfts: false, - }, - ), - ExecuteMsg::CreateTradePool { - collection, - asset_recipient, - bonding_curve, - spot_price, - delta, - finders_fee_bps, - swap_fee_bps, - reinvest_tokens, - reinvest_nfts, - } => execute_create_pool( - deps, - info, - PoolInfo { - collection: api.addr_validate(&collection)?, - asset_recipient: maybe_addr(api, asset_recipient)?, - pool_type: PoolType::Trade, - bonding_curve, - spot_price, - delta, - finders_fee_percent: Decimal::percent(finders_fee_bps), - swap_fee_percent: Decimal::percent(swap_fee_bps), - reinvest_tokens, - reinvest_nfts, - }, - ), - ExecuteMsg::DepositTokens { pool_id } => execute_deposit_tokens(deps, info, pool_id), - ExecuteMsg::DepositNfts { - pool_id, - collection, - nft_token_ids, - } => execute_deposit_nfts( - deps, - info, - env, - pool_id, - api.addr_validate(&collection)?, - nft_token_ids, - ), - ExecuteMsg::WithdrawTokens { - pool_id, - amount, - asset_recipient, - } => execute_withdraw_tokens( - deps, - info, - pool_id, - amount, - maybe_addr(api, asset_recipient)?, - ), - ExecuteMsg::WithdrawAllTokens { - pool_id, - asset_recipient, - } => execute_withdraw_all_tokens(deps, info, pool_id, maybe_addr(api, asset_recipient)?), - ExecuteMsg::WithdrawNfts { - pool_id, - nft_token_ids, - asset_recipient, - } => execute_withdraw_nfts( - deps, - info, - pool_id, - nft_token_ids, - maybe_addr(api, asset_recipient)?, - ), - ExecuteMsg::WithdrawAllNfts { - pool_id, - asset_recipient, - } => execute_withdraw_all_nfts(deps, info, pool_id, maybe_addr(api, asset_recipient)?), - ExecuteMsg::UpdatePoolConfig { - pool_id, - asset_recipient, - delta, - spot_price, - finders_fee_bps, - swap_fee_bps, - reinvest_tokens, - reinvest_nfts, - } => execute_update_pool_config( - deps, - info, - pool_id, - maybe_addr(api, asset_recipient)?, - delta, - spot_price, - finders_fee_bps, - swap_fee_bps, - reinvest_tokens, - reinvest_nfts, - ), - ExecuteMsg::SetActivePool { pool_id, is_active } => { - execute_set_active_pool(deps, info, pool_id, is_active) - } - ExecuteMsg::RemovePool { - pool_id, - asset_recipient, - } => execute_remove_pool(deps, info, pool_id, maybe_addr(api, asset_recipient)?), - ExecuteMsg::DirectSwapNftsForTokens { - pool_id, - nfts_to_swap, - swap_params, - } => { - execute_direct_swap_nfts_for_tokens(deps, env, info, pool_id, nfts_to_swap, swap_params) - } - ExecuteMsg::SwapNftsForTokens { - collection, - nfts_to_swap, - swap_params, - } => execute_swap_nfts_for_tokens( - deps, - env, - info, - api.addr_validate(&collection)?, - nfts_to_swap, - swap_params, - ), - ExecuteMsg::DirectSwapTokensForSpecificNfts { - pool_id, - nfts_to_swap_for, - swap_params, - } => execute_direct_swap_tokens_for_specific_nfts( - deps, - env, - info, - pool_id, - nfts_to_swap_for, - swap_params, - ), - ExecuteMsg::SwapTokensForSpecificNfts { - collection, - pool_nfts_to_swap_for, - swap_params, - } => execute_swap_tokens_for_specific_nfts( - deps, - env, - info, - api.addr_validate(&collection)?, - pool_nfts_to_swap_for, - swap_params, - ), - ExecuteMsg::SwapTokensForAnyNfts { - collection, - max_expected_token_input, - swap_params, - } => execute_swap_tokens_for_any_nfts( - deps, - env, - info, - api.addr_validate(&collection)?, - max_expected_token_input, - swap_params, - ), - } -} - -/// Execute a CreatePool message -pub fn execute_create_pool( - deps: DepsMut, - info: MessageInfo, - pool_info: PoolInfo, -) -> Result { - let pool_counter = get_next_pool_counter(deps.storage)?; - let mut pool = Pool::new( - pool_counter, - pool_info.collection, - info.sender.clone(), - pool_info.asset_recipient, - pool_info.pool_type, - pool_info.bonding_curve, - pool_info.spot_price, - pool_info.delta, - pool_info.finders_fee_percent, - pool_info.swap_fee_percent, - pool_info.reinvest_tokens, - pool_info.reinvest_nfts, - ); - - let config = CONFIG.load(deps.storage)?; - let marketplace_params = load_marketplace_params(deps.as_ref(), &config.marketplace_addr)?; - - let mut response = Response::new(); - response = save_pool(deps.storage, &mut pool, &marketplace_params, response)?; - - // Burn the listing fee set on the marketplace contract - let listing_fee = must_pay(&info, NATIVE_DENOM)?; - if listing_fee != marketplace_params.params.listing_fee { - return Err(ContractError::UnpaidListingFee(listing_fee)); - } - if listing_fee > Uint128::zero() { - fair_burn(listing_fee.u128(), config.developer, &mut response); - } - - let event = pool.create_event_all_props("create-pool")?; - response = response.add_event(event); - - Ok(response) -} - -/// Execute a DepositTokens message -pub fn execute_deposit_tokens( - deps: DepsMut, - info: MessageInfo, - pool_id: u64, -) -> Result { - let received_amount = must_pay(&info, NATIVE_DENOM)?; - - let mut pool = pools().load(deps.storage, pool_id)?; - // Only the owner of the pool can deposit and withdraw assets - only_owner(&info, &pool)?; - - // Track the total amount of tokens that have been deposited into the pool - pool.deposit_tokens(received_amount)?; - - let config = CONFIG.load(deps.storage)?; - let marketplace_params = load_marketplace_params(deps.as_ref(), &config.marketplace_addr)?; - - let mut response = Response::new(); - response = save_pool(deps.storage, &mut pool, &marketplace_params, response)?; - let event = pool.create_event("deposit-tokens", vec!["id", "spot_price", "total_tokens"])?; - response = response.add_event(event); - Ok(response) -} - -/// Execute a DepositNfts message -pub fn execute_deposit_nfts( - deps: DepsMut, - info: MessageInfo, - env: Env, - pool_id: u64, - collection: Addr, - nft_token_ids: Vec, -) -> Result { - nonpayable(&info)?; - - let mut pool = pools().load(deps.storage, pool_id)?; - // Only the owner of the pool can deposit and withdraw assets - only_owner(&info, &pool)?; - if pool.collection != collection { - return Err(ContractError::InvalidInput(format!( - "invalid collection ({}) for pool ({})", - collection, pool.id - ))); - } - - // Push the NFT transfer messages - let mut response = Response::new(); - for nft_token_id in &nft_token_ids { - transfer_nft( - nft_token_id, - env.contract.address.as_ref(), - collection.as_ref(), - &mut response, - )?; - store_nft_deposit(deps.storage, pool.id, nft_token_id)?; - } - // Track the NFTs that have been deposited into the pool - pool.deposit_nfts(&nft_token_ids)?; - - let config = CONFIG.load(deps.storage)?; - let marketplace_params = load_marketplace_params(deps.as_ref(), &config.marketplace_addr)?; - response = save_pool(deps.storage, &mut pool, &marketplace_params, response)?; - - let event = Event::new("deposit-nfts").add_attributes(vec![ - attr("pool_id", pool.id.to_string()), - attr("total_nfts", pool.total_nfts.to_string()), - attr("nft_token_ids", nft_token_ids.join(",")), - ]); - response = response.add_event(event); - - Ok(response) -} - -/// Execute a WithdrawTokens message -pub fn execute_withdraw_tokens( - deps: DepsMut, - info: MessageInfo, - pool_id: u64, - amount: Uint128, - asset_recipient: Option, -) -> Result { - nonpayable(&info)?; - - let mut pool = pools().load(deps.storage, pool_id)?; - // Only the owner of the pool can deposit and withdraw assets - only_owner(&info, &pool)?; - - let mut response = Response::new(); - - // Withdraw tokens to the asset recipient if specified, otherwise to the sender - let recipient = asset_recipient.unwrap_or(info.sender); - transfer_token( - coin(amount.u128(), NATIVE_DENOM), - recipient.as_ref(), - &mut response, - )?; - // Track total amount owned by the pool - pool.withdraw_tokens(amount)?; - - let config = CONFIG.load(deps.storage)?; - let marketplace_params = load_marketplace_params(deps.as_ref(), &config.marketplace_addr)?; - response = save_pool(deps.storage, &mut pool, &marketplace_params, response)?; - - let event = pool.create_event("withdraw-tokens", vec!["id", "spot_price", "total_tokens"])?; - response = response.add_event(event); - - Ok(response) -} - -/// Execute a WithdrawAllNfts message, a convenvience method for withdrawing all tokens -pub fn execute_withdraw_all_tokens( - deps: DepsMut, - info: MessageInfo, - pool_id: u64, - asset_recipient: Option, -) -> Result { - let pool = pools().load(deps.storage, pool_id)?; - execute_withdraw_tokens(deps, info, pool_id, pool.total_tokens, asset_recipient) -} - -/// Execute a WithdrawNfts message -pub fn execute_withdraw_nfts( - deps: DepsMut, - info: MessageInfo, - pool_id: u64, - nft_token_ids: Vec, - asset_recipient: Option, -) -> Result { - nonpayable(&info)?; - - let mut pool = pools().load(deps.storage, pool_id)?; - // Only the owner of the pool can deposit and withdraw assets - only_owner(&info, &pool)?; - - let mut response = Response::new(); - - // Track the NFTs that have been withdrawn from the pool - pool.withdraw_nfts(&nft_token_ids)?; - - // Withdraw NFTs to the asset recipient if specified, otherwise to the sender - let recipient = asset_recipient.unwrap_or(info.sender); - for nft_token_id in &nft_token_ids { - transfer_nft( - nft_token_id, - recipient.as_ref(), - pool.collection.as_ref(), - &mut response, - )?; - remove_nft_deposit(deps.storage, pool_id, nft_token_id)?; - } - - let config = CONFIG.load(deps.storage)?; - let marketplace_params = load_marketplace_params(deps.as_ref(), &config.marketplace_addr)?; - response = save_pool(deps.storage, &mut pool, &marketplace_params, response)?; - - let event = Event::new("withdraw-nfts").add_attributes(vec![ - attr("pool_id", pool.id.to_string()), - attr("total_nfts", pool.total_nfts.to_string()), - attr("nft_token_ids", nft_token_ids.join(",")), - ]); - response = response.add_event(event); - - Ok(response) -} - -/// Execute a WithdrawAllNfts message, a convenvience method for withdrawing all NFTs -pub fn execute_withdraw_all_nfts( - deps: DepsMut, - info: MessageInfo, - pool_id: u64, - asset_recipient: Option, -) -> Result { - let withdrawal_batch_size: u8 = 10; - let token_id_response = query_pool_nft_token_ids( - deps.as_ref(), - pool_id, - QueryOptions { - descending: None, - start_after: None, - limit: Some(withdrawal_batch_size as u32), - }, - )?; - - execute_withdraw_nfts( - deps, - info, - pool_id, - token_id_response.nft_token_ids, - asset_recipient, - ) -} - -/// Execute an UpdatePoolConfig message -/// Option paramaters that are not specified will not be updated -pub fn execute_update_pool_config( - deps: DepsMut, - info: MessageInfo, - pool_id: u64, - asset_recipient: Option, - delta: Option, - spot_price: Option, - finders_fee_bps: Option, - swap_fee_bps: Option, - reinvest_tokens: Option, - reinvest_nfts: Option, -) -> Result { - nonpayable(&info)?; - - let mut pool = pools().load(deps.storage, pool_id)?; - // Only the owner of the pool can update the pool config - only_owner(&info, &pool)?; - - let mut attr_keys: Vec<&str> = vec!["id"]; - if let Some(_asset_recipient) = asset_recipient { - pool.asset_recipient = Some(_asset_recipient); - attr_keys.push("asset_recipient"); - } - if let Some(_spot_price) = spot_price { - pool.spot_price = _spot_price; - attr_keys.push("spot_price"); - } - if let Some(_delta) = delta { - pool.delta = _delta; - attr_keys.push("delta"); - } - if let Some(_swap_fee_bps) = swap_fee_bps { - pool.swap_fee_percent = Decimal::percent(_swap_fee_bps); - attr_keys.push("swap_fee_percent"); - } - if let Some(_finders_fee_bps) = finders_fee_bps { - pool.finders_fee_percent = Decimal::percent(_finders_fee_bps); - attr_keys.push("finders_fee_percent"); - } - if let Some(_reinvest_tokens) = reinvest_tokens { - pool.reinvest_tokens = _reinvest_tokens; - attr_keys.push("reinvest_tokens"); - } - if let Some(_reinvest_nfts) = reinvest_nfts { - pool.reinvest_nfts = _reinvest_nfts; - attr_keys.push("reinvest_nfts"); - } - - let config = CONFIG.load(deps.storage)?; - let marketplace_params = load_marketplace_params(deps.as_ref(), &config.marketplace_addr)?; - - let mut response = Response::new(); - response = save_pool(deps.storage, &mut pool, &marketplace_params, response)?; - - let event = pool.create_event("update-pool-config", attr_keys)?; - response = response.add_event(event); - - Ok(response) -} - -/// Execute a SetActivePool message -pub fn execute_set_active_pool( - deps: DepsMut, - info: MessageInfo, - pool_id: u64, - is_active: bool, -) -> Result { - nonpayable(&info)?; - - let mut pool = pools().load(deps.storage, pool_id)?; - // Only the owner of the pool can update the pool config - only_owner(&info, &pool)?; - - pool.set_active(is_active)?; - - let config = CONFIG.load(deps.storage)?; - let marketplace_params = load_marketplace_params(deps.as_ref(), &config.marketplace_addr)?; - - let mut response = Response::new(); - response = save_pool(deps.storage, &mut pool, &marketplace_params, response)?; - - let event = pool.create_event("set-active-pool", vec!["id", "is_active"])?; - response = response.add_event(event); - - Ok(response) -} - -/// Execute a RemovePool message -pub fn execute_remove_pool( - deps: DepsMut, - info: MessageInfo, - pool_id: u64, - asset_recipient: Option, -) -> Result { - nonpayable(&info)?; - - let mut pool = pools().load(deps.storage, pool_id)?; - // Only the owner of the pool can remove the pool - only_owner(&info, &pool)?; - - // Pools that hold NFTs cannot be removed - if pool.total_nfts > 0 { - return Err(ContractError::UnableToRemovePool(format!( - "pool {} still has NFTs", - pool_id - ))); - } - - let config = CONFIG.load(deps.storage)?; - let mut response = Response::new(); - - // If the pool has tokens, transfer them to the asset recipient - if pool.total_tokens > Uint128::zero() { - let recipient = asset_recipient.unwrap_or(info.sender); - transfer_token( - coin(pool.total_tokens.u128(), NATIVE_DENOM), - recipient.as_ref(), - &mut response, - )?; - } - - let marketplace_params = load_marketplace_params(deps.as_ref(), &config.marketplace_addr)?; - response = remove_pool(deps.storage, &mut pool, &marketplace_params, response)?; - - let event = pool.create_event("remove-pool", vec!["id"])?; - response = response.add_event(event); - - Ok(response) -} - -/// Execute a DirectSwapNftsForTokens message -pub fn execute_direct_swap_nfts_for_tokens( - deps: DepsMut, - env: Env, - info: MessageInfo, - pool_id: u64, - nfts_to_swap: Vec, - swap_params: SwapParams, -) -> Result { - nonpayable(&info)?; - - let pool = pools().load(deps.storage, pool_id)?; - - let swap_prep_result = prep_for_swap( - deps.as_ref(), - &Some(env.block), - &info.sender, - &pool.collection, - &swap_params, - )?; - - validate_nft_swaps_for_sell(deps.as_ref(), &info, &pool.collection, &nfts_to_swap)?; - - let mut response = Response::new(); - let mut pools_to_save: Vec; - let swaps: Vec; - - { - let mut processor = SwapProcessor::new( - TransactionType::UserSubmitsNfts, - env.contract.address.clone(), - pool.collection.clone(), - info.sender, - Uint128::zero(), - swap_prep_result.asset_recipient, - swap_prep_result - .marketplace_params - .params - .trading_fee_percent, - swap_prep_result.marketplace_params.params.min_price, - swap_prep_result.collection_royalties, - swap_prep_result.finder, - swap_prep_result.developer, - ); - processor.direct_swap_nfts_for_tokens(pool, nfts_to_swap, swap_params)?; - processor.finalize_transaction(&mut response)?; - swaps = processor.swaps; - pools_to_save = processor.pools_to_save.into_values().collect(); - } - - update_nft_deposits(deps.storage, &env.contract.address, &swaps)?; - response = save_pools( - deps.storage, - pools_to_save.iter_mut().collect(), - &swap_prep_result.marketplace_params, - response, - )?; - response = response.add_events(get_transaction_events(&swaps, &pools_to_save)); - - Ok(response) -} - -/// Execute a SwapNftsForTokens message -pub fn execute_swap_nfts_for_tokens( - deps: DepsMut, - env: Env, - info: MessageInfo, - collection: Addr, - nfts_to_swap: Vec, - swap_params: SwapParams, -) -> Result { - nonpayable(&info)?; - - let swap_prep_result = prep_for_swap( - deps.as_ref(), - &Some(env.block), - &info.sender, - &collection, - &swap_params, - )?; - - validate_nft_swaps_for_sell(deps.as_ref(), &info, &collection, &nfts_to_swap)?; - - let mut response = Response::new(); - let mut pools_to_save: Vec; - let swaps: Vec; - - { - let mut processor = SwapProcessor::new( - TransactionType::UserSubmitsNfts, - env.contract.address.clone(), - collection, - info.sender, - Uint128::zero(), - swap_prep_result.asset_recipient, - swap_prep_result - .marketplace_params - .params - .trading_fee_percent, - swap_prep_result.marketplace_params.params.min_price, - swap_prep_result.collection_royalties, - swap_prep_result.finder, - swap_prep_result.developer, - ); - processor.swap_nfts_for_tokens(deps.as_ref().storage, nfts_to_swap, swap_params)?; - processor.finalize_transaction(&mut response)?; - swaps = processor.swaps; - pools_to_save = processor.pools_to_save.into_values().collect(); - } - - update_nft_deposits(deps.storage, &env.contract.address, &swaps)?; - response = save_pools( - deps.storage, - pools_to_save.iter_mut().collect(), - &swap_prep_result.marketplace_params, - response, - )?; - response = response.add_events(get_transaction_events(&swaps, &pools_to_save)); - - Ok(response) -} - -/// Execute a DirectSwapTokensForSpecificNfts message -pub fn execute_direct_swap_tokens_for_specific_nfts( - deps: DepsMut, - env: Env, - info: MessageInfo, - pool_id: u64, - nfts_to_swap_for: Vec, - swap_params: SwapParams, -) -> Result { - let pool = pools().load(deps.storage, pool_id)?; - execute_swap_tokens_for_specific_nfts( - deps, - env, - info, - pool.collection, - vec![PoolNftSwap { - pool_id, - nft_swaps: nfts_to_swap_for, - }], - swap_params, - ) -} - -/// Execute a SwapTokensForSpecificNfts message -pub fn execute_swap_tokens_for_specific_nfts( - deps: DepsMut, - env: Env, - info: MessageInfo, - collection: Addr, - nfts_to_swap_for: Vec, - swap_params: SwapParams, -) -> Result { - let swap_prep_result = prep_for_swap( - deps.as_ref(), - &Some(env.block), - &info.sender, - &collection, - &swap_params, - )?; - - let received_amount = validate_nft_swaps_for_buy(&info, &nfts_to_swap_for)?; - - let mut response = Response::new(); - let mut pools_to_save: Vec; - let swaps: Vec; - - { - let mut processor = SwapProcessor::new( - TransactionType::UserSubmitsTokens, - env.contract.address.clone(), - collection, - info.sender, - received_amount, - swap_prep_result.asset_recipient, - swap_prep_result - .marketplace_params - .params - .trading_fee_percent, - swap_prep_result.marketplace_params.params.min_price, - swap_prep_result.collection_royalties, - swap_prep_result.finder, - swap_prep_result.developer, - ); - processor.swap_tokens_for_specific_nfts(deps.storage, nfts_to_swap_for, swap_params)?; - processor.finalize_transaction(&mut response)?; - swaps = processor.swaps; - pools_to_save = processor.pools_to_save.into_values().collect(); - } - - update_nft_deposits(deps.storage, &env.contract.address, &swaps)?; - response = save_pools( - deps.storage, - pools_to_save.iter_mut().collect(), - &swap_prep_result.marketplace_params, - response, - )?; - response = response.add_events(get_transaction_events(&swaps, &pools_to_save)); - - Ok(response) -} - -/// Execute a SwapTokensForAnyNfts message -pub fn execute_swap_tokens_for_any_nfts( - deps: DepsMut, - env: Env, - info: MessageInfo, - collection: Addr, - max_expected_token_input: Vec, - swap_params: SwapParams, -) -> Result { - let swap_prep_result = prep_for_swap( - deps.as_ref(), - &Some(env.block), - &info.sender, - &collection, - &swap_params, - )?; - - if max_expected_token_input.is_empty() { - return Err(ContractError::InvalidInput( - "max expected token input must not be empty".to_string(), - )); - } - - // User must send enough tokens to cover the swap - // Should be the sum of all the token amounts in max_expected_token_input - let received_amount = must_pay(&info, NATIVE_DENOM)?; - let expected_amount = max_expected_token_input - .iter() - .fold(Uint128::zero(), |acc, amount| acc + amount); - if received_amount < expected_amount { - return Err(ContractError::InsufficientFunds(format!( - "expected {} but received {}", - expected_amount, received_amount - ))); - } - - let mut response = Response::new(); - let mut pools_to_save: Vec; - let swaps: Vec; - - { - let mut processor = SwapProcessor::new( - TransactionType::UserSubmitsTokens, - env.contract.address.clone(), - collection, - info.sender, - received_amount, - swap_prep_result.asset_recipient, - swap_prep_result - .marketplace_params - .params - .trading_fee_percent, - swap_prep_result.marketplace_params.params.min_price, - swap_prep_result.collection_royalties, - swap_prep_result.finder, - swap_prep_result.developer, - ); - processor.swap_tokens_for_any_nfts(deps.storage, max_expected_token_input, swap_params)?; - processor.finalize_transaction(&mut response)?; - swaps = processor.swaps; - pools_to_save = processor.pools_to_save.into_values().collect(); - } - - update_nft_deposits(deps.storage, &env.contract.address, &swaps)?; - response = save_pools( - deps.storage, - pools_to_save.iter_mut().collect(), - &swap_prep_result.marketplace_params, - response, - )?; - response = response.add_events(get_transaction_events(&swaps, &pools_to_save)); - - Ok(response) -} diff --git a/contracts/infinity-swap/src/helpers.rs b/contracts/infinity-swap/src/helpers.rs deleted file mode 100644 index ab05df0..0000000 --- a/contracts/infinity-swap/src/helpers.rs +++ /dev/null @@ -1,526 +0,0 @@ -use crate::msg::{NftSwap, PoolNftSwap, SwapParams, TransactionType}; -use crate::state::{ - buy_from_pool_quotes, pools, sell_to_pool_quotes, BondingCurve, Pool, PoolQuote, CONFIG, - NFT_DEPOSITS, POOL_COUNTER, -}; -use crate::swap_processor::Swap; -use crate::ContractError; -use cosmwasm_std::{ - to_binary, Addr, BankMsg, BlockInfo, Coin, Deps, Empty, Event, MessageInfo, Order, StdResult, - Storage, SubMsg, Timestamp, Uint128, WasmMsg, -}; -use cw721::OwnerOfResponse; -use cw721_base::helpers::Cw721Contract; -use cw_utils::{maybe_addr, must_pay}; -use sg721::RoyaltyInfoResponse; -use sg721_base::msg::{CollectionInfoResponse, QueryMsg as Sg721QueryMsg}; -use sg721_base::ExecuteMsg as Sg721ExecuteMsg; -use sg_marketplace::msg::{ParamsResponse, QueryMsg as MarketplaceQueryMsg}; -use sg_std::{Response, NATIVE_DENOM}; -use std::collections::BTreeSet; -use std::marker::PhantomData; - -/// Load the marketplace params for use within the contract -pub fn load_marketplace_params( - deps: Deps, - marketplace_addr: &Addr, -) -> Result { - let marketplace_params: ParamsResponse = deps - .querier - .query_wasm_smart(marketplace_addr, &MarketplaceQueryMsg::Params {})?; - Ok(marketplace_params) -} - -/// Load the collection royalties as defined on the NFT collection contract -pub fn load_collection_royalties( - deps: Deps, - collection_addr: &Addr, -) -> Result, ContractError> { - let collection_info: CollectionInfoResponse = deps - .querier - .query_wasm_smart(collection_addr, &Sg721QueryMsg::CollectionInfo {})?; - Ok(collection_info.royalty_info) -} - -/// Retrieve the next pool counter from storage and increment it -pub fn get_next_pool_counter(store: &mut dyn Storage) -> Result { - let pool_counter = POOL_COUNTER.load(store)?; - POOL_COUNTER.save(store, &(pool_counter + 1))?; - Ok(pool_counter) -} - -pub fn remove_buy_from_pool_quote( - store: &mut dyn Storage, - pool_id: u64, - response: Response, -) -> Result { - let old_data = buy_from_pool_quotes().may_load(store, pool_id)?; - if old_data.is_none() { - return Ok(response); - } - buy_from_pool_quotes().replace(store, pool_id, None, old_data.as_ref())?; - let response = response - .add_event(Event::new("remove-buy-pool-quote").add_attribute("id", pool_id.to_string())); - Ok(response) -} - -pub fn remove_sell_to_pool_quote( - store: &mut dyn Storage, - pool_id: u64, - response: Response, -) -> Result { - let old_data = sell_to_pool_quotes().may_load(store, pool_id)?; - if old_data.is_none() { - return Ok(response); - } - sell_to_pool_quotes().replace(store, pool_id, None, old_data.as_ref())?; - let response = response - .add_event(Event::new("remove-sell-pool-quote").add_attribute("id", pool_id.to_string())); - Ok(response) -} - -/// Update the indexed buy pool quotes for a specific pool -pub fn update_buy_from_pool_quotes( - store: &mut dyn Storage, - pool: &Pool, - min_price: Uint128, - response: Response, -) -> Result { - if !pool.can_sell_nfts() { - return Ok(response); - } - let mut response = response; - if !pool.is_active { - response = remove_buy_from_pool_quote(store, pool.id, response)?; - return Ok(response); - } - let buy_pool_quote = pool.get_buy_from_pool_quote(min_price)?; - - // If the pool quote is less than the minimum price, remove it from the index - if buy_pool_quote.is_none() { - response = remove_buy_from_pool_quote(store, pool.id, response)?; - return Ok(response); - } - let pool_quote = PoolQuote { - id: pool.id, - collection: pool.collection.clone(), - quote_price: buy_pool_quote.unwrap(), - }; - buy_from_pool_quotes().save(store, pool.id, &pool_quote)?; - response = response.add_event( - Event::new("add-buy-pool-quote") - .add_attribute("id", pool_quote.id.to_string()) - .add_attribute("collection", pool_quote.collection.to_string()) - .add_attribute("quote_price", pool_quote.quote_price.to_string()), - ); - Ok(response) -} - -/// Update the indexed sell pool quotes for a specific pool -pub fn update_sell_to_pool_quotes( - store: &mut dyn Storage, - pool: &Pool, - min_price: Uint128, - response: Response, -) -> Result { - if !pool.can_buy_nfts() { - return Ok(response); - } - let mut response = response; - if !pool.is_active { - response = remove_sell_to_pool_quote(store, pool.id, response)?; - return Ok(response); - } - let sell_pool_quote = pool.get_sell_to_pool_quote(min_price)?; - // If the pool quote is less than the minimum price, remove it from the index - if sell_pool_quote.is_none() { - response = remove_sell_to_pool_quote(store, pool.id, response)?; - return Ok(response); - } - let pool_quote = PoolQuote { - id: pool.id, - collection: pool.collection.clone(), - quote_price: sell_pool_quote.unwrap(), - }; - sell_to_pool_quotes().save(store, pool.id, &pool_quote)?; - response = response.add_event( - Event::new("add-sell-pool-quote") - .add_attribute("id", pool_quote.id.to_string()) - .add_attribute("collection", pool_quote.collection.to_string()) - .add_attribute("quote_price", pool_quote.quote_price.to_string()), - ); - Ok(response) -} - -/// Force pool property values for certain pools -pub fn force_property_values(pool: &mut Pool) -> Result<(), ContractError> { - if pool.bonding_curve == BondingCurve::ConstantProduct { - pool.delta = Uint128::zero(); - if pool.total_nfts == 0u64 { - pool.spot_price = Uint128::zero(); - } else { - pool.spot_price = pool - .total_tokens - .checked_div(Uint128::from(pool.total_nfts)) - .unwrap(); - } - }; - Ok(()) -} - -/// Save a pool, check invariants, update pool quotes -/// IMPORTANT: this function must always be called when saving a pool! -pub fn save_pool( - store: &mut dyn Storage, - pool: &mut Pool, - marketplace_params: &ParamsResponse, - response: Response, -) -> Result { - let mut response = response; - pool.validate(marketplace_params)?; - force_property_values(pool)?; - response = - update_buy_from_pool_quotes(store, pool, marketplace_params.params.min_price, response)?; - response = - update_sell_to_pool_quotes(store, pool, marketplace_params.params.min_price, response)?; - pools().save(store, pool.id, pool)?; - - Ok(response) -} - -/// Save pools batch convenience function -pub fn save_pools( - store: &mut dyn Storage, - pools: Vec<&mut Pool>, - marketplace_params: &ParamsResponse, - response: Response, -) -> Result { - let mut response = response; - for pool in pools { - response = save_pool(store, pool, marketplace_params, response)?; - } - Ok(response) -} - -/// Remove a pool, and remove pool quotes -/// IMPORTANT: this function must always be called when removing a pool! -pub fn remove_pool( - store: &mut dyn Storage, - pool: &mut Pool, - marketplace_params: &ParamsResponse, - response: Response, -) -> Result { - let mut response = response; - pool.set_active(false)?; - response = - update_buy_from_pool_quotes(store, pool, marketplace_params.params.min_price, response)?; - response = - update_sell_to_pool_quotes(store, pool, marketplace_params.params.min_price, response)?; - pools().remove(store, pool.id)?; - - Ok(response) -} - -/// Store NFT deposit -pub fn store_nft_deposit( - storage: &mut dyn Storage, - pool_id: u64, - nft_token_id: &str, -) -> StdResult<()> { - NFT_DEPOSITS.save(storage, (pool_id, nft_token_id.to_string()), &true) -} - -/// Remove NFT deposit -pub fn remove_nft_deposit( - storage: &mut dyn Storage, - pool_id: u64, - nft_token_id: &str, -) -> Result<(), ContractError> { - let nft_found = verify_nft_deposit(storage, pool_id, nft_token_id); - if !nft_found { - return Err(ContractError::NftNotFound(nft_token_id.to_string())); - } - NFT_DEPOSITS.remove(storage, (pool_id, nft_token_id.to_string())); - Ok(()) -} - -/// Verify NFT is deposited into pool -pub fn verify_nft_deposit(storage: &dyn Storage, pool_id: u64, nft_token_id: &str) -> bool { - NFT_DEPOSITS.has(storage, (pool_id, nft_token_id.to_string())) -} - -/// Grab the first NFT in a pool -pub fn get_nft_deposit( - storage: &dyn Storage, - pool_id: u64, - offset: u32, -) -> Result, ContractError> { - let mut nft_token_id: Vec = NFT_DEPOSITS - .prefix(pool_id) - .range(storage, None, None, Order::Ascending) - .skip(offset as usize) - .take(1) - .map(|item| item.map(|(nft_token_id, _)| nft_token_id)) - .collect::>()?; - Ok(nft_token_id.pop()) -} - -/// Process swaps for NFT deposit changes -pub fn update_nft_deposits( - storage: &mut dyn Storage, - contract: &Addr, - swaps: &[Swap], -) -> Result<(), ContractError> { - for swap in swaps.iter() { - match swap.transaction_type { - TransactionType::UserSubmitsNfts => { - if &swap.nft_payment.address == contract { - store_nft_deposit(storage, swap.pool_id, &swap.nft_payment.nft_token_id)?; - } - } - TransactionType::UserSubmitsTokens => { - remove_nft_deposit(storage, swap.pool_id, &swap.nft_payment.nft_token_id)?; - } - } - } - Ok(()) -} - -/// Process swaps for NFT deposit changes -pub fn get_transaction_events(swaps: &[Swap], pools_to_save: &[Pool]) -> Vec { - let mut events: Vec = vec![]; - for swap in swaps.iter() { - events.push(swap.into()); - } - for pool in pools_to_save.iter() { - events.push( - pool.create_event( - "pool-swap-update", - vec![ - "id", - "spot_price", - "total_nfts", - "total_tokens", - "is_active", - ], - ) - .unwrap(), - ); - } - events -} - -/// Push the transfer NFT message on the NFT collection contract -pub fn transfer_nft( - token_id: &str, - recipient: &str, - collection: &str, - response: &mut Response, -) -> StdResult<()> { - let sg721_transfer_msg = Sg721ExecuteMsg::TransferNft { - token_id: token_id.to_string(), - recipient: recipient.to_string(), - }; - - let exec_sg721_transfer = SubMsg::new(WasmMsg::Execute { - contract_addr: collection.to_string(), - msg: to_binary(&sg721_transfer_msg)?, - funds: vec![], - }); - response.messages.push(exec_sg721_transfer); - Ok(()) -} - -/// Push the BankeMsg send message -pub fn transfer_token(coin_send: Coin, recipient: &str, response: &mut Response) -> StdResult<()> { - let token_transfer_msg = BankMsg::Send { - to_address: recipient.to_string(), - amount: vec![coin_send], - }; - response.messages.push(SubMsg::new(token_transfer_msg)); - - Ok(()) -} - -/// Verify that a message is indeed invoked by the owner -pub fn only_owner(info: &MessageInfo, pool: &Pool) -> Result<(), ContractError> { - if pool.owner != info.sender { - return Err(ContractError::Unauthorized(String::from( - "sender is not the owner of the pool", - ))); - } - Ok(()) -} - -pub fn only_nft_owner( - deps: Deps, - info: &MessageInfo, - collection: &Addr, - token_id: &str, -) -> Result { - let res = Cw721Contract::(collection.clone(), PhantomData, PhantomData) - .owner_of(&deps.querier, token_id, false)?; - if res.owner != info.sender { - return Err(ContractError::Unauthorized(String::from( - "only the owner can call this function", - ))); - } - - Ok(res) -} - -/// Convert an option bool to an Order -pub fn option_bool_to_order(descending: Option, default: Order) -> Order { - match descending { - Some(_descending) => { - if _descending { - Order::Descending - } else { - Order::Ascending - } - } - _ => default, - } -} - -/// Verify that a message has been processed before the specified deadline -pub fn check_deadline(block: &BlockInfo, deadline: Timestamp) -> Result<(), ContractError> { - if deadline <= block.time { - return Err(ContractError::DeadlinePassed); - } - Ok(()) -} - -/// Verify that the finder address is neither the sender nor the asset recipient -pub fn validate_finder( - finder: &Option, - sender: &Addr, - asset_recipient: &Option, -) -> Result<(), ContractError> { - if finder.is_none() { - return Ok(()); - } - if finder.as_ref().unwrap() == sender || finder == asset_recipient { - return Err(ContractError::InvalidInput("finder is invalid".to_string())); - } - Ok(()) -} - -pub struct SwapPrepResult { - pub marketplace_params: ParamsResponse, - pub collection_royalties: Option, - pub asset_recipient: Addr, - pub finder: Option, - pub developer: Option, -} - -/// Prepare the contract for a swap transaction -pub fn prep_for_swap( - deps: Deps, - block_info: &Option, - sender: &Addr, - collection: &Addr, - swap_params: &SwapParams, -) -> Result { - if let Some(_block_info) = block_info { - check_deadline(_block_info, swap_params.deadline)?; - } - - let finder = maybe_addr(deps.api, swap_params.finder.clone())?; - let asset_recipient = maybe_addr(deps.api, swap_params.asset_recipient.clone())?; - - validate_finder(&finder, sender, &asset_recipient)?; - - let config = CONFIG.load(deps.storage)?; - let marketplace_params = load_marketplace_params(deps, &config.marketplace_addr)?; - - let collection_royalties = load_collection_royalties(deps, collection)?; - - let seller_recipient = asset_recipient.unwrap_or_else(|| sender.clone()); - - Ok(SwapPrepResult { - marketplace_params, - collection_royalties, - asset_recipient: seller_recipient, - finder, - developer: config.developer, - }) -} - -/// Validate NftSwap vector token amounts, and NFT ownership -pub fn validate_nft_swaps_for_sell( - deps: Deps, - info: &MessageInfo, - collection: &Addr, - nft_swaps: &[NftSwap], -) -> Result<(), ContractError> { - if nft_swaps.is_empty() { - return Err(ContractError::InvalidInput( - "nft swaps must not be empty".to_string(), - )); - } - let mut uniq_nft_token_ids: BTreeSet = BTreeSet::new(); - for (idx, nft_swap) in nft_swaps.iter().enumerate() { - only_nft_owner(deps, info, collection, &nft_swap.nft_token_id)?; - if uniq_nft_token_ids.contains(&nft_swap.nft_token_id) { - return Err(ContractError::InvalidInput( - "found duplicate nft token id".to_string(), - )); - } - uniq_nft_token_ids.insert(nft_swap.nft_token_id.clone()); - - if idx == 0 { - continue; - } - if nft_swaps[idx - 1].token_amount < nft_swap.token_amount { - return Err(ContractError::InvalidInput( - "nft swap token amounts must decrease monotonically".to_string(), - )); - } - } - Ok(()) -} - -/// Validate NftSwap vector token amounts, and that user has provided enough tokens -pub fn validate_nft_swaps_for_buy( - info: &MessageInfo, - pool_nft_swaps: &Vec, -) -> Result { - if pool_nft_swaps.is_empty() { - return Err(ContractError::InvalidInput( - "pool nft swaps must not be empty".to_string(), - )); - } - let mut expected_amount = Uint128::zero(); - let mut uniq_nft_token_ids: BTreeSet = BTreeSet::new(); - - for pool_nft_swap in pool_nft_swaps { - for (idx, nft_swap) in pool_nft_swap.nft_swaps.iter().enumerate() { - if uniq_nft_token_ids.contains(&nft_swap.nft_token_id) { - return Err(ContractError::InvalidInput( - "found duplicate nft token id".to_string(), - )); - } - uniq_nft_token_ids.insert(nft_swap.nft_token_id.clone()); - - expected_amount += nft_swap.token_amount; - if idx == 0 { - continue; - } - if pool_nft_swap.nft_swaps[idx - 1].token_amount > nft_swap.token_amount { - return Err(ContractError::InvalidInput( - "nft swap token amounts must increase monotonically".to_string(), - )); - } - } - } - - let received_amount = must_pay(info, NATIVE_DENOM)?; - if received_amount != expected_amount { - return Err(ContractError::InsufficientFunds(format!( - "expected {} but received {}", - expected_amount, received_amount - ))); - } - Ok(received_amount) -} diff --git a/contracts/infinity-swap/src/msg.rs b/contracts/infinity-swap/src/msg.rs deleted file mode 100644 index 00a670b..0000000 --- a/contracts/infinity-swap/src/msg.rs +++ /dev/null @@ -1,298 +0,0 @@ -use crate::{ - state::{BondingCurve, Config, Pool, PoolQuote}, - swap_processor::Swap, -}; -use cosmwasm_schema::cw_serde; -use cosmwasm_std::{Timestamp, Uint128}; -use std::fmt; - -#[cw_serde] -pub struct InstantiateMsg { - /// The fungible token used in the pools - pub denom: String, - /// The address of the marketplace contract - pub marketplace_addr: String, - /// The address of the developer who will receive a portion of the fair burn - pub developer: Option, -} - -/// SwapParams contains the parameters for a swap -#[cw_serde] -pub struct SwapParams { - /// The deadline after which the swap will be rejected - pub deadline: Timestamp, - /// Whether or not to revert the entire trade if one of the swaps fails - pub robust: bool, - /// The address to receive the assets from the swap, if not specified is set to sender - pub asset_recipient: Option, - /// The address of the finder, will receive a portion of the fees equal to percentage set by the pool - pub finder: Option, -} - -/// Defines whether the end user is buying or selling NFTs -#[cw_serde] -pub enum TransactionType { - UserSubmitsNfts, - UserSubmitsTokens, -} - -impl fmt::Display for TransactionType { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{:?}", self) - } -} - -/// NftSwap contains the parameters for an NFT swap -#[cw_serde] -pub struct NftSwap { - /// The id of the NFT to swap - pub nft_token_id: String, - /// The amount of tokens to accept in exchange for the NFT - /// Note: this could be the minimum acceptable amount for a sale - /// or the maximum acceptable amount for a purchase - pub token_amount: Uint128, -} - -/// PoolNftSwap is the parent of NftSwap and organizes swaps by pool_id -#[cw_serde] -pub struct PoolNftSwap { - /// The id of the pool to swap in - pub pool_id: u64, - /// The NFT swaps to execute - pub nft_swaps: Vec, -} - -#[cw_serde] -pub enum ExecuteMsg { - /// Create a new pool, defaults to an inactive state - CreateTokenPool { - collection: String, - asset_recipient: Option, - bonding_curve: BondingCurve, - spot_price: Uint128, - delta: Uint128, - finders_fee_bps: u64, - }, - CreateNftPool { - collection: String, - asset_recipient: Option, - bonding_curve: BondingCurve, - spot_price: Uint128, - delta: Uint128, - finders_fee_bps: u64, - }, - CreateTradePool { - collection: String, - asset_recipient: Option, - bonding_curve: BondingCurve, - spot_price: Uint128, - delta: Uint128, - finders_fee_bps: u64, - swap_fee_bps: u64, - reinvest_tokens: bool, - reinvest_nfts: bool, - }, - /// Deposit tokens into a pool - DepositTokens { - pool_id: u64, - }, - /// Deposit NFTs into a pool - DepositNfts { - pool_id: u64, - collection: String, - nft_token_ids: Vec, - }, - /// Withdraw tokens from a pool - WithdrawTokens { - pool_id: u64, - amount: Uint128, - asset_recipient: Option, - }, - /// Withdraw all tokens from a pool - WithdrawAllTokens { - pool_id: u64, - asset_recipient: Option, - }, - /// Withdraw NFTs from a pool - WithdrawNfts { - pool_id: u64, - nft_token_ids: Vec, - asset_recipient: Option, - }, - /// Withdraw all NFTs from a pool - WithdrawAllNfts { - pool_id: u64, - asset_recipient: Option, - }, - /// Update the parameters of a pool - UpdatePoolConfig { - pool_id: u64, - asset_recipient: Option, - delta: Option, - spot_price: Option, - finders_fee_bps: Option, - swap_fee_bps: Option, - reinvest_tokens: Option, - reinvest_nfts: Option, - }, - // Activate a pool so that it may begin accepting trades - SetActivePool { - is_active: bool, - pool_id: u64, - }, - /// Remove a pool from contract storage and indexing - RemovePool { - pool_id: u64, - asset_recipient: Option, - }, - /// Swap NFTs for tokens directly with a specified pool - DirectSwapNftsForTokens { - pool_id: u64, - nfts_to_swap: Vec, - swap_params: SwapParams, - }, - /// Swap NFTs for tokens at optimal sale prices - SwapNftsForTokens { - collection: String, - nfts_to_swap: Vec, - swap_params: SwapParams, - }, - /// Swap tokens for NFTs directly with a specified pool - /// Note: client must specify which NFTs they want to swap for - DirectSwapTokensForSpecificNfts { - pool_id: u64, - nfts_to_swap_for: Vec, - swap_params: SwapParams, - }, - /// Swap tokens for specific NFTs at optimal purchase prices - SwapTokensForSpecificNfts { - collection: String, - pool_nfts_to_swap_for: Vec, - swap_params: SwapParams, - }, - /// Swap tokens for any NFTs at optimal purchase prices - SwapTokensForAnyNfts { - collection: String, - max_expected_token_input: Vec, - swap_params: SwapParams, - }, -} - -/// QueryOptions are used to paginate contract queries -#[cw_serde] -pub struct QueryOptions { - /// Whether to sort items in ascending or descending order - pub descending: Option, - /// The key to start the query after - pub start_after: Option, - // The number of items that will be returned - pub limit: Option, -} - -#[cw_serde] -pub enum QueryMsg { - /// Get the global contract configuration object - /// Return type: `ConfigResponse` - Config {}, - /// Retrieve pools sorted by their pool id - /// Return type: `PoolsResponse` - Pools { query_options: QueryOptions }, - /// Retrieve pools by their pool id - /// Return type: `PoolsByIdResponse` - PoolsById { pool_ids: Vec }, - /// Retrieve pools by their owner address - /// Return type: `PoolsResponse` - PoolsByOwner { - owner: String, - query_options: QueryOptions, - }, - /// Retrieve the NFT token ids in a pool - /// Return type: `NftTokenIdsResponse` - PoolNftTokenIds { - pool_id: u64, - query_options: QueryOptions, - }, - /// Retrieve pool quotes sorted by their buy quote price - /// Return type: `PoolQuoteResponse` - QuotesBuyFromPool { - collection: String, - query_options: QueryOptions<(Uint128, u64)>, - }, - /// Retrieve pool quotes sorted by their sell quote price - /// Return type: `PoolQuoteResponse` - QuotesSellToPool { - collection: String, - query_options: QueryOptions<(Uint128, u64)>, - }, - /// Simulate a DirectSwapNftsForTokens transaction - /// Return type: `SwapResponse` - SimDirectSwapNftsForTokens { - pool_id: u64, - nfts_to_swap: Vec, - sender: String, - swap_params: SwapParams, - }, - /// Simulate a SwapNftsForTokens transaction - /// Return type: `SwapResponse` - SimSwapNftsForTokens { - collection: String, - nfts_to_swap: Vec, - sender: String, - swap_params: SwapParams, - }, - /// Simulate a DirectSwapTokensforSpecificNfts transaction - /// Return type: `SwapResponse` - SimDirectSwapTokensForSpecificNfts { - pool_id: u64, - nfts_to_swap_for: Vec, - sender: String, - swap_params: SwapParams, - }, - /// Simulate a SimSwapTokensForSpecificNfts transaction - /// Return type: `SwapResponse` - SimSwapTokensForSpecificNfts { - collection: String, - pool_nfts_to_swap_for: Vec, - sender: String, - swap_params: SwapParams, - }, - /// Simulate a SwapTokensForAnyNfts transaction - /// Return type: `SwapResponse` - SimSwapTokensForAnyNfts { - collection: String, - max_expected_token_input: Vec, - sender: String, - swap_params: SwapParams, - }, -} - -#[cw_serde] -pub struct ConfigResponse { - pub config: Config, -} - -#[cw_serde] -pub struct PoolsResponse { - pub pools: Vec, -} - -#[cw_serde] -pub struct PoolsByIdResponse { - pub pools: Vec<(u64, Option)>, -} - -#[cw_serde] -pub struct NftTokenIdsResponse { - pub pool_id: u64, - pub nft_token_ids: Vec, -} - -#[cw_serde] -pub struct PoolQuoteResponse { - pub pool_quotes: Vec, -} - -#[cw_serde] -pub struct SwapResponse { - pub swaps: Vec, -} diff --git a/contracts/infinity-swap/src/pool.rs b/contracts/infinity-swap/src/pool.rs deleted file mode 100644 index 3a8c41f..0000000 --- a/contracts/infinity-swap/src/pool.rs +++ /dev/null @@ -1,486 +0,0 @@ -use crate::msg::{NftSwap, TransactionType}; -use crate::state::{BondingCurve, Pool, PoolType}; -use crate::ContractError; -use cosmwasm_std::{attr, Addr, Attribute, Decimal, Event, OverflowError, StdError, Uint128}; -use sg_marketplace::msg::ParamsResponse; - -/// 100% represented as basis points -const MAX_BASIS_POINTS: u128 = 10000u128; -/// Maximum swap fee percent that can be set on trade pools -const MAX_SWAP_FEE_PERCENT: u64 = 5000u64; - -impl Pool { - /// Create a Pool object - pub fn new( - id: u64, - collection: Addr, - owner: Addr, - asset_recipient: Option, - pool_type: PoolType, - bonding_curve: BondingCurve, - spot_price: Uint128, - delta: Uint128, - finders_fee_percent: Decimal, - swap_fee_percent: Decimal, - reinvest_tokens: bool, - reinvest_nfts: bool, - ) -> Self { - Self { - id, - collection, - owner, - asset_recipient, - pool_type, - bonding_curve, - spot_price, - delta, - total_tokens: Uint128::zero(), - total_nfts: 0u64, - finders_fee_percent, - swap_fee_percent, - is_active: false, - reinvest_tokens, - reinvest_nfts, - } - } - - /// Verify that the pool is valid by checking invariants before save - pub fn validate(&self, marketplace_params: &ParamsResponse) -> Result<(), ContractError> { - if self.finders_fee_percent > marketplace_params.params.max_finders_fee_percent { - return Err(ContractError::InvalidPool( - "finders_fee_percent is above marketplace max_finders_fee_percent".to_string(), - )); - } - if self.bonding_curve == BondingCurve::Exponential && self.delta.u128() >= MAX_BASIS_POINTS - { - return Err(ContractError::InvalidPool( - "delta cannot exceed max basis points on exponential curves".to_string(), - )); - } - - match &self.pool_type { - PoolType::Token => { - if self.total_nfts != 0 { - return Err(ContractError::InvalidPool( - "total_nfts must be zero for token pool".to_string(), - )); - } - if self.spot_price == Uint128::zero() { - return Err(ContractError::InvalidPool( - "spot_price must be non-zero for token pool".to_string(), - )); - } - if self.swap_fee_percent > Decimal::zero() { - return Err(ContractError::InvalidPool( - "swap_fee_percent must be 0 for token pool".to_string(), - )); - } - if self.bonding_curve == BondingCurve::ConstantProduct { - return Err(ContractError::InvalidPool( - "constant product bonding curve cannot be used with token pools" - .to_string(), - )); - } - if self.reinvest_tokens { - return Err(ContractError::InvalidPool( - "cannot reinvest buy side on one sided pools".to_string(), - )); - } - if self.reinvest_nfts { - return Err(ContractError::InvalidPool( - "cannot reinvest sell side on one sided pools".to_string(), - )); - } - } - PoolType::Nft => { - if self.total_tokens > Uint128::zero() { - return Err(ContractError::InvalidPool( - "total_tokens must be zero for nft pool".to_string(), - )); - } - if self.spot_price == Uint128::zero() { - return Err(ContractError::InvalidPool( - "spot_price must be non-zero for nft pool".to_string(), - )); - } - if self.swap_fee_percent > Decimal::zero() { - return Err(ContractError::InvalidPool( - "swap_fee_percent must be 0 for nft pool".to_string(), - )); - } - if self.bonding_curve == BondingCurve::ConstantProduct { - return Err(ContractError::InvalidPool( - "constant product bonding curve cannot be used with nft pools".to_string(), - )); - } - if self.reinvest_tokens { - return Err(ContractError::InvalidPool( - "cannot reinvest buy side on one sided pools".to_string(), - )); - } - if self.reinvest_nfts { - return Err(ContractError::InvalidPool( - "cannot reinvest sell side on one sided pools".to_string(), - )); - } - } - PoolType::Trade => { - if self.swap_fee_percent > Decimal::percent(MAX_SWAP_FEE_PERCENT) { - return Err(ContractError::InvalidPool( - "swap_fee_percent cannot be greater than 50%".to_string(), - )); - } - } - } - - Ok(()) - } - - /// Get the recipient of assets for trades performed on this pool - pub fn get_recipient(&self) -> Addr { - match &self.asset_recipient { - Some(addr) => addr.clone(), - None => self.owner.clone(), - } - } - - /// Activate the pool so that it may begin accepting trades - pub fn set_active(&mut self, is_active: bool) -> Result<(), ContractError> { - self.is_active = is_active; - Ok(()) - } - - /// Deposit tokens into the pool - pub fn deposit_tokens(&mut self, amount: Uint128) -> Result<(), ContractError> { - if self.pool_type == PoolType::Nft { - return Err(ContractError::InvalidPool( - "cannot deposit tokens into nft pool".to_string(), - )); - } - self.total_tokens += amount; - Ok(()) - } - - /// Deposit nfts into the pool - pub fn deposit_nfts(&mut self, nft_token_ids: &Vec) -> Result<(), ContractError> { - if self.pool_type == PoolType::Token { - return Err(ContractError::InvalidPool( - "cannot deposit nfts into token pool".to_string(), - )); - } - self.total_nfts += nft_token_ids.len() as u64; - Ok(()) - } - - /// Withdraw tokens from the pool - pub fn withdraw_tokens(&mut self, amount: Uint128) -> Result<(), ContractError> { - if self.pool_type == PoolType::Nft { - return Err(ContractError::InvalidPool( - "cannot withdraw tokens from nft pool".to_string(), - )); - } - if self.total_tokens < amount { - return Err(ContractError::Std(StdError::overflow(OverflowError { - operation: cosmwasm_std::OverflowOperation::Sub, - operand1: self.total_tokens.to_string(), - operand2: amount.to_string(), - }))); - } - self.total_tokens -= amount; - Ok(()) - } - - /// Withdraw nfts from the pool - pub fn withdraw_nfts(&mut self, nft_token_ids: &Vec) -> Result<(), ContractError> { - if self.pool_type == PoolType::Token { - return Err(ContractError::InvalidPool( - "cannot withdraw nfts from token pool".to_string(), - )); - } - if self.total_nfts < nft_token_ids.len() as u64 { - return Err(ContractError::InternalError( - "pool NFT overdraw".to_string(), - )); - } - self.total_nfts -= nft_token_ids.len() as u64; - Ok(()) - } - - /// Returns whether or not the pool can buy NFTs - pub fn can_buy_nfts(&self) -> bool { - self.pool_type == PoolType::Trade || self.pool_type == PoolType::Token - } - - /// Returns whether or not the pool can sell NFTs - pub fn can_sell_nfts(&self) -> bool { - self.pool_type == PoolType::Trade || self.pool_type == PoolType::Nft - } - - /// Returns the price at which this pool will sell NFTs - /// Note: the buy_from_pool_quote is indexed by PoolQuote for future discovery - pub fn get_buy_from_pool_quote( - &self, - min_quote: Uint128, - ) -> Result, ContractError> { - // Calculate the buy price with respect to pool types and bonding curves - let buy_price = match self.pool_type { - PoolType::Token => Err(ContractError::InvalidPool( - "pool cannot sell nfts".to_string(), - )), - PoolType::Nft => Ok(self.spot_price), - PoolType::Trade => match self.bonding_curve { - BondingCurve::Linear => self - .spot_price - .checked_add(self.delta) - .map_err(|e| ContractError::Std(StdError::overflow(e))), - BondingCurve::Exponential => { - let net_delta = Uint128::from(MAX_BASIS_POINTS) - .checked_add(self.delta) - .map_err(|e| ContractError::Std(StdError::overflow(e)))?; - self.spot_price - .checked_mul(net_delta) - .map_err(|e| ContractError::Std(StdError::overflow(e)))? - .checked_div(Uint128::from(MAX_BASIS_POINTS)) - .map_err(|e| ContractError::Std(StdError::divide_by_zero(e)))? - .checked_add(Uint128::one()) - .map_err(|e| ContractError::Std(StdError::overflow(e))) - } - BondingCurve::ConstantProduct => { - if self.total_nfts <= 1 { - return Ok(None); - } - let buy_price = self - .total_tokens - .checked_div(Uint128::from(self.total_nfts - 1)) - .map_err(|e| ContractError::Std(StdError::divide_by_zero(e)))? - .checked_add(Uint128::one()) - .map_err(|e| ContractError::Std(StdError::overflow(e)))?; - Ok(buy_price) - } - }, - }?; - // If the pool has no NFTs to sell, or quote is below min, return None - if self.total_nfts == 0 || buy_price < min_quote { - return Ok(None); - } - Ok(Some(buy_price)) - } - - /// Returns the price at which this pool will buy NFTs - /// Note: the sell_to_pool_quote is indexed by PoolQuote for future discovery - pub fn get_sell_to_pool_quote( - &self, - min_quote: Uint128, - ) -> Result, ContractError> { - if !self.can_buy_nfts() { - return Err(ContractError::InvalidPool( - "pool cannot buy nfts".to_string(), - )); - } - let sell_price = match self.bonding_curve { - BondingCurve::Linear | BondingCurve::Exponential => self.spot_price, - BondingCurve::ConstantProduct => { - if self.total_nfts < 1 { - return Ok(None); - } - self.total_tokens - .checked_div(Uint128::from(self.total_nfts + 1)) - .unwrap() - } - }; - // If the pool has insufficient tokens to buy the NFT, or quote is below min, return None - if self.total_tokens < sell_price || sell_price < min_quote { - return Ok(None); - } - Ok(Some(sell_price)) - } - - /// Buy an NFT from the pool - pub fn buy_nft_from_pool( - &mut self, - nft_swap: &NftSwap, - sale_price: Uint128, - ) -> Result<(), ContractError> { - if !self.can_sell_nfts() { - return Err(ContractError::InvalidPool( - "pool cannot sell nfts".to_string(), - )); - } - if !self.is_active { - return Err(ContractError::InvalidPool("pool is not active".to_string())); - } - - // If sale price exceeds the max expected, return an error - if sale_price > nft_swap.token_amount { - return Err(ContractError::SwapError( - "pool sale price is above max expected".to_string(), - )); - } - - // Decrement total_nfts on pool - if self.total_nfts == 0 { - return Err(ContractError::SwapError( - "pool does not own any NFTS".to_string(), - )); - } else { - self.total_nfts -= 1; - } - - Ok(()) - } - - /// Sell an NFT to the pool - pub fn sell_nft_to_pool( - &mut self, - nft_swap: &NftSwap, - sale_price: Uint128, - ) -> Result<(), ContractError> { - if !self.can_buy_nfts() { - return Err(ContractError::InvalidPool( - "pool cannot buy nfts".to_string(), - )); - } - if !self.is_active { - return Err(ContractError::InvalidPool("pool is not active".to_string())); - } - - // If sale price is below the min expected, return an error - if sale_price < nft_swap.token_amount { - return Err(ContractError::SwapError( - "pool sale price is below min expected".to_string(), - )); - } - - // Deduct the sale price from the pool's token balance - self.total_tokens -= sale_price; - - Ok(()) - } - - /// Updates the spot price of the pool depending on the transaction type - pub fn update_spot_price(&mut self, tx_type: &TransactionType) -> Result<(), StdError> { - let result = match tx_type { - TransactionType::UserSubmitsNfts => match self.bonding_curve { - BondingCurve::Linear => self - .spot_price - .checked_sub(self.delta) - .map_err(StdError::overflow), - BondingCurve::Exponential => { - let denominator = Uint128::from(MAX_BASIS_POINTS) - .checked_add(self.delta) - .map_err(StdError::overflow)?; - self.spot_price - .checked_mul(Uint128::from(MAX_BASIS_POINTS)) - .map_err(StdError::overflow)? - .checked_div(denominator) - .map_err(StdError::divide_by_zero) - } - BondingCurve::ConstantProduct => self - .total_tokens - .checked_div(Uint128::from(self.total_nfts)) - .map_err(StdError::divide_by_zero), - }, - TransactionType::UserSubmitsTokens => match self.bonding_curve { - BondingCurve::Linear => self - .spot_price - .checked_add(self.delta) - .map_err(StdError::overflow), - BondingCurve::Exponential => { - let net_delta = Uint128::from(MAX_BASIS_POINTS) - .checked_add(self.delta) - .map_err(StdError::overflow)?; - self.spot_price - .checked_mul(net_delta) - .map_err(StdError::overflow)? - .checked_div(Uint128::from(MAX_BASIS_POINTS)) - .map_err(StdError::divide_by_zero)? - .checked_add(Uint128::one()) - .map_err(StdError::overflow) - } - BondingCurve::ConstantProduct => self - .total_tokens - .checked_div(Uint128::from(self.total_nfts)) - .map_err(StdError::divide_by_zero)? - .checked_add(Uint128::one()) - .map_err(StdError::overflow), - }, - }; - match result { - Ok(_spot_price) => { - self.spot_price = _spot_price; - Ok(()) - } - Err(_err) => { - self.is_active = false; - Err(_err) - } - } - } - - /// Create an event with all the Pool properties - pub fn create_event_all_props(&self, event_type: &str) -> Result { - self.create_event( - event_type, - vec![ - "id", - "collection", - "owner", - "asset_recipient", - "pool_type", - "bonding_curve", - "spot_price", - "delta", - "total_tokens", - "total_nfts", - "is_active", - "swap_fee_percent", - "finders_fee_percent", - "reinvest_tokens", - "reinvest_nfts", - ], - ) - } - - /// Create an event with certain Pool properties - pub fn create_event( - &self, - event_type: &str, - attr_keys: Vec<&str>, - ) -> Result { - let mut attributes: Vec = vec![]; - for attr_keys in attr_keys { - let attribute = match attr_keys { - "id" => attr("id", self.id.to_string()), - "collection" => attr("collection", self.collection.to_string()), - "owner" => attr("owner", self.owner.to_string()), - "asset_recipient" => attr( - "asset_recipient", - self.asset_recipient - .as_ref() - .map_or("None".to_string(), |addr| addr.to_string()), - ), - "pool_type" => attr("pool_type", self.pool_type.to_string()), - "bonding_curve" => attr("bonding_curve", self.bonding_curve.to_string()), - "spot_price" => attr("spot_price", self.spot_price.to_string()), - "delta" => attr("delta", self.delta.to_string()), - "total_tokens" => attr("total_tokens", self.total_tokens.to_string()), - "total_nfts" => attr("total_nfts", self.total_nfts.to_string()), - "is_active" => attr("is_active", self.is_active.to_string()), - "swap_fee_percent" => attr("swap_fee_percent", self.swap_fee_percent.to_string()), - "finders_fee_percent" => { - attr("finders_fee_percent", self.finders_fee_percent.to_string()) - } - "reinvest_tokens" => attr("reinvest_tokens", self.reinvest_tokens.to_string()), - "reinvest_nfts" => attr("reinvest_nfts", self.reinvest_nfts.to_string()), - _key => { - return Err(ContractError::InvalidPropertyKeyError(format!( - "Invalid property key: {}", - _key - ))); - } - }; - attributes.push(attribute); - } - Ok(Event::new(event_type).add_attributes(attributes)) - } -} diff --git a/contracts/infinity-swap/src/query.rs b/contracts/infinity-swap/src/query.rs deleted file mode 100644 index d07f707..0000000 --- a/contracts/infinity-swap/src/query.rs +++ /dev/null @@ -1,435 +0,0 @@ -use crate::helpers::{option_bool_to_order, prep_for_swap}; -use crate::msg::{ - ConfigResponse, NftSwap, NftTokenIdsResponse, PoolNftSwap, PoolQuoteResponse, - PoolsByIdResponse, PoolsResponse, QueryMsg, QueryOptions, SwapParams, SwapResponse, - TransactionType, -}; -use crate::state::{ - buy_from_pool_quotes, pools, sell_to_pool_quotes, PoolQuote, CONFIG, NFT_DEPOSITS, -}; -use crate::swap_processor::SwapProcessor; -use cosmwasm_std::{ - entry_point, to_binary, Addr, Binary, Deps, Env, Order, StdError, StdResult, Uint128, -}; -use cw_storage_plus::Bound; - -// Query limits -const DEFAULT_QUERY_LIMIT: u32 = 10; -const MAX_QUERY_LIMIT: u32 = 100; - -#[cfg_attr(not(feature = "library"), entry_point)] -pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { - let api = deps.api; - - match msg { - QueryMsg::Config {} => to_binary(&query_config(deps)?), - QueryMsg::Pools { query_options } => to_binary(&query_pools(deps, query_options)?), - QueryMsg::PoolsById { pool_ids } => to_binary(&query_pools_by_id(deps, pool_ids)?), - QueryMsg::PoolsByOwner { - owner, - query_options, - } => to_binary(&query_pools_by_owner( - deps, - api.addr_validate(&owner)?, - query_options, - )?), - QueryMsg::PoolNftTokenIds { - pool_id, - query_options, - } => to_binary(&query_pool_nft_token_ids(deps, pool_id, query_options)?), - QueryMsg::QuotesBuyFromPool { - collection, - query_options, - } => to_binary(&query_quotes_buy_from_pool( - deps, - api.addr_validate(&collection)?, - query_options, - )?), - QueryMsg::QuotesSellToPool { - collection, - query_options, - } => to_binary(&query_quotes_sell_to_pool( - deps, - api.addr_validate(&collection)?, - query_options, - )?), - QueryMsg::SimDirectSwapNftsForTokens { - pool_id, - nfts_to_swap, - sender, - swap_params, - } => to_binary(&sim_direct_swap_nfts_for_tokens( - deps, - env, - pool_id, - nfts_to_swap, - api.addr_validate(&sender)?, - swap_params, - )?), - QueryMsg::SimSwapNftsForTokens { - collection, - nfts_to_swap, - sender, - swap_params, - } => to_binary(&sim_swap_nfts_for_tokens( - deps, - env, - api.addr_validate(&collection)?, - nfts_to_swap, - api.addr_validate(&sender)?, - swap_params, - )?), - QueryMsg::SimDirectSwapTokensForSpecificNfts { - pool_id, - nfts_to_swap_for, - sender, - swap_params, - } => to_binary(&sim_direct_swap_tokens_for_specific_nfts( - deps, - env, - pool_id, - nfts_to_swap_for, - api.addr_validate(&sender)?, - swap_params, - )?), - QueryMsg::SimSwapTokensForSpecificNfts { - collection, - pool_nfts_to_swap_for, - sender, - swap_params, - } => to_binary(&sim_swap_tokens_for_specific_nfts( - deps, - env, - api.addr_validate(&collection)?, - pool_nfts_to_swap_for, - api.addr_validate(&sender)?, - swap_params, - )?), - QueryMsg::SimSwapTokensForAnyNfts { - collection, - max_expected_token_input, - sender, - swap_params, - } => to_binary(&sim_swap_tokens_for_any_nfts( - deps, - env, - api.addr_validate(&collection)?, - max_expected_token_input, - api.addr_validate(&sender)?, - swap_params, - )?), - } -} - -pub fn query_config(deps: Deps) -> StdResult { - let config = CONFIG.load(deps.storage)?; - Ok(ConfigResponse { config }) -} - -pub fn query_pools(deps: Deps, query_options: QueryOptions) -> StdResult { - let limit = query_options - .limit - .unwrap_or(DEFAULT_QUERY_LIMIT) - .min(MAX_QUERY_LIMIT) as usize; - let start = query_options.start_after.map(Bound::exclusive); - let order = option_bool_to_order(query_options.descending, Order::Ascending); - - let pools = pools() - .range(deps.storage, start, None, order) - .take(limit) - .map(|item| item.map(|(_, v)| v)) - .collect::>()?; - - Ok(PoolsResponse { pools }) -} - -pub fn query_pools_by_id(deps: Deps, pool_ids: Vec) -> StdResult { - let mut resp_vec = vec![]; - for pool_id in pool_ids { - let pool = pools().may_load(deps.storage, pool_id)?; - resp_vec.push((pool_id, pool)); - } - Ok(PoolsByIdResponse { pools: resp_vec }) -} - -pub fn query_pools_by_owner( - deps: Deps, - owner: Addr, - query_options: QueryOptions, -) -> StdResult { - let limit = query_options - .limit - .unwrap_or(DEFAULT_QUERY_LIMIT) - .min(MAX_QUERY_LIMIT) as usize; - let start = query_options.start_after.map(Bound::exclusive); - let order = option_bool_to_order(query_options.descending, Order::Ascending); - - let pools = pools() - .idx - .owner - .prefix(owner) - .range(deps.storage, start, None, order) - .take(limit) - .map(|item| item.map(|(_, v)| v)) - .collect::>()?; - - Ok(PoolsResponse { pools }) -} - -pub fn query_pool_nft_token_ids( - deps: Deps, - pool_id: u64, - query_options: QueryOptions, -) -> StdResult { - let limit = query_options - .limit - .unwrap_or(DEFAULT_QUERY_LIMIT) - .min(MAX_QUERY_LIMIT) as usize; - - let start = query_options.start_after.as_ref().map(Bound::exclusive); - let order = option_bool_to_order(query_options.descending, Order::Ascending); - - let nft_token_ids: Vec = NFT_DEPOSITS - .prefix(pool_id) - .range(deps.storage, start, None, order) - .take(limit) - .map(|item| item.map(|(nft_token_id, _)| nft_token_id)) - .collect::>()?; - - Ok(NftTokenIdsResponse { - pool_id, - nft_token_ids, - }) -} - -pub fn query_quotes_buy_from_pool( - deps: Deps, - collection: Addr, - query_options: QueryOptions<(Uint128, u64)>, -) -> StdResult { - let limit = query_options - .limit - .unwrap_or(DEFAULT_QUERY_LIMIT) - .min(MAX_QUERY_LIMIT) as usize; - let start = query_options - .start_after - .as_ref() - .map(|offset| Bound::exclusive((offset.0.u128(), offset.1))); - let order = option_bool_to_order(query_options.descending, Order::Ascending); - - let pool_quotes: Vec = buy_from_pool_quotes() - .idx - .collection_buy_price - .sub_prefix(collection) - .range(deps.storage, start, None, order) - .take(limit) - .map(|item| item.map(|(_, v)| v)) - .collect::>()?; - - Ok(PoolQuoteResponse { pool_quotes }) -} - -pub fn query_quotes_sell_to_pool( - deps: Deps, - collection: Addr, - query_options: QueryOptions<(Uint128, u64)>, -) -> StdResult { - let limit = query_options - .limit - .unwrap_or(DEFAULT_QUERY_LIMIT) - .min(MAX_QUERY_LIMIT) as usize; - let start = query_options - .start_after - .as_ref() - .map(|offset| Bound::exclusive((offset.0.u128(), offset.1))); - let order = option_bool_to_order(query_options.descending, Order::Descending); - - let pool_quotes: Vec = sell_to_pool_quotes() - .idx - .collection_sell_price - .sub_prefix(collection) - .range(deps.storage, start, None, order) - .take(limit) - .map(|item| item.map(|(_, v)| v)) - .collect::>()?; - - Ok(PoolQuoteResponse { pool_quotes }) -} - -pub fn sim_direct_swap_nfts_for_tokens( - deps: Deps, - env: Env, - pool_id: u64, - nfts_to_swap: Vec, - sender: Addr, - swap_params: SwapParams, -) -> StdResult { - let pool = pools().load(deps.storage, pool_id)?; - - let swap_prep_result = prep_for_swap(deps, &None, &sender, &pool.collection, &swap_params) - .map_err(|err| StdError::generic_err(err.to_string()))?; - - let mut processor = SwapProcessor::new( - TransactionType::UserSubmitsNfts, - env.contract.address, - pool.collection.clone(), - sender, - Uint128::zero(), - swap_prep_result.asset_recipient, - swap_prep_result - .marketplace_params - .params - .trading_fee_percent, - swap_prep_result.marketplace_params.params.min_price, - swap_prep_result.collection_royalties, - swap_prep_result.finder, - swap_prep_result.developer, - ); - processor - .direct_swap_nfts_for_tokens(pool, nfts_to_swap, swap_params) - .map_err(|err| StdError::generic_err(err.to_string()))?; - - Ok(SwapResponse { - swaps: processor.swaps, - }) -} - -pub fn sim_swap_nfts_for_tokens( - deps: Deps, - env: Env, - collection: Addr, - nfts_to_swap: Vec, - sender: Addr, - swap_params: SwapParams, -) -> StdResult { - let swap_prep_result = prep_for_swap(deps, &None, &sender, &collection, &swap_params) - .map_err(|err| StdError::generic_err(err.to_string()))?; - - let mut processor = SwapProcessor::new( - TransactionType::UserSubmitsNfts, - env.contract.address, - collection, - sender, - Uint128::zero(), - swap_prep_result.asset_recipient, - swap_prep_result - .marketplace_params - .params - .trading_fee_percent, - swap_prep_result.marketplace_params.params.min_price, - swap_prep_result.collection_royalties, - swap_prep_result.finder, - swap_prep_result.developer, - ); - processor - .swap_nfts_for_tokens(deps.storage, nfts_to_swap, swap_params) - .map_err(|err| StdError::generic_err(err.to_string()))?; - - Ok(SwapResponse { - swaps: processor.swaps, - }) -} - -pub fn sim_direct_swap_tokens_for_specific_nfts( - deps: Deps, - env: Env, - pool_id: u64, - nfts_to_swap_for: Vec, - sender: Addr, - swap_params: SwapParams, -) -> StdResult { - let pool = pools().load(deps.storage, pool_id)?; - - sim_swap_tokens_for_specific_nfts( - deps, - env, - pool.collection, - vec![PoolNftSwap { - pool_id, - nft_swaps: nfts_to_swap_for, - }], - sender, - swap_params, - ) -} - -pub fn sim_swap_tokens_for_specific_nfts( - deps: Deps, - env: Env, - collection: Addr, - pool_nfts_to_swap_for: Vec, - sender: Addr, - swap_params: SwapParams, -) -> StdResult { - let swap_prep_result = prep_for_swap(deps, &None, &sender, &collection, &swap_params) - .map_err(|err| StdError::generic_err(err.to_string()))?; - - let mut spend_amount = 0_u128; - for pool in pool_nfts_to_swap_for.iter() { - for nft_swap in pool.nft_swaps.iter() { - spend_amount += nft_swap.token_amount.u128(); - } - } - - let mut processor = SwapProcessor::new( - TransactionType::UserSubmitsTokens, - env.contract.address, - collection, - sender, - spend_amount.into(), - swap_prep_result.asset_recipient, - swap_prep_result - .marketplace_params - .params - .trading_fee_percent, - swap_prep_result.marketplace_params.params.min_price, - swap_prep_result.collection_royalties, - swap_prep_result.finder, - swap_prep_result.developer, - ); - processor - .swap_tokens_for_specific_nfts(deps.storage, pool_nfts_to_swap_for, swap_params) - .map_err(|err| StdError::generic_err(err.to_string()))?; - - Ok(SwapResponse { - swaps: processor.swaps, - }) -} - -pub fn sim_swap_tokens_for_any_nfts( - deps: Deps, - env: Env, - collection: Addr, - max_expected_token_input: Vec, - sender: Addr, - swap_params: SwapParams, -) -> StdResult { - let swap_prep_result = prep_for_swap(deps, &None, &sender, &collection, &swap_params) - .map_err(|err| StdError::generic_err(err.to_string()))?; - - let total_tokens: Uint128 = max_expected_token_input.iter().sum(); - - let mut processor = SwapProcessor::new( - TransactionType::UserSubmitsTokens, - env.contract.address, - collection, - sender, - total_tokens, - swap_prep_result.asset_recipient, - swap_prep_result - .marketplace_params - .params - .trading_fee_percent, - swap_prep_result.marketplace_params.params.min_price, - swap_prep_result.collection_royalties, - swap_prep_result.finder, - swap_prep_result.developer, - ); - processor - .swap_tokens_for_any_nfts(deps.storage, max_expected_token_input, swap_params) - .map_err(|err| StdError::generic_err(err.to_string()))?; - - Ok(SwapResponse { - swaps: processor.swaps, - }) -} diff --git a/contracts/infinity-swap/src/state.rs b/contracts/infinity-swap/src/state.rs deleted file mode 100644 index c112392..0000000 --- a/contracts/infinity-swap/src/state.rs +++ /dev/null @@ -1,180 +0,0 @@ -use cosmwasm_schema::cw_serde; -use cosmwasm_std::{Addr, Decimal, Uint128}; -use cw_storage_plus::{Index, IndexList, IndexedMap, Item, Map, MultiIndex}; -use std::fmt; - -/// An incrementing uint used as the primary key for pools -pub const POOL_COUNTER: Item = Item::new("pool_counter"); - -/// The global configuration object for the protocol -#[cw_serde] -pub struct Config { - /// The address of the marketplace contract - pub marketplace_addr: Addr, - /// The address of the developer who will receive a portion of the fair burn - pub developer: Option, -} - -pub const CONFIG: Item = Item::new("config"); - -/// PoolType refers to the assets held by the pool -/// * Token: A pool that holds fungible tokens -/// * Nft: A pool that holds NFTs -/// * Trade: A pool that holds both fungible tokens and NFTs -#[cw_serde] -pub enum PoolType { - Token, - Nft, - Trade, -} - -impl fmt::Display for PoolType { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{:?}", self) - } -} - -/// BondingCurve refers to the curve used to calculate the spot price for the pool -/// * Linear: A linear curve that increments by a constant amount (delta) -/// * Exponential: An exponential curve that increments by a percentage amount (delta) -/// * ConstantProduct: A constant product curve that maintains a constant product of the two assets -#[cw_serde] -pub enum BondingCurve { - Linear, - Exponential, - ConstantProduct, -} - -impl fmt::Display for BondingCurve { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{:?}", self) - } -} - -/// Pool represents a pool of assets that can be swapped -#[cw_serde] -pub struct Pool { - /// The unique id of the pool - pub id: u64, - /// The address of the NFT collection contract - pub collection: Addr, - /// The address of the pool owner - pub owner: Addr, - /// The address of the recipient of assets traded into the pool - pub asset_recipient: Option, - /// The type of assets held by the pool - pub pool_type: PoolType, - /// The bonding curve used to calculate the spot price - pub bonding_curve: BondingCurve, - /// A moving value used to derive the price at which the pool will trade assets - /// Note: this value is not necessarily the final sale price for pool assets - pub spot_price: Uint128, - /// The amount by which the spot price will increment/decrement - /// For linear curves, this is the constant amount - /// For exponential curves, this is the percentage amount (treated as basis points) - pub delta: Uint128, - /// The total amount of tokens held by the pool - pub total_tokens: Uint128, - /// The total number of NFTs held by the pool - pub total_nfts: u64, - /// The percentage of the swap that will be paid to the finder of a trade - pub finders_fee_percent: Decimal, - /// The percentage of the swap that will be paid to the pool owner - /// Note: this only applies to Trade pools - pub swap_fee_percent: Decimal, - /// Whether or not the pool is accepting trades - pub is_active: bool, - /// Whether or not the tokens sold into the pool will be reinvested - pub reinvest_tokens: bool, - /// Whether or not the NFTs sold into the pool will be reinvested - pub reinvest_nfts: bool, -} - -/// PoolIndices defines the indices for the Pool type -pub struct PoolIndices<'a> { - /// Indexes pools by the owner address - pub owner: MultiIndex<'a, Addr, Pool, u64>, -} - -impl<'a> IndexList for PoolIndices<'a> { - fn get_indexes(&'_ self) -> Box> + '_> { - let v: Vec<&dyn Index> = vec![&self.owner]; - Box::new(v.into_iter()) - } -} - -pub fn pools<'a>() -> IndexedMap<'a, u64, Pool, PoolIndices<'a>> { - let indexes = PoolIndices { - owner: MultiIndex::new( - |_pk: &[u8], p: &Pool| p.owner.clone(), - "pools", - "pools__owner", - ), - }; - IndexedMap::new("pools", indexes) -} - -/// PoolQuote represents a quote at which assets can be bought or sold from a pool -#[cw_serde] -pub struct PoolQuote { - /// The unique id of the pool quote, also corresponds to a pool_id - pub id: u64, - /// The address of the NFT collection contract - pub collection: Addr, - /// The price at which assets can be bought or sold - pub quote_price: Uint128, -} - -/// BuyPoolQuoteIndices defines the indices for the PoolQuote type -pub struct BuyPoolQuoteIndices<'a> { - /// Indexes pool quotes by the collection address and buy quote price - pub collection_buy_price: MultiIndex<'a, (Addr, u128), PoolQuote, u64>, -} - -impl<'a> IndexList for BuyPoolQuoteIndices<'a> { - fn get_indexes(&'_ self) -> Box> + '_> { - let v: Vec<&dyn Index> = vec![&self.collection_buy_price]; - Box::new(v.into_iter()) - } -} - -pub fn buy_from_pool_quotes<'a>() -> IndexedMap<'a, u64, PoolQuote, BuyPoolQuoteIndices<'a>> { - let indexes = BuyPoolQuoteIndices { - collection_buy_price: MultiIndex::new( - |_pk: &[u8], p: &PoolQuote| (p.collection.clone(), p.quote_price.u128()), - "buy_from_pool_quotes", - "buy_from_pool_quotes__collection_buy_price", - ), - }; - IndexedMap::new("buy_from_pool_quotes", indexes) -} - -/// SellPoolQuoteIndices defines the indices for the PoolQuote type -pub struct SellPoolQuoteIndices<'a> { - /// Indexes pool quotes by the collection address and sell quote price - pub collection_sell_price: MultiIndex<'a, (Addr, u128), PoolQuote, u64>, -} - -impl<'a> IndexList for SellPoolQuoteIndices<'a> { - fn get_indexes(&'_ self) -> Box> + '_> { - let v: Vec<&dyn Index> = vec![&self.collection_sell_price]; - Box::new(v.into_iter()) - } -} - -pub fn sell_to_pool_quotes<'a>() -> IndexedMap<'a, u64, PoolQuote, SellPoolQuoteIndices<'a>> { - let indexes = SellPoolQuoteIndices { - collection_sell_price: MultiIndex::new( - |_pk: &[u8], p: &PoolQuote| (p.collection.clone(), p.quote_price.u128()), - "sell_to_pool_quotes", - "sell_to_pool_quotes__collection_sell_price", - ), - }; - IndexedMap::new("sell_to_pool_quotes", indexes) -} - -/// NftDepositKey is comprised of the pool id and the token id -pub type NftDepositKey = (u64, String); - -/// Nft deposits are used to track the NFTs that have been deposited into a pool -pub const NFT_DEPOSITS: Map = Map::new("nft_deposits"); diff --git a/contracts/infinity-swap/src/swap_processor.rs b/contracts/infinity-swap/src/swap_processor.rs deleted file mode 100644 index 9164945..0000000 --- a/contracts/infinity-swap/src/swap_processor.rs +++ /dev/null @@ -1,735 +0,0 @@ -use crate::error::ContractError; -use crate::helpers::{get_nft_deposit, transfer_nft, transfer_token, verify_nft_deposit}; -use crate::msg::{NftSwap, PoolNftSwap, SwapParams, TransactionType}; -use crate::state::{buy_from_pool_quotes, pools, sell_to_pool_quotes, Pool, PoolQuote, PoolType}; - -use core::cmp::Ordering; -use cosmwasm_schema::cw_serde; -use cosmwasm_std::{attr, coin, Addr, Decimal, Event, Order, StdResult, Storage, Uint128}; -use sg1::fair_burn; -use sg721::RoyaltyInfoResponse; -use sg_std::{Response, NATIVE_DENOM}; -use std::collections::{BTreeMap, BTreeSet}; - -/// A struct for tracking in memory pools that are involved in swaps -#[derive(Debug)] -pub struct PoolQueueItem { - /// The pool object to handle a swap - pub pool: Pool, - /// The price at which to perform the swap - pub quote_price: Uint128, - /// Used to indicate whether the pool can continue to process swaps - pub usable: bool, - /// Number of swaps processed - pub num_swaps: u32, -} - -impl PoolQueueItem { - fn needs_saving(&self) -> bool { - self.num_swaps > 0 - } -} - -impl Ord for PoolQueueItem { - fn cmp(&self, other: &Self) -> Ordering { - (self.quote_price, self.pool.id).cmp(&(other.quote_price, other.pool.id)) - } -} - -impl PartialOrd for PoolQueueItem { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } -} - -impl PartialEq for PoolQueueItem { - fn eq(&self, other: &Self) -> bool { - (self.quote_price, self.pool.id) == (other.quote_price, other.pool.id) - } -} - -impl Eq for PoolQueueItem {} - -/// A token payment that needs to be executed at the end of a transaction -#[cw_serde] -pub struct TokenPayment { - pub amount: Uint128, - pub address: String, -} - -/// An NFT payment that needs to be executed at the end of a transaction -#[cw_serde] -pub struct NftPayment { - pub nft_token_id: String, - pub address: String, -} - -/// A summary of an individual swap -#[cw_serde] -pub struct Swap { - pub pool_id: u64, - pub transaction_type: TransactionType, - pub spot_price: Uint128, - pub network_fee: Uint128, - pub nft_payment: NftPayment, - pub finder_payment: Option, - pub royalty_payment: Option, - pub seller_payment: Option, -} - -impl From<&Swap> for Event { - fn from(val: &Swap) -> Self { - let mut attributes = vec![ - attr("pool_id", val.pool_id.to_string()), - attr("transaction_type", val.transaction_type.to_string()), - attr("spot_price", val.spot_price.to_string()), - attr("network_fee", val.network_fee.to_string()), - ]; - attributes.extend([ - attr("nft_payment_address", val.nft_payment.address.to_string()), - attr( - "nft_payment_token_id", - val.nft_payment.nft_token_id.to_string(), - ), - ]); - if val.finder_payment.is_some() { - let finder_payment = val.finder_payment.as_ref().unwrap(); - attributes.extend([ - attr("finder_payment_address", finder_payment.address.to_string()), - attr("finder_payment_amount", finder_payment.amount.to_string()), - ]); - } - if val.royalty_payment.is_some() { - let royalty_payment = val.royalty_payment.as_ref().unwrap(); - attributes.extend([ - attr( - "royalty_payment_address", - royalty_payment.address.to_string(), - ), - attr("royalty_payment_amount", royalty_payment.amount.to_string()), - ]); - } - if val.seller_payment.is_some() { - let seller_payment = val.seller_payment.as_ref().unwrap(); - attributes.extend([ - attr("seller_payment_address", seller_payment.address.to_string()), - attr("seller_payment_amount", seller_payment.amount.to_string()), - ]); - } - Event::new("swap").add_attributes(attributes) - } -} - -type IterResults = StdResult<(u64, PoolQuote)>; - -/// A struct for managing a series of swaps -pub struct SwapProcessor<'a> { - /// The type of transaction (buy or sell) - tx_type: TransactionType, - /// The address of this contract - contract: Addr, - /// The address of the NFT collection - collection: Addr, - /// The sender address - sender: Addr, - /// The amount of tokens sent to the contract by the end user - remaining_balance: Uint128, - /// The address that will receive assets on the side of the end user - seller_recipient: Addr, - /// The trading fee percentage to be burned - trading_fee_percent: Decimal, - /// The minimum quote price to be handled by the contract - min_quote: Uint128, - /// The royalty info for the NFT collection - royalty: Option, - /// The address of the finder of the transaction - finder: Option, - /// The address to receive developer burn fees - developer: Option, - /// A set of in memory pools that are involved in the transaction - pool_queue: BTreeSet, - /// The latest pool that was retrieved - latest: Option, - /// Skip next pool load to improve efficiency - skip_next_pool_load: bool, - /// An iterator for retrieving sorted pool quotes - pool_quote_iter: Option + 'a>>, - /// A set of in memory pools that should be saved at the end of the transaction - pub pools_to_save: BTreeMap, - /// A list of swaps that have been processed - pub swaps: Vec, -} - -impl<'a> SwapProcessor<'a> { - /// Creates a new SwapProcessor object - pub fn new( - tx_type: TransactionType, - contract: Addr, - collection: Addr, - sender: Addr, - remaining_balance: Uint128, - seller_recipient: Addr, - trading_fee_percent: Decimal, - min_quote: Uint128, - royalty: Option, - finder: Option, - developer: Option, - ) -> Self { - Self { - tx_type, - contract, - collection, - sender, - remaining_balance, - seller_recipient, - trading_fee_percent, - min_quote, - royalty, - finder, - developer, - pool_queue: BTreeSet::new(), - pools_to_save: BTreeMap::new(), - latest: None, - skip_next_pool_load: false, - pool_quote_iter: None, - swaps: vec![], - } - } - - /// Create an individual swap object - fn create_swap(&mut self, pool: &Pool, payment_amount: Uint128, nft_token_id: String) -> Swap { - // Subtract from received amount in the case of a buy - if self.tx_type == TransactionType::UserSubmitsTokens { - self.remaining_balance -= payment_amount; - } - - // Calculate burn fee - let network_fee = payment_amount * self.trading_fee_percent / Uint128::from(100u128); - - // Calculate seller payment (mutable) - let mut seller_amount = payment_amount - network_fee; - - // Calculate finder payment, deduct from seller payment - let mut finder_payment = None; - if self.finder.is_some() && !pool.finders_fee_percent.is_zero() { - let finder_amount = payment_amount * pool.finders_fee_percent / Uint128::from(100u128); - if !finder_amount.is_zero() { - seller_amount -= finder_amount; - finder_payment = Some(TokenPayment { - amount: finder_amount, - address: self.finder.as_ref().unwrap().to_string(), - }); - } - } - - // Calculate royalty payment, deduct from seller payment - let mut royalty_payment = None; - if let Some(_royalty) = &self.royalty { - let royalty_amount = payment_amount * _royalty.share; - if !royalty_amount.is_zero() { - seller_amount -= royalty_amount; - royalty_payment = Some(TokenPayment { - amount: royalty_amount, - address: _royalty.payment_address.clone(), - }); - } - } - - // Set the addresses that will receive the NFT and token payment - let (nft_recipient, token_recipient) = match &self.tx_type { - TransactionType::UserSubmitsTokens => { - (self.seller_recipient.clone(), pool.get_recipient()) - } - TransactionType::UserSubmitsNfts => { - (pool.get_recipient(), self.seller_recipient.clone()) - } - }; - - Swap { - pool_id: pool.id, - transaction_type: self.tx_type.clone(), - spot_price: payment_amount, - network_fee, - nft_payment: NftPayment { - nft_token_id, - address: nft_recipient.to_string(), - }, - finder_payment, - royalty_payment, - seller_payment: Some(TokenPayment { - amount: seller_amount, - address: token_recipient.to_string(), - }), - } - } - - /// Process a swap - fn process_swap( - &mut self, - pool_queue_item: PoolQueueItem, - nft_swap: NftSwap, - robust: bool, - ) -> Result<(PoolQueueItem, bool), ContractError> { - let mut pool_queue_item = pool_queue_item; - - // Manage pool assets for swap - let result = match self.tx_type { - TransactionType::UserSubmitsNfts => pool_queue_item - .pool - .sell_nft_to_pool(&nft_swap, pool_queue_item.quote_price), - TransactionType::UserSubmitsTokens => pool_queue_item - .pool - .buy_nft_from_pool(&nft_swap, pool_queue_item.quote_price), - }; - match result { - Ok(_) => {} - Err(ContractError::SwapError(_err)) => { - if robust { - pool_queue_item.usable = false; - return Ok((pool_queue_item, false)); - } else { - // otherwise throw the error - return Err(ContractError::SwapError(_err)); - } - } - Err(err) => return Err(err), - }; - - // Set the resulting swap with fees included - let mut swap = self.create_swap( - &pool_queue_item.pool, - pool_queue_item.quote_price, - nft_swap.nft_token_id, - ); - - // Reinvest tokens or NFTs if applicable - if pool_queue_item.pool.pool_type == PoolType::Trade { - if self.tx_type == TransactionType::UserSubmitsTokens - && pool_queue_item.pool.reinvest_tokens - { - let reinvest_amount = swap.seller_payment.unwrap().amount; - swap.seller_payment = None; - pool_queue_item.pool.deposit_tokens(reinvest_amount)?; - } else if self.tx_type == TransactionType::UserSubmitsNfts - && pool_queue_item.pool.reinvest_nfts - { - swap.nft_payment.address = self.contract.to_string(); - pool_queue_item - .pool - .deposit_nfts(&vec![swap.nft_payment.nft_token_id.clone()])?; - } - } - self.swaps.push(swap); - - // Pool needs saving past this point - pool_queue_item.num_swaps += 1; - - // Update the pool spot price - let result = pool_queue_item.pool.update_spot_price(&self.tx_type); - if result.is_err() { - pool_queue_item.usable = false; - return Ok((pool_queue_item, true)); - } - let get_next_pool_quote = match self.tx_type { - TransactionType::UserSubmitsNfts => { - pool_queue_item.pool.get_sell_to_pool_quote(self.min_quote) - } - TransactionType::UserSubmitsTokens => { - pool_queue_item.pool.get_buy_from_pool_quote(self.min_quote) - } - }; - if get_next_pool_quote.is_err() { - pool_queue_item.usable = false; - return Ok((pool_queue_item, true)); - } - let next_pool_quote = get_next_pool_quote.unwrap(); - if next_pool_quote.is_none() { - pool_queue_item.usable = false; - return Ok((pool_queue_item, true)); - } - pool_queue_item.quote_price = next_pool_quote.unwrap(); - pool_queue_item.usable = true; - Ok((pool_queue_item, true)) - } - - /// Push asset transfer messages to the response - fn commit_messages(&self, response: &mut Response) -> Result<(), ContractError> { - if self.swaps.is_empty() { - return Err(ContractError::SwapError("no swaps found".to_string())); - } - - let mut total_network_fee = Uint128::zero(); - let mut token_payments: BTreeMap<&str, Uint128> = BTreeMap::new(); - - // Insert refund amount if there is a remainder - if !self.remaining_balance.is_zero() { - token_payments.insert(self.sender.as_str(), self.remaining_balance); - } - - // Iterate over swaps and reduce token payments that need to be made - for swap in self.swaps.iter() { - // Aggregate network fees - total_network_fee += swap.network_fee; - - // Push transfer NFT messages - transfer_nft( - &swap.nft_payment.nft_token_id, - &swap.nft_payment.address, - self.collection.as_ref(), - response, - )?; - - // Track finder payments - if let Some(_finder_payment) = &swap.finder_payment { - let payment = token_payments - .entry(&_finder_payment.address) - .or_insert(Uint128::zero()); - *payment += _finder_payment.amount; - } - - // Track royalty payments - if let Some(_royalty_payment) = &swap.royalty_payment { - let payment = token_payments - .entry(&_royalty_payment.address) - .or_insert(Uint128::zero()); - *payment += _royalty_payment.amount; - } - - // Track seller payments - if let Some(_seller_payment) = &swap.seller_payment { - let payment = token_payments - .entry(&_seller_payment.address) - .or_insert(Uint128::zero()); - *payment += _seller_payment.amount; - } - } - - fair_burn(total_network_fee.u128(), self.developer.clone(), response); - - // Push transfer token messages - for token_payment in token_payments { - transfer_token( - coin(token_payment.1.u128(), NATIVE_DENOM), - token_payment.0, - response, - )?; - } - - Ok(()) - } - - /// Move pools from pool_queue to pools_to_save - fn move_pools(&mut self) { - let mut pool_queue_item = self.pool_queue.pop_first(); - while let Some(_pool_queue_item) = pool_queue_item { - if _pool_queue_item.needs_saving() { - self.pools_to_save - .insert(_pool_queue_item.pool.id, _pool_queue_item.pool); - } - pool_queue_item = self.pool_queue.pop_first(); - } - } - - /// Load the pool with the next best price - fn load_next_pool( - &mut self, - storage: &'a dyn Storage, - ) -> Result, ContractError> { - // Init iter - if self.pool_quote_iter.is_none() { - self.pool_quote_iter = Some(match &self.tx_type { - TransactionType::UserSubmitsNfts => sell_to_pool_quotes() - .idx - .collection_sell_price - .sub_prefix(self.collection.clone()) - .range(storage, None, None, Order::Descending), - TransactionType::UserSubmitsTokens => buy_from_pool_quotes() - .idx - .collection_buy_price - .sub_prefix(self.collection.clone()) - .range(storage, None, None, Order::Ascending), - }) - } - - // If the pool is empty, or the front of the pool is the latest fetched, load the next pool - // Note: if the front of the pool is not the latest fetched, that means the next pool won't have the best price - if self.pool_queue.len() < 2 || !self.skip_next_pool_load { - // Try and fetch next pool quote - let next_pool_quote = self.pool_quote_iter.as_mut().unwrap().next(); - - // If next pool quote exists fetch and set PoolQueueItem - if let Some(_next_pool_quote) = next_pool_quote { - let (pool_id, pool_quote) = _next_pool_quote?; - - let pool = pools().load(storage, pool_id).map_err(|_| { - ContractError::PoolNotFound(format!("pool {} not found", pool_id)) - })?; - - self.pool_queue.insert(PoolQueueItem { - pool, - quote_price: pool_quote.quote_price, - usable: true, - num_swaps: 0, - }); - self.latest = Some(pool_id); - } - } - - let loaded_pool_queue_item = match &self.tx_type { - // For sells, the last pool will have the highest quote - TransactionType::UserSubmitsNfts => self.pool_queue.pop_last(), - // For buys, the first pool will have the lowest quote - TransactionType::UserSubmitsTokens => self.pool_queue.pop_first(), - }; - - if let Some(_loaded_pool_queue_item) = &loaded_pool_queue_item { - self.skip_next_pool_load = _loaded_pool_queue_item.pool.id != self.latest.unwrap(); - } - - Ok(loaded_pool_queue_item) - } - - pub fn finalize_transaction(&mut self, response: &mut Response) -> Result<(), ContractError> { - self.commit_messages(response)?; - self.move_pools(); - - Ok(()) - } - - /// Swap NFTs to tokens directly with the specified pool - pub fn direct_swap_nfts_for_tokens( - &mut self, - pool: Pool, - nfts_to_swap: Vec, - swap_params: SwapParams, - ) -> Result<(), ContractError> { - let quote_price = pool.get_sell_to_pool_quote(self.min_quote)?; - if quote_price.is_none() { - return Err(ContractError::NoQuoteForPool(format!( - "pool {} cannot offer quote", - pool.id - ))); - } - - let mut pool_queue_item = PoolQueueItem { - pool, - quote_price: quote_price.unwrap(), - usable: true, - num_swaps: 0, - }; - let mut success: bool; - - for nft_swap in nfts_to_swap { - (pool_queue_item, success) = - self.process_swap(pool_queue_item, nft_swap, swap_params.robust)?; - - // If the swap failed, stop processing swaps - if !success { - break; - } - } - if pool_queue_item.needs_saving() { - self.pools_to_save - .insert(pool_queue_item.pool.id, pool_queue_item.pool); - } - - Ok(()) - } - - /// Swap NFTs to tokens, using the best priced pools - pub fn swap_nfts_for_tokens( - &mut self, - storage: &'a dyn Storage, - nfts_to_swap: Vec, - swap_params: SwapParams, - ) -> Result<(), ContractError> { - for nft_swap in nfts_to_swap { - // Load best priced pool - let pool_queue_item_option = self.load_next_pool(storage)?; - // No pools found, so return empty - if pool_queue_item_option.is_none() { - return Ok(()); - } - let (pool_queue_item, success) = self.process_swap( - pool_queue_item_option.unwrap(), - nft_swap, - swap_params.robust, - )?; - - // If the swap failed, stop processing swaps - if !success { - break; - } - if pool_queue_item.usable { - // If the swap was a success, and the quote price was updated, save into pool_queue - self.pool_queue.insert(pool_queue_item); - } else { - // If the swap was a success, but the quote price was not updated, - // withdraw from circulation by inserting into pools_to_save - self.pools_to_save - .insert(pool_queue_item.pool.id, pool_queue_item.pool); - } - } - Ok(()) - } - - /// Swap tokens to specific NFTs directly with the specified pool - pub fn swap_tokens_for_specific_nfts( - &mut self, - storage: &'a dyn Storage, - nfts_to_swap_for: Vec, - swap_params: SwapParams, - ) -> Result<(), ContractError> { - // Create a pool_queue_item map for tracking swap pools - let mut pool_queue_item_map: BTreeMap = BTreeMap::new(); - - for pool_nfts in nfts_to_swap_for { - let mut pool_queue_item = - if let Some(_pool_queue_item) = pool_queue_item_map.remove(&pool_nfts.pool_id) { - _pool_queue_item - } else { - let pool_option = pools().may_load(storage, pool_nfts.pool_id)?; - // If pool is not found, return error - if pool_option.is_none() { - return Err(ContractError::PoolNotFound(format!( - "pool {} not found", - pool_nfts.pool_id - ))); - } - // Create PoolQueueItem and insert into pool_queue_item_map - let pool = pool_option.unwrap(); - - if pool.collection != self.collection { - return Err(ContractError::InvalidPool( - "pool does not belong to this collection".to_string(), - )); - } - - let quote_price = pool.get_buy_from_pool_quote(self.min_quote)?; - if quote_price.is_none() { - if swap_params.robust { - continue; - } else { - return Err(ContractError::NoQuoteForPool(format!( - "pool {} cannot offer quote", - pool.id - ))); - } - } - PoolQueueItem { - pool, - quote_price: quote_price.unwrap(), - usable: true, - num_swaps: 0, - } - }; - - // Iterate over all NFTs selected for the given pool - for nft_swap in pool_nfts.nft_swaps { - if !pool_queue_item.usable { - if swap_params.robust { - break; - } else { - return Err(ContractError::SwapError( - "unable to process swap".to_string(), - )); - } - } - - // Check if specified NFT is deposited into pool - let pool_owns_nft = - verify_nft_deposit(storage, pool_nfts.pool_id, &nft_swap.nft_token_id); - if !pool_owns_nft { - if swap_params.robust { - break; - } else { - return Err(ContractError::SwapError(format!( - "pool {} does not own NFT {}", - pool_queue_item.pool.id, nft_swap.nft_token_id - ))); - } - } - - let (_pool_queue_item, success) = - self.process_swap(pool_queue_item, nft_swap, swap_params.robust)?; - pool_queue_item = _pool_queue_item; - - // If the swap failed, stop processing swaps - if !success { - if swap_params.robust { - break; - } else { - return Err(ContractError::SwapError( - "unable to process swap".to_string(), - )); - } - } - } - - pool_queue_item_map.insert(pool_queue_item.pool.id, pool_queue_item); - } - - // Move all pools that need saving from pool_queue_item_map into pools_to_save - for (_, pool_queue_item) in pool_queue_item_map.into_iter() { - if pool_queue_item.needs_saving() { - self.pools_to_save - .insert(pool_queue_item.pool.id, pool_queue_item.pool); - } - } - Ok(()) - } - - /// Swap tokens to any NFTs, using the best priced pools - pub fn swap_tokens_for_any_nfts( - &mut self, - storage: &'a dyn Storage, - min_expected_token_input: Vec, - swap_params: SwapParams, - ) -> Result<(), ContractError> { - for token_amount in min_expected_token_input { - // Load best priced pool - let pool_queue_item_option = self.load_next_pool(storage)?; - // No pools found, so return empty; - if pool_queue_item_option.is_none() { - return Ok(()); - } - let pool_queue_item = pool_queue_item_option.unwrap(); - { - // Grab first NFT from the pool - let nft_token_id = - get_nft_deposit(storage, pool_queue_item.pool.id, pool_queue_item.num_swaps)?; - if nft_token_id.is_none() { - return Err(ContractError::SwapError(format!( - "pool {} does not own any NFTs", - pool_queue_item.pool.id - ))); - } - - let (pool_queue_item, success) = self.process_swap( - pool_queue_item, - NftSwap { - nft_token_id: nft_token_id.unwrap(), - token_amount, - }, - swap_params.robust, - )?; - - // If the swap failed, stop processing swaps - if !success { - break; - } - - if pool_queue_item.usable { - // If the swap was a success, and the quote price was updated, save into pool_queue - self.pool_queue.insert(pool_queue_item); - } else { - // If the swap was a success, but the quote price was not updated, - // withdraw from circulation by inserting into pools_to_save - self.pools_to_save - .insert(pool_queue_item.pool.id, pool_queue_item.pool); - } - } - } - Ok(()) - } -} diff --git a/packages/infinity-shared/Cargo.toml b/packages/infinity-shared/Cargo.toml index 5af420d..003b4b8 100644 --- a/packages/infinity-shared/Cargo.toml +++ b/packages/infinity-shared/Cargo.toml @@ -21,7 +21,6 @@ backtraces = ["cosmwasm-std/backtraces"] library = [] [dependencies] -infinity-swap = { workspace = true } cosmwasm-std = { workspace = true } cosmwasm-schema = { workspace = true } cosmwasm-storage = { workspace = true } diff --git a/packages/infinity-shared/src/error.rs b/packages/infinity-shared/src/error.rs new file mode 100644 index 0000000..34f830b --- /dev/null +++ b/packages/infinity-shared/src/error.rs @@ -0,0 +1,24 @@ +use cosmwasm_std::StdError; +use cw_utils::PaymentError; +use thiserror::Error; + +#[derive(Error, Debug, PartialEq)] +pub enum InfinityError { + #[error("{0}")] + Std(#[from] StdError), + + #[error("{0}")] + PaymentError(#[from] PaymentError), + + #[error("Not NFT owner: {0} is not the owner of the NFT")] + NotNftOwner(String), + + #[error("Invalid input: {0}")] + InvalidInput(String), + + #[error("Insufficient funds: received {received}, expected {expected}")] + InsufficientFunds { received: String, expected: String }, + + #[error("Deadline passed")] + DeadlinePassed, +} diff --git a/packages/infinity-shared/src/lib.rs b/packages/infinity-shared/src/lib.rs index 48cc871..5a195c6 100644 --- a/packages/infinity-shared/src/lib.rs +++ b/packages/infinity-shared/src/lib.rs @@ -1,2 +1,6 @@ pub mod interface; pub mod shared; + +mod error; + +pub use crate::error::InfinityError; diff --git a/packages/infinity-shared/src/shared.rs b/packages/infinity-shared/src/shared.rs index 057d110..b66eb58 100644 --- a/packages/infinity-shared/src/shared.rs +++ b/packages/infinity-shared/src/shared.rs @@ -1,8 +1,19 @@ -use cosmwasm_std::{Addr, QuerierWrapper, StdResult}; +use crate::interface::NftOrder; +use crate::InfinityError; + +use cosmwasm_std::{ + coin, ensure, to_binary, Addr, Api, Coin, Empty, QuerierWrapper, StdResult, Uint128, WasmMsg, +}; +use cw721::{ApprovalResponse, Cw721ExecuteMsg, OwnerOfResponse}; +use cw721_base::helpers::Cw721Contract; use sg_marketplace::{ msg::{ParamsResponse, QueryMsg as MarketplaceQueryMsg}, state::SudoParams, }; +use sg_std::SubMsg; +use std::collections::BTreeSet; +use std::error::Error; +use std::marker::PhantomData; /// Load the marketplace params pub fn load_marketplace_params( @@ -13,3 +24,19 @@ pub fn load_marketplace_params( querier.query_wasm_smart(marketplace_addr, &MarketplaceQueryMsg::Params {})?; Ok(marketplace_params.params) } + +pub fn only_nft_owner( + querier: &QuerierWrapper, + api: &dyn Api, + sender: &Addr, + collection: &Addr, + token_id: &str, +) -> Result { + let response = Cw721Contract::(collection.clone(), PhantomData, PhantomData) + .owner_of(&querier, token_id, false)?; + + let owner = api.addr_validate(&response.owner)?; + ensure!(&owner == sender, InfinityError::NotNftOwner(owner.to_string())); + + Ok(owner) +} diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000..68365be --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,7 @@ +# https://rust-lang.github.io/rustfmt +format_code_in_doc_comments = true # nightly +group_imports = "StdExternalCrate" # nightly +imports_granularity = "Crate" # nightly +match_block_trailing_comma = true +max_width = 100 +use_small_heuristics = "off" diff --git a/test/e2e/Cargo.toml b/test/e2e/Cargo.toml deleted file mode 100644 index a824785..0000000 --- a/test/e2e/Cargo.toml +++ /dev/null @@ -1,30 +0,0 @@ -[package] -name = "e2e-tests" -version = { workspace = true } -edition = { workspace = true } -repository = { workspace = true } -license = { workspace = true } - -[target.'cfg(not(target_arch = "wasm32"))'.dependencies] -infinity-swap = { workspace = true } -sg-marketplace = { workspace = true } -cosmwasm-std = { workspace = true } -cw-utils = { workspace = true } -cw721-base = { workspace = true } -cw721 = { workspace = true } -sg-std = { workspace = true } -sg2 = { workspace = true } -sg721-base = { workspace = true } -sg721 = { workspace = true } -base-minter = { workspace = true } -base-factory = { workspace = true } -itertools = { workspace = true } -cosm-orc = { workspace = true } -cosm-tome = { workspace = true } -assert_matches = { workspace = true } -serde_json = { workspace = true } -env_logger = { workspace = true } -test-context = { workspace = true } -once_cell = { workspace = true } -serde = { workspace = true } -rand = { workspace = true } \ No newline at end of file diff --git a/test/e2e/configs/cosm-orc.yaml b/test/e2e/configs/cosm-orc.yaml deleted file mode 100644 index 4b18ec1..0000000 --- a/test/e2e/configs/cosm-orc.yaml +++ /dev/null @@ -1,7 +0,0 @@ -chain_cfg: - denom: "ustars" - prefix: "stars" - chain_id: "testing" - grpc_endpoint: "http://localhost:9090/" - gas_prices: 0.1 - gas_adjustment: 1.5 diff --git a/test/e2e/configs/test_accounts.json b/test/e2e/configs/test_accounts.json deleted file mode 100644 index b9a1b6c..0000000 --- a/test/e2e/configs/test_accounts.json +++ /dev/null @@ -1,27 +0,0 @@ -[ - { - "name": "user1", - "address": "stars16z43tjws3vw06ej9v7nrszu0ldsmn0eyjnjpu8", - "mnemonic": "game cook seven draw girl special once poem rhythm seven winner praise demise trick access style bracket later tunnel slush lab false game park" - }, - { - "name": "user2", - "address": "stars1t08es9sxvjt3rmmkf426ks4ce528m0u84lyv92", - "mnemonic": "priority ozone forget detect main sheriff delay armor noble ability job front lawsuit never tooth soup wire nominee leopard country cherry ostrich language actress" - }, - { - "name": "user3", - "address": "stars1x0nystpdqr9dtcy02wh4tcmhjxjlnk009ngcs8", - "mnemonic": "wife seminar album post drive garbage ceiling robot skirt sustain notice kite just discover noble nominee one escape clean heavy general segment narrow whisper" - }, - { - "name": "user4", - "address": "stars1v3fwgyw9kgtm08dpmfrlergxzxazwqa3qqxvd7", - "mnemonic": "deposit piece interest because warm gadget pen point settle own all benefit point august garden task broom velvet noble true next impose hood traffic" - }, - { - "name": "user5", - "address": "stars1r98zsyt50k7yk86pf28xhdtf5yedkf7wm7nu0n", - "mnemonic": "follow motion improve audit hazard business decide long convince frame quality rug boil merry luxury robust whip soldier save ritual print screen border board" - } -] \ No newline at end of file diff --git a/test/e2e/src/helpers/chain.rs b/test/e2e/src/helpers/chain.rs deleted file mode 100644 index 3d9c08d..0000000 --- a/test/e2e/src/helpers/chain.rs +++ /dev/null @@ -1,149 +0,0 @@ -use cosm_orc::orchestrator::{CosmosgRPC, Key, SigningKey}; -use cosm_orc::{config::cfg::Config, orchestrator::cosm_orc::CosmOrc}; -use once_cell::sync::OnceCell; -use rand::Rng; -use serde::{Deserialize, Serialize}; -use serde_json::Value; -use std::fs; -use std::path::Path; -use std::time::Duration; -use std::{env, vec}; -use test_context::TestContext; - -use crate::helpers::constants::SG721_NAME; - -use super::instantiate::{ - instantiate_base_factory, instantiate_infinity_swap, instantiate_marketplace, -}; - -static CONFIG: OnceCell = OnceCell::new(); - -#[derive(Clone, Debug)] -pub struct Cfg { - pub orc_cfg: Config, - pub users: Vec, - pub gas_report_dir: String, -} - -#[derive(Clone, Debug)] -pub struct SigningAccount { - pub account: Account, - pub key: SigningKey, -} - -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct Account { - pub name: String, - pub address: String, - pub mnemonic: String, -} - -// NOTE: we have to run the integration tests in one thread right now. -// We get `account sequence mismatch` CosmosSDK errors when we run in parallel. -// If we want to parallelize them we could either serialize the `account.sequence` per key, -// or use a different key per test. - -#[derive(Clone, Debug)] -pub struct Chain { - pub cfg: Cfg, - pub orc: CosmOrc, -} - -impl TestContext for Chain { - fn setup() -> Self { - let cfg = CONFIG.get_or_init(global_setup).clone(); - let orc = CosmOrc::new(cfg.orc_cfg.clone(), true).unwrap(); - Self { cfg, orc } - } - - fn teardown(self) { - let cfg = CONFIG.get().unwrap(); - save_gas_report(&self.orc, &cfg.gas_report_dir); - } -} - -// global_setup() runs once before all of the tests: -// - loads cosm orc / test account config files -// - stores contracts on chain for all tests to reuse -fn global_setup() -> Cfg { - env_logger::init(); - - let config = env::var("CONFIG").expect("missing yaml CONFIG env var"); - let gas_report_dir = env::var("GAS_OUT_DIR").unwrap_or_else(|_| "gas_reports".to_string()); - - let mut cfg = Config::from_yaml(&config).unwrap(); - let mut orc = CosmOrc::new(cfg.clone(), true).unwrap(); - let accounts = test_accounts(); - - // Poll for first block to make sure the node is up: - orc.poll_for_n_blocks(1, Duration::from_millis(20_000), true) - .unwrap(); - - let skip_storage = env::var("SKIP_CONTRACT_STORE").unwrap_or_else(|_| "false".to_string()); - if !skip_storage.parse::().unwrap() { - orc.store_contracts("../../artifacts", &accounts[0].key, None) - .unwrap(); - - save_gas_report(&orc, &gas_report_dir); - - let sg721_code_id = orc.contract_map.code_id(SG721_NAME).unwrap(); - - prep_base_contracts(&mut orc, &accounts[0], &cfg.chain_cfg.denom, sg721_code_id); - - // persist stored code_ids in CONFIG, so we can reuse for all tests - cfg.contract_deploy_info = orc.contract_map.deploy_info().clone(); - - // print contract map - println!("{:#?}", cfg.contract_deploy_info); - } - - Cfg { - orc_cfg: cfg, - users: accounts, - gas_report_dir, - } -} - -fn test_accounts() -> Vec { - let bytes = fs::read("configs/test_accounts.json").unwrap(); - let accounts: Vec = serde_json::from_slice(&bytes).unwrap(); - - accounts - .into_iter() - .map(|a| SigningAccount { - account: a.clone(), - key: SigningKey { - name: a.name, - key: Key::Mnemonic(a.mnemonic), - }, - }) - .collect() -} - -fn save_gas_report(orc: &CosmOrc, gas_report_dir: &str) { - let report = orc - .gas_profiler_report() - .expect("error fetching profile reports"); - - let j: Value = serde_json::to_value(report).unwrap(); - - let p = Path::new(gas_report_dir); - if !p.exists() { - fs::create_dir(p).unwrap(); - } - - let mut rng = rand::thread_rng(); - let file_name = format!("test-{}.json", rng.gen::()); - fs::write(p.join(file_name), j.to_string()).unwrap(); -} - -fn prep_base_contracts( - orc: &mut CosmOrc, - creator: &SigningAccount, - denom: &str, - sg721_code_id: u64, -) { - instantiate_base_factory(orc, creator, denom, vec![sg721_code_id]).unwrap(); - instantiate_marketplace(orc, creator).unwrap(); - instantiate_infinity_swap(orc, denom, creator).unwrap(); -} diff --git a/test/e2e/src/helpers/constants.rs b/test/e2e/src/helpers/constants.rs deleted file mode 100644 index 68dcda9..0000000 --- a/test/e2e/src/helpers/constants.rs +++ /dev/null @@ -1,12 +0,0 @@ -pub const SG721_NAME: &str = "sg721_base"; -pub const BASE_MINTER_NAME: &str = "base_minter"; -pub const BASE_FACTORY_NAME: &str = "base_factory"; -pub const VENDING_MINTER_NAME: &str = "vending_minter"; -pub const VENDING_FACTORY_NAME: &str = "vending_factory"; -pub const MARKETPLACE_NAME: &str = "sg_marketplace"; -pub const INFINITY_SWAP_NAME: &str = "infinity_swap"; - -pub const MAX_TOKENS: u32 = 10_000; -pub const CREATION_FEE: u128 = 1_200_000; -pub const LISTING_FEE: u128 = 500_000; -pub const MINT_PRICE: u128 = 600_000; diff --git a/test/e2e/src/helpers/fixtures.rs b/test/e2e/src/helpers/fixtures.rs deleted file mode 100644 index ae2c48d..0000000 --- a/test/e2e/src/helpers/fixtures.rs +++ /dev/null @@ -1,143 +0,0 @@ -use cosmwasm_std::Uint128; -use infinity_swap::msg::ExecuteMsg; -use infinity_swap::state::BondingCurve; - -pub fn get_pool_fixtures( - collection: &str, - asset_account: &Option, - finders_fee_bps: u64, - swap_fee_bps: u64, -) -> Vec { - vec![ - ExecuteMsg::CreateTokenPool { - collection: collection.to_string(), - asset_recipient: asset_account.clone(), - bonding_curve: BondingCurve::Linear, - spot_price: Uint128::from(100u64), - delta: Uint128::from(10u64), - finders_fee_bps, - }, - ExecuteMsg::CreateTokenPool { - collection: collection.to_string(), - asset_recipient: asset_account.clone(), - bonding_curve: BondingCurve::Exponential, - spot_price: Uint128::from(200u64), - delta: Uint128::from(200u64), - finders_fee_bps, - }, - ExecuteMsg::CreateNftPool { - collection: collection.to_string(), - asset_recipient: asset_account.clone(), - bonding_curve: BondingCurve::Linear, - spot_price: Uint128::from(300u64), - delta: Uint128::from(30u64), - finders_fee_bps, - }, - ExecuteMsg::CreateNftPool { - collection: collection.to_string(), - asset_recipient: asset_account.clone(), - bonding_curve: BondingCurve::Exponential, - spot_price: Uint128::from(400u64), - delta: Uint128::from(400u64), - finders_fee_bps, - }, - ExecuteMsg::CreateTradePool { - collection: collection.to_string(), - asset_recipient: asset_account.clone(), - bonding_curve: BondingCurve::Linear, - spot_price: Uint128::from(500u64), - delta: Uint128::from(50u64), - finders_fee_bps, - swap_fee_bps, - reinvest_nfts: true, - reinvest_tokens: true, - }, - ExecuteMsg::CreateTradePool { - collection: collection.to_string(), - asset_recipient: asset_account.clone(), - bonding_curve: BondingCurve::Exponential, - spot_price: Uint128::from(600u64), - delta: Uint128::from(600u64), - finders_fee_bps, - swap_fee_bps, - reinvest_nfts: true, - reinvest_tokens: true, - }, - ExecuteMsg::CreateTradePool { - collection: collection.to_string(), - asset_recipient: asset_account.clone(), - bonding_curve: BondingCurve::ConstantProduct, - spot_price: Uint128::from(0u64), - delta: Uint128::from(0u64), - finders_fee_bps, - swap_fee_bps, - reinvest_nfts: true, - reinvest_tokens: true, - }, - ExecuteMsg::CreateTokenPool { - collection: collection.to_string(), - asset_recipient: asset_account.clone(), - bonding_curve: BondingCurve::Linear, - spot_price: Uint128::from(800u64), - delta: Uint128::from(80u64), - finders_fee_bps, - }, - ExecuteMsg::CreateTokenPool { - collection: collection.to_string(), - asset_recipient: asset_account.clone(), - bonding_curve: BondingCurve::Exponential, - spot_price: Uint128::from(900u64), - delta: Uint128::from(900u64), - finders_fee_bps, - }, - ExecuteMsg::CreateNftPool { - collection: collection.to_string(), - asset_recipient: asset_account.clone(), - bonding_curve: BondingCurve::Linear, - spot_price: Uint128::from(1000u64), - delta: Uint128::from(100u64), - finders_fee_bps, - }, - ExecuteMsg::CreateNftPool { - collection: collection.to_string(), - asset_recipient: asset_account.clone(), - bonding_curve: BondingCurve::Exponential, - spot_price: Uint128::from(1100u64), - delta: Uint128::from(1100u64), - finders_fee_bps, - }, - ExecuteMsg::CreateTradePool { - collection: collection.to_string(), - asset_recipient: asset_account.clone(), - bonding_curve: BondingCurve::Linear, - spot_price: Uint128::from(1200u64), - delta: Uint128::from(120u64), - finders_fee_bps, - swap_fee_bps, - reinvest_nfts: false, - reinvest_tokens: false, - }, - ExecuteMsg::CreateTradePool { - collection: collection.to_string(), - asset_recipient: asset_account.clone(), - bonding_curve: BondingCurve::Exponential, - spot_price: Uint128::from(1300u64), - delta: Uint128::from(1300u64), - finders_fee_bps, - swap_fee_bps, - reinvest_nfts: false, - reinvest_tokens: false, - }, - ExecuteMsg::CreateTradePool { - collection: collection.to_string(), - asset_recipient: asset_account.clone(), - bonding_curve: BondingCurve::ConstantProduct, - spot_price: Uint128::from(0u64), - delta: Uint128::from(0u64), - finders_fee_bps, - swap_fee_bps, - reinvest_nfts: false, - reinvest_tokens: false, - }, - ] -} diff --git a/test/e2e/src/helpers/helper.rs b/test/e2e/src/helpers/helper.rs deleted file mode 100644 index e117d2e..0000000 --- a/test/e2e/src/helpers/helper.rs +++ /dev/null @@ -1,54 +0,0 @@ -use super::chain::Chain; -use cosm_orc::orchestrator::cosm_orc::{tokio_block, CosmOrc}; -use cosm_orc::orchestrator::SigningKey; -use cosm_orc::orchestrator::{Coin as OrcCoin, CosmosgRPC}; -use cosm_tome::chain::request::TxOptions; -use cosm_tome::modules::bank::model::SendRequest; -use cosmwasm_std::Timestamp; - -// gen_users will create `num_users` random SigningKeys -// and then transfer `init_balance` of funds to each of them. -pub fn gen_users(chain: &mut Chain, num_users: u32, init_balance: u128) -> Vec { - let prefix = &chain.cfg.orc_cfg.chain_cfg.prefix; - let denom = &chain.cfg.orc_cfg.chain_cfg.denom; - let from_user = &chain.cfg.users[1]; - - let mut users = vec![]; - for n in 0..num_users { - users.push(SigningKey::random_mnemonic(n.to_string())); - } - - let mut reqs = vec![]; - for user in &users { - reqs.push(SendRequest { - from: from_user.account.address.parse().unwrap(), - to: user.to_addr(prefix).unwrap(), - amounts: vec![OrcCoin { - amount: init_balance, - denom: denom.parse().unwrap(), - }], - }); - } - - tokio_block( - chain - .orc - .client - .bank_send_batch(reqs, &from_user.key, &TxOptions::default()), - ) - .unwrap(); - - users -} - -pub fn latest_block_time(orc: &CosmOrc) -> Timestamp { - let now = tokio_block(orc.client.tendermint_query_latest_block()) - .unwrap() - .block - .header - .unwrap() - .time - .unwrap(); - - Timestamp::from_seconds(now.seconds.try_into().unwrap()) -} diff --git a/test/e2e/src/helpers/instantiate.rs b/test/e2e/src/helpers/instantiate.rs deleted file mode 100644 index 3f498a2..0000000 --- a/test/e2e/src/helpers/instantiate.rs +++ /dev/null @@ -1,166 +0,0 @@ -use super::chain::SigningAccount; -use super::constants::{ - BASE_FACTORY_NAME, BASE_MINTER_NAME, CREATION_FEE, INFINITY_SWAP_NAME, LISTING_FEE, - MARKETPLACE_NAME, MINT_PRICE, SG721_NAME, -}; -use base_factory::msg::ExecuteMsg as BaseFactoryExecuteMsg; -use base_factory::msg::InstantiateMsg as BaseFactoryInstantiateMsg; -use base_factory::state::BaseMinterParams; -use cosm_orc::orchestrator::cosm_orc::CosmOrc; -use cosm_orc::orchestrator::error::ProcessError; -use cosm_orc::orchestrator::{ - Coin as OrcCoin, CosmosgRPC, ExecResponse, InstantiateResponse, SigningKey, -}; -use cosmwasm_std::{Coin, Empty, Uint128}; -use cw_utils::Duration; -use infinity_swap::msg::InstantiateMsg as PoolInstantiateMsg; -use sg2::msg::{CollectionParams, CreateMinterMsg}; -use sg721::CollectionInfo; -use sg_marketplace::msg::InstantiateMsg as MarketplaceInstantiateMsg; -use sg_marketplace::ExpiryRange; - -pub fn instantiate_base_factory( - orc: &mut CosmOrc, - user: &SigningAccount, - denom: &str, - allowed_sg721_code_ids: Vec, -) -> Result { - orc.instantiate( - BASE_FACTORY_NAME, - &format!("{}_inst", BASE_FACTORY_NAME), - &BaseFactoryInstantiateMsg { - params: BaseMinterParams { - code_id: orc.contract_map.code_id(BASE_MINTER_NAME).unwrap(), - creation_fee: Coin { - denom: denom.to_string(), - amount: Uint128::from(CREATION_FEE), - }, - min_mint_price: Coin { - denom: denom.to_string(), - amount: Uint128::from(MINT_PRICE), - }, - // Setting this to 100% because I think there is a bug in the base minter contract - mint_fee_bps: 10000, - max_trading_offset_secs: 0, - extension: None, - frozen: false, - allowed_sg721_code_ids, - }, - }, - &user.key, - Some(user.account.address.parse().unwrap()), - vec![], - ) -} - -pub fn instantiate_minter( - orc: &mut CosmOrc, - creator_addr: String, - signer: &SigningKey, - denom: &str, -) -> Result { - let init_minter_msg = BaseFactoryExecuteMsg::CreateMinter(CreateMinterMsg { - init_msg: Some(Empty {}), - collection_params: CollectionParams { - code_id: orc.contract_map.code_id(SG721_NAME).unwrap(), - name: "Collection".to_string(), - symbol: "SYM".to_string(), - info: CollectionInfo { - creator: creator_addr, - description: "Description".to_string(), - image: "https://example.com/image.png".to_string(), - start_trading_time: None, - external_link: None, - explicit_content: None, - royalty_info: None, - }, - }, - }); - - let res = orc - .execute( - BASE_FACTORY_NAME, - "base_factory_exec_minter_inst", - &init_minter_msg, - signer, - vec![OrcCoin { - amount: CREATION_FEE, - denom: denom.parse().unwrap(), - }], - ) - .unwrap(); - - let tags = res - .res - .find_event_tags("instantiate".to_string(), "_contract_address".to_string()); - - let (minter_addr, sg721_addr) = (tags[0].value.to_string(), tags[1].value.to_string()); - orc.contract_map - .add_address(BASE_MINTER_NAME, minter_addr) - .unwrap(); - orc.contract_map - .add_address(SG721_NAME, sg721_addr) - .unwrap(); - - Ok(res) -} - -pub fn instantiate_marketplace( - orc: &mut CosmOrc, - user: &SigningAccount, -) -> Result { - orc.instantiate( - MARKETPLACE_NAME, - &format!("{}_inst", MARKETPLACE_NAME), - // Parameters copied from mainnet 2023-02-23 - &MarketplaceInstantiateMsg { - // "trading_fee_percent":"2" - trading_fee_bps: 200, - // "ask_expiry":{"min":86400,"max":15552000} - ask_expiry: ExpiryRange { - min: 86400, - max: 15552000, - }, - // "bid_expiry":{"min":86400,"max":15552000} - bid_expiry: ExpiryRange { - min: 86400, - max: 15552000, - }, - // "operators":["stars1j7cddngyhwkr7w74qac960lee9uh9y0hgcsnfa"] - operators: vec![user.account.address.clone()], - sale_hook: None, - // "max_finders_fee_percent":"2" - max_finders_fee_bps: 200, - // "min_price":"5000000" - min_price: Uint128::from(10u64), - // "stale_bid_duration":{"time":7776000} - stale_bid_duration: Duration::Time(7776000), - // "bid_removal_reward_percent":"0.5" - bid_removal_reward_bps: 50, - // "listing_fee":"500000" - listing_fee: Uint128::from(LISTING_FEE), - }, - &user.key, - Some(user.account.address.parse().unwrap()), - vec![], - ) -} - -pub fn instantiate_infinity_swap( - orc: &mut CosmOrc, - denom: &str, - user: &SigningAccount, -) -> Result { - orc.instantiate( - INFINITY_SWAP_NAME, - &format!("{}_inst", INFINITY_SWAP_NAME), - &PoolInstantiateMsg { - denom: denom.to_string(), - marketplace_addr: orc.contract_map.address(MARKETPLACE_NAME)?, - developer: None, - }, - &user.key, - Some(user.account.address.parse().unwrap()), - vec![], - ) -} diff --git a/test/e2e/src/helpers/mod.rs b/test/e2e/src/helpers/mod.rs deleted file mode 100644 index eebda4d..0000000 --- a/test/e2e/src/helpers/mod.rs +++ /dev/null @@ -1,18 +0,0 @@ -pub mod chain; - -#[allow(dead_code)] -pub mod constants; - -pub mod fixtures; - -#[allow(dead_code)] -pub mod helper; - -#[allow(dead_code)] -pub mod instantiate; - -#[allow(dead_code)] -pub mod nft; - -#[allow(dead_code)] -pub mod pool; diff --git a/test/e2e/src/helpers/nft.rs b/test/e2e/src/helpers/nft.rs deleted file mode 100644 index 62aaeb7..0000000 --- a/test/e2e/src/helpers/nft.rs +++ /dev/null @@ -1,142 +0,0 @@ -use super::chain::Chain; -use super::constants::{BASE_MINTER_NAME, MINT_PRICE, SG721_NAME}; -use base_minter::msg::ExecuteMsg as BaseMinterExecuteMsg; -use cosm_orc::orchestrator::Coin as OrcCoin; -use cosm_orc::orchestrator::ExecResponse; -use cosm_orc::orchestrator::{ExecReq, SigningKey}; -use itertools::Itertools; -use sg721_base::ExecuteMsg as SG721ExecuteMsg; -use std::time::Duration; - -const MSGS_PER_TX: usize = 15; -const TXS_PER_BLOCK: usize = 5; - -pub fn mint_nfts(chain: &mut Chain, num_nfts: u32, user: &SigningKey) -> Vec { - let denom = &chain.cfg.orc_cfg.chain_cfg.denom; - - let mut reqs = vec![]; - for i in 1..(num_nfts + 1) { - reqs.push(ExecReq { - contract_name: BASE_MINTER_NAME.to_string(), - msg: Box::new(BaseMinterExecuteMsg::Mint { - token_uri: format!( - "ipfs://bafybeideczllcb5kz75hgy25irzevarybvazgdiaeiv2xmgqevqgo6d3ua/{}.png", - i - ), - }), - funds: vec![OrcCoin { - amount: MINT_PRICE, - denom: denom.parse().unwrap(), - }], - }); - } - - let chunked_chunked_reqs: Vec>> = reqs - .into_iter() - .chunks(MSGS_PER_TX) - .into_iter() - .map(|chunk| chunk.collect()) - .chunks(TXS_PER_BLOCK) - .into_iter() - .map(|chunk| chunk.collect()) - .collect(); - - let mut mint_ctr = 0; - let mut token_ids: Vec = vec![]; - - for chunked_chunked_req in chunked_chunked_reqs { - for chunked_req in chunked_chunked_req { - mint_ctr += chunked_req.len() as u32; - - let resp = chain - .orc - .execute_batch("base_minter_batch_mint", chunked_req, user) - .unwrap(); - - let tags = resp - .res - .find_event_tags("wasm".to_string(), "token_id".to_string()); - token_ids.append( - &mut tags - .iter() - .map(|tag| tag.value.clone()) - .collect::>(), - ); - } - - println!("Minted {} NFTs", mint_ctr); - chain - .orc - .poll_for_n_blocks(1, Duration::from_secs(10), true) - .unwrap(); - } - - token_ids -} - -pub fn mint_and_transfer_nfts( - chain: &mut Chain, - num_nfts: u32, - user: &SigningKey, - transfer_to: &str, -) -> Vec { - let token_ids = mint_nfts(chain, num_nfts, user); - - let mut reqs = vec![]; - for token_id in token_ids.iter() { - reqs.push(ExecReq { - contract_name: SG721_NAME.to_string(), - msg: Box::new(SG721ExecuteMsg::TransferNft { - recipient: transfer_to.to_string(), - token_id: token_id.to_string(), - }), - funds: vec![], - }); - } - - let chunked_chunked_reqs: Vec>> = reqs - .into_iter() - .chunks(MSGS_PER_TX) - .into_iter() - .map(|chunk| chunk.collect()) - .chunks(TXS_PER_BLOCK) - .into_iter() - .map(|chunk| chunk.collect()) - .collect(); - - for chunked_chunked_req in chunked_chunked_reqs { - for chunked_req in chunked_chunked_req { - let _resp = chain - .orc - .execute_batch("sg721_batch_transfer", chunked_req, user) - .unwrap(); - } - - chain - .orc - .poll_for_n_blocks(1, Duration::from_secs(10), true) - .unwrap(); - } - - token_ids -} - -pub fn approve_all_nfts( - chain: &mut Chain, - approve_addr: String, - user: &SigningKey, -) -> ExecResponse { - let reqs = vec![ExecReq { - contract_name: SG721_NAME.to_string(), - msg: Box::new(SG721ExecuteMsg::ApproveAll { - operator: approve_addr, - expires: None, - }), - funds: vec![], - }]; - - chain - .orc - .execute_batch("sg721_approve_all", reqs, user) - .unwrap() -} diff --git a/test/e2e/src/helpers/pool.rs b/test/e2e/src/helpers/pool.rs deleted file mode 100644 index f734d3a..0000000 --- a/test/e2e/src/helpers/pool.rs +++ /dev/null @@ -1,155 +0,0 @@ -use super::chain::Chain; -use super::constants::{INFINITY_SWAP_NAME, LISTING_FEE, SG721_NAME}; -use super::fixtures::get_pool_fixtures; -use crate::helpers::nft::{approve_all_nfts, mint_nfts}; -use cosm_orc::orchestrator::Coin as OrcCoin; -use cosm_orc::orchestrator::ExecResponse; -use cosm_orc::orchestrator::{ExecReq, SigningKey}; -use infinity_swap::msg::{ - ExecuteMsg as InfinitySwapExecuteMsg, PoolsByIdResponse, QueryMsg as InfinitySwapQueryMsg, -}; -use infinity_swap::state::Pool; -use serde::Deserialize; - -pub fn pool_execute_message( - chain: &mut Chain, - execute_msg: InfinitySwapExecuteMsg, - op_name: &str, - funds: Vec, - user: &SigningKey, -) -> ExecResponse { - let reqs = vec![ExecReq { - contract_name: INFINITY_SWAP_NAME.to_string(), - msg: Box::new(execute_msg), - funds, - }]; - - chain.orc.execute_batch(op_name, reqs, user).unwrap() -} - -pub fn pool_query_message Deserialize<'a>>( - chain: &Chain, - query_msg: InfinitySwapQueryMsg, -) -> T { - chain - .orc - .query(INFINITY_SWAP_NAME, &query_msg) - .unwrap() - .data() - .unwrap() -} - -pub fn create_active_pool( - chain: &mut Chain, - user: &SigningKey, - pool_deposit_amount: u128, - num_nfts: u32, - create_pool_msg: InfinitySwapExecuteMsg, -) -> Pool { - let denom = chain.cfg.orc_cfg.chain_cfg.denom.clone(); - let collection = chain.orc.contract_map.address(SG721_NAME).unwrap(); - - let token_ids = mint_nfts(chain, num_nfts, user); - - approve_all_nfts( - chain, - chain.orc.contract_map.address(INFINITY_SWAP_NAME).unwrap(), - user, - ); - - let resp = pool_execute_message( - chain, - create_pool_msg, - "infinity-swap-create-pool", - vec![OrcCoin { - amount: LISTING_FEE, - denom: denom.parse().unwrap(), - }], - user, - ); - - let tag = resp - .res - .find_event_tags("wasm-create-pool".to_string(), "id".to_string())[0]; - let pool_id = tag.value.parse::().unwrap(); - let mut resp: PoolsByIdResponse = pool_query_message( - chain, - InfinitySwapQueryMsg::PoolsById { - pool_ids: vec![pool_id], - }, - ); - let pool = &resp.pools.pop().unwrap().1.unwrap(); - - if pool.can_sell_nfts() { - pool_execute_message( - chain, - InfinitySwapExecuteMsg::DepositNfts { - pool_id, - collection, - nft_token_ids: token_ids, - }, - "infinity-swap-deposit-nfts", - vec![], - user, - ); - } - - if pool.can_buy_nfts() { - pool_execute_message( - chain, - InfinitySwapExecuteMsg::DepositTokens { pool_id }, - "infinity-swap-deposit-tokens", - vec![OrcCoin { - amount: pool_deposit_amount, - denom: denom.parse().unwrap(), - }], - user, - ); - } - - pool_execute_message( - chain, - InfinitySwapExecuteMsg::SetActivePool { - is_active: true, - pool_id, - }, - "infinity-swap-activate", - vec![], - user, - ); - - let mut resp: PoolsByIdResponse = pool_query_message( - chain, - InfinitySwapQueryMsg::PoolsById { - pool_ids: vec![pool_id], - }, - ); - resp.pools.pop().unwrap().1.unwrap() -} - -pub fn create_pools_from_fixtures( - chain: &mut Chain, - user: &SigningKey, - pool_deposit_amount: u128, - num_nfts: u32, - asset_account: &Option, - finders_fee_bps: u64, - swap_fee_bps: u64, -) -> Vec { - let collection = chain.orc.contract_map.address(SG721_NAME).unwrap(); - - let pool_fixtures = - get_pool_fixtures(&collection, asset_account, finders_fee_bps, swap_fee_bps); - - let mut pools: Vec = vec![]; - for fixt in pool_fixtures { - pools.push(create_active_pool( - chain, - user, - pool_deposit_amount, - num_nfts, - fixt, - )); - } - pools -} diff --git a/test/e2e/src/lib.rs b/test/e2e/src/lib.rs deleted file mode 100644 index 13e3934..0000000 --- a/test/e2e/src/lib.rs +++ /dev/null @@ -1,7 +0,0 @@ -#![allow(clippy::too_many_arguments)] - -#[cfg(not(target_arch = "wasm32"))] -mod tests; - -#[cfg(not(target_arch = "wasm32"))] -mod helpers; diff --git a/test/e2e/src/tests/create_pool.rs b/test/e2e/src/tests/create_pool.rs deleted file mode 100644 index 6f1ecfc..0000000 --- a/test/e2e/src/tests/create_pool.rs +++ /dev/null @@ -1,192 +0,0 @@ -use crate::helpers::{ - chain::Chain, - constants::{INFINITY_SWAP_NAME, LISTING_FEE, MINT_PRICE, SG721_NAME}, - fixtures::get_pool_fixtures, - helper::gen_users, - instantiate::instantiate_minter, - nft::{approve_all_nfts, mint_nfts}, - pool::{create_pools_from_fixtures, pool_execute_message, pool_query_message}, -}; -use cosm_orc::orchestrator::Coin as OrcCoin; -use cosmwasm_std::{Addr, Decimal, Uint128}; -use infinity_swap::msg::{ - ExecuteMsg as InfinitySwapExecuteMsg, PoolsByIdResponse, QueryMsg as InfinitySwapQueryMsg, -}; -use infinity_swap::state::{BondingCurve, Pool, PoolType}; -use test_context::test_context; - -#[test_context(Chain)] -#[test] -#[ignore] -fn test_small_pool_creation(chain: &mut Chain) { - let denom = chain.cfg.orc_cfg.chain_cfg.denom.clone(); - let prefix = chain.cfg.orc_cfg.chain_cfg.prefix.clone(); - - // create minter with master account - let master_account = chain.cfg.users[1].clone(); - - // gen user that will: - // * init minter - // * mint 2 NFTs - // * create Trade pool - // * deposit 2 NFTs - // * deposit 1_000_000 tokens - // * activate pool - // Min balance: MINT_PRICE + LISTING_FEE + 1_000_000 tokens - let pool_deposit_amount = 1_000_000; - let balance = (MINT_PRICE + LISTING_FEE + pool_deposit_amount) * 2; - let user = gen_users(chain, 1, balance)[0].clone(); - let user_addr = user.to_addr(&prefix).unwrap(); - - // init minter - instantiate_minter( - &mut chain.orc, - // set creator address as user to allow for minting on base minter - user_addr.to_string(), - &master_account.key, - &denom, - ) - .unwrap(); - - let collection = chain.orc.contract_map.address(SG721_NAME).unwrap(); - - let token_ids = mint_nfts(chain, 2, &user); - - approve_all_nfts( - chain, - chain.orc.contract_map.address(INFINITY_SWAP_NAME).unwrap(), - &user, - ); - - let resp = pool_execute_message( - chain, - InfinitySwapExecuteMsg::CreateTradePool { - collection: collection.clone(), - asset_recipient: None, - bonding_curve: BondingCurve::ConstantProduct, - spot_price: Uint128::zero(), - delta: Uint128::zero(), - finders_fee_bps: 0, - swap_fee_bps: 100, - reinvest_tokens: true, - reinvest_nfts: true, - }, - "infinity-swap-create-pool", - vec![OrcCoin { - amount: LISTING_FEE, - denom: denom.parse().unwrap(), - }], - &user, - ); - - let tag = resp - .res - .find_event_tags("wasm-create-pool".to_string(), "id".to_string())[0]; - - let pool_id = tag.value.parse::().unwrap(); - - pool_execute_message( - chain, - InfinitySwapExecuteMsg::DepositNfts { - pool_id, - collection: collection.clone(), - nft_token_ids: token_ids.clone(), - }, - "infinity-swap-deposit-nfts", - vec![], - &user, - ); - - pool_execute_message( - chain, - InfinitySwapExecuteMsg::DepositTokens { pool_id }, - "infinity-swap-deposit-tokens", - vec![OrcCoin { - amount: pool_deposit_amount, - denom: denom.parse().unwrap(), - }], - &user, - ); - - pool_execute_message( - chain, - InfinitySwapExecuteMsg::SetActivePool { - is_active: true, - pool_id, - }, - "infinity-swap-activate", - vec![], - &user, - ); - - let resp: PoolsByIdResponse = pool_query_message( - chain, - InfinitySwapQueryMsg::PoolsById { - pool_ids: vec![pool_id], - }, - ); - let resp_pool = resp.pools[0].1.clone().unwrap(); - assert_eq!( - resp_pool, - Pool { - id: pool_id, - collection: Addr::unchecked(collection), - owner: Addr::unchecked(user_addr.to_string()), - asset_recipient: None, - pool_type: PoolType::Trade, - bonding_curve: BondingCurve::ConstantProduct, - spot_price: Uint128::from(500_000u128), - delta: Uint128::zero(), - total_tokens: Uint128::new(1000000u128), - total_nfts: token_ids.len() as u64, - finders_fee_percent: Decimal::zero(), - swap_fee_percent: Decimal::new(Uint128::from(1000000000000000000u128)), - is_active: true, - reinvest_tokens: true, - reinvest_nfts: true, - } - ); -} - -#[test_context(Chain)] -#[test] -#[ignore] -fn test_pool_creation_all_types(chain: &mut Chain) { - let denom = chain.cfg.orc_cfg.chain_cfg.denom.clone(); - let prefix = chain.cfg.orc_cfg.chain_cfg.prefix.clone(); - - // create minter with master account - let master_account = chain.cfg.users[1].clone(); - - let pool_deposit_amount = 1_000_000; - let balance = 1_000_000_000; - let user = gen_users(chain, 1, balance)[0].clone(); - let user_addr = user.to_addr(&prefix).unwrap(); - - let asset_account = gen_users(chain, 1, 1)[0].clone(); - let asset_account_addr = asset_account.to_addr(&prefix).unwrap(); - - // init minter - instantiate_minter( - &mut chain.orc, - // set creator address as user to allow for minting on base minter - user_addr.to_string(), - &master_account.key, - &denom, - ) - .unwrap(); - let collection = chain.orc.contract_map.address(SG721_NAME).unwrap(); - - let pools = create_pools_from_fixtures( - chain, - &user, - pool_deposit_amount, - 10, - &Some(asset_account_addr.to_string()), - 150, - 300, - ); - let fixtures = get_pool_fixtures(&collection, &Some(asset_account_addr.to_string()), 250, 300); - - assert_eq!(pools.len(), fixtures.len()); -} diff --git a/test/e2e/src/tests/direct_swap_nfts_for_tokens.rs b/test/e2e/src/tests/direct_swap_nfts_for_tokens.rs deleted file mode 100644 index d22d049..0000000 --- a/test/e2e/src/tests/direct_swap_nfts_for_tokens.rs +++ /dev/null @@ -1,113 +0,0 @@ -use crate::helpers::{ - chain::Chain, - constants::INFINITY_SWAP_NAME, - helper::{gen_users, latest_block_time}, - instantiate::instantiate_minter, - nft::{approve_all_nfts, mint_and_transfer_nfts}, - pool::{create_pools_from_fixtures, pool_execute_message, pool_query_message}, -}; -use cosmwasm_std::Uint128; -use infinity_swap::msg::{ - ExecuteMsg as InfinitySwapExecuteMsg, NftSwap, QueryMsg as InfinitySwapQueryMsg, SwapParams, - SwapResponse, -}; -use test_context::test_context; - -#[test_context(Chain)] -#[test] -#[ignore] -fn swap_small(chain: &mut Chain) { - let denom = chain.cfg.orc_cfg.chain_cfg.denom.clone(); - let prefix = chain.cfg.orc_cfg.chain_cfg.prefix.clone(); - let master_account = chain.cfg.users[1].clone(); - - let pool_deposit_amount = 1_000_000; - let balance = 1_000_000_000; - let mut users = gen_users(chain, 2, balance); - let maker = users.pop().unwrap(); - let maker_addr = maker.to_addr(&prefix).unwrap(); - let taker = users.pop().unwrap(); - let taker_addr = taker.to_addr(&prefix).unwrap(); - - let asset_account = gen_users(chain, 1, 1)[0].clone(); - let asset_account_addr = asset_account.to_addr(&prefix).unwrap(); - - // init minter - instantiate_minter( - &mut chain.orc, - // set creator address as maker to allow for minting on base minter - maker_addr.to_string(), - &master_account.key, - &denom, - ) - .unwrap(); - - let pools = create_pools_from_fixtures( - chain, - &maker, - pool_deposit_amount, - 10, - &Some(asset_account_addr.to_string()), - 150, - 300, - ); - - let mut bidder_token_ids = mint_and_transfer_nfts(chain, 50, &maker, taker_addr.as_ref()); - approve_all_nfts( - chain, - chain.orc.contract_map.address(INFINITY_SWAP_NAME).unwrap(), - &taker, - ); - - for pool in pools.iter() { - if !pool.can_buy_nfts() { - continue; - } - let num_swaps = 3; - let nfts_to_swap: Vec = bidder_token_ids - .drain(0..num_swaps) - .map(|token_id| NftSwap { - nft_token_id: token_id, - token_amount: Uint128::from(10u128), - }) - .collect(); - - let sim_res: SwapResponse = pool_query_message( - chain, - InfinitySwapQueryMsg::SimDirectSwapNftsForTokens { - pool_id: pool.id, - nfts_to_swap: nfts_to_swap.clone(), - sender: taker_addr.to_string(), - swap_params: SwapParams { - deadline: latest_block_time(&chain.orc).plus_seconds(1_000), - robust: false, - asset_recipient: None, - finder: None, - }, - }, - ); - assert!(!sim_res.swaps.is_empty()); - - let exec_resp = pool_execute_message( - chain, - InfinitySwapExecuteMsg::DirectSwapNftsForTokens { - pool_id: pool.id, - nfts_to_swap, - swap_params: SwapParams { - deadline: latest_block_time(&chain.orc).plus_seconds(1_000), - robust: false, - asset_recipient: None, - finder: None, - }, - }, - "infinity-swap-direct-swap-nfts-for-tokens", - vec![], - &taker, - ); - - let tags = exec_resp - .res - .find_event_tags("wasm-swap".to_string(), "pool_id".to_string()); - assert!(tags.len() == num_swaps); - } -} diff --git a/test/e2e/src/tests/direct_swap_tokens_for_specific_nfts.rs b/test/e2e/src/tests/direct_swap_tokens_for_specific_nfts.rs deleted file mode 100644 index 641fcae..0000000 --- a/test/e2e/src/tests/direct_swap_tokens_for_specific_nfts.rs +++ /dev/null @@ -1,127 +0,0 @@ -use crate::helpers::{ - chain::Chain, - helper::{gen_users, latest_block_time}, - instantiate::instantiate_minter, - pool::{create_pools_from_fixtures, pool_execute_message, pool_query_message}, -}; -use cosm_orc::orchestrator::Coin as OrcCoin; -use cosmwasm_std::Uint128; -use infinity_swap::msg::{ - ExecuteMsg as InfinitySwapExecuteMsg, NftSwap, NftTokenIdsResponse, - QueryMsg as InfinitySwapQueryMsg, QueryOptions, SwapParams, SwapResponse, -}; -use test_context::test_context; - -#[test_context(Chain)] -#[test] -#[ignore] -fn swap_small(chain: &mut Chain) { - let denom = chain.cfg.orc_cfg.chain_cfg.denom.clone(); - let prefix = chain.cfg.orc_cfg.chain_cfg.prefix.clone(); - let master_account = chain.cfg.users[1].clone(); - - let pool_deposit_amount = 1_000_000; - let balance = 1_000_000_000; - let mut users = gen_users(chain, 2, balance); - let maker = users.pop().unwrap(); - let maker_addr = maker.to_addr(&prefix).unwrap(); - let taker = users.pop().unwrap(); - let taker_addr = taker.to_addr(&prefix).unwrap(); - - let asset_account = gen_users(chain, 1, 1)[0].clone(); - let asset_account_addr = asset_account.to_addr(&prefix).unwrap(); - - // init minter - instantiate_minter( - &mut chain.orc, - // set creator address as maker to allow for minting on base minter - maker_addr.to_string(), - &master_account.key, - &denom, - ) - .unwrap(); - - let pools = create_pools_from_fixtures( - chain, - &maker, - pool_deposit_amount, - 10, - &Some(asset_account_addr.to_string()), - 150, - 300, - ); - - for pool in pools.iter() { - if !pool.can_sell_nfts() { - continue; - } - let num_swaps = 3u8; - - let nft_token_ids_res: NftTokenIdsResponse = pool_query_message( - chain, - InfinitySwapQueryMsg::PoolNftTokenIds { - pool_id: pool.id, - query_options: QueryOptions { - descending: None, - start_after: None, - limit: Some(num_swaps as u32), - }, - }, - ); - - let nfts_to_swap_for: Vec = nft_token_ids_res - .nft_token_ids - .clone() - .into_iter() - .map(|token_id| NftSwap { - nft_token_id: token_id, - token_amount: Uint128::from(1_000_000u128), - }) - .collect(); - - let sim_res: SwapResponse = pool_query_message( - chain, - InfinitySwapQueryMsg::SimDirectSwapTokensForSpecificNfts { - pool_id: pool.id, - nfts_to_swap_for: nfts_to_swap_for.clone(), - sender: taker_addr.to_string(), - swap_params: SwapParams { - deadline: latest_block_time(&chain.orc).plus_seconds(1_000), - robust: false, - asset_recipient: None, - finder: None, - }, - }, - ); - assert!(!sim_res.swaps.is_empty()); - - let total_amount = nfts_to_swap_for - .iter() - .fold(Uint128::zero(), |acc, nft_swap| acc + nft_swap.token_amount); - - let exec_resp = pool_execute_message( - chain, - InfinitySwapExecuteMsg::DirectSwapTokensForSpecificNfts { - pool_id: pool.id, - nfts_to_swap_for, - swap_params: SwapParams { - deadline: latest_block_time(&chain.orc).plus_seconds(1_000), - robust: false, - asset_recipient: None, - finder: None, - }, - }, - "infinity-swap-direct-swap-tokens-for-specific-nfts", - vec![OrcCoin { - amount: total_amount.u128(), - denom: denom.parse().unwrap(), - }], - &taker, - ); - - let tags = exec_resp - .res - .find_event_tags("wasm-swap".to_string(), "pool_id".to_string()); - assert!(tags.len() == num_swaps as usize); - } -} diff --git a/test/e2e/src/tests/large_nfts_for_tokens.rs b/test/e2e/src/tests/large_nfts_for_tokens.rs deleted file mode 100644 index ac9a041..0000000 --- a/test/e2e/src/tests/large_nfts_for_tokens.rs +++ /dev/null @@ -1,264 +0,0 @@ -use crate::helpers::{ - chain::Chain, - constants::{INFINITY_SWAP_NAME, LISTING_FEE, SG721_NAME}, - helper::{gen_users, latest_block_time}, - instantiate::instantiate_minter, - nft::{approve_all_nfts, mint_nfts}, - pool::{create_active_pool, pool_execute_message, pool_query_message}, -}; -use cosm_orc::orchestrator::Coin as OrcCoin; -use cosmwasm_std::{Addr, Decimal, Uint128}; -use infinity_swap::msg::{ - ExecuteMsg as InfinitySwapExecuteMsg, NftSwap, PoolsByIdResponse, - QueryMsg as InfinitySwapQueryMsg, SwapParams, -}; -use infinity_swap::state::Pool; -use infinity_swap::state::{BondingCurve, PoolType}; -use std::env; -use test_context::test_context; - -#[allow(dead_code)] -const LARGE_NUM_SWAPS: usize = 250; - -#[test_context(Chain)] -#[test] -#[ignore] -fn large_single_pool_nft_for_token_swap(chain: &mut Chain) { - if env::var("ENABLE_LARGE_TESTS").is_err() { - return; - } - - let denom = chain.cfg.orc_cfg.chain_cfg.denom.clone(); - let prefix = chain.cfg.orc_cfg.chain_cfg.prefix.clone(); - - let master_account = chain.cfg.users[1].clone(); - - let pool_deposit_amount = 10_000_000; - let balance = pool_deposit_amount * 10_000; - let user = gen_users(chain, 1, balance)[0].clone(); - let user_addr = user.to_addr(&prefix).unwrap(); - - // init minter - instantiate_minter( - &mut chain.orc, - // set creator address as user to allow for minting on base minter - user_addr.to_string(), - &master_account.key, - &denom, - ) - .unwrap(); - - let collection = chain.orc.contract_map.address(SG721_NAME).unwrap(); - - let token_ids = mint_nfts(chain, 10_000, &user); - - approve_all_nfts( - chain, - chain.orc.contract_map.address(INFINITY_SWAP_NAME).unwrap(), - &user, - ); - - let resp = pool_execute_message( - chain, - InfinitySwapExecuteMsg::CreateTradePool { - collection: collection.clone(), - asset_recipient: None, - bonding_curve: BondingCurve::ConstantProduct, - spot_price: Uint128::zero(), - delta: Uint128::zero(), - finders_fee_bps: 0, - swap_fee_bps: 0, - reinvest_tokens: true, - reinvest_nfts: true, - }, - "infinity-swap-create-pool", - vec![OrcCoin { - amount: LISTING_FEE, - denom: denom.parse().unwrap(), - }], - &user, - ); - - let tag = resp - .res - .find_event_tags("wasm-create-pool".to_string(), "id".to_string())[0]; - - let pool_id = tag.value.parse::().unwrap(); - - pool_execute_message( - chain, - InfinitySwapExecuteMsg::DepositNfts { - pool_id, - collection: collection.clone(), - nft_token_ids: token_ids.clone(), - }, - "infinity-swap-deposit-nfts", - vec![], - &user, - ); - - pool_execute_message( - chain, - InfinitySwapExecuteMsg::DepositTokens { pool_id }, - "infinity-swap-deposit-tokens", - vec![OrcCoin { - amount: pool_deposit_amount, - denom: denom.parse().unwrap(), - }], - &user, - ); - - pool_execute_message( - chain, - InfinitySwapExecuteMsg::SetActivePool { - is_active: true, - pool_id, - }, - "infinity-swap-activate", - vec![], - &user, - ); - - let resp: PoolsByIdResponse = pool_query_message( - chain, - InfinitySwapQueryMsg::PoolsById { - pool_ids: vec![pool_id], - }, - ); - let resp_pool = resp.pools[0].1.clone().unwrap(); - - assert_eq!( - resp_pool, - Pool { - id: 1, - collection: Addr::unchecked(collection.clone()), - owner: Addr::unchecked(user_addr.to_string()), - asset_recipient: None, - pool_type: PoolType::Trade, - bonding_curve: BondingCurve::ConstantProduct, - spot_price: Uint128::new(pool_deposit_amount) / Uint128::from(token_ids.len() as u64), - delta: Uint128::zero(), - total_tokens: Uint128::new(pool_deposit_amount), - total_nfts: token_ids.len() as u64, - finders_fee_percent: Decimal::zero(), - swap_fee_percent: Decimal::zero(), - is_active: true, - reinvest_tokens: true, - reinvest_nfts: true, - } - ); - - let bidder_token_ids = mint_nfts(chain, LARGE_NUM_SWAPS as u32, &user); - let nfts_to_swap: Vec = bidder_token_ids - .into_iter() - .map(|token_id| NftSwap { - nft_token_id: token_id, - token_amount: Uint128::from(10u128), - }) - .collect(); - - let exec_res = pool_execute_message( - chain, - InfinitySwapExecuteMsg::SwapNftsForTokens { - collection, - nfts_to_swap, - swap_params: SwapParams { - deadline: latest_block_time(&chain.orc).plus_seconds(1_000), - robust: false, - asset_recipient: None, - finder: None, - }, - }, - "infinity-swap-swap-nfts-for-tokens", - vec![], - &user, - ); - println!("gas_wanted {:?}", exec_res.res.gas_wanted); - println!("gas_used {:?}", exec_res.res.gas_used); -} - -#[test_context(Chain)] -#[test] -#[ignore] -fn large_many_pool_nft_for_token_swap(chain: &mut Chain) { - if env::var("ENABLE_LARGE_TESTS").is_err() { - return; - } - - let denom = chain.cfg.orc_cfg.chain_cfg.denom.clone(); - let prefix = chain.cfg.orc_cfg.chain_cfg.prefix.clone(); - - let master_account = chain.cfg.users[1].clone(); - - let pool_deposit_amount = 10_000_000; - let balance = pool_deposit_amount * 10_000; - let mut users = gen_users(chain, 2, balance); - let maker = users.pop().unwrap(); - let _maker_addr = maker.to_addr(&prefix).unwrap(); - let taker = users.pop().unwrap(); - let taker_addr = taker.to_addr(&prefix).unwrap(); - - // init minter - instantiate_minter( - &mut chain.orc, - // set creator address as user to allow for minting on base minter - taker_addr.to_string(), - &master_account.key, - &denom, - ) - .unwrap(); - - let collection = chain.orc.contract_map.address(SG721_NAME).unwrap(); - - let mut pools: Vec = vec![]; - for _ in 0..LARGE_NUM_SWAPS { - pools.push(create_active_pool( - chain, - &maker, - pool_deposit_amount, - 0, - InfinitySwapExecuteMsg::CreateTokenPool { - collection: collection.to_string(), - asset_recipient: None, - bonding_curve: BondingCurve::Linear, - spot_price: Uint128::from(100u64), - delta: Uint128::from(10u64), - finders_fee_bps: 0, - }, - )); - } - - let bidder_token_ids = mint_nfts(chain, LARGE_NUM_SWAPS as u32, &taker); - let nfts_to_swap: Vec = bidder_token_ids - .into_iter() - .map(|token_id| NftSwap { - nft_token_id: token_id, - token_amount: Uint128::from(10u128), - }) - .collect(); - - approve_all_nfts( - chain, - chain.orc.contract_map.address(INFINITY_SWAP_NAME).unwrap(), - &taker, - ); - - let exec_res = pool_execute_message( - chain, - InfinitySwapExecuteMsg::SwapNftsForTokens { - collection, - nfts_to_swap, - swap_params: SwapParams { - deadline: latest_block_time(&chain.orc).plus_seconds(1_000), - robust: false, - asset_recipient: None, - finder: None, - }, - }, - "infinity-swap-swap-nfts-for-tokens", - vec![], - &taker, - ); - println!("gas_wanted {:?}", exec_res.res.gas_wanted); - println!("gas_used {:?}", exec_res.res.gas_used); -} diff --git a/test/e2e/src/tests/large_tokens_for_nfts.rs b/test/e2e/src/tests/large_tokens_for_nfts.rs deleted file mode 100644 index 2caad4f..0000000 --- a/test/e2e/src/tests/large_tokens_for_nfts.rs +++ /dev/null @@ -1,253 +0,0 @@ -use crate::helpers::{ - chain::Chain, - constants::{INFINITY_SWAP_NAME, LISTING_FEE, SG721_NAME}, - helper::{gen_users, latest_block_time}, - instantiate::instantiate_minter, - nft::{approve_all_nfts, mint_nfts}, - pool::{create_active_pool, pool_execute_message, pool_query_message}, -}; -use cosm_orc::orchestrator::Coin as OrcCoin; -use cosmwasm_std::{Addr, Decimal, Uint128}; -use infinity_swap::msg::{ - ExecuteMsg as InfinitySwapExecuteMsg, PoolsByIdResponse, QueryMsg as InfinitySwapQueryMsg, - SwapParams, -}; -use infinity_swap::state::Pool; -use infinity_swap::state::{BondingCurve, PoolType}; -use std::env; -use test_context::test_context; - -#[allow(dead_code)] -const LARGE_NUM_SWAPS: usize = 250; - -#[test_context(Chain)] -#[test] -#[ignore] -fn large_single_pool_token_for_nft_swap(chain: &mut Chain) { - if env::var("ENABLE_LARGE_TESTS").is_err() { - return; - } - - let denom = chain.cfg.orc_cfg.chain_cfg.denom.clone(); - let prefix = chain.cfg.orc_cfg.chain_cfg.prefix.clone(); - - let master_account = chain.cfg.users[1].clone(); - - let pool_deposit_amount = 10_000_000; - let balance = pool_deposit_amount * 10_000; - let user = gen_users(chain, 1, balance)[0].clone(); - let user_addr = user.to_addr(&prefix).unwrap(); - - // init minter - instantiate_minter( - &mut chain.orc, - // set creator address as user to allow for minting on base minter - user_addr.to_string(), - &master_account.key, - &denom, - ) - .unwrap(); - - let collection = chain.orc.contract_map.address(SG721_NAME).unwrap(); - - let token_ids = mint_nfts(chain, 10_000, &user); - - approve_all_nfts( - chain, - chain.orc.contract_map.address(INFINITY_SWAP_NAME).unwrap(), - &user, - ); - - let resp = pool_execute_message( - chain, - InfinitySwapExecuteMsg::CreateTradePool { - collection: collection.clone(), - asset_recipient: None, - bonding_curve: BondingCurve::ConstantProduct, - spot_price: Uint128::zero(), - delta: Uint128::zero(), - finders_fee_bps: 0, - swap_fee_bps: 0, - reinvest_tokens: true, - reinvest_nfts: true, - }, - "infinity-swap-create-pool", - vec![OrcCoin { - amount: LISTING_FEE, - denom: denom.parse().unwrap(), - }], - &user, - ); - - let tag = resp - .res - .find_event_tags("wasm-create-pool".to_string(), "id".to_string())[0]; - - let pool_id = tag.value.parse::().unwrap(); - - pool_execute_message( - chain, - InfinitySwapExecuteMsg::DepositNfts { - pool_id, - collection: collection.clone(), - nft_token_ids: token_ids.clone(), - }, - "infinity-swap-deposit-nfts", - vec![], - &user, - ); - - pool_execute_message( - chain, - InfinitySwapExecuteMsg::DepositTokens { pool_id }, - "infinity-swap-deposit-tokens", - vec![OrcCoin { - amount: pool_deposit_amount, - denom: denom.parse().unwrap(), - }], - &user, - ); - - pool_execute_message( - chain, - InfinitySwapExecuteMsg::SetActivePool { - is_active: true, - pool_id, - }, - "infinity-swap-activate", - vec![], - &user, - ); - - let resp: PoolsByIdResponse = pool_query_message( - chain, - InfinitySwapQueryMsg::PoolsById { - pool_ids: vec![pool_id], - }, - ); - let resp_pool = resp.pools[0].1.clone().unwrap(); - - assert_eq!( - resp_pool, - Pool { - id: 1, - collection: Addr::unchecked(collection.clone()), - owner: Addr::unchecked(user_addr.to_string()), - asset_recipient: None, - pool_type: PoolType::Trade, - bonding_curve: BondingCurve::ConstantProduct, - spot_price: Uint128::new(pool_deposit_amount) / Uint128::from(token_ids.len() as u64), - delta: Uint128::zero(), - total_tokens: Uint128::new(pool_deposit_amount), - total_nfts: token_ids.len() as u64, - finders_fee_percent: Decimal::zero(), - swap_fee_percent: Decimal::zero(), - is_active: true, - reinvest_tokens: true, - reinvest_nfts: true, - } - ); - - let max_expected_token_input = [Uint128::from(10_000u64); LARGE_NUM_SWAPS]; - let send_amount: Uint128 = max_expected_token_input.iter().sum(); - let exec_res = pool_execute_message( - chain, - InfinitySwapExecuteMsg::SwapTokensForAnyNfts { - collection, - max_expected_token_input: max_expected_token_input.to_vec(), - swap_params: SwapParams { - deadline: latest_block_time(&chain.orc).plus_seconds(1_000), - robust: false, - asset_recipient: None, - finder: None, - }, - }, - "infinity-swap-swap-tokens-for-any-nfts", - vec![OrcCoin { - amount: send_amount.u128(), - denom: denom.parse().unwrap(), - }], - &user, - ); - println!("gas_wanted {:?}", exec_res.res.gas_wanted); - println!("gas_used {:?}", exec_res.res.gas_used); -} - -#[test_context(Chain)] -#[test] -#[ignore] -fn large_many_pool_token_for_nft_swap(chain: &mut Chain) { - if env::var("ENABLE_LARGE_TESTS").is_err() { - return; - } - - let denom = chain.cfg.orc_cfg.chain_cfg.denom.clone(); - let prefix = chain.cfg.orc_cfg.chain_cfg.prefix.clone(); - - let master_account = chain.cfg.users[1].clone(); - - let pool_deposit_amount = 10_000_000; - let balance = pool_deposit_amount * 10_000; - let user = gen_users(chain, 1, balance)[0].clone(); - let user_addr = user.to_addr(&prefix).unwrap(); - - // init minter - instantiate_minter( - &mut chain.orc, - // set creator address as user to allow for minting on base minter - user_addr.to_string(), - &master_account.key, - &denom, - ) - .unwrap(); - - let collection = chain.orc.contract_map.address(SG721_NAME).unwrap(); - - approve_all_nfts( - chain, - chain.orc.contract_map.address(INFINITY_SWAP_NAME).unwrap(), - &user, - ); - - let mut pools: Vec = vec![]; - for _ in 0..LARGE_NUM_SWAPS { - pools.push(create_active_pool( - chain, - &user, - pool_deposit_amount, - 2, - InfinitySwapExecuteMsg::CreateNftPool { - collection: collection.to_string(), - asset_recipient: None, - bonding_curve: BondingCurve::Linear, - spot_price: Uint128::from(100u64), - delta: Uint128::from(10u64), - finders_fee_bps: 0, - }, - )); - } - - let max_expected_token_input = [Uint128::from(10_000u64); LARGE_NUM_SWAPS]; - let send_amount: Uint128 = max_expected_token_input.iter().sum(); - let exec_res = pool_execute_message( - chain, - InfinitySwapExecuteMsg::SwapTokensForAnyNfts { - collection, - max_expected_token_input: max_expected_token_input.to_vec(), - swap_params: SwapParams { - deadline: latest_block_time(&chain.orc).plus_seconds(1_000), - robust: false, - asset_recipient: None, - finder: None, - }, - }, - "infinity-swap-swap-tokens-for-any-nfts", - vec![OrcCoin { - amount: send_amount.u128(), - denom: denom.parse().unwrap(), - }], - &user, - ); - println!("gas_wanted {:?}", exec_res.res.gas_wanted); - println!("gas_used {:?}", exec_res.res.gas_used); -} diff --git a/test/e2e/src/tests/mod.rs b/test/e2e/src/tests/mod.rs deleted file mode 100644 index 9b5e5a5..0000000 --- a/test/e2e/src/tests/mod.rs +++ /dev/null @@ -1,8 +0,0 @@ -pub mod create_pool; -pub mod direct_swap_nfts_for_tokens; -pub mod direct_swap_tokens_for_specific_nfts; -pub mod large_nfts_for_tokens; -pub mod large_tokens_for_nfts; -pub mod swap_nfts_for_tokens; -pub mod swap_tokens_for_any_nfts; -pub mod swap_tokens_for_specific_nfts; diff --git a/test/e2e/src/tests/swap_nfts_for_tokens.rs b/test/e2e/src/tests/swap_nfts_for_tokens.rs deleted file mode 100644 index 5d27a97..0000000 --- a/test/e2e/src/tests/swap_nfts_for_tokens.rs +++ /dev/null @@ -1,111 +0,0 @@ -use crate::helpers::{ - chain::Chain, - constants::{INFINITY_SWAP_NAME, SG721_NAME}, - helper::{gen_users, latest_block_time}, - instantiate::instantiate_minter, - nft::{approve_all_nfts, mint_and_transfer_nfts}, - pool::{create_pools_from_fixtures, pool_execute_message, pool_query_message}, -}; -use cosmwasm_std::Uint128; -use infinity_swap::msg::{ - ExecuteMsg as InfinitySwapExecuteMsg, NftSwap, QueryMsg as InfinitySwapQueryMsg, SwapParams, - SwapResponse, -}; -use test_context::test_context; - -#[test_context(Chain)] -#[test] -#[ignore] -fn swap_small(chain: &mut Chain) { - let denom = chain.cfg.orc_cfg.chain_cfg.denom.clone(); - let prefix = chain.cfg.orc_cfg.chain_cfg.prefix.clone(); - let master_account = chain.cfg.users[1].clone(); - - let pool_deposit_amount = 1_000_000; - let balance = 1_000_000_000; - let mut users = gen_users(chain, 2, balance); - let maker = users.pop().unwrap(); - let maker_addr = maker.to_addr(&prefix).unwrap(); - let taker = users.pop().unwrap(); - let taker_addr = taker.to_addr(&prefix).unwrap(); - - let asset_account = gen_users(chain, 1, 1)[0].clone(); - let asset_account_addr = asset_account.to_addr(&prefix).unwrap(); - - // init minter - instantiate_minter( - &mut chain.orc, - // set creator address as maker to allow for minting on base minter - maker_addr.to_string(), - &master_account.key, - &denom, - ) - .unwrap(); - let collection = chain.orc.contract_map.address(SG721_NAME).unwrap(); - - let _pools = create_pools_from_fixtures( - chain, - &maker, - pool_deposit_amount, - 10, - &Some(asset_account_addr.to_string()), - 150, - 300, - ); - - let bidder_token_ids = mint_and_transfer_nfts(chain, 10, &maker, taker_addr.as_ref()); - approve_all_nfts( - chain, - chain.orc.contract_map.address(INFINITY_SWAP_NAME).unwrap(), - &taker, - ); - - let num_swaps: u8 = 10; - - let nfts_to_swap: Vec = bidder_token_ids - .to_vec() - .drain(0..(num_swaps as usize)) - .map(|token_id| NftSwap { - nft_token_id: token_id, - token_amount: Uint128::from(100u128), - }) - .collect(); - - let sim_res: SwapResponse = pool_query_message( - chain, - InfinitySwapQueryMsg::SimSwapNftsForTokens { - collection: collection.to_string(), - nfts_to_swap: nfts_to_swap.clone(), - sender: taker_addr.to_string(), - swap_params: SwapParams { - deadline: latest_block_time(&chain.orc).plus_seconds(1_000), - robust: false, - asset_recipient: None, - finder: None, - }, - }, - ); - assert!(!sim_res.swaps.is_empty()); - - let exec_resp = pool_execute_message( - chain, - InfinitySwapExecuteMsg::SwapNftsForTokens { - collection, - nfts_to_swap, - swap_params: SwapParams { - deadline: latest_block_time(&chain.orc).plus_seconds(1_000), - robust: false, - asset_recipient: None, - finder: None, - }, - }, - "infinity-swap-swap-nfts-for-tokens", - vec![], - &taker, - ); - - let tags = exec_resp - .res - .find_event_tags("wasm-swap".to_string(), "pool_id".to_string()); - assert!(tags.len() == num_swaps as usize); -} diff --git a/test/e2e/src/tests/swap_tokens_for_any_nfts.rs b/test/e2e/src/tests/swap_tokens_for_any_nfts.rs deleted file mode 100644 index 284f6b5..0000000 --- a/test/e2e/src/tests/swap_tokens_for_any_nfts.rs +++ /dev/null @@ -1,102 +0,0 @@ -use crate::helpers::{ - chain::Chain, - constants::SG721_NAME, - helper::{gen_users, latest_block_time}, - instantiate::instantiate_minter, - pool::{create_pools_from_fixtures, pool_execute_message, pool_query_message}, -}; -use cosm_orc::orchestrator::Coin as OrcCoin; -use cosmwasm_std::Uint128; -use infinity_swap::msg::{ - ExecuteMsg as InfinitySwapExecuteMsg, QueryMsg as InfinitySwapQueryMsg, SwapParams, - SwapResponse, -}; -use test_context::test_context; - -#[test_context(Chain)] -#[test] -#[ignore] -fn swap_small(chain: &mut Chain) { - let denom = chain.cfg.orc_cfg.chain_cfg.denom.clone(); - let prefix = chain.cfg.orc_cfg.chain_cfg.prefix.clone(); - let master_account = chain.cfg.users[1].clone(); - - let pool_deposit_amount = 1_000_000; - let balance = 1_000_000_000; - let mut users = gen_users(chain, 2, balance); - let maker = users.pop().unwrap(); - let maker_addr = maker.to_addr(&prefix).unwrap(); - let taker = users.pop().unwrap(); - let taker_addr = taker.to_addr(&prefix).unwrap(); - - let asset_account = gen_users(chain, 1, 1)[0].clone(); - let asset_account_addr = asset_account.to_addr(&prefix).unwrap(); - - // init minter - instantiate_minter( - &mut chain.orc, - // set creator address as maker to allow for minting on base minter - maker_addr.to_string(), - &master_account.key, - &denom, - ) - .unwrap(); - - let _pools = create_pools_from_fixtures( - chain, - &maker, - pool_deposit_amount, - 10, - &Some(asset_account_addr.to_string()), - 150, - 300, - ); - let collection = chain.orc.contract_map.address(SG721_NAME).unwrap(); - - let num_swaps: u8 = 10; - let max_expected_token_input: Vec = - vec![Uint128::from(1_000_000u128); num_swaps as usize]; - - let sim_res: SwapResponse = pool_query_message( - chain, - InfinitySwapQueryMsg::SimSwapTokensForAnyNfts { - collection: collection.to_string(), - max_expected_token_input: max_expected_token_input.clone(), - sender: taker_addr.to_string(), - swap_params: SwapParams { - deadline: latest_block_time(&chain.orc).plus_seconds(1_000), - robust: false, - asset_recipient: None, - finder: None, - }, - }, - ); - assert!(!sim_res.swaps.is_empty()); - - let total_amount: Uint128 = max_expected_token_input.iter().sum(); - - let exec_resp = pool_execute_message( - chain, - InfinitySwapExecuteMsg::SwapTokensForAnyNfts { - collection, - max_expected_token_input, - swap_params: SwapParams { - deadline: latest_block_time(&chain.orc).plus_seconds(1_000), - robust: false, - asset_recipient: None, - finder: None, - }, - }, - "infinity-swap-swap-nfts-for-tokens", - vec![OrcCoin { - amount: total_amount.u128(), - denom: denom.parse().unwrap(), - }], - &taker, - ); - - let tags = exec_resp - .res - .find_event_tags("wasm-swap".to_string(), "pool_id".to_string()); - assert!(tags.len() == num_swaps as usize); -} diff --git a/test/e2e/src/tests/swap_tokens_for_specific_nfts.rs b/test/e2e/src/tests/swap_tokens_for_specific_nfts.rs deleted file mode 100644 index 7ac6cac..0000000 --- a/test/e2e/src/tests/swap_tokens_for_specific_nfts.rs +++ /dev/null @@ -1,143 +0,0 @@ -use crate::helpers::{ - chain::Chain, - constants::SG721_NAME, - helper::{gen_users, latest_block_time}, - instantiate::instantiate_minter, - pool::{create_pools_from_fixtures, pool_execute_message, pool_query_message}, -}; -use cosm_orc::orchestrator::Coin as OrcCoin; -use cosmwasm_std::Uint128; -use infinity_swap::msg::{ - ExecuteMsg as InfinitySwapExecuteMsg, NftSwap, NftTokenIdsResponse, PoolNftSwap, - QueryMsg as InfinitySwapQueryMsg, QueryOptions, SwapParams, SwapResponse, -}; -use infinity_swap::state::Pool; -use itertools::Itertools; -use test_context::test_context; - -#[test_context(Chain)] -#[test] -#[ignore] -fn swap_small(chain: &mut Chain) { - let denom = chain.cfg.orc_cfg.chain_cfg.denom.clone(); - let prefix = chain.cfg.orc_cfg.chain_cfg.prefix.clone(); - let master_account = chain.cfg.users[1].clone(); - - let pool_deposit_amount = 1_000_000; - let balance = 1_000_000_000; - let mut users = gen_users(chain, 2, balance); - let maker = users.pop().unwrap(); - let maker_addr = maker.to_addr(&prefix).unwrap(); - let taker = users.pop().unwrap(); - let taker_addr = taker.to_addr(&prefix).unwrap(); - - let asset_account = gen_users(chain, 1, 1)[0].clone(); - let asset_account_addr = asset_account.to_addr(&prefix).unwrap(); - - // init minter - instantiate_minter( - &mut chain.orc, - // set creator address as maker to allow for minting on base minter - maker_addr.to_string(), - &master_account.key, - &denom, - ) - .unwrap(); - let collection = chain.orc.contract_map.address(SG721_NAME).unwrap(); - - let pools = create_pools_from_fixtures( - chain, - &maker, - pool_deposit_amount, - 10, - &Some(asset_account_addr.to_string()), - 150, - 300, - ); - - let pool_chunks: Vec> = pools - .iter() - .filter(|&p| p.can_sell_nfts()) - .chunks(3_usize) - .into_iter() - .map(|chunk| chunk.collect()) - .collect(); - - for chunk in pool_chunks { - let mut pool_nfts_to_swap_for: Vec = vec![]; - let mut sender_amount = Uint128::zero(); - - let swaps_per_chunk: u8 = 3; - for pool in &chunk { - let nft_token_ids_res: NftTokenIdsResponse = pool_query_message( - chain, - InfinitySwapQueryMsg::PoolNftTokenIds { - pool_id: pool.id, - query_options: QueryOptions { - descending: None, - start_after: None, - limit: Some(swaps_per_chunk as u32), - }, - }, - ); - - pool_nfts_to_swap_for.push(PoolNftSwap { - pool_id: pool.id, - nft_swaps: nft_token_ids_res - .nft_token_ids - .iter() - .take(swaps_per_chunk as usize) - .map(|token_id| { - let nft_swap = NftSwap { - nft_token_id: token_id.to_string(), - token_amount: Uint128::from(1_000_000u128), - }; - sender_amount += nft_swap.token_amount; - nft_swap - }) - .collect(), - }); - } - - let sim_res: SwapResponse = pool_query_message( - chain, - InfinitySwapQueryMsg::SimSwapTokensForSpecificNfts { - collection: collection.to_string(), - pool_nfts_to_swap_for: pool_nfts_to_swap_for.clone(), - sender: taker_addr.to_string(), - swap_params: SwapParams { - deadline: latest_block_time(&chain.orc).plus_seconds(1_000), - robust: false, - asset_recipient: None, - finder: None, - }, - }, - ); - assert!(!sim_res.swaps.is_empty()); - - let exec_resp = pool_execute_message( - chain, - InfinitySwapExecuteMsg::SwapTokensForSpecificNfts { - collection: collection.to_string(), - pool_nfts_to_swap_for: pool_nfts_to_swap_for.clone(), - swap_params: SwapParams { - deadline: latest_block_time(&chain.orc).plus_seconds(1_000), - robust: false, - asset_recipient: None, - finder: None, - }, - }, - "infinity-swap-swap-tokens-for-specific-nfts", - vec![OrcCoin { - amount: sender_amount.u128(), - denom: denom.parse().unwrap(), - }], - &taker, - ); - - let tags = exec_resp - .res - .find_event_tags("wasm-swap".to_string(), "pool_id".to_string()); - assert!(tags.len() == chunk.len() * swaps_per_chunk as usize); - } -} diff --git a/test/unit/Cargo.toml b/test/unit/Cargo.toml index 0921584..e35aa1f 100644 --- a/test/unit/Cargo.toml +++ b/test/unit/Cargo.toml @@ -6,9 +6,12 @@ repository = { workspace = true } license = { workspace = true } [dependencies] -infinity-swap = { workspace = true } -infinity-marketplace-adapter = { workspace = true } +infinity-pool = { workspace = true } +infinity-index = { workspace = true } +infinity-router = { workspace = true } infinity-shared = { workspace = true } +# infinity-swap = { workspace = true } +# infinity-marketplace-adapter = { workspace = true } cosmwasm-std = { workspace = true } cosmwasm-schema = { workspace = true } cosmwasm-storage = { workspace = true } diff --git a/test/unit/src/helpers/mod.rs b/test/unit/src/helpers/mod.rs index 1a84b86..069f6ba 100644 --- a/test/unit/src/helpers/mod.rs +++ b/test/unit/src/helpers/mod.rs @@ -1,6 +1,7 @@ -pub mod fixtures; +// pub mod fixtures; pub mod marketplace_functions; pub mod nft_functions; -pub mod pool_functions; -pub mod swap_functions; +// pub mod pool_functions; +// pub mod swap_functions; +pub mod tracer_functions; pub mod utils; diff --git a/test/unit/src/helpers/tracer_functions.rs b/test/unit/src/helpers/tracer_functions.rs new file mode 100644 index 0000000..b5deccd --- /dev/null +++ b/test/unit/src/helpers/tracer_functions.rs @@ -0,0 +1,314 @@ +use crate::helpers::nft_functions::validate_nft_owner; +use crate::setup::msg::MarketAccounts; +use crate::setup::setup_accounts::setup_accounts; +use crate::setup::setup_infinity_contracts::{ + contract_infinity_index, contract_infinity_pool, contract_infinity_router, + setup_infinity_index, setup_infinity_router, +}; +use crate::setup::setup_marketplace::setup_marketplace; +use crate::setup::templates::standard_minter_template; + +use anyhow::Error; +use cosmwasm_std::{Addr, BankMsg, Coin, Decimal, Event, Uint128}; +use cw_multi_test::{AppResponse, Executor}; +use infinity_pool::msg::PoolInfo; +use sg721::RoyaltyInfoResponse; +use sg721_base::contract; +use sg_marketplace::msg::ParamsResponse; +use sg_multi_test::StargazeApp; +use sg_std::{GENESIS_MINT_START_TIME, NATIVE_DENOM}; +use std::collections::{HashMap, HashSet}; +use test_suite::common_setup::msg::MinterTemplateResponse; +use test_suite::common_setup::setup_accounts_and_block::setup_block_time; + +pub struct SwapTestSetup { + pub vending_template: MinterTemplateResponse, + pub marketplace: Addr, + pub infinity_index: Addr, + pub infinity_router: Addr, + pub infinity_pool_code_id: u64, +} + +pub fn setup_swap_test(num_tokens: u32) -> Result { + let mut vt = standard_minter_template(num_tokens); + + let marketplace = setup_marketplace(&mut vt.router, vt.accts.creator.clone()).unwrap(); + setup_block_time(&mut vt.router, GENESIS_MINT_START_TIME, None); + + let infinity_pool_code_id = vt.router.store_code(contract_infinity_pool()); + + let infinity_factory = Addr::unchecked("infinity_factory"); + + let infinity_index = + setup_infinity_index(&mut vt.router, &vt.accts.creator, &marketplace, &infinity_factory)?; + let infinity_router = + setup_infinity_router(&mut vt.router, &vt.accts.creator, &marketplace, &infinity_index)?; + + Ok(SwapTestSetup { + marketplace, + vending_template: vt, + infinity_pool_code_id, + infinity_index, + infinity_router, + }) +} + +pub fn create_pool( + router: &mut StargazeApp, + infinity_pool_code_id: u64, + owner: &Addr, + marketplace: String, + infinity_index: String, + pool_info: PoolInfo, + deposit_tokens: Uint128, +) -> Result { + let infinity_pool = router.instantiate_contract( + infinity_pool_code_id, + owner.clone(), + &infinity_pool::msg::InstantiateMsg { + global_gov: marketplace, + infinity_index, + pool_info, + }, + &[], + "InfinityPool", + None, + )?; + + router.execute( + owner.clone(), + cosmwasm_std::CosmosMsg::Bank(BankMsg::Send { + to_address: infinity_pool.to_string(), + amount: vec![Coin { + denom: NATIVE_DENOM.to_string(), + amount: deposit_tokens, + }], + }), + )?; + + router.execute_contract( + owner.clone(), + infinity_pool.clone(), + &infinity_pool::msg::ExecuteMsg::SetIsActive { + is_active: true, + }, + &[], + )?; + + Ok(infinity_pool) +} + +// fn validate_address_paid( +// pre_swap_balances: &HashMap, +// post_swap_balances: &HashMap, +// check_addr: &Addr, +// ) { +// assert!(pre_swap_balances[check_addr].amount < post_swap_balances[check_addr].amount); +// } + +// pub fn validate_swap_fees( +// swap: &Swap, +// pool: &Pool, +// marketplace_params: &ParamsResponse, +// royalty_info: &Option, +// ) { +// assert_eq!(swap.pool_id, pool.id); + +// assert_eq!( +// swap.network_fee, +// swap.spot_price * marketplace_params.params.trading_fee_percent / Uint128::from(100u128), +// ); +// let mut remaining_payment = swap.spot_price - swap.network_fee; + +// if royalty_info.is_none() { +// assert_eq!(swap.royalty_payment, None); +// } else { +// let royalty_info = royalty_info.as_ref().unwrap(); +// if royalty_info.share > Decimal::zero() { +// assert_eq!( +// swap.royalty_payment.as_ref().unwrap().amount, +// swap.spot_price * royalty_info.share, +// ); +// assert_eq!( +// swap.royalty_payment.as_ref().unwrap().address, +// royalty_info.payment_address +// ); +// remaining_payment -= swap.royalty_payment.as_ref().unwrap().amount; +// } else { +// assert_eq!(swap.royalty_payment, None); +// } +// } + +// if pool.finders_fee_percent > Decimal::zero() { +// assert_eq!( +// swap.finder_payment.as_ref().unwrap().amount, +// swap.spot_price * pool.finders_fee_percent / Uint128::from(100u128), +// ); +// remaining_payment -= swap.finder_payment.as_ref().unwrap().amount; +// } else { +// assert_eq!(swap.finder_payment, None); +// } + +// if pool.reinvest_tokens && swap.transaction_type == TransactionType::UserSubmitsTokens { +// assert_eq!(swap.seller_payment, None); +// } else { +// assert_eq!(swap.seller_payment.as_ref().unwrap().amount, remaining_payment); +// } + +// assert!(!swap.nft_payment.nft_token_id.is_empty()); +// } + +// pub fn validate_swap_outcome( +// router: &StargazeApp, +// response: &AppResponse, +// expected_num_swaps: u8, +// pre_swap_balances: &HashMap, +// post_swap_balances: &HashMap, +// pools: &Vec, +// royalty_info: &Option, +// sender: &Addr, +// finder: &Option, +// ) { +// // Test that addresses receive assets +// // Network fee was paid +// response.assert_event(&Event::new("wasm-fair-burn")); + +// let mut num_swaps = 0u8; +// let mut expected_pool_quote_updates = 0u8; +// let mut pool_ids: HashSet = HashSet::new(); + +// let wasm_swap_event = response.events.iter().find(|&e| e.ty == "wasm-swap").unwrap(); + +// let infinity_swap_addr = Addr::unchecked(wasm_swap_event.attributes[0].value.clone()); +// let tx_type = wasm_swap_event +// .attributes +// .iter() +// .find(|&a| a.key == "transaction_type") +// .unwrap() +// .value +// .clone(); + +// for event in response.events.iter() { +// if event.ty == "wasm-swap" { +// num_swaps += 1; + +// let pool_id = event +// .attributes +// .iter() +// .find(|&a| a.key == "pool_id") +// .unwrap() +// .value +// .parse::() +// .unwrap(); + +// let pool = pools.iter().find(|&p| p.id == pool_id).unwrap(); + +// if !pool_ids.contains(&pool_id) { +// expected_pool_quote_updates += 1; +// if pool.pool_type == PoolType::Trade { +// expected_pool_quote_updates += 1; +// } +// pool_ids.insert(pool_id); +// } + +// let token_id = event +// .attributes +// .iter() +// .find(|&a| a.key == "nft_payment_token_id") +// .unwrap() +// .value +// .clone(); + +// // Verify that finder was paid +// if pool.finders_fee_percent > Decimal::zero() && finder.is_some() { +// validate_address_paid( +// pre_swap_balances, +// post_swap_balances, +// finder.as_ref().unwrap(), +// ); +// } + +// if tx_type == "UserSubmitsNfts" { +// // Verify pool owner received NFT +// let pool_owner_account = if pool.pool_type == PoolType::Trade && pool.reinvest_nfts +// { +// infinity_swap_addr.clone() +// } else { +// pool.get_recipient() +// }; +// validate_nft_owner(router, &pool.collection, token_id, &pool_owner_account); + +// // Verify user received tokens +// validate_address_paid(pre_swap_balances, post_swap_balances, sender); +// } else { +// // Verify pool owner received tokens +// let pool_owner_account = +// if pool.pool_type == PoolType::Trade && pool.reinvest_tokens { +// infinity_swap_addr.clone() +// } else { +// pool.get_recipient() +// }; +// validate_address_paid(pre_swap_balances, post_swap_balances, &pool_owner_account); + +// // Verify user received NFT +// validate_nft_owner(router, &pool.collection, token_id, sender); +// } +// } +// } + +// // Verify that swap events are emitted +// assert_eq!(num_swaps, expected_num_swaps); + +// // Verify royalty was paid +// if let Some(_royalty_info) = royalty_info { +// validate_address_paid( +// pre_swap_balances, +// post_swap_balances, +// &Addr::unchecked(&_royalty_info.payment_address), +// ); +// } + +// // Verify that pool state update events are emitted +// let num_pool_updates = +// response.events.iter().filter(|&e| e.ty == "wasm-pool-swap-update").count(); +// assert_eq!(num_pool_updates, pool_ids.len()); + +// // Verify that new pool quotes are generated +// let num_pool_quote_updates = response +// .events +// .iter() +// .filter(|&e| { +// [ +// "wasm-add-buy-pool-quote".to_string(), +// "wasm-remove-buy-pool-quote".to_string(), +// "wasm-add-sell-pool-quote".to_string(), +// "wasm-remove-sell-pool-quote".to_string(), +// ] +// .contains(&e.ty) +// }) +// .count(); +// assert_eq!(num_pool_quote_updates, expected_pool_quote_updates as usize); + +// // Verify that pool state is updated +// let get_pools_msg = QueryMsg::PoolsById { +// pool_ids: pool_ids.clone().into_iter().collect(), +// }; +// let post_swap_pools: PoolsByIdResponse = +// router.wrap().query_wasm_smart(infinity_swap_addr, &get_pools_msg).unwrap(); +// let mut post_swap_pools_map: HashMap = HashMap::new(); +// for (pool_id, pool) in post_swap_pools.pools { +// post_swap_pools_map.insert(pool_id, pool.unwrap()); +// } + +// for pool in pools { +// if !pool_ids.contains(&pool.id) { +// continue; +// } +// let post_swap_pool = post_swap_pools_map.get(&pool.id).unwrap(); +// if tx_type == "UserSubmitsNfts" { +// assert!(pool.spot_price >= post_swap_pool.spot_price) +// } else { +// assert!(pool.spot_price <= post_swap_pool.spot_price) +// } +// } +// } diff --git a/test/unit/src/helpers/utils.rs b/test/unit/src/helpers/utils.rs index e0b563e..85bdf56 100644 --- a/test/unit/src/helpers/utils.rs +++ b/test/unit/src/helpers/utils.rs @@ -1,18 +1,10 @@ use anyhow::Error; use cosmwasm_std::{Addr, Coin}; use cw_multi_test::AppResponse; -use infinity_swap::ContractError; use sg_multi_test::StargazeApp; use sg_std::NATIVE_DENOM; use std::collections::HashMap; -pub fn assert_error(res: Result, expected: ContractError) { - assert_eq!( - res.unwrap_err().source().unwrap().to_string(), - expected.to_string() - ); -} - pub fn get_native_balances(router: &StargazeApp, addresses: &Vec) -> HashMap { let mut balances: HashMap = HashMap::new(); for address in addresses { diff --git a/test/unit/src/infinity_marketplace_adapter_tests/mod.rs b/test/unit/src/infinity_marketplace_adapter_tests/mod.rs deleted file mode 100644 index 775fd01..0000000 --- a/test/unit/src/infinity_marketplace_adapter_tests/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -#[cfg(test)] -mod sim_tests; - -#[cfg(test)] -mod swap_tests; diff --git a/test/unit/src/infinity_marketplace_adapter_tests/sim_tests/mod.rs b/test/unit/src/infinity_marketplace_adapter_tests/sim_tests/mod.rs deleted file mode 100644 index 637214e..0000000 --- a/test/unit/src/infinity_marketplace_adapter_tests/sim_tests/mod.rs +++ /dev/null @@ -1,8 +0,0 @@ -#[cfg(test)] -mod sim_swap_nfts_for_tokens; - -#[cfg(test)] -mod sim_swap_tokens_for_any_nfts; - -#[cfg(test)] -mod sim_swap_tokens_for_specific_nfts; diff --git a/test/unit/src/infinity_marketplace_adapter_tests/sim_tests/sim_swap_nfts_for_tokens.rs b/test/unit/src/infinity_marketplace_adapter_tests/sim_tests/sim_swap_nfts_for_tokens.rs deleted file mode 100644 index f2310e8..0000000 --- a/test/unit/src/infinity_marketplace_adapter_tests/sim_tests/sim_swap_nfts_for_tokens.rs +++ /dev/null @@ -1,206 +0,0 @@ -use crate::helpers::marketplace_functions::{set_bid, set_collection_bid}; -use crate::helpers::nft_functions::mint_and_approve_many; -use crate::helpers::swap_functions::{setup_swap_test, SwapTestSetup}; -use crate::setup::msg::MarketAccounts; -use crate::setup::setup_accounts::{setup_addtl_account, INITIAL_BALANCE}; -use crate::setup::setup_marketplace::MIN_EXPIRY; -use cosmwasm_std::Uint128; -use infinity_marketplace_adapter::msg::QueryMsg as InfinityAdapterQueryMsg; -use infinity_shared::interface::{ - NftOrder, NftPayment, Swap, SwapParams, SwapResponse, TokenPayment, TransactionType, -}; -use sg_marketplace::state::SaleType; -use test_suite::common_setup::msg::MinterTemplateResponse; - -#[test] -fn sim_nft_for_token_marketplace_adapter() { - let SwapTestSetup { - vending_template: - MinterTemplateResponse { - mut router, - accts: - MarketAccounts { - creator, - bidder, - owner, - }, - collection_response_vec, - .. - }, - marketplace, - infinity_marketplace_adapter, - .. - } = setup_swap_test(5000).unwrap(); - - let collection_resp = &collection_response_vec[0]; - let minter = collection_resp.minter.clone().unwrap(); - let collection = collection_resp.collection.clone().unwrap(); - let block_time = router.block_info().time; - - let owner_token_ids = mint_and_approve_many( - &mut router, - &creator, - &owner, - &minter, - &collection, - &infinity_marketplace_adapter, - 5, - ); - - /* - Testing Bid Matching - * Test CollectionBids are taken when no Bid is found - * Test Bids are taken when greater than or equal to CollectionBid - * Test CollectionBids are taken when greater than Bid - * Test Bids are taken when no CollectionBid is found - * Test Bids are not accepted when below NftOrder - - Bids - bid_0: token_id_0, None - bid_1: token_id_1, 1002 STARS - bid_2: token_id_2, 999 STARS - bid_3: token_id_3, 998 STARS - bid_3: token_id_4, 997 STARS - - Collection Bids - collection_bid_0: 1001 STARS - collection_bid_1: 1000 STARS - - Match Order - token_id_0: collection_bid_0 - token_id_1: bid_1 - token_id_2: collection_bid_1 - token_id_3: bid_3 - token_id_4: None - */ - - // Setup Bids - let expires = block_time.plus_seconds(MIN_EXPIRY + 1); - for (idx, token_id) in owner_token_ids.iter().enumerate() { - let bid_amount = match idx { - 0 => None, - 1 => Some(1002u128), - 2 => Some(999u128), - 3 => Some(998u128), - 4 => Some(997u128), - _ => unreachable!(), - }; - if let Some(_bid_amount) = bid_amount { - set_bid( - &mut router, - marketplace.clone(), - bidder.clone(), - _bid_amount, - collection.to_string(), - token_id.parse::().unwrap(), - expires, - SaleType::FixedPrice, - None, - None, - ); - } - } - - // Setup CollectionBids - let collection_bidder_0 = - setup_addtl_account(&mut router, "collection_bidder_0", INITIAL_BALANCE).unwrap(); - set_collection_bid( - &mut router, - marketplace.clone(), - collection_bidder_0.clone(), - collection.to_string(), - expires, - None, - 1001u128, - ); - let collection_bidder_1 = - setup_addtl_account(&mut router, "collection_bidder_1", INITIAL_BALANCE).unwrap(); - set_collection_bid( - &mut router, - marketplace.clone(), - collection_bidder_1.clone(), - collection.to_string(), - expires, - None, - 1000u128, - ); - - let sim_msg = InfinityAdapterQueryMsg::SimSwapNftsForTokens { - sender: owner.to_string(), - collection: collection.to_string(), - nft_orders: owner_token_ids - .iter() - .map(|token_id| NftOrder { - token_id: token_id.to_string(), - amount: Uint128::from(998u128), - }) - .collect(), - swap_params: SwapParams { - deadline: expires, - robust: true, - asset_recipient: None, - finder: None, - }, - }; - let response: SwapResponse = router - .wrap() - .query_wasm_smart(infinity_marketplace_adapter.clone(), &sim_msg) - .unwrap(); - - assert_eq!(response.swaps.len(), 4); - - let swap_0 = response.swaps[0].clone(); - assert_eq!( - swap_0, - Swap { - source: marketplace.to_string(), - transaction_type: TransactionType::UserSubmitsNfts, - sale_price: Uint128::from(1001u128), - network_fee: Uint128::from(20u128), - nft_payments: vec![NftPayment { - label: "buyer".to_string(), - token_id: owner_token_ids[0].to_string(), - address: collection_bidder_0.to_string() - }], - token_payments: vec![ - TokenPayment { - label: "royalty".to_string(), - amount: Uint128::from(100u128), - address: creator.to_string() - }, - TokenPayment { - label: "seller".to_string(), - amount: Uint128::from(881u128), - address: owner.to_string() - }, - ] - } - ); - - let swap_1 = response.swaps[1].clone(); - assert_eq!(swap_1.sale_price, Uint128::from(1002u128)); - assert_eq!( - swap_1.nft_payments[0].token_id, - owner_token_ids[1].to_string() - ); - assert_eq!(swap_1.nft_payments[0].address, bidder.to_string()); - - let swap_2 = response.swaps[2].clone(); - assert_eq!(swap_2.sale_price, Uint128::from(1000u128)); - assert_eq!( - swap_2.nft_payments[0].token_id, - owner_token_ids[2].to_string() - ); - assert_eq!( - swap_2.nft_payments[0].address, - collection_bidder_1.to_string() - ); - - let swap_3 = response.swaps[3].clone(); - assert_eq!(swap_3.sale_price, Uint128::from(998u128)); - assert_eq!( - swap_3.nft_payments[0].token_id, - owner_token_ids[3].to_string() - ); - assert_eq!(swap_3.nft_payments[0].address, bidder.to_string()); -} diff --git a/test/unit/src/infinity_marketplace_adapter_tests/sim_tests/sim_swap_tokens_for_any_nfts.rs b/test/unit/src/infinity_marketplace_adapter_tests/sim_tests/sim_swap_tokens_for_any_nfts.rs deleted file mode 100644 index 2acca31..0000000 --- a/test/unit/src/infinity_marketplace_adapter_tests/sim_tests/sim_swap_tokens_for_any_nfts.rs +++ /dev/null @@ -1,172 +0,0 @@ -use crate::helpers::marketplace_functions::set_ask; -use crate::helpers::nft_functions::{approve, mint_and_approve_many}; -use crate::helpers::swap_functions::{setup_swap_test, SwapTestSetup}; -use crate::setup::msg::MarketAccounts; -use crate::setup::setup_marketplace::MIN_EXPIRY; -use cosmwasm_std::Uint128; -use infinity_marketplace_adapter::msg::QueryMsg as InfinityAdapterQueryMsg; -use infinity_shared::interface::{ - NftPayment, Swap, SwapParams, SwapResponse, TokenPayment, TransactionType, -}; -use sg_marketplace::state::SaleType; -use test_suite::common_setup::msg::MinterTemplateResponse; - -#[test] -fn sim_token_for_any_nfts_marketplace_adapter() { - let SwapTestSetup { - vending_template: - MinterTemplateResponse { - mut router, - accts: - MarketAccounts { - creator, - bidder, - owner, - }, - collection_response_vec, - .. - }, - marketplace, - infinity_marketplace_adapter, - .. - } = setup_swap_test(5000).unwrap(); - - let collection_resp = &collection_response_vec[0]; - let minter = collection_resp.minter.clone().unwrap(); - let collection = collection_resp.collection.clone().unwrap(); - let block_time = router.block_info().time; - - let owner_token_ids = mint_and_approve_many( - &mut router, - &creator, - &owner, - &minter, - &collection, - &marketplace, - 4, - ); - - /* - Test Ask Matching: - * Test that only Asks below or equal to the desired price are taken - * Test that they are taken in the order of price ascending - * Test that multiple orders can be filled - - Asks - ask_0: token_id_0, 999 STARS - ask_1: token_id_1, 1001 STARS - ask_2: token_id_2, None - ask_3: token_id_3, 1000 STARS - - Match Order - token_id_0: ask_0 - token_id_3: ask_3 - */ - - // Setup Asks - let expires = block_time.plus_seconds(MIN_EXPIRY + 1); - for (idx, token_id) in owner_token_ids.iter().enumerate() { - let token_id: u32 = token_id.parse().unwrap(); - approve(&mut router, &owner, &collection, &marketplace, token_id); - - let ask_amount = match idx { - 0 => Some(999u128), - 1 => Some(1001u128), - 2 => None, - 3 => Some(1000u128), - _ => unreachable!(), - }; - if let Some(_ask_amount) = ask_amount { - set_ask( - &mut router, - marketplace.clone(), - owner.clone(), - _ask_amount, - collection.to_string(), - token_id, - expires, - SaleType::FixedPrice, - None, - None, - None, - ); - } - } - - let sim_msg = InfinityAdapterQueryMsg::SimSwapTokensForAnyNfts { - sender: bidder.to_string(), - collection: collection.to_string(), - nft_orders: owner_token_ids - .iter() - .map(|_| Uint128::from(1000u128)) - .collect(), - swap_params: SwapParams { - deadline: expires, - robust: true, - asset_recipient: None, - finder: None, - }, - }; - let swap_response: SwapResponse = router - .wrap() - .query_wasm_smart(infinity_marketplace_adapter, &sim_msg) - .unwrap(); - - assert_eq!(swap_response.swaps.len(), 2); - - let swap_0 = swap_response.swaps[0].clone(); - assert_eq!( - swap_0, - Swap { - source: marketplace.to_string(), - transaction_type: TransactionType::UserSubmitsTokens, - sale_price: Uint128::from(999u128), - network_fee: Uint128::from(19u128), - nft_payments: vec![NftPayment { - label: "buyer".to_string(), - token_id: owner_token_ids[0].to_string(), - address: bidder.to_string() - }], - token_payments: vec![ - TokenPayment { - label: "royalty".to_string(), - amount: Uint128::from(99u128), - address: creator.to_string() - }, - TokenPayment { - label: "seller".to_string(), - amount: Uint128::from(881u128), - address: owner.to_string() - } - ] - } - ); - - let swap_1 = swap_response.swaps[1].clone(); - assert_eq!( - swap_1, - Swap { - source: marketplace.to_string(), - transaction_type: TransactionType::UserSubmitsTokens, - sale_price: Uint128::from(1000u128), - network_fee: Uint128::from(20u128), - nft_payments: vec![NftPayment { - label: "buyer".to_string(), - token_id: owner_token_ids[3].to_string(), - address: bidder.to_string() - }], - token_payments: vec![ - TokenPayment { - label: "royalty".to_string(), - amount: Uint128::from(100u128), - address: creator.to_string() - }, - TokenPayment { - label: "seller".to_string(), - amount: Uint128::from(880u128), - address: owner.to_string() - } - ] - } - ); -} diff --git a/test/unit/src/infinity_marketplace_adapter_tests/sim_tests/sim_swap_tokens_for_specific_nfts.rs b/test/unit/src/infinity_marketplace_adapter_tests/sim_tests/sim_swap_tokens_for_specific_nfts.rs deleted file mode 100644 index 82e8bd6..0000000 --- a/test/unit/src/infinity_marketplace_adapter_tests/sim_tests/sim_swap_tokens_for_specific_nfts.rs +++ /dev/null @@ -1,178 +0,0 @@ -use crate::helpers::marketplace_functions::set_ask; -use crate::helpers::nft_functions::{approve, mint_and_approve_many}; -use crate::helpers::swap_functions::{setup_swap_test, SwapTestSetup}; -use crate::setup::msg::MarketAccounts; -use crate::setup::setup_marketplace::MIN_EXPIRY; -use cosmwasm_std::Uint128; -use infinity_marketplace_adapter::msg::QueryMsg as InfinityAdapterQueryMsg; -use infinity_shared::interface::{ - NftOrder, NftPayment, Swap, SwapParams, SwapResponse, TokenPayment, TransactionType, -}; -use sg_marketplace::state::SaleType; -use test_suite::common_setup::msg::MinterTemplateResponse; - -#[test] -fn sim_token_for_specific_nfts_marketplace_adapter() { - let SwapTestSetup { - vending_template: - MinterTemplateResponse { - mut router, - accts: - MarketAccounts { - creator, - bidder, - owner, - }, - collection_response_vec, - .. - }, - marketplace, - infinity_marketplace_adapter, - .. - } = setup_swap_test(5000).unwrap(); - - let collection_resp = &collection_response_vec[0]; - let minter = collection_resp.minter.clone().unwrap(); - let collection = collection_resp.collection.clone().unwrap(); - let block_time = router.block_info().time; - - let owner_token_ids = mint_and_approve_many( - &mut router, - &creator, - &owner, - &minter, - &collection, - &marketplace, - 4, - ); - - /* - Test Ask Matching: - * Test that the Ask is taken when price is below or equal to order amount - * Test that the Ask is not taken when price is above order amount - * Test when there are no Asks found - * Test that multiple orders can be filled - - Asks - ask_0: token_id_0, 999 STARS - ask_1: token_id_1, 1001 STARS - ask_2: token_id_2, None - ask_3: token_id_3, 1000 STARS - - Match Order - token_id_0: ask_0 - token_id_1: None - token_id_2: None - token_id_3: ask_3 - */ - - // Setup Asks - let expires = block_time.plus_seconds(MIN_EXPIRY + 1); - for (idx, token_id) in owner_token_ids.iter().enumerate() { - let token_id: u32 = token_id.parse().unwrap(); - approve(&mut router, &owner, &collection, &marketplace, token_id); - - let ask_amount = match idx { - 0 => Some(999u128), - 1 => Some(1001u128), - 2 => None, - 3 => Some(1000u128), - _ => unreachable!(), - }; - if let Some(_ask_amount) = ask_amount { - set_ask( - &mut router, - marketplace.clone(), - owner.clone(), - _ask_amount, - collection.to_string(), - token_id, - expires, - SaleType::FixedPrice, - None, - None, - None, - ); - } - } - - let sim_msg = InfinityAdapterQueryMsg::SimSwapTokensForSpecificNfts { - sender: bidder.to_string(), - collection: collection.to_string(), - nft_orders: owner_token_ids - .iter() - .map(|token_id| NftOrder { - token_id: token_id.to_string(), - amount: Uint128::from(1000u128), - }) - .collect(), - swap_params: SwapParams { - deadline: expires, - robust: true, - asset_recipient: None, - finder: None, - }, - }; - let swap_response: SwapResponse = router - .wrap() - .query_wasm_smart(infinity_marketplace_adapter, &sim_msg) - .unwrap(); - - assert_eq!(swap_response.swaps.len(), 2); - - let swap_0 = swap_response.swaps[0].clone(); - assert_eq!( - swap_0, - Swap { - source: marketplace.to_string(), - transaction_type: TransactionType::UserSubmitsTokens, - sale_price: Uint128::from(999u128), - network_fee: Uint128::from(19u128), - nft_payments: vec![NftPayment { - label: "buyer".to_string(), - token_id: owner_token_ids[0].to_string(), - address: bidder.to_string() - }], - token_payments: vec![ - TokenPayment { - label: "royalty".to_string(), - amount: Uint128::from(99u128), - address: creator.to_string() - }, - TokenPayment { - label: "seller".to_string(), - amount: Uint128::from(881u128), - address: owner.to_string() - } - ] - } - ); - - let swap_1 = swap_response.swaps[1].clone(); - assert_eq!( - swap_1, - Swap { - source: marketplace.to_string(), - transaction_type: TransactionType::UserSubmitsTokens, - sale_price: Uint128::from(1000u128), - network_fee: Uint128::from(20u128), - nft_payments: vec![NftPayment { - label: "buyer".to_string(), - token_id: owner_token_ids[3].to_string(), - address: bidder.to_string() - }], - token_payments: vec![ - TokenPayment { - label: "royalty".to_string(), - amount: Uint128::from(100u128), - address: creator.to_string() - }, - TokenPayment { - label: "seller".to_string(), - amount: Uint128::from(880u128), - address: owner.to_string() - } - ] - } - ); -} diff --git a/test/unit/src/infinity_marketplace_adapter_tests/swap_tests/mod.rs b/test/unit/src/infinity_marketplace_adapter_tests/swap_tests/mod.rs deleted file mode 100644 index 98aa164..0000000 --- a/test/unit/src/infinity_marketplace_adapter_tests/swap_tests/mod.rs +++ /dev/null @@ -1,8 +0,0 @@ -#[cfg(test)] -mod swap_nfts_for_tokens; - -#[cfg(test)] -mod swap_tokens_for_any_nfts; - -#[cfg(test)] -mod swap_tokens_for_specific_nfts; diff --git a/test/unit/src/infinity_marketplace_adapter_tests/swap_tests/swap_nfts_for_tokens.rs b/test/unit/src/infinity_marketplace_adapter_tests/swap_tests/swap_nfts_for_tokens.rs deleted file mode 100644 index 0dec742..0000000 --- a/test/unit/src/infinity_marketplace_adapter_tests/swap_tests/swap_nfts_for_tokens.rs +++ /dev/null @@ -1,293 +0,0 @@ -use crate::helpers::marketplace_functions::{set_bid, set_collection_bid}; -use crate::helpers::nft_functions::{mint_and_approve_many, validate_nft_owner}; -use crate::helpers::swap_functions::{setup_swap_test, SwapTestSetup}; -use crate::setup::msg::MarketAccounts; -use crate::setup::setup_accounts::{setup_addtl_account, INITIAL_BALANCE}; -use crate::setup::setup_marketplace::MIN_EXPIRY; -use cosmwasm_std::{Addr, Uint128}; -use cw_multi_test::Executor; -use infinity_marketplace_adapter::msg::{ - ExecuteMsg as InfinityAdapterExecuteMsg, QueryMsg as InfinityAdapterQueryMsg, -}; -use infinity_shared::interface::{NftOrder, SwapParams, SwapResponse}; -use sg_marketplace::state::SaleType; -use sg_std::NATIVE_DENOM; -use test_suite::common_setup::msg::MinterTemplateResponse; - -#[test] -fn swap_nft_for_token_marketplace_adapter() { - let SwapTestSetup { - vending_template: - MinterTemplateResponse { - mut router, - accts: - MarketAccounts { - creator, - bidder, - owner, - }, - collection_response_vec, - .. - }, - marketplace, - infinity_marketplace_adapter, - .. - } = setup_swap_test(5000).unwrap(); - - let collection_resp = &collection_response_vec[0]; - let minter = collection_resp.minter.clone().unwrap(); - let collection = collection_resp.collection.clone().unwrap(); - let block_time = router.block_info().time; - - let finder = setup_addtl_account(&mut router, "finder", INITIAL_BALANCE).unwrap(); - - let owner_token_ids = mint_and_approve_many( - &mut router, - &creator, - &owner, - &minter, - &collection, - &infinity_marketplace_adapter, - 5, - ); - - /* - Testing Bid Matching - * Test CollectionBids are taken when no Bid is found - * Test Bids are taken when greater than or equal to CollectionBid - * Test CollectionBids are taken when greater than Bid - * Test Bids are taken when no CollectionBid is found - * Test Bids are not accepted when below NftOrder - - Bids - bid_0: token_id_0, None - bid_1: token_id_1, 1002 STARS - bid_2: token_id_2, 999 STARS - bid_3: token_id_3, 998 STARS - bid_3: token_id_4, 997 STARS - - Collection Bids - collection_bid_0: 1001 STARS - collection_bid_1: 1000 STARS - - Match Order - token_id_0: collection_bid_0 - token_id_1: bid_1 - token_id_2: collection_bid_1 - token_id_3: bid_3 - token_id_4: None - */ - - // Setup Bids - let expires = block_time.plus_seconds(MIN_EXPIRY + 1); - for (idx, token_id) in owner_token_ids.iter().enumerate() { - let bid_amount = match idx { - 0 => None, - 1 => Some(1002u128), - 2 => Some(999u128), - 3 => Some(998u128), - 4 => Some(997u128), - _ => unreachable!(), - }; - if let Some(_bid_amount) = bid_amount { - set_bid( - &mut router, - marketplace.clone(), - bidder.clone(), - _bid_amount, - collection.to_string(), - token_id.parse::().unwrap(), - expires, - SaleType::FixedPrice, - None, - Some(250), - ); - } - } - - // Setup CollectionBids - let collection_bidder_0 = - setup_addtl_account(&mut router, "collection_bidder_0", INITIAL_BALANCE).unwrap(); - set_collection_bid( - &mut router, - marketplace.clone(), - collection_bidder_0, - collection.to_string(), - expires, - Some(250), - 1001u128, - ); - let collection_bidder_1 = - setup_addtl_account(&mut router, "collection_bidder_1", INITIAL_BALANCE).unwrap(); - set_collection_bid( - &mut router, - marketplace, - collection_bidder_1, - collection.to_string(), - expires, - Some(250), - 1000u128, - ); - - let sim_msg = InfinityAdapterQueryMsg::SimSwapNftsForTokens { - sender: owner.to_string(), - collection: collection.to_string(), - nft_orders: owner_token_ids - .iter() - .map(|token_id| NftOrder { - token_id: token_id.to_string(), - amount: Uint128::from(998u128), - }) - .collect(), - swap_params: SwapParams { - deadline: expires, - robust: true, - asset_recipient: None, - finder: Some(finder.to_string()), - }, - }; - let sim_response: SwapResponse = router - .wrap() - .query_wasm_smart(&infinity_marketplace_adapter, &sim_msg) - .unwrap(); - assert_eq!(sim_response.swaps.len(), 4); - - let exec_msg = InfinityAdapterExecuteMsg::SwapNftsForTokens { - collection: collection.to_string(), - nft_orders: owner_token_ids - .iter() - .map(|token_id| NftOrder { - token_id: token_id.to_string(), - amount: Uint128::from(998u128), - }) - .collect(), - swap_params: SwapParams { - deadline: expires, - robust: true, - asset_recipient: None, - finder: Some(finder.to_string()), - }, - }; - let exec_res = router - .execute_contract(owner.clone(), infinity_marketplace_adapter, &exec_msg, &[]) - .unwrap(); - - // Account for 4 swaps - // ------------------- - - // Verify burn amount - let sim_burn_amount = sim_response - .swaps - .iter() - .fold(Uint128::zero(), |acc, swap| acc + swap.network_fee); - - let actual_burn_amount = exec_res - .events - .iter() - .filter(|&event| event.ty == "wasm-fair-burn") - .fold(Uint128::zero(), |acc, event| { - let burn_amount = event - .attributes - .iter() - .find(|attr| attr.key == "burn_amount") - .unwrap() - .value - .parse::() - .unwrap(); - let dist_amount = event - .attributes - .iter() - .find(|attr| attr.key == "dist_amount") - .unwrap() - .value - .parse::() - .unwrap(); - acc + Uint128::from(burn_amount + dist_amount) - }); - assert_eq!(sim_burn_amount, actual_burn_amount); - - // Verify royalties paid - let sim_royalty_amount = sim_response - .swaps - .iter() - .fold(Uint128::zero(), |acc, swap| { - let royalty_payment = swap - .token_payments - .iter() - .find(|&payment| payment.label == "royalty") - .unwrap() - .amount; - acc + royalty_payment - }); - - let actual_royalty_amount = exec_res - .events - .iter() - .filter(|&event| event.ty == "wasm-royalty-payout") - .fold(Uint128::zero(), |acc, event| { - let amount = event - .attributes - .iter() - .find(|attr| attr.key == "amount") - .unwrap() - .value - .parse::() - .unwrap(); - acc + Uint128::from(amount) - }); - assert_eq!(sim_royalty_amount, actual_royalty_amount); - - // Verify finders paid - let sim_finder_amount = sim_response - .swaps - .iter() - .fold(Uint128::zero(), |acc, swap| { - let finder_payment = swap - .token_payments - .iter() - .find(|&payment| payment.label == "finder") - .unwrap() - .amount; - acc + finder_payment - }); - - let actual_finder_amount = router - .wrap() - .query_balance(&finder, NATIVE_DENOM) - .unwrap() - .amount - - Uint128::from(INITIAL_BALANCE); - assert_eq!(sim_finder_amount, actual_finder_amount); - - // Verify that seller was paid - let sim_seller_amount = sim_response - .swaps - .iter() - .fold(Uint128::zero(), |acc, swap| { - let seller_payment = swap - .token_payments - .iter() - .find(|&payment| payment.label == "seller") - .unwrap() - .amount; - acc + seller_payment - }); - let actual_seller_amount = router - .wrap() - .query_balance(&owner, NATIVE_DENOM) - .unwrap() - .amount - - Uint128::from(INITIAL_BALANCE); - assert_eq!(sim_seller_amount, actual_seller_amount); - - // Verify that bidders received their NFTs - for swap in sim_response.swaps { - let nft_recipient = swap.nft_payments[0].address.clone(); - validate_nft_owner( - &router, - &collection, - swap.nft_payments[0].token_id.clone(), - &Addr::unchecked(nft_recipient), - ); - } -} diff --git a/test/unit/src/infinity_marketplace_adapter_tests/swap_tests/swap_tokens_for_any_nfts.rs b/test/unit/src/infinity_marketplace_adapter_tests/swap_tests/swap_tokens_for_any_nfts.rs deleted file mode 100644 index eff0eed..0000000 --- a/test/unit/src/infinity_marketplace_adapter_tests/swap_tests/swap_tokens_for_any_nfts.rs +++ /dev/null @@ -1,268 +0,0 @@ -use crate::helpers::marketplace_functions::set_ask; -use crate::helpers::nft_functions::{approve, mint_and_approve_many, validate_nft_owner}; -use crate::helpers::swap_functions::{setup_swap_test, SwapTestSetup}; -use crate::setup::msg::MarketAccounts; -use crate::setup::setup_accounts::{setup_addtl_account, INITIAL_BALANCE}; -use crate::setup::setup_marketplace::MIN_EXPIRY; -use cosmwasm_std::{coins, Uint128}; -use cw_multi_test::Executor; -use infinity_marketplace_adapter::msg::{ - ExecuteMsg as InfinityAdapterExecuteMsg, QueryMsg as InfinityAdapterQueryMsg, -}; -use infinity_shared::interface::{SwapParams, SwapResponse}; -use sg_marketplace::state::SaleType; -use sg_std::NATIVE_DENOM; -use test_suite::common_setup::msg::MinterTemplateResponse; - -#[test] -fn swap_token_for_any_nfts_marketplace_adapter() { - let SwapTestSetup { - vending_template: - MinterTemplateResponse { - mut router, - accts: - MarketAccounts { - creator, - bidder, - owner, - }, - collection_response_vec, - .. - }, - marketplace, - infinity_marketplace_adapter, - .. - } = setup_swap_test(5000).unwrap(); - - let collection_resp = &collection_response_vec[0]; - let minter = collection_resp.minter.clone().unwrap(); - let collection = collection_resp.collection.clone().unwrap(); - let block_time = router.block_info().time; - - let finder = setup_addtl_account(&mut router, "finder", INITIAL_BALANCE).unwrap(); - - let owner_token_ids = mint_and_approve_many( - &mut router, - &creator, - &owner, - &minter, - &collection, - &marketplace, - 4, - ); - - /* - Test Ask Matching: - * Test that only Asks below or equal to the desired price are taken - * Test that they are taken in the order of price ascending - * Test that multiple orders can be filled - - Asks - ask_0: token_id_0, 999 STARS - ask_1: token_id_1, 1001 STARS - ask_2: token_id_2, None - ask_3: token_id_3, 1000 STARS - - Match Order - token_id_0: ask_0 - token_id_3: ask_3 - */ - - // Setup Asks - let expires = block_time.plus_seconds(MIN_EXPIRY + 1); - for (idx, token_id) in owner_token_ids.iter().enumerate() { - let token_id: u32 = token_id.parse().unwrap(); - approve(&mut router, &owner, &collection, &marketplace, token_id); - - let ask_amount = match idx { - 0 => Some(999u128), - 1 => Some(1001u128), - 2 => None, - 3 => Some(1000u128), - _ => unreachable!(), - }; - if let Some(_ask_amount) = ask_amount { - set_ask( - &mut router, - marketplace.clone(), - owner.clone(), - _ask_amount, - collection.to_string(), - token_id, - expires, - SaleType::FixedPrice, - Some(250), - None, - None, - ); - } - } - let seller_balance = router - .wrap() - .query_balance(&owner, NATIVE_DENOM) - .unwrap() - .amount; - - let nft_orders: Vec = owner_token_ids - .iter() - .map(|_| Uint128::from(1000u128)) - .collect(); - let fund_amount = nft_orders - .iter() - .fold(Uint128::zero(), |acc, order| acc + order); - - let sim_msg = InfinityAdapterQueryMsg::SimSwapTokensForAnyNfts { - sender: bidder.to_string(), - collection: collection.to_string(), - nft_orders: nft_orders.clone(), - swap_params: SwapParams { - deadline: expires, - robust: true, - asset_recipient: None, - finder: Some(finder.to_string()), - }, - }; - let sim_response: SwapResponse = router - .wrap() - .query_wasm_smart(infinity_marketplace_adapter.clone(), &sim_msg) - .unwrap(); - - assert_eq!(sim_response.swaps.len(), 2); - - let exec_msg = InfinityAdapterExecuteMsg::SwapTokensForAnyNfts { - collection: collection.to_string(), - nft_orders, - swap_params: SwapParams { - deadline: expires, - robust: true, - asset_recipient: None, - finder: Some(finder.to_string()), - }, - }; - let exec_res = router - .execute_contract( - bidder.clone(), - infinity_marketplace_adapter, - &exec_msg, - &coins(fund_amount.u128(), NATIVE_DENOM), - ) - .unwrap(); - - // Account for 2 swaps - // ------------------- - - // Verify burn amount - let sim_burn_amount = sim_response - .swaps - .iter() - .fold(Uint128::zero(), |acc, swap| acc + swap.network_fee); - - let actual_burn_amount = exec_res - .events - .iter() - .filter(|&event| event.ty == "wasm-fair-burn") - .fold(Uint128::zero(), |acc, event| { - let burn_amount = event - .attributes - .iter() - .find(|attr| attr.key == "burn_amount") - .unwrap() - .value - .parse::() - .unwrap(); - let dist_amount = event - .attributes - .iter() - .find(|attr| attr.key == "dist_amount") - .unwrap() - .value - .parse::() - .unwrap(); - acc + Uint128::from(burn_amount + dist_amount) - }); - assert_eq!(sim_burn_amount, actual_burn_amount); - - // Verify royalties paid - let sim_royalty_amount = sim_response - .swaps - .iter() - .fold(Uint128::zero(), |acc, swap| { - let royalty_payment = swap - .token_payments - .iter() - .find(|&payment| payment.label == "royalty") - .unwrap() - .amount; - acc + royalty_payment - }); - - let actual_royalty_amount = exec_res - .events - .iter() - .filter(|&event| event.ty == "wasm-royalty-payout") - .fold(Uint128::zero(), |acc, event| { - let amount = event - .attributes - .iter() - .find(|attr| attr.key == "amount") - .unwrap() - .value - .parse::() - .unwrap(); - acc + Uint128::from(amount) - }); - assert_eq!(sim_royalty_amount, actual_royalty_amount); - - // Verify finders paid - let sim_finder_amount = sim_response - .swaps - .iter() - .fold(Uint128::zero(), |acc, swap| { - let finder_payment = swap - .token_payments - .iter() - .find(|&payment| payment.label == "finder") - .unwrap() - .amount; - acc + finder_payment - }); - - let actual_finder_amount = router - .wrap() - .query_balance(&finder, NATIVE_DENOM) - .unwrap() - .amount - - Uint128::from(INITIAL_BALANCE); - assert_eq!(sim_finder_amount, actual_finder_amount); - - // Verify that seller was paid - let sim_seller_amount = sim_response - .swaps - .iter() - .fold(Uint128::zero(), |acc, swap| { - let seller_payment = swap - .token_payments - .iter() - .find(|&payment| payment.label == "seller") - .unwrap() - .amount; - acc + seller_payment - }); - let actual_seller_amount = router - .wrap() - .query_balance(&owner, NATIVE_DENOM) - .unwrap() - .amount - - seller_balance; - assert_eq!(sim_seller_amount, actual_seller_amount); - - // Verify that bidders received their NFTs - for swap in sim_response.swaps { - validate_nft_owner( - &router, - &collection, - swap.nft_payments[0].token_id.clone(), - &bidder, - ); - } -} diff --git a/test/unit/src/infinity_marketplace_adapter_tests/swap_tests/swap_tokens_for_specific_nfts.rs b/test/unit/src/infinity_marketplace_adapter_tests/swap_tests/swap_tokens_for_specific_nfts.rs deleted file mode 100644 index 9b50e1e..0000000 --- a/test/unit/src/infinity_marketplace_adapter_tests/swap_tests/swap_tokens_for_specific_nfts.rs +++ /dev/null @@ -1,274 +0,0 @@ -use crate::helpers::marketplace_functions::set_ask; -use crate::helpers::nft_functions::{approve, mint_and_approve_many, validate_nft_owner}; -use crate::helpers::swap_functions::{setup_swap_test, SwapTestSetup}; -use crate::setup::msg::MarketAccounts; -use crate::setup::setup_accounts::{setup_addtl_account, INITIAL_BALANCE}; -use crate::setup::setup_marketplace::MIN_EXPIRY; -use cosmwasm_std::{coins, Uint128}; -use cw_multi_test::Executor; -use infinity_marketplace_adapter::msg::{ - ExecuteMsg as InfinityAdapterExecuteMsg, QueryMsg as InfinityAdapterQueryMsg, -}; -use infinity_shared::interface::{NftOrder, SwapParams, SwapResponse}; -use sg_marketplace::state::SaleType; -use sg_std::NATIVE_DENOM; -use test_suite::common_setup::msg::MinterTemplateResponse; - -#[test] -fn swap_token_for_specific_nfts_marketplace_adapter() { - let SwapTestSetup { - vending_template: - MinterTemplateResponse { - mut router, - accts: - MarketAccounts { - creator, - bidder, - owner, - }, - collection_response_vec, - .. - }, - marketplace, - infinity_marketplace_adapter, - .. - } = setup_swap_test(5000).unwrap(); - - let collection_resp = &collection_response_vec[0]; - let minter = collection_resp.minter.clone().unwrap(); - let collection = collection_resp.collection.clone().unwrap(); - let block_time = router.block_info().time; - - let finder = setup_addtl_account(&mut router, "finder", INITIAL_BALANCE).unwrap(); - - let owner_token_ids = mint_and_approve_many( - &mut router, - &creator, - &owner, - &minter, - &collection, - &marketplace, - 4, - ); - - /* - Test Ask Matching: - * Test that the Ask is taken when price is below or equal to order amount - * Test that the Ask is not taken when price is above order amount - * Test when there are no Asks found - * Test that multiple orders can be filled - - Asks - ask_0: token_id_0, 999 STARS - ask_1: token_id_1, 1001 STARS - ask_2: token_id_2, None - ask_3: token_id_3, 1000 STARS - - Match Order - token_id_0: ask_0 - token_id_1: None - token_id_2: None - token_id_3: ask_3 - */ - - // Setup Asks - let expires = block_time.plus_seconds(MIN_EXPIRY + 1); - for (idx, token_id) in owner_token_ids.iter().enumerate() { - let token_id: u32 = token_id.parse().unwrap(); - approve(&mut router, &owner, &collection, &marketplace, token_id); - - let ask_amount = match idx { - 0 => Some(999u128), - 1 => Some(1001u128), - 2 => None, - 3 => Some(1000u128), - _ => unreachable!(), - }; - if let Some(_ask_amount) = ask_amount { - set_ask( - &mut router, - marketplace.clone(), - owner.clone(), - _ask_amount, - collection.to_string(), - token_id, - expires, - SaleType::FixedPrice, - Some(250), - None, - None, - ); - } - } - let seller_balance = router - .wrap() - .query_balance(&owner, NATIVE_DENOM) - .unwrap() - .amount; - - let nft_orders: Vec = owner_token_ids - .iter() - .map(|token_id| NftOrder { - token_id: token_id.to_string(), - amount: Uint128::from(1000u128), - }) - .collect(); - let fund_amount = nft_orders - .iter() - .fold(Uint128::zero(), |acc, order| acc + order.amount); - - let sim_msg = InfinityAdapterQueryMsg::SimSwapTokensForSpecificNfts { - sender: bidder.to_string(), - collection: collection.to_string(), - nft_orders: nft_orders.clone(), - swap_params: SwapParams { - deadline: expires, - robust: true, - asset_recipient: None, - finder: Some(finder.to_string()), - }, - }; - let sim_response: SwapResponse = router - .wrap() - .query_wasm_smart(infinity_marketplace_adapter.clone(), &sim_msg) - .unwrap(); - - assert_eq!(sim_response.swaps.len(), 2); - - let exec_msg = InfinityAdapterExecuteMsg::SwapTokensForSpecificNfts { - collection: collection.to_string(), - nft_orders, - swap_params: SwapParams { - deadline: expires, - robust: true, - asset_recipient: None, - finder: Some(finder.to_string()), - }, - }; - let exec_res = router - .execute_contract( - bidder.clone(), - infinity_marketplace_adapter, - &exec_msg, - &coins(fund_amount.u128(), NATIVE_DENOM), - ) - .unwrap(); - - // Account for 2 swaps - // ------------------- - - // Verify burn amount - let sim_burn_amount = sim_response - .swaps - .iter() - .fold(Uint128::zero(), |acc, swap| acc + swap.network_fee); - - let actual_burn_amount = exec_res - .events - .iter() - .filter(|&event| event.ty == "wasm-fair-burn") - .fold(Uint128::zero(), |acc, event| { - let burn_amount = event - .attributes - .iter() - .find(|attr| attr.key == "burn_amount") - .unwrap() - .value - .parse::() - .unwrap(); - let dist_amount = event - .attributes - .iter() - .find(|attr| attr.key == "dist_amount") - .unwrap() - .value - .parse::() - .unwrap(); - acc + Uint128::from(burn_amount + dist_amount) - }); - assert_eq!(sim_burn_amount, actual_burn_amount); - - // Verify royalties paid - let sim_royalty_amount = sim_response - .swaps - .iter() - .fold(Uint128::zero(), |acc, swap| { - let royalty_payment = swap - .token_payments - .iter() - .find(|&payment| payment.label == "royalty") - .unwrap() - .amount; - acc + royalty_payment - }); - - let actual_royalty_amount = exec_res - .events - .iter() - .filter(|&event| event.ty == "wasm-royalty-payout") - .fold(Uint128::zero(), |acc, event| { - let amount = event - .attributes - .iter() - .find(|attr| attr.key == "amount") - .unwrap() - .value - .parse::() - .unwrap(); - acc + Uint128::from(amount) - }); - assert_eq!(sim_royalty_amount, actual_royalty_amount); - - // Verify finders paid - let sim_finder_amount = sim_response - .swaps - .iter() - .fold(Uint128::zero(), |acc, swap| { - let finder_payment = swap - .token_payments - .iter() - .find(|&payment| payment.label == "finder") - .unwrap() - .amount; - acc + finder_payment - }); - - let actual_finder_amount = router - .wrap() - .query_balance(&finder, NATIVE_DENOM) - .unwrap() - .amount - - Uint128::from(INITIAL_BALANCE); - assert_eq!(sim_finder_amount, actual_finder_amount); - - // Verify that seller was paid - let sim_seller_amount = sim_response - .swaps - .iter() - .fold(Uint128::zero(), |acc, swap| { - let seller_payment = swap - .token_payments - .iter() - .find(|&payment| payment.label == "seller") - .unwrap() - .amount; - acc + seller_payment - }); - let actual_seller_amount = router - .wrap() - .query_balance(&owner, NATIVE_DENOM) - .unwrap() - .amount - - seller_balance; - assert_eq!(sim_seller_amount, actual_seller_amount); - - // Verify that bidders received their NFTs - for swap in sim_response.swaps { - validate_nft_owner( - &router, - &collection, - swap.nft_payments[0].token_id.clone(), - &bidder, - ); - } -} diff --git a/test/unit/src/infinity_shared_tests/mod.rs b/test/unit/src/infinity_shared_tests/mod.rs deleted file mode 100644 index c67eebc..0000000 --- a/test/unit/src/infinity_shared_tests/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -#[cfg(test)] -mod unit_tests; diff --git a/test/unit/src/infinity_shared_tests/unit_tests.rs b/test/unit/src/infinity_shared_tests/unit_tests.rs deleted file mode 100644 index 55e3f78..0000000 --- a/test/unit/src/infinity_shared_tests/unit_tests.rs +++ /dev/null @@ -1,65 +0,0 @@ -use cosmwasm_std::{ - to_binary, Addr, ContractResult, Decimal, Querier, QuerierResult, QuerierWrapper, SystemResult, - Uint128, -}; -use cw_utils::Duration; -use infinity_shared::shared::load_marketplace_params; -use mockall::{mock, predicate}; -use sg_marketplace::msg::ParamsResponse; -use sg_marketplace::state::SudoParams; -use sg_marketplace::ExpiryRange; - -#[test] -fn try_load_marketplace_params() { - mock! { - QuerierStruct {} - impl Querier for QuerierStruct { - fn raw_query(&self, bin_request: &[u8]) -> QuerierResult; - } - } - - let listing_fee: u128 = 10; - let trading_fee_bps = 200; - let min_expiry: u64 = 24 * 60 * 60; // 24 hours (in seconds) - let max_expiry: u64 = 180 * 24 * 60 * 60; // 6 months (in seconds) - let max_finders_fee_bps: u64 = 1000; // 10% - let bid_removal_reward_bps: u64 = 500; // 5% - - let sudo_params = SudoParams { - trading_fee_percent: Decimal::percent(trading_fee_bps), - ask_expiry: ExpiryRange { - min: min_expiry, - max: max_expiry, - }, - bid_expiry: ExpiryRange { - min: min_expiry, - max: max_expiry, - }, - operators: vec![Addr::unchecked("operator")], - max_finders_fee_percent: Decimal::percent(max_finders_fee_bps), - min_price: Uint128::from(5u128), - stale_bid_duration: Duration::Time(100), - bid_removal_reward_percent: Decimal::percent(bid_removal_reward_bps), - listing_fee: Uint128::from(listing_fee), - }; - - let return_value = SystemResult::Ok(ContractResult::Ok( - to_binary(&ParamsResponse { - params: sudo_params.clone(), - }) - .unwrap(), - )); - - let mut mock = MockQuerierStruct::new(); - mock.expect_raw_query() - .with(predicate::always()) - .times(1) - .returning(move |_| return_value.clone()); - - let querier_wrapper = QuerierWrapper::new(&mock); - - assert_eq!( - Ok(sudo_params), - load_marketplace_params(&querier_wrapper, &Addr::unchecked("marketplace")) - ); -} diff --git a/test/unit/src/infinity_swap_tests/mod.rs b/test/unit/src/infinity_swap_tests/mod.rs deleted file mode 100644 index 46d9ac9..0000000 --- a/test/unit/src/infinity_swap_tests/mod.rs +++ /dev/null @@ -1,14 +0,0 @@ -#[cfg(test)] -mod pool_tests; - -#[cfg(test)] -mod query_tests; - -#[cfg(test)] -mod multitest; - -#[cfg(test)] -mod sim_tests; - -#[cfg(test)] -mod swap_tests; diff --git a/test/unit/src/infinity_swap_tests/multitest.rs b/test/unit/src/infinity_swap_tests/multitest.rs deleted file mode 100644 index 056466a..0000000 --- a/test/unit/src/infinity_swap_tests/multitest.rs +++ /dev/null @@ -1,36 +0,0 @@ -use std::vec; - -use cosmwasm_std::testing::{mock_dependencies, mock_env, mock_info}; -use cosmwasm_std::{coins, Addr, Attribute}; -use infinity_swap::instantiate::instantiate; -use infinity_swap::msg::InstantiateMsg; -use sg_std::NATIVE_DENOM; - -const MARKETPLACE: &str = "marketplace"; - -#[test] -fn proper_initialization() { - let mut deps = mock_dependencies(); - - let marketplace_addr = Addr::unchecked(MARKETPLACE); - - let msg = InstantiateMsg { - denom: NATIVE_DENOM.to_string(), - marketplace_addr: marketplace_addr.to_string(), - developer: None, - }; - let info = mock_info("creator", &coins(1000, NATIVE_DENOM)); - - let res = instantiate(deps.as_mut(), mock_env(), info, msg).unwrap(); - let expected = vec![ - Attribute { - key: "denom".to_string(), - value: NATIVE_DENOM.to_string(), - }, - Attribute { - key: "marketplace_addr".to_string(), - value: marketplace_addr.to_string(), - }, - ]; - assert_eq!(res.attributes[3..5], expected); -} diff --git a/test/unit/src/infinity_swap_tests/pool_tests/mod.rs b/test/unit/src/infinity_swap_tests/pool_tests/mod.rs deleted file mode 100644 index cf621d1..0000000 --- a/test/unit/src/infinity_swap_tests/pool_tests/mod.rs +++ /dev/null @@ -1,8 +0,0 @@ -#[cfg(test)] -mod token_pool_tests; - -#[cfg(test)] -mod nft_pool_tests; - -#[cfg(test)] -mod trade_pool_tests; diff --git a/test/unit/src/infinity_swap_tests/pool_tests/nft_pool_tests.rs b/test/unit/src/infinity_swap_tests/pool_tests/nft_pool_tests.rs deleted file mode 100644 index bdbaaa7..0000000 --- a/test/unit/src/infinity_swap_tests/pool_tests/nft_pool_tests.rs +++ /dev/null @@ -1,169 +0,0 @@ -use std::vec; - -use crate::helpers::nft_functions::{approve, mint}; -use crate::helpers::pool_functions::create_pool; -use crate::helpers::utils::assert_error; -use crate::setup::setup_accounts::setup_addtl_account; -use crate::setup::setup_infinity_swap::setup_infinity_swap; -use crate::setup::setup_marketplace::{setup_marketplace, LISTING_FEE}; -use crate::setup::templates::standard_minter_template; -use cosmwasm_std::{coins, Addr, Uint128}; -use cw_multi_test::Executor; -use infinity_swap::msg::ExecuteMsg; -use infinity_swap::state::BondingCurve; -use infinity_swap::ContractError; -use sg_std::{GENESIS_MINT_START_TIME, NATIVE_DENOM}; -use test_suite::common_setup::setup_accounts_and_block::setup_block_time; - -const ASSET_ACCOUNT: &str = "asset"; - -#[test] -fn create_nft_pool() { - let vt = standard_minter_template(5000); - let (mut router, creator, _bidder) = (vt.router, vt.accts.creator, vt.accts.bidder); - let collection = vt.collection_response_vec[0].collection.clone().unwrap(); - let asset_account = Addr::unchecked(ASSET_ACCOUNT); - - let marketplace = setup_marketplace(&mut router, creator.clone()).unwrap(); - let infinity_swap = setup_infinity_swap(&mut router, creator.clone(), marketplace).unwrap(); - - // Cannot create a ConstantProduct Nft Pool because the pool does not hold both assets - let msg = ExecuteMsg::CreateNftPool { - collection: collection.to_string(), - asset_recipient: Some(asset_account.to_string()), - bonding_curve: BondingCurve::ConstantProduct, - spot_price: Uint128::from(2400u64), - delta: Uint128::from(120u64), - finders_fee_bps: 0, - }; - let res = router.execute_contract(creator.clone(), infinity_swap.clone(), &msg, &[]); - assert_error( - res, - ContractError::InvalidPool(String::from( - "constant product bonding curve cannot be used with nft pools", - )), - ); - - // Can create a Linear Nft Pool - let msg = ExecuteMsg::CreateNftPool { - collection: collection.to_string(), - asset_recipient: Some(asset_account.to_string()), - bonding_curve: BondingCurve::Linear, - spot_price: Uint128::from(2400u64), - delta: Uint128::from(120u64), - finders_fee_bps: 0, - }; - let res = router.execute_contract( - creator.clone(), - infinity_swap.clone(), - &msg, - &coins(LISTING_FEE, NATIVE_DENOM), - ); - assert!(res.is_ok()); - - // Can create an Exponential Nft Pool - let msg = ExecuteMsg::CreateNftPool { - collection: collection.to_string(), - asset_recipient: Some(asset_account.to_string()), - bonding_curve: BondingCurve::Exponential, - spot_price: Uint128::from(2400u64), - delta: Uint128::from(120u64), - finders_fee_bps: 0, - }; - let res = router.execute_contract( - creator, - infinity_swap, - &msg, - &coins(LISTING_FEE, NATIVE_DENOM), - ); - assert!(res.is_ok()); -} - -#[test] -fn deposit_assets_nft_pool() { - let vt = standard_minter_template(5000); - let (mut router, minter, creator, user1) = ( - vt.router, - vt.collection_response_vec[0].minter.as_ref().unwrap(), - vt.accts.creator, - vt.accts.bidder, - ); - let _user2 = setup_addtl_account(&mut router, "bidder2", 5_000_002_000); - - let collection = vt.collection_response_vec[0].collection.clone().unwrap(); - let asset_account = Addr::unchecked(ASSET_ACCOUNT); - - setup_block_time(&mut router, GENESIS_MINT_START_TIME, None); - let marketplace = setup_marketplace(&mut router, creator.clone()).unwrap(); - let infinity_swap = setup_infinity_swap(&mut router, creator.clone(), marketplace).unwrap(); - - let pool = create_pool( - &mut router, - infinity_swap.clone(), - creator.clone(), - ExecuteMsg::CreateNftPool { - collection: collection.to_string(), - asset_recipient: Some(asset_account.to_string()), - bonding_curve: BondingCurve::Linear, - spot_price: Uint128::from(2400u64), - delta: Uint128::from(100u64), - finders_fee_bps: 0, - }, - ) - .unwrap(); - - // Only owner can deposit NFTs into nft pool - let token_id_1 = mint(&mut router, &user1, minter); - approve(&mut router, &user1, &collection, &infinity_swap, token_id_1); - let token_id_2 = mint(&mut router, &user1, minter); - approve(&mut router, &user1, &collection, &infinity_swap, token_id_2); - let msg = ExecuteMsg::DepositNfts { - pool_id: pool.id, - collection: collection.to_string(), - nft_token_ids: vec![token_id_1.to_string(), token_id_2.to_string()], - }; - let res = router.execute_contract(user1.clone(), infinity_swap.clone(), &msg, &[]); - assert_error( - res, - ContractError::Unauthorized("sender is not the owner of the pool".to_string()), - ); - - // Owner can deposit NFTs into nft pool - let token_id_1 = mint(&mut router, &creator, minter); - approve( - &mut router, - &creator, - &collection, - &infinity_swap, - token_id_1, - ); - let token_id_2 = mint(&mut router, &creator, minter); - approve( - &mut router, - &creator, - &collection, - &infinity_swap, - token_id_2, - ); - let msg = ExecuteMsg::DepositNfts { - pool_id: pool.id, - collection: collection.to_string(), - nft_token_ids: vec![token_id_1.to_string(), token_id_2.to_string()], - }; - let res = router.execute_contract(creator.clone(), infinity_swap.clone(), &msg, &[]); - assert!(res.is_ok()); - - // Owner cannot deposit tokens into nft pool - let deposit_amount = 1000u128; - let msg = ExecuteMsg::DepositTokens { pool_id: pool.id }; - let res = router.execute_contract( - creator, - infinity_swap, - &msg, - &coins(deposit_amount, NATIVE_DENOM), - ); - assert_error( - res, - ContractError::InvalidPool("cannot deposit tokens into nft pool".to_string()), - ); -} diff --git a/test/unit/src/infinity_swap_tests/pool_tests/token_pool_tests.rs b/test/unit/src/infinity_swap_tests/pool_tests/token_pool_tests.rs deleted file mode 100644 index a823451..0000000 --- a/test/unit/src/infinity_swap_tests/pool_tests/token_pool_tests.rs +++ /dev/null @@ -1,539 +0,0 @@ -use std::vec; - -use crate::helpers::nft_functions::{approve, mint}; -use crate::helpers::pool_functions::{create_pool, deposit_tokens}; -use crate::helpers::utils::assert_error; -use crate::setup::setup_accounts::{setup_addtl_account, INITIAL_BALANCE}; -use crate::setup::setup_infinity_swap::setup_infinity_swap; -use crate::setup::setup_marketplace::{setup_marketplace, LISTING_FEE}; -use crate::setup::templates::standard_minter_template; -use cosmwasm_std::{coins, Addr, Attribute, Uint128}; -use cw_multi_test::Executor; -use infinity_swap::msg::ExecuteMsg; -use infinity_swap::state::BondingCurve; -use infinity_swap::ContractError; -use sg_std::{GENESIS_MINT_START_TIME, NATIVE_DENOM}; -use test_suite::common_setup::setup_accounts_and_block::setup_block_time; - -const ASSET_ACCOUNT: &str = "asset"; - -#[test] -fn create_token_pool() { - let vt = standard_minter_template(5000); - let (mut router, creator, _bidder) = (vt.router, vt.accts.creator, vt.accts.bidder); - let collection = vt.collection_response_vec[0].collection.clone().unwrap(); - let asset_account = Addr::unchecked(ASSET_ACCOUNT); - - let marketplace = setup_marketplace(&mut router, creator.clone()).unwrap(); - let infinity_swap = setup_infinity_swap(&mut router, creator.clone(), marketplace).unwrap(); - - // Cannot create a ConstantProduct Token Pool because the pool does not hold both assets - let msg = ExecuteMsg::CreateTokenPool { - collection: collection.to_string(), - asset_recipient: Some(asset_account.to_string()), - bonding_curve: BondingCurve::ConstantProduct, - spot_price: Uint128::from(2400u64), - delta: Uint128::from(120u64), - finders_fee_bps: 0, - }; - let res = router.execute_contract( - creator.clone(), - infinity_swap.clone(), - &msg, - &coins(LISTING_FEE, NATIVE_DENOM), - ); - assert_error( - res, - ContractError::InvalidPool(String::from( - "constant product bonding curve cannot be used with token pools", - )), - ); - - // Can create a Linear Token Pool - let msg = ExecuteMsg::CreateTokenPool { - collection: collection.to_string(), - asset_recipient: Some(asset_account.to_string()), - bonding_curve: BondingCurve::Linear, - spot_price: Uint128::from(2400u64), - delta: Uint128::from(120u64), - finders_fee_bps: 0, - }; - let res = router.execute_contract( - creator.clone(), - infinity_swap.clone(), - &msg, - &coins(LISTING_FEE, NATIVE_DENOM), - ); - assert!(res.is_ok()); - - // Can create an Exponential Token Pool - let msg = ExecuteMsg::CreateTokenPool { - collection: collection.to_string(), - asset_recipient: Some(asset_account.to_string()), - bonding_curve: BondingCurve::Exponential, - spot_price: Uint128::from(2400u64), - delta: Uint128::from(120u64), - finders_fee_bps: 0, - }; - let res = router.execute_contract( - creator, - infinity_swap, - &msg, - &coins(LISTING_FEE, NATIVE_DENOM), - ); - assert!(res.is_ok()); -} - -#[test] -fn deposit_assets_token_pool() { - let vt = standard_minter_template(5000); - let (mut router, minter, creator, user1) = ( - vt.router, - vt.collection_response_vec[0].minter.as_ref().unwrap(), - vt.accts.creator, - vt.accts.bidder, - ); - let _user2 = setup_addtl_account(&mut router, "bidder2", 5_000_002_000); - - let collection = vt.collection_response_vec[0].collection.clone().unwrap(); - let asset_account = Addr::unchecked(ASSET_ACCOUNT); - - setup_block_time(&mut router, GENESIS_MINT_START_TIME, None); - let marketplace = setup_marketplace(&mut router, creator.clone()).unwrap(); - let infinity_swap = setup_infinity_swap(&mut router, creator.clone(), marketplace).unwrap(); - - let pool = create_pool( - &mut router, - infinity_swap.clone(), - creator.clone(), - ExecuteMsg::CreateTokenPool { - collection: collection.to_string(), - asset_recipient: Some(asset_account.to_string()), - bonding_curve: BondingCurve::Linear, - spot_price: Uint128::from(2400u64), - delta: Uint128::from(100u64), - finders_fee_bps: 0, - }, - ) - .unwrap(); - - // Only owner of pool can deposit tokens - let deposit_amount = 1000u128; - let msg = ExecuteMsg::DepositTokens { pool_id: pool.id }; - let res = router.execute_contract( - user1, - infinity_swap.clone(), - &msg, - &coins(deposit_amount, NATIVE_DENOM), - ); - assert_error( - res, - ContractError::Unauthorized("sender is not the owner of the pool".to_string()), - ); - - // Owner can deposit tokens - let deposit_amount_1 = 1250u128; - let msg = ExecuteMsg::DepositTokens { pool_id: pool.id }; - let res = router.execute_contract( - creator.clone(), - infinity_swap.clone(), - &msg, - &coins(deposit_amount_1, NATIVE_DENOM), - ); - assert!(res.is_ok()); - - // Tokens are summed by the pool - let deposit_amount_2 = 3200u128; - let total_tokens = deposit_tokens( - &mut router, - infinity_swap.clone(), - creator.clone(), - pool.id, - Uint128::from(deposit_amount_2), - ) - .unwrap(); - assert_eq!(deposit_amount_1 + deposit_amount_2, total_tokens); - - // Cannot deposit NFTs into token pool - let token_id_1 = mint(&mut router, &creator, minter); - approve( - &mut router, - &creator, - &collection, - &infinity_swap, - token_id_1, - ); - let token_id_2 = mint(&mut router, &creator, minter); - approve( - &mut router, - &creator, - &collection, - &infinity_swap, - token_id_2, - ); - let msg = ExecuteMsg::DepositNfts { - pool_id: pool.id, - collection: collection.to_string(), - nft_token_ids: vec![token_id_1.to_string(), token_id_2.to_string()], - }; - let res = router.execute_contract(creator, infinity_swap, &msg, &[]); - assert_error( - res, - ContractError::InvalidPool("cannot deposit nfts into token pool".to_string()), - ); -} - -#[test] -fn withdraw_assets_token_pool() { - let vt = standard_minter_template(5000); - let (mut router, _minter, creator, user1) = ( - vt.router, - vt.collection_response_vec[0].minter.as_ref().unwrap(), - vt.accts.creator, - vt.accts.bidder, - ); - - let collection = vt.collection_response_vec[0].collection.clone().unwrap(); - let asset_account = Addr::unchecked(ASSET_ACCOUNT); - - setup_block_time(&mut router, GENESIS_MINT_START_TIME, None); - let marketplace = setup_marketplace(&mut router, creator.clone()).unwrap(); - let infinity_swap = setup_infinity_swap(&mut router, creator.clone(), marketplace).unwrap(); - - let pool = create_pool( - &mut router, - infinity_swap.clone(), - creator.clone(), - ExecuteMsg::CreateTokenPool { - collection: collection.to_string(), - asset_recipient: Some(asset_account.to_string()), - bonding_curve: BondingCurve::Linear, - spot_price: Uint128::from(2400u64), - delta: Uint128::from(100u64), - finders_fee_bps: 0, - }, - ) - .unwrap(); - - let deposit_amount = Uint128::from(1000u64); - deposit_tokens( - &mut router, - infinity_swap.clone(), - creator.clone(), - pool.id, - deposit_amount, - ) - .unwrap(); - - // Only owner of pool can withdraw tokens - let msg = ExecuteMsg::WithdrawTokens { - pool_id: pool.id, - amount: Uint128::from(300u64), - asset_recipient: None, - }; - let res = router.execute_contract(user1, infinity_swap.clone(), &msg, &[]); - assert_error( - res, - ContractError::Unauthorized("sender is not the owner of the pool".to_string()), - ); - - // Owner of pool can withdraw tokens, tokens are directed to asset_recipient - let withdraw_amount = Uint128::from(300u64); - let msg = ExecuteMsg::WithdrawTokens { - pool_id: pool.id, - amount: withdraw_amount, - asset_recipient: Some(asset_account.to_string()), - }; - let res = router.execute_contract(creator.clone(), infinity_swap.clone(), &msg, &[]); - let total_tokens = res.as_ref().unwrap().events[1].attributes[3] - .value - .parse::() - .unwrap(); - assert!(res.is_ok()); - assert_eq!( - Uint128::from(total_tokens), - deposit_amount - withdraw_amount - ); - let asset_account_balance = router.wrap().query_all_balances(asset_account).unwrap(); - assert_eq!(withdraw_amount, asset_account_balance[0].amount); - - // Owner of pool can withdraw remaining tokens, tokens are directed toward owner - let msg = ExecuteMsg::WithdrawAllTokens { - pool_id: pool.id, - asset_recipient: None, - }; - let res = router.execute_contract(creator.clone(), infinity_swap.clone(), &msg, &[]); - let total_tokens = res.as_ref().unwrap().events[1].attributes[3] - .value - .parse::() - .unwrap(); - assert!(res.is_ok()); - assert_eq!(Uint128::from(total_tokens), Uint128::from(0u128)); - let creator_balance = router.wrap().query_all_balances(creator.clone()).unwrap(); - assert_eq!( - creator_balance[0].amount, - Uint128::from(INITIAL_BALANCE) - withdraw_amount - Uint128::from(LISTING_FEE) - ); - - // Owner of pool cannot withdraw NFTs from a token pool - let msg = ExecuteMsg::WithdrawNfts { - pool_id: pool.id, - nft_token_ids: vec!["1".to_string()], - asset_recipient: None, - }; - let res = router.execute_contract(creator.clone(), infinity_swap.clone(), &msg, &[]); - assert_error( - res, - ContractError::InvalidPool("cannot withdraw nfts from token pool".to_string()), - ); - - // Owner of pool cannot withdraw NFTs from a token pool - let msg = ExecuteMsg::WithdrawAllNfts { - pool_id: pool.id, - asset_recipient: None, - }; - let res = router.execute_contract(creator, infinity_swap, &msg, &[]); - assert_error( - res, - ContractError::InvalidPool("cannot withdraw nfts from token pool".to_string()), - ); -} - -#[test] -fn update_token_pool() { - let vt = standard_minter_template(5000); - let (mut router, _minter, creator, user1) = ( - vt.router, - vt.collection_response_vec[0].minter.as_ref().unwrap(), - vt.accts.creator, - vt.accts.bidder, - ); - - let collection = vt.collection_response_vec[0].collection.clone().unwrap(); - let asset_account = Addr::unchecked(ASSET_ACCOUNT); - - setup_block_time(&mut router, GENESIS_MINT_START_TIME, None); - let marketplace = setup_marketplace(&mut router, creator.clone()).unwrap(); - let infinity_swap = setup_infinity_swap(&mut router, creator.clone(), marketplace).unwrap(); - - let pool = create_pool( - &mut router, - infinity_swap.clone(), - creator.clone(), - ExecuteMsg::CreateTokenPool { - collection: collection.to_string(), - asset_recipient: None, - bonding_curve: BondingCurve::Linear, - spot_price: Uint128::from(2400u64), - delta: Uint128::from(100u64), - finders_fee_bps: 0, - }, - ) - .unwrap(); - - // Only owner of pool can update pool - let msg = ExecuteMsg::UpdatePoolConfig { - pool_id: pool.id, - asset_recipient: Some(asset_account.to_string()), - delta: Some(Uint128::from(101u64)), - spot_price: Some(Uint128::from(102u64)), - finders_fee_bps: Some(0), - swap_fee_bps: Some(0u64), - reinvest_nfts: Some(false), - reinvest_tokens: Some(false), - }; - let res = router.execute_contract(user1, infinity_swap.clone(), &msg, &[]); - assert_error( - res, - ContractError::Unauthorized("sender is not the owner of the pool".to_string()), - ); - - // Fee cannot be set on token pool - let msg = ExecuteMsg::UpdatePoolConfig { - pool_id: pool.id, - asset_recipient: Some(asset_account.to_string()), - delta: Some(Uint128::from(101u64)), - spot_price: Some(Uint128::from(102u64)), - finders_fee_bps: Some(0), - swap_fee_bps: Some(100u64), - reinvest_nfts: Some(false), - reinvest_tokens: Some(false), - }; - let res = router.execute_contract(creator.clone(), infinity_swap.clone(), &msg, &[]); - assert_error( - res, - ContractError::InvalidPool("swap_fee_percent must be 0 for token pool".to_string()), - ); - - // Properties on pool are updated correctly - let new_spot_price = Uint128::from(2400u64); - let new_delta = Uint128::from(100u64); - let msg = ExecuteMsg::UpdatePoolConfig { - pool_id: pool.id, - asset_recipient: Some(asset_account.to_string()), - spot_price: Some(new_spot_price), - delta: Some(new_delta), - finders_fee_bps: Some(0), - swap_fee_bps: Some(0u64), - reinvest_nfts: Some(false), - reinvest_tokens: Some(false), - }; - let res = router.execute_contract(creator, infinity_swap, &msg, &[]); - assert!(res.is_ok()); - let attrs = &res.as_ref().unwrap().events[1].attributes; - assert_eq!( - attrs[1], - Attribute { - key: "id".to_string(), - value: pool.id.to_string() - } - ); - assert_eq!( - attrs[2], - Attribute { - key: "asset_recipient".to_string(), - value: ASSET_ACCOUNT.to_string() - } - ); - assert_eq!( - attrs[3], - Attribute { - key: "spot_price".to_string(), - value: new_spot_price.to_string() - } - ); - assert_eq!( - attrs[4], - Attribute { - key: "delta".to_string(), - value: new_delta.to_string() - } - ); -} - -#[test] -fn remove_token_pool() { - let vt = standard_minter_template(5000); - let (mut router, _minter, creator, user1) = ( - vt.router, - vt.collection_response_vec[0].minter.as_ref().unwrap(), - vt.accts.creator, - vt.accts.bidder, - ); - - let collection = vt.collection_response_vec[0].collection.clone().unwrap(); - let asset_account = Addr::unchecked(ASSET_ACCOUNT); - - setup_block_time(&mut router, GENESIS_MINT_START_TIME, None); - let marketplace = setup_marketplace(&mut router, creator.clone()).unwrap(); - let infinity_swap = setup_infinity_swap(&mut router, creator.clone(), marketplace).unwrap(); - - let pool = create_pool( - &mut router, - infinity_swap.clone(), - creator.clone(), - ExecuteMsg::CreateTokenPool { - collection: collection.to_string(), - asset_recipient: None, - bonding_curve: BondingCurve::Linear, - spot_price: Uint128::from(2400u64), - delta: Uint128::from(100u64), - finders_fee_bps: 0, - }, - ) - .unwrap(); - - let deposit_amount = Uint128::from(1000u64); - deposit_tokens( - &mut router, - infinity_swap.clone(), - creator.clone(), - pool.id, - deposit_amount, - ) - .unwrap(); - - // Only owner of pool can remove pool - let msg = ExecuteMsg::RemovePool { - pool_id: pool.id, - asset_recipient: Some(asset_account.to_string()), - }; - let res = router.execute_contract(user1, infinity_swap.clone(), &msg, &[]); - assert_error( - res, - ContractError::Unauthorized("sender is not the owner of the pool".to_string()), - ); - - // Owner of pool can remove pool, and asset_recipient is transferred remaining tokens - let msg = ExecuteMsg::RemovePool { - pool_id: pool.id, - asset_recipient: Some(asset_account.to_string()), - }; - let res = router.execute_contract(creator, infinity_swap, &msg, &[]); - assert!(res.is_ok()); - let asset_account_balance = router.wrap().query_all_balances(asset_account).unwrap(); - assert_eq!(deposit_amount, asset_account_balance[0].amount); -} - -#[test] -fn activate_token_pool() { - let vt = standard_minter_template(5000); - let (mut router, _minter, creator, user1) = ( - vt.router, - vt.collection_response_vec[0].minter.as_ref().unwrap(), - vt.accts.creator, - vt.accts.bidder, - ); - - let collection = vt.collection_response_vec[0].collection.clone().unwrap(); - let _asset_account = Addr::unchecked(ASSET_ACCOUNT); - - setup_block_time(&mut router, GENESIS_MINT_START_TIME, None); - let marketplace = setup_marketplace(&mut router, creator.clone()).unwrap(); - let infinity_swap = setup_infinity_swap(&mut router, creator.clone(), marketplace).unwrap(); - - let pool = create_pool( - &mut router, - infinity_swap.clone(), - creator.clone(), - ExecuteMsg::CreateTokenPool { - collection: collection.to_string(), - asset_recipient: None, - bonding_curve: BondingCurve::Linear, - spot_price: Uint128::from(2400u64), - delta: Uint128::from(100u64), - finders_fee_bps: 0, - }, - ) - .unwrap(); - - let deposit_amount = Uint128::from(1000u64); - deposit_tokens( - &mut router, - infinity_swap.clone(), - creator.clone(), - pool.id, - deposit_amount, - ) - .unwrap(); - - // Only owner of pool can activate pool - let msg = ExecuteMsg::SetActivePool { - is_active: true, - pool_id: pool.id, - }; - let res = router.execute_contract(user1, infinity_swap.clone(), &msg, &[]); - assert_error( - res, - ContractError::Unauthorized("sender is not the owner of the pool".to_string()), - ); - - // Owner of pool can activate pool - let msg = ExecuteMsg::SetActivePool { - is_active: true, - pool_id: pool.id, - }; - let res = router.execute_contract(creator, infinity_swap, &msg, &[]); - let is_active = &res.as_ref().unwrap().events[1].attributes[2].value; - assert_eq!(is_active, &"true"); -} diff --git a/test/unit/src/infinity_swap_tests/pool_tests/trade_pool_tests.rs b/test/unit/src/infinity_swap_tests/pool_tests/trade_pool_tests.rs deleted file mode 100644 index 3cccdc6..0000000 --- a/test/unit/src/infinity_swap_tests/pool_tests/trade_pool_tests.rs +++ /dev/null @@ -1,213 +0,0 @@ -use std::vec; - -use crate::helpers::nft_functions::{approve, mint}; -use crate::helpers::pool_functions::create_pool; -use crate::helpers::utils::assert_error; -use crate::setup::setup_infinity_swap::setup_infinity_swap; -use crate::setup::setup_marketplace::{setup_marketplace, LISTING_FEE}; -use crate::setup::templates::standard_minter_template; -use cosmwasm_std::{coins, Addr, Uint128}; -use cw_multi_test::Executor; -use infinity_swap::msg::ExecuteMsg; -use infinity_swap::state::BondingCurve; -use infinity_swap::ContractError; -use sg_std::{GENESIS_MINT_START_TIME, NATIVE_DENOM}; -use test_suite::common_setup::setup_accounts_and_block::setup_block_time; - -const ASSET_ACCOUNT: &str = "asset"; - -#[test] -fn create_trade_pool() { - let vt = standard_minter_template(5000); - let (mut router, creator, _bidder) = (vt.router, vt.accts.creator, vt.accts.bidder); - let collection = vt.collection_response_vec[0].collection.clone().unwrap(); - let asset_account = Addr::unchecked(ASSET_ACCOUNT); - - let marketplace = setup_marketplace(&mut router, creator.clone()).unwrap(); - let infinity_swap = setup_infinity_swap(&mut router, creator.clone(), marketplace).unwrap(); - - // Cannot create a Trade Pool with a fee > 9000; - let msg = ExecuteMsg::CreateTradePool { - collection: collection.to_string(), - asset_recipient: Some(asset_account.to_string()), - bonding_curve: BondingCurve::Linear, - spot_price: Uint128::from(1000u64), - delta: Uint128::from(100u64), - finders_fee_bps: 0, - swap_fee_bps: 5001u64, - reinvest_nfts: false, - reinvest_tokens: false, - }; - let res = router.execute_contract( - creator.clone(), - infinity_swap.clone(), - &msg, - &coins(LISTING_FEE, NATIVE_DENOM), - ); - assert_error( - res, - ContractError::InvalidPool(String::from("swap_fee_percent cannot be greater than 50%")), - ); - - // Can create a Linear Trade Pool w/ no fee - let msg = ExecuteMsg::CreateTradePool { - collection: collection.to_string(), - asset_recipient: Some(asset_account.to_string()), - bonding_curve: BondingCurve::Linear, - spot_price: Uint128::from(1000u64), - delta: Uint128::from(100u64), - finders_fee_bps: 0, - swap_fee_bps: 0, - reinvest_nfts: false, - reinvest_tokens: false, - }; - let res = router.execute_contract( - creator.clone(), - infinity_swap.clone(), - &msg, - &coins(LISTING_FEE, NATIVE_DENOM), - ); - assert!(res.is_ok()); - - // Can create an Exponential Trade Pool - let msg = ExecuteMsg::CreateTradePool { - collection: collection.to_string(), - asset_recipient: Some(asset_account.to_string()), - bonding_curve: BondingCurve::Exponential, - spot_price: Uint128::from(1000u64), - delta: Uint128::from(100u64), - finders_fee_bps: 0, - swap_fee_bps: 200u64, - reinvest_nfts: false, - reinvest_tokens: false, - }; - let res = router.execute_contract( - creator.clone(), - infinity_swap.clone(), - &msg, - &coins(LISTING_FEE, NATIVE_DENOM), - ); - assert!(res.is_ok()); - - // Can create an Constant Product Trade Pool - let msg = ExecuteMsg::CreateTradePool { - collection: collection.to_string(), - asset_recipient: Some(asset_account.to_string()), - bonding_curve: BondingCurve::ConstantProduct, - spot_price: Uint128::from(0u64), - delta: Uint128::from(0u64), - finders_fee_bps: 0, - swap_fee_bps: 200u64, - reinvest_nfts: false, - reinvest_tokens: false, - }; - let res = router.execute_contract( - creator, - infinity_swap, - &msg, - &coins(LISTING_FEE, NATIVE_DENOM), - ); - assert!(res.is_ok()); -} - -#[test] -fn deposit_assets_trade_pool() { - let vt = standard_minter_template(5000); - let (mut router, minter, creator, user1) = ( - vt.router, - vt.collection_response_vec[0].minter.as_ref().unwrap(), - vt.accts.creator, - vt.accts.bidder, - ); - - let collection = vt.collection_response_vec[0].collection.clone().unwrap(); - let asset_account = Addr::unchecked(ASSET_ACCOUNT); - - setup_block_time(&mut router, GENESIS_MINT_START_TIME, None); - let marketplace = setup_marketplace(&mut router, creator.clone()).unwrap(); - let infinity_swap = setup_infinity_swap(&mut router, creator.clone(), marketplace).unwrap(); - - let pool = create_pool( - &mut router, - infinity_swap.clone(), - creator.clone(), - ExecuteMsg::CreateTradePool { - collection: collection.to_string(), - asset_recipient: Some(asset_account.to_string()), - bonding_curve: BondingCurve::Linear, - spot_price: Uint128::from(1000u64), - delta: Uint128::from(100u64), - finders_fee_bps: 0, - swap_fee_bps: 0, - reinvest_tokens: false, - reinvest_nfts: false, - }, - ) - .unwrap(); - - // Only owner of pool can deposit tokens - let deposit_amount = 1000u128; - let msg = ExecuteMsg::DepositTokens { pool_id: pool.id }; - let res = router.execute_contract( - user1.clone(), - infinity_swap.clone(), - &msg, - &coins(deposit_amount, NATIVE_DENOM), - ); - assert_error( - res, - ContractError::Unauthorized("sender is not the owner of the pool".to_string()), - ); - - // Owner can deposit tokens - let deposit_amount = 1000u128; - let msg = ExecuteMsg::DepositTokens { pool_id: pool.id }; - let res = router.execute_contract( - creator.clone(), - infinity_swap.clone(), - &msg, - &coins(deposit_amount, NATIVE_DENOM), - ); - assert!(res.is_ok()); - - // Only owner can deposit NFTs into nft pool - let token_id_1 = mint(&mut router, &user1, minter); - approve(&mut router, &user1, &collection, &infinity_swap, token_id_1); - let token_id_2 = mint(&mut router, &user1, minter); - approve(&mut router, &user1, &collection, &infinity_swap, token_id_2); - let msg = ExecuteMsg::DepositNfts { - pool_id: pool.id, - collection: collection.to_string(), - nft_token_ids: vec![token_id_1.to_string(), token_id_2.to_string()], - }; - let res = router.execute_contract(user1.clone(), infinity_swap.clone(), &msg, &[]); - assert_error( - res, - ContractError::Unauthorized("sender is not the owner of the pool".to_string()), - ); - - // Owner can deposit NFTs into nft pool - let token_id_1 = mint(&mut router, &creator, minter); - approve( - &mut router, - &creator, - &collection, - &infinity_swap, - token_id_1, - ); - let token_id_2 = mint(&mut router, &creator, minter); - approve( - &mut router, - &creator, - &collection, - &infinity_swap, - token_id_2, - ); - let msg = ExecuteMsg::DepositNfts { - pool_id: pool.id, - collection: collection.to_string(), - nft_token_ids: vec![token_id_1.to_string(), token_id_2.to_string()], - }; - let res = router.execute_contract(creator, infinity_swap, &msg, &[]); - assert!(res.is_ok()); -} diff --git a/test/unit/src/infinity_swap_tests/query_tests.rs b/test/unit/src/infinity_swap_tests/query_tests.rs deleted file mode 100644 index 138228f..0000000 --- a/test/unit/src/infinity_swap_tests/query_tests.rs +++ /dev/null @@ -1,425 +0,0 @@ -use std::vec; - -use crate::helpers::fixtures::{create_and_activate_pool_fixtures, create_pool_fixtures}; -use crate::helpers::nft_functions::mint_and_approve_many; -use crate::helpers::pool_functions::prepare_swap_pool; -use crate::setup::setup_accounts::setup_addtl_account; -use crate::setup::setup_infinity_swap::setup_infinity_swap; -use crate::setup::setup_marketplace::setup_marketplace; -use crate::setup::templates::standard_minter_template; -use cosmwasm_std::{Addr, Uint128}; -use infinity_swap::msg::{ - ConfigResponse, ExecuteMsg, NftTokenIdsResponse, PoolQuoteResponse, PoolsByIdResponse, - PoolsResponse, QueryMsg, QueryOptions, -}; -use infinity_swap::state::{BondingCurve, Config, PoolQuote}; -use sg_std::GENESIS_MINT_START_TIME; -use test_suite::common_setup::setup_accounts_and_block::setup_block_time; - -const USER: &str = "user1"; -const ASSET_ACCOUNT: &str = "asset"; - -#[test] -fn try_query_config() { - let vt = standard_minter_template(5000); - let (mut router, creator, _bidder) = (vt.router, vt.accts.creator, vt.accts.bidder); - let _collection = vt.collection_response_vec[0].collection.clone().unwrap(); - let _asset_account = Addr::unchecked(ASSET_ACCOUNT); - - let marketplace = setup_marketplace(&mut router, creator.clone()).unwrap(); - let infinity_swap = setup_infinity_swap(&mut router, creator, marketplace.clone()).unwrap(); - - let config_query = QueryMsg::Config {}; - - let res: ConfigResponse = router - .wrap() - .query_wasm_smart(infinity_swap, &config_query) - .unwrap(); - - assert_eq!( - res.config, - Config { - marketplace_addr: marketplace, - developer: None, - } - ) -} - -#[test] -fn try_query_pools() { - let vt = standard_minter_template(5000); - let (mut router, creator, _bidder) = (vt.router, vt.accts.creator, vt.accts.bidder); - let collection = vt.collection_response_vec[0].collection.clone().unwrap(); - let user = setup_addtl_account(&mut router, USER, 1_000_000).unwrap(); - let asset_account = Addr::unchecked(ASSET_ACCOUNT); - - let marketplace = setup_marketplace(&mut router, creator.clone()).unwrap(); - let infinity_swap = setup_infinity_swap(&mut router, creator.clone(), marketplace).unwrap(); - - let pools = create_pool_fixtures( - &mut router, - infinity_swap.clone(), - collection, - creator, - user, - asset_account, - 0, - 50, - ); - - let pool_query = QueryMsg::Pools { - query_options: QueryOptions { - descending: Some(false), - start_after: Some(3u64), - limit: Some(2), - }, - }; - - let res: PoolsResponse = router - .wrap() - .query_wasm_smart(infinity_swap, &pool_query) - .unwrap(); - assert_eq!(res.pools.len(), 2); - assert_eq!(res.pools[0], pools[3].clone()); - assert_eq!(res.pools[1], pools[4].clone()); -} - -#[test] -fn try_query_pools_by_id() { - let vt = standard_minter_template(5000); - let (mut router, creator, _bidder) = (vt.router, vt.accts.creator, vt.accts.bidder); - let collection = vt.collection_response_vec[0].collection.clone().unwrap(); - let user = setup_addtl_account(&mut router, USER, 1_000_000).unwrap(); - let asset_account = Addr::unchecked(ASSET_ACCOUNT); - - let marketplace = setup_marketplace(&mut router, creator.clone()).unwrap(); - let infinity_swap = setup_infinity_swap(&mut router, creator.clone(), marketplace).unwrap(); - - let pools = create_pool_fixtures( - &mut router, - infinity_swap.clone(), - collection, - creator, - user, - asset_account, - 0, - 50, - ); - - let pool_query = QueryMsg::PoolsById { - pool_ids: vec![1, 2, 1000], - }; - - let res: PoolsByIdResponse = router - .wrap() - .query_wasm_smart(infinity_swap, &pool_query) - .unwrap(); - assert_eq!(res.pools[0], (1, Some(pools[0].clone()))); - assert_eq!(res.pools[1], (2, Some(pools[1].clone()))); - assert_eq!(res.pools[2], (1000, None)); -} - -#[test] -fn try_query_pools_by_owner() { - let vt = standard_minter_template(5000); - let (mut router, creator, _bidder) = (vt.router, vt.accts.creator, vt.accts.bidder); - let collection = vt.collection_response_vec[0].collection.clone().unwrap(); - let user = setup_addtl_account(&mut router, USER, 1_000_000).unwrap(); - let asset_account = Addr::unchecked(ASSET_ACCOUNT); - - let marketplace = setup_marketplace(&mut router, creator.clone()).unwrap(); - let infinity_swap = setup_infinity_swap(&mut router, creator.clone(), marketplace).unwrap(); - - let pools = create_pool_fixtures( - &mut router, - infinity_swap.clone(), - collection, - creator, - user.clone(), - asset_account, - 0, - 50, - ); - - let pool_query = QueryMsg::PoolsByOwner { - owner: user.to_string(), - query_options: QueryOptions { - descending: Some(false), - start_after: Some(9u64), - limit: Some(3), - }, - }; - - let res: PoolsResponse = router - .wrap() - .query_wasm_smart(infinity_swap, &pool_query) - .unwrap(); - assert_eq!(res.pools.len(), 3); - assert_eq!(res.pools[0], pools[9].clone()); - assert_eq!(res.pools[1], pools[10].clone()); - assert_eq!(res.pools[2], pools[11].clone()); -} - -#[test] -fn try_query_pools_by_buy_price() { - let vt = standard_minter_template(5000); - let (mut router, creator, _bidder) = (vt.router, vt.accts.creator, vt.accts.bidder); - let collection = vt.collection_response_vec[0].collection.clone().unwrap(); - let minter = vt.collection_response_vec[0].minter.clone().unwrap(); - let asset_account = Addr::unchecked(ASSET_ACCOUNT); - - let marketplace = setup_marketplace(&mut router, creator.clone()).unwrap(); - let infinity_swap = setup_infinity_swap(&mut router, creator.clone(), marketplace).unwrap(); - - setup_block_time(&mut router, GENESIS_MINT_START_TIME, None); - - let _pools = create_and_activate_pool_fixtures( - &mut router, - infinity_swap.clone(), - minter, - collection.clone(), - creator, - asset_account, - 0, - 50, - ); - - let pool_query = QueryMsg::QuotesBuyFromPool { - collection: collection.to_string(), - query_options: QueryOptions { - descending: None, - start_after: None, - limit: None, - }, - }; - - let res: PoolQuoteResponse = router - .wrap() - .query_wasm_smart(infinity_swap, &pool_query) - .unwrap(); - - let expected_pool_quotes = vec![ - PoolQuote { - id: 3, - collection: Addr::unchecked("contract2"), - quote_price: Uint128::from(300u128), - }, - PoolQuote { - id: 4, - collection: Addr::unchecked("contract2"), - quote_price: Uint128::from(400u128), - }, - PoolQuote { - id: 5, - collection: Addr::unchecked("contract2"), - quote_price: Uint128::from(550u128), - }, - PoolQuote { - id: 6, - collection: Addr::unchecked("contract2"), - quote_price: Uint128::from(637u128), - }, - PoolQuote { - id: 10, - collection: Addr::unchecked("contract2"), - quote_price: Uint128::from(1000u128), - }, - PoolQuote { - id: 11, - collection: Addr::unchecked("contract2"), - quote_price: Uint128::from(1100u128), - }, - PoolQuote { - id: 12, - collection: Addr::unchecked("contract2"), - quote_price: Uint128::from(1320u128), - }, - PoolQuote { - id: 13, - collection: Addr::unchecked("contract2"), - quote_price: Uint128::from(1470u128), - }, - PoolQuote { - id: 7, - collection: Addr::unchecked("contract2"), - quote_price: Uint128::from(3001u128), - }, - PoolQuote { - id: 14, - collection: Addr::unchecked("contract2"), - quote_price: Uint128::from(3001u128), - }, - ]; - - assert_eq!(res.pool_quotes.len(), expected_pool_quotes.len()); - for (id, pq) in res.pool_quotes.iter().enumerate() { - assert_eq!(pq, &expected_pool_quotes[id]); - } -} - -#[test] -fn try_query_pools_by_sell_price() { - let vt = standard_minter_template(5000); - let (mut router, creator, _bidder) = (vt.router, vt.accts.creator, vt.accts.bidder); - let collection = vt.collection_response_vec[0].collection.clone().unwrap(); - let minter = vt.collection_response_vec[0].minter.clone().unwrap(); - let _user = setup_addtl_account(&mut router, USER, 1_000_000).unwrap(); - let asset_account = Addr::unchecked(ASSET_ACCOUNT); - - let marketplace = setup_marketplace(&mut router, creator.clone()).unwrap(); - let infinity_swap = setup_infinity_swap(&mut router, creator.clone(), marketplace).unwrap(); - - setup_block_time(&mut router, GENESIS_MINT_START_TIME, None); - - let _pools = create_and_activate_pool_fixtures( - &mut router, - infinity_swap.clone(), - minter, - collection.clone(), - creator, - asset_account, - 0, - 50, - ); - - let pool_query = QueryMsg::QuotesSellToPool { - collection: collection.to_string(), - query_options: QueryOptions { - descending: None, - start_after: None, - limit: None, - }, - }; - - let res: PoolQuoteResponse = router - .wrap() - .query_wasm_smart(infinity_swap, &pool_query) - .unwrap(); - assert_eq!(res.pool_quotes.len(), 10); - let expected_pool_quotes = vec![ - PoolQuote { - id: 13, - collection: Addr::unchecked("contract2"), - quote_price: Uint128::from(1300u64), - }, - PoolQuote { - id: 12, - collection: Addr::unchecked("contract2"), - quote_price: Uint128::from(1200u64), - }, - PoolQuote { - id: 14, - collection: Addr::unchecked("contract2"), - quote_price: Uint128::from(1000u64), - }, - PoolQuote { - id: 7, - collection: Addr::unchecked("contract2"), - quote_price: Uint128::from(1000u64), - }, - PoolQuote { - id: 9, - collection: Addr::unchecked("contract2"), - quote_price: Uint128::from(900u64), - }, - PoolQuote { - id: 8, - collection: Addr::unchecked("contract2"), - quote_price: Uint128::from(800u64), - }, - PoolQuote { - id: 6, - collection: Addr::unchecked("contract2"), - quote_price: Uint128::from(600u64), - }, - PoolQuote { - id: 5, - collection: Addr::unchecked("contract2"), - quote_price: Uint128::from(500u64), - }, - PoolQuote { - id: 2, - collection: Addr::unchecked("contract2"), - quote_price: Uint128::from(200u64), - }, - PoolQuote { - id: 1, - collection: Addr::unchecked("contract2"), - quote_price: Uint128::from(100u64), - }, - ]; - for (id, pq) in res.pool_quotes.iter().enumerate() { - assert_eq!(pq, &expected_pool_quotes[id]); - } -} - -#[test] -fn try_query_pool_nft_token_ids() { - let vt = standard_minter_template(5000); - let (mut router, creator, _bidder) = (vt.router, vt.accts.creator, vt.accts.bidder); - let collection = vt.collection_response_vec[0].collection.clone().unwrap(); - let minter = vt.collection_response_vec[0].minter.clone().unwrap(); - let owner = setup_addtl_account(&mut router, USER, 1_000_000_000).unwrap(); - let _asset_account = Addr::unchecked(ASSET_ACCOUNT); - - let marketplace = setup_marketplace(&mut router, creator.clone()).unwrap(); - let infinity_swap = setup_infinity_swap(&mut router, creator.clone(), marketplace).unwrap(); - - setup_block_time(&mut router, GENESIS_MINT_START_TIME, None); - - let owner_token_ids = mint_and_approve_many( - &mut router, - &creator, - &owner, - &minter, - &collection, - &infinity_swap, - 500, - ); - - let pool = prepare_swap_pool( - &mut router, - &infinity_swap.clone(), - &owner, - Uint128::from(1_000_000u128), - owner_token_ids.clone(), - true, - ExecuteMsg::CreateTradePool { - collection: collection.to_string(), - asset_recipient: None, - bonding_curve: BondingCurve::ConstantProduct, - spot_price: Uint128::zero(), - delta: Uint128::zero(), - finders_fee_bps: 0, - swap_fee_bps: 0, - reinvest_tokens: true, - reinvest_nfts: true, - }, - ) - .unwrap(); - - let mut expected_token_ids = vec![]; - let mut start_after = None; - loop { - let response: NftTokenIdsResponse = router - .wrap() - .query_wasm_smart( - infinity_swap.clone(), - &QueryMsg::PoolNftTokenIds { - pool_id: pool.id, - query_options: QueryOptions { - descending: None, - start_after: start_after.clone(), - limit: None, - }, - }, - ) - .unwrap(); - if response.nft_token_ids.is_empty() { - break; - } - start_after = Some(response.nft_token_ids.last().unwrap().to_string()); - expected_token_ids.extend(response.nft_token_ids); - } - assert_eq!(expected_token_ids.len(), owner_token_ids.len()); -} diff --git a/test/unit/src/infinity_swap_tests/sim_tests/get_messages.rs b/test/unit/src/infinity_swap_tests/sim_tests/get_messages.rs deleted file mode 100644 index a35e91f..0000000 --- a/test/unit/src/infinity_swap_tests/sim_tests/get_messages.rs +++ /dev/null @@ -1,134 +0,0 @@ -use std::vec; - -use cosmwasm_std::Timestamp; -use cosmwasm_std::{Addr, Uint128}; -use infinity_swap::msg::PoolNftSwap; -use infinity_swap::msg::QueryMsg::SimDirectSwapNftsForTokens; -use infinity_swap::msg::QueryMsg::SimDirectSwapTokensForSpecificNfts; -use infinity_swap::msg::QueryMsg::SimSwapNftsForTokens; -use infinity_swap::msg::QueryMsg::SimSwapTokensForAnyNfts; -use infinity_swap::msg::QueryMsg::SimSwapTokensForSpecificNfts; -use infinity_swap::msg::{self}; -use infinity_swap::msg::{NftSwap, SwapParams}; -use infinity_swap::state::Pool; -use sg_std::GENESIS_MINT_START_TIME; - -pub fn get_sim_swap_message( - pool: Pool, - token_id_1: u32, - token_amount: u128, - robust: bool, - user2: Addr, - finder: Option, -) -> msg::QueryMsg { - SimDirectSwapNftsForTokens { - pool_id: pool.id, - nfts_to_swap: vec![NftSwap { - nft_token_id: token_id_1.to_string(), - token_amount: Uint128::new(token_amount), - }], - sender: user2.to_string(), - swap_params: SwapParams { - deadline: Timestamp::from_nanos(GENESIS_MINT_START_TIME).plus_seconds(1000), - robust, - asset_recipient: None, - finder, - }, - } -} - -pub fn get_sim_swap_nfts_for_tokens_msg( - collection: &Addr, - token_id_1: u32, - token_amount: u128, - robust: bool, - user2: Addr, - finder: Option, -) -> msg::QueryMsg { - SimSwapNftsForTokens { - collection: collection.to_string(), - nfts_to_swap: vec![NftSwap { - nft_token_id: token_id_1.to_string(), - token_amount: Uint128::new(token_amount), - }], - sender: user2.to_string(), - swap_params: SwapParams { - deadline: Timestamp::from_nanos(GENESIS_MINT_START_TIME).plus_seconds(1000), - robust, - asset_recipient: None, - finder, - }, - } -} - -pub fn get_sim_direct_swap_tokens_for_specific_nfts_msg( - pool: Pool, - token_id_1: u32, - token_amount: u128, - robust: bool, - user2: Addr, - finder: Option, -) -> msg::QueryMsg { - SimDirectSwapTokensForSpecificNfts { - pool_id: pool.id, - nfts_to_swap_for: vec![NftSwap { - nft_token_id: token_id_1.to_string(), - token_amount: Uint128::new(token_amount), - }], - sender: user2.to_string(), - swap_params: SwapParams { - deadline: Timestamp::from_nanos(GENESIS_MINT_START_TIME).plus_seconds(1000), - robust, - asset_recipient: None, - finder, - }, - } -} - -pub fn get_swap_tokens_for_specific_nfts_msg( - pool: Pool, - collection: Addr, - token_id_1: u32, - token_amount: u128, - robust: bool, - user2: Addr, - finder: Option, -) -> msg::QueryMsg { - SimSwapTokensForSpecificNfts { - pool_nfts_to_swap_for: vec![PoolNftSwap { - pool_id: pool.id, - nft_swaps: vec![NftSwap { - nft_token_id: token_id_1.to_string(), - token_amount: Uint128::new(token_amount), - }], - }], - sender: user2.to_string(), - collection: collection.to_string(), - swap_params: SwapParams { - deadline: Timestamp::from_nanos(GENESIS_MINT_START_TIME).plus_seconds(1000), - robust, - asset_recipient: None, - finder, - }, - } -} - -pub fn get_swap_tokens_for_any_nfts_msg( - collection: Addr, - max_expected_token_input: Vec, - robust: bool, - user2: Addr, - finder: Option, -) -> msg::QueryMsg { - SimSwapTokensForAnyNfts { - sender: user2.to_string(), - collection: collection.to_string(), - max_expected_token_input, - swap_params: SwapParams { - deadline: Timestamp::from_nanos(GENESIS_MINT_START_TIME).plus_seconds(1000), - robust, - asset_recipient: None, - finder, - }, - } -} diff --git a/test/unit/src/infinity_swap_tests/sim_tests/helpers.rs b/test/unit/src/infinity_swap_tests/sim_tests/helpers.rs deleted file mode 100644 index bb9fa4e..0000000 --- a/test/unit/src/infinity_swap_tests/sim_tests/helpers.rs +++ /dev/null @@ -1,400 +0,0 @@ -use std::vec; - -use crate::helpers::nft_functions::{approve, mint}; -use crate::helpers::pool_functions::create_pool; -use crate::setup::setup_infinity_swap::setup_infinity_swap; -use crate::setup::setup_marketplace::setup_marketplace_trading_fee; -use crate::swap_processor::{NftPayment, Swap, TokenPayment}; -use cosmwasm_std::{coins, Addr, Uint128}; -use cw_multi_test::Executor; -use infinity_swap::msg::ExecuteMsg; -use infinity_swap::state::BondingCurve; -use infinity_swap::state::Pool; -use infinity_swap::state::PoolType; -use sg_multi_test::StargazeApp; -use sg_std::{GENESIS_MINT_START_TIME, NATIVE_DENOM}; -use test_suite::common_setup::setup_accounts_and_block::setup_block_time; - -pub const ASSET_ACCOUNT: &str = "asset"; - -#[derive(Debug)] -pub struct SwapPoolResult { - pub user1: Addr, - pub user2: Addr, - pub creator: Addr, - pub minter: Addr, - pub collection: Addr, - pub infinity_swap: Addr, - pub pool: Pool, -} - -pub struct SwapPoolSetup { - pub pool_type: PoolType, - pub spot_price: u128, - pub finders_fee_bps: Option, -} - -pub struct VendingTemplateSetup<'a> { - pub minter: &'a Addr, - pub collection: &'a Addr, - pub creator: Addr, - pub user1: Addr, - pub user2: Addr, -} - -pub struct ProcessSwapPoolResultsResponse { - pub minter: Addr, - pub collection: Addr, - pub infinity_swap: Addr, - pub pool: Pool, - pub creator: Addr, - pub user1: Addr, - pub user2: Addr, - pub token_ids: Vec, -} - -pub struct NftSaleCheckParams { - pub expected_spot_price: u128, - pub expected_royalty_price: u128, - pub expected_network_fee: u128, - pub expected_finders_fee: u128, - pub swaps: Vec, - pub creator: Addr, - pub expected_seller: Addr, - pub token_id: String, - pub expected_nft_payer: Addr, - pub expected_finder: Addr, -} - -pub fn setup_swap_pool( - router: &mut StargazeApp, - vts: VendingTemplateSetup, - swap_pool_configs: Vec, - trading_fee: Option, -) -> Vec> { - let (minter, creator, user1, user2) = (vts.minter, vts.creator, vts.user1, vts.user2); - let minter = minter.to_owned(); - - let collection = vts.collection; - let asset_account = Addr::unchecked(ASSET_ACCOUNT); - - let marketplace = setup_marketplace_trading_fee(router, creator.clone(), trading_fee).unwrap(); - - setup_block_time(router, GENESIS_MINT_START_TIME, None); - let infinity_swap = setup_infinity_swap(router, creator.clone(), marketplace).unwrap(); - - let mut results: Vec> = vec![]; - - for swap_pool_config in swap_pool_configs { - let infinity_swap = infinity_swap.clone(); - let creator = creator.clone(); - let user1 = user1.clone(); - let user2 = user2.clone(); - let minter = minter.clone(); - let collection = collection.clone(); - - let create_pool_msg = match swap_pool_config.pool_type { - PoolType::Token => ExecuteMsg::CreateTokenPool { - collection: collection.to_string(), - asset_recipient: Some(asset_account.to_string()), - bonding_curve: BondingCurve::Linear, - spot_price: Uint128::from(swap_pool_config.spot_price), - delta: Uint128::from(100u64), - finders_fee_bps: swap_pool_config.finders_fee_bps.unwrap_or(0), - }, - PoolType::Nft => ExecuteMsg::CreateNftPool { - collection: collection.to_string(), - asset_recipient: Some(asset_account.to_string()), - bonding_curve: BondingCurve::Linear, - spot_price: Uint128::from(swap_pool_config.spot_price), - delta: Uint128::from(100u64), - finders_fee_bps: swap_pool_config.finders_fee_bps.unwrap_or(0), - }, - PoolType::Trade => ExecuteMsg::CreateTradePool { - collection: collection.to_string(), - asset_recipient: Some(asset_account.to_string()), - bonding_curve: BondingCurve::Linear, - spot_price: Uint128::from(swap_pool_config.spot_price), - delta: Uint128::from(100u64), - finders_fee_bps: swap_pool_config.finders_fee_bps.unwrap_or(0), - swap_fee_bps: 0u64, - reinvest_tokens: false, - reinvest_nfts: false, - }, - }; - - // Can create a Linear Nft Pool - let pool_result = create_pool( - router, - infinity_swap.clone(), - creator.clone(), - create_pool_msg, - ); - let result = match pool_result { - Ok(result) => Ok(SwapPoolResult { - user1, - user2, - creator, - minter, - collection, - infinity_swap, - pool: result, - }), - Err(err) => Err(err), - }; - results.push(result); - } - results -} -pub struct DepositNftsResult { - pub token_id_1: u32, - pub token_id_2: u32, -} - -pub fn deposit_nfts_and_tokens( - router: &mut StargazeApp, - minter: Addr, - collection: Addr, - infinity_swap: Addr, - pool: Pool, - creator: Addr, - deposit_amount: u128, -) -> DepositNftsResult { - let tokens = deposit_nfts( - router, - minter, - collection, - infinity_swap.clone(), - pool.clone(), - creator.clone(), - ); - let _ = deposit_tokens(router, deposit_amount, infinity_swap, pool, creator); - DepositNftsResult { - token_id_1: tokens.token_id_1, - token_id_2: tokens.token_id_2, - } -} - -pub fn deposit_nfts( - router: &mut StargazeApp, - minter: Addr, - collection: Addr, - infinity_swap: Addr, - pool: Pool, - creator: Addr, -) -> DepositNftsResult { - let token_id_1 = mint(router, &creator, &minter); - approve(router, &creator, &collection, &infinity_swap, token_id_1); - let token_id_2 = mint(router, &creator, &minter); - approve(router, &creator, &collection, &infinity_swap, token_id_2); - let msg = ExecuteMsg::DepositNfts { - pool_id: pool.id, - collection: collection.to_string(), - nft_token_ids: vec![token_id_1.to_string(), token_id_2.to_string()], - }; - let _ = router.execute_contract(creator, infinity_swap, &msg, &[]); - - DepositNftsResult { - token_id_1, - token_id_2, - } -} - -pub fn deposit_one_nft( - router: &mut StargazeApp, - minter: Addr, - collection: Addr, - infinity_swap: Addr, - pool: Pool, - creator: Addr, -) -> u32 { - let token_id_1 = mint(router, &creator, &minter); - approve(router, &creator, &collection, &infinity_swap, token_id_1); - - let msg = ExecuteMsg::DepositNfts { - pool_id: pool.id, - collection: collection.to_string(), - nft_token_ids: vec![token_id_1.to_string()], - }; - let _ = router.execute_contract(creator, infinity_swap, &msg, &[]); - token_id_1 -} - -pub fn deposit_tokens( - router: &mut StargazeApp, - deposit_amount: u128, - infinity_swap: Addr, - pool: Pool, - creator: Addr, -) -> Result<(), anyhow::Error> { - // Owner can deposit tokens - let deposit_amount_1 = deposit_amount; - let msg = ExecuteMsg::DepositTokens { pool_id: pool.id }; - let res = router.execute_contract( - creator, - infinity_swap, - &msg, - &coins(deposit_amount_1, NATIVE_DENOM), - ); - match res { - Ok(_) => Ok(()), - Err(err) => Err(err), - } -} - -fn process_swap_result( - router: &mut StargazeApp, - swap_result: &Result, - deposit_amount: u128, - skip_deposit_nfts: bool, -) -> (u32, Addr, Addr, Addr, Pool, Addr, Addr, Addr) { - let r = swap_result.as_ref().unwrap(); - - set_pool_active( - router, - true, - r.pool.clone(), - r.creator.clone(), - r.infinity_swap.clone(), - ); - let minter = r.minter.clone(); - let collection = r.collection.clone(); - let infinity_swap = r.infinity_swap.clone(); - let pool = r.pool.clone(); - let creator = r.creator.clone(); - let user1 = r.user1.clone(); - let user2 = r.user2.clone(); - let token_id = match skip_deposit_nfts { - false => deposit_one_nft( - router, - minter.clone(), - collection.clone(), - infinity_swap.clone(), - pool.clone(), - creator.clone(), - ), - true => 0, - }; - let _ = deposit_tokens( - router, - deposit_amount, - r.infinity_swap.clone(), - r.pool.clone(), - r.creator.clone(), - ); - - ( - token_id, - minter, - collection, - infinity_swap, - pool, - creator, - user1, - user2, - ) -} -pub fn execute_process_swap_results( - router: &mut StargazeApp, - swap_results: Vec>, - deposit_amounts: Vec, - skip_deposit_nfts: bool, -) -> Vec { - let mut token_ids = vec![]; - for (i, result) in swap_results.iter().enumerate() { - let token_id = process_swap_result(router, result, deposit_amounts[i], skip_deposit_nfts).0; - token_ids.append(&mut vec![token_id]); - } - token_ids.reverse(); - token_ids -} - -pub fn process_swap_results( - router: &mut StargazeApp, - vts: VendingTemplateSetup, - swap_pool_configs: Vec, - deposit_amounts: Vec, - trading_fee: Option, - skip_deposit_nfts: Option, -) -> ProcessSwapPoolResultsResponse { - let mut swap_results: Vec> = - setup_swap_pool(router, vts, swap_pool_configs, trading_fee); - let swap_result = swap_results.pop().unwrap(); - let (token_id, minter, collection, infinity_swap, pool, creator, user1, user2) = - process_swap_result( - router, - &swap_result, - deposit_amounts[0], - skip_deposit_nfts.unwrap_or(false), - ); - let mut token_ids_2 = execute_process_swap_results( - router, - swap_results, - deposit_amounts[1..].into(), - skip_deposit_nfts.unwrap_or(false), - ); - - let mut token_ids = vec![token_id]; - token_ids.append(&mut token_ids_2); - ProcessSwapPoolResultsResponse { - minter, - collection, - infinity_swap, - pool, - creator, - user1, - user2, - token_ids, - } -} - -pub fn set_pool_active( - router: &mut StargazeApp, - is_active: bool, - pool: Pool, - creator: Addr, - infinity_swap: Addr, -) { - let msg = ExecuteMsg::SetActivePool { - is_active, - pool_id: pool.id, - }; - let _ = router.execute_contract(creator, infinity_swap, &msg, &[]); -} - -pub fn check_nft_sale(scp: NftSaleCheckParams) { - assert_eq!(scp.swaps[0].spot_price.u128(), scp.expected_spot_price); - let expected_nft_payment = NftPayment { - nft_token_id: scp.token_id, - address: scp.expected_nft_payer.to_string(), - }; - assert_eq!(scp.swaps[0].nft_payment, expected_nft_payment); - - let network_fee = scp.swaps[0].network_fee.u128(); - - assert_eq!(network_fee, scp.expected_network_fee); - let mut expected_price = scp.expected_spot_price - network_fee; - expected_price -= scp.expected_royalty_price; - expected_price -= scp.expected_finders_fee; - - let expected_seller_payment = Some(TokenPayment { - amount: Uint128::new(expected_price), - address: scp.expected_seller.to_string(), - }); - assert_eq!(scp.swaps[0].seller_payment, expected_seller_payment); - - let expected_finder_payment = match scp.expected_finders_fee { - 0 => None, - _ => Some(TokenPayment { - amount: Uint128::from(scp.expected_finders_fee), - address: scp.expected_finder.to_string(), - }), - }; - assert_eq!(scp.swaps[0].finder_payment, expected_finder_payment); - - let expected_royalty_payment = Some(TokenPayment { - amount: Uint128::new(scp.expected_royalty_price), - address: scp.creator.to_string(), - }); - assert_eq!(scp.swaps[0].royalty_payment, expected_royalty_payment); -} diff --git a/test/unit/src/infinity_swap_tests/sim_tests/mod.rs b/test/unit/src/infinity_swap_tests/sim_tests/mod.rs deleted file mode 100644 index 9708885..0000000 --- a/test/unit/src/infinity_swap_tests/sim_tests/mod.rs +++ /dev/null @@ -1,7 +0,0 @@ -// pub mod get_messages; -// pub mod helpers; -pub mod sim_direct_swap_nfts_for_tokens; -pub mod sim_direct_swap_tokens_for_specific_nfts; -pub mod sim_swap_nfts_for_tokens; -pub mod sim_swap_tokens_for_any_nfts; -pub mod sim_swap_tokens_for_specific_nfts; diff --git a/test/unit/src/infinity_swap_tests/sim_tests/sim_direct_swap_nfts_for_tokens.rs b/test/unit/src/infinity_swap_tests/sim_tests/sim_direct_swap_nfts_for_tokens.rs deleted file mode 100644 index bcc27bd..0000000 --- a/test/unit/src/infinity_swap_tests/sim_tests/sim_direct_swap_nfts_for_tokens.rs +++ /dev/null @@ -1,757 +0,0 @@ -use crate::helpers::nft_functions::mint_and_approve_many; -use crate::helpers::pool_functions::prepare_pool_variations; -use crate::helpers::swap_functions::{setup_swap_test, validate_swap_fees, SwapTestSetup}; -use crate::setup::setup_accounts::setup_addtl_account; -use cosmwasm_std::{StdError, StdResult, Timestamp, Uint128}; -use infinity_swap::msg::{NftSwap, QueryMsg, SwapParams, SwapResponse}; -use sg721_base::msg::{CollectionInfoResponse, QueryMsg as Sg721QueryMsg}; -use sg_marketplace::msg::{ParamsResponse, QueryMsg as MarketplaceQueryMsg}; -use sg_std::GENESIS_MINT_START_TIME; -use test_suite::common_setup::msg::MinterTemplateResponse; - -#[test] -fn cant_swap_inactive_pool() { - let SwapTestSetup { - vending_template: - MinterTemplateResponse { - mut router, - accts, - collection_response_vec, - .. - }, - infinity_swap, - .. - } = setup_swap_test(5000).unwrap(); - - let collection_resp = &collection_response_vec[0]; - let minter = collection_resp.minter.clone().unwrap(); - let collection = collection_resp.collection.clone().unwrap(); - - let owner_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.owner, - &minter, - &collection, - &infinity_swap, - 100, - ); - let bidder_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.bidder, - &minter, - &collection, - &infinity_swap, - 100, - ); - - let deposit_tokens_per_pool = Uint128::from(10_000u128); - let pools = prepare_pool_variations( - &mut router, - 7, - &None, - &infinity_swap, - &collection, - &accts.owner, - deposit_tokens_per_pool, - owner_token_ids.to_vec(), - 6, - false, - 0, - 0, - ); - - for pool in pools { - if !pool.can_buy_nfts() { - continue; - } - let nfts_to_swap: Vec = bidder_token_ids - .to_vec() - .drain(0..3_usize) - .map(|token_id| NftSwap { - nft_token_id: token_id, - token_amount: Uint128::from(100_000u128), - }) - .collect(); - let sim_msg = QueryMsg::SimDirectSwapNftsForTokens { - pool_id: pool.id, - nfts_to_swap, - sender: accts.bidder.to_string(), - swap_params: SwapParams { - deadline: Timestamp::from_nanos(GENESIS_MINT_START_TIME).plus_seconds(1000), - robust: true, - asset_recipient: None, - finder: None, - }, - }; - - let res: StdResult = router - .wrap() - .query_wasm_smart(infinity_swap.clone(), &sim_msg); - assert_eq!( - res.unwrap_err(), - StdError::GenericErr { - msg: "Querier contract error: Generic error: Invalid pool: pool is not active" - .to_string() - } - ); - } -} - -#[test] -fn cant_swap_invalid_pool_type() { - let SwapTestSetup { - vending_template: - MinterTemplateResponse { - mut router, - accts, - collection_response_vec, - .. - }, - infinity_swap, - .. - } = setup_swap_test(5000).unwrap(); - - let collection_resp = &collection_response_vec[0]; - let minter = collection_resp.minter.clone().unwrap(); - let collection = collection_resp.collection.clone().unwrap(); - - let owner_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.owner, - &minter, - &collection, - &infinity_swap, - 100, - ); - let bidder_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.bidder, - &minter, - &collection, - &infinity_swap, - 100, - ); - - let deposit_tokens_per_pool = Uint128::from(10_000u128); - let pools = prepare_pool_variations( - &mut router, - 7, - &None, - &infinity_swap, - &collection, - &accts.owner, - deposit_tokens_per_pool, - owner_token_ids.to_vec(), - 6, - true, - 0, - 0, - ); - - for pool in pools { - if pool.can_buy_nfts() { - continue; - } - let nfts_to_swap: Vec = bidder_token_ids - .to_vec() - .drain(0..3_usize) - .map(|token_id| NftSwap { - nft_token_id: token_id, - token_amount: Uint128::from(100_000u128), - }) - .collect(); - let sim_msg = QueryMsg::SimDirectSwapNftsForTokens { - pool_id: pool.id, - nfts_to_swap, - sender: accts.bidder.to_string(), - swap_params: SwapParams { - deadline: Timestamp::from_nanos(GENESIS_MINT_START_TIME).plus_seconds(1000), - robust: true, - asset_recipient: None, - finder: None, - }, - }; - - let res: StdResult = router - .wrap() - .query_wasm_smart(infinity_swap.clone(), &sim_msg); - assert_eq!( - res.unwrap_err(), - StdError::GenericErr { - msg: "Querier contract error: Generic error: Invalid pool: pool cannot buy nfts" - .to_string() - } - ); - } -} - -#[test] -fn can_swap_active_pool() { - let SwapTestSetup { - vending_template: - MinterTemplateResponse { - mut router, - accts, - collection_response_vec, - .. - }, - infinity_swap, - .. - } = setup_swap_test(5000).unwrap(); - - let collection_resp = &collection_response_vec[0]; - let minter = collection_resp.minter.clone().unwrap(); - let collection = collection_resp.collection.clone().unwrap(); - - let owner_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.owner, - &minter, - &collection, - &infinity_swap, - 100, - ); - let bidder_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.bidder, - &minter, - &collection, - &infinity_swap, - 100, - ); - - let deposit_tokens_per_pool = Uint128::from(10_000u128); - let pools = prepare_pool_variations( - &mut router, - 7, - &None, - &infinity_swap, - &collection, - &accts.owner, - deposit_tokens_per_pool, - owner_token_ids.to_vec(), - 6, - true, - 0, - 0, - ); - - for pool in pools { - if !pool.can_buy_nfts() { - continue; - } - let nfts_to_swap: Vec = bidder_token_ids - .to_vec() - .drain(0..3_usize) - .map(|token_id| NftSwap { - nft_token_id: token_id, - token_amount: Uint128::from(10u128), - }) - .collect(); - - let sim_msg = QueryMsg::SimDirectSwapNftsForTokens { - pool_id: pool.id, - nfts_to_swap, - sender: accts.bidder.to_string(), - swap_params: SwapParams { - deadline: Timestamp::from_nanos(GENESIS_MINT_START_TIME).plus_seconds(1000), - robust: false, - asset_recipient: None, - finder: None, - }, - }; - - let res: StdResult = router - .wrap() - .query_wasm_smart(infinity_swap.clone(), &sim_msg); - assert_eq!(res.unwrap().swaps.len(), 3); - } -} - -#[test] -fn insufficient_tokens_error() { - let SwapTestSetup { - vending_template: - MinterTemplateResponse { - mut router, - accts, - collection_response_vec, - .. - }, - infinity_swap, - .. - } = setup_swap_test(5000).unwrap(); - - let collection_resp = &collection_response_vec[0]; - let minter = collection_resp.minter.clone().unwrap(); - let collection = collection_resp.collection.clone().unwrap(); - - let owner_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.owner, - &minter, - &collection, - &infinity_swap, - 100, - ); - let bidder_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.bidder, - &minter, - &collection, - &infinity_swap, - 100, - ); - - let deposit_tokens_per_pool = Uint128::from(1u128); - let pools = prepare_pool_variations( - &mut router, - 7, - &None, - &infinity_swap, - &collection, - &accts.owner, - deposit_tokens_per_pool, - owner_token_ids.to_vec(), - 6, - true, - 0, - 0, - ); - - for pool in pools { - if !pool.can_buy_nfts() { - continue; - } - let nfts_to_swap: Vec = bidder_token_ids - .to_vec() - .drain(0..3_usize) - .map(|token_id| NftSwap { - nft_token_id: token_id, - token_amount: Uint128::from(100_000u128), - }) - .collect(); - let sim_msg = QueryMsg::SimDirectSwapNftsForTokens { - pool_id: pool.id, - nfts_to_swap, - sender: accts.bidder.to_string(), - swap_params: SwapParams { - deadline: Timestamp::from_nanos(GENESIS_MINT_START_TIME).plus_seconds(1000), - robust: true, - asset_recipient: None, - finder: None, - }, - }; - - let res: StdResult = router - .wrap() - .query_wasm_smart(infinity_swap.clone(), &sim_msg); - assert_eq!( - res.unwrap_err(), - StdError::GenericErr { - msg: format!("Querier contract error: Generic error: No quote for pool: pool {} cannot offer quote", pool.id) - .to_string() - } - ); - } -} - -#[test] -fn sale_price_below_min_expected() { - let SwapTestSetup { - vending_template: - MinterTemplateResponse { - mut router, - accts, - collection_response_vec, - .. - }, - infinity_swap, - .. - } = setup_swap_test(5000).unwrap(); - - let collection_resp = &collection_response_vec[0]; - let minter = collection_resp.minter.clone().unwrap(); - let collection = collection_resp.collection.clone().unwrap(); - - let owner_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.owner, - &minter, - &collection, - &infinity_swap, - 100, - ); - let bidder_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.bidder, - &minter, - &collection, - &infinity_swap, - 100, - ); - - let deposit_tokens_per_pool = Uint128::from(100_000u128); - let pools = prepare_pool_variations( - &mut router, - 7, - &None, - &infinity_swap, - &collection, - &accts.owner, - deposit_tokens_per_pool, - owner_token_ids.to_vec(), - 6, - true, - 0, - 0, - ); - - for pool in pools { - if !pool.can_buy_nfts() { - continue; - } - let nfts_to_swap: Vec = bidder_token_ids - .to_vec() - .drain(0..3_usize) - .map(|token_id| NftSwap { - nft_token_id: token_id, - token_amount: Uint128::from(1_000_000u128), - }) - .collect(); - let sim_msg = QueryMsg::SimDirectSwapNftsForTokens { - pool_id: pool.id, - nfts_to_swap, - sender: accts.bidder.to_string(), - swap_params: SwapParams { - deadline: Timestamp::from_nanos(GENESIS_MINT_START_TIME).plus_seconds(1000), - robust: false, - asset_recipient: None, - finder: None, - }, - }; - - let res: StdResult = router - .wrap() - .query_wasm_smart(infinity_swap.clone(), &sim_msg); - assert_eq!( - res.unwrap_err(), - StdError::GenericErr { - msg: "Querier contract error: Generic error: Swap error: pool sale price is below min expected" - .to_string() - } - ); - } -} - -#[test] -fn robust_query_does_not_revert_whole_tx_on_error() { - let SwapTestSetup { - vending_template: - MinterTemplateResponse { - mut router, - accts, - collection_response_vec, - .. - }, - infinity_swap, - .. - } = setup_swap_test(5000).unwrap(); - - let collection_resp = &collection_response_vec[0]; - let minter = collection_resp.minter.clone().unwrap(); - let collection = collection_resp.collection.clone().unwrap(); - - let owner_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.owner, - &minter, - &collection, - &infinity_swap, - 100, - ); - let bidder_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.bidder, - &minter, - &collection, - &infinity_swap, - 100, - ); - - let deposit_tokens_per_pool = Uint128::from(100_000u128); - let pools = prepare_pool_variations( - &mut router, - 7, - &None, - &infinity_swap, - &collection, - &accts.owner, - deposit_tokens_per_pool, - owner_token_ids.to_vec(), - 6, - true, - 0, - 0, - ); - - for pool in pools { - if !pool.can_buy_nfts() { - continue; - } - let mut nfts_to_swap: Vec = bidder_token_ids - .to_vec() - .drain(0..2_usize) - .map(|token_id| NftSwap { - nft_token_id: token_id, - token_amount: Uint128::from(10u128), - }) - .collect(); - nfts_to_swap.extend( - bidder_token_ids - .to_vec() - .drain(0..1_usize) - .map(|token_id| NftSwap { - nft_token_id: token_id, - token_amount: Uint128::from(1_000_000u128), - }) - .collect::>(), - ); - - let sim_msg = QueryMsg::SimDirectSwapNftsForTokens { - pool_id: pool.id, - nfts_to_swap, - sender: accts.bidder.to_string(), - swap_params: SwapParams { - deadline: Timestamp::from_nanos(GENESIS_MINT_START_TIME).plus_seconds(1000), - robust: true, - asset_recipient: None, - finder: None, - }, - }; - - let res: StdResult = router - .wrap() - .query_wasm_smart(infinity_swap.clone(), &sim_msg); - assert_eq!(res.unwrap().swaps.len(), 2); - } -} - -#[test] -fn minimal_fee_tx_is_handled_correctly() { - let SwapTestSetup { - vending_template: - MinterTemplateResponse { - mut router, - accts, - collection_response_vec, - .. - }, - infinity_swap, - marketplace, - .. - } = setup_swap_test(5000).unwrap(); - - let collection_resp = &collection_response_vec[0]; - let minter = collection_resp.minter.clone().unwrap(); - let collection = collection_resp.collection.clone().unwrap(); - - let owner_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.owner, - &minter, - &collection, - &infinity_swap, - 100, - ); - let bidder_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.bidder, - &minter, - &collection, - &infinity_swap, - 100, - ); - - let deposit_tokens_per_pool = Uint128::from(100_000u128); - let pools = prepare_pool_variations( - &mut router, - 7, - &None, - &infinity_swap, - &collection, - &accts.owner, - deposit_tokens_per_pool, - owner_token_ids.to_vec(), - 6, - true, - 0, - 0, - ); - - let marketplace_params: ParamsResponse = router - .wrap() - .query_wasm_smart(marketplace, &MarketplaceQueryMsg::Params {}) - .unwrap(); - let collection_info: CollectionInfoResponse = router - .wrap() - .query_wasm_smart(collection.clone(), &Sg721QueryMsg::CollectionInfo {}) - .unwrap(); - - for pool in pools { - if !pool.can_buy_nfts() { - continue; - } - let nfts_to_swap: Vec = bidder_token_ids - .to_vec() - .drain(0..3_usize) - .map(|token_id| NftSwap { - nft_token_id: token_id, - token_amount: Uint128::from(10u128), - }) - .collect(); - - let sim_msg = QueryMsg::SimDirectSwapNftsForTokens { - pool_id: pool.id, - nfts_to_swap, - sender: accts.bidder.to_string(), - swap_params: SwapParams { - deadline: Timestamp::from_nanos(GENESIS_MINT_START_TIME).plus_seconds(1000), - robust: true, - asset_recipient: None, - finder: None, - }, - }; - - let res: StdResult = router - .wrap() - .query_wasm_smart(infinity_swap.clone(), &sim_msg); - - for swap in res.unwrap().swaps { - validate_swap_fees( - &swap, - &pool, - &marketplace_params, - &collection_info.royalty_info, - ); - } - } -} - -#[test] -fn finders_and_swap_fee_tx_is_handled_correctly() { - let SwapTestSetup { - vending_template: - MinterTemplateResponse { - mut router, - accts, - collection_response_vec, - .. - }, - infinity_swap, - marketplace, - .. - } = setup_swap_test(5000).unwrap(); - let user2 = setup_addtl_account(&mut router, "asset", 100u128).unwrap(); - - let collection_resp = &collection_response_vec[0]; - let minter = collection_resp.minter.clone().unwrap(); - let collection = collection_resp.collection.clone().unwrap(); - - let owner_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.owner, - &minter, - &collection, - &infinity_swap, - 100, - ); - let bidder_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.bidder, - &minter, - &collection, - &infinity_swap, - 100, - ); - - let deposit_tokens_per_pool = Uint128::from(100_000u128); - let pools = prepare_pool_variations( - &mut router, - 7, - &None, - &infinity_swap, - &collection, - &accts.owner, - deposit_tokens_per_pool, - owner_token_ids.to_vec(), - 6, - true, - 250, - 300, - ); - - let marketplace_params: ParamsResponse = router - .wrap() - .query_wasm_smart(marketplace, &MarketplaceQueryMsg::Params {}) - .unwrap(); - let collection_info: CollectionInfoResponse = router - .wrap() - .query_wasm_smart(collection.clone(), &Sg721QueryMsg::CollectionInfo {}) - .unwrap(); - - for pool in pools { - if !pool.can_buy_nfts() { - continue; - } - let nfts_to_swap: Vec = bidder_token_ids - .to_vec() - .drain(0..3_usize) - .map(|token_id| NftSwap { - nft_token_id: token_id, - token_amount: Uint128::from(10u128), - }) - .collect(); - - let sim_msg = QueryMsg::SimDirectSwapNftsForTokens { - pool_id: pool.id, - nfts_to_swap, - sender: accts.bidder.to_string(), - swap_params: SwapParams { - deadline: Timestamp::from_nanos(GENESIS_MINT_START_TIME).plus_seconds(1000), - robust: true, - asset_recipient: None, - finder: Some(user2.to_string()), - }, - }; - - let res: StdResult = router - .wrap() - .query_wasm_smart(infinity_swap.clone(), &sim_msg); - - for swap in res.unwrap().swaps { - validate_swap_fees( - &swap, - &pool, - &marketplace_params, - &collection_info.royalty_info, - ); - } - } -} diff --git a/test/unit/src/infinity_swap_tests/sim_tests/sim_direct_swap_tokens_for_specific_nfts.rs b/test/unit/src/infinity_swap_tests/sim_tests/sim_direct_swap_tokens_for_specific_nfts.rs deleted file mode 100644 index b480aeb..0000000 --- a/test/unit/src/infinity_swap_tests/sim_tests/sim_direct_swap_tokens_for_specific_nfts.rs +++ /dev/null @@ -1,800 +0,0 @@ -use crate::helpers::nft_functions::mint_and_approve_many; -use crate::helpers::pool_functions::prepare_pool_variations; -use crate::helpers::swap_functions::{setup_swap_test, validate_swap_fees, SwapTestSetup}; -use crate::setup::setup_accounts::setup_addtl_account; -use cosmwasm_std::{StdError, StdResult, Timestamp, Uint128}; -use infinity_swap::msg::{ - NftSwap, NftTokenIdsResponse, QueryMsg, QueryOptions, SwapParams, SwapResponse, -}; -use sg721_base::msg::{CollectionInfoResponse, QueryMsg as Sg721QueryMsg}; -use sg_marketplace::msg::{ParamsResponse, QueryMsg as MarketplaceQueryMsg}; -use sg_std::GENESIS_MINT_START_TIME; -use test_suite::common_setup::msg::MinterTemplateResponse; - -#[test] -fn cant_swap_inactive_pool() { - let SwapTestSetup { - vending_template: - MinterTemplateResponse { - mut router, - accts, - collection_response_vec, - .. - }, - infinity_swap, - .. - } = setup_swap_test(5000).unwrap(); - - let collection_resp = &collection_response_vec[0]; - let minter = collection_resp.minter.clone().unwrap(); - let collection = collection_resp.collection.clone().unwrap(); - - let owner_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.owner, - &minter, - &collection, - &infinity_swap, - 100, - ); - - let deposit_tokens_per_pool = Uint128::from(10_000u128); - let pools = prepare_pool_variations( - &mut router, - 7, - &None, - &infinity_swap, - &collection, - &accts.owner, - deposit_tokens_per_pool, - owner_token_ids, - 6, - false, - 0, - 0, - ); - - for pool in pools { - if !pool.can_sell_nfts() { - continue; - } - - let nft_token_ids_response: NftTokenIdsResponse = router - .wrap() - .query_wasm_smart( - infinity_swap.clone(), - &QueryMsg::PoolNftTokenIds { - pool_id: pool.id, - query_options: QueryOptions { - descending: None, - start_after: None, - limit: Some(3), - }, - }, - ) - .unwrap(); - - let nfts_to_swap_for: Vec = nft_token_ids_response - .nft_token_ids - .into_iter() - .map(|token_id| NftSwap { - nft_token_id: token_id, - token_amount: Uint128::from(100_000u128), - }) - .collect(); - let sim_msg = QueryMsg::SimDirectSwapTokensForSpecificNfts { - pool_id: pool.id, - nfts_to_swap_for, - sender: accts.bidder.to_string(), - swap_params: SwapParams { - deadline: Timestamp::from_nanos(GENESIS_MINT_START_TIME).plus_seconds(1000), - robust: true, - asset_recipient: None, - finder: None, - }, - }; - - let res: StdResult = router - .wrap() - .query_wasm_smart(infinity_swap.clone(), &sim_msg); - assert_eq!( - res.unwrap_err(), - StdError::GenericErr { - msg: "Querier contract error: Generic error: Invalid pool: pool is not active" - .to_string() - } - ); - } -} - -#[test] -fn cant_swap_invalid_pool_type() { - let SwapTestSetup { - vending_template: - MinterTemplateResponse { - mut router, - accts, - collection_response_vec, - .. - }, - infinity_swap, - .. - } = setup_swap_test(5000).unwrap(); - - let collection_resp = &collection_response_vec[0]; - let minter = collection_resp.minter.clone().unwrap(); - let collection = collection_resp.collection.clone().unwrap(); - - let owner_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.owner, - &minter, - &collection, - &infinity_swap, - 100, - ); - - let deposit_tokens_per_pool = Uint128::from(10_000u128); - let pools = prepare_pool_variations( - &mut router, - 7, - &None, - &infinity_swap, - &collection, - &accts.owner, - deposit_tokens_per_pool, - owner_token_ids, - 6, - false, - 0, - 0, - ); - - for pool in pools { - if pool.can_sell_nfts() { - continue; - } - let nft_token_ids_response: NftTokenIdsResponse = router - .wrap() - .query_wasm_smart( - infinity_swap.clone(), - &QueryMsg::PoolNftTokenIds { - pool_id: pool.id, - query_options: QueryOptions { - descending: None, - start_after: None, - limit: Some(3), - }, - }, - ) - .unwrap(); - - let nfts_to_swap_for: Vec = nft_token_ids_response - .nft_token_ids - .into_iter() - .map(|token_id| NftSwap { - nft_token_id: token_id, - token_amount: Uint128::from(100_000u128), - }) - .collect(); - let sim_msg = QueryMsg::SimDirectSwapTokensForSpecificNfts { - pool_id: pool.id, - nfts_to_swap_for, - sender: accts.bidder.to_string(), - swap_params: SwapParams { - deadline: Timestamp::from_nanos(GENESIS_MINT_START_TIME).plus_seconds(1000), - robust: true, - asset_recipient: None, - finder: None, - }, - }; - - let res: StdResult = router - .wrap() - .query_wasm_smart(infinity_swap.clone(), &sim_msg); - assert_eq!( - res.unwrap_err(), - StdError::GenericErr { - msg: "Querier contract error: Generic error: Invalid pool: pool cannot sell nfts" - .to_string() - } - ); - } -} - -#[test] -fn can_swap_active_pool() { - let SwapTestSetup { - vending_template: - MinterTemplateResponse { - mut router, - accts, - collection_response_vec, - .. - }, - infinity_swap, - .. - } = setup_swap_test(5000).unwrap(); - - let collection_resp = &collection_response_vec[0]; - let minter = collection_resp.minter.clone().unwrap(); - let collection = collection_resp.collection.clone().unwrap(); - - let owner_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.owner, - &minter, - &collection, - &infinity_swap, - 100, - ); - - let deposit_tokens_per_pool = Uint128::from(10_000u128); - let pools = prepare_pool_variations( - &mut router, - 7, - &None, - &infinity_swap, - &collection, - &accts.owner, - deposit_tokens_per_pool, - owner_token_ids, - 6, - true, - 0, - 0, - ); - - for pool in pools { - if !pool.can_sell_nfts() { - continue; - } - let nft_token_ids_response: NftTokenIdsResponse = router - .wrap() - .query_wasm_smart( - infinity_swap.clone(), - &QueryMsg::PoolNftTokenIds { - pool_id: pool.id, - query_options: QueryOptions { - descending: None, - start_after: None, - limit: Some(3), - }, - }, - ) - .unwrap(); - - let nfts_to_swap_for: Vec = nft_token_ids_response - .nft_token_ids - .into_iter() - .map(|token_id| NftSwap { - nft_token_id: token_id, - token_amount: Uint128::from(100_000u128), - }) - .collect(); - let sim_msg = QueryMsg::SimDirectSwapTokensForSpecificNfts { - pool_id: pool.id, - nfts_to_swap_for, - sender: accts.bidder.to_string(), - swap_params: SwapParams { - deadline: Timestamp::from_nanos(GENESIS_MINT_START_TIME).plus_seconds(1000), - robust: false, - asset_recipient: None, - finder: None, - }, - }; - - let res: StdResult = router - .wrap() - .query_wasm_smart(infinity_swap.clone(), &sim_msg); - assert_eq!(res.unwrap().swaps.len(), 3); - } -} - -#[test] -fn incorrect_nfts_error() { - let SwapTestSetup { - vending_template: - MinterTemplateResponse { - mut router, - accts, - collection_response_vec, - .. - }, - infinity_swap, - .. - } = setup_swap_test(5000).unwrap(); - - let collection_resp = &collection_response_vec[0]; - let minter = collection_resp.minter.clone().unwrap(); - let collection = collection_resp.collection.clone().unwrap(); - - let owner_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.owner, - &minter, - &collection, - &infinity_swap, - 100, - ); - - let mut bidder_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.bidder, - &minter, - &collection, - &infinity_swap, - 100, - ); - - let deposit_tokens_per_pool = Uint128::from(10_000u128); - let pools = prepare_pool_variations( - &mut router, - 7, - &None, - &infinity_swap, - &collection, - &accts.owner, - deposit_tokens_per_pool, - owner_token_ids, - 6, - true, - 0, - 0, - ); - - for pool in pools { - if !pool.can_sell_nfts() { - continue; - } - let nfts_to_swap_for: Vec = bidder_token_ids - .drain(0..3) - .map(|token_id| NftSwap { - nft_token_id: token_id, - token_amount: Uint128::from(100_000u128), - }) - .collect(); - let sim_msg = QueryMsg::SimDirectSwapTokensForSpecificNfts { - pool_id: pool.id, - nfts_to_swap_for: nfts_to_swap_for.clone(), - sender: accts.bidder.to_string(), - swap_params: SwapParams { - deadline: Timestamp::from_nanos(GENESIS_MINT_START_TIME).plus_seconds(1000), - robust: false, - asset_recipient: None, - finder: None, - }, - }; - - let res: StdResult = router - .wrap() - .query_wasm_smart(infinity_swap.clone(), &sim_msg); - assert_eq!( - res.unwrap_err(), - StdError::GenericErr { - msg: format!( - "Querier contract error: Generic error: Swap error: pool {} does not own NFT {}", - pool.id, nfts_to_swap_for[0].nft_token_id - ) - .to_string() - } - ); - } -} - -#[test] -fn sale_price_above_max_expected() { - let SwapTestSetup { - vending_template: - MinterTemplateResponse { - mut router, - accts, - collection_response_vec, - .. - }, - infinity_swap, - .. - } = setup_swap_test(5000).unwrap(); - - let collection_resp = &collection_response_vec[0]; - let minter = collection_resp.minter.clone().unwrap(); - let collection = collection_resp.collection.clone().unwrap(); - - let owner_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.owner, - &minter, - &collection, - &infinity_swap, - 100, - ); - - let deposit_tokens_per_pool = Uint128::from(10_000u128); - let pools = prepare_pool_variations( - &mut router, - 7, - &None, - &infinity_swap, - &collection, - &accts.owner, - deposit_tokens_per_pool, - owner_token_ids, - 6, - true, - 0, - 0, - ); - - for pool in pools { - if !pool.can_sell_nfts() { - continue; - } - let nft_token_ids_response: NftTokenIdsResponse = router - .wrap() - .query_wasm_smart( - infinity_swap.clone(), - &QueryMsg::PoolNftTokenIds { - pool_id: pool.id, - query_options: QueryOptions { - descending: None, - start_after: None, - limit: Some(3), - }, - }, - ) - .unwrap(); - - let nfts_to_swap_for: Vec = nft_token_ids_response - .nft_token_ids - .into_iter() - .map(|token_id| NftSwap { - nft_token_id: token_id, - token_amount: Uint128::from(20u128), - }) - .collect(); - let sim_msg = QueryMsg::SimDirectSwapTokensForSpecificNfts { - pool_id: pool.id, - nfts_to_swap_for, - sender: accts.bidder.to_string(), - swap_params: SwapParams { - deadline: Timestamp::from_nanos(GENESIS_MINT_START_TIME).plus_seconds(1000), - robust: false, - asset_recipient: None, - finder: None, - }, - }; - - let res: StdResult = router - .wrap() - .query_wasm_smart(infinity_swap.clone(), &sim_msg); - - assert_eq!(res.unwrap_err(), StdError::GenericErr { - msg: "Querier contract error: Generic error: Swap error: pool sale price is above max expected" - .to_string(), - }); - } -} - -#[test] -fn robust_query_does_not_revert_whole_tx() { - let SwapTestSetup { - vending_template: - MinterTemplateResponse { - mut router, - accts, - collection_response_vec, - .. - }, - infinity_swap, - .. - } = setup_swap_test(5000).unwrap(); - - let collection_resp = &collection_response_vec[0]; - let minter = collection_resp.minter.clone().unwrap(); - let collection = collection_resp.collection.clone().unwrap(); - - let owner_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.owner, - &minter, - &collection, - &infinity_swap, - 100, - ); - - let deposit_tokens_per_pool = Uint128::from(10_000u128); - let pools = prepare_pool_variations( - &mut router, - 7, - &None, - &infinity_swap, - &collection, - &accts.owner, - deposit_tokens_per_pool, - owner_token_ids, - 6, - true, - 0, - 0, - ); - - for pool in pools { - if !pool.can_sell_nfts() { - continue; - } - let mut nft_token_ids_response: NftTokenIdsResponse = router - .wrap() - .query_wasm_smart( - infinity_swap.clone(), - &QueryMsg::PoolNftTokenIds { - pool_id: pool.id, - query_options: QueryOptions { - descending: None, - start_after: None, - limit: None, - }, - }, - ) - .unwrap(); - - let mut nfts_to_swap_for: Vec = nft_token_ids_response - .nft_token_ids - .drain(0..2_usize) - .map(|token_id| NftSwap { - nft_token_id: token_id, - token_amount: Uint128::from(100_000_u128), - }) - .collect(); - nfts_to_swap_for.extend( - nft_token_ids_response - .nft_token_ids - .drain(0..1_usize) - .map(|token_id| NftSwap { - nft_token_id: token_id, - token_amount: Uint128::from(10_u128), - }) - .collect::>(), - ); - let sim_msg = QueryMsg::SimDirectSwapTokensForSpecificNfts { - pool_id: pool.id, - nfts_to_swap_for, - sender: accts.bidder.to_string(), - swap_params: SwapParams { - deadline: Timestamp::from_nanos(GENESIS_MINT_START_TIME).plus_seconds(1000), - robust: true, - asset_recipient: None, - finder: None, - }, - }; - - let res: StdResult = router - .wrap() - .query_wasm_smart(infinity_swap.clone(), &sim_msg); - assert_eq!(res.unwrap().swaps.len(), 2); - } -} - -#[test] -fn minimal_fee_tx_is_handled_correctly() { - let SwapTestSetup { - vending_template: - MinterTemplateResponse { - mut router, - accts, - collection_response_vec, - .. - }, - infinity_swap, - marketplace, - .. - } = setup_swap_test(5000).unwrap(); - - let collection_resp = &collection_response_vec[0]; - let minter = collection_resp.minter.clone().unwrap(); - let collection = collection_resp.collection.clone().unwrap(); - - let owner_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.owner, - &minter, - &collection, - &infinity_swap, - 100, - ); - - let deposit_tokens_per_pool = Uint128::from(10_000u128); - let pools = prepare_pool_variations( - &mut router, - 7, - &None, - &infinity_swap, - &collection, - &accts.owner, - deposit_tokens_per_pool, - owner_token_ids, - 6, - true, - 0, - 0, - ); - - let marketplace_params: ParamsResponse = router - .wrap() - .query_wasm_smart(marketplace, &MarketplaceQueryMsg::Params {}) - .unwrap(); - let collection_info: CollectionInfoResponse = router - .wrap() - .query_wasm_smart(collection.clone(), &Sg721QueryMsg::CollectionInfo {}) - .unwrap(); - - for pool in pools { - if !pool.can_sell_nfts() { - continue; - } - let nft_token_ids_response: NftTokenIdsResponse = router - .wrap() - .query_wasm_smart( - infinity_swap.clone(), - &QueryMsg::PoolNftTokenIds { - pool_id: pool.id, - query_options: QueryOptions { - descending: None, - start_after: None, - limit: Some(3), - }, - }, - ) - .unwrap(); - - let nfts_to_swap_for: Vec = nft_token_ids_response - .nft_token_ids - .clone() - .into_iter() - .take(3) - .map(|token_id| NftSwap { - nft_token_id: token_id, - token_amount: Uint128::from(100_000_u128), - }) - .collect(); - let sim_msg = QueryMsg::SimDirectSwapTokensForSpecificNfts { - pool_id: pool.id, - nfts_to_swap_for, - sender: accts.bidder.to_string(), - swap_params: SwapParams { - deadline: Timestamp::from_nanos(GENESIS_MINT_START_TIME).plus_seconds(1000), - robust: true, - asset_recipient: None, - finder: None, - }, - }; - let res: StdResult = router - .wrap() - .query_wasm_smart(infinity_swap.clone(), &sim_msg); - - for swap in res.unwrap().swaps { - validate_swap_fees( - &swap, - &pool, - &marketplace_params, - &collection_info.royalty_info, - ); - } - } -} - -#[test] -fn finders_and_swap_fee_tx_is_handled_correctly() { - let SwapTestSetup { - vending_template: - MinterTemplateResponse { - mut router, - accts, - collection_response_vec, - .. - }, - infinity_swap, - marketplace, - .. - } = setup_swap_test(5000).unwrap(); - let user2 = setup_addtl_account(&mut router, "asset", 100_u128).unwrap(); - - let collection_resp = &collection_response_vec[0]; - let minter = collection_resp.minter.clone().unwrap(); - let collection = collection_resp.collection.clone().unwrap(); - - let owner_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.owner, - &minter, - &collection, - &infinity_swap, - 100, - ); - - let deposit_tokens_per_pool = Uint128::from(10_000_u128); - let pools = prepare_pool_variations( - &mut router, - 7, - &None, - &infinity_swap, - &collection, - &accts.owner, - deposit_tokens_per_pool, - owner_token_ids, - 6, - true, - 250, - 300, - ); - - let marketplace_params: ParamsResponse = router - .wrap() - .query_wasm_smart(marketplace, &MarketplaceQueryMsg::Params {}) - .unwrap(); - let collection_info: CollectionInfoResponse = router - .wrap() - .query_wasm_smart(collection.clone(), &Sg721QueryMsg::CollectionInfo {}) - .unwrap(); - - for pool in pools { - if !pool.can_sell_nfts() { - continue; - } - let nft_token_ids_response: NftTokenIdsResponse = router - .wrap() - .query_wasm_smart( - infinity_swap.clone(), - &QueryMsg::PoolNftTokenIds { - pool_id: pool.id, - query_options: QueryOptions { - descending: None, - start_after: None, - limit: Some(3), - }, - }, - ) - .unwrap(); - - let nfts_to_swap_for: Vec = nft_token_ids_response - .nft_token_ids - .clone() - .into_iter() - .map(|token_id| NftSwap { - nft_token_id: token_id, - token_amount: Uint128::from(100_000_u128), - }) - .collect(); - let sim_msg = QueryMsg::SimDirectSwapTokensForSpecificNfts { - pool_id: pool.id, - nfts_to_swap_for, - sender: accts.bidder.to_string(), - swap_params: SwapParams { - deadline: Timestamp::from_nanos(GENESIS_MINT_START_TIME).plus_seconds(1000), - robust: true, - asset_recipient: None, - finder: Some(user2.to_string()), - }, - }; - let res: StdResult = router - .wrap() - .query_wasm_smart(infinity_swap.clone(), &sim_msg); - - for swap in res.unwrap().swaps { - validate_swap_fees( - &swap, - &pool, - &marketplace_params, - &collection_info.royalty_info, - ); - } - } -} diff --git a/test/unit/src/infinity_swap_tests/sim_tests/sim_swap_nfts_for_tokens.rs b/test/unit/src/infinity_swap_tests/sim_tests/sim_swap_nfts_for_tokens.rs deleted file mode 100644 index 3d79f15..0000000 --- a/test/unit/src/infinity_swap_tests/sim_tests/sim_swap_nfts_for_tokens.rs +++ /dev/null @@ -1,624 +0,0 @@ -use crate::helpers::nft_functions::mint_and_approve_many; -use crate::helpers::pool_functions::prepare_pool_variations; -use crate::helpers::swap_functions::{setup_swap_test, validate_swap_fees, SwapTestSetup}; -use crate::setup::setup_accounts::setup_addtl_account; -use cosmwasm_std::{StdError, StdResult, Timestamp, Uint128}; -use infinity_swap::msg::{NftSwap, QueryMsg, SwapParams, SwapResponse}; -use sg721_base::msg::{CollectionInfoResponse, QueryMsg as Sg721QueryMsg}; -use sg_marketplace::msg::{ParamsResponse, QueryMsg as MarketplaceQueryMsg}; -use sg_std::GENESIS_MINT_START_TIME; -use test_suite::common_setup::msg::MinterTemplateResponse; - -#[test] -fn cant_swap_inactive_pools() { - let SwapTestSetup { - vending_template: - MinterTemplateResponse { - mut router, - accts, - collection_response_vec, - .. - }, - infinity_swap, - .. - } = setup_swap_test(5000).unwrap(); - - let collection_resp = &collection_response_vec[0]; - let minter = collection_resp.minter.clone().unwrap(); - let collection = collection_resp.collection.clone().unwrap(); - - let owner_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.owner, - &minter, - &collection, - &infinity_swap, - 100, - ); - let bidder_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.bidder, - &minter, - &collection, - &infinity_swap, - 100, - ); - - let deposit_tokens_per_pool = Uint128::from(10_000u128); - let _pools = prepare_pool_variations( - &mut router, - 7, - &None, - &infinity_swap, - &collection, - &accts.owner, - deposit_tokens_per_pool, - owner_token_ids.to_vec(), - 6, - false, - 0, - 0, - ); - - let nfts_to_swap: Vec = bidder_token_ids - .to_vec() - .drain(0..3_usize) - .map(|token_id| NftSwap { - nft_token_id: token_id, - token_amount: Uint128::from(100_000u128), - }) - .collect(); - let sim_msg = QueryMsg::SimSwapNftsForTokens { - collection: collection.to_string(), - nfts_to_swap, - sender: accts.bidder.to_string(), - swap_params: SwapParams { - deadline: Timestamp::from_nanos(GENESIS_MINT_START_TIME).plus_seconds(1000), - robust: false, - asset_recipient: None, - finder: None, - }, - }; - - let res: StdResult = router - .wrap() - .query_wasm_smart(infinity_swap.clone(), &sim_msg); - - assert!(res.unwrap().swaps.is_empty()); -} - -#[test] -fn can_swap_active_pools() { - let SwapTestSetup { - vending_template: - MinterTemplateResponse { - mut router, - accts, - collection_response_vec, - .. - }, - infinity_swap, - .. - } = setup_swap_test(5000).unwrap(); - - let collection_resp = &collection_response_vec[0]; - let minter = collection_resp.minter.clone().unwrap(); - let collection = collection_resp.collection.clone().unwrap(); - - let owner_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.owner, - &minter, - &collection, - &infinity_swap, - 100, - ); - let bidder_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.bidder, - &minter, - &collection, - &infinity_swap, - 100, - ); - - let deposit_tokens_per_pool = Uint128::from(10_000u128); - let _pools = prepare_pool_variations( - &mut router, - 7, - &None, - &infinity_swap, - &collection, - &accts.owner, - deposit_tokens_per_pool, - owner_token_ids.to_vec(), - 6, - true, - 0, - 0, - ); - - let nfts_to_swap: Vec = bidder_token_ids - .to_vec() - .drain(0..3_usize) - .map(|token_id| NftSwap { - nft_token_id: token_id, - token_amount: Uint128::from(10u128), - }) - .collect(); - let sim_msg = QueryMsg::SimSwapNftsForTokens { - collection: collection.to_string(), - nfts_to_swap, - sender: accts.bidder.to_string(), - swap_params: SwapParams { - deadline: Timestamp::from_nanos(GENESIS_MINT_START_TIME).plus_seconds(1000), - robust: false, - asset_recipient: None, - finder: None, - }, - }; - - let res: StdResult = router - .wrap() - .query_wasm_smart(infinity_swap.clone(), &sim_msg); - - assert!(res.is_ok()); - assert!(!res.unwrap().swaps.is_empty()); -} - -#[test] -fn sale_price_below_min_expected() { - let SwapTestSetup { - vending_template: - MinterTemplateResponse { - mut router, - accts, - collection_response_vec, - .. - }, - infinity_swap, - .. - } = setup_swap_test(5000).unwrap(); - - let collection_resp = &collection_response_vec[0]; - let minter = collection_resp.minter.clone().unwrap(); - let collection = collection_resp.collection.clone().unwrap(); - - let owner_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.owner, - &minter, - &collection, - &infinity_swap, - 100, - ); - let bidder_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.bidder, - &minter, - &collection, - &infinity_swap, - 100, - ); - - let deposit_tokens_per_pool = Uint128::from(10_000u128); - let _pools = prepare_pool_variations( - &mut router, - 7, - &None, - &infinity_swap, - &collection, - &accts.owner, - deposit_tokens_per_pool, - owner_token_ids.to_vec(), - 6, - true, - 0, - 0, - ); - - let nfts_to_swap: Vec = bidder_token_ids - .to_vec() - .drain(0..3_usize) - .map(|token_id| NftSwap { - nft_token_id: token_id, - token_amount: Uint128::from(100_000u128), - }) - .collect(); - let sim_msg = QueryMsg::SimSwapNftsForTokens { - collection: collection.to_string(), - nfts_to_swap, - sender: accts.bidder.to_string(), - swap_params: SwapParams { - deadline: Timestamp::from_nanos(GENESIS_MINT_START_TIME).plus_seconds(1000), - robust: false, - asset_recipient: None, - finder: None, - }, - }; - - let res: StdResult = router - .wrap() - .query_wasm_smart(infinity_swap.clone(), &sim_msg); - - assert_eq!( - res.unwrap_err(), - StdError::GenericErr { - msg: "Querier contract error: Generic error: Swap error: pool sale price is below min expected" - .to_string() - } - ); -} - -#[test] -fn robust_query_does_not_revert_whole_tx() { - let SwapTestSetup { - vending_template: - MinterTemplateResponse { - mut router, - accts, - collection_response_vec, - .. - }, - infinity_swap, - .. - } = setup_swap_test(5000).unwrap(); - - let collection_resp = &collection_response_vec[0]; - let minter = collection_resp.minter.clone().unwrap(); - let collection = collection_resp.collection.clone().unwrap(); - - let owner_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.owner, - &minter, - &collection, - &infinity_swap, - 100, - ); - let bidder_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.bidder, - &minter, - &collection, - &infinity_swap, - 100, - ); - - let deposit_tokens_per_pool = Uint128::from(10_000u128); - let _pools = prepare_pool_variations( - &mut router, - 7, - &None, - &infinity_swap, - &collection, - &accts.owner, - deposit_tokens_per_pool, - owner_token_ids.to_vec(), - 6, - true, - 0, - 0, - ); - - let nfts_to_swap: Vec = bidder_token_ids - .to_vec() - .drain(0..3_usize) - .map(|token_id| NftSwap { - nft_token_id: token_id, - token_amount: Uint128::from(1_000u128), - }) - .collect(); - let sim_msg = QueryMsg::SimSwapNftsForTokens { - collection: collection.to_string(), - nfts_to_swap, - sender: accts.bidder.to_string(), - swap_params: SwapParams { - deadline: Timestamp::from_nanos(GENESIS_MINT_START_TIME).plus_seconds(1000), - robust: true, - asset_recipient: None, - finder: None, - }, - }; - - let res: StdResult = router - .wrap() - .query_wasm_smart(infinity_swap.clone(), &sim_msg); - - assert!(res.is_ok()); - assert_eq!(res.unwrap().swaps.len(), 2); -} - -#[test] -fn minimal_fee_tx_is_handled_correctly() { - let SwapTestSetup { - vending_template: - MinterTemplateResponse { - mut router, - accts, - collection_response_vec, - .. - }, - infinity_swap, - marketplace, - .. - } = setup_swap_test(5000).unwrap(); - - let collection_resp = &collection_response_vec[0]; - let minter = collection_resp.minter.clone().unwrap(); - let collection = collection_resp.collection.clone().unwrap(); - - let owner_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.owner, - &minter, - &collection, - &infinity_swap, - 100, - ); - let bidder_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.bidder, - &minter, - &collection, - &infinity_swap, - 100, - ); - - let deposit_tokens_per_pool = Uint128::from(10_000u128); - let pools = prepare_pool_variations( - &mut router, - 7, - &None, - &infinity_swap, - &collection, - &accts.owner, - deposit_tokens_per_pool, - owner_token_ids.to_vec(), - 6, - true, - 0, - 0, - ); - - let marketplace_params: ParamsResponse = router - .wrap() - .query_wasm_smart(marketplace, &MarketplaceQueryMsg::Params {}) - .unwrap(); - let collection_info: CollectionInfoResponse = router - .wrap() - .query_wasm_smart(collection.clone(), &Sg721QueryMsg::CollectionInfo {}) - .unwrap(); - - let nfts_to_swap: Vec = bidder_token_ids - .to_vec() - .drain(0..3_usize) - .map(|token_id| NftSwap { - nft_token_id: token_id, - token_amount: Uint128::from(10u128), - }) - .collect(); - let sim_msg = QueryMsg::SimSwapNftsForTokens { - collection: collection.to_string(), - nfts_to_swap, - sender: accts.bidder.to_string(), - swap_params: SwapParams { - deadline: Timestamp::from_nanos(GENESIS_MINT_START_TIME).plus_seconds(1000), - robust: false, - asset_recipient: None, - finder: None, - }, - }; - - let res: StdResult = router - .wrap() - .query_wasm_smart(infinity_swap.clone(), &sim_msg); - - for swap in res.unwrap().swaps { - let pool = pools.iter().find(|p| p.id == swap.pool_id).unwrap(); - validate_swap_fees( - &swap, - pool, - &marketplace_params, - &collection_info.royalty_info, - ); - } -} - -#[test] -fn finders_and_swap_fee_tx_is_handled_correctly() { - let SwapTestSetup { - vending_template: - MinterTemplateResponse { - mut router, - accts, - collection_response_vec, - .. - }, - infinity_swap, - marketplace, - .. - } = setup_swap_test(5000).unwrap(); - let user2 = setup_addtl_account(&mut router, "asset", 100u128).unwrap(); - - let collection_resp = &collection_response_vec[0]; - let minter = collection_resp.minter.clone().unwrap(); - let collection = collection_resp.collection.clone().unwrap(); - - let owner_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.owner, - &minter, - &collection, - &infinity_swap, - 100, - ); - let bidder_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.bidder, - &minter, - &collection, - &infinity_swap, - 100, - ); - - let deposit_tokens_per_pool = Uint128::from(10_000u128); - let pools = prepare_pool_variations( - &mut router, - 7, - &None, - &infinity_swap, - &collection, - &accts.owner, - deposit_tokens_per_pool, - owner_token_ids.to_vec(), - 6, - true, - 250, - 300, - ); - - let marketplace_params: ParamsResponse = router - .wrap() - .query_wasm_smart(marketplace, &MarketplaceQueryMsg::Params {}) - .unwrap(); - let collection_info: CollectionInfoResponse = router - .wrap() - .query_wasm_smart(collection.clone(), &Sg721QueryMsg::CollectionInfo {}) - .unwrap(); - - let nfts_to_swap: Vec = bidder_token_ids - .to_vec() - .drain(0..3_usize) - .map(|token_id| NftSwap { - nft_token_id: token_id, - token_amount: Uint128::from(10u128), - }) - .collect(); - let sim_msg = QueryMsg::SimSwapNftsForTokens { - collection: collection.to_string(), - nfts_to_swap, - sender: accts.bidder.to_string(), - swap_params: SwapParams { - deadline: Timestamp::from_nanos(GENESIS_MINT_START_TIME).plus_seconds(1000), - robust: false, - asset_recipient: None, - finder: Some(user2.to_string()), - }, - }; - - let res: StdResult = router - .wrap() - .query_wasm_smart(infinity_swap.clone(), &sim_msg); - - for swap in res.unwrap().swaps { - let pool = pools.iter().find(|p| p.id == swap.pool_id).unwrap(); - validate_swap_fees( - &swap, - pool, - &marketplace_params, - &collection_info.royalty_info, - ); - } -} - -#[test] -fn trades_are_routed_correctly() { - let SwapTestSetup { - vending_template: - MinterTemplateResponse { - mut router, - accts, - collection_response_vec, - .. - }, - infinity_swap, - .. - } = setup_swap_test(5000).unwrap(); - - let collection_resp = &collection_response_vec[0]; - let minter = collection_resp.minter.clone().unwrap(); - let collection = collection_resp.collection.clone().unwrap(); - - let owner_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.owner, - &minter, - &collection, - &infinity_swap, - 100, - ); - let bidder_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.bidder, - &minter, - &collection, - &infinity_swap, - 100, - ); - - let deposit_tokens_per_pool = Uint128::from(10_000u128); - let _pools = prepare_pool_variations( - &mut router, - 14, - &None, - &infinity_swap, - &collection, - &accts.owner, - deposit_tokens_per_pool, - owner_token_ids.to_vec(), - 6, - true, - 0, - 0, - ); - - let num_swaps: usize = 50; - let nfts_to_swap: Vec = bidder_token_ids - .to_vec() - .drain(0..num_swaps) - .map(|token_id| NftSwap { - nft_token_id: token_id, - token_amount: Uint128::from(10u128), - }) - .collect(); - - let sim_msg = QueryMsg::SimSwapNftsForTokens { - collection: collection.to_string(), - nfts_to_swap, - sender: accts.bidder.to_string(), - swap_params: SwapParams { - deadline: Timestamp::from_nanos(GENESIS_MINT_START_TIME).plus_seconds(1000), - robust: false, - asset_recipient: None, - finder: None, - }, - }; - - let res: StdResult = router - .wrap() - .query_wasm_smart(infinity_swap.clone(), &sim_msg); - let swaps = res.unwrap().swaps; - - assert_eq!(swaps.len(), num_swaps); - for (idx, swap) in swaps.iter().enumerate() { - if idx == 0 { - continue; - } - assert!(swaps[idx - 1].spot_price >= swap.spot_price); - } -} diff --git a/test/unit/src/infinity_swap_tests/sim_tests/sim_swap_tokens_for_any_nfts.rs b/test/unit/src/infinity_swap_tests/sim_tests/sim_swap_tokens_for_any_nfts.rs deleted file mode 100644 index bea26f2..0000000 --- a/test/unit/src/infinity_swap_tests/sim_tests/sim_swap_tokens_for_any_nfts.rs +++ /dev/null @@ -1,610 +0,0 @@ -use crate::helpers::nft_functions::mint_and_approve_many; -use crate::helpers::pool_functions::{prepare_pool_variations, prepare_swap_pool}; -use crate::helpers::swap_functions::{setup_swap_test, validate_swap_fees, SwapTestSetup}; -use crate::setup::setup_accounts::setup_addtl_account; -use cosmwasm_std::{coins, StdError, StdResult, Timestamp, Uint128}; -use cw_multi_test::Executor; -use infinity_swap::msg::{ExecuteMsg, QueryMsg, SwapParams, SwapResponse}; -use infinity_swap::state::BondingCurve; -use sg721_base::msg::{CollectionInfoResponse, QueryMsg as Sg721QueryMsg}; -use sg_marketplace::msg::{ParamsResponse, QueryMsg as MarketplaceQueryMsg}; -use sg_std::{GENESIS_MINT_START_TIME, NATIVE_DENOM}; -use test_suite::common_setup::msg::MinterTemplateResponse; - -#[test] -fn cant_swap_inactive_pools() { - let SwapTestSetup { - vending_template: - MinterTemplateResponse { - mut router, - accts, - collection_response_vec, - .. - }, - infinity_swap, - .. - } = setup_swap_test(5000).unwrap(); - - let collection_resp = &collection_response_vec[0]; - let minter = collection_resp.minter.clone().unwrap(); - let collection = collection_resp.collection.clone().unwrap(); - - let owner_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.owner, - &minter, - &collection, - &infinity_swap, - 100, - ); - - let deposit_tokens_per_pool = Uint128::from(10_000u128); - let _pools = prepare_pool_variations( - &mut router, - 7, - &None, - &infinity_swap, - &collection, - &accts.owner, - deposit_tokens_per_pool, - owner_token_ids.to_vec(), - 6, - false, - 0, - 0, - ); - - let max_expected_token_input: Vec = - vec![Uint128::from(1_000_000u128), Uint128::from(1_000_000u128)]; - let sim_msg = QueryMsg::SimSwapTokensForAnyNfts { - collection: collection.to_string(), - max_expected_token_input, - sender: accts.bidder.to_string(), - swap_params: SwapParams { - deadline: Timestamp::from_nanos(GENESIS_MINT_START_TIME).plus_seconds(1000), - robust: false, - asset_recipient: None, - finder: None, - }, - }; - let res: StdResult = router - .wrap() - .query_wasm_smart(infinity_swap.clone(), &sim_msg); - - assert!(res.unwrap().swaps.is_empty()); -} - -#[test] -fn can_swap_active_pools() { - let SwapTestSetup { - vending_template: - MinterTemplateResponse { - mut router, - accts, - collection_response_vec, - .. - }, - infinity_swap, - .. - } = setup_swap_test(5000).unwrap(); - - let collection_resp = &collection_response_vec[0]; - let minter = collection_resp.minter.clone().unwrap(); - let collection = collection_resp.collection.clone().unwrap(); - - let owner_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.owner, - &minter, - &collection, - &infinity_swap, - 100, - ); - - let deposit_tokens_per_pool = Uint128::from(10_000u128); - let _pools = prepare_pool_variations( - &mut router, - 7, - &None, - &infinity_swap, - &collection, - &accts.owner, - deposit_tokens_per_pool, - owner_token_ids.to_vec(), - 6, - true, - 0, - 0, - ); - - let max_expected_token_input: Vec = - vec![Uint128::from(1_000_000u128), Uint128::from(1_000_000u128)]; - let sim_msg = QueryMsg::SimSwapTokensForAnyNfts { - collection: collection.to_string(), - max_expected_token_input, - sender: accts.bidder.to_string(), - swap_params: SwapParams { - deadline: Timestamp::from_nanos(GENESIS_MINT_START_TIME).plus_seconds(1000), - robust: false, - asset_recipient: None, - finder: None, - }, - }; - let res: StdResult = router - .wrap() - .query_wasm_smart(infinity_swap.clone(), &sim_msg); - - assert!(res.is_ok()); - assert!(!res.unwrap().swaps.is_empty()); -} - -#[test] -fn sale_price_above_max_expected() { - let SwapTestSetup { - vending_template: - MinterTemplateResponse { - mut router, - accts, - collection_response_vec, - .. - }, - infinity_swap, - .. - } = setup_swap_test(5000).unwrap(); - - let collection_resp = &collection_response_vec[0]; - let minter = collection_resp.minter.clone().unwrap(); - let collection = collection_resp.collection.clone().unwrap(); - - let owner_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.owner, - &minter, - &collection, - &infinity_swap, - 100, - ); - - let deposit_tokens_per_pool = Uint128::from(10_000u128); - let _pools = prepare_pool_variations( - &mut router, - 7, - &None, - &infinity_swap, - &collection, - &accts.owner, - deposit_tokens_per_pool, - owner_token_ids.to_vec(), - 6, - true, - 0, - 0, - ); - - let max_expected_token_input: Vec = vec![Uint128::from(10u128), Uint128::from(10u128)]; - let sim_msg = QueryMsg::SimSwapTokensForAnyNfts { - collection: collection.to_string(), - max_expected_token_input, - sender: accts.bidder.to_string(), - swap_params: SwapParams { - deadline: Timestamp::from_nanos(GENESIS_MINT_START_TIME).plus_seconds(1000), - robust: false, - asset_recipient: None, - finder: None, - }, - }; - - let res: StdResult = router - .wrap() - .query_wasm_smart(infinity_swap.clone(), &sim_msg); - - assert_eq!( - res.unwrap_err(), - StdError::GenericErr { - msg: "Querier contract error: Generic error: Swap error: pool sale price is above max expected" - .to_string() - } - ); -} - -#[test] -fn robust_query_does_not_revert_whole_tx() { - let SwapTestSetup { - vending_template: - MinterTemplateResponse { - mut router, - accts, - collection_response_vec, - .. - }, - infinity_swap, - .. - } = setup_swap_test(5000).unwrap(); - - let collection_resp = &collection_response_vec[0]; - let minter = collection_resp.minter.clone().unwrap(); - let collection = collection_resp.collection.clone().unwrap(); - - let owner_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.owner, - &minter, - &collection, - &infinity_swap, - 100, - ); - - let deposit_tokens_per_pool = Uint128::from(10_000u128); - let _pools = prepare_pool_variations( - &mut router, - 7, - &None, - &infinity_swap, - &collection, - &accts.owner, - deposit_tokens_per_pool, - owner_token_ids.to_vec(), - 6, - true, - 0, - 0, - ); - - let max_expected_token_input: Vec = vec![ - Uint128::from(320u128), - Uint128::from(340u128), - Uint128::from(350u128), - ]; - let sim_msg = QueryMsg::SimSwapTokensForAnyNfts { - collection: collection.to_string(), - max_expected_token_input, - sender: accts.bidder.to_string(), - swap_params: SwapParams { - deadline: Timestamp::from_nanos(GENESIS_MINT_START_TIME).plus_seconds(1000), - robust: true, - asset_recipient: None, - finder: None, - }, - }; - let res: StdResult = router - .wrap() - .query_wasm_smart(infinity_swap.clone(), &sim_msg); - - assert!(res.is_ok()); - assert_eq!(res.unwrap().swaps.len(), 2); -} - -#[test] -fn minimal_fee_tx_is_handled_correctly() { - let SwapTestSetup { - vending_template: - MinterTemplateResponse { - mut router, - accts, - collection_response_vec, - .. - }, - infinity_swap, - marketplace, - .. - } = setup_swap_test(5000).unwrap(); - - let collection_resp = &collection_response_vec[0]; - let minter = collection_resp.minter.clone().unwrap(); - let collection = collection_resp.collection.clone().unwrap(); - - let owner_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.owner, - &minter, - &collection, - &infinity_swap, - 100, - ); - - let deposit_tokens_per_pool = Uint128::from(10_000u128); - let pools = prepare_pool_variations( - &mut router, - 7, - &None, - &infinity_swap, - &collection, - &accts.owner, - deposit_tokens_per_pool, - owner_token_ids.to_vec(), - 6, - true, - 0, - 0, - ); - - let marketplace_params: ParamsResponse = router - .wrap() - .query_wasm_smart(marketplace, &MarketplaceQueryMsg::Params {}) - .unwrap(); - let collection_info: CollectionInfoResponse = router - .wrap() - .query_wasm_smart(collection.clone(), &Sg721QueryMsg::CollectionInfo {}) - .unwrap(); - - let max_expected_token_input: Vec = vec![ - Uint128::from(1_000_000u128), - Uint128::from(1_000_000u128), - Uint128::from(1_000_000u128), - ]; - let sim_msg = QueryMsg::SimSwapTokensForAnyNfts { - collection: collection.to_string(), - max_expected_token_input, - sender: accts.bidder.to_string(), - swap_params: SwapParams { - deadline: Timestamp::from_nanos(GENESIS_MINT_START_TIME).plus_seconds(1000), - robust: true, - asset_recipient: None, - finder: None, - }, - }; - let res: StdResult = router - .wrap() - .query_wasm_smart(infinity_swap.clone(), &sim_msg); - - for swap in res.unwrap().swaps { - let pool = pools.iter().find(|p| p.id == swap.pool_id).unwrap(); - validate_swap_fees( - &swap, - pool, - &marketplace_params, - &collection_info.royalty_info, - ); - } -} - -#[test] -fn finders_and_swap_fee_tx_is_handled_correctly() { - let SwapTestSetup { - vending_template: - MinterTemplateResponse { - mut router, - accts, - collection_response_vec, - .. - }, - infinity_swap, - marketplace, - .. - } = setup_swap_test(5000).unwrap(); - let user2 = setup_addtl_account(&mut router, "asset", 100u128).unwrap(); - - let collection_resp = &collection_response_vec[0]; - let minter = collection_resp.minter.clone().unwrap(); - let collection = collection_resp.collection.clone().unwrap(); - - let owner_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.owner, - &minter, - &collection, - &infinity_swap, - 100, - ); - - let deposit_tokens_per_pool = Uint128::from(10_000u128); - let pools = prepare_pool_variations( - &mut router, - 7, - &None, - &infinity_swap, - &collection, - &accts.owner, - deposit_tokens_per_pool, - owner_token_ids.to_vec(), - 6, - true, - 250, - 300, - ); - - let marketplace_params: ParamsResponse = router - .wrap() - .query_wasm_smart(marketplace, &MarketplaceQueryMsg::Params {}) - .unwrap(); - let collection_info: CollectionInfoResponse = router - .wrap() - .query_wasm_smart(collection.clone(), &Sg721QueryMsg::CollectionInfo {}) - .unwrap(); - - let max_expected_token_input: Vec = vec![ - Uint128::from(1_000_000u128), - Uint128::from(1_000_000u128), - Uint128::from(1_000_000u128), - ]; - let sim_msg = QueryMsg::SimSwapTokensForAnyNfts { - collection: collection.to_string(), - max_expected_token_input, - sender: accts.bidder.to_string(), - swap_params: SwapParams { - deadline: Timestamp::from_nanos(GENESIS_MINT_START_TIME).plus_seconds(1000), - robust: true, - asset_recipient: None, - finder: Some(user2.to_string()), - }, - }; - let res: StdResult = router - .wrap() - .query_wasm_smart(infinity_swap.clone(), &sim_msg); - - for swap in res.unwrap().swaps { - let pool = pools.iter().find(|p| p.id == swap.pool_id).unwrap(); - validate_swap_fees( - &swap, - pool, - &marketplace_params, - &collection_info.royalty_info, - ); - } -} - -#[test] -fn trades_are_routed_correctly() { - let SwapTestSetup { - vending_template: - MinterTemplateResponse { - mut router, - accts, - collection_response_vec, - .. - }, - infinity_swap, - .. - } = setup_swap_test(5000).unwrap(); - - let collection_resp = &collection_response_vec[0]; - let minter = collection_resp.minter.clone().unwrap(); - let collection = collection_resp.collection.clone().unwrap(); - - let owner_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.owner, - &minter, - &collection, - &infinity_swap, - 500, - ); - - let deposit_tokens_per_pool = Uint128::from(10_000u128); - let _pools = prepare_pool_variations( - &mut router, - 7, - &None, - &infinity_swap, - &collection, - &accts.owner, - deposit_tokens_per_pool, - owner_token_ids.to_vec(), - 20, - true, - 0, - 0, - ); - - let num_swaps: usize = 50; - let max_expected_token_input: Vec = vec![Uint128::from(1_000_000u128); num_swaps]; - let sim_msg = QueryMsg::SimSwapTokensForAnyNfts { - collection: collection.to_string(), - max_expected_token_input, - sender: accts.bidder.to_string(), - swap_params: SwapParams { - deadline: Timestamp::from_nanos(GENESIS_MINT_START_TIME).plus_seconds(1000), - robust: true, - asset_recipient: None, - finder: None, - }, - }; - let res: StdResult = router - .wrap() - .query_wasm_smart(infinity_swap.clone(), &sim_msg); - let swaps = res.unwrap().swaps; - assert_eq!(swaps.len(), num_swaps); - - for (idx, swap) in swaps.iter().enumerate() { - if idx == 0 { - continue; - } - assert!(swaps[idx - 1].spot_price <= swap.spot_price); - } -} - -#[test] -fn constant_product_pools_with_little_nfts() { - let SwapTestSetup { - vending_template: - MinterTemplateResponse { - mut router, - accts, - collection_response_vec, - .. - }, - infinity_swap, - .. - } = setup_swap_test(5000).unwrap(); - - let collection_resp = &collection_response_vec[0]; - let minter = collection_resp.minter.clone().unwrap(); - let collection = collection_resp.collection.clone().unwrap(); - - let owner_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.owner, - &minter, - &collection, - &infinity_swap, - 100, - ); - - let _pool = prepare_swap_pool( - &mut router, - &infinity_swap, - &accts.owner, - Uint128::from(1_000u128), - owner_token_ids.to_vec().drain(0..4).collect(), - true, - ExecuteMsg::CreateTradePool { - collection: collection.to_string(), - asset_recipient: None, - bonding_curve: BondingCurve::ConstantProduct, - spot_price: Uint128::from(0u64), - delta: Uint128::from(0u64), - finders_fee_bps: 0, - swap_fee_bps: 0, - reinvest_nfts: true, - reinvest_tokens: true, - }, - ) - .unwrap(); - - let num_swaps: usize = 4; - let max_expected_token_input: Vec = vec![Uint128::from(100_000_000u128); num_swaps]; - let sim_msg = QueryMsg::SimSwapTokensForAnyNfts { - collection: collection.to_string(), - max_expected_token_input: max_expected_token_input.clone(), - sender: accts.bidder.to_string(), - swap_params: SwapParams { - deadline: Timestamp::from_nanos(GENESIS_MINT_START_TIME).plus_seconds(1000), - robust: true, - asset_recipient: None, - finder: None, - }, - }; - let res: StdResult = router - .wrap() - .query_wasm_smart(infinity_swap.clone(), &sim_msg); - - let _swaps = res.unwrap().swaps; - - let exec_msg = ExecuteMsg::SwapTokensForAnyNfts { - collection: collection.to_string(), - max_expected_token_input: max_expected_token_input.clone(), - swap_params: SwapParams { - deadline: Timestamp::from_nanos(GENESIS_MINT_START_TIME).plus_seconds(1000), - robust: true, - asset_recipient: None, - finder: None, - }, - }; - - let funds: Uint128 = max_expected_token_input.iter().sum(); - let exec_res = router.execute_contract( - accts.bidder.clone(), - infinity_swap.clone(), - &exec_msg, - &coins(funds.u128(), NATIVE_DENOM), - ); - assert!(exec_res.is_ok()); -} diff --git a/test/unit/src/infinity_swap_tests/sim_tests/sim_swap_tokens_for_specific_nfts.rs b/test/unit/src/infinity_swap_tests/sim_tests/sim_swap_tokens_for_specific_nfts.rs deleted file mode 100644 index 96f2120..0000000 --- a/test/unit/src/infinity_swap_tests/sim_tests/sim_swap_tokens_for_specific_nfts.rs +++ /dev/null @@ -1,1021 +0,0 @@ -use crate::helpers::nft_functions::mint_and_approve_many; -use crate::helpers::pool_functions::prepare_pool_variations; -use crate::helpers::swap_functions::{setup_swap_test, validate_swap_fees, SwapTestSetup}; -use crate::setup::setup_accounts::setup_addtl_account; -use crate::setup::setup_infinity_swap::setup_infinity_swap; -use crate::setup::setup_marketplace::setup_marketplace; -use crate::setup::templates::minter_two_collections; -use cosmwasm_std::{StdError, StdResult, Timestamp, Uint128}; -use infinity_swap::msg::{ - NftSwap, NftTokenIdsResponse, PoolNftSwap, QueryMsg, QueryOptions, SwapParams, SwapResponse, -}; -use infinity_swap::state::Pool; -use itertools::Itertools; -use sg721_base::msg::{CollectionInfoResponse, QueryMsg as Sg721QueryMsg}; -use sg_marketplace::msg::{ParamsResponse, QueryMsg as MarketplaceQueryMsg}; -use sg_std::GENESIS_MINT_START_TIME; -use std::vec; -use test_suite::common_setup::msg::MinterTemplateResponse; -use test_suite::common_setup::setup_accounts_and_block::setup_block_time; - -#[test] -fn cant_swap_inactive_pool() { - let SwapTestSetup { - vending_template: - MinterTemplateResponse { - mut router, - accts, - collection_response_vec, - .. - }, - infinity_swap, - .. - } = setup_swap_test(5000).unwrap(); - - let collection_resp = &collection_response_vec[0]; - let minter = collection_resp.minter.clone().unwrap(); - let collection = collection_resp.collection.clone().unwrap(); - - let owner_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.owner, - &minter, - &collection, - &infinity_swap, - 100, - ); - - let deposit_tokens_per_pool = Uint128::from(10_000u128); - let pools = prepare_pool_variations( - &mut router, - 7, - &None, - &infinity_swap, - &collection, - &accts.owner, - deposit_tokens_per_pool, - owner_token_ids, - 6, - false, - 0, - 0, - ); - - let pool_chunks: Vec> = pools - .into_iter() - .filter(|p| p.can_sell_nfts()) - .chunks(3) - .into_iter() - .map(|chunk| chunk.collect()) - .collect(); - - for chunk in pool_chunks { - let mut pool_nfts_to_swap_for: Vec = vec![]; - for pool in chunk { - let nft_token_ids_response: NftTokenIdsResponse = router - .wrap() - .query_wasm_smart( - infinity_swap.clone(), - &QueryMsg::PoolNftTokenIds { - pool_id: pool.id, - query_options: QueryOptions { - descending: None, - start_after: None, - limit: Some(3), - }, - }, - ) - .unwrap(); - - pool_nfts_to_swap_for.push(PoolNftSwap { - pool_id: pool.id, - nft_swaps: nft_token_ids_response - .nft_token_ids - .into_iter() - .map(|token_id| NftSwap { - nft_token_id: token_id, - token_amount: Uint128::from(100_000u128), - }) - .collect(), - }); - } - - let sim_msg = QueryMsg::SimSwapTokensForSpecificNfts { - collection: collection.to_string(), - pool_nfts_to_swap_for, - sender: accts.bidder.to_string(), - swap_params: SwapParams { - deadline: Timestamp::from_nanos(GENESIS_MINT_START_TIME).plus_seconds(1000), - robust: true, - asset_recipient: None, - finder: None, - }, - }; - - let res: StdResult = router - .wrap() - .query_wasm_smart(infinity_swap.clone(), &sim_msg); - assert_eq!( - res.unwrap_err(), - StdError::GenericErr { - msg: "Querier contract error: Generic error: Invalid pool: pool is not active" - .to_string() - } - ); - } -} - -#[test] -fn cant_swap_invalid_pool_type() { - let SwapTestSetup { - vending_template: - MinterTemplateResponse { - mut router, - accts, - collection_response_vec, - .. - }, - infinity_swap, - .. - } = setup_swap_test(5000).unwrap(); - - let collection_resp = &collection_response_vec[0]; - let minter = collection_resp.minter.clone().unwrap(); - let collection = collection_resp.collection.clone().unwrap(); - - let owner_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.owner, - &minter, - &collection, - &infinity_swap, - 100, - ); - - let deposit_tokens_per_pool = Uint128::from(10_000u128); - let pools = prepare_pool_variations( - &mut router, - 7, - &None, - &infinity_swap, - &collection, - &accts.owner, - deposit_tokens_per_pool, - owner_token_ids, - 6, - false, - 0, - 0, - ); - - let pool_chunks: Vec> = pools - .into_iter() - .filter(|p| !p.can_sell_nfts()) - .chunks(3) - .into_iter() - .map(|chunk| chunk.collect()) - .collect(); - - for chunk in pool_chunks { - let mut pool_nfts_to_swap_for: Vec = vec![]; - for pool in chunk { - let nft_token_ids_response: NftTokenIdsResponse = router - .wrap() - .query_wasm_smart( - infinity_swap.clone(), - &QueryMsg::PoolNftTokenIds { - pool_id: pool.id, - query_options: QueryOptions { - descending: None, - start_after: None, - limit: Some(3), - }, - }, - ) - .unwrap(); - - pool_nfts_to_swap_for.push(PoolNftSwap { - pool_id: pool.id, - nft_swaps: nft_token_ids_response - .nft_token_ids - .into_iter() - .map(|token_id| NftSwap { - nft_token_id: token_id, - token_amount: Uint128::from(100_000u128), - }) - .collect(), - }); - } - - let sim_msg = QueryMsg::SimSwapTokensForSpecificNfts { - collection: collection.to_string(), - pool_nfts_to_swap_for, - sender: accts.bidder.to_string(), - swap_params: SwapParams { - deadline: Timestamp::from_nanos(GENESIS_MINT_START_TIME).plus_seconds(1000), - robust: true, - asset_recipient: None, - finder: None, - }, - }; - - let res: StdResult = router - .wrap() - .query_wasm_smart(infinity_swap.clone(), &sim_msg); - assert_eq!( - res.unwrap_err(), - StdError::GenericErr { - msg: "Querier contract error: Generic error: Invalid pool: pool cannot sell nfts" - .to_string() - } - ); - } -} - -#[test] -fn cant_swap_for_pools_outside_of_collection() { - let mut vt = minter_two_collections(5000); - - let marketplace = setup_marketplace(&mut vt.router, vt.accts.creator.clone()).unwrap(); - setup_block_time(&mut vt.router, GENESIS_MINT_START_TIME, None); - - let infinity_swap = - setup_infinity_swap(&mut vt.router, vt.accts.creator.clone(), marketplace).unwrap(); - - let MinterTemplateResponse { - mut router, - accts, - collection_response_vec, - .. - } = vt; - - let minter = &collection_response_vec[0].minter.clone().unwrap(); - let collection_a = &collection_response_vec[0].collection.clone().unwrap(); - let collection_resp_b = &collection_response_vec[1]; - let collection_b = collection_resp_b.collection.clone().unwrap(); - - let owner_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.owner, - minter, - collection_a, - &infinity_swap, - 100, - ); - - let deposit_tokens_per_pool = Uint128::from(10_000u128); - let pools = prepare_pool_variations( - &mut router, - 7, - &None, - &infinity_swap, - collection_a, - &accts.owner, - deposit_tokens_per_pool, - owner_token_ids, - 6, - true, - 0, - 0, - ); - - let pool_chunks: Vec> = pools - .into_iter() - .filter(|p| p.can_sell_nfts()) - .chunks(3) - .into_iter() - .map(|chunk| chunk.collect()) - .collect(); - - for chunk in pool_chunks { - let mut pool_nfts_to_swap_for: Vec = vec![]; - for pool in chunk { - let nft_token_ids_response: NftTokenIdsResponse = router - .wrap() - .query_wasm_smart( - infinity_swap.clone(), - &QueryMsg::PoolNftTokenIds { - pool_id: pool.id, - query_options: QueryOptions { - descending: None, - start_after: None, - limit: Some(3), - }, - }, - ) - .unwrap(); - - pool_nfts_to_swap_for.push(PoolNftSwap { - pool_id: pool.id, - nft_swaps: nft_token_ids_response - .nft_token_ids - .into_iter() - .map(|token_id| NftSwap { - nft_token_id: token_id, - token_amount: Uint128::from(100_000u128), - }) - .collect(), - }); - } - - let sim_msg = QueryMsg::SimSwapTokensForSpecificNfts { - collection: collection_b.to_string(), - pool_nfts_to_swap_for, - sender: accts.bidder.to_string(), - swap_params: SwapParams { - deadline: Timestamp::from_nanos(GENESIS_MINT_START_TIME).plus_seconds(1000), - robust: false, - asset_recipient: None, - finder: None, - }, - }; - - let res: StdResult = router - .wrap() - .query_wasm_smart(infinity_swap.clone(), &sim_msg); - - assert_eq!( - res.unwrap_err(), - StdError::GenericErr { - msg: "Querier contract error: Generic error: Invalid pool: pool does not belong to this collection" - .to_string() - } - ); - } -} - -#[test] -fn can_swap_active_pool() { - let SwapTestSetup { - vending_template: - MinterTemplateResponse { - mut router, - accts, - collection_response_vec, - .. - }, - infinity_swap, - .. - } = setup_swap_test(5000).unwrap(); - - let collection_resp = &collection_response_vec[0]; - let minter = collection_resp.minter.clone().unwrap(); - let collection = collection_resp.collection.clone().unwrap(); - - let owner_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.owner, - &minter, - &collection, - &infinity_swap, - 100, - ); - - let deposit_tokens_per_pool = Uint128::from(10_000u128); - let pools = prepare_pool_variations( - &mut router, - 7, - &None, - &infinity_swap, - &collection, - &accts.owner, - deposit_tokens_per_pool, - owner_token_ids, - 6, - true, - 0, - 0, - ); - - let pool_chunks: Vec> = pools - .into_iter() - .filter(|p| p.can_sell_nfts()) - .chunks(3) - .into_iter() - .map(|chunk| chunk.collect()) - .collect(); - - for chunk in pool_chunks { - let mut pool_nfts_to_swap_for: Vec = vec![]; - for pool in chunk { - let nft_token_ids_response: NftTokenIdsResponse = router - .wrap() - .query_wasm_smart( - infinity_swap.clone(), - &QueryMsg::PoolNftTokenIds { - pool_id: pool.id, - query_options: QueryOptions { - descending: None, - start_after: None, - limit: Some(3), - }, - }, - ) - .unwrap(); - - pool_nfts_to_swap_for.push(PoolNftSwap { - pool_id: pool.id, - nft_swaps: nft_token_ids_response - .nft_token_ids - .into_iter() - .map(|token_id| NftSwap { - nft_token_id: token_id, - token_amount: Uint128::from(100_000u128), - }) - .collect(), - }); - } - - let sim_msg = QueryMsg::SimSwapTokensForSpecificNfts { - collection: collection.to_string(), - pool_nfts_to_swap_for, - sender: accts.bidder.to_string(), - swap_params: SwapParams { - deadline: Timestamp::from_nanos(GENESIS_MINT_START_TIME).plus_seconds(1000), - robust: false, - asset_recipient: None, - finder: None, - }, - }; - - let res: StdResult = router - .wrap() - .query_wasm_smart(infinity_swap.clone(), &sim_msg); - - assert!(res.is_ok()); - assert!(!res.unwrap().swaps.is_empty()); - } -} - -#[test] -fn incorrect_nfts_error() { - let SwapTestSetup { - vending_template: - MinterTemplateResponse { - mut router, - accts, - collection_response_vec, - .. - }, - infinity_swap, - .. - } = setup_swap_test(5000).unwrap(); - - let collection_resp = &collection_response_vec[0]; - let minter = collection_resp.minter.clone().unwrap(); - let collection = collection_resp.collection.clone().unwrap(); - - let owner_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.owner, - &minter, - &collection, - &infinity_swap, - 100, - ); - let mut bidder_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.bidder, - &minter, - &collection, - &infinity_swap, - 100, - ); - - let deposit_tokens_per_pool = Uint128::from(10_000u128); - let pools = prepare_pool_variations( - &mut router, - 7, - &None, - &infinity_swap, - &collection, - &accts.owner, - deposit_tokens_per_pool, - owner_token_ids, - 6, - true, - 0, - 0, - ); - - let pool_chunks: Vec> = pools - .into_iter() - .filter(|p| p.can_sell_nfts()) - .chunks(3) - .into_iter() - .map(|chunk| chunk.collect()) - .collect(); - - for chunk in pool_chunks { - let mut pool_nfts_to_swap_for: Vec = vec![]; - for pool in chunk { - pool_nfts_to_swap_for.push(PoolNftSwap { - pool_id: pool.id, - nft_swaps: bidder_token_ids - .drain(0..3) - .map(|token_id| NftSwap { - nft_token_id: token_id, - token_amount: Uint128::from(100_000u128), - }) - .collect(), - }); - } - - let sim_msg = QueryMsg::SimSwapTokensForSpecificNfts { - collection: collection.to_string(), - pool_nfts_to_swap_for: pool_nfts_to_swap_for.clone(), - sender: accts.bidder.to_string(), - swap_params: SwapParams { - deadline: Timestamp::from_nanos(GENESIS_MINT_START_TIME).plus_seconds(1000), - robust: false, - asset_recipient: None, - finder: None, - }, - }; - - let res: StdResult = router - .wrap() - .query_wasm_smart(infinity_swap.clone(), &sim_msg); - - assert_eq!( - res.unwrap_err(), - StdError::GenericErr { - msg: format!( - "Querier contract error: Generic error: Swap error: pool {} does not own NFT {}", - pool_nfts_to_swap_for[0].pool_id, pool_nfts_to_swap_for[0].nft_swaps[0].nft_token_id - ) - .to_string() - } - ); - } -} - -#[test] -fn sale_price_above_max_expected() { - let SwapTestSetup { - vending_template: - MinterTemplateResponse { - mut router, - accts, - collection_response_vec, - .. - }, - infinity_swap, - .. - } = setup_swap_test(5000).unwrap(); - - let collection_resp = &collection_response_vec[0]; - let minter = collection_resp.minter.clone().unwrap(); - let collection = collection_resp.collection.clone().unwrap(); - - let owner_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.owner, - &minter, - &collection, - &infinity_swap, - 100, - ); - - let deposit_tokens_per_pool = Uint128::from(10_000u128); - let pools = prepare_pool_variations( - &mut router, - 7, - &None, - &infinity_swap, - &collection, - &accts.owner, - deposit_tokens_per_pool, - owner_token_ids, - 6, - true, - 0, - 0, - ); - - let pool_chunks: Vec> = pools - .into_iter() - .filter(|p| p.can_sell_nfts()) - .chunks(3) - .into_iter() - .map(|chunk| chunk.collect()) - .collect(); - - for chunk in pool_chunks { - let mut pool_nfts_to_swap_for: Vec = vec![]; - for pool in chunk { - let nft_token_ids_response: NftTokenIdsResponse = router - .wrap() - .query_wasm_smart( - infinity_swap.clone(), - &QueryMsg::PoolNftTokenIds { - pool_id: pool.id, - query_options: QueryOptions { - descending: None, - start_after: None, - limit: Some(3), - }, - }, - ) - .unwrap(); - - pool_nfts_to_swap_for.push(PoolNftSwap { - pool_id: pool.id, - nft_swaps: nft_token_ids_response - .nft_token_ids - .into_iter() - .map(|token_id| NftSwap { - nft_token_id: token_id, - token_amount: Uint128::from(10u128), - }) - .collect(), - }); - } - - let sim_msg = QueryMsg::SimSwapTokensForSpecificNfts { - collection: collection.to_string(), - pool_nfts_to_swap_for, - sender: accts.bidder.to_string(), - swap_params: SwapParams { - deadline: Timestamp::from_nanos(GENESIS_MINT_START_TIME).plus_seconds(1000), - robust: false, - asset_recipient: None, - finder: None, - }, - }; - - let res: StdResult = router - .wrap() - .query_wasm_smart(infinity_swap.clone(), &sim_msg); - - assert_eq!(res.unwrap_err(), StdError::GenericErr { - msg: "Querier contract error: Generic error: Swap error: pool sale price is above max expected" - .to_string(), - }); - } -} - -#[test] -fn robust_query_does_not_revert_whole_tx() { - let SwapTestSetup { - vending_template: - MinterTemplateResponse { - mut router, - accts, - collection_response_vec, - .. - }, - infinity_swap, - .. - } = setup_swap_test(5000).unwrap(); - - let collection_resp = &collection_response_vec[0]; - let minter = collection_resp.minter.clone().unwrap(); - let collection = collection_resp.collection.clone().unwrap(); - - let owner_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.owner, - &minter, - &collection, - &infinity_swap, - 100, - ); - - let deposit_tokens_per_pool = Uint128::from(10_000u128); - let pools = prepare_pool_variations( - &mut router, - 7, - &None, - &infinity_swap, - &collection, - &accts.owner, - deposit_tokens_per_pool, - owner_token_ids, - 6, - true, - 0, - 0, - ); - - let pool_chunks: Vec> = pools - .into_iter() - .filter(|p| p.can_sell_nfts()) - .chunks(3) - .into_iter() - .map(|chunk| chunk.collect()) - .collect(); - - for chunk in pool_chunks { - let mut pool_nfts_to_swap_for: Vec = vec![]; - for pool in chunk { - let nft_token_ids_response: NftTokenIdsResponse = router - .wrap() - .query_wasm_smart( - infinity_swap.clone(), - &QueryMsg::PoolNftTokenIds { - pool_id: pool.id, - query_options: QueryOptions { - descending: None, - start_after: None, - limit: Some(3), - }, - }, - ) - .unwrap(); - - let mut pool_nft_token_ids: Vec = - nft_token_ids_response.nft_token_ids.into_iter().collect(); - let mut pool_nft_swap = PoolNftSwap { - pool_id: pool.id, - nft_swaps: pool_nft_token_ids - .drain(0..2_usize) - .map(|token_id| NftSwap { - nft_token_id: token_id, - token_amount: Uint128::from(100_000_u128), - }) - .collect(), - }; - pool_nft_swap.nft_swaps.extend( - pool_nft_token_ids - .drain(0..1_usize) - .map(|token_id| NftSwap { - nft_token_id: token_id, - token_amount: Uint128::from(10u128), - }) - .collect::>(), - ); - pool_nfts_to_swap_for.push(pool_nft_swap); - } - - let sim_msg = QueryMsg::SimSwapTokensForSpecificNfts { - collection: collection.to_string(), - pool_nfts_to_swap_for, - sender: accts.bidder.to_string(), - swap_params: SwapParams { - deadline: Timestamp::from_nanos(GENESIS_MINT_START_TIME).plus_seconds(1000), - robust: true, - asset_recipient: None, - finder: None, - }, - }; - - let res: StdResult = router - .wrap() - .query_wasm_smart(infinity_swap.clone(), &sim_msg); - - assert!(res.is_ok()); - assert!(!res.unwrap().swaps.is_empty()); - } -} - -#[test] -fn trading_fee_is_applied_correctly() { - let SwapTestSetup { - vending_template: - MinterTemplateResponse { - mut router, - accts, - collection_response_vec, - .. - }, - infinity_swap, - marketplace, - .. - } = setup_swap_test(5000).unwrap(); - - let collection_resp = &collection_response_vec[0]; - let minter = collection_resp.minter.clone().unwrap(); - let collection = collection_resp.collection.clone().unwrap(); - - let owner_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.owner, - &minter, - &collection, - &infinity_swap, - 100, - ); - - let deposit_tokens_per_pool = Uint128::from(10_000u128); - let pools = prepare_pool_variations( - &mut router, - 7, - &None, - &infinity_swap, - &collection, - &accts.owner, - deposit_tokens_per_pool, - owner_token_ids, - 6, - true, - 0, - 0, - ); - - let pool_chunks: Vec> = pools - .into_iter() - .filter(|p| p.can_sell_nfts()) - .chunks(3) - .into_iter() - .map(|chunk| chunk.collect()) - .collect(); - - let marketplace_params: ParamsResponse = router - .wrap() - .query_wasm_smart(marketplace, &MarketplaceQueryMsg::Params {}) - .unwrap(); - let collection_info: CollectionInfoResponse = router - .wrap() - .query_wasm_smart(collection.clone(), &Sg721QueryMsg::CollectionInfo {}) - .unwrap(); - - for chunk in pool_chunks { - let mut pool_nfts_to_swap_for: Vec = vec![]; - for pool in chunk.iter() { - let nft_token_ids_response: NftTokenIdsResponse = router - .wrap() - .query_wasm_smart( - infinity_swap.clone(), - &QueryMsg::PoolNftTokenIds { - pool_id: pool.id, - query_options: QueryOptions { - descending: None, - start_after: None, - limit: Some(3), - }, - }, - ) - .unwrap(); - - pool_nfts_to_swap_for.push(PoolNftSwap { - pool_id: pool.id, - nft_swaps: nft_token_ids_response - .nft_token_ids - .iter() - .map(|token_id| NftSwap { - nft_token_id: token_id.to_string(), - token_amount: Uint128::from(100_000u128), - }) - .collect(), - }); - } - - let sim_msg = QueryMsg::SimSwapTokensForSpecificNfts { - collection: collection.to_string(), - pool_nfts_to_swap_for, - sender: accts.bidder.to_string(), - swap_params: SwapParams { - deadline: Timestamp::from_nanos(GENESIS_MINT_START_TIME).plus_seconds(1000), - robust: false, - asset_recipient: None, - finder: None, - }, - }; - - let res: StdResult = router - .wrap() - .query_wasm_smart(infinity_swap.clone(), &sim_msg); - - for swap in res.unwrap().swaps { - let pool = chunk.iter().find(|p| p.id == swap.pool_id).unwrap(); - validate_swap_fees( - &swap, - pool, - &marketplace_params, - &collection_info.royalty_info, - ); - } - } -} - -#[test] -fn finders_and_swap_fee_tx_is_handled_correctly() { - let SwapTestSetup { - vending_template: - MinterTemplateResponse { - mut router, - accts, - collection_response_vec, - .. - }, - infinity_swap, - marketplace, - .. - } = setup_swap_test(5000).unwrap(); - let user2 = setup_addtl_account(&mut router, "asset", 100u128).unwrap(); - - let collection_resp = &collection_response_vec[0]; - let minter = collection_resp.minter.clone().unwrap(); - let collection = collection_resp.collection.clone().unwrap(); - - let owner_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.owner, - &minter, - &collection, - &infinity_swap, - 100, - ); - - let deposit_tokens_per_pool = Uint128::from(10_000u128); - let pools = prepare_pool_variations( - &mut router, - 7, - &None, - &infinity_swap, - &collection, - &accts.owner, - deposit_tokens_per_pool, - owner_token_ids, - 6, - true, - 250, - 300, - ); - - let pool_chunks: Vec> = pools - .into_iter() - .filter(|p| p.can_sell_nfts()) - .chunks(3) - .into_iter() - .map(|chunk| chunk.collect()) - .collect(); - - let marketplace_params: ParamsResponse = router - .wrap() - .query_wasm_smart(marketplace, &MarketplaceQueryMsg::Params {}) - .unwrap(); - let collection_info: CollectionInfoResponse = router - .wrap() - .query_wasm_smart(collection.clone(), &Sg721QueryMsg::CollectionInfo {}) - .unwrap(); - - for chunk in pool_chunks { - let mut pool_nfts_to_swap_for: Vec = vec![]; - for pool in chunk.iter() { - let nft_token_ids_response: NftTokenIdsResponse = router - .wrap() - .query_wasm_smart( - infinity_swap.clone(), - &QueryMsg::PoolNftTokenIds { - pool_id: pool.id, - query_options: QueryOptions { - descending: None, - start_after: None, - limit: Some(3), - }, - }, - ) - .unwrap(); - - pool_nfts_to_swap_for.push(PoolNftSwap { - pool_id: pool.id, - nft_swaps: nft_token_ids_response - .nft_token_ids - .iter() - .map(|token_id| NftSwap { - nft_token_id: token_id.to_string(), - token_amount: Uint128::from(100_000u128), - }) - .collect(), - }); - } - - let sim_msg = QueryMsg::SimSwapTokensForSpecificNfts { - collection: collection.to_string(), - pool_nfts_to_swap_for, - sender: accts.bidder.to_string(), - swap_params: SwapParams { - deadline: Timestamp::from_nanos(GENESIS_MINT_START_TIME).plus_seconds(1000), - robust: false, - asset_recipient: None, - finder: Some(user2.to_string()), - }, - }; - - let res: StdResult = router - .wrap() - .query_wasm_smart(infinity_swap.clone(), &sim_msg); - - for swap in res.unwrap().swaps { - let pool = chunk.iter().find(|p| p.id == swap.pool_id).unwrap(); - validate_swap_fees( - &swap, - pool, - &marketplace_params, - &collection_info.royalty_info, - ); - } - } -} diff --git a/test/unit/src/infinity_swap_tests/swap_tests/direct_swap_nfts_for_tokens.rs b/test/unit/src/infinity_swap_tests/swap_tests/direct_swap_nfts_for_tokens.rs deleted file mode 100644 index f6acf8c..0000000 --- a/test/unit/src/infinity_swap_tests/swap_tests/direct_swap_nfts_for_tokens.rs +++ /dev/null @@ -1,142 +0,0 @@ -use crate::helpers::nft_functions::mint_and_approve_many; -use crate::helpers::pool_functions::prepare_pool_variations; -use crate::helpers::swap_functions::{setup_swap_test, validate_swap_outcome, SwapTestSetup}; -use crate::helpers::utils::get_native_balances; -use cosmwasm_std::{Addr, Timestamp, Uint128}; -use cw_multi_test::Executor; -use infinity_swap::msg::{ExecuteMsg, NftSwap, QueryMsg, SwapParams, SwapResponse}; -use sg721_base::msg::{CollectionInfoResponse, QueryMsg as Sg721QueryMsg}; -use sg_std::GENESIS_MINT_START_TIME; -use test_suite::common_setup::msg::MinterTemplateResponse; - -#[test] -fn correct_swap_simple() { - let SwapTestSetup { - vending_template: - MinterTemplateResponse { - mut router, - accts, - collection_response_vec, - .. - }, - infinity_swap, - .. - } = setup_swap_test(5000).unwrap(); - - let collection_resp = &collection_response_vec[0]; - let minter = collection_resp.minter.clone().unwrap(); - let collection = collection_resp.collection.clone().unwrap(); - - let owner_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.owner, - &minter, - &collection, - &infinity_swap, - 100, - ); - let mut bidder_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.bidder, - &minter, - &collection, - &infinity_swap, - 100, - ); - - let deposit_tokens_per_pool = Uint128::from(10_000u128); - - let pools = prepare_pool_variations( - &mut router, - 7, - &None, - &infinity_swap, - &collection, - &accts.owner, - deposit_tokens_per_pool, - owner_token_ids.to_vec(), - 6, - true, - 250, - 300, - ); - - let finder = Addr::unchecked("finder"); - let mut check_addresses = vec![ - accts.owner.clone(), - accts.bidder.clone(), - finder.clone(), - infinity_swap.clone(), - ]; - - let collection_info: CollectionInfoResponse = router - .wrap() - .query_wasm_smart(collection.clone(), &Sg721QueryMsg::CollectionInfo {}) - .unwrap(); - - if let Some(_royalty_info) = &collection_info.royalty_info { - check_addresses.push(Addr::unchecked(_royalty_info.payment_address.clone())); - } - - for pool in pools.iter() { - if !pool.can_buy_nfts() { - continue; - } - let num_swaps = 3; - let nfts_to_swap: Vec = bidder_token_ids - .drain(0..(num_swaps as usize)) - .map(|token_id| NftSwap { - nft_token_id: token_id, - token_amount: Uint128::from(10u128), - }) - .collect(); - - let sim_msg = QueryMsg::SimDirectSwapNftsForTokens { - pool_id: pool.id, - nfts_to_swap: nfts_to_swap.clone(), - sender: accts.bidder.to_string(), - swap_params: SwapParams { - deadline: Timestamp::from_nanos(GENESIS_MINT_START_TIME).plus_seconds(1000), - robust: false, - asset_recipient: None, - finder: Some(finder.to_string()), - }, - }; - - let _sim_res: SwapResponse = router - .wrap() - .query_wasm_smart(infinity_swap.clone(), &sim_msg) - .unwrap(); - - let exec_msg = ExecuteMsg::DirectSwapNftsForTokens { - pool_id: pool.id, - nfts_to_swap, - swap_params: SwapParams { - deadline: Timestamp::from_nanos(GENESIS_MINT_START_TIME).plus_seconds(1000), - robust: false, - asset_recipient: None, - finder: Some(finder.to_string()), - }, - }; - - let pre_swap_balances = get_native_balances(&router, &check_addresses); - let exec_res = router - .execute_contract(accts.bidder.clone(), infinity_swap.clone(), &exec_msg, &[]) - .unwrap(); - let post_swap_balances = get_native_balances(&router, &check_addresses); - - validate_swap_outcome( - &router, - &exec_res, - num_swaps, - &pre_swap_balances, - &post_swap_balances, - &pools, - &collection_info.royalty_info, - &accts.bidder, - &Some(finder.clone()), - ); - } -} diff --git a/test/unit/src/infinity_swap_tests/swap_tests/direct_swap_tokens_for_specific_nfts.rs b/test/unit/src/infinity_swap_tests/swap_tests/direct_swap_tokens_for_specific_nfts.rs deleted file mode 100644 index 3f50517..0000000 --- a/test/unit/src/infinity_swap_tests/swap_tests/direct_swap_tokens_for_specific_nfts.rs +++ /dev/null @@ -1,160 +0,0 @@ -use crate::helpers::nft_functions::mint_and_approve_many; -use crate::helpers::pool_functions::prepare_pool_variations; -use crate::helpers::swap_functions::{setup_swap_test, validate_swap_outcome, SwapTestSetup}; -use crate::helpers::utils::get_native_balances; -use cosmwasm_std::{coins, Addr, Timestamp, Uint128}; -use cw_multi_test::Executor; -use infinity_swap::msg::{ - ExecuteMsg, NftSwap, NftTokenIdsResponse, QueryMsg, QueryOptions, SwapParams, SwapResponse, -}; -use sg721_base::msg::{CollectionInfoResponse, QueryMsg as Sg721QueryMsg}; -use sg_std::{GENESIS_MINT_START_TIME, NATIVE_DENOM}; -use test_suite::common_setup::msg::MinterTemplateResponse; - -#[test] -fn correct_swap_simple() { - let SwapTestSetup { - vending_template: - MinterTemplateResponse { - mut router, - accts, - collection_response_vec, - .. - }, - infinity_swap, - .. - } = setup_swap_test(5000).unwrap(); - - let collection_resp = &collection_response_vec[0]; - let minter = collection_resp.minter.clone().unwrap(); - let collection = collection_resp.collection.clone().unwrap(); - - let owner_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.owner, - &minter, - &collection, - &infinity_swap, - 100, - ); - - let deposit_tokens_per_pool = Uint128::from(10_000u128); - - let pools = prepare_pool_variations( - &mut router, - 7, - &None, - &infinity_swap, - &collection, - &accts.owner, - deposit_tokens_per_pool, - owner_token_ids.to_vec(), - 6, - true, - 250, - 300, - ); - - let finder = Addr::unchecked("finder"); - let mut check_addresses = vec![ - accts.owner.clone(), - accts.bidder.clone(), - finder.clone(), - infinity_swap.clone(), - ]; - - let collection_info: CollectionInfoResponse = router - .wrap() - .query_wasm_smart(collection.clone(), &Sg721QueryMsg::CollectionInfo {}) - .unwrap(); - - if let Some(_royalty_info) = &collection_info.royalty_info { - check_addresses.push(Addr::unchecked(_royalty_info.payment_address.clone())); - } - - for pool in pools.iter() { - if !pool.can_sell_nfts() { - continue; - } - let num_swaps = 3u8; - let nft_token_ids_response: NftTokenIdsResponse = router - .wrap() - .query_wasm_smart( - infinity_swap.clone(), - &QueryMsg::PoolNftTokenIds { - pool_id: pool.id, - query_options: QueryOptions { - descending: None, - start_after: None, - limit: Some(num_swaps as u32), - }, - }, - ) - .unwrap(); - let nfts_to_swap_for: Vec = nft_token_ids_response - .nft_token_ids - .clone() - .into_iter() - .take(num_swaps as usize) - .map(|token_id| NftSwap { - nft_token_id: token_id, - token_amount: Uint128::from(100_000u128), - }) - .collect(); - - let sim_msg = QueryMsg::SimDirectSwapTokensForSpecificNfts { - pool_id: pool.id, - nfts_to_swap_for: nfts_to_swap_for.clone(), - sender: accts.bidder.to_string(), - swap_params: SwapParams { - deadline: Timestamp::from_nanos(GENESIS_MINT_START_TIME).plus_seconds(1000), - robust: false, - asset_recipient: None, - finder: Some(finder.to_string()), - }, - }; - - let _sim_res: SwapResponse = router - .wrap() - .query_wasm_smart(infinity_swap.clone(), &sim_msg) - .unwrap(); - - let exec_msg = ExecuteMsg::DirectSwapTokensForSpecificNfts { - pool_id: pool.id, - nfts_to_swap_for: nfts_to_swap_for.clone(), - swap_params: SwapParams { - deadline: Timestamp::from_nanos(GENESIS_MINT_START_TIME).plus_seconds(1000), - robust: false, - asset_recipient: None, - finder: Some(finder.to_string()), - }, - }; - let sender_amount = nfts_to_swap_for - .iter() - .fold(Uint128::zero(), |acc, nft| acc + nft.token_amount); - - let pre_swap_balances = get_native_balances(&router, &check_addresses); - let exec_res = router - .execute_contract( - accts.bidder.clone(), - infinity_swap.clone(), - &exec_msg, - &coins(sender_amount.u128(), NATIVE_DENOM), - ) - .unwrap(); - let post_swap_balances = get_native_balances(&router, &check_addresses); - - validate_swap_outcome( - &router, - &exec_res, - num_swaps, - &pre_swap_balances, - &post_swap_balances, - &pools, - &collection_info.royalty_info, - &accts.bidder, - &Some(finder.clone()), - ); - } -} diff --git a/test/unit/src/infinity_swap_tests/swap_tests/mod.rs b/test/unit/src/infinity_swap_tests/swap_tests/mod.rs deleted file mode 100644 index 6662592..0000000 --- a/test/unit/src/infinity_swap_tests/swap_tests/mod.rs +++ /dev/null @@ -1,14 +0,0 @@ -#[cfg(test)] -mod direct_swap_nfts_for_tokens; - -#[cfg(test)] -mod direct_swap_tokens_for_specific_nfts; - -#[cfg(test)] -mod swap_nfts_for_tokens; - -#[cfg(test)] -mod swap_tokens_for_any_nfts; - -#[cfg(test)] -mod swap_tokens_for_specific_nfts; diff --git a/test/unit/src/infinity_swap_tests/swap_tests/swap_nfts_for_tokens.rs b/test/unit/src/infinity_swap_tests/swap_tests/swap_nfts_for_tokens.rs deleted file mode 100644 index 9893dad..0000000 --- a/test/unit/src/infinity_swap_tests/swap_tests/swap_nfts_for_tokens.rs +++ /dev/null @@ -1,138 +0,0 @@ -use crate::helpers::nft_functions::mint_and_approve_many; -use crate::helpers::pool_functions::prepare_pool_variations; -use crate::helpers::swap_functions::{setup_swap_test, validate_swap_outcome, SwapTestSetup}; -use crate::helpers::utils::get_native_balances; -use cosmwasm_std::{Addr, Timestamp, Uint128}; -use cw_multi_test::Executor; -use infinity_swap::msg::{ExecuteMsg, NftSwap, QueryMsg, SwapParams, SwapResponse}; -use sg721_base::msg::{CollectionInfoResponse, QueryMsg as Sg721QueryMsg}; -use sg_std::GENESIS_MINT_START_TIME; -use test_suite::common_setup::msg::MinterTemplateResponse; - -#[test] -fn correct_swap_simple() { - let SwapTestSetup { - vending_template: - MinterTemplateResponse { - mut router, - accts, - collection_response_vec, - .. - }, - infinity_swap, - .. - } = setup_swap_test(5000).unwrap(); - - let collection_resp = &collection_response_vec[0]; - let minter = collection_resp.minter.clone().unwrap(); - let collection = collection_resp.collection.clone().unwrap(); - - let owner_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.owner, - &minter, - &collection, - &infinity_swap, - 100, - ); - let bidder_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.bidder, - &minter, - &collection, - &infinity_swap, - 100, - ); - - let deposit_tokens_per_pool = Uint128::from(10_000u128); - - let pools = prepare_pool_variations( - &mut router, - 7, - &None, - &infinity_swap, - &collection, - &accts.owner, - deposit_tokens_per_pool, - owner_token_ids.to_vec(), - 6, - true, - 250, - 300, - ); - - let finder = Addr::unchecked("finder"); - let mut check_addresses = vec![ - accts.owner.clone(), - accts.bidder.clone(), - finder.clone(), - infinity_swap.clone(), - ]; - - let collection_info: CollectionInfoResponse = router - .wrap() - .query_wasm_smart(collection.clone(), &Sg721QueryMsg::CollectionInfo {}) - .unwrap(); - - if let Some(_royalty_info) = &collection_info.royalty_info { - check_addresses.push(Addr::unchecked(_royalty_info.payment_address.clone())); - } - - let num_swaps: u8 = 10; - - let nfts_to_swap: Vec = bidder_token_ids - .to_vec() - .drain(0..(num_swaps as usize)) - .map(|token_id| NftSwap { - nft_token_id: token_id, - token_amount: Uint128::from(100u128), - }) - .collect(); - let sim_msg = QueryMsg::SimSwapNftsForTokens { - collection: collection.to_string(), - nfts_to_swap: nfts_to_swap.clone(), - sender: accts.bidder.to_string(), - swap_params: SwapParams { - deadline: Timestamp::from_nanos(GENESIS_MINT_START_TIME).plus_seconds(1000), - robust: false, - asset_recipient: None, - finder: Some(finder.to_string()), - }, - }; - - let _sim_res: SwapResponse = router - .wrap() - .query_wasm_smart(infinity_swap.clone(), &sim_msg) - .unwrap(); - - let exec_msg = ExecuteMsg::SwapNftsForTokens { - collection: collection.to_string(), - nfts_to_swap, - swap_params: SwapParams { - deadline: Timestamp::from_nanos(GENESIS_MINT_START_TIME).plus_seconds(1000), - robust: false, - asset_recipient: None, - finder: Some(finder.to_string()), - }, - }; - - let pre_swap_balances = get_native_balances(&router, &check_addresses); - let exec_res = router - .execute_contract(accts.bidder.clone(), infinity_swap.clone(), &exec_msg, &[]) - .unwrap(); - let post_swap_balances = get_native_balances(&router, &check_addresses); - - validate_swap_outcome( - &router, - &exec_res, - num_swaps, - &pre_swap_balances, - &post_swap_balances, - &pools, - &collection_info.royalty_info, - &accts.bidder, - &Some(finder), - ); -} diff --git a/test/unit/src/infinity_swap_tests/swap_tests/swap_tokens_for_any_nfts.rs b/test/unit/src/infinity_swap_tests/swap_tests/swap_tokens_for_any_nfts.rs deleted file mode 100644 index 10fce1e..0000000 --- a/test/unit/src/infinity_swap_tests/swap_tests/swap_tokens_for_any_nfts.rs +++ /dev/null @@ -1,129 +0,0 @@ -use crate::helpers::nft_functions::mint_and_approve_many; -use crate::helpers::pool_functions::prepare_pool_variations; -use crate::helpers::swap_functions::{setup_swap_test, validate_swap_outcome, SwapTestSetup}; -use crate::helpers::utils::get_native_balances; -use cosmwasm_std::{coins, Addr, Timestamp, Uint128}; -use cw_multi_test::Executor; -use infinity_swap::msg::{ExecuteMsg, QueryMsg, SwapParams, SwapResponse}; -use sg721_base::msg::{CollectionInfoResponse, QueryMsg as Sg721QueryMsg}; -use sg_std::{GENESIS_MINT_START_TIME, NATIVE_DENOM}; -use test_suite::common_setup::msg::MinterTemplateResponse; - -#[test] -fn correct_swap_simple() { - let SwapTestSetup { - vending_template: - MinterTemplateResponse { - mut router, - accts, - collection_response_vec, - .. - }, - infinity_swap, - .. - } = setup_swap_test(5000).unwrap(); - - let collection_resp = &collection_response_vec[0]; - let minter = collection_resp.minter.clone().unwrap(); - let collection = collection_resp.collection.clone().unwrap(); - - let owner_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.owner, - &minter, - &collection, - &infinity_swap, - 100, - ); - - let deposit_tokens_per_pool = Uint128::from(10_000u128); - - let pools = prepare_pool_variations( - &mut router, - 7, - &None, - &infinity_swap, - &collection, - &accts.owner, - deposit_tokens_per_pool, - owner_token_ids.to_vec(), - 6, - true, - 250, - 300, - ); - - let finder = Addr::unchecked("finder"); - let mut check_addresses = vec![ - accts.owner.clone(), - accts.bidder.clone(), - finder.clone(), - infinity_swap.clone(), - ]; - - let collection_info: CollectionInfoResponse = router - .wrap() - .query_wasm_smart(collection.clone(), &Sg721QueryMsg::CollectionInfo {}) - .unwrap(); - - if let Some(_royalty_info) = &collection_info.royalty_info { - check_addresses.push(Addr::unchecked(_royalty_info.payment_address.clone())); - } - - let num_swaps: u8 = 10; - let max_expected_token_input: Vec = - vec![Uint128::from(1_000_000u128); num_swaps as usize]; - let sim_msg = QueryMsg::SimSwapTokensForAnyNfts { - collection: collection.to_string(), - max_expected_token_input: max_expected_token_input.clone(), - sender: accts.bidder.to_string(), - swap_params: SwapParams { - deadline: Timestamp::from_nanos(GENESIS_MINT_START_TIME).plus_seconds(1000), - robust: false, - asset_recipient: None, - finder: Some(finder.to_string()), - }, - }; - - let _res: SwapResponse = router - .wrap() - .query_wasm_smart(infinity_swap.clone(), &sim_msg) - .unwrap(); - - let exec_msg = ExecuteMsg::SwapTokensForAnyNfts { - collection: collection.to_string(), - max_expected_token_input: max_expected_token_input.clone(), - swap_params: SwapParams { - deadline: Timestamp::from_nanos(GENESIS_MINT_START_TIME).plus_seconds(1000), - robust: false, - asset_recipient: None, - finder: Some(finder.to_string()), - }, - }; - - let sender_amount = max_expected_token_input.iter().sum::(); - - let pre_swap_balances = get_native_balances(&router, &check_addresses); - let exec_res = router - .execute_contract( - accts.bidder.clone(), - infinity_swap.clone(), - &exec_msg, - &coins(sender_amount.u128(), NATIVE_DENOM), - ) - .unwrap(); - let post_swap_balances = get_native_balances(&router, &check_addresses); - - validate_swap_outcome( - &router, - &exec_res, - num_swaps, - &pre_swap_balances, - &post_swap_balances, - &pools, - &collection_info.royalty_info, - &accts.bidder, - &Some(finder), - ); -} diff --git a/test/unit/src/infinity_swap_tests/swap_tests/swap_tokens_for_specific_nfts.rs b/test/unit/src/infinity_swap_tests/swap_tests/swap_tokens_for_specific_nfts.rs deleted file mode 100644 index 35f50d9..0000000 --- a/test/unit/src/infinity_swap_tests/swap_tests/swap_tokens_for_specific_nfts.rs +++ /dev/null @@ -1,176 +0,0 @@ -use crate::helpers::nft_functions::mint_and_approve_many; -use crate::helpers::pool_functions::prepare_pool_variations; -use crate::helpers::swap_functions::{setup_swap_test, validate_swap_outcome, SwapTestSetup}; -use crate::helpers::utils::get_native_balances; -use cosmwasm_std::{coins, Addr, Timestamp, Uint128}; -use cw_multi_test::Executor; -use infinity_swap::msg::{ - ExecuteMsg, NftSwap, NftTokenIdsResponse, PoolNftSwap, QueryMsg, QueryOptions, SwapParams, - SwapResponse, -}; -use infinity_swap::state::Pool; -use itertools::Itertools; -use sg721_base::msg::{CollectionInfoResponse, QueryMsg as Sg721QueryMsg}; -use sg_std::{GENESIS_MINT_START_TIME, NATIVE_DENOM}; -use test_suite::common_setup::msg::MinterTemplateResponse; - -#[test] -fn correct_swap_simple() { - let SwapTestSetup { - vending_template: - MinterTemplateResponse { - mut router, - accts, - collection_response_vec, - .. - }, - infinity_swap, - .. - } = setup_swap_test(5000).unwrap(); - - let collection_resp = &collection_response_vec[0]; - let minter = collection_resp.minter.clone().unwrap(); - let collection = collection_resp.collection.clone().unwrap(); - - let owner_token_ids = mint_and_approve_many( - &mut router, - &accts.creator, - &accts.owner, - &minter, - &collection, - &infinity_swap, - 100, - ); - - let deposit_tokens_per_pool = Uint128::from(10_000u128); - - let pools = prepare_pool_variations( - &mut router, - 7, - &None, - &infinity_swap, - &collection, - &accts.owner, - deposit_tokens_per_pool, - owner_token_ids.to_vec(), - 6, - true, - 250, - 300, - ); - - let pool_chunks: Vec> = pools - .iter() - .filter(|&p| p.can_sell_nfts()) - .chunks(3_usize) - .into_iter() - .map(|chunk| chunk.collect()) - .collect(); - - let finder = Addr::unchecked("finder"); - let mut check_addresses = vec![ - accts.owner.clone(), - accts.bidder.clone(), - finder.clone(), - infinity_swap.clone(), - ]; - - let collection_info: CollectionInfoResponse = router - .wrap() - .query_wasm_smart(collection.clone(), &Sg721QueryMsg::CollectionInfo {}) - .unwrap(); - - if let Some(_royalty_info) = &collection_info.royalty_info { - check_addresses.push(Addr::unchecked(_royalty_info.payment_address.clone())); - } - - for chunk in pool_chunks { - let mut pool_nfts_to_swap_for: Vec = vec![]; - let mut sender_amount = Uint128::zero(); - - let swaps_per_chunk: u8 = 3; - for pool in &chunk { - let nft_token_ids_response: NftTokenIdsResponse = router - .wrap() - .query_wasm_smart( - infinity_swap.clone(), - &QueryMsg::PoolNftTokenIds { - pool_id: pool.id, - query_options: QueryOptions { - descending: None, - start_after: None, - limit: Some(swaps_per_chunk as u32), - }, - }, - ) - .unwrap(); - - pool_nfts_to_swap_for.push(PoolNftSwap { - pool_id: pool.id, - nft_swaps: nft_token_ids_response - .nft_token_ids - .iter() - .map(|token_id| { - let nft_swap = NftSwap { - nft_token_id: token_id.to_string(), - token_amount: Uint128::from(100_000u128), - }; - sender_amount += nft_swap.token_amount; - nft_swap - }) - .collect(), - }); - } - - let sim_msg = QueryMsg::SimSwapTokensForSpecificNfts { - collection: collection.to_string(), - pool_nfts_to_swap_for: pool_nfts_to_swap_for.clone(), - sender: accts.bidder.to_string(), - swap_params: SwapParams { - deadline: Timestamp::from_nanos(GENESIS_MINT_START_TIME).plus_seconds(1000), - robust: false, - asset_recipient: None, - finder: Some(finder.to_string()), - }, - }; - - let _sim_res: SwapResponse = router - .wrap() - .query_wasm_smart(infinity_swap.clone(), &sim_msg) - .unwrap(); - - let exec_msg = ExecuteMsg::SwapTokensForSpecificNfts { - collection: collection.to_string(), - pool_nfts_to_swap_for: pool_nfts_to_swap_for.clone(), - swap_params: SwapParams { - deadline: Timestamp::from_nanos(GENESIS_MINT_START_TIME).plus_seconds(1000), - robust: false, - asset_recipient: None, - finder: Some(finder.to_string()), - }, - }; - - let pre_swap_balances = get_native_balances(&router, &check_addresses); - let exec_res = router - .execute_contract( - accts.bidder.clone(), - infinity_swap.clone(), - &exec_msg, - &coins(sender_amount.u128(), NATIVE_DENOM), - ) - .unwrap(); - let post_swap_balances = get_native_balances(&router, &check_addresses); - - validate_swap_outcome( - &router, - &exec_res, - chunk.len() as u8 * swaps_per_chunk, - &pre_swap_balances, - &post_swap_balances, - &pools, - &collection_info.royalty_info, - &accts.bidder, - &Some(finder.clone()), - ); - } -} diff --git a/test/unit/src/lib.rs b/test/unit/src/lib.rs index 08d75fb..650f646 100644 --- a/test/unit/src/lib.rs +++ b/test/unit/src/lib.rs @@ -6,11 +6,14 @@ mod helpers; #[cfg(test)] mod setup; -#[cfg(test)] -mod infinity_marketplace_adapter_tests; +// #[cfg(test)] +// mod infinity_marketplace_adapter_tests; -#[cfg(test)] -mod infinity_shared_tests; +// #[cfg(test)] +// mod infinity_shared_tests; + +// #[cfg(test)] +// mod infinity_swap_tests; #[cfg(test)] -mod infinity_swap_tests; +mod tracer_tests; diff --git a/test/unit/src/setup/mod.rs b/test/unit/src/setup/mod.rs index 510109b..d22d418 100644 --- a/test/unit/src/setup/mod.rs +++ b/test/unit/src/setup/mod.rs @@ -1,7 +1,8 @@ pub mod msg; pub mod setup_accounts; pub mod setup_contracts; -pub mod setup_infinity_marketplace_adapter; -pub mod setup_infinity_swap; +// pub mod setup_infinity_marketplace_adapter; +// pub mod setup_infinity_swap; +pub mod setup_infinity_contracts; pub mod setup_marketplace; pub mod templates; diff --git a/test/unit/src/setup/setup_accounts.rs b/test/unit/src/setup/setup_accounts.rs index bacc487..4e3d091 100644 --- a/test/unit/src/setup/setup_accounts.rs +++ b/test/unit/src/setup/setup_accounts.rs @@ -1,7 +1,6 @@ -use cosmwasm_std::{coins, Addr, Coin}; +use cosmwasm_std::{coins, Addr, Coin, StdResult}; use cw_multi_test::SudoMsg as CwSudoMsg; use cw_multi_test::{BankSudo, SudoMsg}; -use sg_marketplace::ContractError; use sg_multi_test::StargazeApp; use sg_std::NATIVE_DENOM; @@ -10,7 +9,7 @@ pub const INITIAL_BALANCE: u128 = 5_000_000_000; pub const _MINT_PRICE: u128 = 100_000_000; // initializes accounts with balances -pub fn setup_accounts(router: &mut StargazeApp) -> Result<(Addr, Addr, Addr), ContractError> { +pub fn setup_accounts(router: &mut StargazeApp) -> StdResult<(Addr, Addr, Addr)> { let owner: Addr = Addr::unchecked("owner"); let bidder: Addr = Addr::unchecked("bidder"); let creator: Addr = Addr::unchecked("creator"); @@ -59,7 +58,7 @@ pub fn setup_addtl_account( router: &mut StargazeApp, input: &str, initial_balance: u128, -) -> Result { +) -> StdResult { let addr: Addr = Addr::unchecked(input); let funds: Vec = coins(initial_balance, NATIVE_DENOM); router diff --git a/test/unit/src/setup/setup_contracts.rs b/test/unit/src/setup/setup_contracts.rs index 2b6ed78..a274c92 100644 --- a/test/unit/src/setup/setup_contracts.rs +++ b/test/unit/src/setup/setup_contracts.rs @@ -13,21 +13,21 @@ pub fn contract_marketplace() -> Box> { Box::new(contract) } -pub fn contract_infinity_swap() -> Box> { - let contract = ContractWrapper::new( - infinity_swap::execute::execute, - infinity_swap::instantiate::instantiate, - infinity_swap::query::query, - ); - Box::new(contract) -} +// pub fn contract_infinity_swap() -> Box> { +// let contract = ContractWrapper::new( +// infinity_swap::execute::execute, +// infinity_swap::instantiate::instantiate, +// infinity_swap::query::query, +// ); +// Box::new(contract) +// } -pub fn contract_infinity_marketplace_adapter() -> Box> { - let contract = ContractWrapper::new( - infinity_marketplace_adapter::execute::execute, - infinity_marketplace_adapter::instantiate::instantiate, - infinity_marketplace_adapter::query::query, - ) - .with_reply(infinity_marketplace_adapter::reply::reply); - Box::new(contract) -} +// pub fn contract_infinity_marketplace_adapter() -> Box> { +// let contract = ContractWrapper::new( +// infinity_marketplace_adapter::execute::execute, +// infinity_marketplace_adapter::instantiate::instantiate, +// infinity_marketplace_adapter::query::query, +// ) +// .with_reply(infinity_marketplace_adapter::reply::reply); +// Box::new(contract) +// } diff --git a/test/unit/src/setup/setup_infinity_contracts.rs b/test/unit/src/setup/setup_infinity_contracts.rs new file mode 100644 index 0000000..52e9758 --- /dev/null +++ b/test/unit/src/setup/setup_infinity_contracts.rs @@ -0,0 +1,72 @@ +use cosmwasm_std::Addr; +use cw_multi_test::{Contract, ContractWrapper, Executor}; +use sg_multi_test::StargazeApp; +use sg_std::StargazeMsgWrapper; + +pub fn contract_infinity_pool() -> Box> { + let contract = ContractWrapper::new( + infinity_pool::execute::execute, + infinity_pool::instantiate::instantiate, + infinity_pool::query::query, + ); + Box::new(contract) +} + +pub fn contract_infinity_index() -> Box> { + let contract = ContractWrapper::new( + infinity_index::execute::execute, + infinity_index::instantiate::instantiate, + infinity_index::query::query, + ); + Box::new(contract) +} + +pub fn setup_infinity_index( + router: &mut StargazeApp, + creator: &Addr, + marketplace: &Addr, + infinity_factory: &Addr, +) -> Result { + let infinity_index_code_id = router.store_code(contract_infinity_index()); + let msg = infinity_index::msg::InstantiateMsg { + global_gov: marketplace.to_string(), + infinity_factory: infinity_factory.to_string(), + }; + router.instantiate_contract( + infinity_index_code_id, + creator.clone(), + &msg, + &[], + "InfinityIndex", + None, + ) +} + +pub fn contract_infinity_router() -> Box> { + let contract = ContractWrapper::new( + infinity_router::execute::execute, + infinity_router::instantiate::instantiate, + infinity_router::query::query, + ); + Box::new(contract) +} + +pub fn setup_infinity_router( + router: &mut StargazeApp, + creator: &Addr, + marketplace: &Addr, + infinity_index: &Addr, +) -> Result { + let infinity_router_code_id = router.store_code(contract_infinity_router()); + let msg = infinity_router::msg::InstantiateMsg { + infinity_index: infinity_index.to_string(), + }; + router.instantiate_contract( + infinity_router_code_id, + creator.clone(), + &msg, + &[], + "InfinityRouter", + None, + ) +} diff --git a/test/unit/src/setup/setup_infinity_marketplace_adapter.rs b/test/unit/src/setup/setup_infinity_marketplace_adapter.rs deleted file mode 100644 index 3711178..0000000 --- a/test/unit/src/setup/setup_infinity_marketplace_adapter.rs +++ /dev/null @@ -1,29 +0,0 @@ -use super::setup_contracts::contract_infinity_marketplace_adapter; -use cosmwasm_std::Addr; -use cw_multi_test::Executor; -use sg_marketplace::ContractError; -use sg_multi_test::StargazeApp; - -pub fn setup_infinity_marketplace_adapter( - router: &mut StargazeApp, - sender: Addr, - marketplace_addr: Addr, -) -> Result { - let infinity_marketplace_adapter_id = - router.store_code(contract_infinity_marketplace_adapter()); - let msg = infinity_marketplace_adapter::msg::InstantiateMsg { - marketplace: marketplace_addr.to_string(), - max_batch_size: 100, - }; - let infinity_marketplace_adapter = router - .instantiate_contract( - infinity_marketplace_adapter_id, - sender, - &msg, - &[], - "Infinity Marketplace Adapter", - None, - ) - .unwrap(); - Ok(infinity_marketplace_adapter) -} diff --git a/test/unit/src/setup/setup_infinity_swap.rs b/test/unit/src/setup/setup_infinity_swap.rs deleted file mode 100644 index 224453a..0000000 --- a/test/unit/src/setup/setup_infinity_swap.rs +++ /dev/null @@ -1,23 +0,0 @@ -use super::setup_contracts::contract_infinity_swap; -use cosmwasm_std::Addr; -use cw_multi_test::Executor; -use sg_marketplace::ContractError; -use sg_multi_test::StargazeApp; -use sg_std::NATIVE_DENOM; - -pub fn setup_infinity_swap( - router: &mut StargazeApp, - sender: Addr, - marketplace_addr: Addr, -) -> Result { - let infinity_swap_id = router.store_code(contract_infinity_swap()); - let msg = infinity_swap::msg::InstantiateMsg { - denom: NATIVE_DENOM.to_string(), - marketplace_addr: marketplace_addr.to_string(), - developer: None, - }; - let infinity_swap = router - .instantiate_contract(infinity_swap_id, sender, &msg, &[], "Infinity Swap", None) - .unwrap(); - Ok(infinity_swap) -} diff --git a/test/unit/src/tracer_tests/mod.rs b/test/unit/src/tracer_tests/mod.rs new file mode 100644 index 0000000..722eec2 --- /dev/null +++ b/test/unit/src/tracer_tests/mod.rs @@ -0,0 +1,149 @@ +use crate::helpers::nft_functions::{approve_all, validate_nft_owner}; +use crate::helpers::tracer_functions::{create_pool, SwapTestSetup}; +use crate::helpers::{nft_functions::mint_and_approve_many, tracer_functions::setup_swap_test}; +// use crate::helpers::tracer_functions::{setup_swap_test, validate_swap_outcome, SwapTestSetup}; +use crate::helpers::utils::get_native_balances; + +use cosmwasm_std::{Addr, Timestamp, Uint128}; +use cw_multi_test::Executor; +use infinity_index::msg::{PoolQuoteResponse, QueryMsg as InfinityIndexQueryMsg}; +use infinity_index::state::PoolQuote; +use infinity_pool::msg::{ExecuteMsg as InfinityIndexExecuteMsg, PoolInfo}; +use infinity_pool::state::{BondingCurve, PoolType}; +use infinity_router::msg::ExecuteMsg as InfinityRouterExecuteMsg; +use infinity_shared::interface::{NftOrder, SwapParams, SwapResponse}; +use sg_std::GENESIS_MINT_START_TIME; +use test_suite::common_setup::msg::MinterTemplateResponse; + +#[test] +fn infinity_redesign_tracer() { + let SwapTestSetup { + vending_template: + MinterTemplateResponse { + collection_response_vec, + mut router, + accts, + }, + marketplace, + infinity_index, + infinity_router, + infinity_pool_code_id, + } = setup_swap_test(5000).unwrap(); + + let collection_resp = &collection_response_vec[0]; + let minter = collection_resp.minter.clone().unwrap(); + let collection = collection_resp.collection.clone().unwrap(); + + let deposit_amount = Uint128::from(10_000_000u128); + + let response = create_pool( + &mut router, + infinity_pool_code_id, + &accts.owner, + marketplace.to_string(), + infinity_index.to_string(), + PoolInfo { + collection: collection.to_string(), + owner: accts.owner.to_string(), + asset_recipient: None, + pool_type: PoolType::Token, + bonding_curve: BondingCurve::Linear, + spot_price: Uint128::from(10_000u128), + delta: Uint128::from(10u128), + finders_fee_bps: 0u64, + swap_fee_bps: 0u64, + reinvest_tokens: false, + reinvest_nfts: false, + }, + deposit_amount, + ); + assert!(response.is_ok()); + + let infinity_pool = response.unwrap(); + + let mut bidder_token_ids = mint_and_approve_many( + &mut router, + &accts.creator, + &accts.bidder, + &minter, + &collection, + &infinity_pool, + 101, + ); + + let mut query_response: PoolQuoteResponse = router + .wrap() + .query_wasm_smart( + infinity_index.clone(), + &InfinityIndexQueryMsg::QuoteSellToPool { + collection: collection.to_string(), + limit: 1, + }, + ) + .unwrap(); + let pool_quote = query_response.pool_quotes.pop().unwrap(); + assert_eq!( + pool_quote, + PoolQuote { + pool: Addr::unchecked("contract6",), + collection: Addr::unchecked("contract2",), + quote_price: Uint128::from(10_000u128), + }, + ); + + let response = router + .execute_contract( + accts.bidder.clone(), + infinity_pool, + &InfinityIndexExecuteMsg::SwapNftsForTokens { + token_id: bidder_token_ids.pop().unwrap().to_string(), + min_output: Uint128::from(1u128), + asset_recipient: accts.bidder.to_string(), + finder: None, + }, + &[], + ) + .unwrap(); + + let mut query_response: PoolQuoteResponse = router + .wrap() + .query_wasm_smart( + infinity_index.clone(), + &InfinityIndexQueryMsg::QuoteSellToPool { + collection: collection.to_string(), + limit: 1, + }, + ) + .unwrap(); + let pool_quote = query_response.pool_quotes.pop().unwrap(); + assert_eq!( + pool_quote, + PoolQuote { + pool: Addr::unchecked("contract6",), + collection: Addr::unchecked("contract2",), + quote_price: Uint128::from(9990u128), + }, + ); + + let nft_orders: Vec = bidder_token_ids + .iter() + .map(|token_id| NftOrder { + token_id: token_id.to_string(), + amount: Uint128::from(1u128), + }) + .collect(); + + approve_all(&mut router, &accts.bidder, &collection, &infinity_router); + let response = router.execute_contract( + accts.bidder.clone(), + infinity_router, + &InfinityRouterExecuteMsg::SwapNftsForTokens { + collection: collection.to_string(), + sender: accts.bidder.to_string(), + nft_orders, + }, + &[], + ); + + println!("{:?}", response); +}