From a11aeff51c0a191f3745bdc1b092cfd15fbc8179 Mon Sep 17 00:00:00 2001 From: Wilhelm Thieme Date: Wed, 21 Aug 2024 21:09:16 -0400 Subject: [PATCH] Squash --- .github/workflows/checks.yml | 2 +- README.md | 10 +- docs/legacy/package.json | 1 + docs/ts/package.json | 1 + docs/whirlpool/docusaurus.config.js | 3 +- programs/whirlpool/package.json | 4 +- rust-sdk/client/Cargo.toml | 5 +- rust-sdk/client/package.json | 4 +- rust-sdk/core/Cargo.lock | 1944 +++++++++++++++++++++++++ rust-sdk/core/Cargo.toml | 26 + rust-sdk/core/package.json | 15 + rust-sdk/core/src/constants/bundle.rs | 8 + rust-sdk/core/src/constants/mod.rs | 7 + rust-sdk/core/src/constants/swap.rs | 8 + rust-sdk/core/src/constants/tick.rs | 21 + rust-sdk/core/src/lib.rs | 15 + rust-sdk/core/src/math/bundle.rs | 117 ++ rust-sdk/core/src/math/mod.rs | 17 + rust-sdk/core/src/math/position.rs | 145 ++ rust-sdk/core/src/math/price.rs | 140 ++ rust-sdk/core/src/math/tick.rs | 490 +++++++ rust-sdk/core/src/math/tick_array.rs | 196 +++ rust-sdk/core/src/math/token.rs | 477 ++++++ rust-sdk/core/src/quote/fees.rs | 206 +++ rust-sdk/core/src/quote/liquidity.rs | 1111 ++++++++++++++ rust-sdk/core/src/quote/mod.rs | 9 + rust-sdk/core/src/quote/rewards.rs | 302 ++++ rust-sdk/core/src/quote/swap.rs | 647 ++++++++ rust-sdk/core/src/types/fees.rs | 16 + rust-sdk/core/src/types/liquidity.rs | 33 + rust-sdk/core/src/types/mod.rs | 19 + rust-sdk/core/src/types/pool.rs | 37 + rust-sdk/core/src/types/position.rs | 55 + rust-sdk/core/src/types/rewards.rs | 18 + rust-sdk/core/src/types/swap.rs | 31 + rust-sdk/core/src/types/tick.rs | 53 + rust-sdk/core/src/types/token.rs | 53 + rust-sdk/core/src/types/u128.rs | 58 + rust-sdk/macros/Cargo.lock | 47 + rust-sdk/macros/Cargo.toml | 12 + rust-sdk/macros/package.json | 11 + rust-sdk/macros/src/lib.rs | 226 +++ rust-sdk/whirlpool/Cargo.lock | 22 + rust-sdk/whirlpool/Cargo.toml | 1 + rust-sdk/whirlpool/package.json | 4 +- rust-sdk/whirlpool/src/lib.rs | 1 + ts-sdk/core/Cargo.lock | 1814 +++++++++++++++++++++++ ts-sdk/core/Cargo.toml | 13 + ts-sdk/core/package.json | 26 + ts-sdk/core/src/lib.rs | 1 + ts-sdk/core/test.sh | 15 + ts-sdk/whirlpool/package.json | 3 +- ts-sdk/whirlpool/src/index.ts | 1 + yarn.lock | 291 ++-- 54 files changed, 8629 insertions(+), 163 deletions(-) create mode 100644 rust-sdk/core/Cargo.lock create mode 100644 rust-sdk/core/Cargo.toml create mode 100644 rust-sdk/core/package.json create mode 100644 rust-sdk/core/src/constants/bundle.rs create mode 100644 rust-sdk/core/src/constants/mod.rs create mode 100644 rust-sdk/core/src/constants/swap.rs create mode 100644 rust-sdk/core/src/constants/tick.rs create mode 100644 rust-sdk/core/src/lib.rs create mode 100644 rust-sdk/core/src/math/bundle.rs create mode 100644 rust-sdk/core/src/math/mod.rs create mode 100644 rust-sdk/core/src/math/position.rs create mode 100644 rust-sdk/core/src/math/price.rs create mode 100644 rust-sdk/core/src/math/tick.rs create mode 100644 rust-sdk/core/src/math/tick_array.rs create mode 100644 rust-sdk/core/src/math/token.rs create mode 100644 rust-sdk/core/src/quote/fees.rs create mode 100644 rust-sdk/core/src/quote/liquidity.rs create mode 100644 rust-sdk/core/src/quote/mod.rs create mode 100644 rust-sdk/core/src/quote/rewards.rs create mode 100644 rust-sdk/core/src/quote/swap.rs create mode 100644 rust-sdk/core/src/types/fees.rs create mode 100644 rust-sdk/core/src/types/liquidity.rs create mode 100644 rust-sdk/core/src/types/mod.rs create mode 100644 rust-sdk/core/src/types/pool.rs create mode 100644 rust-sdk/core/src/types/position.rs create mode 100644 rust-sdk/core/src/types/rewards.rs create mode 100644 rust-sdk/core/src/types/swap.rs create mode 100644 rust-sdk/core/src/types/tick.rs create mode 100644 rust-sdk/core/src/types/token.rs create mode 100644 rust-sdk/core/src/types/u128.rs create mode 100644 rust-sdk/macros/Cargo.lock create mode 100644 rust-sdk/macros/Cargo.toml create mode 100644 rust-sdk/macros/package.json create mode 100644 rust-sdk/macros/src/lib.rs create mode 100644 ts-sdk/core/Cargo.lock create mode 100644 ts-sdk/core/Cargo.toml create mode 100644 ts-sdk/core/package.json create mode 100644 ts-sdk/core/src/lib.rs create mode 100644 ts-sdk/core/test.sh diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index c706469e1..c249ee487 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: ${{ github.workflow }}-${{ github.ref }} diff --git a/README.md b/README.md index 083733df0..83e4c7cc1 100644 --- a/README.md +++ b/README.md @@ -19,13 +19,11 @@ The program has been audited several times by different security firms. ***The new whirlpool SDKs are still in development and are not recommended for production use yet. Please see [Legacy](#legacy)*** -This repository contains several libraries that can be used to interact with the Whirlpools contract. For most purposes you can use the full library (`@orca-so/whirlpools` and `orca-whirlpools`). +This repository contains several libraries that can be used to interact with the Whirlpools contract. For most purposes you can use the full library (`@orca-so/whirlpools` and `orca_whirlpools`). For specific use-cases you can opt for integrating with lower level packages such as: -* `@orca-so/whirlpools-client` & `orca-whirlpools-client` - auto-generated client for the Whirlpools program that contains account, instruction and error parsing. -* `@orca-so/whirlpools-quoting` & `orca-whirlpools-quoting` - math lib used to calculate a quote for a given trade or liquidity action. -* `@orca-so/whirlpools-composite` & `orca-whirlpools-composite` - helper package for compositing instructions together for executing common actions. -* `@orca-so/whirlpools-utils` & `orca-whirlpools-utils` - utility and math functions used by other packages. +* `@orca-so/whirlpools-client` & `orca_whirlpools_client` - auto-generated client for the Whirlpools program that contains account, instruction and error parsing. +* `@orca-so/whirlpools-core` & `orca_whirlpools_core` - utility and math functions used by other packages. ### Legacy @@ -90,8 +88,6 @@ If you look closely, the commands just call individual commands specified in the If you want to stream the logs of a specific command you can add the `--output-style stream` flag to the command. This allows you to view the logs of the command as they are being produced which can be useful for longer running tasks like integration tests. ---- - # Support ### Questions diff --git a/docs/legacy/package.json b/docs/legacy/package.json index 6702db282..d0d87ffc0 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.6", "typescript": "^5.5.4" diff --git a/docs/ts/package.json b/docs/ts/package.json index 6fdeea77b..ac7b593dc 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.6", "typescript": "^5.5.4" } diff --git a/docs/whirlpool/docusaurus.config.js b/docs/whirlpool/docusaurus.config.js index e5ee40c0b..363eda938 100644 --- a/docs/whirlpool/docusaurus.config.js +++ b/docs/whirlpool/docusaurus.config.js @@ -32,7 +32,8 @@ export default { docs: { routeBasePath: "/", sidebarPath: "./sidebars.js", - editUrl: "https://github.com/orca-so/whirlpools/tree/main/docs/whirlpool", + editUrl: + "https://github.com/orca-so/whirlpools/tree/main/docs/whirlpool", }, theme: { customCss: "./static/index.css", 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/Cargo.toml b/rust-sdk/client/Cargo.toml index e06c35e07..6134fba0d 100644 --- a/rust-sdk/client/Cargo.toml +++ b/rust-sdk/client/Cargo.toml @@ -4,6 +4,7 @@ version = "0.1.0" edition = "2021" [features] +default = [] anchor = ["dep:anchor-lang"] anchor-idl-build = [] test-sbf = [] @@ -16,5 +17,5 @@ num-derive = { version = "^0.4.2" } num-traits = { version = "^0.2.19" } solana-program = { version = "^1.18.21" } thiserror = { version = "^1.0.63" } -serde = { version = "^1.0", features = ["derive"], optional = true } -serde_with = { version = "^3.0", optional = true } +serde = { version = "^1.0.207", features = ["derive"], optional = true } +serde_with = { version = "^3.9.0", optional = true } diff --git a/rust-sdk/client/package.json b/rust-sdk/client/package.json index fa39e9d5f..aa6fe6d87 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/core/Cargo.lock b/rust-sdk/core/Cargo.lock new file mode 100644 index 000000000..70dc8ca0a --- /dev/null +++ b/rust-sdk/core/Cargo.lock @@ -0,0 +1,1944 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "ahash" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" +dependencies = [ + "getrandom 0.2.15", + "once_cell", + "version_check", +] + +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "anyhow" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" + +[[package]] +name = "approx" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0e60b75072ecd4168020818c0107f2857bb6c4e64252d8d3983f6263b40a5c3" +dependencies = [ + "num-traits", +] + +[[package]] +name = "ark-bn254" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a22f4561524cd949590d78d7d4c5df8f592430d221f7f3c9497bbafd8972120f" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-std", +] + +[[package]] +name = "ark-ec" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "defd9a439d56ac24968cca0571f598a61bc8c55f71d50a89cda591cb750670ba" +dependencies = [ + "ark-ff", + "ark-poly", + "ark-serialize", + "ark-std", + "derivative", + "hashbrown 0.13.2", + "itertools", + "num-traits", + "zeroize", +] + +[[package]] +name = "ark-ff" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" +dependencies = [ + "ark-ff-asm", + "ark-ff-macros", + "ark-serialize", + "ark-std", + "derivative", + "digest 0.10.7", + "itertools", + "num-bigint", + "num-traits", + "paste", + "rustc_version", + "zeroize", +] + +[[package]] +name = "ark-ff-asm" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-macros" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" +dependencies = [ + "num-bigint", + "num-traits", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-poly" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d320bfc44ee185d899ccbadfa8bc31aab923ce1558716e1997a1e74057fe86bf" +dependencies = [ + "ark-ff", + "ark-serialize", + "ark-std", + "derivative", + "hashbrown 0.13.2", +] + +[[package]] +name = "ark-serialize" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" +dependencies = [ + "ark-serialize-derive", + "ark-std", + "digest 0.10.7", + "num-bigint", +] + +[[package]] +name = "ark-serialize-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae3281bc6d0fd7e549af32b52511e1302185bd688fd3359fa36423346ff682ea" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-std" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" +dependencies = [ + "num-traits", + "rand 0.8.5", +] + +[[package]] +name = "arrayref" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d151e35f61089500b617991b791fc8bfd237ae50cd5950803758a179b41e67a" + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "base64" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +dependencies = [ + "serde", +] + +[[package]] +name = "bitmaps" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "031043d04099746d8db04daf1fa424b2bc8bd69d92b25962dcde24da39ab64a2" +dependencies = [ + "typenum", +] + +[[package]] +name = "blake3" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30cca6d3674597c30ddf2c587bf8d9d65c9a84d2326d941cc79c9842dfe0ef52" +dependencies = [ + "arrayref", + "arrayvec", + "cc", + "cfg-if", + "constant_time_eq", + "digest 0.10.7", +] + +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "borsh" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15bf3650200d8bffa99015595e10f1fbd17de07abbc25bb067da79e769939bfa" +dependencies = [ + "borsh-derive 0.9.3", + "hashbrown 0.11.2", +] + +[[package]] +name = "borsh" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4114279215a005bc675e386011e594e1d9b800918cea18fcadadcce864a2046b" +dependencies = [ + "borsh-derive 0.10.3", + "hashbrown 0.13.2", +] + +[[package]] +name = "borsh" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6362ed55def622cddc70a4746a68554d7b687713770de539e59a739b249f8ed" +dependencies = [ + "borsh-derive 1.5.1", + "cfg_aliases", +] + +[[package]] +name = "borsh-derive" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6441c552f230375d18e3cc377677914d2ca2b0d36e52129fe15450a2dce46775" +dependencies = [ + "borsh-derive-internal 0.9.3", + "borsh-schema-derive-internal 0.9.3", + "proc-macro-crate 0.1.5", + "proc-macro2", + "syn 1.0.109", +] + +[[package]] +name = "borsh-derive" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0754613691538d51f329cce9af41d7b7ca150bc973056f1156611489475f54f7" +dependencies = [ + "borsh-derive-internal 0.10.3", + "borsh-schema-derive-internal 0.10.3", + "proc-macro-crate 0.1.5", + "proc-macro2", + "syn 1.0.109", +] + +[[package]] +name = "borsh-derive" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3ef8005764f53cd4dca619f5bf64cafd4664dada50ece25e4d81de54c80cc0b" +dependencies = [ + "once_cell", + "proc-macro-crate 3.1.0", + "proc-macro2", + "quote", + "syn 2.0.75", + "syn_derive", +] + +[[package]] +name = "borsh-derive-internal" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5449c28a7b352f2d1e592a8a28bf139bc71afb0764a14f3c02500935d8c44065" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "borsh-derive-internal" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afb438156919598d2c7bad7e1c0adf3d26ed3840dbc010db1a882a65583ca2fb" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "borsh-schema-derive-internal" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdbd5696d8bfa21d53d9fe39a714a18538bad11492a42d066dbbc395fb1951c0" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "borsh-schema-derive-internal" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634205cc43f74a1b9046ef87c4540ebda95696ec0f315024860cad7c5b0f5ccd" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "bs58" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "bv" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8834bb1d8ee5dc048ee3124f2c7c1afcc6bc9aed03f11e9dfd8c69470a5db340" +dependencies = [ + "feature-probe", + "serde", +] + +[[package]] +name = "bytemuck" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fd4c6dcc3b0aea2f5c0b4b82c2b15fe39ddbc76041a310848f4706edf76bb31" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cc8b54b395f2fcfbb3d90c47b01c7f444d94d05bdeb775811dec868ac3bbc26" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.75", +] + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "cc" +version = "1.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68064e60dbf1f17005c2fde4d07c16d8baa506fd7ffed8ccab702d93617975c7" +dependencies = [ + "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "console_error_panic_hook" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" +dependencies = [ + "cfg-if", + "wasm-bindgen", +] + +[[package]] +name = "console_log" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89f72f65e8501878b8a004d5a1afb780987e2ce2b4532c562e367a72c57499f" +dependencies = [ + "log", + "web-sys", +] + +[[package]] +name = "constant_time_eq" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" + +[[package]] +name = "cpufeatures" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad" +dependencies = [ + "libc", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "crypto-mac" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" +dependencies = [ + "generic-array", + "subtle", +] + +[[package]] +name = "curve25519-dalek" +version = "3.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90f9d052967f590a76e62eb387bd0bbb1b000182c3cefe5364db6b7211651bc0" +dependencies = [ + "byteorder", + "digest 0.9.0", + "rand_core 0.5.1", + "serde", + "subtle", + "zeroize", +] + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer 0.10.4", + "crypto-common", + "subtle", +] + +[[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 = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[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 = "feature-probe" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835a3dc7d1ec9e75e2b5fb4ba75396837112d2060b03f7d43bc1897c7f7211da" + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "serde", + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", + "wasm-bindgen", +] + +[[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 = "hashbrown" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +dependencies = [ + "ahash 0.7.8", +] + +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash 0.8.11", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "hmac" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "126888268dcc288495a26bf004b38c5fdbb31682f992c84ceb046a1f0fe38840" +dependencies = [ + "crypto-mac", + "digest 0.9.0", +] + +[[package]] +name = "hmac-drbg" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17ea0a1394df5b6574da6e0c1ade9e78868c9fb0a4e5ef4428e32da4676b85b1" +dependencies = [ + "digest 0.9.0", + "generic-array", + "hmac", +] + +[[package]] +name = "im" +version = "15.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0acd33ff0285af998aaf9b57342af478078f53492322fafc47450e09397e0e9" +dependencies = [ + "bitmaps", + "rand_core 0.6.4", + "rand_xoshiro", + "rayon", + "serde", + "sized-chunks", + "typenum", + "version_check", +] + +[[package]] +name = "indexmap" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93ead53efc7ea8ed3cfb0c79fc8023fbb782a5432b52830b6518941cebe6505c" +dependencies = [ + "equivalent", + "hashbrown 0.14.5", +] + +[[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 = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "jobserver" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +dependencies = [ + "libc", +] + +[[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 = "keccak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[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 = "libsecp256k1" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9d220bc1feda2ac231cb78c3d26f27676b8cf82c96971f7aeef3d0cf2797c73" +dependencies = [ + "arrayref", + "base64 0.12.3", + "digest 0.9.0", + "hmac-drbg", + "libsecp256k1-core", + "libsecp256k1-gen-ecmult", + "libsecp256k1-gen-genmult", + "rand 0.7.3", + "serde", + "sha2 0.9.9", + "typenum", +] + +[[package]] +name = "libsecp256k1-core" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0f6ab710cec28cef759c5f18671a27dae2a5f952cdaaee1d8e2908cb2478a80" +dependencies = [ + "crunchy", + "digest 0.9.0", + "subtle", +] + +[[package]] +name = "libsecp256k1-gen-ecmult" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccab96b584d38fac86a83f07e659f0deafd0253dc096dab5a36d53efe653c5c3" +dependencies = [ + "libsecp256k1-core", +] + +[[package]] +name = "libsecp256k1-gen-genmult" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67abfe149395e3aa1c48a2beb32b068e2334402df8181f818d3aee2b304c4f5d" +dependencies = [ + "libsecp256k1-core", +] + +[[package]] +name = "light-poseidon" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c9a85a9752c549ceb7578064b4ed891179d20acd85f27318573b64d2d7ee7ee" +dependencies = [ + "ark-bn254", + "ark-ff", + "num-bigint", + "thiserror", +] + +[[package]] +name = "litrs" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[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 = "memmap2" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" +dependencies = [ + "libc", +] + +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.75", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[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 = "opaque-debug" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" + +[[package]] +name = "orca_whirlpools_client" +version = "0.1.0" +dependencies = [ + "borsh 0.10.3", + "num-derive", + "num-traits", + "solana-program", + "thiserror", +] + +[[package]] +name = "orca_whirlpools_core" +version = "0.1.0" +dependencies = [ + "approx", + "ethnum", + "libm", + "orca_whirlpools_client", + "orca_whirlpools_macros", + "print-no-std", + "serde", + "serde-big-array", + "serde-wasm-bindgen 0.6.5", + "tsify", + "wasm-bindgen", +] + +[[package]] +name = "orca_whirlpools_macros" +version = "0.1.0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.75", +] + +[[package]] +name = "panicking" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21eb594cd667adf943bf4617e74ca71e2f4041f2fa630d5fc7be9314a1b480de" + +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pbkdf2" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "216eaa586a190f0a738f2f918511eecfa90f13295abec0e457cdebcceda80cbd" +dependencies = [ + "crypto-mac", +] + +[[package]] +name = "pc-ints" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46a0c5099ffcaf701968dbd51a2b05ababc9e3360d7ad0af87d2622a93b7efb7" +dependencies = [ + "memoffset", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + +[[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-macro-crate" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" +dependencies = [ + "toml", +] + +[[package]] +name = "proc-macro-crate" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" +dependencies = [ + "toml_edit", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[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 = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom 0.1.16", + "libc", + "rand_chacha 0.2.2", + "rand_core 0.5.1", + "rand_hc", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core 0.5.1", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom 0.1.16", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.15", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core 0.5.1", +] + +[[package]] +name = "rand_xoshiro" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa" +dependencies = [ + "rand_core 0.6.4", +] + +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "redox_syscall" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" +dependencies = [ + "bitflags", +] + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + +[[package]] +name = "rustversion" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "semver" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" + +[[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-big-array" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11fc7cc2c76d73e0f27ee52abbd64eec84d46f370c88371120433196934e4b7f" +dependencies = [ + "serde", +] + +[[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_bytes" +version = "0.11.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "387cc504cb06bb40a96c8e04e951fe01854cf6bc921053c954e4a606d9675c6a" +dependencies = [ + "serde", +] + +[[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 2.0.75", +] + +[[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 2.0.75", +] + +[[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 = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures", + "digest 0.9.0", + "opaque-debug", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest 0.10.7", + "keccak", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "sized-chunks" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16d69225bde7a69b235da73377861095455d298f2b970996eec25ddbb42b3d1e" +dependencies = [ + "bitmaps", + "typenum", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "solana-frozen-abi" +version = "1.18.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20a6ef2db80dceb124b7bf81cca3300804bf427d2711973fc3df450ed7dfb26d" +dependencies = [ + "block-buffer 0.10.4", + "bs58", + "bv", + "either", + "generic-array", + "im", + "lazy_static", + "log", + "memmap2", + "rustc_version", + "serde", + "serde_bytes", + "serde_derive", + "sha2 0.10.8", + "solana-frozen-abi-macro", + "subtle", + "thiserror", +] + +[[package]] +name = "solana-frozen-abi-macro" +version = "1.18.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70088de7d4067d19a7455609e2b393e6086bd847bb39c4d2bf234fc14827ef9e" +dependencies = [ + "proc-macro2", + "quote", + "rustc_version", + "syn 2.0.75", +] + +[[package]] +name = "solana-program" +version = "1.18.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb2b2c8babfae4cace1a25b6efa00418f3acd852cf55d7cecc0360d3c5050479" +dependencies = [ + "ark-bn254", + "ark-ec", + "ark-ff", + "ark-serialize", + "base64 0.21.7", + "bincode", + "bitflags", + "blake3", + "borsh 0.10.3", + "borsh 0.9.3", + "borsh 1.5.1", + "bs58", + "bv", + "bytemuck", + "cc", + "console_error_panic_hook", + "console_log", + "curve25519-dalek", + "getrandom 0.2.15", + "itertools", + "js-sys", + "lazy_static", + "libc", + "libsecp256k1", + "light-poseidon", + "log", + "memoffset", + "num-bigint", + "num-derive", + "num-traits", + "parking_lot", + "rand 0.8.5", + "rustc_version", + "rustversion", + "serde", + "serde_bytes", + "serde_derive", + "serde_json", + "sha2 0.10.8", + "sha3", + "solana-frozen-abi", + "solana-frozen-abi-macro", + "solana-sdk-macro", + "thiserror", + "tiny-bip39", + "wasm-bindgen", + "zeroize", +] + +[[package]] +name = "solana-sdk-macro" +version = "1.18.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c55c196c8050834c391a34b58e3c9fd86b15452ef1feeeafa1dbeb9d2291dfec" +dependencies = [ + "bs58", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.75", +] + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6af063034fc1935ede7be0122941bafa9bacb949334d090b77ca98b5817c7d9" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn_derive" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1329189c02ff984e9736652b1631330da25eaa6bc639089ed4915d25446cbe7b" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.75", +] + +[[package]] +name = "thiserror" +version = "1.0.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.75", +] + +[[package]] +name = "tiny-bip39" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffc59cb9dfc85bb312c3a78fd6aa8a8582e310b0fa885d5bb877f6dcc601839d" +dependencies = [ + "anyhow", + "hmac", + "once_cell", + "pbkdf2", + "rand 0.7.3", + "rustc-hash", + "sha2 0.9.9", + "thiserror", + "unicode-normalization", + "wasm-bindgen", + "zeroize", +] + +[[package]] +name = "tinyvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" + +[[package]] +name = "toml_edit" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow", +] + +[[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 2.0.75", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-normalization" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + +[[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.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 2.0.75", + "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 2.0.75", + "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" + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "0.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.75", +] + +[[package]] +name = "zeroize" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4756f7db3f7b5574938c3eb1c117038b8e07f95ee6718c0efad4ac21508f1efd" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.75", +] diff --git a/rust-sdk/core/Cargo.toml b/rust-sdk/core/Cargo.toml new file mode 100644 index 000000000..ddf65d5cc --- /dev/null +++ b/rust-sdk/core/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "orca_whirlpools_core" +version = "0.1.0" +edition = "2021" + +[features] +default = ["floats"] +wasm = ["dep:wasm-bindgen", "dep:serde-wasm-bindgen", "dep:serde", "dep:serde-big-array", "dep:tsify", "dep:orca_whirlpools_macros"] +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-big-array = { version = "^0.5.1", optional = true } +serde-wasm-bindgen = { version = "^0.6.5", optional = true } +tsify = { version = "^0.4.5", features = ["js"], optional = true } +orca_whirlpools_macros = { path = "../macros", optional = true } + +[target.'cfg(not(feature = "wasm"))'.dependencies] +orca_whirlpools_client = { path = "../client" } + +[dev-dependencies] +print-no-std = { version = "^0.1.0"} +approx = { version = "^0.3.2" } diff --git a/rust-sdk/core/package.json b/rust-sdk/core/package.json new file mode 100644 index 000000000..ed5178dc5 --- /dev/null +++ b/rust-sdk/core/package.json @@ -0,0 +1,15 @@ +{ + "name": "@orca-so/whirlpools-rust-core", + "version": "0.0.1", + "scripts": { + "build": "cargo build -p orca_whirlpools_core", + "test": "cargo test -p orca_whirlpools_core --lib", + "format": "cargo clippy --fix --allow-dirty --allow-staged && cargo fmt", + "lint": "cargo clippy", + "clean": "cargo clean -p orca_whirlpools_core" + }, + "devDependencies": { + "@orca-so/whirlpools-rust-client": "*", + "@orca-so/whirlpools-rust-macros": "*" + } +} diff --git a/rust-sdk/core/src/constants/bundle.rs b/rust-sdk/core/src/constants/bundle.rs new file mode 100644 index 000000000..cdbef384c --- /dev/null +++ b/rust-sdk/core/src/constants/bundle.rs @@ -0,0 +1,8 @@ +#![allow(non_snake_case)] + +#[cfg(feature = "wasm")] +use orca_whirlpools_macros::export_ts_const; + +/// The maximum number of positions in a position bundle. +#[cfg_attr(feature = "wasm", export_ts_const)] +pub const POSITION_BUNDLE_SIZE: usize = 256; diff --git a/rust-sdk/core/src/constants/mod.rs b/rust-sdk/core/src/constants/mod.rs new file mode 100644 index 000000000..a48b3ee81 --- /dev/null +++ b/rust-sdk/core/src/constants/mod.rs @@ -0,0 +1,7 @@ +mod bundle; +mod swap; +mod tick; + +pub use bundle::*; +pub use swap::*; +pub use tick::*; diff --git a/rust-sdk/core/src/constants/swap.rs b/rust-sdk/core/src/constants/swap.rs new file mode 100644 index 000000000..f09a4c104 --- /dev/null +++ b/rust-sdk/core/src/constants/swap.rs @@ -0,0 +1,8 @@ +#![allow(non_snake_case)] + +#[cfg(feature = "wasm")] +use orca_whirlpools_macros::export_ts_const; + +/// The denominator of the fee rate value. +#[cfg_attr(feature = "wasm", export_ts_const)] +pub const FEE_RATE_DENOMINATOR: u32 = 1_000_000; diff --git a/rust-sdk/core/src/constants/tick.rs b/rust-sdk/core/src/constants/tick.rs new file mode 100644 index 000000000..8bd2d6ba2 --- /dev/null +++ b/rust-sdk/core/src/constants/tick.rs @@ -0,0 +1,21 @@ +#![allow(non_snake_case)] + +#[cfg(feature = "wasm")] +use orca_whirlpools_macros::export_ts_const; + +/// The number of ticks in a tick array. +#[cfg_attr(feature = "wasm", export_ts_const)] +pub const TICK_ARRAY_SIZE: usize = 88; + +/// Pools with tick spacing above this threshold are considered full range only. +/// This means the program rejects any non-full range positions in these pools. +#[cfg_attr(feature = "wasm", export_ts_const)] +pub const FULL_RANGE_ONLY_TICK_SPACING_THRESHOLD: u16 = 32768; // 2^15 + +/// The minimum tick index. +#[cfg_attr(feature = "wasm", export_ts_const)] +pub const MIN_TICK_INDEX: i32 = -443636; + +/// The maximum tick index. +#[cfg_attr(feature = "wasm", export_ts_const)] +pub const MAX_TICK_INDEX: i32 = 443636; diff --git a/rust-sdk/core/src/lib.rs b/rust-sdk/core/src/lib.rs new file mode 100644 index 000000000..4eb174f1e --- /dev/null +++ b/rust-sdk/core/src/lib.rs @@ -0,0 +1,15 @@ +// FIXME: disable std for non-test builds to decrease wasm binary size. +// There is currently something in tsify that prevents this: +// https://github.com/madonoharu/tsify/issues/56 +// #![cfg_attr(not(test), 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/core/src/math/bundle.rs b/rust-sdk/core/src/math/bundle.rs new file mode 100644 index 000000000..df08640bf --- /dev/null +++ b/rust-sdk/core/src/math/bundle.rs @@ -0,0 +1,117 @@ +#[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 + +#[allow(clippy::needless_range_loop)] +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(all(test, not(feature = "wasm")))] +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!(!is_position_bundle_full(&bundle)); + + let bundle: [u8; POSITION_BUNDLE_BYTES] = [255; POSITION_BUNDLE_BYTES]; + assert!(is_position_bundle_full(&bundle)); + + let mut bundle: [u8; POSITION_BUNDLE_BYTES] = [0; POSITION_BUNDLE_BYTES]; + bundle[0] = 0b11111111; + assert!(!is_position_bundle_full(&bundle)); + } + + #[test] + fn test_is_position_bundle_empty() { + let bundle: [u8; POSITION_BUNDLE_BYTES] = [0; POSITION_BUNDLE_BYTES]; + assert!(is_position_bundle_empty(&bundle)); + + let bundle: [u8; POSITION_BUNDLE_BYTES] = [255; POSITION_BUNDLE_BYTES]; + assert!(!is_position_bundle_empty(&bundle)); + + let mut bundle: [u8; POSITION_BUNDLE_BYTES] = [0; POSITION_BUNDLE_BYTES]; + bundle[0] = 0b111111; + assert!(!is_position_bundle_empty(&bundle)); + } +} diff --git a/rust-sdk/core/src/math/mod.rs b/rust-sdk/core/src/math/mod.rs new file mode 100644 index 000000000..cf2a832d5 --- /dev/null +++ b/rust-sdk/core/src/math/mod.rs @@ -0,0 +1,17 @@ +mod bundle; +mod position; +mod tick; +mod tick_array; +mod token; + +#[cfg(feature = "floats")] +mod price; + +pub use bundle::*; +pub use position::*; +pub use tick::*; +pub use tick_array::*; +pub use token::*; + +#[cfg(feature = "floats")] +pub use price::*; diff --git a/rust-sdk/core/src/math/position.rs b/rust-sdk/core/src/math/position.rs new file mode 100644 index 000000000..0b477a0de --- /dev/null +++ b/rust-sdk/core/src/math/position.rs @@ -0,0 +1,145 @@ +use crate::{PositionRatio, PositionStatus}; + +#[cfg(feature = "wasm")] +use wasm_bindgen::prelude::*; + +use super::tick_index_to_sqrt_price; + +/// 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 { + position_status(tick_current_index, tick_lower_index, tick_upper_index) + == PositionStatus::InRange +} + +/// Calculate the status of a position +/// The status can be one of three values: +/// - InRange: The position is in range +/// - BelowRange: The position is below the range +/// - AboveRange: The position is above the range +/// +/// # 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 PositionStatus enum value indicating the status of the position +#[cfg_attr(feature = "wasm", wasm_bindgen(js_name = positionStatus, skip_jsdoc))] +pub fn position_status( + tick_current_index: i32, + tick_lower_index: i32, + tick_upper_index: i32, +) -> PositionStatus { + if tick_current_index < tick_lower_index { + PositionStatus::BelowRange + } else if tick_current_index >= tick_upper_index { + PositionStatus::AboveRange + } else { + PositionStatus::InRange + } +} + +/// Calculate the token_a / token_b ratio of a (ficticious) position +/// +/// # 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 PositionRatio struct containing the ratio of token_a and token_b +#[cfg_attr(feature = "wasm", wasm_bindgen(js_name = positionRatio, skip_jsdoc))] +pub fn position_ratio( + tick_current_index: i32, + tick_lower_index: i32, + tick_upper_index: i32, +) -> PositionRatio { + let position_status = position_status(tick_current_index, tick_lower_index, tick_upper_index); + match position_status { + PositionStatus::BelowRange => PositionRatio { + ratio_a: 10000, + ratio_b: 0, + }, + PositionStatus::AboveRange => PositionRatio { + ratio_a: 0, + ratio_b: 10000, + }, + PositionStatus::InRange => { + let current_sqrt_price: u128 = tick_index_to_sqrt_price(tick_current_index).into(); + let lower_sqrt_price: u128 = tick_index_to_sqrt_price(tick_lower_index).into(); + let upper_sqrt_price: u128 = tick_index_to_sqrt_price(tick_upper_index).into(); + + let amount_b: u128 = current_sqrt_price - lower_sqrt_price; + let amount_a = upper_sqrt_price - current_sqrt_price; + let amount_total = amount_a + amount_b; + + let ratio_a = (amount_a * 10000) / amount_total; + let ratio_b = 10000 - ratio_a; + + PositionRatio { + ratio_a: ratio_a.try_into().unwrap(), + ratio_b: ratio_b.try_into().unwrap(), + } + } + } +} + +#[cfg(all(test, not(feature = "wasm")))] +mod test { + use super::*; + + #[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)); + } + + #[test] + fn test_position_status() { + assert_eq!(position_status(85, 90, 100), PositionStatus::BelowRange); + assert_eq!(position_status(90, 90, 100), PositionStatus::InRange); + assert_eq!(position_status(95, 90, 100), PositionStatus::InRange); + assert_eq!(position_status(100, 90, 100), PositionStatus::AboveRange); + assert_eq!(position_status(105, 90, 100), PositionStatus::AboveRange); + } + + #[test] + fn test_position_ratio() { + let ratio_1 = position_ratio(-10, -10, 10); + assert_eq!(ratio_1.ratio_a, 10000); + assert_eq!(ratio_1.ratio_b, 0); + + let ratio_2 = position_ratio(-5, -10, 10); + assert_eq!(ratio_2.ratio_a, 7500); + assert_eq!(ratio_2.ratio_b, 2500); + + let ratio_3 = position_ratio(0, -10, 10); + assert_eq!(ratio_3.ratio_a, 5001); + assert_eq!(ratio_3.ratio_b, 4999); + + let ratio_4 = position_ratio(5, -10, 10); + assert_eq!(ratio_4.ratio_a, 2500); + assert_eq!(ratio_4.ratio_b, 7500); + + let ratio_5 = position_ratio(10, -10, 10); + assert_eq!(ratio_5.ratio_a, 0); + assert_eq!(ratio_5.ratio_b, 10000); + } +} diff --git a/rust-sdk/core/src/math/price.rs b/rust-sdk/core/src/math/price.rs new file mode 100644 index 000000000..bcbe62d3c --- /dev/null +++ b/rust-sdk/core/src/math/price.rs @@ -0,0 +1,140 @@ +#[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); + + (floor(sqrt(price * power) * Q64_RESOLUTION) as u128).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 = sqrt_price.into(); + let sqrt_price_u128 = 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(all(test, not(feature = "wasm")))] +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(1844674407370955161600, 8, 6), 100.0); + assert_eq!(sqrt_price_to_price(184467440737095516160, 6, 6), 100.0); + assert_eq!(sqrt_price_to_price(18446744073709551616, 6, 8), 100.0); + } + + #[test] + fn test_invert_price() { + relative_eq!(invert_price(100.0, 8, 6), 0.000001); + relative_eq!(invert_price(100.0, 6, 6), 0.0); + relative_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/core/src/math/tick.rs b/rust-sdk/core/src/math/tick.rs new file mode 100644 index 000000000..bf1c3f709 --- /dev/null +++ b/rust-sdk/core/src/math/tick.rs @@ -0,0 +1,490 @@ +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 { + tick_lower_index: min_tick_index, + tick_upper_index: max_tick_index, + } +} + +/// Order tick indexes in ascending order. +/// If the lower tick index is greater than the upper tick index, the indexes are swapped. +/// This is useful for ensuring that the lower tick index is always less than the upper tick index. +/// +/// # Parameters +/// - `tick_lower_index` - A i32 integer representing the lower tick index +/// - `tick_upper_index` - A i32 integer representing the upper tick index +/// +/// # Returns +/// - A TickRange struct containing the lower and upper tick index +#[cfg_attr(feature = "wasm", wasm_bindgen(js_name = orderTickIndexes, skip_jsdoc))] +pub fn order_tick_indexes(tick_lower_index: i32, tick_upper_index: i32) -> TickRange { + if tick_lower_index < tick_upper_index { + TickRange { + tick_lower_index, + tick_upper_index, + } + } else { + TickRange { + tick_lower_index: tick_upper_index, + tick_upper_index: tick_lower_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 +} + +// Private functions + +fn mul_shift_96(n0: u128, n1: u128) -> u128 { + let mul = ::from(n0) * ::from(n1); + mul.wrapping_shr(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(all(test, not(feature = "wasm")))] +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() { + assert_eq!(tick_index_to_sqrt_price(100), 18539204128674405812); + assert_eq!(tick_index_to_sqrt_price(1), 18447666387855959850); + assert_eq!(tick_index_to_sqrt_price(0), 18446744073709551616); + assert_eq!(tick_index_to_sqrt_price(-1), 18445821805675392311); + assert_eq!(tick_index_to_sqrt_price(-100), 18354745142194483561); + } + + #[test] + fn test_sqrt_price_to_tick_index() { + assert_eq!(sqrt_price_to_tick_index(18539204128674405812), 100); + assert_eq!(sqrt_price_to_tick_index(18447666387855959850), 1); + assert_eq!(sqrt_price_to_tick_index(18446744073709551616), 0); + assert_eq!(sqrt_price_to_tick_index(18445821805675392311), -1); + assert_eq!(sqrt_price_to_tick_index(18354745142194483561), -100); + } + + #[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.tick_lower_index, (MIN_TICK_INDEX / 10) * 10); + assert_eq!(range.tick_upper_index, (MAX_TICK_INDEX / 10) * 10); + } + + #[test] + fn test_order_tick_indexes() { + let range_1 = order_tick_indexes(100, 200); + assert_eq!(range_1.tick_lower_index, 100); + assert_eq!(range_1.tick_upper_index, 200); + + let range_2 = order_tick_indexes(200, 100); + assert_eq!(range_2.tick_lower_index, 100); + assert_eq!(range_2.tick_upper_index, 200); + + let range_3 = order_tick_indexes(100, 100); + assert_eq!(range_3.tick_lower_index, 100); + assert_eq!(range_3.tick_upper_index, 100); + } + + #[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 + )); + } +} diff --git a/rust-sdk/core/src/math/tick_array.rs b/rust-sdk/core/src/math/tick_array.rs new file mode 100644 index 000000000..0a2d7fb86 --- /dev/null +++ b/rust-sdk/core/src/math/tick_array.rs @@ -0,0 +1,196 @@ +use crate::{Tick, TickArray, TICK_ARRAY_SIZE}; + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct TickArraySequence { + tick_arrays: [TickArray; 3], + tick_spacing: u16, +} + +impl TickArraySequence { + pub fn new(one: TickArray, two: TickArray, three: TickArray, tick_spacing: u16) -> Self { + let (first, second, third) = order_tick_arrays(one, two, three); + + let first_second_diff = (second.start_tick_index - first.start_tick_index).unsigned_abs(); + let second_thrid_diff = (third.start_tick_index - second.start_tick_index).unsigned_abs(); + let required_diff: u32 = TICK_ARRAY_SIZE as u32 * tick_spacing as u32; + if first_second_diff != required_diff || second_thrid_diff != required_diff { + panic!("tick arrays are not evenly spaced"); + } + Self { + tick_arrays: [first, second, third], + tick_spacing, + } + } + + pub fn start_index(&self) -> i32 { + self.tick_arrays[0].start_tick_index + } + + pub fn end_index(&self) -> i32 { + let tick_span = TICK_ARRAY_SIZE * 3 * self.tick_spacing as usize; + self.start_index() + tick_span as i32 + } + + pub fn tick(&self, tick_index: i32) -> &Tick { + if (tick_index < self.start_index()) || (tick_index >= self.end_index()) { + panic!("tick index out of bounds"); + } + if (tick_index % self.tick_spacing as i32) != 0 { + panic!("invalid tick index"); + } + let tick_array_index = ((tick_index - self.start_index()) + / (TICK_ARRAY_SIZE as i32 * self.tick_spacing as i32)) + as usize; + let tick_array = &self.tick_arrays[tick_array_index]; + let tick_index_in_array = + (tick_index - tick_array.start_tick_index) / self.tick_spacing as i32; + &tick_array.ticks[tick_index_in_array as usize] + } + + pub fn next_initialized_tick(&self, tick_index: i32) -> (&Tick, i32) { + let remainder = tick_index % self.tick_spacing as i32; + let next_index = tick_index + self.tick_spacing as i32 - remainder; + let tick = self.tick(next_index); + if !tick.initialized { + return self.next_initialized_tick(next_index); + } + (tick, next_index) + } + + pub fn prev_initialized_tick(&self, tick_index: i32) -> (&Tick, i32) { + let remainder = tick_index % self.tick_spacing as i32; + let prev_index = tick_index - self.tick_spacing as i32 + remainder; + let tick = self.tick(prev_index); + if !tick.initialized { + return self.prev_initialized_tick(prev_index); + } + (tick, prev_index) + } +} + +fn order_tick_arrays( + one: TickArray, + two: TickArray, + three: TickArray, +) -> (TickArray, TickArray, TickArray) { + let first_start_index = one.start_tick_index; + let second_start_index = two.start_tick_index; + let third_start_index = three.start_tick_index; + + if first_start_index < second_start_index { + if second_start_index < third_start_index { + (one, two, three) + } else if first_start_index < third_start_index { + (one, three, two) + } else { + (three, one, two) + } + } else if first_start_index < third_start_index { + (two, one, three) + } else if second_start_index < third_start_index { + (two, three, one) + } else { + (three, two, one) + } +} + +#[cfg(all(test, not(feature = "wasm")))] +mod tests { + use super::*; + + fn test_sequence() -> TickArraySequence { + let ticks: [Tick; TICK_ARRAY_SIZE] = (0..TICK_ARRAY_SIZE) + .map(|x| Tick { + initialized: x & 1 == 1, + liquidity_gross: x as u128, + ..Tick::default() + }) + .collect::>() + .try_into() + .unwrap(); + let one = TickArray { + start_tick_index: 0, + ticks, + }; + let two = TickArray { + start_tick_index: TICK_ARRAY_SIZE as i32 * 16, + ticks, + }; + let three = TickArray { + start_tick_index: TICK_ARRAY_SIZE as i32 * 16 * 2, + ticks, + }; + TickArraySequence::new(one, two, three, 16) + } + + #[test] + fn test_tick_array_start_index() { + let sequence = test_sequence(); + assert_eq!(sequence.start_index(), 0); + } + + #[test] + fn test_tick_array_end_index() { + let sequence = test_sequence(); + assert_eq!(sequence.end_index(), 4224); + } + + #[test] + fn test_get_tick() { + let sequence = test_sequence(); + assert_eq!(sequence.tick(0).liquidity_gross, 0); + assert_eq!(sequence.tick(16).liquidity_gross, 1); + assert_eq!(sequence.tick(1408).liquidity_gross, 0); + assert_eq!(sequence.tick(1424).liquidity_gross, 1); + } + + #[test] + #[should_panic(expected = "tick index out of bounds")] + fn test_tick_out_of_bounds_below() { + test_sequence().tick(-1); + } + + #[test] + #[should_panic(expected = "tick index out of bounds")] + fn test_tick_out_of_bounds_above() { + test_sequence().tick(4225); + } + + #[test] + #[should_panic(expected = "invalid tick index")] + fn test_tick_invalid_index() { + test_sequence().tick(1); + } + + #[test] + fn test_get_next_initializable_tick_index() { + let sequence = test_sequence(); + let (tick, index) = sequence.next_initialized_tick(0); + assert_eq!(index, 16); + assert_eq!(tick.liquidity_gross, 1); + } + + #[test] + fn test_get_next_initializable_tick_cross_array() { + let sequence = test_sequence(); + let (tick, index) = sequence.next_initialized_tick(1392); + assert_eq!(index, 1424); + assert_eq!(tick.liquidity_gross, 1); + } + + #[test] + fn test_get_prev_initializable_tick_index() { + let sequence = test_sequence(); + let (tick, index) = sequence.prev_initialized_tick(32); + assert_eq!(index, 16); + assert_eq!(tick.liquidity_gross, 1); + } + + #[test] + fn test_get_prev_initializable_tick_cross_array() { + let sequence = test_sequence(); + let (tick, index) = sequence.prev_initialized_tick(1408); + assert_eq!(index, 1392); + assert_eq!(tick.liquidity_gross, 87); + } +} diff --git a/rust-sdk/core/src/math/token.rs b/rust-sdk/core/src/math/token.rs new file mode 100644 index 000000000..f88170ac1 --- /dev/null +++ b/rust-sdk/core/src/math/token.rs @@ -0,0 +1,477 @@ +use crate::{AdjustmentType, FEE_RATE_DENOMINATOR, U128}; + +use core::ops::{Shl, Shr}; + +use ethnum::U256; +#[cfg(feature = "wasm")] +use wasm_bindgen::prelude::*; + +const BPS_DENOMINATOR: u16 = 10000; + +/// Calculate the amount A delta between two sqrt_prices +/// +/// # Parameters +/// - `current_sqrt_price`: The current square root price +/// - `target_sqrt_price`: The target square root price +/// - `current_liquidity`: The current liquidity +/// - `round_up`: Whether to round up or not +/// +/// # Returns +/// - `u64`: The amount delta +#[cfg_attr(feature = "wasm", wasm_bindgen(js_name = getAmountDeltaA, skip_jsdoc))] +pub fn get_amount_delta_a( + current_sqrt_price: U128, + target_sqrt_price: U128, + current_liquidity: U128, + round_up: bool, +) -> u64 { + let (sqrt_price_lower, sqrt_price_upper) = + order_prices(current_sqrt_price.into(), target_sqrt_price.into()); + let sqrt_price_diff = sqrt_price_upper - sqrt_price_lower; + let numerator: U256 = ::from(current_liquidity) + .saturating_mul(sqrt_price_diff.into()) + .shl(64); + + let denominator: U256 = ::from(sqrt_price_lower).saturating_mul(sqrt_price_upper.into()); + + let quotient = numerator / denominator; + let remainder = numerator % denominator; + + let result = if round_up && remainder != 0 { + quotient + 1 + } else { + quotient + }; + + result.try_into().unwrap() +} + +/// Calculate the amount B delta between two sqrt_prices +/// +/// # Parameters +/// - `current_sqrt_price`: The current square root price +/// - `target_sqrt_price`: The target square root price +/// - `current_liquidity`: The current liquidity +/// - `round_up`: Whether to round up or not +/// +/// # Returns +/// - `u64`: The amount delta +#[cfg_attr(feature = "wasm", wasm_bindgen(js_name = getAmountDeltaB, skip_jsdoc))] +pub fn get_amount_delta_b( + current_sqrt_price: U128, + target_sqrt_price: U128, + current_liquidity: U128, + round_up: bool, +) -> u64 { + let (sqrt_price_lower, sqrt_price_upper) = + order_prices(current_sqrt_price.into(), target_sqrt_price.into()); + let sqrt_price_diff = sqrt_price_upper - sqrt_price_lower; + + let p: U256 = ::from(current_liquidity).saturating_mul(sqrt_price_diff.into()); + let result: U256 = p.shr(64); + + let should_round = round_up && p & ::from(u64::MAX) > 0; + + if should_round { + (result + 1).try_into().unwrap() + } else { + result.try_into().unwrap() + } +} + +/// Calculate the next square root price +/// +/// # Parameters +/// - `current_sqrt_price`: The current square root price +/// - `current_liquidity`: The current liquidity +/// - `amount`: The amount +/// - `specified_input`: Whether the input is specified +/// +/// # Returns +/// - `u128`: The next square root price +#[cfg_attr(feature = "wasm", wasm_bindgen(js_name = getNextSqrtPriceFromA, skip_jsdoc))] +pub fn get_next_sqrt_price_from_a( + current_sqrt_price: U128, + current_liquidity: U128, + amount: U128, + specified_input: bool, +) -> U128 { + if amount == 0 { + return current_sqrt_price; + } + let current_sqrt_price: u128 = current_sqrt_price.into(); + let current_liquidity: u128 = current_liquidity.into(); + + let p = ::from(current_sqrt_price).saturating_mul(amount.into()); + let numerator = ::from(current_liquidity) + .saturating_mul(current_sqrt_price.into()) + .shl(64); + + let current_liquidity_shifted: u128 = current_liquidity.shl(64); + let denominator = if specified_input { + current_liquidity_shifted + p + } else { + current_liquidity_shifted - p + }; + + let quotient: U256 = numerator / denominator; + let remainder: U256 = numerator % denominator; + + let result: u128 = if remainder != 0 { + (quotient + 1).try_into().unwrap() + } else { + quotient.try_into().unwrap() + }; + + result.into() +} + +/// Calculate the next square root price +/// +/// # Parameters +/// - `current_sqrt_price`: The current square root price +/// - `current_liquidity`: The current liquidity +/// - `amount`: The amount +/// - `specified_input`: Whether the input is specified +/// +/// # Returns +/// - `u128`: The next square root price +#[cfg_attr(feature = "wasm", wasm_bindgen(js_name = getNextSqrtPriceFromB, skip_jsdoc))] +pub fn get_next_sqrt_price_from_b( + current_sqrt_price: U128, + current_liquidity: U128, + amount: U128, + specified_input: bool, +) -> U128 { + if amount == 0 { + return current_sqrt_price; + } + let current_sqrt_price: u128 = current_sqrt_price.into(); + + let current_liquidity = ::from(current_liquidity); + let amount_shifted = ::from(amount).shl(64); + + let quotient: U256 = amount_shifted / current_liquidity; + let remainder: U256 = amount_shifted % current_liquidity; + + let delta: u128 = if !specified_input && remainder != 0 { + (quotient + 1).try_into().unwrap() + } else { + quotient.try_into().unwrap() + }; + + if specified_input { + (current_sqrt_price + delta).into() + } else { + (current_sqrt_price - delta).into() + } +} + +/// Calculate the amount after transfer fee +/// amount_without_transfer_fee > amount_with_transfer_fee +/// +/// # Parameters +/// - `amount`: The amount before tranfer fee +/// - `transfer_fee`: The transfer fee +/// - `adjust_up`: Whether to adjust up or down +/// +/// # Returns +/// - `u128`: The amount after transfer fee +#[cfg_attr(feature = "wasm", wasm_bindgen(js_name = adjust_amount, skip_jsdoc))] +pub fn adjust_amount(amount: U128, adjust_type: AdjustmentType, adjust_up: bool) -> U128 { + let amount: u128 = amount.into(); + + if adjustment_numerator(adjust_type) == 0 { + return amount.into(); + } + + let p = if adjust_up { + adjustment_denominator(adjust_type) + adjustment_numerator(adjust_type) + } else { + adjustment_denominator(adjust_type) - adjustment_numerator(adjust_type) + }; + + let numerator = ::from(amount).saturating_mul(p.into()); + let denominator = ::from(adjustment_denominator(adjust_type)); + let quotient = numerator / denominator; + let remainder = numerator % denominator; + + let mut result: u128 = if adjust_up && remainder != 0 { + (quotient + 1).try_into().unwrap() + } else { + quotient.try_into().unwrap() + }; + + let fee_amount = if adjust_up { + result - amount + } else { + amount - result + }; + + let max_fee = adjustment_max(adjust_type); + if fee_amount >= max_fee { + if adjust_up { + result = amount + max_fee + } else { + result = amount - max_fee + } + } + + result.into() +} + +/// Calculate the amount before transfer fee +/// The original transfer amount may not always be unique due to rounding. +/// In this case, the smaller amount will be chosen. +/// e.g. Both transfer amount 10, 11 with 10% fee rate results in net +/// transfer amount of 9. In this case, 10 will be chosen. +/// +/// # Parameters +/// - `amount`: The amount after tranfer fee +/// - `transfer_fee`: The transfer fee +/// - `adjust_up`: Whether to adjust up or down +/// +/// # Returns +/// - `u128`: The amount before transfer fee +#[cfg_attr(feature = "wasm", wasm_bindgen(js_name = inverseAdjustAmount, skip_jsdoc))] +pub fn inverse_adjust_amount(amount: U128, adjust_type: AdjustmentType, adjust_up: bool) -> U128 { + let amount: u128 = amount.into(); + + if amount == 0 { + return 0u128.into(); + } + + if adjustment_numerator(adjust_type) == 0 { + return amount.into(); + } + + let numerator = ::from(amount).saturating_mul(adjustment_denominator(adjust_type).into()); + let denominator = if adjust_up { + adjustment_denominator(adjust_type) + adjustment_numerator(adjust_type) + } else { + adjustment_denominator(adjust_type) - adjustment_numerator(adjust_type) + }; + + let quotient = numerator / ::from(denominator); + let remainder = numerator % ::from(denominator); + + let mut result = if !adjust_up && remainder != 0 { + (quotient + 1).try_into().unwrap() + } else { + quotient.try_into().unwrap() + }; + + let fee_amount = if adjust_up { + amount - result + } else { + result - amount + }; + + let max_fee = adjustment_max(adjust_type); + if fee_amount >= max_fee { + if adjust_up { + result = amount - max_fee + } else { + result = amount + max_fee + } + } + + result.try_into().unwrap() +} + +// Private functions + +fn order_prices(a: u128, b: u128) -> (u128, u128) { + if a < b { + (a, b) + } else { + (b, a) + } +} + +fn adjustment_numerator(adjust_type: AdjustmentType) -> u128 { + match adjust_type { + AdjustmentType::None => 0, + AdjustmentType::SwapFee(num) | AdjustmentType::Slippage(num) => num.into(), + AdjustmentType::TransferFee(num, _) => num.into(), + } +} + +fn adjustment_denominator(adjust_type: AdjustmentType) -> u128 { + match adjust_type { + AdjustmentType::SwapFee(_) => FEE_RATE_DENOMINATOR.into(), + _ => BPS_DENOMINATOR.into(), + } +} + +fn adjustment_max(adjust_type: AdjustmentType) -> u128 { + match adjust_type { + AdjustmentType::TransferFee(_, max_fee) => max_fee.into(), + _ => u128::MAX, + } +} + +#[cfg(all(test, not(feature = "wasm")))] +mod tests { + use super::*; + + #[test] + fn test_get_amount_delta_a() { + assert_eq!(get_amount_delta_a(4 << 64, 2 << 64, 4, true), 1); + assert_eq!(get_amount_delta_a(4 << 64, 2 << 64, 4, false), 1); + + assert_eq!(get_amount_delta_a(4 << 64, 4 << 64, 4, true), 0); + assert_eq!(get_amount_delta_a(4 << 64, 4 << 64, 4, false), 0); + } + + #[test] + fn test_get_amount_delta_b() { + assert_eq!(get_amount_delta_b(4 << 64, 2 << 64, 4, true), 8); + assert_eq!(get_amount_delta_b(4 << 64, 2 << 64, 4, false), 8); + + assert_eq!(get_amount_delta_b(4 << 64, 4 << 64, 4, true), 0); + assert_eq!(get_amount_delta_b(4 << 64, 4 << 64, 4, false), 0); + } + + #[test] + fn test_get_next_sqrt_price_from_a() { + assert_eq!(get_next_sqrt_price_from_a(4 << 64, 4, 1, true), 2 << 64); + assert_eq!(get_next_sqrt_price_from_a(2 << 64, 4, 1, false), 4 << 64); + + assert_eq!(get_next_sqrt_price_from_a(4 << 64, 4, 0, true), 4 << 64); + assert_eq!(get_next_sqrt_price_from_a(4 << 64, 4, 0, false), 4 << 64); + } + + #[test] + fn test_get_next_sqrt_price_from_b() { + assert_eq!(get_next_sqrt_price_from_b(2 << 64, 4, 8, true), 4 << 64); + assert_eq!(get_next_sqrt_price_from_b(4 << 64, 4, 8, false), 2 << 64); + + assert_eq!(get_next_sqrt_price_from_b(4 << 64, 4, 0, true), 4 << 64); + assert_eq!(get_next_sqrt_price_from_b(4 << 64, 4, 0, false), 4 << 64); + } + + #[test] + fn test_adjust_amount() { + assert_eq!( + adjust_amount(10000, AdjustmentType::TransferFee(1000, 10000), true), + 11000 + ); + assert_eq!( + adjust_amount(10000, AdjustmentType::TransferFee(1000, 10000), false), + 9000 + ); + assert_eq!( + adjust_amount(10000, AdjustmentType::TransferFee(1000, 500), true), + 10500 + ); + assert_eq!( + adjust_amount(10000, AdjustmentType::TransferFee(1000, 500), false), + 9500 + ); + assert_eq!( + adjust_amount(10000, AdjustmentType::TransferFee(0, 10000), true), + 10000 + ); + assert_eq!( + adjust_amount(10000, AdjustmentType::TransferFee(0, 10000), false), + 10000 + ); + + assert_eq!( + adjust_amount(10000, AdjustmentType::SwapFee(1000), true), + 10010 + ); + assert_eq!( + adjust_amount(10000, AdjustmentType::SwapFee(1000), false), + 9990 + ); + assert_eq!( + adjust_amount(10000, AdjustmentType::SwapFee(0), true), + 10000 + ); + assert_eq!( + adjust_amount(10000, AdjustmentType::SwapFee(0), false), + 10000 + ); + + assert_eq!( + adjust_amount(10000, AdjustmentType::Slippage(1000), true), + 11000 + ); + assert_eq!( + adjust_amount(10000, AdjustmentType::Slippage(1000), false), + 9000 + ); + assert_eq!( + adjust_amount(10000, AdjustmentType::Slippage(0), true), + 10000 + ); + assert_eq!( + adjust_amount(10000, AdjustmentType::Slippage(0), false), + 10000 + ); + } + + #[test] + fn test_inverse_adjust_amount() { + assert_eq!( + inverse_adjust_amount(11000, AdjustmentType::TransferFee(1000, 10000), true), + 10000 + ); + assert_eq!( + inverse_adjust_amount(9000, AdjustmentType::TransferFee(1000, 10000), false), + 10000 + ); + assert_eq!( + inverse_adjust_amount(10500, AdjustmentType::TransferFee(1000, 500), true), + 10000 + ); + assert_eq!( + inverse_adjust_amount(9500, AdjustmentType::TransferFee(1000, 500), false), + 10000 + ); + assert_eq!( + inverse_adjust_amount(10000, AdjustmentType::TransferFee(0, 10000), true), + 10000 + ); + assert_eq!( + inverse_adjust_amount(10000, AdjustmentType::TransferFee(0, 10000), false), + 10000 + ); + + assert_eq!( + inverse_adjust_amount(10010, AdjustmentType::SwapFee(1000), true), + 10000 + ); + assert_eq!( + inverse_adjust_amount(9990, AdjustmentType::SwapFee(1000), false), + 10000 + ); + assert_eq!( + inverse_adjust_amount(10000, AdjustmentType::SwapFee(0), true), + 10000 + ); + assert_eq!( + inverse_adjust_amount(10000, AdjustmentType::SwapFee(0), false), + 10000 + ); + + assert_eq!( + inverse_adjust_amount(11000, AdjustmentType::Slippage(1000), true), + 10000 + ); + assert_eq!( + inverse_adjust_amount(9000, AdjustmentType::Slippage(1000), false), + 10000 + ); + assert_eq!( + inverse_adjust_amount(10000, AdjustmentType::Slippage(0), true), + 10000 + ); + assert_eq!( + inverse_adjust_amount(10000, AdjustmentType::Slippage(0), false), + 10000 + ); + } +} diff --git a/rust-sdk/core/src/quote/fees.rs b/rust-sdk/core/src/quote/fees.rs new file mode 100644 index 000000000..05df01d51 --- /dev/null +++ b/rust-sdk/core/src/quote/fees.rs @@ -0,0 +1,206 @@ +use core::ops::Shr; + +use ethnum::U256; +#[cfg(feature = "wasm")] +use wasm_bindgen::prelude::*; + +use crate::{adjust_amount, CollectFeesQuote, Position, Tick, TransferFee, Whirlpool}; + +/// Calculate fees owed for a position +/// +/// # Paramters +/// - `whirlpool`: The whirlpool state +/// - `position`: The position state +/// - `tick_lower`: The lower tick state +/// - `tick_upper`: The upper tick state +/// - `transfer_fee_a`: The transfer fee for token A +/// - `transfer_fee_b`: The transfer fee for token B +/// +/// # 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( + whirlpool: Whirlpool, + position: Position, + tick_lower: Tick, + tick_upper: Tick, + transfer_fee_a: Option, + transfer_fee_b: Option, +) -> CollectFeesQuote { + let mut fee_growth_below_a: u128 = tick_lower.fee_growth_outside_a; + let mut fee_growth_above_a: u128 = tick_upper.fee_growth_outside_a; + let mut fee_growth_below_b: u128 = tick_lower.fee_growth_outside_b; + let mut fee_growth_above_b: u128 = tick_upper.fee_growth_outside_b; + + if whirlpool.tick_current_index < position.tick_lower_index { + fee_growth_below_a = whirlpool + .fee_growth_global_a + .saturating_sub(fee_growth_below_a); + fee_growth_below_b = whirlpool + .fee_growth_global_b + .saturating_sub(fee_growth_below_b); + } + + if whirlpool.tick_current_index >= position.tick_upper_index { + fee_growth_above_a = whirlpool + .fee_growth_global_a + .saturating_sub(fee_growth_above_a); + fee_growth_above_b = whirlpool + .fee_growth_global_b + .saturating_sub(fee_growth_above_b); + } + + let fee_growth_inside_a = whirlpool + .fee_growth_global_a + .saturating_sub(fee_growth_below_a) + .saturating_sub(fee_growth_above_a); + + let fee_growth_inside_b = whirlpool + .fee_growth_global_b + .saturating_sub(fee_growth_below_b) + .saturating_sub(fee_growth_above_b); + + let fee_owed_delta_a: U256 = ::from(fee_growth_inside_a) + .saturating_sub(position.fee_growth_checkpoint_a.into()) + .saturating_mul(position.liquidity.into()) + .shr(64); + + let fee_owed_delta_b: U256 = ::from(fee_growth_inside_b) + .saturating_sub(position.fee_growth_checkpoint_b.into()) + .saturating_mul(position.liquidity.into()) + .shr(64); + + let fee_owed_delta_a: u128 = fee_owed_delta_a.try_into().unwrap(); + let fee_owed_delta_b: u128 = fee_owed_delta_b.try_into().unwrap(); + + let withdrawable_fee_a: u128 = position.fee_owed_a as u128 + fee_owed_delta_a; + let withdrawable_fee_b: u128 = position.fee_owed_b as u128 + fee_owed_delta_b; + + let fee_owed_a = adjust_amount(withdrawable_fee_a.into(), transfer_fee_a.into(), false); + let fee_owed_b = adjust_amount(withdrawable_fee_b.into(), transfer_fee_b.into(), false); + + CollectFeesQuote { + fee_owed_a: fee_owed_a.into(), + fee_owed_b: fee_owed_b.into(), + } +} + +#[cfg(all(test, not(feature = "wasm")))] +mod tests { + use super::*; + + fn test_whirlpool(tick_index: i32) -> Whirlpool { + Whirlpool { + tick_current_index: tick_index, + fee_growth_global_a: 800, + fee_growth_global_b: 1000, + ..Whirlpool::default() + } + } + + fn test_position() -> Position { + Position { + liquidity: 10000000000000000000, + tick_lower_index: 5, + tick_upper_index: 10, + fee_growth_checkpoint_a: 300, + fee_owed_a: 400, + fee_growth_checkpoint_b: 500, + fee_owed_b: 600, + ..Position::default() + } + } + + fn test_tick() -> Tick { + Tick { + fee_growth_outside_a: 50, + fee_growth_outside_b: 20, + ..Tick::default() + } + } + + #[test] + fn test_collect_out_of_range_lower() { + let result = collect_fees_quote( + test_whirlpool(0), + test_position(), + test_tick(), + test_tick(), + None, + None, + ); + assert_eq!(result.fee_owed_a, 400); + assert_eq!(result.fee_owed_b, 600); + } + + #[test] + fn test_in_range() { + let result = collect_fees_quote( + test_whirlpool(7), + test_position(), + test_tick(), + test_tick(), + None, + None, + ); + assert_eq!(result.fee_owed_a, 616); + assert_eq!(result.fee_owed_b, 849); + } + + #[test] + fn test_collect_out_of_range_upper() { + let result = collect_fees_quote( + test_whirlpool(15), + test_position(), + test_tick(), + test_tick(), + None, + None, + ); + assert_eq!(result.fee_owed_a, 400); + assert_eq!(result.fee_owed_b, 600); + } + + #[test] + fn test_collect_on_range_lower() { + let result = collect_fees_quote( + test_whirlpool(5), + test_position(), + test_tick(), + test_tick(), + None, + None, + ); + assert_eq!(result.fee_owed_a, 616); + assert_eq!(result.fee_owed_b, 849); + } + + #[test] + fn test_collect_on_upper() { + let result = collect_fees_quote( + test_whirlpool(10), + test_position(), + test_tick(), + test_tick(), + None, + None, + ); + assert_eq!(result.fee_owed_a, 400); + assert_eq!(result.fee_owed_b, 600); + } + + #[test] + fn test_collect_transfer_fee() { + let result = collect_fees_quote( + test_whirlpool(7), + test_position(), + test_tick(), + test_tick(), + Some(TransferFee::new(2000)), + Some(TransferFee::new(5000)), + ); + assert_eq!(result.fee_owed_a, 492); + assert_eq!(result.fee_owed_b, 424); + } +} diff --git a/rust-sdk/core/src/quote/liquidity.rs b/rust-sdk/core/src/quote/liquidity.rs new file mode 100644 index 000000000..aa644c425 --- /dev/null +++ b/rust-sdk/core/src/quote/liquidity.rs @@ -0,0 +1,1111 @@ +use core::ops::{Shl, Shr}; + +#[cfg(feature = "wasm")] +use wasm_bindgen::prelude::*; + +use ethnum::U256; + +use crate::{ + adjust_amount, inverse_adjust_amount, order_tick_indexes, position_status, + tick_index_to_sqrt_price, AdjustmentType, DecreaseLiquidityQuote, IncreaseLiquidityQuote, + PositionStatus, TransferFee, U128, +}; + +/// Calculate the quote for decreasing liquidity +/// +/// # Parameters +/// - `liquidity_delta` - The amount of liquidity to decrease +/// - `slippage_tolerance` - The slippage tolerance in bps +/// - `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 +/// - `transfer_fee_a` - The transfer fee for token A in bps +/// - `transfer_fee_b` - The transfer fee for token B in bps +/// +/// # Returns +/// - A DecreaseLiquidityQuote struct containing the estimated token amounts +#[cfg_attr(feature = "wasm", wasm_bindgen(js_name = decreaseLiquidityQuote, skip_jsdoc))] +pub fn decrease_liquidity_quote( + liquidity_delta: U128, + slippage_tolerance: u16, + tick_current_index: i32, + tick_lower_index: i32, + tick_upper_index: i32, + transfer_fee_a: Option, + transfer_fee_b: Option, +) -> DecreaseLiquidityQuote { + let liquidity_delta: u128 = liquidity_delta.into(); + if liquidity_delta == 0 { + return DecreaseLiquidityQuote::default(); + } + + let tick_range = order_tick_indexes(tick_lower_index, tick_upper_index); + + let (token_est_before_fees_a, token_est_before_fees_b) = get_token_estimates_from_liquidity( + liquidity_delta, + tick_current_index, + tick_range.tick_lower_index, + tick_range.tick_upper_index, + ); + + let token_min_before_fees_a = adjust_amount( + token_est_before_fees_a.into(), + AdjustmentType::Slippage(slippage_tolerance), + false, + ); + let token_min_before_fees_b = adjust_amount( + token_est_before_fees_b.into(), + AdjustmentType::Slippage(slippage_tolerance), + false, + ); + + let token_est_a = adjust_amount(token_est_before_fees_a.into(), transfer_fee_a.into(), false); + let token_est_b = adjust_amount(token_est_before_fees_b.into(), transfer_fee_b.into(), false); + + let token_min_a = adjust_amount(token_min_before_fees_a.into(), transfer_fee_a.into(), false); + let token_min_b = adjust_amount(token_min_before_fees_b.into(), transfer_fee_b.into(), false); + + DecreaseLiquidityQuote { + liquidity_delta, + token_est_a: token_est_a.into(), + token_est_b: token_est_b.into(), + token_min_a: token_min_a.into(), + token_min_b: token_min_b.into(), + } +} + +/// Calculate the quote for decreasing liquidity given a token a amount +/// +/// # Parameters +/// - `token_amount_a` - The amount of token a to decrease +/// - `slippage_tolerance` - The slippage tolerance in bps +/// - `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 +/// - `transfer_fee_a` - The transfer fee for token A in bps +/// - `transfer_fee_b` - The transfer fee for token B in bps +/// +/// # Returns +/// - A DecreaseLiquidityQuote struct containing the estimated token amounts +#[cfg_attr(feature = "wasm", wasm_bindgen(js_name = decreaseLiquidityQuoteA, skip_jsdoc))] +pub fn decrease_liquidity_quote_a( + token_amount_a: U128, + slippage_tolerance: u16, + tick_current_index: i32, + tick_lower_index: i32, + tick_upper_index: i32, + transfer_fee_a: Option, + transfer_fee_b: Option, +) -> DecreaseLiquidityQuote { + let tick_range = order_tick_indexes(tick_lower_index, tick_upper_index); + let token_delta_a = inverse_adjust_amount(token_amount_a, transfer_fee_a.into(), false); + + if token_delta_a == 0 { + return DecreaseLiquidityQuote::default(); + } + + let position_status = position_status( + tick_current_index, + tick_range.tick_lower_index, + tick_range.tick_upper_index, + ); + + let liquidity: u128 = match position_status { + PositionStatus::BelowRange => get_liquidity_from_a( + token_delta_a.into(), + tick_range.tick_lower_index, + tick_range.tick_upper_index, + ), + PositionStatus::AboveRange => 0, + PositionStatus::InRange => get_liquidity_from_a( + token_delta_a.into(), + tick_current_index, + tick_range.tick_upper_index, + ), + }; + + decrease_liquidity_quote( + liquidity.into(), + slippage_tolerance, + tick_current_index, + tick_lower_index, + tick_upper_index, + transfer_fee_a, + transfer_fee_b, + ) +} + +/// Calculate the quote for decreasing liquidity given a token b amount +/// +/// # Parameters +/// - `token_amount_b` - The amount of token b to decrease +/// - `slippage_tolerance` - The slippage tolerance in bps +/// - `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 +/// - `transfer_fee_a` - The transfer fee for token A in bps +/// - `transfer_fee_b` - The transfer fee for token B in bps +/// +/// # Returns +/// - A DecreaseLiquidityQuote struct containing the estimated token amounts +#[cfg_attr(feature = "wasm", wasm_bindgen(js_name = decreaseLiquidityQuoteB, skip_jsdoc))] +pub fn decrease_liquidity_quote_b( + token_amount_b: U128, + slippage_tolerance: u16, + tick_current_index: i32, + tick_lower_index: i32, + tick_upper_index: i32, + transfer_fee_a: Option, + transfer_fee_b: Option, +) -> DecreaseLiquidityQuote { + let tick_range = order_tick_indexes(tick_lower_index, tick_upper_index); + let token_delta_b = inverse_adjust_amount(token_amount_b.into(), transfer_fee_b.into(), false); + + if token_delta_b == 0 { + return DecreaseLiquidityQuote::default(); + } + + let position_status = position_status( + tick_current_index, + tick_range.tick_lower_index, + tick_range.tick_upper_index, + ); + + let liquidity: u128 = match position_status { + PositionStatus::BelowRange => 0, + PositionStatus::AboveRange => get_liquidity_from_b( + token_delta_b.into(), + tick_range.tick_lower_index, + tick_range.tick_upper_index, + ), + PositionStatus::InRange => get_liquidity_from_b( + token_delta_b.into(), + tick_range.tick_lower_index, + tick_current_index, + ), + }; + + decrease_liquidity_quote( + liquidity.into(), + slippage_tolerance, + tick_current_index, + tick_lower_index, + tick_upper_index, + transfer_fee_a, + transfer_fee_b, + ) +} + +/// Calculate the quote for increasing liquidity +/// +/// # Parameters +/// - `liquidity_delta` - The amount of liquidity to increase +/// - `slippage_tolerance` - The slippage tolerance in bps +/// - `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 +/// - `transfer_fee_a` - The transfer fee for token A in bps +/// - `transfer_fee_b` - The transfer fee for token B in bps +/// +/// # Returns +/// - An IncreaseLiquidityQuote struct containing the estimated token amounts +#[cfg_attr(feature = "wasm", wasm_bindgen(js_name = increaseLiquidityQuote, skip_jsdoc))] +pub fn increase_liquidity_quote( + liquidity_delta: U128, + slippage_tolerance: u16, + tick_current_index: i32, + tick_lower_index: i32, + tick_upper_index: i32, + transfer_fee_a: Option, + transfer_fee_b: Option, +) -> IncreaseLiquidityQuote { + let liquidity_delta: u128 = liquidity_delta.into(); + if liquidity_delta == 0 { + return IncreaseLiquidityQuote::default(); + } + + let tick_range = order_tick_indexes(tick_lower_index, tick_upper_index); + + let (token_est_before_fees_a, token_est_before_fees_b) = get_token_estimates_from_liquidity( + liquidity_delta, + tick_current_index, + tick_range.tick_lower_index, + tick_range.tick_upper_index, + ); + + let token_max_before_fees_a = adjust_amount( + token_est_before_fees_a.into(), + AdjustmentType::Slippage(slippage_tolerance), + true, + ); + let token_max_before_fees_b = adjust_amount( + token_est_before_fees_b.into(), + AdjustmentType::Slippage(slippage_tolerance), + true, + ); + + let token_est_a = + inverse_adjust_amount(token_est_before_fees_a.into(), transfer_fee_a.into(), false); + let token_est_b = + inverse_adjust_amount(token_est_before_fees_b.into(), transfer_fee_b.into(), false); + + let token_max_a = + inverse_adjust_amount(token_max_before_fees_a.into(), transfer_fee_a.into(), false); + let token_max_b = + inverse_adjust_amount(token_max_before_fees_b.into(), transfer_fee_b.into(), false); + + IncreaseLiquidityQuote { + liquidity_delta, + token_est_a: token_est_a.into(), + token_est_b: token_est_b.into(), + token_max_a: token_max_a.into(), + token_max_b: token_max_b.into(), + } +} + +/// Calculate the quote for increasing liquidity given a token a amount +/// +/// # Parameters +/// - `token_amount_a` - The amount of token a to increase +/// - `slippage_tolerance` - The slippage tolerance in bps +/// - `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 +/// - `transfer_fee_a` - The transfer fee for token A in bps +/// - `transfer_fee_b` - The transfer fee for token B in bps +/// +/// # Returns +/// - An IncreaseLiquidityQuote struct containing the estimated token amounts +#[cfg_attr(feature = "wasm", wasm_bindgen(js_name = increaseLiquidityQuoteA, skip_jsdoc))] +pub fn increase_liquidity_quote_a( + token_amount_a: U128, + slippage_tolerance: u16, + tick_current_index: i32, + tick_lower_index: i32, + tick_upper_index: i32, + transfer_fee_a: Option, + transfer_fee_b: Option, +) -> IncreaseLiquidityQuote { + let tick_range = order_tick_indexes(tick_lower_index, tick_upper_index); + let token_delta_a = adjust_amount(token_amount_a.into(), transfer_fee_a.into(), false); + + if token_delta_a == 0 { + return IncreaseLiquidityQuote::default(); + } + + let position_status = position_status( + tick_current_index, + tick_range.tick_lower_index, + tick_range.tick_upper_index, + ); + + let liquidity: u128 = match position_status { + PositionStatus::BelowRange => get_liquidity_from_a( + token_delta_a.into(), + tick_range.tick_lower_index, + tick_range.tick_upper_index, + ), + PositionStatus::AboveRange => 0, + PositionStatus::InRange => get_liquidity_from_a( + token_delta_a.into(), + tick_current_index, + tick_range.tick_upper_index, + ), + }; + + increase_liquidity_quote( + liquidity.into(), + slippage_tolerance, + tick_current_index, + tick_lower_index, + tick_upper_index, + transfer_fee_a, + transfer_fee_b, + ) +} + +/// Calculate the quote for increasing liquidity given a token b amount +/// +/// # Parameters +/// - `token_amount_b` - The amount of token b to increase +/// - `slippage_tolerance` - The slippage tolerance in bps +/// - `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 +/// - `transfer_fee_a` - The transfer fee for token A in bps +/// - `transfer_fee_b` - The transfer fee for token B in bps +/// +/// # Returns +/// - An IncreaseLiquidityQuote struct containing the estimated token amounts +#[cfg_attr(feature = "wasm", wasm_bindgen(js_name = increaseLiquidityQuoteB, skip_jsdoc))] +pub fn increase_liquidity_quote_b( + token_amount_b: U128, + slippage_tolerance: u16, + tick_current_index: i32, + tick_lower_index: i32, + tick_upper_index: i32, + transfer_fee_a: Option, + transfer_fee_b: Option, +) -> IncreaseLiquidityQuote { + let tick_range = order_tick_indexes(tick_lower_index, tick_upper_index); + let token_delta_b = adjust_amount(token_amount_b.into(), transfer_fee_b.into(), false); + + if token_delta_b == 0 { + return IncreaseLiquidityQuote::default(); + } + + let position_status = position_status( + tick_current_index, + tick_range.tick_lower_index, + tick_range.tick_upper_index, + ); + + let liquidity: u128 = match position_status { + PositionStatus::BelowRange => 0, + PositionStatus::AboveRange => get_liquidity_from_b( + token_delta_b.into(), + tick_range.tick_lower_index, + tick_range.tick_upper_index, + ), + PositionStatus::InRange => get_liquidity_from_b( + token_delta_b.into(), + tick_range.tick_lower_index, + tick_current_index, + ), + }; + + increase_liquidity_quote( + liquidity.into(), + slippage_tolerance, + tick_current_index, + tick_lower_index, + tick_upper_index, + transfer_fee_a, + transfer_fee_b, + ) +} + +// Private functions + +fn get_liquidity_from_a(token_delta_a: u128, tick_lower_index: i32, tick_upper_index: i32) -> u128 { + let sqrt_price_lower: U256 = tick_index_to_sqrt_price(tick_lower_index).into(); + let sqrt_price_upper: U256 = tick_index_to_sqrt_price(tick_upper_index).into(); + let result: U256 = ::from(token_delta_a) + .saturating_mul(sqrt_price_lower) + .saturating_mul(sqrt_price_upper) + .saturating_div(sqrt_price_upper - sqrt_price_lower) + .shr(64); + result.try_into().unwrap() +} + +fn get_token_a_from_liquidity( + liquidity_delta: u128, + tick_lower_index: i32, + tick_upper_index: i32, + round_up: bool, +) -> u128 { + let sqrt_price_lower: U256 = tick_index_to_sqrt_price(tick_lower_index).into(); + let sqrt_price_upper: U256 = tick_index_to_sqrt_price(tick_upper_index).into(); + let numerator: U256 = ::from(liquidity_delta) + .saturating_mul(sqrt_price_upper - sqrt_price_lower) + .shl(64); + let denominator = sqrt_price_upper.saturating_mul(sqrt_price_lower); + let quotient = numerator / denominator; + let remainder = numerator % denominator; + if round_up && remainder != 0 { + (quotient + 1).try_into().unwrap() + } else { + quotient.try_into().unwrap() + } +} + +fn get_liquidity_from_b(token_delta_b: u128, tick_lower_index: i32, tick_upper_index: i32) -> u128 { + let sqrt_price_lower: U256 = tick_index_to_sqrt_price(tick_lower_index).into(); + let sqrt_price_upper: U256 = tick_index_to_sqrt_price(tick_upper_index).into(); + let numerator: U256 = ::from(token_delta_b).shl(64); + let denominator = sqrt_price_upper - sqrt_price_lower; + numerator.saturating_div(denominator).try_into().unwrap() +} + +fn get_token_b_from_liquidity( + liquidity_delta: u128, + tick_lower_index: i32, + tick_upper_index: i32, + round_up: bool, +) -> u128 { + let sqrt_price_lower: U256 = tick_index_to_sqrt_price(tick_lower_index).into(); + let sqrt_price_upper: U256 = tick_index_to_sqrt_price(tick_upper_index).into(); + let p: U256 = ::from(liquidity_delta).saturating_mul(sqrt_price_upper - sqrt_price_lower); + let result: U256 = p.shr(64); + if round_up && p & ::from(u64::MAX) > 0 { + (result + 1).try_into().unwrap() + } else { + result.try_into().unwrap() + } +} + +fn get_token_estimates_from_liquidity( + liquidity_delta: u128, + tick_current_index: i32, + tick_lower_index: i32, + tick_upper_index: i32, +) -> (u128, u128) { + if liquidity_delta == 0 { + return (0, 0); + } + + let position_status = position_status(tick_current_index, tick_lower_index, tick_upper_index); + + match position_status { + PositionStatus::BelowRange => { + let token_a = get_token_a_from_liquidity( + liquidity_delta, + tick_lower_index, + tick_upper_index, + true, + ); + (token_a, 0) + } + PositionStatus::InRange => { + let token_a = get_token_a_from_liquidity( + liquidity_delta, + tick_lower_index, + tick_current_index, + false, + ); + let token_b = get_token_b_from_liquidity( + liquidity_delta, + tick_current_index, + tick_upper_index, + false, + ); + (token_a, token_b) + } + PositionStatus::AboveRange => { + let token_b = get_token_b_from_liquidity( + liquidity_delta, + tick_lower_index, + tick_upper_index, + true, + ); + (0, token_b) + } + } +} + +#[cfg(all(test, not(feature = "wasm")))] +mod tests { + use super::*; + + #[test] + fn test_decrease_liquidity_quote() { + // Below range + let result = decrease_liquidity_quote(1000000, 100, -20, -10, 10, None, None); + assert_eq!(result.liquidity_delta, 1000000); + assert_eq!(result.token_est_a, 1000); + assert_eq!(result.token_est_b, 0); + assert_eq!(result.token_min_a, 990); + assert_eq!(result.token_min_b, 0); + + // in range + let result = decrease_liquidity_quote(1000000, 100, 0, -10, 10, None, None); + assert_eq!(result.liquidity_delta, 1000000); + assert_eq!(result.token_est_a, 500); + assert_eq!(result.token_est_b, 500); + assert_eq!(result.token_min_a, 495); + assert_eq!(result.token_min_b, 495); + + // Above range + let result = decrease_liquidity_quote(1000000, 100, 20, -10, 10, None, None); + assert_eq!(result.liquidity_delta, 1000000); + assert_eq!(result.token_est_a, 0); + assert_eq!(result.token_est_b, 1000); + assert_eq!(result.token_min_a, 0); + assert_eq!(result.token_min_b, 990); + + // zero liquidity + let result = decrease_liquidity_quote(0, 100, 20, -10, 10, None, None); + assert_eq!(result.liquidity_delta, 0); + assert_eq!(result.token_est_a, 0); + assert_eq!(result.token_est_b, 0); + assert_eq!(result.token_min_a, 0); + assert_eq!(result.token_min_b, 0); + } + + #[test] + fn test_decrease_liquidity_quote_a() { + // Below range + let result = decrease_liquidity_quote_a(1000, 100, -20, -10, 10, None, None); + assert_eq!(result.liquidity_delta, 1000049); + assert_eq!(result.token_est_a, 1000); + assert_eq!(result.token_est_b, 0); + assert_eq!(result.token_min_a, 990); + assert_eq!(result.token_min_b, 0); + + // in range + let result = decrease_liquidity_quote_a(500, 100, 0, -10, 10, None, None); + assert_eq!(result.liquidity_delta, 1000300); + assert_eq!(result.token_est_a, 500); + assert_eq!(result.token_est_b, 500); + assert_eq!(result.token_min_a, 495); + assert_eq!(result.token_min_b, 495); + + // Above range + let result = decrease_liquidity_quote_a(1000, 100, 20, -10, 10, None, None); + assert_eq!(result.liquidity_delta, 0); + assert_eq!(result.token_est_a, 0); + assert_eq!(result.token_est_b, 0); + assert_eq!(result.token_min_a, 0); + assert_eq!(result.token_min_b, 0); + + // zero liquidity + let result = decrease_liquidity_quote_a(0, 100, 20, -10, 10, None, None); + assert_eq!(result.liquidity_delta, 0); + assert_eq!(result.token_est_a, 0); + assert_eq!(result.token_est_b, 0); + assert_eq!(result.token_min_a, 0); + assert_eq!(result.token_min_b, 0); + } + + #[test] + fn test_decrease_liquidity_quote_b() { + // Below range + let result = decrease_liquidity_quote_b(1000, 100, -20, -10, 10, None, None); + assert_eq!(result.liquidity_delta, 0); + assert_eq!(result.token_est_a, 0); + assert_eq!(result.token_est_b, 0); + assert_eq!(result.token_min_a, 0); + assert_eq!(result.token_min_b, 0); + + // in range + let result = decrease_liquidity_quote_b(500, 100, 0, -10, 10, None, None); + assert_eq!(result.liquidity_delta, 1000300); + assert_eq!(result.token_est_a, 500); + assert_eq!(result.token_est_b, 500); + assert_eq!(result.token_min_a, 495); + assert_eq!(result.token_min_b, 495); + + // Above range + let result = decrease_liquidity_quote_b(1000, 100, 20, -10, 10, None, None); + assert_eq!(result.liquidity_delta, 1000049); + assert_eq!(result.token_est_a, 0); + assert_eq!(result.token_est_b, 1000); + assert_eq!(result.token_min_a, 0); + assert_eq!(result.token_min_b, 990); + + // zero liquidity + let result = decrease_liquidity_quote_b(0, 100, 20, -10, 10, None, None); + assert_eq!(result.liquidity_delta, 0); + assert_eq!(result.token_est_a, 0); + assert_eq!(result.token_est_b, 0); + assert_eq!(result.token_min_a, 0); + assert_eq!(result.token_min_b, 0); + } + + #[test] + fn test_increase_liquidity_quote() { + // Below range + let result = increase_liquidity_quote(1000000, 100, -20, -10, 10, None, None); + assert_eq!(result.liquidity_delta, 1000000); + assert_eq!(result.token_est_a, 1000); + assert_eq!(result.token_est_b, 0); + assert_eq!(result.token_max_a, 1010); + assert_eq!(result.token_max_b, 0); + + // in range + let result = increase_liquidity_quote(1000000, 100, 0, -10, 10, None, None); + assert_eq!(result.liquidity_delta, 1000000); + assert_eq!(result.token_est_a, 500); + assert_eq!(result.token_est_b, 500); + assert_eq!(result.token_max_a, 505); + assert_eq!(result.token_max_b, 505); + + // Above range + let result = increase_liquidity_quote(1000000, 100, 20, -10, 10, None, None); + assert_eq!(result.liquidity_delta, 1000000); + assert_eq!(result.token_est_a, 0); + assert_eq!(result.token_est_b, 1000); + assert_eq!(result.token_max_a, 0); + assert_eq!(result.token_max_b, 1010); + + // zero liquidity + let result = increase_liquidity_quote(0, 100, 20, -10, 10, None, None); + assert_eq!(result.liquidity_delta, 0); + assert_eq!(result.token_est_a, 0); + assert_eq!(result.token_est_b, 0); + assert_eq!(result.token_max_a, 0); + assert_eq!(result.token_max_b, 0); + } + + #[test] + fn test_increase_liquidity_quote_a() { + // Below range + let result = increase_liquidity_quote_a(1000, 100, -20, -10, 10, None, None); + assert_eq!(result.liquidity_delta, 1000049); + assert_eq!(result.token_est_a, 1000); + assert_eq!(result.token_est_b, 0); + assert_eq!(result.token_max_a, 1010); + assert_eq!(result.token_max_b, 0); + + // in range + let result = increase_liquidity_quote_a(500, 100, 0, -10, 10, None, None); + assert_eq!(result.liquidity_delta, 1000300); + assert_eq!(result.token_est_a, 500); + assert_eq!(result.token_est_b, 500); + assert_eq!(result.token_max_a, 505); + assert_eq!(result.token_max_b, 505); + + // Above range + let result = increase_liquidity_quote_a(1000, 100, 20, -10, 10, None, None); + assert_eq!(result.liquidity_delta, 0); + assert_eq!(result.token_est_a, 0); + assert_eq!(result.token_est_b, 0); + assert_eq!(result.token_max_a, 0); + assert_eq!(result.token_max_b, 0); + + // zero liquidity + let result = increase_liquidity_quote_a(0, 100, 20, -10, 10, None, None); + assert_eq!(result.liquidity_delta, 0); + assert_eq!(result.token_est_a, 0); + assert_eq!(result.token_est_b, 0); + assert_eq!(result.token_max_a, 0); + assert_eq!(result.token_max_b, 0); + } + + #[test] + fn test_increase_liquidity_quote_b() { + // Below range + let result = increase_liquidity_quote_b(1000, 100, -20, -10, 10, None, None); + assert_eq!(result.liquidity_delta, 0); + assert_eq!(result.token_est_a, 0); + assert_eq!(result.token_est_b, 0); + assert_eq!(result.token_max_a, 0); + assert_eq!(result.token_max_b, 0); + + // in range + let result = increase_liquidity_quote_b(500, 100, 0, -10, 10, None, None); + assert_eq!(result.liquidity_delta, 1000300); + assert_eq!(result.token_est_a, 500); + assert_eq!(result.token_est_b, 500); + assert_eq!(result.token_max_a, 505); + assert_eq!(result.token_max_b, 505); + + // Above range + let result = increase_liquidity_quote_b(1000, 100, 20, -10, 10, None, None); + assert_eq!(result.liquidity_delta, 1000049); + assert_eq!(result.token_est_a, 0); + assert_eq!(result.token_est_b, 1000); + assert_eq!(result.token_max_a, 0); + assert_eq!(result.token_max_b, 1010); + + // zero liquidity + let result = increase_liquidity_quote_b(0, 100, 20, -10, 10, None, None); + assert_eq!(result.liquidity_delta, 0); + assert_eq!(result.token_est_a, 0); + assert_eq!(result.token_est_b, 0); + assert_eq!(result.token_max_a, 0); + assert_eq!(result.token_max_b, 0); + } + + #[test] + fn test_decrease_liquidity_quote_with_fee() { + // Below range + let result = decrease_liquidity_quote( + 1000000, + 100, + -20, + -10, + 10, + Some(TransferFee::new(2000)), + Some(TransferFee::new(1000)), + ); + assert_eq!(result.liquidity_delta, 1000000); + assert_eq!(result.token_est_a, 800); + assert_eq!(result.token_est_b, 0); + assert_eq!(result.token_min_a, 792); + assert_eq!(result.token_min_b, 0); + + // in range + let result = decrease_liquidity_quote( + 1000000, + 100, + 0, + -10, + 10, + Some(TransferFee::new(2000)), + Some(TransferFee::new(1000)), + ); + assert_eq!(result.liquidity_delta, 1000000); + assert_eq!(result.token_est_a, 400); + assert_eq!(result.token_est_b, 450); + assert_eq!(result.token_min_a, 396); + assert_eq!(result.token_min_b, 445); + + // Above range + let result = decrease_liquidity_quote( + 1000000, + 100, + 20, + -10, + 10, + Some(TransferFee::new(2000)), + Some(TransferFee::new(1000)), + ); + assert_eq!(result.liquidity_delta, 1000000); + assert_eq!(result.token_est_a, 0); + assert_eq!(result.token_est_b, 900); + assert_eq!(result.token_min_a, 0); + assert_eq!(result.token_min_b, 891); + + // zero liquidity + let result = decrease_liquidity_quote( + 0, + 100, + 20, + -10, + 10, + Some(TransferFee::new(2000)), + Some(TransferFee::new(1000)), + ); + assert_eq!(result.liquidity_delta, 0); + assert_eq!(result.token_est_a, 0); + assert_eq!(result.token_est_b, 0); + assert_eq!(result.token_min_a, 0); + assert_eq!(result.token_min_b, 0); + } + + #[test] + fn test_decrease_liquidity_quote_a_with_fee() { + // Below range + let result = decrease_liquidity_quote_a( + 1000, + 100, + -20, + -10, + 10, + Some(TransferFee::new(2000)), + Some(TransferFee::new(1000)), + ); + assert_eq!(result.liquidity_delta, 1250062); + assert_eq!(result.token_est_a, 1000); + assert_eq!(result.token_est_b, 0); + assert_eq!(result.token_min_a, 989); + assert_eq!(result.token_min_b, 0); + + // in range + let result = decrease_liquidity_quote_a( + 500, + 100, + 0, + -10, + 10, + Some(TransferFee::new(2000)), + Some(TransferFee::new(1000)), + ); + assert_eq!(result.liquidity_delta, 1250375); + assert_eq!(result.token_est_a, 500); + assert_eq!(result.token_est_b, 562); + assert_eq!(result.token_min_a, 494); + assert_eq!(result.token_min_b, 556); + + // Above range + let result = decrease_liquidity_quote_a( + 1000, + 100, + 20, + -10, + 10, + Some(TransferFee::new(2000)), + Some(TransferFee::new(1000)), + ); + assert_eq!(result.liquidity_delta, 0); + assert_eq!(result.token_est_a, 0); + assert_eq!(result.token_est_b, 0); + assert_eq!(result.token_min_a, 0); + assert_eq!(result.token_min_b, 0); + + // zero liquidity + let result = decrease_liquidity_quote_a( + 0, + 100, + 20, + -10, + 10, + Some(TransferFee::new(2000)), + Some(TransferFee::new(1000)), + ); + assert_eq!(result.liquidity_delta, 0); + assert_eq!(result.token_est_a, 0); + assert_eq!(result.token_est_b, 0); + assert_eq!(result.token_min_a, 0); + assert_eq!(result.token_min_b, 0); + } + + #[test] + fn test_decrease_liquidity_quote_b_with_fee() { + // Below range + let result = decrease_liquidity_quote_b( + 1000, + 100, + -20, + -10, + 10, + Some(TransferFee::new(2000)), + Some(TransferFee::new(1000)), + ); + assert_eq!(result.liquidity_delta, 0); + assert_eq!(result.token_est_a, 0); + assert_eq!(result.token_est_b, 0); + assert_eq!(result.token_min_a, 0); + assert_eq!(result.token_min_b, 0); + + // in range + let result = decrease_liquidity_quote_b( + 500, + 100, + 0, + -10, + 10, + Some(TransferFee::new(2000)), + Some(TransferFee::new(1000)), + ); + assert_eq!(result.liquidity_delta, 1112333); + assert_eq!(result.token_est_a, 444); + assert_eq!(result.token_est_b, 500); + assert_eq!(result.token_min_a, 440); + assert_eq!(result.token_min_b, 495); + + // Above range + let result = decrease_liquidity_quote_b( + 1000, + 100, + 20, + -10, + 10, + Some(TransferFee::new(2000)), + Some(TransferFee::new(1000)), + ); + assert_eq!(result.liquidity_delta, 1112055); + assert_eq!(result.token_est_a, 0); + assert_eq!(result.token_est_b, 1000); + assert_eq!(result.token_min_a, 0); + assert_eq!(result.token_min_b, 990); + + // zero liquidity + let result = decrease_liquidity_quote_b( + 0, + 100, + 20, + -10, + 10, + Some(TransferFee::new(2000)), + Some(TransferFee::new(1000)), + ); + assert_eq!(result.liquidity_delta, 0); + assert_eq!(result.token_est_a, 0); + assert_eq!(result.token_est_b, 0); + assert_eq!(result.token_min_a, 0); + assert_eq!(result.token_min_b, 0); + } + + #[test] + fn test_increase_liquidity_quote_with_fee() { + // Below range + let result = increase_liquidity_quote( + 1000000, + 100, + -20, + -10, + 10, + Some(TransferFee::new(2000)), + Some(TransferFee::new(1000)), + ); + assert_eq!(result.liquidity_delta, 1000000); + assert_eq!(result.token_est_a, 1200); + assert_eq!(result.token_est_b, 0); + assert_eq!(result.token_max_a, 1212); + assert_eq!(result.token_max_b, 0); + + // in range + let result = increase_liquidity_quote( + 1000000, + 100, + 0, + -10, + 10, + Some(TransferFee::new(2000)), + Some(TransferFee::new(1000)), + ); + assert_eq!(result.liquidity_delta, 1000000); + assert_eq!(result.token_est_a, 600); + assert_eq!(result.token_est_b, 550); + assert_eq!(result.token_max_a, 606); + assert_eq!(result.token_max_b, 556); + + // Above range + let result = increase_liquidity_quote( + 1000000, + 100, + 20, + -10, + 10, + Some(TransferFee::new(2000)), + Some(TransferFee::new(1000)), + ); + assert_eq!(result.liquidity_delta, 1000000); + assert_eq!(result.token_est_a, 0); + assert_eq!(result.token_est_b, 1100); + assert_eq!(result.token_max_a, 0); + assert_eq!(result.token_max_b, 1111); + + // zero liquidity + let result = increase_liquidity_quote( + 0, + 100, + 20, + -10, + 10, + Some(TransferFee::new(2000)), + Some(TransferFee::new(1000)), + ); + assert_eq!(result.liquidity_delta, 0); + assert_eq!(result.token_est_a, 0); + assert_eq!(result.token_est_b, 0); + assert_eq!(result.token_max_a, 0); + assert_eq!(result.token_max_b, 0); + } + + #[test] + fn test_increase_liquidity_quote_a_with_fee() { + // Below range + let result = increase_liquidity_quote_a( + 1000, + 100, + -20, + -10, + 10, + Some(TransferFee::new(2000)), + Some(TransferFee::new(1000)), + ); + assert_eq!(result.liquidity_delta, 800039); + assert_eq!(result.token_est_a, 1000); + assert_eq!(result.token_est_b, 0); + assert_eq!(result.token_max_a, 1010); + assert_eq!(result.token_max_b, 0); + + // in range + let result = increase_liquidity_quote_a( + 500, + 100, + 0, + -10, + 10, + Some(TransferFee::new(2000)), + Some(TransferFee::new(1000)), + ); + assert_eq!(result.liquidity_delta, 800240); + assert_eq!(result.token_est_a, 500); + assert_eq!(result.token_est_b, 445); + assert_eq!(result.token_max_a, 505); + assert_eq!(result.token_max_b, 449); + + // Above range + let result = increase_liquidity_quote_a( + 1000, + 100, + 20, + -10, + 10, + Some(TransferFee::new(2000)), + Some(TransferFee::new(1000)), + ); + assert_eq!(result.liquidity_delta, 0); + assert_eq!(result.token_est_a, 0); + assert_eq!(result.token_est_b, 0); + assert_eq!(result.token_max_a, 0); + assert_eq!(result.token_max_b, 0); + + // zero liquidity + let result = increase_liquidity_quote_a( + 0, + 100, + 20, + -10, + 10, + Some(TransferFee::new(2000)), + Some(TransferFee::new(1000)), + ); + assert_eq!(result.liquidity_delta, 0); + assert_eq!(result.token_est_a, 0); + assert_eq!(result.token_est_b, 0); + assert_eq!(result.token_max_a, 0); + assert_eq!(result.token_max_b, 0); + } + + #[test] + fn test_increase_liquidity_quote_b_with_fee() { + // Below range + let result = increase_liquidity_quote_b( + 1000, + 100, + -20, + -10, + 10, + Some(TransferFee::new(2000)), + Some(TransferFee::new(1000)), + ); + assert_eq!(result.liquidity_delta, 0); + assert_eq!(result.token_est_a, 0); + assert_eq!(result.token_est_b, 0); + assert_eq!(result.token_max_a, 0); + assert_eq!(result.token_max_b, 0); + + // in range + let result = increase_liquidity_quote_b( + 500, + 100, + 0, + -10, + 10, + Some(TransferFee::new(2000)), + Some(TransferFee::new(1000)), + ); + assert_eq!(result.liquidity_delta, 900270); + assert_eq!(result.token_est_a, 563); + assert_eq!(result.token_est_b, 500); + assert_eq!(result.token_max_a, 569); + assert_eq!(result.token_max_b, 506); + + // Above range + let result = increase_liquidity_quote_b( + 1000, + 100, + 20, + -10, + 10, + Some(TransferFee::new(2000)), + Some(TransferFee::new(1000)), + ); + assert_eq!(result.liquidity_delta, 900044); + assert_eq!(result.token_est_a, 0); + assert_eq!(result.token_est_b, 1000); + assert_eq!(result.token_max_a, 0); + assert_eq!(result.token_max_b, 1010); + + // zero liquidity + let result = increase_liquidity_quote_b( + 0, + 100, + 20, + -10, + 10, + Some(TransferFee::new(2000)), + Some(TransferFee::new(1000)), + ); + assert_eq!(result.liquidity_delta, 0); + assert_eq!(result.token_est_a, 0); + assert_eq!(result.token_est_b, 0); + assert_eq!(result.token_max_a, 0); + assert_eq!(result.token_max_b, 0); + } +} diff --git a/rust-sdk/core/src/quote/mod.rs b/rust-sdk/core/src/quote/mod.rs new file mode 100644 index 000000000..825594d31 --- /dev/null +++ b/rust-sdk/core/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/core/src/quote/rewards.rs b/rust-sdk/core/src/quote/rewards.rs new file mode 100644 index 000000000..eaa52205a --- /dev/null +++ b/rust-sdk/core/src/quote/rewards.rs @@ -0,0 +1,302 @@ +use core::ops::{Shl, Shr}; + +use ethnum::U256; + +#[cfg(feature = "wasm")] +use wasm_bindgen::prelude::*; + +use crate::{adjust_amount, CollectRewardsQuote, Position, Tick, TransferFee, Whirlpool}; + +/// Calculate rewards owed for a position +/// +/// # Paramters +/// - `whirlpool`: The whirlpool state +/// - `position`: The position state +/// - `tick_lower`: The lower tick state +/// - `tick_upper`: The upper tick state +/// - `current_timestamp`: The current timestamp +/// - `transfer_fee_1`: The transfer fee for token 1 +/// - `transfer_fee_2`: The transfer fee for token 2 +/// - `transfer_fee_3`: The transfer fee for token 3 +/// +/// # 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( + whirlpool: Whirlpool, + position: Position, + tick_lower: Tick, + tick_upper: Tick, + current_timestamp: u64, + transfer_fee_1: Option, + transfer_fee_2: Option, + transfer_fee_3: Option, +) -> CollectRewardsQuote { + let timestamp_delta = current_timestamp - whirlpool.reward_last_updated_timestamp; + + let mut reward_growth_1: u128 = whirlpool.reward_infos[0].growth_global_x64; + let mut reward_growth_2: u128 = whirlpool.reward_infos[1].growth_global_x64; + let mut reward_growth_3: u128 = whirlpool.reward_infos[2].growth_global_x64; + + if whirlpool.liquidity != 0 { + let reward_growth_delta_1 = whirlpool.reward_infos[0] + .emissions_per_second_x64 + .saturating_mul(timestamp_delta as u128) + .saturating_div(whirlpool.liquidity); + reward_growth_1 += ::try_from(reward_growth_delta_1).unwrap(); + + let reward_growth_delta_2 = whirlpool.reward_infos[1] + .emissions_per_second_x64 + .saturating_mul(timestamp_delta as u128) + .saturating_div(whirlpool.liquidity); + reward_growth_2 += ::try_from(reward_growth_delta_2).unwrap(); + + let reward_growth_delta_3 = whirlpool.reward_infos[2] + .emissions_per_second_x64 + .saturating_mul(timestamp_delta as u128) + .saturating_div(whirlpool.liquidity); + reward_growth_3 += ::try_from(reward_growth_delta_3).unwrap(); + } + + let mut reward_growth_below_1: u128 = tick_lower.reward_growths_outside[0]; + let mut reward_growth_below_2: u128 = tick_lower.reward_growths_outside[1]; + let mut reward_growth_below_3: u128 = tick_lower.reward_growths_outside[2]; + + let mut reward_growth_above_1: u128 = tick_upper.reward_growths_outside[0]; + let mut reward_growth_above_2: u128 = tick_upper.reward_growths_outside[1]; + let mut reward_growth_above_3: u128 = tick_upper.reward_growths_outside[2]; + + if whirlpool.tick_current_index < position.tick_lower_index { + reward_growth_below_1 = reward_growth_1.saturating_sub(reward_growth_below_1); + reward_growth_below_2 = reward_growth_2.saturating_sub(reward_growth_below_2); + reward_growth_below_3 = reward_growth_3.saturating_sub(reward_growth_below_3); + } + + if whirlpool.tick_current_index >= position.tick_upper_index { + reward_growth_above_1 = reward_growth_1.saturating_sub(reward_growth_above_1); + reward_growth_above_2 = reward_growth_2.saturating_sub(reward_growth_above_2); + reward_growth_above_3 = reward_growth_3.saturating_sub(reward_growth_above_3); + } + + let reward_growth_inside_1 = reward_growth_1 + .saturating_sub(reward_growth_below_1) + .saturating_sub(reward_growth_above_1); + + let reward_growth_inside_2 = reward_growth_2 + .saturating_sub(reward_growth_below_2) + .saturating_sub(reward_growth_above_2); + + let reward_growth_inside_3 = reward_growth_3 + .saturating_sub(reward_growth_below_3) + .saturating_sub(reward_growth_above_3); + + let reward_growth_delta_1: U256 = ::from(reward_growth_inside_1) + .saturating_sub(position.reward_infos[0].growth_inside_checkpoint.into()) + .saturating_mul(position.liquidity.into()) + .shl(64); + + let reward_growth_delta_2: U256 = ::from(reward_growth_inside_2) + .saturating_sub(position.reward_infos[1].growth_inside_checkpoint.into()) + .saturating_mul(position.liquidity.into()) + .shl(64); + + let reward_growth_delta_3: U256 = ::from(reward_growth_inside_3) + .saturating_sub(position.reward_infos[2].growth_inside_checkpoint.into()) + .saturating_mul(position.liquidity.into()) + .shl(64); + + let reward_growth_delta_1: u128 = reward_growth_delta_1.try_into().unwrap(); + let reward_growth_delta_2: u128 = reward_growth_delta_2.try_into().unwrap(); + let reward_growth_delta_3: u128 = reward_growth_delta_3.try_into().unwrap(); + + let amount_owed_1: u128 = position.reward_infos[0].amount_owed.into(); + let amount_owed_2: u128 = position.reward_infos[1].amount_owed.into(); + let amount_owed_3: u128 = position.reward_infos[2].amount_owed.into(); + + let amount_owed_1_shifted: u128 = amount_owed_1.shl(64); + let amount_owed_2_shifted: u128 = amount_owed_2.shl(64); + let amount_owed_3_shifted: u128 = amount_owed_3.shl(64); + + let withdrawable_reward_1: u128 = (amount_owed_1_shifted + reward_growth_delta_1).shr(64); + let withdrawable_reward_2: u128 = (amount_owed_2_shifted + reward_growth_delta_2).shr(64); + let withdrawable_reward_3: u128 = (amount_owed_3_shifted + reward_growth_delta_3).shr(64); + + let reward_owed_1 = adjust_amount(withdrawable_reward_1.into(), transfer_fee_1.into(), false); + let reward_owed_2 = adjust_amount(withdrawable_reward_2.into(), transfer_fee_2.into(), false); + let reward_owed_3 = adjust_amount(withdrawable_reward_3.into(), transfer_fee_3.into(), false); + + CollectRewardsQuote { + reward_owed_1: reward_owed_1.into(), + reward_owed_2: reward_owed_2.into(), + reward_owed_3: reward_owed_3.into(), + } +} + +#[cfg(all(test, not(feature = "wasm")))] +mod tests { + use crate::{PositionRewardInfo, WhirlpoolRewardInfo}; + + use super::*; + + fn test_whirlpool(tick_current_index: i32) -> Whirlpool { + Whirlpool { + tick_current_index, + reward_last_updated_timestamp: 0, + reward_infos: [ + WhirlpoolRewardInfo { + growth_global_x64: 500, + emissions_per_second_x64: 1, + }, + WhirlpoolRewardInfo { + growth_global_x64: 600, + emissions_per_second_x64: 2, + }, + WhirlpoolRewardInfo { + growth_global_x64: 700, + emissions_per_second_x64: 3, + }, + ], + liquidity: 50, + ..Whirlpool::default() + } + } + + fn test_position() -> Position { + Position { + liquidity: 50, + tick_lower_index: 5, + tick_upper_index: 10, + reward_infos: [ + PositionRewardInfo { + growth_inside_checkpoint: 100, + amount_owed: 100, + }, + PositionRewardInfo { + growth_inside_checkpoint: 200, + amount_owed: 200, + }, + PositionRewardInfo { + growth_inside_checkpoint: 300, + amount_owed: 300, + }, + ], + ..Position::default() + } + } + + fn test_tick() -> Tick { + Tick { + reward_growths_outside: [10, 20, 30], + ..Tick::default() + } + } + + #[test] + fn test_collect_rewards_below_range() { + let quote = collect_rewards_quote( + test_whirlpool(0), + test_position(), + test_tick(), + test_tick(), + 10, + None, + None, + None, + ); + + assert_eq!(quote.reward_owed_1, 100); + assert_eq!(quote.reward_owed_2, 200); + assert_eq!(quote.reward_owed_3, 300); + } + + #[test] + fn test_collect_rewards_in_range() { + let quote = collect_rewards_quote( + test_whirlpool(7), + test_position(), + test_tick(), + test_tick(), + 10, + None, + None, + None, + ); + + assert_eq!(quote.reward_owed_1, 19100); + assert_eq!(quote.reward_owed_2, 18200); + assert_eq!(quote.reward_owed_3, 17300); + } + + #[test] + fn test_collect_rewards_above_range() { + let quote = collect_rewards_quote( + test_whirlpool(15), + test_position(), + test_tick(), + test_tick(), + 10, + None, + None, + None, + ); + + assert_eq!(quote.reward_owed_1, 100); + assert_eq!(quote.reward_owed_2, 200); + assert_eq!(quote.reward_owed_3, 300); + } + + #[test] + fn test_collect_rewards_on_range_lower() { + let quote = collect_rewards_quote( + test_whirlpool(5), + test_position(), + test_tick(), + test_tick(), + 10, + None, + None, + None, + ); + + assert_eq!(quote.reward_owed_1, 19100); + assert_eq!(quote.reward_owed_2, 18200); + assert_eq!(quote.reward_owed_3, 17300); + } + + #[test] + fn test_collect_rewards_on_range_upper() { + let quote = collect_rewards_quote( + test_whirlpool(10), + test_position(), + test_tick(), + test_tick(), + 10, + None, + None, + None, + ); + + assert_eq!(quote.reward_owed_1, 100); + assert_eq!(quote.reward_owed_2, 200); + assert_eq!(quote.reward_owed_3, 300); + } + + #[test] + fn test_transfer_fee() { + let quote = collect_rewards_quote( + test_whirlpool(7), + test_position(), + test_tick(), + test_tick(), + 10, + Some(TransferFee::new(1000)), + Some(TransferFee::new(2000)), + Some(TransferFee::new(3000)), + ); + + assert_eq!(quote.reward_owed_1, 17190); + assert_eq!(quote.reward_owed_2, 14740); + assert_eq!(quote.reward_owed_3, 12110); + } +} diff --git a/rust-sdk/core/src/quote/swap.rs b/rust-sdk/core/src/quote/swap.rs new file mode 100644 index 000000000..01fa860f7 --- /dev/null +++ b/rust-sdk/core/src/quote/swap.rs @@ -0,0 +1,647 @@ +use core::cmp::{max, min}; + +use crate::{ + adjust_amount, get_amount_delta_a, get_amount_delta_b, get_next_sqrt_price_from_a, + get_next_sqrt_price_from_b, inverse_adjust_amount, sqrt_price_to_tick_index, + tick_index_to_sqrt_price, AdjustmentType, ExactInSwapQuote, ExactOutSwapQuote, Tick, TickArray, + TickArraySequence, TransferFee, Whirlpool, U128, +}; + +#[cfg(feature = "wasm")] +use wasm_bindgen::prelude::*; + +const MIN_SQRT_PRICE: u128 = 4295048016; +const MAX_SQRT_PRICE: u128 = 79226673515401279992447579055; + +/// Computes the exact input or output amount for a swap transaction. +/// +/// # Arguments +/// - `token_in`: The input token amount. +/// - `specified_token_a`: If `true`, the input token is token A. Otherwise, it is token B. +/// - `slippage_tolerance`: The slippage tolerance in basis points. +/// - `whirlpool`: The whirlpool state. +/// - `tick_array_1`: The first tick array. +/// - `tick_array_2`: The second tick array. +/// - `tick_array_3`: The third tick array. +/// - `transfer_fee_a`: The transfer fee for token A. +/// - `transfer_fee_b`: The transfer fee for token B. +/// +/// # Returns +/// The exact input or output amount for the swap transaction. +#[allow(clippy::too_many_arguments)] +#[cfg_attr(feature = "wasm", wasm_bindgen(js_name = swapQuoteByInputToken, skip_jsdoc))] +pub fn swap_quote_by_input_token( + token_in: U128, + specified_token_a: bool, + slippage_tolerance: u16, + whirlpool: Whirlpool, + tick_array_1: TickArray, + tick_array_2: TickArray, + tick_array_3: TickArray, + transfer_fee_a: Option, + transfer_fee_b: Option, +) -> ExactInSwapQuote { + let (transfer_fee_in, transfer_fee_out) = if specified_token_a { + (transfer_fee_b, transfer_fee_a) + } else { + (transfer_fee_a, transfer_fee_b) + }; + let token_in_after_fee = adjust_amount(token_in.into(), transfer_fee_in.into(), false); + + let tick_sequence = TickArraySequence::new( + tick_array_1, + tick_array_2, + tick_array_3, + whirlpool.tick_spacing, + ); + + let swap_result = compute_swap( + token_in_after_fee.into(), + whirlpool, + tick_sequence, + specified_token_a, + true, + ); + + let (token_in_after_fees, token_est_out_before_fee) = if specified_token_a { + (swap_result.token_a, swap_result.token_b) + } else { + (swap_result.token_b, swap_result.token_a) + }; + + let token_min_out_before_fee = adjust_amount( + token_est_out_before_fee.into(), + AdjustmentType::Slippage(slippage_tolerance), + false, + ); + + let token_in = inverse_adjust_amount(token_in_after_fees.into(), transfer_fee_in.into(), false); + let token_est_out = adjust_amount( + token_est_out_before_fee.into(), + transfer_fee_out.into(), + false, + ); + let token_min_out = adjust_amount( + token_min_out_before_fee.into(), + transfer_fee_out.into(), + false, + ); + + ExactInSwapQuote { + token_in: token_in.into(), + token_est_out: token_est_out.into(), + token_min_out: token_min_out.into(), + total_fee: swap_result.total_fee, + } +} + +/// Computes the exact input or output amount for a swap transaction. +/// +/// # Arguments +/// - `token_out`: The output token amount. +/// - `specified_token_a`: If `true`, the output token is token A. Otherwise, it is token B. +/// - `slippage_tolerance`: The slippage tolerance in basis points. +/// - `whirlpool`: The whirlpool state. +/// - `tick_array_1`: The first tick array. +/// - `tick_array_2`: The second tick array. +/// - `tick_array_3`: The third tick array. +/// - `transfer_fee_a`: The transfer fee for token A. +/// - `transfer_fee_b`: The transfer fee for token B. +/// +/// # Returns +/// The exact input or output amount for the swap transaction. +#[allow(clippy::too_many_arguments)] +#[cfg_attr(feature = "wasm", wasm_bindgen(js_name = swapQuoteByOutputToken, skip_jsdoc))] +pub fn swap_quote_by_output_token( + token_out: U128, + specified_token_a: bool, + slippage_tolerance: u16, + whirlpool: Whirlpool, + tick_array_1: TickArray, + tick_array_2: TickArray, + tick_array_3: TickArray, + transfer_fee_a: Option, + transfer_fee_b: Option, +) -> ExactOutSwapQuote { + let (transfer_fee_in, transfer_fee_out) = if specified_token_a { + (transfer_fee_b, transfer_fee_a) + } else { + (transfer_fee_a, transfer_fee_b) + }; + let token_out_before_fee = + inverse_adjust_amount(token_out.into(), transfer_fee_out.into(), false); + + let tick_sequence = TickArraySequence::new( + tick_array_1, + tick_array_2, + tick_array_3, + whirlpool.tick_spacing, + ); + + let swap_result = compute_swap( + token_out_before_fee.into(), + whirlpool, + tick_sequence, + !specified_token_a, + false, + ); + + let (token_out_before_fee, token_est_in_after_fee) = if specified_token_a { + (swap_result.token_a, swap_result.token_b) + } else { + (swap_result.token_b, swap_result.token_a) + }; + + let token_max_in_after_fee = adjust_amount( + token_est_in_after_fee.into(), + crate::AdjustmentType::Slippage(slippage_tolerance), + true, + ); + + let token_est_in = + inverse_adjust_amount(token_est_in_after_fee.into(), transfer_fee_in.into(), false); + let token_max_in = + inverse_adjust_amount(token_max_in_after_fee.into(), transfer_fee_in.into(), false); + let token_out = adjust_amount(token_out_before_fee.into(), transfer_fee_out.into(), false); + + ExactOutSwapQuote { + token_out: token_out.into(), + token_est_in: token_est_in.into(), + token_max_in: token_max_in.into(), + total_fee: swap_result.total_fee, + } +} + +// Private functions + +struct SwapResult { + token_a: u128, + token_b: u128, + total_fee: u128, +} + +fn compute_swap( + token_amount: u128, + whirlpool: Whirlpool, + tick_sequence: TickArraySequence, + a_to_b: bool, + specified_input: bool, +) -> SwapResult { + let mut amount_remaining = token_amount; + let mut amount_calculated = 0u128; + let mut current_sqrt_price = whirlpool.sqrt_price; + let mut current_tick_index = whirlpool.tick_current_index; + let mut current_liquidity = whirlpool.liquidity; + let mut total_fee = 0u128; + + while amount_remaining > 0 + && current_sqrt_price > MIN_SQRT_PRICE + && current_sqrt_price < MAX_SQRT_PRICE + { + let (next_tick, next_tick_index) = if a_to_b { + tick_sequence.next_initialized_tick(current_tick_index) + } else { + tick_sequence.prev_initialized_tick(current_tick_index) + }; + let next_tick_sqrt_price: u128 = tick_index_to_sqrt_price(next_tick_index.into()).into(); + let target_sqrt_price = if a_to_b { + max(next_tick_sqrt_price, MIN_SQRT_PRICE) + } else { + min(next_tick_sqrt_price, MAX_SQRT_PRICE) + }; + + let step_quote = compute_swap_step( + amount_remaining, + whirlpool.fee_rate, + current_liquidity, + current_sqrt_price, + target_sqrt_price, + a_to_b, + specified_input, + ); + + total_fee += step_quote.fee_amount; + + if specified_input { + amount_remaining -= step_quote.amount_in + step_quote.fee_amount; + amount_calculated += step_quote.amount_out; + } else { + amount_remaining -= step_quote.amount_out; + amount_calculated += step_quote.amount_in + step_quote.fee_amount; + } + + if step_quote.next_sqrt_price == next_tick_sqrt_price { + current_liquidity = get_next_liquidity(current_liquidity, next_tick, a_to_b); + current_tick_index = next_tick_index; + } else { + current_tick_index = sqrt_price_to_tick_index(step_quote.next_sqrt_price.into()).into(); + } + + current_sqrt_price = step_quote.next_sqrt_price; + } + + let swapped_amount = token_amount - amount_remaining; + let token_a = if a_to_b == specified_input { + swapped_amount + } else { + amount_calculated + }; + let token_b = if a_to_b == specified_input { + amount_calculated + } else { + swapped_amount + }; + + SwapResult { + token_a, + token_b, + total_fee, + } +} + +fn get_next_liquidity(current_liquidity: u128, next_tick: &Tick, a_to_b: bool) -> u128 { + let liquidity_net = next_tick.liquidity_net; + let liquidity_net_unsigned = liquidity_net.unsigned_abs(); + if a_to_b { + if liquidity_net < 0 { + current_liquidity + liquidity_net_unsigned + } else { + current_liquidity - liquidity_net_unsigned + } + } else if liquidity_net < 0 { + current_liquidity - liquidity_net_unsigned + } else { + current_liquidity + liquidity_net_unsigned + } +} + +struct SwapStepQuote { + amount_in: u128, + amount_out: u128, + next_sqrt_price: u128, + fee_amount: u128, +} + +fn compute_swap_step( + amount_remaining: u128, + fee_rate: u16, + current_liquidity: u128, + current_sqrt_price: u128, + target_sqrt_price: u128, + a_to_b: bool, + specified_input: bool, +) -> SwapStepQuote { + let mut amount_fixed_delta = get_amount_fixed_delta( + current_sqrt_price, + target_sqrt_price, + current_liquidity, + a_to_b, + specified_input, + ); + + let amount_calculated: u128 = if specified_input { + adjust_amount( + amount_remaining.into(), + AdjustmentType::SwapFee(fee_rate), + false, + ) + .into() + } else { + amount_remaining + }; + + let next_sqrt_price = if amount_calculated >= amount_fixed_delta { + target_sqrt_price + } else { + get_next_sqrt_price( + current_sqrt_price, + current_liquidity, + amount_calculated, + a_to_b, + specified_input, + ) + }; + + let is_max_swap = next_sqrt_price == target_sqrt_price; + + let amount_unfixed_delta = get_amount_unfixed_delta( + current_sqrt_price, + next_sqrt_price, + current_liquidity, + a_to_b, + specified_input, + ); + + // If the swap is not at the max, we need to readjust the amount of the fixed token we are using + if !is_max_swap { + amount_fixed_delta = get_amount_fixed_delta( + current_sqrt_price, + next_sqrt_price, + current_liquidity, + a_to_b, + specified_input, + ); + }; + + let (amount_in, mut amount_out) = if specified_input { + (amount_fixed_delta, amount_unfixed_delta) + } else { + (amount_unfixed_delta, amount_fixed_delta) + }; + + // Cap output amount if using output + if !specified_input && amount_out > amount_remaining { + amount_out = amount_remaining; + } + + let fee_amount: u128 = if specified_input && !is_max_swap { + amount_remaining - amount_in + } else { + let pre_fee_amount: u128 = + inverse_adjust_amount(amount_in.into(), AdjustmentType::SwapFee(fee_rate), false) + .into(); + pre_fee_amount - amount_in + }; + + SwapStepQuote { + amount_in, + amount_out, + next_sqrt_price, + fee_amount, + } +} + +fn get_amount_fixed_delta( + current_sqrt_price: u128, + target_sqrt_price: u128, + current_liquidity: u128, + a_to_b: bool, + specified_input: bool, +) -> u128 { + if a_to_b == specified_input { + get_amount_delta_a( + current_sqrt_price.into(), + target_sqrt_price.into(), + current_liquidity.into(), + specified_input, + ) + .into() + } else { + get_amount_delta_b( + current_sqrt_price.into(), + target_sqrt_price.into(), + current_liquidity.into(), + specified_input, + ) + .into() + } +} + +fn get_amount_unfixed_delta( + current_sqrt_price: u128, + target_sqrt_price: u128, + current_liquidity: u128, + a_to_b: bool, + specified_input: bool, +) -> u128 { + if specified_input == a_to_b { + get_amount_delta_b( + current_sqrt_price.into(), + target_sqrt_price.into(), + current_liquidity.into(), + !specified_input, + ) + .into() + } else { + get_amount_delta_a( + current_sqrt_price.into(), + target_sqrt_price.into(), + current_liquidity.into(), + !specified_input, + ) + .into() + } +} + +fn get_next_sqrt_price( + current_sqrt_price: u128, + current_liquidity: u128, + amount_calculated: u128, + a_to_b: bool, + specified_input: bool, +) -> u128 { + if specified_input == a_to_b { + get_next_sqrt_price_from_a( + current_sqrt_price.into(), + current_liquidity.into(), + amount_calculated.into(), + specified_input, + ) + .into() + } else { + get_next_sqrt_price_from_b( + current_sqrt_price.into(), + current_liquidity.into(), + amount_calculated.into(), + specified_input, + ) + .into() + } +} + +#[cfg(all(test, not(feature = "wasm")))] +mod tests { + use crate::TICK_ARRAY_SIZE; + + use super::*; + + fn test_whirlpool(sqrt_price: u128, sufficient_liq: bool) -> Whirlpool { + let tick_current_index = sqrt_price_to_tick_index(sqrt_price); + let liquidity = if sufficient_liq { 100000000 } else { 100000 }; + Whirlpool { + tick_current_index, + fee_rate: 3000, + liquidity, + sqrt_price, + tick_spacing: 2, + ..Whirlpool::default() + } + } + + fn test_tick(positive: bool) -> Tick { + let liquidity_net = if positive { 1000 } else { -1000 }; + Tick { + initialized: true, + liquidity_net, + ..Tick::default() + } + } + + fn test_tick_array(start_tick_index: i32) -> TickArray { + let positive_liq_net = start_tick_index < 0; + TickArray { + start_tick_index, + ticks: [test_tick(positive_liq_net); TICK_ARRAY_SIZE], + } + } + + #[test] + fn test_exact_in_a_to_b_simple() { + let result = swap_quote_by_input_token( + 1000, + true, + 1000, + test_whirlpool(1 << 64, true), + test_tick_array(0), + test_tick_array(176), + test_tick_array(352), + None, + None, + ); + assert_eq!(result.token_in, 1000); + assert_eq!(result.token_est_out, 996); + assert_eq!(result.token_min_out, 896); + assert_eq!(result.total_fee, 3); + } + + #[test] + fn test_exact_in_a_to_b() { + let result = swap_quote_by_input_token( + 1000, + true, + 1000, + test_whirlpool(1 << 64, false), + test_tick_array(0), + test_tick_array(176), + test_tick_array(352), + None, + None, + ); + assert_eq!(result.token_in, 1000); + assert_eq!(result.token_est_out, 871); + assert_eq!(result.token_min_out, 783); + assert_eq!(result.total_fee, 68); + } + + #[test] + fn test_exact_in_b_to_a_simple() { + let result = swap_quote_by_input_token( + 1000, + false, + 1000, + test_whirlpool(1 << 64, true), + test_tick_array(-176), + test_tick_array(0), + test_tick_array(176), + None, + None, + ); + + assert_eq!(result.token_in, 1000); + assert_eq!(result.token_est_out, 996); + assert_eq!(result.token_min_out, 896); + assert_eq!(result.total_fee, 3); + } + + #[test] + fn test_exact_in_b_to_a() { + let result = swap_quote_by_input_token( + 1000, + false, + 1000, + test_whirlpool(1 << 64, false), + test_tick_array(-176), + test_tick_array(0), + test_tick_array(176), + None, + None, + ); + + assert_eq!(result.token_in, 1000); + assert_eq!(result.token_est_out, 872); + assert_eq!(result.token_min_out, 784); + assert_eq!(result.total_fee, 68); + } + + #[test] + fn test_exact_out_a_to_b_simple() { + let result = swap_quote_by_output_token( + 1000, + false, + 1000, + test_whirlpool(1 << 64, true), + test_tick_array(-176), + test_tick_array(0), + test_tick_array(176), + None, + None, + ); + // FIXME: still has a round up issue somewhere + assert_eq!(result.token_out, 1000); + assert_eq!(result.token_est_in, 1005); + assert_eq!(result.token_max_in, 1106); + assert_eq!(result.total_fee, 4); + } + + #[test] + fn test_exact_out_a_to_b() { + let result = swap_quote_by_output_token( + 1000, + false, + 1000, + test_whirlpool(1 << 64, false), + test_tick_array(-176), + test_tick_array(0), + test_tick_array(176), + None, + None, + ); + // FIXME: still has a round up issue somewhere + assert_eq!(result.token_out, 1000); + assert_eq!(result.token_est_in, 1142); + assert_eq!(result.token_max_in, 1257); + assert_eq!(result.total_fee, 76); + } + + #[test] + fn test_exact_out_b_to_a_simple() { + let result = swap_quote_by_output_token( + 1000, + true, + 1000, + test_whirlpool(1 << 64, true), + test_tick_array(-176), + test_tick_array(0), + test_tick_array(176), + None, + None, + ); + assert_eq!(result.token_out, 1000); + assert_eq!(result.token_est_in, 1005); + assert_eq!(result.token_max_in, 1106); + assert_eq!(result.total_fee, 4); + } + + #[test] + fn test_exact_out_b_to_a() { + let result = swap_quote_by_output_token( + 1000, + true, + 1000, + test_whirlpool(1 << 64, false), + test_tick_array(-176), + test_tick_array(0), + test_tick_array(176), + None, + None, + ); + assert_eq!(result.token_out, 1000); + assert_eq!(result.token_est_in, 1141); + assert_eq!(result.token_max_in, 1256); + assert_eq!(result.total_fee, 76); + } + + // TODO: add more complex tests that + // * only fill partially + // * transfer fee +} diff --git a/rust-sdk/core/src/types/fees.rs b/rust-sdk/core/src/types/fees.rs new file mode 100644 index 000000000..21280e219 --- /dev/null +++ b/rust-sdk/core/src/types/fees.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, Default)] +#[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/core/src/types/liquidity.rs b/rust-sdk/core/src/types/liquidity.rs new file mode 100644 index 000000000..e7313923d --- /dev/null +++ b/rust-sdk/core/src/types/liquidity.rs @@ -0,0 +1,33 @@ +#![allow(non_snake_case)] + +#[cfg(feature = "wasm")] +use serde::{Deserialize, Serialize}; + +#[cfg(feature = "wasm")] +use tsify::Tsify; + +#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)] +#[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 DecreaseLiquidityQuote { + pub liquidity_delta: u128, + pub token_est_a: u128, + pub token_est_b: u128, + pub token_min_a: u128, + pub token_min_b: u128, +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)] +#[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 IncreaseLiquidityQuote { + pub liquidity_delta: u128, + pub token_est_a: u128, + pub token_est_b: u128, + pub token_max_a: u128, + pub token_max_b: u128, +} diff --git a/rust-sdk/core/src/types/mod.rs b/rust-sdk/core/src/types/mod.rs new file mode 100644 index 000000000..c399d63a3 --- /dev/null +++ b/rust-sdk/core/src/types/mod.rs @@ -0,0 +1,19 @@ +mod fees; +mod liquidity; +mod pool; +mod position; +mod rewards; +mod swap; +mod tick; +mod token; +mod u128; + +pub use fees::*; +pub use liquidity::*; +pub use pool::*; +pub use position::*; +pub use rewards::*; +pub use swap::*; +pub use tick::*; +pub use token::*; +pub use u128::*; diff --git a/rust-sdk/core/src/types/pool.rs b/rust-sdk/core/src/types/pool.rs new file mode 100644 index 000000000..18e76ed5c --- /dev/null +++ b/rust-sdk/core/src/types/pool.rs @@ -0,0 +1,37 @@ +#![allow(non_snake_case)] + +#[cfg(feature = "wasm")] +use serde::{Deserialize, Serialize}; + +#[cfg(feature = "wasm")] +use tsify::Tsify; + +#[cfg(any(feature = "wasm", test))] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)] +#[cfg_attr(feature = "wasm", derive(Serialize, Deserialize, Tsify))] +#[cfg_attr(feature = "wasm", serde(rename_all = "camelCase"))] +#[cfg_attr(feature = "wasm", tsify(from_wasm_abi))] +pub struct Whirlpool { + pub tick_spacing: u16, + pub fee_rate: u16, + pub liquidity: u128, + pub sqrt_price: u128, + pub tick_current_index: i32, + pub fee_growth_global_a: u128, + pub fee_growth_global_b: u128, + pub reward_last_updated_timestamp: u64, + pub reward_infos: [WhirlpoolRewardInfo; 3], +} + +#[cfg(any(feature = "wasm", test))] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)] +#[cfg_attr(feature = "wasm", derive(Serialize, Deserialize, Tsify))] +#[cfg_attr(feature = "wasm", serde(rename_all = "camelCase"))] +#[cfg_attr(feature = "wasm", tsify(from_wasm_abi))] +pub struct WhirlpoolRewardInfo { + pub emissions_per_second_x64: u128, + pub growth_global_x64: u128, +} + +#[cfg(not(any(feature = "wasm", test)))] +pub use orca_whirlpools_client::accounts::Whirlpool; diff --git a/rust-sdk/core/src/types/position.rs b/rust-sdk/core/src/types/position.rs new file mode 100644 index 000000000..2b8e5846f --- /dev/null +++ b/rust-sdk/core/src/types/position.rs @@ -0,0 +1,55 @@ +#![allow(non_snake_case)] + +#[cfg(feature = "wasm")] +use serde::{Deserialize, Serialize}; + +#[cfg(feature = "wasm")] +use tsify::Tsify; + +#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)] +#[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 PositionRatio { + pub ratio_a: u16, + pub ratio_b: u16, +} + +#[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 enum PositionStatus { + InRange, + BelowRange, + AboveRange, +} + +#[cfg(any(feature = "wasm", test))] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)] +#[cfg_attr(feature = "wasm", derive(Serialize, Deserialize, Tsify))] +#[cfg_attr(feature = "wasm", serde(rename_all = "camelCase"))] +#[cfg_attr(feature = "wasm", tsify(from_wasm_abi))] +pub struct Position { + pub liquidity: u128, + pub tick_lower_index: i32, + pub tick_upper_index: i32, + pub fee_growth_checkpoint_a: u128, + pub fee_owed_a: u64, + pub fee_growth_checkpoint_b: u128, + pub fee_owed_b: u64, + pub reward_infos: [PositionRewardInfo; 3], +} + +#[cfg(any(feature = "wasm", test))] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)] +#[cfg_attr(feature = "wasm", derive(Serialize, Deserialize, Tsify))] +#[cfg_attr(feature = "wasm", serde(rename_all = "camelCase"))] +#[cfg_attr(feature = "wasm", tsify(from_wasm_abi))] +pub struct PositionRewardInfo { + pub growth_inside_checkpoint: u128, + pub amount_owed: u64, +} + +#[cfg(not(any(feature = "wasm", test)))] +pub use orca_whirlpools_client::accounts::Position; diff --git a/rust-sdk/core/src/types/rewards.rs b/rust-sdk/core/src/types/rewards.rs new file mode 100644 index 000000000..90f4e1cbc --- /dev/null +++ b/rust-sdk/core/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, Default)] +#[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/core/src/types/swap.rs b/rust-sdk/core/src/types/swap.rs new file mode 100644 index 000000000..fb4dd199a --- /dev/null +++ b/rust-sdk/core/src/types/swap.rs @@ -0,0 +1,31 @@ +#![allow(non_snake_case)] + +#[cfg(feature = "wasm")] +use serde::{Deserialize, Serialize}; + +#[cfg(feature = "wasm")] +use tsify::Tsify; + +#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)] +#[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 ExactInSwapQuote { + pub token_in: u128, + pub token_est_out: u128, + pub token_min_out: u128, + pub total_fee: u128, +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)] +#[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 ExactOutSwapQuote { + pub token_out: u128, + pub token_est_in: u128, + pub token_max_in: u128, + pub total_fee: u128, +} diff --git a/rust-sdk/core/src/types/tick.rs b/rust-sdk/core/src/types/tick.rs new file mode 100644 index 000000000..12d5f9a1b --- /dev/null +++ b/rust-sdk/core/src/types/tick.rs @@ -0,0 +1,53 @@ +#![allow(non_snake_case)] + +#[cfg(feature = "wasm")] +use serde::{Deserialize, Serialize}; + +#[cfg(feature = "wasm")] +use serde_big_array::BigArray; + +#[cfg(feature = "wasm")] +use tsify::Tsify; + +#[cfg(any(feature = "wasm", test))] +use crate::TICK_ARRAY_SIZE; + +#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)] +#[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 tick_lower_index: i32, + pub tick_upper_index: i32, +} + +#[cfg(any(feature = "wasm", test))] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)] +#[cfg_attr(feature = "wasm", derive(Serialize, Deserialize, Tsify))] +#[cfg_attr(feature = "wasm", serde(rename_all = "camelCase"))] +#[cfg_attr(feature = "wasm", tsify(from_wasm_abi))] +pub struct Tick { + pub initialized: bool, + pub liquidity_net: i128, + pub liquidity_gross: u128, + pub fee_growth_outside_a: u128, + pub fee_growth_outside_b: u128, + pub reward_growths_outside: [u128; 3], +} + +#[cfg(not(any(feature = "wasm", test)))] +pub use orca_whirlpools_client::types::Tick; + +#[cfg(any(feature = "wasm", test))] +#[derive(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(from_wasm_abi))] +pub struct TickArray { + pub start_tick_index: i32, + #[cfg_attr(feature = "wasm", serde(with = "BigArray"))] + pub ticks: [Tick; TICK_ARRAY_SIZE], +} + +#[cfg(not(any(feature = "wasm", test)))] +pub use orca_whirlpools_client::accounts::TickArray; diff --git a/rust-sdk/core/src/types/token.rs b/rust-sdk/core/src/types/token.rs new file mode 100644 index 000000000..b6dd8636b --- /dev/null +++ b/rust-sdk/core/src/types/token.rs @@ -0,0 +1,53 @@ +#![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(from_wasm_abi))] +pub enum AdjustmentType { + None, + // fee bps, maximum fee + TransferFee(u16, u64), + // fee denominated by 1e6 + SwapFee(u16), + // slippage bps + Slippage(u16), +} + +#[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(from_wasm_abi))] +pub struct TransferFee { + pub fee_bps: u16, + pub max_fee: u64, +} + +impl TransferFee { + pub fn new(fee_bps: u16) -> Self { + Self { + fee_bps, + max_fee: u64::MAX, + } + } + + pub fn new_with_max(fee_bps: u16, max_fee: u64) -> Self { + Self { fee_bps, max_fee } + } +} + +impl From> for AdjustmentType { + fn from(transfer_fee: Option) -> Self { + if let Some(transfer_fee) = transfer_fee { + Self::TransferFee(transfer_fee.fee_bps, transfer_fee.max_fee) + } else { + Self::None + } + } +} diff --git a/rust-sdk/core/src/types/u128.rs b/rust-sdk/core/src/types/u128.rs new file mode 100644 index 000000000..eb1c73031 --- /dev/null +++ b/rust-sdk/core/src/types/u128.rs @@ -0,0 +1,58 @@ +// 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. + +#[cfg(not(feature = "wasm"))] +pub type U128 = u128; + +#[cfg(feature = "wasm")] +use core::fmt::{Debug, Formatter, Result}; + +#[cfg(feature = "wasm")] +use ethnum::U256; + +#[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 U256 { + fn from(value: U128) -> U256 { + let u_128: u128 = JsValue::from(value).try_into().unwrap(); + ::from(u_128) + } +} + +#[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/macros/Cargo.lock b/rust-sdk/macros/Cargo.lock new file mode 100644 index 000000000..7082fc989 --- /dev/null +++ b/rust-sdk/macros/Cargo.lock @@ -0,0 +1,47 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "orca_whirlpools_macros" +version = "0.1.0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[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 = "syn" +version = "2.0.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6af063034fc1935ede7be0122941bafa9bacb949334d090b77ca98b5817c7d9" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" diff --git a/rust-sdk/macros/Cargo.toml b/rust-sdk/macros/Cargo.toml new file mode 100644 index 000000000..0622ad11b --- /dev/null +++ b/rust-sdk/macros/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "orca_whirlpools_macros" +version = "0.1.0" +edition = "2021" + +[lib] +proc-macro = true + +[dependencies] +syn = { version = "^2", features = ["full"] } +quote = { version = "^1" } +proc-macro2 = { version = "^1" } diff --git a/rust-sdk/macros/package.json b/rust-sdk/macros/package.json new file mode 100644 index 000000000..bc73d837b --- /dev/null +++ b/rust-sdk/macros/package.json @@ -0,0 +1,11 @@ +{ + "name": "@orca-so/whirlpools-rust-macros", + "version": "0.0.1", + "scripts": { + "build": "cargo build", + "test": "cargo test --lib", + "format": "cargo clippy --fix --allow-dirty --allow-staged && cargo fmt", + "lint": "cargo clippy", + "clean": "cargo clean" + } +} diff --git a/rust-sdk/macros/src/lib.rs b/rust-sdk/macros/src/lib.rs new file mode 100644 index 000000000..507e0b8f1 --- /dev/null +++ b/rust-sdk/macros/src/lib.rs @@ -0,0 +1,226 @@ +use proc_macro::TokenStream; +use proc_macro2::TokenStream as TokenStream2; +use quote::{format_ident, quote}; +use syn::{parse::Nothing, parse2, Expr, ExprUnary, ItemConst, Lit, Result, UnOp}; + +// FIXME: also add the rustdoc comment to the generated ts constant + +#[proc_macro_attribute] +pub fn export_ts_const(attr: TokenStream, item: TokenStream) -> TokenStream { + match export_ts_const_impl(attr.into(), item.into()) { + Ok(expanded) => expanded.into(), + Err(err) => err.to_compile_error().into(), + } +} + +fn export_ts_const_impl(attr: TokenStream2, item: TokenStream2) -> Result { + let _attr = parse2::(attr)?; + + let item_const: ItemConst = parse2(item)?; + + let const_name = format_ident!("_{}", item_const.ident); + let const_type = &item_const.ty; + let attrs = &item_const.attrs; + + let const_value = match &*item_const.expr { + Expr::Lit(syn::ExprLit { lit, .. }) => match lit { + Lit::Int(value) => quote! { #value }, + Lit::Float(value) => quote! { #value }, + Lit::Bool(value) => quote! { #value }, + Lit::Str(value) => quote! { #value }, + _ => { + return Err(syn::Error::new_spanned( + &item_const.expr, + "Unsupported literal type", + )) + } + }, + Expr::Unary(ExprUnary { + op: UnOp::Neg(_), + expr, + .. + }) => match &**expr { + Expr::Lit(syn::ExprLit { lit, .. }) => match lit { + Lit::Int(value) => quote! { -#value }, + Lit::Float(value) => quote! { -#value }, + _ => { + return Err(syn::Error::new_spanned( + &item_const.expr, + "Unsupported literal type", + )) + } + }, + _ => { + return Err(syn::Error::new_spanned( + &item_const.expr, + "Expected a literal after unary operator", + )) + } + }, + _ => { + return Err(syn::Error::new_spanned( + &item_const.expr, + "Expected a literal or unary operator", + )) + } + }; + + let expanded = quote! { + #(#attrs)* + #[::wasm_bindgen::prelude::wasm_bindgen(skip_jsdoc)] + pub fn #const_name() -> #const_type { + #const_value + } + #item_const + }; + + Ok(expanded) +} + +#[cfg(test)] +pub mod tests { + + use super::*; + + #[test] + fn test_correct_input_usize() { + let tokens = quote! { + #[export_ts_const] + pub const TICK_ARRAY_SIZE_TS: usize = 88; + }; + let attr = quote! {}; + let result: Result = export_ts_const_impl(attr, tokens); + assert!(result.is_ok()); + } + + #[test] + fn test_correct_input_f64() { + let tokens = quote! { + #[export_ts_const] + pub const PI_TS: f64 = 3.14; + }; + let attr = quote! {}; + let result: Result = export_ts_const_impl(attr, tokens); + assert!(result.is_ok()); + } + + #[test] + fn test_correct_input_negative_int() { + let tokens = quote! { + #[export_ts_const] + pub const NEG_INT_TS: i32 = -42; + }; + let attr = quote! {}; + let result: Result = export_ts_const_impl(attr, tokens); + assert!(result.is_ok()); + } + + #[test] + fn test_correct_input_negative_float() { + let tokens = quote! { + #[export_ts_const] + pub const NEG_FLOAT_TS: f64 = -3.14; + }; + let attr = quote! {}; + let result: Result = export_ts_const_impl(attr, tokens); + assert!(result.is_ok()); + } + + #[test] + fn test_correct_input_bool() { + let tokens = quote! { + #[export_ts_const] + pub const IS_ENABLED_TS: bool = true; + }; + let attr = quote! {}; + let result: Result = export_ts_const_impl(attr, tokens); + assert!(result.is_ok()); + } + + #[test] + fn test_correct_input_string() { + let tokens = quote! { + #[export_ts_const] + pub const NAME_TS: &str = "example"; + }; + let attr = quote! {}; + let result: Result = export_ts_const_impl(attr, tokens); + assert!(result.is_ok()); + } + + #[test] + fn test_incorrect_input_non_literal() { + let tokens = quote! { + #[export_ts_const] + pub const INVALID_TS: usize = some_function(); + }; + let attr = quote! {}; + let result: Result = export_ts_const_impl(attr, tokens); + assert!(result.is_err()); + } + + #[test] + fn test_incorrect_input_missing_value() { + let tokens = quote! { + #[export_ts_const] + pub const MISSING_TS: usize; + }; + let attr = quote! {}; + let result: Result = export_ts_const_impl(attr, tokens); + assert!(result.is_err()); + } + + #[test] + fn test_negative_literals() { + let tokens = quote! { + #[export_ts_const] + pub const NEG_INT: i32 = -123; + }; + let attr = quote! {}; + let result: Result = export_ts_const_impl(attr, tokens); + assert!(result.is_ok()); + + let tokens = quote! { + #[export_ts_const] + pub const NEG_FLOAT: f64 = -45.67; + }; + let attr = quote! {}; + let result: Result = export_ts_const_impl(attr, tokens); + assert!(result.is_ok()); + } + + #[test] + fn test_regression_negative_numeric_expansion() { + // Test case for a negative integer + let tokens = quote! { + #[export_ts_const] + pub const NEG_INT: i32 = -123; + }; + let attr = quote! {}; + let result: Result = export_ts_const_impl(attr, tokens); + assert!(result.is_ok()); + + let output = result.unwrap().to_string(); + println!("Generated Output for NEG_INT:\n{}", output); + + assert!(output.contains("pub fn _NEG_INT () -> i32 {")); + assert!(output.contains("- 123 }")); + assert!(output.contains("pub const NEG_INT : i32 = - 123 ;")); + + // Test case for a negative float + let tokens = quote! { + #[export_ts_const] + pub const NEG_FLOAT: f64 = -45.67; + }; + let attr = quote! {}; + let result: Result = export_ts_const_impl(attr, tokens); + assert!(result.is_ok()); + + let output = result.unwrap().to_string(); + println!("Generated Output for NEG_FLOAT:\n{}", output); + + assert!(output.contains("pub fn _NEG_FLOAT () -> f64 {")); + assert!(output.contains("- 45.67 }")); + assert!(output.contains("pub const NEG_FLOAT : f64 = - 45.67 ;")); + } +} diff --git a/rust-sdk/whirlpool/Cargo.lock b/rust-sdk/whirlpool/Cargo.lock index 17c4fdf11..1150d92cf 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_core", ] [[package]] @@ -902,6 +915,15 @@ dependencies = [ "thiserror", ] +[[package]] +name = "orca_whirlpools_core" +version = "0.1.0" +dependencies = [ + "ethnum", + "libm", + "orca_whirlpools_client", +] + [[package]] name = "parking_lot" version = "0.12.3" diff --git a/rust-sdk/whirlpool/Cargo.toml b/rust-sdk/whirlpool/Cargo.toml index 1415a2526..21a151f2d 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_core = { path = "../core" } 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..b97c07886 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_core::*; diff --git a/ts-sdk/core/Cargo.lock b/ts-sdk/core/Cargo.lock new file mode 100644 index 000000000..50722c573 --- /dev/null +++ b/ts-sdk/core/Cargo.lock @@ -0,0 +1,1814 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "ahash" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" +dependencies = [ + "getrandom 0.2.15", + "once_cell", + "version_check", +] + +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "anyhow" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" + +[[package]] +name = "ark-bn254" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a22f4561524cd949590d78d7d4c5df8f592430d221f7f3c9497bbafd8972120f" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-std", +] + +[[package]] +name = "ark-ec" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "defd9a439d56ac24968cca0571f598a61bc8c55f71d50a89cda591cb750670ba" +dependencies = [ + "ark-ff", + "ark-poly", + "ark-serialize", + "ark-std", + "derivative", + "hashbrown 0.13.2", + "itertools", + "num-traits", + "zeroize", +] + +[[package]] +name = "ark-ff" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" +dependencies = [ + "ark-ff-asm", + "ark-ff-macros", + "ark-serialize", + "ark-std", + "derivative", + "digest 0.10.7", + "itertools", + "num-bigint", + "num-traits", + "paste", + "rustc_version", + "zeroize", +] + +[[package]] +name = "ark-ff-asm" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-macros" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" +dependencies = [ + "num-bigint", + "num-traits", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-poly" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d320bfc44ee185d899ccbadfa8bc31aab923ce1558716e1997a1e74057fe86bf" +dependencies = [ + "ark-ff", + "ark-serialize", + "ark-std", + "derivative", + "hashbrown 0.13.2", +] + +[[package]] +name = "ark-serialize" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" +dependencies = [ + "ark-serialize-derive", + "ark-std", + "digest 0.10.7", + "num-bigint", +] + +[[package]] +name = "ark-serialize-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae3281bc6d0fd7e549af32b52511e1302185bd688fd3359fa36423346ff682ea" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-std" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" +dependencies = [ + "num-traits", + "rand 0.8.5", +] + +[[package]] +name = "arrayref" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d151e35f61089500b617991b791fc8bfd237ae50cd5950803758a179b41e67a" + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "base64" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +dependencies = [ + "serde", +] + +[[package]] +name = "bitmaps" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "031043d04099746d8db04daf1fa424b2bc8bd69d92b25962dcde24da39ab64a2" +dependencies = [ + "typenum", +] + +[[package]] +name = "blake3" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30cca6d3674597c30ddf2c587bf8d9d65c9a84d2326d941cc79c9842dfe0ef52" +dependencies = [ + "arrayref", + "arrayvec", + "cc", + "cfg-if", + "constant_time_eq", + "digest 0.10.7", +] + +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "borsh" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15bf3650200d8bffa99015595e10f1fbd17de07abbc25bb067da79e769939bfa" +dependencies = [ + "borsh-derive 0.9.3", + "hashbrown 0.11.2", +] + +[[package]] +name = "borsh" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4114279215a005bc675e386011e594e1d9b800918cea18fcadadcce864a2046b" +dependencies = [ + "borsh-derive 0.10.3", + "hashbrown 0.13.2", +] + +[[package]] +name = "borsh" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6362ed55def622cddc70a4746a68554d7b687713770de539e59a739b249f8ed" +dependencies = [ + "borsh-derive 1.5.1", + "cfg_aliases", +] + +[[package]] +name = "borsh-derive" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6441c552f230375d18e3cc377677914d2ca2b0d36e52129fe15450a2dce46775" +dependencies = [ + "borsh-derive-internal 0.9.3", + "borsh-schema-derive-internal 0.9.3", + "proc-macro-crate 0.1.5", + "proc-macro2", + "syn 1.0.109", +] + +[[package]] +name = "borsh-derive" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0754613691538d51f329cce9af41d7b7ca150bc973056f1156611489475f54f7" +dependencies = [ + "borsh-derive-internal 0.10.3", + "borsh-schema-derive-internal 0.10.3", + "proc-macro-crate 0.1.5", + "proc-macro2", + "syn 1.0.109", +] + +[[package]] +name = "borsh-derive" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3ef8005764f53cd4dca619f5bf64cafd4664dada50ece25e4d81de54c80cc0b" +dependencies = [ + "once_cell", + "proc-macro-crate 3.1.0", + "proc-macro2", + "quote", + "syn 2.0.74", + "syn_derive", +] + +[[package]] +name = "borsh-derive-internal" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5449c28a7b352f2d1e592a8a28bf139bc71afb0764a14f3c02500935d8c44065" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "borsh-derive-internal" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afb438156919598d2c7bad7e1c0adf3d26ed3840dbc010db1a882a65583ca2fb" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "borsh-schema-derive-internal" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdbd5696d8bfa21d53d9fe39a714a18538bad11492a42d066dbbc395fb1951c0" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "borsh-schema-derive-internal" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634205cc43f74a1b9046ef87c4540ebda95696ec0f315024860cad7c5b0f5ccd" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "bs58" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "bv" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8834bb1d8ee5dc048ee3124f2c7c1afcc6bc9aed03f11e9dfd8c69470a5db340" +dependencies = [ + "feature-probe", + "serde", +] + +[[package]] +name = "bytemuck" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fd4c6dcc3b0aea2f5c0b4b82c2b15fe39ddbc76041a310848f4706edf76bb31" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cc8b54b395f2fcfbb3d90c47b01c7f444d94d05bdeb775811dec868ac3bbc26" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.74", +] + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "cc" +version = "1.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72db2f7947ecee9b03b510377e8bb9077afa27176fdbff55c51027e976fdcc48" +dependencies = [ + "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "console_error_panic_hook" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" +dependencies = [ + "cfg-if", + "wasm-bindgen", +] + +[[package]] +name = "console_log" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89f72f65e8501878b8a004d5a1afb780987e2ce2b4532c562e367a72c57499f" +dependencies = [ + "log", + "web-sys", +] + +[[package]] +name = "constant_time_eq" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" + +[[package]] +name = "cpufeatures" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad" +dependencies = [ + "libc", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "crypto-mac" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" +dependencies = [ + "generic-array", + "subtle", +] + +[[package]] +name = "curve25519-dalek" +version = "3.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90f9d052967f590a76e62eb387bd0bbb1b000182c3cefe5364db6b7211651bc0" +dependencies = [ + "byteorder", + "digest 0.9.0", + "rand_core 0.5.1", + "serde", + "subtle", + "zeroize", +] + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer 0.10.4", + "crypto-common", + "subtle", +] + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "equivalent" +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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835a3dc7d1ec9e75e2b5fb4ba75396837112d2060b03f7d43bc1897c7f7211da" + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "serde", + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", + "wasm-bindgen", +] + +[[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 = "hashbrown" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +dependencies = [ + "ahash 0.7.8", +] + +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash 0.8.11", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "hmac" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "126888268dcc288495a26bf004b38c5fdbb31682f992c84ceb046a1f0fe38840" +dependencies = [ + "crypto-mac", + "digest 0.9.0", +] + +[[package]] +name = "hmac-drbg" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17ea0a1394df5b6574da6e0c1ade9e78868c9fb0a4e5ef4428e32da4676b85b1" +dependencies = [ + "digest 0.9.0", + "generic-array", + "hmac", +] + +[[package]] +name = "im" +version = "15.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0acd33ff0285af998aaf9b57342af478078f53492322fafc47450e09397e0e9" +dependencies = [ + "bitmaps", + "rand_core 0.6.4", + "rand_xoshiro", + "rayon", + "serde", + "sized-chunks", + "typenum", + "version_check", +] + +[[package]] +name = "indexmap" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93ead53efc7ea8ed3cfb0c79fc8023fbb782a5432b52830b6518941cebe6505c" +dependencies = [ + "equivalent", + "hashbrown 0.14.5", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "jobserver" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +dependencies = [ + "libc", +] + +[[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 = "keccak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.158" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9d220bc1feda2ac231cb78c3d26f27676b8cf82c96971f7aeef3d0cf2797c73" +dependencies = [ + "arrayref", + "base64 0.12.3", + "digest 0.9.0", + "hmac-drbg", + "libsecp256k1-core", + "libsecp256k1-gen-ecmult", + "libsecp256k1-gen-genmult", + "rand 0.7.3", + "serde", + "sha2 0.9.9", + "typenum", +] + +[[package]] +name = "libsecp256k1-core" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0f6ab710cec28cef759c5f18671a27dae2a5f952cdaaee1d8e2908cb2478a80" +dependencies = [ + "crunchy", + "digest 0.9.0", + "subtle", +] + +[[package]] +name = "libsecp256k1-gen-ecmult" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccab96b584d38fac86a83f07e659f0deafd0253dc096dab5a36d53efe653c5c3" +dependencies = [ + "libsecp256k1-core", +] + +[[package]] +name = "libsecp256k1-gen-genmult" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67abfe149395e3aa1c48a2beb32b068e2334402df8181f818d3aee2b304c4f5d" +dependencies = [ + "libsecp256k1-core", +] + +[[package]] +name = "light-poseidon" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c9a85a9752c549ceb7578064b4ed891179d20acd85f27318573b64d2d7ee7ee" +dependencies = [ + "ark-bn254", + "ark-ff", + "num-bigint", + "thiserror", +] + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[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 = "memmap2" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" +dependencies = [ + "libc", +] + +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.74", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[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 = "opaque-debug" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" + +[[package]] +name = "orca_whirlpools_client" +version = "0.1.0" +dependencies = [ + "borsh 0.10.3", + "num-derive", + "num-traits", + "solana-program", + "thiserror", +] + +[[package]] +name = "orca_whirlpools_core" +version = "0.1.0" +dependencies = [ + "ethnum", + "libm", + "orca_whirlpools_client", + "orca_whirlpools_macros", + "serde", + "serde-big-array", + "serde-wasm-bindgen 0.6.5", + "tsify", + "wasm-bindgen", +] + +[[package]] +name = "orca_whirlpools_core_js_bindings" +version = "0.1.0" +dependencies = [ + "orca_whirlpools_core", +] + +[[package]] +name = "orca_whirlpools_macros" +version = "0.1.0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.74", +] + +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pbkdf2" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "216eaa586a190f0a738f2f918511eecfa90f13295abec0e457cdebcceda80cbd" +dependencies = [ + "crypto-mac", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "proc-macro-crate" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" +dependencies = [ + "toml", +] + +[[package]] +name = "proc-macro-crate" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" +dependencies = [ + "toml_edit", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[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 = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom 0.1.16", + "libc", + "rand_chacha 0.2.2", + "rand_core 0.5.1", + "rand_hc", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core 0.5.1", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom 0.1.16", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.15", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core 0.5.1", +] + +[[package]] +name = "rand_xoshiro" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa" +dependencies = [ + "rand_core 0.6.4", +] + +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "redox_syscall" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" +dependencies = [ + "bitflags", +] + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + +[[package]] +name = "rustversion" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "semver" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" + +[[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-big-array" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11fc7cc2c76d73e0f27ee52abbd64eec84d46f370c88371120433196934e4b7f" +dependencies = [ + "serde", +] + +[[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_bytes" +version = "0.11.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "387cc504cb06bb40a96c8e04e951fe01854cf6bc921053c954e4a606d9675c6a" +dependencies = [ + "serde", +] + +[[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 2.0.74", +] + +[[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 2.0.74", +] + +[[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 = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures", + "digest 0.9.0", + "opaque-debug", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest 0.10.7", + "keccak", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "sized-chunks" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16d69225bde7a69b235da73377861095455d298f2b970996eec25ddbb42b3d1e" +dependencies = [ + "bitmaps", + "typenum", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "solana-frozen-abi" +version = "1.18.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20a6ef2db80dceb124b7bf81cca3300804bf427d2711973fc3df450ed7dfb26d" +dependencies = [ + "block-buffer 0.10.4", + "bs58", + "bv", + "either", + "generic-array", + "im", + "lazy_static", + "log", + "memmap2", + "rustc_version", + "serde", + "serde_bytes", + "serde_derive", + "sha2 0.10.8", + "solana-frozen-abi-macro", + "subtle", + "thiserror", +] + +[[package]] +name = "solana-frozen-abi-macro" +version = "1.18.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70088de7d4067d19a7455609e2b393e6086bd847bb39c4d2bf234fc14827ef9e" +dependencies = [ + "proc-macro2", + "quote", + "rustc_version", + "syn 2.0.74", +] + +[[package]] +name = "solana-program" +version = "1.18.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb2b2c8babfae4cace1a25b6efa00418f3acd852cf55d7cecc0360d3c5050479" +dependencies = [ + "ark-bn254", + "ark-ec", + "ark-ff", + "ark-serialize", + "base64 0.21.7", + "bincode", + "bitflags", + "blake3", + "borsh 0.10.3", + "borsh 0.9.3", + "borsh 1.5.1", + "bs58", + "bv", + "bytemuck", + "cc", + "console_error_panic_hook", + "console_log", + "curve25519-dalek", + "getrandom 0.2.15", + "itertools", + "js-sys", + "lazy_static", + "libc", + "libsecp256k1", + "light-poseidon", + "log", + "memoffset", + "num-bigint", + "num-derive", + "num-traits", + "parking_lot", + "rand 0.8.5", + "rustc_version", + "rustversion", + "serde", + "serde_bytes", + "serde_derive", + "serde_json", + "sha2 0.10.8", + "sha3", + "solana-frozen-abi", + "solana-frozen-abi-macro", + "solana-sdk-macro", + "thiserror", + "tiny-bip39", + "wasm-bindgen", + "zeroize", +] + +[[package]] +name = "solana-sdk-macro" +version = "1.18.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c55c196c8050834c391a34b58e3c9fd86b15452ef1feeeafa1dbeb9d2291dfec" +dependencies = [ + "bs58", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.74", +] + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[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 = "syn_derive" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1329189c02ff984e9736652b1631330da25eaa6bc639089ed4915d25446cbe7b" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.74", +] + +[[package]] +name = "thiserror" +version = "1.0.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.74", +] + +[[package]] +name = "tiny-bip39" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffc59cb9dfc85bb312c3a78fd6aa8a8582e310b0fa885d5bb877f6dcc601839d" +dependencies = [ + "anyhow", + "hmac", + "once_cell", + "pbkdf2", + "rand 0.7.3", + "rustc-hash", + "sha2 0.9.9", + "thiserror", + "unicode-normalization", + "wasm-bindgen", + "zeroize", +] + +[[package]] +name = "tinyvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" + +[[package]] +name = "toml_edit" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow", +] + +[[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 2.0.74", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-normalization" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + +[[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.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 2.0.74", + "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 2.0.74", + "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 = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "0.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.74", +] + +[[package]] +name = "zeroize" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4756f7db3f7b5574938c3eb1c117038b8e07f95ee6718c0efad4ac21508f1efd" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.74", +] diff --git a/ts-sdk/core/Cargo.toml b/ts-sdk/core/Cargo.toml new file mode 100644 index 000000000..09deccdd8 --- /dev/null +++ b/ts-sdk/core/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "orca_whirlpools_core_js_bindings" +version = "0.1.0" +edition = "2021" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +orca_whirlpools_core = { path = "../../rust-sdk/core", features = ["wasm", "floats"] } + +[profile.release] +opt-level = "s" diff --git a/ts-sdk/core/package.json b/ts-sdk/core/package.json new file mode 100644 index 000000000..a2de36731 --- /dev/null +++ b/ts-sdk/core/package.json @@ -0,0 +1,26 @@ +{ + "name": "@orca-so/whirlpools-core", + "version": "0.0.1", + "main": "./dist/nodejs/orca_whirlpools_core_js_bindings.js", + "types": "./dist/nodejs/orca_whirlpools_core_js_bindings.d.ts", + "browser": "./dist/web/orca_whirlpools_core_js_bindings.js", + "type": "module", + "sideEffects": [ + "./dist/web/snippets/*" + ], + "files": [ + "./dist/*/orca_whirlpools_core_js_bindings_bg.wasm", + "./dist/*/orca_whirlpools_core_js_bindings.js", + "./dist/*/orca_whirlpools_core_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-core": "*", + "wasm-pack": "^0.13.0" + } +} diff --git a/ts-sdk/core/src/lib.rs b/ts-sdk/core/src/lib.rs new file mode 100644 index 000000000..289154dc5 --- /dev/null +++ b/ts-sdk/core/src/lib.rs @@ -0,0 +1 @@ +pub use orca_whirlpools_core::*; diff --git a/ts-sdk/core/test.sh b/ts-sdk/core/test.sh new file mode 100644 index 000000000..9efd91439 --- /dev/null +++ b/ts-sdk/core/test.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +set -e + +NODE_SIZE=$(gzip -c dist/nodejs/orca_whirlpools_core_js_bindings_bg.wasm | wc -c) +echo "Node wasm binary gzip size: $NODE_SIZE" +WEB_SIZE=$(gzip -c dist/web/orca_whirlpools_core_js_bindings_bg.wasm | wc -c) +echo "Web wasm binary gzip side: $WEB_SIZE" +SIZE=$(( $NODE_SIZE > $WEB_SIZE ? $NODE_SIZE : $WEB_SIZE )) + +# FIXME: Renable this test when we remove stdlib from the wasm binary. +# 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..a236ad66d 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-core": "*" }, "devDependencies": { "typescript": "^5.5.4" diff --git a/ts-sdk/whirlpool/src/index.ts b/ts-sdk/whirlpool/src/index.ts index 171c874f1..543d60617 100644 --- a/ts-sdk/whirlpool/src/index.ts +++ b/ts-sdk/whirlpool/src/index.ts @@ -1 +1,2 @@ +export * from "@orca-so/whirlpools-core"; export * from "@orca-so/whirlpools-client"; diff --git a/yarn.lock b/yarn.lock index c88fb78bd..541172391 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2503,19 +2503,6 @@ __metadata: languageName: node linkType: hard -"@kinobi-so/errors@npm:0.21.3": - version: 0.21.3 - resolution: "@kinobi-so/errors@npm:0.21.3" - dependencies: - "@kinobi-so/node-types": "npm:0.21.3" - chalk: "npm:^5.3.0" - commander: "npm:^12.1.0" - bin: - errors: bin/cli.mjs - checksum: 10c0/20bee010dd1fa01e46470426eab77da7fbf492d36f5895fc4499d8b8d4f9f41eb5be5686f987fe291d7712c8936404cbd4933357661d4faabb9dd119c761dccc - languageName: node - linkType: hard - "@kinobi-so/errors@npm:0.21.4": version: 0.21.4 resolution: "@kinobi-so/errors@npm:0.21.4" @@ -2529,13 +2516,6 @@ __metadata: languageName: node linkType: hard -"@kinobi-so/node-types@npm:0.21.3": - version: 0.21.3 - resolution: "@kinobi-so/node-types@npm:0.21.3" - checksum: 10c0/ee44d1667d6a74d74872efb0c14bf6e1e73fcde883c8ef1220bf2b99db61fd05d713a2fc466e50a3162186c7c7a1e9eceb65906c007464f869d826d87406b77e - languageName: node - linkType: hard - "@kinobi-so/node-types@npm:0.21.4": version: 0.21.4 resolution: "@kinobi-so/node-types@npm:0.21.4" @@ -2543,7 +2523,7 @@ __metadata: languageName: node linkType: hard -"@kinobi-so/nodes-from-anchor@npm:0.21.2": +"@kinobi-so/nodes-from-anchor@npm:0.21.2, @kinobi-so/nodes-from-anchor@npm:^0.21.1": version: 0.21.2 resolution: "@kinobi-so/nodes-from-anchor@npm:0.21.2" dependencies: @@ -2555,28 +2535,6 @@ __metadata: languageName: node linkType: hard -"@kinobi-so/nodes-from-anchor@npm:^0.21.1": - version: 0.21.1 - resolution: "@kinobi-so/nodes-from-anchor@npm:0.21.1" - dependencies: - "@kinobi-so/errors": "npm:0.21.3" - "@kinobi-so/nodes": "npm:0.21.3" - "@kinobi-so/visitors": "npm:0.21.3" - "@noble/hashes": "npm:^1.4.0" - checksum: 10c0/6d59a93c9dadb83467177f726c3e031c72f3eeda61cdae4011443aa165e5ad2cfd67493c0acd2a5a12ad3683d6ecdf1b766a2522dd7001b824daba8774bf21e5 - languageName: node - linkType: hard - -"@kinobi-so/nodes@npm:0.21.3": - version: 0.21.3 - resolution: "@kinobi-so/nodes@npm:0.21.3" - dependencies: - "@kinobi-so/errors": "npm:0.21.3" - "@kinobi-so/node-types": "npm:0.21.3" - checksum: 10c0/a8710328232762a4d7167d35d444ab298eefaad4bfdfece235be7ab5ad17eb8f3354b631b27f5117da0a61e8c8f5729b8666b54004118bb1e0b11fa20e1ba66e - languageName: node - linkType: hard - "@kinobi-so/nodes@npm:0.21.4": version: 0.21.4 resolution: "@kinobi-so/nodes@npm:0.21.4" @@ -2628,25 +2586,14 @@ __metadata: languageName: node linkType: hard -"@kinobi-so/validators@npm:0.21.3": - version: 0.21.3 - resolution: "@kinobi-so/validators@npm:0.21.3" - dependencies: - "@kinobi-so/errors": "npm:0.21.3" - "@kinobi-so/nodes": "npm:0.21.3" - "@kinobi-so/visitors-core": "npm:0.21.3" - checksum: 10c0/067d4eb365bea5072ee7e246e2e67574562bc4eeb066f1fa34f945cc006b6a1bd587e34ff289e4127ea6e2010e7a1c1ebfc036faf0baa7bc7785c8b8b638a895 - languageName: node - linkType: hard - -"@kinobi-so/visitors-core@npm:0.21.3": - version: 0.21.3 - resolution: "@kinobi-so/visitors-core@npm:0.21.3" +"@kinobi-so/validators@npm:0.21.4": + version: 0.21.4 + resolution: "@kinobi-so/validators@npm:0.21.4" dependencies: - "@kinobi-so/errors": "npm:0.21.3" - "@kinobi-so/nodes": "npm:0.21.3" - json-stable-stringify: "npm:^1.1.1" - checksum: 10c0/ec4b6538b17b0263a381019101f38de3d8b637668674135192d19ac7f909e9c01a3992668393a50077778887f1c01054734ce0affbafb3e577ccbf9a0aac4bbc + "@kinobi-so/errors": "npm:0.21.4" + "@kinobi-so/nodes": "npm:0.21.4" + "@kinobi-so/visitors-core": "npm:0.21.4" + checksum: 10c0/2e7ae88ac46c329a8ab9445ec68238ae766163e9523ed8862915ad4a39bc52db7a9aa627e5417f97859c0d1802487416f7f0f0d69eda2f9e62325db93982bcf5 languageName: node linkType: hard @@ -2661,17 +2608,6 @@ __metadata: languageName: node linkType: hard -"@kinobi-so/visitors@npm:0.21.3": - version: 0.21.3 - resolution: "@kinobi-so/visitors@npm:0.21.3" - dependencies: - "@kinobi-so/errors": "npm:0.21.3" - "@kinobi-so/nodes": "npm:0.21.3" - "@kinobi-so/visitors-core": "npm:0.21.3" - checksum: 10c0/6d2ed0a16b3683f4889c6f618d97ab52a9d5e3d954e91edbc6095823bf613f8d6d7fac86df9c385fcd746418e243b5579552ae3b027a120102cd49dc8f0967ac - languageName: node - linkType: hard - "@kinobi-so/visitors@npm:0.21.4": version: 0.21.4 resolution: "@kinobi-so/visitors@npm:0.21.4" @@ -2809,84 +2745,84 @@ __metadata: languageName: node linkType: hard -"@nrwl/tao@npm:19.6.1": - version: 19.6.1 - resolution: "@nrwl/tao@npm:19.6.1" +"@nrwl/tao@npm:19.6.2": + version: 19.6.2 + resolution: "@nrwl/tao@npm:19.6.2" dependencies: - nx: "npm:19.6.1" + nx: "npm:19.6.2" tslib: "npm:^2.3.0" bin: tao: index.js - checksum: 10c0/14125fc1a7ecec6100ad1370e85f1bdce5cb44b35eda2a3e89ec911d2ef5e46835745de5ac24b6b45ab4023b4ba17e13baacaaf575be69066cf935bdbd85a091 + checksum: 10c0/db7ae5796274740298ffb2eb44f8542b784181321d9898f94ed9a64e01b6d336d48afedb09c1db9c299605eb5f4544d5aa37656f80c44b219919238ecda2d2ae languageName: node linkType: hard -"@nx/nx-darwin-arm64@npm:19.6.1": - version: 19.6.1 - resolution: "@nx/nx-darwin-arm64@npm:19.6.1" +"@nx/nx-darwin-arm64@npm:19.6.2": + version: 19.6.2 + resolution: "@nx/nx-darwin-arm64@npm:19.6.2" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@nx/nx-darwin-x64@npm:19.6.1": - version: 19.6.1 - resolution: "@nx/nx-darwin-x64@npm:19.6.1" +"@nx/nx-darwin-x64@npm:19.6.2": + version: 19.6.2 + resolution: "@nx/nx-darwin-x64@npm:19.6.2" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@nx/nx-freebsd-x64@npm:19.6.1": - version: 19.6.1 - resolution: "@nx/nx-freebsd-x64@npm:19.6.1" +"@nx/nx-freebsd-x64@npm:19.6.2": + version: 19.6.2 + resolution: "@nx/nx-freebsd-x64@npm:19.6.2" conditions: os=freebsd & cpu=x64 languageName: node linkType: hard -"@nx/nx-linux-arm-gnueabihf@npm:19.6.1": - version: 19.6.1 - resolution: "@nx/nx-linux-arm-gnueabihf@npm:19.6.1" +"@nx/nx-linux-arm-gnueabihf@npm:19.6.2": + version: 19.6.2 + resolution: "@nx/nx-linux-arm-gnueabihf@npm:19.6.2" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@nx/nx-linux-arm64-gnu@npm:19.6.1": - version: 19.6.1 - resolution: "@nx/nx-linux-arm64-gnu@npm:19.6.1" +"@nx/nx-linux-arm64-gnu@npm:19.6.2": + version: 19.6.2 + resolution: "@nx/nx-linux-arm64-gnu@npm:19.6.2" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@nx/nx-linux-arm64-musl@npm:19.6.1": - version: 19.6.1 - resolution: "@nx/nx-linux-arm64-musl@npm:19.6.1" +"@nx/nx-linux-arm64-musl@npm:19.6.2": + version: 19.6.2 + resolution: "@nx/nx-linux-arm64-musl@npm:19.6.2" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@nx/nx-linux-x64-gnu@npm:19.6.1": - version: 19.6.1 - resolution: "@nx/nx-linux-x64-gnu@npm:19.6.1" +"@nx/nx-linux-x64-gnu@npm:19.6.2": + version: 19.6.2 + resolution: "@nx/nx-linux-x64-gnu@npm:19.6.2" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@nx/nx-linux-x64-musl@npm:19.6.1": - version: 19.6.1 - resolution: "@nx/nx-linux-x64-musl@npm:19.6.1" +"@nx/nx-linux-x64-musl@npm:19.6.2": + version: 19.6.2 + resolution: "@nx/nx-linux-x64-musl@npm:19.6.2" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@nx/nx-win32-arm64-msvc@npm:19.6.1": - version: 19.6.1 - resolution: "@nx/nx-win32-arm64-msvc@npm:19.6.1" +"@nx/nx-win32-arm64-msvc@npm:19.6.2": + version: 19.6.2 + resolution: "@nx/nx-win32-arm64-msvc@npm:19.6.2" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@nx/nx-win32-x64-msvc@npm:19.6.1": - version: 19.6.1 - resolution: "@nx/nx-win32-x64-msvc@npm:19.6.1" +"@nx/nx-win32-x64-msvc@npm:19.6.2": + version: 19.6.2 + resolution: "@nx/nx-win32-x64-msvc@npm:19.6.2" conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -2919,10 +2855,20 @@ __metadata: languageName: unknown linkType: soft +"@orca-so/whirlpools-core@npm:*, @orca-so/whirlpools-core@workspace:ts-sdk/core": + version: 0.0.0-use.local + resolution: "@orca-so/whirlpools-core@workspace:ts-sdk/core" + dependencies: + "@orca-so/whirlpools-rust-core": "npm:*" + wasm-pack: "npm:^0.13.0" + languageName: unknown + linkType: soft + "@orca-so/whirlpools-docs-legacy@npm:*, @orca-so/whirlpools-docs-legacy@workspace:docs/legacy": 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.6" typescript: "npm:^5.5.4" @@ -2942,6 +2888,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.6" typescript: "npm:^5.5.4" languageName: unknown @@ -3013,6 +2960,21 @@ __metadata: languageName: unknown linkType: soft +"@orca-so/whirlpools-rust-core@npm:*, @orca-so/whirlpools-rust-core@workspace:rust-sdk/core": + version: 0.0.0-use.local + resolution: "@orca-so/whirlpools-rust-core@workspace:rust-sdk/core" + dependencies: + "@orca-so/whirlpools-rust-client": "npm:*" + "@orca-so/whirlpools-rust-macros": "npm:*" + languageName: unknown + linkType: soft + +"@orca-so/whirlpools-rust-macros@npm:*, @orca-so/whirlpools-rust-macros@workspace:rust-sdk/macros": + version: 0.0.0-use.local + resolution: "@orca-so/whirlpools-rust-macros@workspace:rust-sdk/macros" + 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" @@ -3061,6 +3023,7 @@ __metadata: resolution: "@orca-so/whirlpools@workspace:ts-sdk/whirlpool" dependencies: "@orca-so/whirlpools-client": "npm:*" + "@orca-so/whirlpools-core": "npm:*" typescript: "npm:^5.5.4" languageName: unknown linkType: soft @@ -3129,12 +3092,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 @@ -4516,11 +4479,11 @@ __metadata: linkType: hard "@types/node@npm:^22.4.2": - version: 22.4.2 - resolution: "@types/node@npm:22.4.2" + version: 22.5.0 + resolution: "@types/node@npm:22.5.0" dependencies: undici-types: "npm:~6.19.2" - checksum: 10c0/db583e83230eed29eb73e24cc03637f5bdc8c01883ae0ba0a6ab9356065f93d0355a91ad1c89b985631006bd77c529d6a3ce042b3667b69c8851d05e1f965db1 + checksum: 10c0/45aa75c5e71645fac42dced4eff7f197c3fdfff6e8a9fdacd0eb2e748ff21ee70ffb73982f068a58e8d73b2c088a63613142c125236cdcf3c072ea97eada1559 languageName: node linkType: hard @@ -4672,10 +4635,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 @@ -4686,6 +4649,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" @@ -5431,6 +5401,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.4": version: 1.7.4 resolution: "axios@npm:1.7.4" @@ -5568,6 +5547,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" @@ -7944,7 +7934,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: @@ -9754,14 +9744,14 @@ __metadata: linkType: hard "kinobi@npm:^0.21.3": - version: 0.21.3 - resolution: "kinobi@npm:0.21.3" + version: 0.21.4 + resolution: "kinobi@npm:0.21.4" dependencies: - "@kinobi-so/errors": "npm:0.21.3" - "@kinobi-so/nodes": "npm:0.21.3" - "@kinobi-so/validators": "npm:0.21.3" - "@kinobi-so/visitors": "npm:0.21.3" - checksum: 10c0/36acf9ec99ba8b110205a4b7110c906ae0ffe653f8abd6209bc0e1d38ca2990b371a7a38c43d53ddbf181f8370eb9b29608e9c241cab7f56b5b52ebca54d68d5 + "@kinobi-so/errors": "npm:0.21.4" + "@kinobi-so/nodes": "npm:0.21.4" + "@kinobi-so/validators": "npm:0.21.4" + "@kinobi-so/visitors": "npm:0.21.4" + checksum: 10c0/cd29af06d22f18fa3adfca1001e507e305b67e3657f231c541ab0fda783da4009cc65c0af9f3af80a9ebeb9f506815d7ca41a0878ba20c193cb18c18d9f7fa60 languageName: node linkType: hard @@ -11492,22 +11482,22 @@ __metadata: languageName: node linkType: hard -"nx@npm:19.6.1, nx@npm:^19.6.1": - version: 19.6.1 - resolution: "nx@npm:19.6.1" +"nx@npm:19.6.2, nx@npm:^19.6.1": + version: 19.6.2 + resolution: "nx@npm:19.6.2" dependencies: "@napi-rs/wasm-runtime": "npm:0.2.4" - "@nrwl/tao": "npm:19.6.1" - "@nx/nx-darwin-arm64": "npm:19.6.1" - "@nx/nx-darwin-x64": "npm:19.6.1" - "@nx/nx-freebsd-x64": "npm:19.6.1" - "@nx/nx-linux-arm-gnueabihf": "npm:19.6.1" - "@nx/nx-linux-arm64-gnu": "npm:19.6.1" - "@nx/nx-linux-arm64-musl": "npm:19.6.1" - "@nx/nx-linux-x64-gnu": "npm:19.6.1" - "@nx/nx-linux-x64-musl": "npm:19.6.1" - "@nx/nx-win32-arm64-msvc": "npm:19.6.1" - "@nx/nx-win32-x64-msvc": "npm:19.6.1" + "@nrwl/tao": "npm:19.6.2" + "@nx/nx-darwin-arm64": "npm:19.6.2" + "@nx/nx-darwin-x64": "npm:19.6.2" + "@nx/nx-freebsd-x64": "npm:19.6.2" + "@nx/nx-linux-arm-gnueabihf": "npm:19.6.2" + "@nx/nx-linux-arm64-gnu": "npm:19.6.2" + "@nx/nx-linux-arm64-musl": "npm:19.6.2" + "@nx/nx-linux-x64-gnu": "npm:19.6.2" + "@nx/nx-linux-x64-musl": "npm:19.6.2" + "@nx/nx-win32-arm64-msvc": "npm:19.6.2" + "@nx/nx-win32-x64-msvc": "npm:19.6.2" "@yarnpkg/lockfile": "npm:^1.1.0" "@yarnpkg/parsers": "npm:3.0.0-rc.46" "@zkochan/js-yaml": "npm:0.0.7" @@ -11573,7 +11563,7 @@ __metadata: bin: nx: bin/nx.js nx-cloud: bin/nx-cloud.js - checksum: 10c0/a27d249776e924fe28c1c961e25e890dabc0b701e6dee425ed115b4819371f56042fd5490ce1d4d4ccfd7c8fad3e7b816a051e689487312372c23e68920da033 + checksum: 10c0/f97da3455de56c3e2b46c999b0b7f523bf3a3584974a647da669f11db6c3ce63c6e22bd90b863e6966c4a06ea237521a2115d81a76d6862d9c34c6368feeddfc languageName: node linkType: hard @@ -13720,12 +13710,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 @@ -14996,6 +14986,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"