From acc72f82edaa94634e2fed00f5c44e43a83ba984 Mon Sep 17 00:00:00 2001 From: Wilhelm Thieme Date: Fri, 16 Aug 2024 09:22:46 -0400 Subject: [PATCH] Squash --- .github/workflows/checks.yml | 2 +- docs/legacy/package.json | 1 + docs/ts/package.json | 1 + programs/whirlpool/package.json | 4 +- rust-sdk/client/package.json | 4 +- rust-sdk/utils/Cargo.lock | 470 ++++++++++++++++++++++++ rust-sdk/utils/Cargo.toml | 21 ++ rust-sdk/utils/package.json | 11 + rust-sdk/utils/src/constants/bundle.rs | 1 + rust-sdk/utils/src/constants/mod.rs | 7 + rust-sdk/utils/src/constants/tick.rs | 4 + rust-sdk/utils/src/lib.rs | 12 + rust-sdk/utils/src/math/bundle.rs | 116 ++++++ rust-sdk/utils/src/math/mod.rs | 11 + rust-sdk/utils/src/math/price.rs | 148 ++++++++ rust-sdk/utils/src/math/tick.rs | 476 +++++++++++++++++++++++++ rust-sdk/utils/src/quote/fees.rs | 187 ++++++++++ rust-sdk/utils/src/quote/liquidity.rs | 12 + rust-sdk/utils/src/quote/mod.rs | 9 + rust-sdk/utils/src/quote/rewards.rs | 245 +++++++++++++ rust-sdk/utils/src/quote/swap.rs | 5 + rust-sdk/utils/src/types/fees.rs | 17 + rust-sdk/utils/src/types/mod.rs | 9 + rust-sdk/utils/src/types/rewards.rs | 18 + rust-sdk/utils/src/types/tick.rs | 16 + rust-sdk/utils/src/types/u128.rs | 49 +++ rust-sdk/whirlpool/Cargo.lock | 21 ++ rust-sdk/whirlpool/Cargo.toml | 1 + rust-sdk/whirlpool/package.json | 4 +- rust-sdk/whirlpool/src/lib.rs | 1 + ts-sdk/utils/Cargo.lock | 289 +++++++++++++++ ts-sdk/utils/Cargo.toml | 13 + ts-sdk/utils/package.json | 26 ++ ts-sdk/utils/src/lib.rs | 1 + ts-sdk/utils/test.sh | 14 + ts-sdk/whirlpool/package.json | 3 +- ts-sdk/whirlpool/src/index.ts | 1 + yarn.lock | 82 ++++- 38 files changed, 2291 insertions(+), 21 deletions(-) create mode 100644 rust-sdk/utils/Cargo.lock create mode 100644 rust-sdk/utils/Cargo.toml create mode 100644 rust-sdk/utils/package.json create mode 100644 rust-sdk/utils/src/constants/bundle.rs create mode 100644 rust-sdk/utils/src/constants/mod.rs create mode 100644 rust-sdk/utils/src/constants/tick.rs create mode 100644 rust-sdk/utils/src/lib.rs create mode 100644 rust-sdk/utils/src/math/bundle.rs create mode 100644 rust-sdk/utils/src/math/mod.rs create mode 100644 rust-sdk/utils/src/math/price.rs create mode 100644 rust-sdk/utils/src/math/tick.rs create mode 100644 rust-sdk/utils/src/quote/fees.rs create mode 100644 rust-sdk/utils/src/quote/liquidity.rs create mode 100644 rust-sdk/utils/src/quote/mod.rs create mode 100644 rust-sdk/utils/src/quote/rewards.rs create mode 100644 rust-sdk/utils/src/quote/swap.rs create mode 100644 rust-sdk/utils/src/types/fees.rs create mode 100644 rust-sdk/utils/src/types/mod.rs create mode 100644 rust-sdk/utils/src/types/rewards.rs create mode 100644 rust-sdk/utils/src/types/tick.rs create mode 100644 rust-sdk/utils/src/types/u128.rs create mode 100644 ts-sdk/utils/Cargo.lock create mode 100644 ts-sdk/utils/Cargo.toml create mode 100644 ts-sdk/utils/package.json create mode 100644 ts-sdk/utils/src/lib.rs create mode 100644 ts-sdk/utils/test.sh diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 1774ae811..e8bbbbf4c 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -2,7 +2,7 @@ name: Checks on: pull_request: - branches: [main] + branches: "*" concurrency: group: "checks" diff --git a/docs/legacy/package.json b/docs/legacy/package.json index 36a9f0416..e196f0377 100644 --- a/docs/legacy/package.json +++ b/docs/legacy/package.json @@ -8,6 +8,7 @@ "clean": "rimraf dist" }, "devDependencies": { + "@orca-so/whirlpools": "*", "@orca-so/whirlpools-sdk": "*", "typedoc": "^0.26.5", "typescript": "^5.5.4" diff --git a/docs/ts/package.json b/docs/ts/package.json index ffc4dd6b1..814f4a33b 100644 --- a/docs/ts/package.json +++ b/docs/ts/package.json @@ -9,6 +9,7 @@ }, "devDependencies": { "@orca-so/whirlpools": "*", + "@orca-so/whirlpools-sdk": "*", "typedoc": "^0.26.5", "typescript": "^5.5.4" } diff --git a/programs/whirlpool/package.json b/programs/whirlpool/package.json index 466d11e20..346166e8c 100644 --- a/programs/whirlpool/package.json +++ b/programs/whirlpool/package.json @@ -5,8 +5,8 @@ "scripts": { "build": "anchor build -p whirlpool", "test": "cargo test -p whirlpool --lib", - "format": "cargo clippy -p whirlpool --fix --allow-dirty --allow-staged -- -D clippy::all && cargo fmt -p whirlpool", - "lint": "cargo clippy -p whirlpool -- -D clippy::all", + "format": "cargo clippy -p whirlpool --fix --allow-dirty --allow-staged && cargo fmt -p whirlpool", + "lint": "cargo clippy -p whirlpool", "clean": "anchor clean" } } diff --git a/rust-sdk/client/package.json b/rust-sdk/client/package.json index eb0d4ecb4..54f8f427b 100644 --- a/rust-sdk/client/package.json +++ b/rust-sdk/client/package.json @@ -5,8 +5,8 @@ "scripts": { "build": "node ./kinobi.js && cargo build", "test": "cargo test --lib", - "format": "cargo clippy --fix --allow-dirty --allow-staged -- -D clippy::all && cargo fmt", - "lint": "cargo clippy -- -D clippy::all", + "format": "cargo clippy --fix --allow-dirty --allow-staged && cargo fmt", + "lint": "cargo clippy", "clean": "cargo clean" }, "devDependencies": { diff --git a/rust-sdk/utils/Cargo.lock b/rust-sdk/utils/Cargo.lock new file mode 100644 index 000000000..4a9d3c768 --- /dev/null +++ b/rust-sdk/utils/Cargo.lock @@ -0,0 +1,470 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "approx" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0e60b75072ecd4168020818c0107f2857bb6c4e64252d8d3983f6263b40a5c3" +dependencies = [ + "num-traits", +] + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "cc" +version = "1.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68064e60dbf1f17005c2fde4d07c16d8baa506fd7ffed8ccab702d93617975c7" +dependencies = [ + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "document-features" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb6969eaabd2421f8a2775cfd2471a2b634372b4a25d41e3bd647b79912850a0" +dependencies = [ + "litrs", +] + +[[package]] +name = "dos-cp" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea38e2b4c8238a6ab3939a92df9c6a4566ee1b61d6f854c876d293dd71c8fa68" +dependencies = [ + "either", + "exit-no-std", + "iter-identify_first_last", + "panicking", + "pc-ints", +] + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "errno-no-std" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52957d5a39c0201d89003e04241836a10ec2d8052c2be288f32652d7643467bc" +dependencies = [ + "errno-sys", + "libc", + "widestring", + "winapi", +] + +[[package]] +name = "errno-sys" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f7083207e75d4435df450dc6413612d97fe5a441477aba02484f9f7f77057e" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "ethnum" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b90ca2580b73ab6a1f724b76ca11ab632df820fd6040c336200d2c1df7b3c82c" + +[[package]] +name = "exit-no-std" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7def75a0ce294b69f3b025ef7e15e74adc15c6543bbde027f3276b683f288b1c" +dependencies = [ + "libc", + "pc-ints", + "winapi", +] + +[[package]] +name = "gloo-utils" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037fcb07216cb3a30f7292bd0176b050b7b9a052ba830ef7d5d65f6dc64ba58e" +dependencies = [ + "js-sys", + "serde", + "serde_json", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "iter-identify_first_last" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16ed9150989e6046a3d1cd8e2049a6d00cce627565c0a0d1ea5dc3357eb3a755" +dependencies = [ + "document-features", +] + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "js-sys" +version = "0.3.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "libc" +version = "0.2.155" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" + +[[package]] +name = "libm" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" + +[[package]] +name = "litrs" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "orca_whirlpools_utils" +version = "0.1.0" +dependencies = [ + "approx", + "ethnum", + "libm", + "print-no-std", + "serde", + "serde-wasm-bindgen 0.6.5", + "tsify", + "wasm-bindgen", +] + +[[package]] +name = "panicking" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21eb594cd667adf943bf4617e74ca71e2f4041f2fa630d5fc7be9314a1b480de" + +[[package]] +name = "pc-ints" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46a0c5099ffcaf701968dbd51a2b05ababc9e3360d7ad0af87d2622a93b7efb7" +dependencies = [ + "memoffset", +] + +[[package]] +name = "print-no-std" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4617895c4a5787cff6720529173d06c1426925da4910638e66731557e847ba10" +dependencies = [ + "dos-cp", + "errno-no-std", + "iter-identify_first_last", + "libc", + "winapi", +] + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "serde" +version = "1.0.207" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5665e14a49a4ea1b91029ba7d3bca9f299e1f7cfa194388ccc20f14743e784f2" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde-wasm-bindgen" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3b143e2833c57ab9ad3ea280d21fd34e285a42837aeb0ee301f4f41890fa00e" +dependencies = [ + "js-sys", + "serde", + "wasm-bindgen", +] + +[[package]] +name = "serde-wasm-bindgen" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8302e169f0eddcc139c70f139d19d6467353af16f9fce27e8c30158036a1e16b" +dependencies = [ + "js-sys", + "serde", + "wasm-bindgen", +] + +[[package]] +name = "serde_derive" +version = "1.0.207" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6aea2634c86b0e8ef2cfdc0c340baede54ec27b1e46febd7f80dffb2aa44a00e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_derive_internals" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e578a843d40b4189a4d66bba51d7684f57da5bd7c304c64e14bd63efbef49509" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.125" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83c8e735a073ccf5be70aa8066aa984eaf2fa000db6c8d0100ae605b366d31ed" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "syn" +version = "2.0.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fceb41e3d546d0bd83421d3409b1460cc7444cd389341a4c880fe7a042cb3d7" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tsify" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6b26cf145f2f3b9ff84e182c448eaf05468e247f148cf3d2a7d67d78ff023a0" +dependencies = [ + "gloo-utils", + "serde", + "serde-wasm-bindgen 0.5.0", + "serde_json", + "tsify-macros", + "wasm-bindgen", +] + +[[package]] +name = "tsify-macros" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a94b0f0954b3e59bfc2c246b4c8574390d94a4ad4ad246aaf2fb07d7dfd3b47" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "wasm-bindgen" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" + +[[package]] +name = "web-sys" +version = "0.3.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "widestring" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7219d36b6eac893fa81e84ebe06485e7dcbb616177469b142df14f1f4deb1311" + +[[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-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/rust-sdk/utils/Cargo.toml b/rust-sdk/utils/Cargo.toml new file mode 100644 index 000000000..10f9693f3 --- /dev/null +++ b/rust-sdk/utils/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "orca_whirlpools_utils" +version = "0.1.0" +edition = "2021" + +[features] +default = ["floats"] +wasm = ["dep:wasm-bindgen", "dep:serde-wasm-bindgen", "dep:serde", "dep:tsify"] +floats = ["dep:libm"] + +[dependencies] +ethnum = { version = "^1.5.0" } +libm = { version = "^0.2.1", optional = true } +wasm-bindgen = { version = "^0.2.93", optional = true } +serde = { version = "^1.0.207", features = ["derive"], optional = true } +serde-wasm-bindgen = { version = "^0.6.5", optional = true } +tsify = { version = "^0.4.5", features = ["js"], optional = true } + +[dev-dependencies] +print-no-std = { version = "^0.1.0"} +approx = { version = "^0.3.2" } diff --git a/rust-sdk/utils/package.json b/rust-sdk/utils/package.json new file mode 100644 index 000000000..a4fb3e205 --- /dev/null +++ b/rust-sdk/utils/package.json @@ -0,0 +1,11 @@ +{ + "name": "@orca-so/whirlpools-rust-utils", + "version": "0.0.1", + "scripts": { + "build": "cargo build -p orca_whirlpools_utils", + "test": "cargo test -p orca_whirlpools_utils --lib", + "format": "cargo clippy --fix --allow-dirty --allow-staged && cargo fmt", + "lint": "cargo clippy", + "clean": "cargo clean -p orca_whirlpools_utils" + } +} diff --git a/rust-sdk/utils/src/constants/bundle.rs b/rust-sdk/utils/src/constants/bundle.rs new file mode 100644 index 000000000..ead337138 --- /dev/null +++ b/rust-sdk/utils/src/constants/bundle.rs @@ -0,0 +1 @@ +pub const POSITION_BUNDLE_SIZE: usize = 256; diff --git a/rust-sdk/utils/src/constants/mod.rs b/rust-sdk/utils/src/constants/mod.rs new file mode 100644 index 000000000..8561a50d7 --- /dev/null +++ b/rust-sdk/utils/src/constants/mod.rs @@ -0,0 +1,7 @@ +mod bundle; +mod tick; + +// FIXME: figure out a way to expose constants in wasm + +pub use bundle::*; +pub use tick::*; diff --git a/rust-sdk/utils/src/constants/tick.rs b/rust-sdk/utils/src/constants/tick.rs new file mode 100644 index 000000000..5d1699f8b --- /dev/null +++ b/rust-sdk/utils/src/constants/tick.rs @@ -0,0 +1,4 @@ +pub const TICK_ARRAY_SIZE: usize = 88; +pub const FULL_RANGE_ONLY_TICK_SPACING_THRESHOLD: u16 = 32768; // 2^15 +pub const MIN_TICK_INDEX: i32 = -443636; +pub const MAX_TICK_INDEX: i32 = 443636; diff --git a/rust-sdk/utils/src/lib.rs b/rust-sdk/utils/src/lib.rs new file mode 100644 index 000000000..17e6fed17 --- /dev/null +++ b/rust-sdk/utils/src/lib.rs @@ -0,0 +1,12 @@ +#![no_std] +#![allow(clippy::useless_conversion)] + +mod constants; +mod math; +mod quote; +mod types; + +pub use constants::*; +pub use math::*; +pub use quote::*; +pub use types::*; diff --git a/rust-sdk/utils/src/math/bundle.rs b/rust-sdk/utils/src/math/bundle.rs new file mode 100644 index 000000000..f12ad0a5c --- /dev/null +++ b/rust-sdk/utils/src/math/bundle.rs @@ -0,0 +1,116 @@ +#[cfg(feature = "wasm")] +use wasm_bindgen::prelude::*; + +use ethnum::U256; + +use crate::POSITION_BUNDLE_SIZE; + +const POSITION_BUNDLE_BYTES: usize = POSITION_BUNDLE_SIZE / 8; + +/// Get the first unoccupied position in a bundle +/// +/// # Arguments +/// * `bundle` - The bundle to check +/// +/// # Returns +/// * `u32` - The first unoccupied position +#[cfg_attr(feature = "wasm", wasm_bindgen(js_name = firstUnoccupiedPositionInBundle, skip_jsdoc))] +pub fn first_unoccupied_position_in_bundle(bitmap: &[u8]) -> u32 { + let value = bitmap_to_u256(bitmap); + for i in 0..POSITION_BUNDLE_SIZE { + if value & (U256::ONE << i) == 0 { + return i as u32; + } + } + panic!("No unoccupied position in bundle"); +} + +/// Check whether a position bundle is full +/// A position bundle can contain 256 positions +/// +/// # Arguments +/// * `bundle` - The bundle to check +/// +/// # Returns +/// * `bool` - Whether the bundle is full +#[cfg_attr(feature = "wasm", wasm_bindgen(js_name = isPositionBundleFull, skip_jsdoc))] +pub fn is_position_bundle_full(bitmap: &[u8]) -> bool { + let value = bitmap_to_u256(bitmap); + value == U256::MAX +} + +/// Check whether a position bundle is empty +/// +/// # Arguments +/// * `bundle` - The bundle to check +/// +/// # Returns +/// * `bool` - Whether the bundle is empty +#[cfg_attr(feature = "wasm", wasm_bindgen(js_name = isPositionBundleEmpty, skip_jsdoc))] +pub fn is_position_bundle_empty(bitmap: &[u8]) -> bool { + let value = bitmap_to_u256(bitmap); + value == U256::MIN +} + +// Private functions + +fn bitmap_to_u256(bitmap: &[u8]) -> U256 { + let mut u256 = ::from(0u32); + for i in 0..POSITION_BUNDLE_BYTES { + let byte = bitmap[i]; + u256 += ::from(byte) << (i * 8); + } + u256 +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_first_unoccupied_position_in_bundle() { + let bundle: [u8; POSITION_BUNDLE_BYTES] = [0; POSITION_BUNDLE_BYTES]; + assert_eq!(first_unoccupied_position_in_bundle(&bundle), 0); + + let mut empty_bundle: [u8; POSITION_BUNDLE_BYTES] = [0; POSITION_BUNDLE_BYTES]; + empty_bundle[0] = 0b11101111; + assert_eq!(first_unoccupied_position_in_bundle(&empty_bundle), 4); + + let mut full_bundle: [u8; POSITION_BUNDLE_BYTES] = [255; POSITION_BUNDLE_BYTES]; + full_bundle[10] = 0b10111111; + assert_eq!(first_unoccupied_position_in_bundle(&full_bundle), 86); + } + + #[test] + #[should_panic(expected = "No unoccupied position in bundle")] + fn test_first_unoccupied_position_in_bundle_panic() { + let bundle: [u8; POSITION_BUNDLE_BYTES] = [255; POSITION_BUNDLE_BYTES]; + first_unoccupied_position_in_bundle(&bundle); + } + + #[test] + fn test_is_position_bundle_full() { + let bundle: [u8; POSITION_BUNDLE_BYTES] = [0; POSITION_BUNDLE_BYTES]; + assert_eq!(is_position_bundle_full(&bundle), false); + + let bundle: [u8; POSITION_BUNDLE_BYTES] = [255; POSITION_BUNDLE_BYTES]; + assert_eq!(is_position_bundle_full(&bundle), true); + + let mut bundle: [u8; POSITION_BUNDLE_BYTES] = [0; POSITION_BUNDLE_BYTES]; + bundle[0] = 0b11111111; + assert_eq!(is_position_bundle_full(&bundle), false); + } + + #[test] + fn test_is_position_bundle_empty() { + let bundle: [u8; POSITION_BUNDLE_BYTES] = [0; POSITION_BUNDLE_BYTES]; + assert_eq!(is_position_bundle_empty(&bundle), true); + + let bundle: [u8; POSITION_BUNDLE_BYTES] = [255; POSITION_BUNDLE_BYTES]; + assert_eq!(is_position_bundle_empty(&bundle), false); + + let mut bundle: [u8; POSITION_BUNDLE_BYTES] = [0; POSITION_BUNDLE_BYTES]; + bundle[0] = 0b111111; + assert_eq!(is_position_bundle_empty(&bundle), false); + } +} diff --git a/rust-sdk/utils/src/math/mod.rs b/rust-sdk/utils/src/math/mod.rs new file mode 100644 index 000000000..ea8c2a5a0 --- /dev/null +++ b/rust-sdk/utils/src/math/mod.rs @@ -0,0 +1,11 @@ +mod bundle; +mod tick; + +#[cfg(feature = "floats")] +mod price; + +pub use bundle::*; +pub use tick::*; + +#[cfg(feature = "floats")] +pub use price::*; diff --git a/rust-sdk/utils/src/math/price.rs b/rust-sdk/utils/src/math/price.rs new file mode 100644 index 000000000..6de2e42de --- /dev/null +++ b/rust-sdk/utils/src/math/price.rs @@ -0,0 +1,148 @@ +#[cfg(feature = "wasm")] +use wasm_bindgen::prelude::*; + +use libm::{floor, pow, sqrt}; + +use crate::U128; + +use super::{invert_tick_index, sqrt_price_to_tick_index, tick_index_to_sqrt_price}; + +const Q64_RESOLUTION: f64 = 18446744073709551616.0; + +/// Convert a price into a sqrt priceX64 +/// IMPORTANT: floating point operations can reduce the precision of the result. +/// Make sure to do these operations last and not to use the result for further calculations. +/// +/// # Parameters +/// * `price` - The price to convert +/// * `decimals_a` - The number of decimals of the base token +/// * `decimals_b` - The number of decimals of the quote token +/// +/// # Returns +/// * `u128` - The sqrt priceX64 +#[cfg_attr(feature = "wasm", wasm_bindgen(js_name = priceToSqrtPrice, skip_jsdoc))] +pub fn price_to_sqrt_price(price: f64, decimals_a: u8, decimals_b: u8) -> U128 { + let power = pow(10f64, decimals_a as f64 - decimals_b as f64); + let sqrt_price = floor(sqrt(price * power) * Q64_RESOLUTION) as u128; + sqrt_price.into() +} + +/// Convert a sqrt priceX64 into a tick index +/// IMPORTANT: floating point operations can reduce the precision of the result. +/// Make sure to do these operations last and not to use the result for further calculations. +/// +/// # Parameters +/// * `sqrt_price` - The sqrt priceX64 to convert +/// * `decimals_a` - The number of decimals of the base token +/// * `decimals_b` - The number of decimals of the quote token +/// +/// # Returns +/// * `f64` - The decimal price +#[cfg_attr(feature = "wasm", wasm_bindgen(js_name = sqrtPriceToPrice, skip_jsdoc))] +pub fn sqrt_price_to_price(sqrt_price: U128, decimals_a: u8, decimals_b: u8) -> f64 { + let power = pow(10f64, decimals_a as f64 - decimals_b as f64); + let sqrt_price_u128 = ::from(sqrt_price) as f64; + pow(sqrt_price_u128 / Q64_RESOLUTION, 2.0) / power +} + +/// Invert a price +/// IMPORTANT: floating point operations can reduce the precision of the result. +/// Make sure to do these operations last and not to use the result for further calculations. +/// +/// # Parameters +/// * `price` - The price to invert +/// * `decimals_a` - The number of decimals of the base token +/// * `decimals_b` - The number of decimals of the quote token +/// +/// # Returns +/// * `f64` - The inverted price +#[cfg_attr(feature = "wasm", wasm_bindgen(js_name = invertPrice, skip_jsdoc))] +pub fn invert_price(price: f64, decimals_a: u8, decimals_b: u8) -> f64 { + let tick_index = price_to_tick_index(price, decimals_a, decimals_b); + let inverted_tick_index = invert_tick_index(tick_index); + tick_index_to_price(inverted_tick_index, decimals_a, decimals_b) +} + +/// Convert a tick index into a price +/// IMPORTANT: floating point operations can reduce the precision of the result. +/// Make sure to do these operations last and not to use the result for further calculations. +/// +/// # Parameters +/// * `tick_index` - The tick index to convert +/// * `decimals_a` - The number of decimals of the base token +/// * `decimals_b` - The number of decimals of the quote token +/// +/// # Returns +/// * `f64` - The decimal price +#[cfg_attr(feature = "wasm", wasm_bindgen(js_name = tickIndexToPrice, skip_jsdoc))] +pub fn tick_index_to_price(tick_index: i32, decimals_a: u8, decimals_b: u8) -> f64 { + let sqrt_price = tick_index_to_sqrt_price(tick_index); + sqrt_price_to_price(sqrt_price, decimals_a, decimals_b) +} + +/// Convert a price into a tick index +/// IMPORTANT: floating point operations can reduce the precision of the result. +/// Make sure to do these operations last and not to use the result for further calculations. +/// +/// # Parameters +/// * `price` - The price to convert +/// * `decimals_a` - The number of decimals of the base token +/// * `decimals_b` - The number of decimals of the quote token +/// +/// # Returns +/// * `i32` - The tick index +#[cfg_attr(feature = "wasm", wasm_bindgen(js_name = priceToTickIndex, skip_jsdoc))] +pub fn price_to_tick_index(price: f64, decimals_a: u8, decimals_b: u8) -> i32 { + let sqrt_price = price_to_sqrt_price(price, decimals_a, decimals_b); + sqrt_price_to_tick_index(sqrt_price) +} + +#[cfg(test)] +mod tests { + use super::*; + use approx::relative_eq; + + #[test] + fn test_price_to_sqrt_price() { + assert_eq!(price_to_sqrt_price(100.0, 8, 6), 1844674407370955161600); + assert_eq!(price_to_sqrt_price(100.0, 6, 6), 184467440737095516160); + assert_eq!(price_to_sqrt_price(100.0, 6, 8), 18446744073709551616); + } + + #[test] + fn test_sqrt_price_to_price() { + assert_eq!( + sqrt_price_to_price(1844674407370955161600u128.into(), 8, 6), + 100.0 + ); + assert_eq!( + sqrt_price_to_price(184467440737095516160u128.into(), 6, 6), + 100.0 + ); + assert_eq!( + sqrt_price_to_price(18446744073709551616u128.into(), 6, 8), + 100.0 + ); + } + + #[test] + fn test_invert_price() { + assert_eq!(invert_price(100.0, 8, 6), 0.01); + assert_eq!(invert_price(100.0, 6, 6), 0.0); + assert_eq!(invert_price(100.0, 6, 8), -1000.0); + } + + #[test] + fn test_tick_index_to_price() { + relative_eq!(tick_index_to_price(-1, 8, 6), 0.00999999); + relative_eq!(tick_index_to_price(0, 6, 6), 1.0); + relative_eq!(tick_index_to_price(1, 6, 8), 100.011); + } + + #[test] + fn test_price_to_tick_index() { + assert_eq!(price_to_tick_index(0.00999999, 8, 6), -1); + assert_eq!(price_to_tick_index(1.0, 6, 6), 0); + assert_eq!(price_to_tick_index(100.011, 6, 8), 1); + } +} diff --git a/rust-sdk/utils/src/math/tick.rs b/rust-sdk/utils/src/math/tick.rs new file mode 100644 index 000000000..48b492b95 --- /dev/null +++ b/rust-sdk/utils/src/math/tick.rs @@ -0,0 +1,476 @@ +use ethnum::U256; + +#[cfg(feature = "wasm")] +use wasm_bindgen::prelude::*; + +use crate::{ + TickRange, FULL_RANGE_ONLY_TICK_SPACING_THRESHOLD, MAX_TICK_INDEX, MIN_TICK_INDEX, + TICK_ARRAY_SIZE, U128, +}; + +const LOG_B_2_X32: i128 = 59543866431248i128; +const BIT_PRECISION: u32 = 14; +const LOG_B_P_ERR_MARGIN_LOWER_X64: i128 = 184467440737095516i128; // 0.01 +const LOG_B_P_ERR_MARGIN_UPPER_X64: i128 = 15793534762490258745i128; // 2^-precision / log_2_b + 0.01 + +/// Get the first tick index in the tick array that contains the specified tick index. +/// +/// # Parameters +/// - `tick_index` - A i32 integer representing the tick integer +/// - `tick_spacing` - A i32 integer representing the tick spacing +/// +/// # Returns +/// - A i32 integer representing the first tick index in the tick array +#[cfg_attr(feature = "wasm", wasm_bindgen(js_name = getTickArrayStartTickIndex, skip_jsdoc))] +pub fn get_tick_array_start_tick_index(tick_index: i32, tick_spacing: u16) -> i32 { + let tick_spacing_i32 = tick_spacing as i32; + let tick_array_size_i32 = TICK_ARRAY_SIZE as i32; + let real_index = tick_index / tick_spacing_i32 / tick_array_size_i32; + real_index * tick_spacing_i32 * tick_array_size_i32 +} + +/// Derive the sqrt-price from a tick index. The precision of this method is only guarranted +/// if tick is within the bounds of {max, min} tick-index. +/// +/// # Parameters +/// - `tick_index` - A i32 integer representing the tick integer +/// +/// # Returns +/// - `Ok`: A u128 Q32.64 representing the sqrt_price +#[cfg_attr(feature = "wasm", wasm_bindgen(js_name = tickIndexToSqrtPrice, skip_jsdoc))] +pub fn tick_index_to_sqrt_price(tick_index: i32) -> U128 { + if tick_index >= 0 { + get_sqrt_price_positive_tick(tick_index).into() + } else { + get_sqrt_price_negative_tick(tick_index).into() + } +} + +/// Derive the tick index from a sqrt price. The precision of this method is only guarranted +/// if tick is within the bounds of {max, min} tick-index. +/// +/// # Parameters +/// - `sqrt_price` - A u128 integer representing the sqrt price +/// +/// # Returns +/// - `Ok`: A i32 integer representing the tick integer +#[cfg_attr(feature = "wasm", wasm_bindgen(js_name = sqrtPriceToTickIndex, skip_jsdoc))] +pub fn sqrt_price_to_tick_index(sqrt_price: U128) -> i32 { + let sqrt_price_x64: u128 = sqrt_price.into(); + // Determine log_b(sqrt_ratio). First by calculating integer portion (msb) + let msb: u32 = 128 - sqrt_price_x64.leading_zeros() - 1; + let log2p_integer_x32 = (msb as i128 - 64) << 32; + + // get fractional value (r/2^msb), msb always > 128 + // We begin the iteration from bit 63 (0.5 in Q64.64) + let mut bit: i128 = 0x8000_0000_0000_0000i128; + let mut precision = 0; + let mut log2p_fraction_x64 = 0; + + // Log2 iterative approximation for the fractional part + // Go through each 2^(j) bit where j < 64 in a Q64.64 number + // Append current bit value to fraction result if r^2 Q2.126 is more than 2 + let mut r = if msb >= 64 { + sqrt_price_x64 >> (msb - 63) + } else { + sqrt_price_x64 << (63 - msb) + }; + + while bit > 0 && precision < BIT_PRECISION { + r *= r; + let is_r_more_than_two = r >> 127_u32; + r >>= 63 + is_r_more_than_two; + log2p_fraction_x64 += bit * is_r_more_than_two as i128; + bit >>= 1; + precision += 1; + } + + let log2p_fraction_x32 = log2p_fraction_x64 >> 32; + let log2p_x32 = log2p_integer_x32 + log2p_fraction_x32; + + // Transform from base 2 to base b + let logbp_x64 = log2p_x32 * LOG_B_2_X32; + + // Derive tick_low & high estimate. Adjust with the possibility of under-estimating by 2^precision_bits/log_2(b) + 0.01 error margin. + let tick_low: i32 = ((logbp_x64 - LOG_B_P_ERR_MARGIN_LOWER_X64) >> 64) + .try_into() + .unwrap(); + let tick_high: i32 = ((logbp_x64 + LOG_B_P_ERR_MARGIN_UPPER_X64) >> 64) + .try_into() + .unwrap(); + + if tick_low == tick_high { + tick_low + } else { + // If our estimation for tick_high returns a lower sqrt_price than the input + // then the actual tick_high has to be higher than than tick_high. + // Otherwise, the actual value is between tick_low & tick_high, so a floor value + // (tick_low) is returned + let actual_tick_high_sqrt_price_x64: u128 = tick_index_to_sqrt_price(tick_high).into(); + if actual_tick_high_sqrt_price_x64 <= sqrt_price_x64 { + tick_high + } else { + tick_low + } + } +} + +/// Get the previous initializable tick index. +/// +/// # Parameters +/// - `tick_index` - A i32 integer representing the tick integer +/// - `tick_spacing` - A i32 integer representing the tick spacing +/// +/// # Returns +/// - A i32 integer representing the previous initializable tick index +#[cfg_attr(feature = "wasm", wasm_bindgen(js_name = getPrevInitializableTickIndex, skip_jsdoc))] +pub fn get_prev_initializable_tick_index(tick_index: i32, tick_spacing: u16) -> i32 { + let tick_spacing_i32 = tick_spacing as i32; + tick_index - (tick_index % tick_spacing_i32) +} + +/// Get the next initializable tick index. +/// +/// # Parameters +/// - `tick_index` - A i32 integer representing the tick integer +/// - `tick_spacing` - A i32 integer representing the tick spacing +/// +/// # Returns +/// - A i32 integer representing the next initializable tick index +#[cfg_attr(feature = "wasm", wasm_bindgen(js_name = getNextInitializableTickIndex, skip_jsdoc))] +pub fn get_next_initializable_tick_index(tick_index: i32, tick_spacing: u16) -> i32 { + let tick_spacing_i32 = tick_spacing as i32; + get_prev_initializable_tick_index(tick_index, tick_spacing) + tick_spacing_i32 +} + +/// Check if a tick is in-bounds. +/// +/// # Parameters +/// - `tick_index` - A i32 integer representing the tick integer +/// +/// # Returns +/// - A boolean value indicating if the tick is in-bounds +#[cfg_attr(feature = "wasm", wasm_bindgen(js_name = isTickIndexInBounds, skip_jsdoc))] +#[allow(clippy::manual_range_contains)] +pub fn is_tick_index_in_bounds(tick_index: i32) -> bool { + tick_index <= MAX_TICK_INDEX && tick_index >= MIN_TICK_INDEX +} + +/// Check if a tick is initializable. +/// A tick is initializable if it is divisible by the tick spacing. +/// +/// # Parameters +/// - `tick_index` - A i32 integer representing the tick integer +/// - `tick_spacing` - A i32 integer representing the tick spacing +/// +/// # Returns +/// - A boolean value indicating if the tick is initializable +#[cfg_attr(feature = "wasm", wasm_bindgen(js_name = isTickInitializable, skip_jsdoc))] +pub fn is_tick_initializable(tick_index: i32, tick_spacing: u16) -> bool { + let tick_spacing_i32 = tick_spacing as i32; + tick_index % tick_spacing_i32 == 0 +} + +/// Get the tick index for the inverse of the price that this tick represents. +/// Eg: Consider tick i where Pb/Pa = 1.0001 ^ i +/// inverse of this, i.e. Pa/Pb = 1 / (1.0001 ^ i) = 1.0001^-i +/// +/// # Parameters +/// - `tick_index` - A i32 integer representing the tick integer +/// +/// # Returns +/// - A i32 integer representing the tick index for the inverse of the price +#[cfg_attr(feature = "wasm", wasm_bindgen(js_name = invertTickIndex, skip_jsdoc))] +pub fn invert_tick_index(tick_index: i32) -> i32 { + -tick_index +} + +/// Get the sqrt price for the inverse of the price that this tick represents. +/// +/// # Parameters +/// - `sqrt_price` - A u128 integer representing the sqrt price +/// +/// # Returns +/// - A u128 integer representing the sqrt price for the inverse of the price +#[cfg_attr(feature = "wasm", wasm_bindgen(js_name = invertSqrtPrice, skip_jsdoc))] +pub fn invert_sqrt_price(sqrt_price: U128) -> U128 { + let tick_index = sqrt_price_to_tick_index(sqrt_price); + let inverted_tick_index = invert_tick_index(tick_index); + tick_index_to_sqrt_price(inverted_tick_index) +} + +/// Get the minimum and maximum tick index that can be initialized. +/// +/// # Parameters +/// - `tick_spacing` - A i32 integer representing the tick spacing +/// +/// # Returns +/// - A TickRange struct containing the lower and upper tick index +#[cfg_attr(feature = "wasm", wasm_bindgen(js_name = getFullRangeTickIndexes, skip_jsdoc))] +pub fn get_full_range_tick_indexes(tick_spacing: u16) -> TickRange { + let tick_spacing_i32 = tick_spacing as i32; + let min_tick_index = (MIN_TICK_INDEX / tick_spacing_i32) * tick_spacing_i32; + let max_tick_index = (MAX_TICK_INDEX / tick_spacing_i32) * tick_spacing_i32; + TickRange { + lower: min_tick_index, + upper: max_tick_index, + } +} + +/// Check if a whirlpool is a full-range only pool. +/// +/// # Parameters +/// - `tick_spacing` - A u16 integer representing the tick spacing +/// +/// # Returns +/// - A boolean value indicating if the whirlpool is a full-range only pool +#[cfg_attr(feature = "wasm", wasm_bindgen(js_name = isFullRangeOnly, skip_jsdoc))] +pub fn is_full_range_only(tick_spacing: u16) -> bool { + tick_spacing >= FULL_RANGE_ONLY_TICK_SPACING_THRESHOLD +} + +/// Check if a position is in range. +/// When a position is in range it is earning fees and rewards +/// +/// # Parameters +/// - `tick_current_index` - A i32 integer representing the tick index of the pool +/// - `tick_lower_index` - A i32 integer representing the lower tick index of the position +/// - `tick_upper_index` - A i32 integer representing the upper tick index of the position +/// +/// # Returns +/// - A boolean value indicating if the position is in range +#[cfg_attr(feature = "wasm", wasm_bindgen(js_name = isPositionInRange, skip_jsdoc))] +pub fn is_position_in_range( + tick_current_index: i32, + tick_lower_index: i32, + tick_upper_index: i32, +) -> bool { + tick_current_index >= tick_lower_index && tick_current_index < tick_upper_index +} + +// Private functions + +fn mul_shift_96(n0: u128, n1: u128) -> u128 { + let mul = ::from(n0) * ::from(n1); + mul.wrapping_shl(96).try_into().unwrap() +} + +fn get_sqrt_price_positive_tick(tick: i32) -> u128 { + let mut ratio: u128 = if tick & 1 != 0 { + 79232123823359799118286999567 + } else { + 79228162514264337593543950336 + }; + + if tick & 2 != 0 { + ratio = mul_shift_96(ratio, 79236085330515764027303304731); + } + if tick & 4 != 0 { + ratio = mul_shift_96(ratio, 79244008939048815603706035061); + } + if tick & 8 != 0 { + ratio = mul_shift_96(ratio, 79259858533276714757314932305); + } + if tick & 16 != 0 { + ratio = mul_shift_96(ratio, 79291567232598584799939703904); + } + if tick & 32 != 0 { + ratio = mul_shift_96(ratio, 79355022692464371645785046466); + } + if tick & 64 != 0 { + ratio = mul_shift_96(ratio, 79482085999252804386437311141); + } + if tick & 128 != 0 { + ratio = mul_shift_96(ratio, 79736823300114093921829183326); + } + if tick & 256 != 0 { + ratio = mul_shift_96(ratio, 80248749790819932309965073892); + } + if tick & 512 != 0 { + ratio = mul_shift_96(ratio, 81282483887344747381513967011); + } + if tick & 1024 != 0 { + ratio = mul_shift_96(ratio, 83390072131320151908154831281); + } + if tick & 2048 != 0 { + ratio = mul_shift_96(ratio, 87770609709833776024991924138); + } + if tick & 4096 != 0 { + ratio = mul_shift_96(ratio, 97234110755111693312479820773); + } + if tick & 8192 != 0 { + ratio = mul_shift_96(ratio, 119332217159966728226237229890); + } + if tick & 16384 != 0 { + ratio = mul_shift_96(ratio, 179736315981702064433883588727); + } + if tick & 32768 != 0 { + ratio = mul_shift_96(ratio, 407748233172238350107850275304); + } + if tick & 65536 != 0 { + ratio = mul_shift_96(ratio, 2098478828474011932436660412517); + } + if tick & 131072 != 0 { + ratio = mul_shift_96(ratio, 55581415166113811149459800483533); + } + if tick & 262144 != 0 { + ratio = mul_shift_96(ratio, 38992368544603139932233054999993551); + } + + ratio >> 32 +} + +fn get_sqrt_price_negative_tick(tick: i32) -> u128 { + let abs_tick = tick.abs(); + + let mut ratio: u128 = if abs_tick & 1 != 0 { + 18445821805675392311 + } else { + 18446744073709551616 + }; + + if abs_tick & 2 != 0 { + ratio = (ratio * 18444899583751176498) >> 64 + } + if abs_tick & 4 != 0 { + ratio = (ratio * 18443055278223354162) >> 64 + } + if abs_tick & 8 != 0 { + ratio = (ratio * 18439367220385604838) >> 64 + } + if abs_tick & 16 != 0 { + ratio = (ratio * 18431993317065449817) >> 64 + } + if abs_tick & 32 != 0 { + ratio = (ratio * 18417254355718160513) >> 64 + } + if abs_tick & 64 != 0 { + ratio = (ratio * 18387811781193591352) >> 64 + } + if abs_tick & 128 != 0 { + ratio = (ratio * 18329067761203520168) >> 64 + } + if abs_tick & 256 != 0 { + ratio = (ratio * 18212142134806087854) >> 64 + } + if abs_tick & 512 != 0 { + ratio = (ratio * 17980523815641551639) >> 64 + } + if abs_tick & 1024 != 0 { + ratio = (ratio * 17526086738831147013) >> 64 + } + if abs_tick & 2048 != 0 { + ratio = (ratio * 16651378430235024244) >> 64 + } + if abs_tick & 4096 != 0 { + ratio = (ratio * 15030750278693429944) >> 64 + } + if abs_tick & 8192 != 0 { + ratio = (ratio * 12247334978882834399) >> 64 + } + if abs_tick & 16384 != 0 { + ratio = (ratio * 8131365268884726200) >> 64 + } + if abs_tick & 32768 != 0 { + ratio = (ratio * 3584323654723342297) >> 64 + } + if abs_tick & 65536 != 0 { + ratio = (ratio * 696457651847595233) >> 64 + } + if abs_tick & 131072 != 0 { + ratio = (ratio * 26294789957452057) >> 64 + } + if abs_tick & 262144 != 0 { + ratio = (ratio * 37481735321082) >> 64 + } + + ratio +} + +// Tests + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_get_tick_array_start_tick_index() { + assert_eq!(get_tick_array_start_tick_index(100, 10), 0); + assert_eq!(get_tick_array_start_tick_index(1000, 10), 880); + assert_eq!(get_tick_array_start_tick_index(0, 10), 0); + } + + #[test] + fn test_tick_index_to_sqrt_price() { + // Assuming get_sqrt_price_positive_tick and get_sqrt_price_negative_tick are correct + assert_eq!(tick_index_to_sqrt_price(1), 18447666387855959850); + assert_eq!(tick_index_to_sqrt_price(-1), 18445821805675392311); + } + + #[test] + fn test_sqrt_price_to_tick_index() { + assert_eq!(sqrt_price_to_tick_index(18447666387855959850u128.into()), 1); + assert_eq!( + sqrt_price_to_tick_index(18445821805675392311u128.into()), + -1 + ); + } + + #[test] + fn test_get_prev_initializable_tick_index() { + assert_eq!(get_prev_initializable_tick_index(100, 10), 100); + assert_eq!(get_prev_initializable_tick_index(105, 10), 100); + assert_eq!(get_prev_initializable_tick_index(0, 10), 0); + } + + #[test] + fn test_get_next_initializable_tick_index() { + assert_eq!(get_next_initializable_tick_index(100, 10), 110); + assert_eq!(get_next_initializable_tick_index(105, 10), 110); + assert_eq!(get_next_initializable_tick_index(0, 10), 10); + } + + #[test] + fn test_is_tick_index_in_bounds() { + assert!(is_tick_index_in_bounds(MAX_TICK_INDEX)); + assert!(is_tick_index_in_bounds(MIN_TICK_INDEX)); + assert!(!is_tick_index_in_bounds(MAX_TICK_INDEX + 1)); + assert!(!is_tick_index_in_bounds(MIN_TICK_INDEX - 1)); + } + + #[test] + fn test_is_tick_initializable() { + assert!(is_tick_initializable(100, 10)); + assert!(!is_tick_initializable(105, 10)); + } + + #[test] + fn test_invert_tick_index() { + assert_eq!(invert_tick_index(100), -100); + assert_eq!(invert_tick_index(-100), 100); + } + + #[test] + fn test_get_full_range_tick_indexes() { + let range = get_full_range_tick_indexes(10); + assert_eq!(range.lower, (MIN_TICK_INDEX / 10) * 10); + assert_eq!(range.upper, (MAX_TICK_INDEX / 10) * 10); + } + + #[test] + fn test_is_full_range_only() { + assert!(is_full_range_only(FULL_RANGE_ONLY_TICK_SPACING_THRESHOLD)); + assert!(!is_full_range_only( + FULL_RANGE_ONLY_TICK_SPACING_THRESHOLD - 1 + )); + } + + #[test] + fn test_is_position_in_range() { + assert!(!is_position_in_range(85, 90, 100)); + assert!(is_position_in_range(90, 90, 100)); + assert!(is_position_in_range(95, 90, 100)); + assert!(!is_position_in_range(100, 90, 100)); + assert!(!is_position_in_range(105, 90, 100)); + } +} diff --git a/rust-sdk/utils/src/quote/fees.rs b/rust-sdk/utils/src/quote/fees.rs new file mode 100644 index 000000000..0de25facc --- /dev/null +++ b/rust-sdk/utils/src/quote/fees.rs @@ -0,0 +1,187 @@ +use core::ops::Shl; + +#[cfg(feature = "wasm")] +use wasm_bindgen::prelude::*; + +use crate::{CollectFeesQuote, U128}; + +/// Calculate fees owed for a position +/// +/// # Paramters +/// - `fee_growth_outside_a_lower`: The fee growth outside the lower tick +/// - `fee_growth_outside_b_lower`: The fee growth outside the lower tick +/// - `fee_growth_outside_a_upper`: The fee growth outside the upper tick +/// - `fee_growth_outside_b_upper`: The fee growth outside the upper tick +/// - `fee_growth_global_a`: The global fee growth for token A +/// - `fee_growth_global_b`: The global fee growth for token B +/// - `fee_growth_checkpoint_a`: The fee growth checkpoint for token A +/// - `fee_growth_checkpoint_b`: The fee growth checkpoint for token B +/// - `position_liquidity`: The liquidity of the position +/// - `position_fee_owed_a`: The fee owed for token A +/// - `position_fee_owed_b`: The fee owed for token B +/// - `tick_current_index`: The current tick index +/// - `tick_lower_index`: The lower tick index of the position +/// - `tick_upper_index`: The upper tick index of the position +/// +/// # Returns +/// - `CollectFeesQuote`: The fees owed for token A and token B +#[allow(clippy::too_many_arguments)] +#[cfg_attr(feature = "wasm", wasm_bindgen(js_name = collectFeesQuote, skip_jsdoc))] +pub fn collect_fees_quote( + fee_growth_outside_a_lower: U128, + fee_growth_outside_b_lower: U128, + fee_growth_outside_a_upper: U128, + fee_growth_outside_b_upper: U128, + fee_growth_global_a: U128, + fee_growth_global_b: U128, + fee_growth_checkpoint_a: U128, + fee_growth_checkpoint_b: U128, + position_liquidity: U128, + position_fee_owed_a: U128, + position_fee_owed_b: U128, + tick_current_index: i32, + tick_lower_index: i32, + tick_upper_index: i32, +) -> CollectFeesQuote { + let mut fee_growth_below_a_x_64: u128 = fee_growth_outside_a_lower.into(); + let mut fee_growth_above_a_x_64: u128 = fee_growth_outside_a_upper.into(); + let mut fee_growth_below_b_x_64: u128 = fee_growth_outside_b_lower.into(); + let mut fee_growth_above_b_x_64: u128 = fee_growth_outside_b_upper.into(); + + let fee_growth_global_a_x_64: u128 = fee_growth_global_a.into(); + let fee_growth_global_b_x_64: u128 = fee_growth_global_b.into(); + + let fee_growth_checkpoint_a_x_64: u128 = fee_growth_checkpoint_a.into(); + let fee_growth_checkpoint_b_x_64: u128 = fee_growth_checkpoint_b.into(); + + let position_liquidity_u128: u128 = position_liquidity.into(); + let position_fee_owed_a_u128: u128 = position_fee_owed_a.into(); + let position_fee_owed_b_u128: u128 = position_fee_owed_b.into(); + + if tick_current_index < tick_lower_index { + fee_growth_below_a_x_64 = fee_growth_global_a_x_64.wrapping_sub(fee_growth_below_a_x_64); + fee_growth_below_b_x_64 = fee_growth_global_b_x_64.wrapping_sub(fee_growth_below_b_x_64); + } + + if tick_current_index > tick_upper_index { + fee_growth_above_a_x_64 = fee_growth_global_a_x_64.wrapping_sub(fee_growth_above_a_x_64); + fee_growth_above_b_x_64 = fee_growth_global_b_x_64.wrapping_sub(fee_growth_above_b_x_64); + } + + let fee_growth_inside_a_x_64 = fee_growth_global_a_x_64 + .wrapping_sub(fee_growth_below_a_x_64) + .wrapping_sub(fee_growth_above_a_x_64); + + let fee_growth_inside_b_x_64 = fee_growth_global_b_x_64 + .wrapping_sub(fee_growth_below_b_x_64) + .wrapping_sub(fee_growth_above_b_x_64); + + let fee_owed_delta_a_x_64 = fee_growth_inside_a_x_64 + .wrapping_sub(fee_growth_checkpoint_a_x_64) + .wrapping_mul(position_liquidity_u128); + + let fee_owed_delta_b_x_64 = fee_growth_inside_b_x_64 + .wrapping_sub(fee_growth_checkpoint_b_x_64) + .wrapping_mul(position_liquidity_u128); + + let fee_owed_a: u128 = position_fee_owed_a_u128 + fee_owed_delta_a_x_64.shl(64); + let fee_owed_b: u128 = position_fee_owed_b_u128 + fee_owed_delta_b_x_64.shl(64); + + // TOOD: remove transfer fee deduction + + CollectFeesQuote { + fee_owed_a: fee_owed_a.into(), + fee_owed_b: fee_owed_b.into(), + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_collect_out_of_range_lower() { + let result1 = collect_fees_quote( + 100u128.into(), + 200u128.into(), + 300u128.into(), + 400u128.into(), + 500u128.into(), + 600u128.into(), + 700u128.into(), + 800u128.into(), + 900u128.into(), + 1000u128.into(), + 1100u128.into(), + 5, + 3, + 7, + ); + assert_eq!(result1.fee_owed_a, 1000); + assert_eq!(result1.fee_owed_b, 1100); + } + + #[test] + fn test_in_range() { + let result1 = collect_fees_quote( + 100u128.into(), + 200u128.into(), + 300u128.into(), + 400u128.into(), + 500u128.into(), + 600u128.into(), + 700u128.into(), + 800u128.into(), + 900u128.into(), + 1000u128.into(), + 1100u128.into(), + 5, + 5, + 7, + ); + assert_eq!(result1.fee_owed_a, 1000); + assert_eq!(result1.fee_owed_b, 1100); + } + + #[test] + fn test_collect_out_of_range_upper() { + let result2 = collect_fees_quote( + 200u128.into(), + 400u128.into(), + 600u128.into(), + 800u128.into(), + 1000u128.into(), + 1200u128.into(), + 1400u128.into(), + 1600u128.into(), + 1800u128.into(), + 2000u128.into(), + 2200u128.into(), + 9, + 7, + 5, + ); + assert_eq!(result2.fee_owed_a, 2000); + assert_eq!(result2.fee_owed_b, 2200); + + // Test case 3: tick_current_index == tick_lower_index + let result3 = collect_fees_quote( + 300u128.into(), + 600u128.into(), + 900u128.into(), + 1200u128.into(), + 1500u128.into(), + 1800u128.into(), + 2100u128.into(), + 2400u128.into(), + 2700u128.into(), + 3000u128.into(), + 3300u128.into(), + 5, + 5, + 7, + ); + assert_eq!(result3.fee_owed_a, 2700); + assert_eq!(result3.fee_owed_b, 3000); + } +} diff --git a/rust-sdk/utils/src/quote/liquidity.rs b/rust-sdk/utils/src/quote/liquidity.rs new file mode 100644 index 000000000..3499c9b20 --- /dev/null +++ b/rust-sdk/utils/src/quote/liquidity.rs @@ -0,0 +1,12 @@ + +// TODO: + +// Increase liq +// - by liquidity amount +// - by token a +// - by token b + +// decrease liq +// - by liquidity amount +// - by token a +// - by token b diff --git a/rust-sdk/utils/src/quote/mod.rs b/rust-sdk/utils/src/quote/mod.rs new file mode 100644 index 000000000..825594d31 --- /dev/null +++ b/rust-sdk/utils/src/quote/mod.rs @@ -0,0 +1,9 @@ +mod fees; +mod liquidity; +mod rewards; +mod swap; + +pub use fees::*; +pub use liquidity::*; +pub use rewards::*; +pub use swap::*; diff --git a/rust-sdk/utils/src/quote/rewards.rs b/rust-sdk/utils/src/quote/rewards.rs new file mode 100644 index 000000000..48a1c26b4 --- /dev/null +++ b/rust-sdk/utils/src/quote/rewards.rs @@ -0,0 +1,245 @@ +use core::ops::Shl; + +#[cfg(feature = "wasm")] +use wasm_bindgen::prelude::*; + +use crate::{CollectRewardsQuote, U128}; + +/// Calculate rewards owed for a position +/// +/// # Paramters +/// - `tick_current_index`: The current tick index +/// - `tick_lower_index`: The lower tick index of the position +/// - `tick_upper_index`: The upper tick index of the position +/// - `pool_liquidity`: The liquidity of the pool +/// - `position_liquidity`: The liquidity of the position +/// - `growth_global_1`: The global growth for reward token 1 +/// - `growth_global_2`: The global growth for reward token 2 +/// - `growth_global_3`: The global growth for reward token 3 +/// - `reward_growth_outside_1_lower`: The reward growth outside the lower tick for reward token 1 +/// - `reward_growth_outside_2_lower`: The reward growth outside the lower tick for reward token 2 +/// - `reward_growth_outside_3_lower`: The reward growth outside the lower tick for reward token 3 +/// - `reward_growth_outside_1_upper`: The reward growth outside the upper tick for reward token 1 +/// - `reward_growth_outside_2_upper`: The reward growth outside the upper tick for reward token 2 +/// - `reward_growth_outside_3_upper`: The reward growth outside the upper tick for reward token 3 +/// - `reward_emissions_per_second_1`: The reward emissions per second for reward token 1 +/// - `reward_emissions_per_second_2`: The reward emissions per second for reward token 2 +/// - `reward_emissions_per_second_3`: The reward emissions per second for reward token 3 +/// - `growth_inside_checkpoint_1`: The growth inside the checkpoint for reward token 1 +/// - `growth_inside_checkpoint_2`: The growth inside the checkpoint for reward token 2 +/// - `growth_inside_checkpoint_3`: The growth inside the checkpoint for reward token 3 +/// - `amount_owed_1`: The amount owed for reward token 1 +/// - `amount_owed_2`: The amount owed for reward token 2 +/// - `amount_owed_3`: The amount owed for reward token 3 +/// - `reward_last_updated_timestamp`: The timestamp when the rewards were last updated +/// +/// # Returns +/// - `CollectRewardsQuote`: The rewards owed for the 3 reward tokens. +#[allow(clippy::too_many_arguments)] +#[cfg_attr(feature = "wasm", wasm_bindgen(js_name = collectRewardsQuote, skip_jsdoc))] +pub fn collect_rewards_quote( + tick_current_index: i32, + tick_lower_index: i32, + tick_upper_index: i32, + pool_liquidity: U128, + position_liquidity: U128, + growth_global_1: U128, + growth_global_2: U128, + growth_global_3: U128, + reward_growth_outside_1_lower: U128, + reward_growth_outside_2_lower: U128, + reward_growth_outside_3_lower: U128, + reward_growth_outside_1_upper: U128, + reward_growth_outside_2_upper: U128, + reward_growth_outside_3_upper: U128, + reward_emissions_per_second_1: U128, + reward_emissions_per_second_2: U128, + reward_emissions_per_second_3: U128, + growth_inside_checkpoint_1: U128, + growth_inside_checkpoint_2: U128, + growth_inside_checkpoint_3: U128, + amount_owed_1: U128, + amount_owed_2: U128, + amount_owed_3: U128, + reward_last_updated_timestamp: i32, +) -> CollectRewardsQuote { + let current_timestamp = 0; // TODO: get current timestamp + let timestamp_delta = (current_timestamp - reward_last_updated_timestamp).unsigned_abs(); + + let reward_emissions_per_second_1: u128 = reward_emissions_per_second_1.into(); + let reward_emissions_per_second_2: u128 = reward_emissions_per_second_2.into(); + let reward_emissions_per_second_3: u128 = reward_emissions_per_second_3.into(); + + let position_liquidity: u128 = position_liquidity.into(); + let pool_liquidity: u128 = pool_liquidity.into(); + + let mut reward_growth_1: u128 = growth_global_1.into(); + let mut reward_growth_2: u128 = growth_global_2.into(); + let mut reward_growth_3: u128 = growth_global_3.into(); + + if pool_liquidity != 0 { + let reward_growth_delta_1 = reward_emissions_per_second_1 + .wrapping_mul(timestamp_delta as u128) + .wrapping_div(pool_liquidity); + reward_growth_1 += ::try_from(reward_growth_delta_1).unwrap(); + + let reward_growth_delta_2 = reward_emissions_per_second_2 + .wrapping_mul(timestamp_delta as u128) + .wrapping_div(pool_liquidity); + reward_growth_2 += ::try_from(reward_growth_delta_2).unwrap(); + + let reward_growth_delta_3 = reward_emissions_per_second_3 + .wrapping_mul(timestamp_delta as u128) + .wrapping_div(pool_liquidity); + reward_growth_3 += ::try_from(reward_growth_delta_3).unwrap(); + } + + let mut reward_growth_below_1: u128 = reward_growth_outside_1_lower.into(); + let mut reward_growth_below_2: u128 = reward_growth_outside_2_lower.into(); + let mut reward_growth_below_3: u128 = reward_growth_outside_3_lower.into(); + + let mut reward_growth_above_1: u128 = reward_growth_outside_1_upper.into(); + let mut reward_growth_above_2: u128 = reward_growth_outside_2_upper.into(); + let mut reward_growth_above_3: u128 = reward_growth_outside_3_upper.into(); + + if tick_current_index < tick_lower_index { + reward_growth_below_1 = reward_growth_1.wrapping_sub(reward_growth_below_1); + + reward_growth_below_2 = reward_growth_2.wrapping_sub(reward_growth_below_2); + + reward_growth_below_3 = reward_growth_3.wrapping_sub(reward_growth_below_3); + } + + if tick_current_index > tick_upper_index { + reward_growth_above_1 = reward_growth_1.wrapping_sub(reward_growth_above_1); + + reward_growth_above_2 = reward_growth_2.wrapping_sub(reward_growth_above_2); + + reward_growth_above_3 = reward_growth_3.wrapping_sub(reward_growth_above_3); + } + + let reward_growth_inside_1 = reward_growth_1 + .wrapping_sub(reward_growth_below_1) + .wrapping_sub(reward_growth_above_1); + + let reward_growth_inside_2 = reward_growth_2 + .wrapping_sub(reward_growth_below_2) + .wrapping_sub(reward_growth_above_2); + + let reward_growth_inside_3 = reward_growth_3 + .wrapping_sub(reward_growth_below_3) + .wrapping_sub(reward_growth_above_3); + + let reward_growth_inside_checkpoint_1: u128 = growth_inside_checkpoint_1.into(); + let reward_growth_inside_checkpoint_2: u128 = growth_inside_checkpoint_2.into(); + let reward_growth_inside_checkpoint_3: u128 = growth_inside_checkpoint_3.into(); + + let reward_growth_delta_1 = reward_growth_inside_1 + .wrapping_sub(reward_growth_inside_checkpoint_1) + .wrapping_mul(position_liquidity); + + let reward_growth_delta_2 = reward_growth_inside_2 + .wrapping_sub(reward_growth_inside_checkpoint_2) + .wrapping_mul(position_liquidity); + + let reward_growth_delta_3 = reward_growth_inside_3 + .wrapping_sub(reward_growth_inside_checkpoint_3) + .wrapping_mul(position_liquidity); + + let amount_owed_1: u128 = amount_owed_1.into(); + let amount_owed_2: u128 = amount_owed_2.into(); + let amount_owed_3: u128 = amount_owed_3.into(); + + let reward_owed_1 = amount_owed_1.shl(64) + reward_growth_delta_1.shl(64); + let reward_owed_2 = amount_owed_2.shl(64) + reward_growth_delta_2.shl(64); + let reward_owed_3 = amount_owed_3.shl(64) + reward_growth_delta_3.shl(64); + + // TOOD: remove transfer fee deduction + + CollectRewardsQuote { + reward_owed_1, + reward_owed_2, + reward_owed_3, + } +} +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_collect_rewards_quote() { + let quote1 = collect_rewards_quote( + 0, + -100, + 100, + 100000u128.into(), + 50000u128.into(), + 1000000u128.into(), + 2000000u128.into(), + 3000000u128.into(), + 500000u128.into(), + 1000000u128.into(), + 1500000u128.into(), + 2000000u128.into(), + 2500000u128.into(), + 3000000u128.into(), + 100u128.into(), + 200u128.into(), + 300u128.into(), + 500000u128.into(), + 1000000u128.into(), + 1500000u128.into(), + 100u128.into(), + 200u128.into(), + 300u128.into(), + 0, + ); + + assert_eq!( + quote1.reward_owed_1, + 340282365076264057937093853202723373056 + ); + assert_eq!( + quote1.reward_owed_2, + 340282364615095457939029470173678534656 + ); + assert_eq!( + quote1.reward_owed_3, + 340282364153926857940965087144633696256 + ); + } + + #[test] + fn test_collect_rewards_quote_2() { + let quote2 = collect_rewards_quote( + 0, + -100, + 100, + 100000u128.into(), + 50000u128.into(), + 1000000u128.into(), + 2000000u128.into(), + 3000000u128.into(), + 500000u128.into(), + 1000000u128.into(), + 1500000u128.into(), + 2000000u128.into(), + 2500000u128.into(), + 3000000u128.into(), + 100u128.into(), + 200u128.into(), + 300u128.into(), + 500000u128.into(), + 1000000u128.into(), + 1500000u128.into(), + 100u128.into(), + 200u128.into(), + 300u128.into(), + 100, + ); + + assert_eq!(quote2.reward_owed_1, 50000); + assert_eq!(quote2.reward_owed_2, 100000); + assert_eq!(quote2.reward_owed_3, 150000); + } +} diff --git a/rust-sdk/utils/src/quote/swap.rs b/rust-sdk/utils/src/quote/swap.rs new file mode 100644 index 000000000..5b287949d --- /dev/null +++ b/rust-sdk/utils/src/quote/swap.rs @@ -0,0 +1,5 @@ + + +// one hop swap + +// two hop swap diff --git a/rust-sdk/utils/src/types/fees.rs b/rust-sdk/utils/src/types/fees.rs new file mode 100644 index 000000000..ee2c0ad86 --- /dev/null +++ b/rust-sdk/utils/src/types/fees.rs @@ -0,0 +1,17 @@ +#![allow(non_snake_case)] + +#[cfg(feature = "wasm")] +use serde::{Deserialize, Serialize}; + +#[cfg(feature = "wasm")] +use tsify::Tsify; + +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "wasm", derive(Serialize, Deserialize, Tsify))] +#[cfg_attr(feature = "wasm", serde(rename_all = "camelCase"))] +#[cfg_attr(feature = "wasm", tsify(into_wasm_abi))] + +pub struct CollectFeesQuote { + pub fee_owed_a: u128, + pub fee_owed_b: u128, +} diff --git a/rust-sdk/utils/src/types/mod.rs b/rust-sdk/utils/src/types/mod.rs new file mode 100644 index 000000000..be9cbeb60 --- /dev/null +++ b/rust-sdk/utils/src/types/mod.rs @@ -0,0 +1,9 @@ +mod fees; +mod rewards; +mod tick; +mod u128; + +pub use fees::*; +pub use rewards::*; +pub use tick::*; +pub use u128::*; diff --git a/rust-sdk/utils/src/types/rewards.rs b/rust-sdk/utils/src/types/rewards.rs new file mode 100644 index 000000000..bf722d21c --- /dev/null +++ b/rust-sdk/utils/src/types/rewards.rs @@ -0,0 +1,18 @@ +#![allow(non_snake_case)] + +#[cfg(feature = "wasm")] +use serde::{Deserialize, Serialize}; + +#[cfg(feature = "wasm")] +use tsify::Tsify; + +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "wasm", derive(Serialize, Deserialize, Tsify))] +#[cfg_attr(feature = "wasm", serde(rename_all = "camelCase"))] +#[cfg_attr(feature = "wasm", tsify(into_wasm_abi))] + +pub struct CollectRewardsQuote { + pub reward_owed_1: u128, + pub reward_owed_2: u128, + pub reward_owed_3: u128, +} diff --git a/rust-sdk/utils/src/types/tick.rs b/rust-sdk/utils/src/types/tick.rs new file mode 100644 index 000000000..247365426 --- /dev/null +++ b/rust-sdk/utils/src/types/tick.rs @@ -0,0 +1,16 @@ +#![allow(non_snake_case)] + +#[cfg(feature = "wasm")] +use serde::{Deserialize, Serialize}; + +#[cfg(feature = "wasm")] +use tsify::Tsify; + +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "wasm", derive(Serialize, Deserialize, Tsify))] +#[cfg_attr(feature = "wasm", serde(rename_all = "camelCase"))] +#[cfg_attr(feature = "wasm", tsify(into_wasm_abi))] +pub struct TickRange { + pub lower: i32, + pub upper: i32, +} diff --git a/rust-sdk/utils/src/types/u128.rs b/rust-sdk/utils/src/types/u128.rs new file mode 100644 index 000000000..6a564b44d --- /dev/null +++ b/rust-sdk/utils/src/types/u128.rs @@ -0,0 +1,49 @@ +// While `wasm_bindgen` doesn't automatically convert rust `u128` to js `bigint`, we have +// to proxy it through an opaque type that we define here. This is a workaround until +// `wasm_bindgen` supports `u128` abi conversion natively. + +#![allow(clippy::useless_conversion)] + +#[cfg(not(feature = "wasm"))] +pub type U128 = u128; + +#[cfg(feature = "wasm")] +use core::fmt::{Debug, Formatter, Result}; + +#[cfg(feature = "wasm")] +use wasm_bindgen::prelude::*; + +#[cfg(feature = "wasm")] +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "bigint")] + pub type U128; +} + +#[cfg(feature = "wasm")] +impl Debug for U128 { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + write!(f, "{:?}", JsValue::from(self)) + } +} + +#[cfg(feature = "wasm")] +impl From for u128 { + fn from(value: U128) -> u128 { + JsValue::from(value).try_into().unwrap() + } +} + +#[cfg(feature = "wasm")] +impl From for U128 { + fn from(value: u128) -> U128 { + JsValue::from(value).unchecked_into() + } +} + +#[cfg(feature = "wasm")] +impl PartialEq for U128 { + fn eq(&self, other: &u128) -> bool { + self == &(*other).into() + } +} diff --git a/rust-sdk/whirlpool/Cargo.lock b/rust-sdk/whirlpool/Cargo.lock index 17c4fdf11..8b4864793 100644 --- a/rust-sdk/whirlpool/Cargo.lock +++ b/rust-sdk/whirlpool/Cargo.lock @@ -565,6 +565,12 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +[[package]] +name = "ethnum" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b90ca2580b73ab6a1f724b76ca11ab632df820fd6040c336200d2c1df7b3c82c" + [[package]] name = "feature-probe" version = "0.1.1" @@ -733,6 +739,12 @@ version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +[[package]] +name = "libm" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" + [[package]] name = "libsecp256k1" version = "0.6.0" @@ -889,6 +901,7 @@ name = "orca_whirlpools" version = "0.1.0" dependencies = [ "orca_whirlpools_client", + "orca_whirlpools_utils", ] [[package]] @@ -902,6 +915,14 @@ dependencies = [ "thiserror", ] +[[package]] +name = "orca_whirlpools_utils" +version = "0.1.0" +dependencies = [ + "ethnum", + "libm", +] + [[package]] name = "parking_lot" version = "0.12.3" diff --git a/rust-sdk/whirlpool/Cargo.toml b/rust-sdk/whirlpool/Cargo.toml index 1415a2526..e99d92fc7 100644 --- a/rust-sdk/whirlpool/Cargo.toml +++ b/rust-sdk/whirlpool/Cargo.toml @@ -4,4 +4,5 @@ version = "0.1.0" edition = "2021" [dependencies] +orca_whirlpools_utils = { path = "../utils" } orca_whirlpools_client = { path = "../client" } diff --git a/rust-sdk/whirlpool/package.json b/rust-sdk/whirlpool/package.json index 9a220fa67..e082de90d 100644 --- a/rust-sdk/whirlpool/package.json +++ b/rust-sdk/whirlpool/package.json @@ -4,8 +4,8 @@ "scripts": { "build": "cargo build", "test": "cargo test --lib", - "format": "cargo clippy --fix --allow-dirty --allow-staged -- -D clippy::all && cargo fmt", - "lint": "cargo clippy -- -D clippy::all", + "format": "cargo clippy --fix --allow-dirty --allow-staged && cargo fmt", + "lint": "cargo clippy", "clean": "cargo clean" }, "devDependencies": { diff --git a/rust-sdk/whirlpool/src/lib.rs b/rust-sdk/whirlpool/src/lib.rs index 130f136ab..6de50ee5d 100644 --- a/rust-sdk/whirlpool/src/lib.rs +++ b/rust-sdk/whirlpool/src/lib.rs @@ -1 +1,2 @@ pub use orca_whirlpools_client::*; +pub use orca_whirlpools_utils::*; diff --git a/ts-sdk/utils/Cargo.lock b/ts-sdk/utils/Cargo.lock new file mode 100644 index 000000000..af08fe52f --- /dev/null +++ b/ts-sdk/utils/Cargo.lock @@ -0,0 +1,289 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "ethnum" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b90ca2580b73ab6a1f724b76ca11ab632df820fd6040c336200d2c1df7b3c82c" + +[[package]] +name = "gloo-utils" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037fcb07216cb3a30f7292bd0176b050b7b9a052ba830ef7d5d65f6dc64ba58e" +dependencies = [ + "js-sys", + "serde", + "serde_json", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "js-sys" +version = "0.3.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "libm" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "orca_whirlpools_utils" +version = "0.1.0" +dependencies = [ + "ethnum", + "libm", + "serde", + "serde-wasm-bindgen 0.6.5", + "tsify", + "wasm-bindgen", +] + +[[package]] +name = "orca_whirlpools_utils_js_bindings" +version = "0.1.0" +dependencies = [ + "orca_whirlpools_utils", +] + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "serde" +version = "1.0.207" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5665e14a49a4ea1b91029ba7d3bca9f299e1f7cfa194388ccc20f14743e784f2" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde-wasm-bindgen" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3b143e2833c57ab9ad3ea280d21fd34e285a42837aeb0ee301f4f41890fa00e" +dependencies = [ + "js-sys", + "serde", + "wasm-bindgen", +] + +[[package]] +name = "serde-wasm-bindgen" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8302e169f0eddcc139c70f139d19d6467353af16f9fce27e8c30158036a1e16b" +dependencies = [ + "js-sys", + "serde", + "wasm-bindgen", +] + +[[package]] +name = "serde_derive" +version = "1.0.207" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6aea2634c86b0e8ef2cfdc0c340baede54ec27b1e46febd7f80dffb2aa44a00e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_derive_internals" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e578a843d40b4189a4d66bba51d7684f57da5bd7c304c64e14bd63efbef49509" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.125" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83c8e735a073ccf5be70aa8066aa984eaf2fa000db6c8d0100ae605b366d31ed" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "syn" +version = "2.0.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fceb41e3d546d0bd83421d3409b1460cc7444cd389341a4c880fe7a042cb3d7" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tsify" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6b26cf145f2f3b9ff84e182c448eaf05468e247f148cf3d2a7d67d78ff023a0" +dependencies = [ + "gloo-utils", + "serde", + "serde-wasm-bindgen 0.5.0", + "serde_json", + "tsify-macros", + "wasm-bindgen", +] + +[[package]] +name = "tsify-macros" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a94b0f0954b3e59bfc2c246b4c8574390d94a4ad4ad246aaf2fb07d7dfd3b47" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "wasm-bindgen" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" + +[[package]] +name = "web-sys" +version = "0.3.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" +dependencies = [ + "js-sys", + "wasm-bindgen", +] diff --git a/ts-sdk/utils/Cargo.toml b/ts-sdk/utils/Cargo.toml new file mode 100644 index 000000000..674ecc356 --- /dev/null +++ b/ts-sdk/utils/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "orca_whirlpools_utils_js_bindings" +version = "0.1.0" +edition = "2021" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +orca_whirlpools_utils = { path = "../../rust-sdk/utils", features = ["wasm", "floats"] } + +[profile.release] +opt-level = "s" diff --git a/ts-sdk/utils/package.json b/ts-sdk/utils/package.json new file mode 100644 index 000000000..374681a2c --- /dev/null +++ b/ts-sdk/utils/package.json @@ -0,0 +1,26 @@ +{ + "name": "@orca-so/whirlpools-utils", + "version": "0.0.1", + "main": "./dist/nodejs/orca_whirlpools_utils_js_bindings.js", + "types": "./dist/nodejs/orca_whirlpools_utils_js_bindings.d.ts", + "browser": "./dist/web/orca_whirlpools_utils_js_bindings.js", + "type": "module", + "sideEffects": [ + "./dist/web/snippets/*" + ], + "files": [ + "./dist/*/orca_whirlpools_utils_js_bindings_bg.wasm", + "./dist/*/orca_whirlpools_utils_js_bindings.js", + "./dist/*/orca_whirlpools_utils_js_bindings.d.ts", + "LICENSE" + ], + "scripts": { + "build": "wasm-pack build --out-dir ./dist/web --target web && wasm-pack build --out-dir ./dist/nodejs --target nodejs", + "test": "bash test.sh", + "clean": "rimraf dist" + }, + "devDependencies": { + "@orca-so/whirlpools-rust-utils": "*", + "wasm-pack": "^0.13.0" + } +} diff --git a/ts-sdk/utils/src/lib.rs b/ts-sdk/utils/src/lib.rs new file mode 100644 index 000000000..dc59e83bd --- /dev/null +++ b/ts-sdk/utils/src/lib.rs @@ -0,0 +1 @@ +pub use orca_whirlpools_utils::*; diff --git a/ts-sdk/utils/test.sh b/ts-sdk/utils/test.sh new file mode 100644 index 000000000..7ca860b77 --- /dev/null +++ b/ts-sdk/utils/test.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash +set -e + +NODE_SIZE=$(gzip -c dist/nodejs/orca_whirlpools_utils_js_bindings_bg.wasm | wc -c) +echo "Node wasm binary gzip size: $NODE_SIZE" +WEB_SIZE=$(gzip -c dist/web/orca_whirlpools_utils_js_bindings_bg.wasm | wc -c) +echo "Web wasm binary gzip side: $WEB_SIZE" +SIZE=$(( $NODE_SIZE > $WEB_SIZE ? $NODE_SIZE : $WEB_SIZE )) + +# If the gzipped wasm binary is larger than 25KB, then fail the test +if [ $SIZE -gt 25000 ]; then + echo "Failed because the wasm binary is larger than 25KB" + exit 1 +fi diff --git a/ts-sdk/whirlpool/package.json b/ts-sdk/whirlpool/package.json index 992ad7872..14c58c835 100644 --- a/ts-sdk/whirlpool/package.json +++ b/ts-sdk/whirlpool/package.json @@ -13,7 +13,8 @@ "clean": "rimraf dist" }, "dependencies": { - "@orca-so/whirlpools-client": "*" + "@orca-so/whirlpools-client": "*", + "@orca-so/whirlpools-utils": "*" }, "devDependencies": { "typescript": "^5.5.4" diff --git a/ts-sdk/whirlpool/src/index.ts b/ts-sdk/whirlpool/src/index.ts index 171c874f1..28fcf795a 100644 --- a/ts-sdk/whirlpool/src/index.ts +++ b/ts-sdk/whirlpool/src/index.ts @@ -1 +1,2 @@ +export * from "@orca-so/whirlpools-utils"; export * from "@orca-so/whirlpools-client"; diff --git a/yarn.lock b/yarn.lock index 1992167f9..b97a44aeb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2859,6 +2859,7 @@ __metadata: version: 0.0.0-use.local resolution: "@orca-so/whirlpools-docs-legacy@workspace:docs/legacy" dependencies: + "@orca-so/whirlpools": "npm:*" "@orca-so/whirlpools-sdk": "npm:*" typedoc: "npm:^0.26.5" typescript: "npm:^5.5.4" @@ -2878,6 +2879,7 @@ __metadata: resolution: "@orca-so/whirlpools-docs-ts@workspace:docs/ts" dependencies: "@orca-so/whirlpools": "npm:*" + "@orca-so/whirlpools-sdk": "npm:*" typedoc: "npm:^0.26.5" typescript: "npm:^5.5.4" languageName: unknown @@ -2949,6 +2951,12 @@ __metadata: languageName: unknown linkType: soft +"@orca-so/whirlpools-rust-utils@npm:*, @orca-so/whirlpools-rust-utils@workspace:rust-sdk/utils": + version: 0.0.0-use.local + resolution: "@orca-so/whirlpools-rust-utils@workspace:rust-sdk/utils" + languageName: unknown + linkType: soft + "@orca-so/whirlpools-rust@npm:*, @orca-so/whirlpools-rust@workspace:rust-sdk/whirlpool": version: 0.0.0-use.local resolution: "@orca-so/whirlpools-rust@workspace:rust-sdk/whirlpool" @@ -2992,11 +3000,21 @@ __metadata: languageName: unknown linkType: soft +"@orca-so/whirlpools-utils@npm:*, @orca-so/whirlpools-utils@workspace:ts-sdk/utils": + version: 0.0.0-use.local + resolution: "@orca-so/whirlpools-utils@workspace:ts-sdk/utils" + dependencies: + "@orca-so/whirlpools-rust-utils": "npm:*" + wasm-pack: "npm:^0.13.0" + languageName: unknown + linkType: soft + "@orca-so/whirlpools@npm:*, @orca-so/whirlpools@workspace:ts-sdk/whirlpool": version: 0.0.0-use.local resolution: "@orca-so/whirlpools@workspace:ts-sdk/whirlpool" dependencies: "@orca-so/whirlpools-client": "npm:*" + "@orca-so/whirlpools-utils": "npm:*" typescript: "npm:^5.5.4" languageName: unknown linkType: soft @@ -3065,12 +3083,12 @@ __metadata: languageName: node linkType: hard -"@shikijs/core@npm:1.13.0": - version: 1.13.0 - resolution: "@shikijs/core@npm:1.13.0" +"@shikijs/core@npm:1.12.1": + version: 1.12.1 + resolution: "@shikijs/core@npm:1.12.1" dependencies: "@types/hast": "npm:^3.0.4" - checksum: 10c0/271ce7f3a6589d0dc5f7e8028fd2a471d4545f87f569d9f33f69fa443d3de52d2b0011b57309eeb2e954c7e0bf5134e9c21fcb69fa0ad5b9590be5163869919a + checksum: 10c0/196df410a63a7cee3539f7ea46ee2241f7d6876af622041330b9c2725e9efa2993a2f0e24938d1dd1c214222fa03e18e61b4c849d323b06505387d93acadb918 languageName: node linkType: hard @@ -4608,10 +4626,10 @@ __metadata: languageName: node linkType: hard -"@types/unist@npm:*, @types/unist@npm:^3.0.0": - version: 3.0.3 - resolution: "@types/unist@npm:3.0.3" - checksum: 10c0/2b1e4adcab78388e088fcc3c0ae8700f76619dbcb4741d7d201f87e2cb346bfc29a89003cfea2d76c996e1061452e14fcd737e8b25aacf949c1f2d6b2bc3dd60 +"@types/unist@npm:*": + version: 3.0.2 + resolution: "@types/unist@npm:3.0.2" + checksum: 10c0/39f220ce184a773c55c18a127062bfc4d0d30c987250cd59bab544d97be6cfec93717a49ef96e81f024b575718f798d4d329eb81c452fc57d6d051af8b043ebf languageName: node linkType: hard @@ -4622,6 +4640,13 @@ __metadata: languageName: node linkType: hard +"@types/unist@npm:^3.0.0": + version: 3.0.3 + resolution: "@types/unist@npm:3.0.3" + checksum: 10c0/2b1e4adcab78388e088fcc3c0ae8700f76619dbcb4741d7d201f87e2cb346bfc29a89003cfea2d76c996e1061452e14fcd737e8b25aacf949c1f2d6b2bc3dd60 + languageName: node + linkType: hard + "@types/uuid@npm:^8.3.4": version: 8.3.4 resolution: "@types/uuid@npm:8.3.4" @@ -5367,6 +5392,15 @@ __metadata: languageName: node linkType: hard +"axios@npm:^0.26.1": + version: 0.26.1 + resolution: "axios@npm:0.26.1" + dependencies: + follow-redirects: "npm:^1.14.8" + checksum: 10c0/77ad7f1e6ca04fcd3fa8af1795b09d8b7c005b71a31f28d99ba40cda0bdcc12a4627801d7fac5efa62b9f667a8402bd54c669039694373bc8d44f6be611f785c + languageName: node + linkType: hard + "axios@npm:^1.7.2": version: 1.7.3 resolution: "axios@npm:1.7.3" @@ -5504,6 +5538,17 @@ __metadata: languageName: node linkType: hard +"binary-install@npm:^1.0.1": + version: 1.1.0 + resolution: "binary-install@npm:1.1.0" + dependencies: + axios: "npm:^0.26.1" + rimraf: "npm:^3.0.2" + tar: "npm:^6.1.11" + checksum: 10c0/c0c94a81262c037a1a84f12ff9acfe667b7938b126e764b0f066d5be128d21e0bb8ac5700f4d89f8f7b860b660882deddeaca300dea0ff218d94676999a133a1 + languageName: node + linkType: hard + "bindings@npm:^1.3.0": version: 1.5.0 resolution: "bindings@npm:1.5.0" @@ -7880,7 +7925,7 @@ __metadata: languageName: node linkType: hard -"follow-redirects@npm:^1.0.0, follow-redirects@npm:^1.15.6": +"follow-redirects@npm:^1.0.0, follow-redirects@npm:^1.14.8, follow-redirects@npm:^1.15.6": version: 1.15.6 resolution: "follow-redirects@npm:1.15.6" peerDependenciesMeta: @@ -13656,12 +13701,12 @@ __metadata: linkType: hard "shiki@npm:^1.9.1": - version: 1.13.0 - resolution: "shiki@npm:1.13.0" + version: 1.12.1 + resolution: "shiki@npm:1.12.1" dependencies: - "@shikijs/core": "npm:1.13.0" + "@shikijs/core": "npm:1.12.1" "@types/hast": "npm:^3.0.4" - checksum: 10c0/0536b255b2522fe89d5ef1be211a30a64ad18c50dc576d6a2afee2398c0d12e9135d9c80c1dfdc25a19e97ce90c3a2b9a2778549b56ccd22ed5ed941274bf918 + checksum: 10c0/1afe9a0002a215fec6960e48284b207d4714de192f4a2223f748a640c0de17a45f2c76ebc4c4020c308bd441c6f7b913eecbd97d346ddd681db0a643c46190fc languageName: node linkType: hard @@ -14932,6 +14977,17 @@ __metadata: languageName: node linkType: hard +"wasm-pack@npm:^0.13.0": + version: 0.13.0 + resolution: "wasm-pack@npm:0.13.0" + dependencies: + binary-install: "npm:^1.0.1" + bin: + wasm-pack: run.js + checksum: 10c0/71ed64c9b0082d51098ec71041ce68a9323d7a0027e3a9c0b694c5931f83ce2a58f1df7255c68239ca4ab702e2daf5c550a7886f8af048f0cb76945a510268b6 + languageName: node + linkType: hard + "watchpack@npm:^2.4.1": version: 2.4.2 resolution: "watchpack@npm:2.4.2"