diff --git a/Cargo.lock b/Cargo.lock index 984f037..b79e5ca 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -18,7 +18,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8" dependencies = [ "cfg-if", - "cipher 0.3.0", + "cipher", "cpufeatures", "opaque-debug", ] @@ -31,7 +31,7 @@ checksum = "589c637f0e68c877bbd59a4599bbe849cac8e5f3e4b5a3ebae8f528cd218dcdc" dependencies = [ "aead", "aes", - "cipher 0.3.0", + "cipher", "ctr", "polyval", "subtle", @@ -44,11 +44,24 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" dependencies = [ - "getrandom 0.2.8", + "getrandom 0.2.14", "once_cell", "version_check", ] +[[package]] +name = "ahash" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd7d5a2cecb58716e47d67d5703a249964b14c7be1ec3cad3affc295b2d1c35d" +dependencies = [ + "cfg-if", + "getrandom 0.2.14", + "once_cell", + "version_check", + "zerocopy", +] + [[package]] name = "aho-corasick" version = "0.7.20" @@ -60,174 +73,162 @@ dependencies = [ [[package]] name = "anchor-attribute-access-control" -version = "0.26.0" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf7d535e1381be3de2c0716c0a1c1e32ad9df1042cddcf7bc18d743569e53319" +checksum = "e5f619f1d04f53621925ba8a2e633ba5a6081f2ae14758cbb67f38fd823e0a3e" dependencies = [ "anchor-syn", - "anyhow", "proc-macro2", "quote", - "regex", - "syn", + "syn 1.0.107", ] [[package]] name = "anchor-attribute-account" -version = "0.26.0" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3bcd731f21048a032be27c7791701120e44f3f6371358fc4261a7f716283d29" +checksum = "e7f2a3e1df4685f18d12a943a9f2a7456305401af21a07c9fe076ef9ecd6e400" dependencies = [ "anchor-syn", - "anyhow", - "bs58 0.4.0", + "bs58 0.5.1", "proc-macro2", "quote", - "rustversion", - "syn", + "syn 1.0.107", ] [[package]] name = "anchor-attribute-constant" -version = "0.26.0" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1be64a48e395fe00b8217287f226078be2cf32dae42fdf8a885b997945c3d28" +checksum = "9423945cb55627f0b30903288e78baf6f62c6c8ab28fb344b6b25f1ffee3dca7" dependencies = [ "anchor-syn", - "proc-macro2", - "syn", + "quote", + "syn 1.0.107", ] [[package]] name = "anchor-attribute-error" -version = "0.26.0" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38ea6713d1938c0da03656ff8a693b17dc0396da66d1ba320557f07e86eca0d4" +checksum = "93ed12720033cc3c3bf3cfa293349c2275cd5ab99936e33dd4bf283aaad3e241" dependencies = [ "anchor-syn", - "proc-macro2", "quote", - "syn", + "syn 1.0.107", ] [[package]] name = "anchor-attribute-event" -version = "0.26.0" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d401f11efb3644285685f8339829a9786d43ed7490bb1699f33c478d04d5a582" +checksum = "eef4dc0371eba2d8c8b54794b0b0eb786a234a559b77593d6f80825b6d2c77a2" dependencies = [ "anchor-syn", - "anyhow", "proc-macro2", "quote", - "syn", -] - -[[package]] -name = "anchor-attribute-interface" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6700a6f5c888a9c33fe8afc0c64fd8575fa28d05446037306d0f96102ae4480" -dependencies = [ - "anchor-syn", - "anyhow", - "heck", - "proc-macro2", - "quote", - "syn", + "syn 1.0.107", ] [[package]] name = "anchor-attribute-program" -version = "0.26.0" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ad769993b5266714e8939e47fbdede90e5c030333c7522d99a4d4748cf26712" +checksum = "b18c4f191331e078d4a6a080954d1576241c29c56638783322a18d308ab27e4f" dependencies = [ "anchor-syn", - "anyhow", - "proc-macro2", "quote", - "syn", -] - -[[package]] -name = "anchor-attribute-state" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e677fae4a016a554acdd0e3b7f178d3acafaa7e7ffac6b8690cf4e171f1c116" -dependencies = [ - "anchor-syn", - "anyhow", - "proc-macro2", - "quote", - "syn", + "syn 1.0.107", ] [[package]] name = "anchor-derive-accounts" -version = "0.26.0" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "340beef6809d1c3fcc7ae219153d981e95a8a277ff31985bd7050e32645dc9a8" +checksum = "5de10d6e9620d3bcea56c56151cad83c5992f50d5960b3a9bebc4a50390ddc3c" dependencies = [ "anchor-syn", - "anyhow", + "quote", + "syn 1.0.107", +] + +[[package]] +name = "anchor-derive-serde" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4e2e5be518ec6053d90a2a7f26843dbee607583c779e6c8395951b9739bdfbe" +dependencies = [ + "anchor-syn", + "borsh-derive-internal 0.10.3", "proc-macro2", "quote", - "syn", + "syn 1.0.107", +] + +[[package]] +name = "anchor-derive-space" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ecc31d19fa54840e74b7a979d44bcea49d70459de846088a1d71e87ba53c419" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.107", ] [[package]] name = "anchor-lang" -version = "0.26.0" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "662ceafe667448ee4199a4be2ee83b6bb76da28566eee5cea05f96ab38255af8" +checksum = "35da4785497388af0553586d55ebdc08054a8b1724720ef2749d313494f2b8ad" dependencies = [ "anchor-attribute-access-control", "anchor-attribute-account", "anchor-attribute-constant", "anchor-attribute-error", "anchor-attribute-event", - "anchor-attribute-interface", "anchor-attribute-program", - "anchor-attribute-state", "anchor-derive-accounts", + "anchor-derive-serde", + "anchor-derive-space", "arrayref", "base64 0.13.1", "bincode", - "borsh", + "borsh 0.10.3", "bytemuck", + "getrandom 0.2.14", "solana-program", "thiserror", ] [[package]] name = "anchor-spl" -version = "0.26.0" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f32390ce8356f54c0f0245ea156f8190717e37285b8bf4f406a613dc4b954cde" +checksum = "6c4fd6e43b2ca6220d2ef1641539e678bfc31b6cc393cf892b373b5997b6a39a" dependencies = [ "anchor-lang", "solana-program", "spl-associated-token-account", - "spl-token", + "spl-token 4.0.1", + "spl-token-2022 0.9.0", ] [[package]] name = "anchor-syn" -version = "0.26.0" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0418bcb5daac3b8cb1b60d8fdb1d468ca36f5509f31fb51179326fae1028fdcc" +checksum = "d9101b84702fed2ea57bd22992f75065da5648017135b844283a2f6d74f27825" dependencies = [ "anyhow", - "bs58 0.3.1", + "bs58 0.5.1", "heck", "proc-macro2", - "proc-macro2-diagnostics", "quote", "serde", "serde_json", - "sha2 0.9.9", - "syn", + "sha2 0.10.8", + "syn 1.0.107", "thiserror", ] @@ -238,16 +239,133 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61" [[package]] -name = "arrayref" -version = "0.3.6" +name = "ark-bn254" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" +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.107", +] + +[[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.107", +] + +[[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.107", +] + +[[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.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" [[package]] name = "arrayvec" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" [[package]] name = "assert_matches" @@ -284,6 +402,12 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" +[[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" @@ -314,6 +438,15 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +dependencies = [ + "serde", +] + [[package]] name = "bitmaps" version = "2.1.0" @@ -325,16 +458,16 @@ dependencies = [ [[package]] name = "blake3" -version = "1.3.3" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ae2468a89544a466886840aa467a25b766499f4f04bf7d9fcd10ecee9fccef" +checksum = "30cca6d3674597c30ddf2c587bf8d9d65c9a84d2326d941cc79c9842dfe0ef52" dependencies = [ "arrayref", "arrayvec", "cc", "cfg-if", "constant_time_eq", - "digest 0.10.6", + "digest 0.10.7", ] [[package]] @@ -349,9 +482,9 @@ dependencies = [ [[package]] name = "block-buffer" -version = "0.10.3" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ "generic-array", ] @@ -368,21 +501,44 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "15bf3650200d8bffa99015595e10f1fbd17de07abbc25bb067da79e769939bfa" dependencies = [ - "borsh-derive", + "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-derive" version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6441c552f230375d18e3cc377677914d2ca2b0d36e52129fe15450a2dce46775" dependencies = [ - "borsh-derive-internal", - "borsh-schema-derive-internal", + "borsh-derive-internal 0.9.3", + "borsh-schema-derive-internal 0.9.3", "proc-macro-crate 0.1.5", "proc-macro2", - "syn", + "syn 1.0.107", +] + +[[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.107", ] [[package]] @@ -393,7 +549,18 @@ checksum = "5449c28a7b352f2d1e592a8a28bf139bc71afb0764a14f3c02500935d8c44065" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.107", +] + +[[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.107", ] [[package]] @@ -404,14 +571,19 @@ checksum = "cdbd5696d8bfa21d53d9fe39a714a18538bad11492a42d066dbbc395fb1951c0" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.107", ] [[package]] -name = "bs58" -version = "0.3.1" +name = "borsh-schema-derive-internal" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "476e9cd489f9e121e02ffa6014a8ef220ecb15c05ed23fc34cca13925dc283fb" +checksum = "634205cc43f74a1b9046ef87c4540ebda95696ec0f315024860cad7c5b0f5ccd" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.107", +] [[package]] name = "bs58" @@ -419,6 +591,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" +[[package]] +name = "bs58" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4" +dependencies = [ + "tinyvec", +] + [[package]] name = "bumpalo" version = "3.11.1" @@ -437,37 +618,38 @@ dependencies = [ [[package]] name = "bytemuck" -version = "1.12.3" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aaa3a8d9a1ca92e282c96a32d6511b695d7d994d1d102ba85d279f9b2756947f" +checksum = "5d6d68c57235a3a081186990eca2867354726650f42f7516ca50c28d6281fd15" dependencies = [ "bytemuck_derive", ] [[package]] name = "bytemuck_derive" -version = "1.3.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fe233b960f12f8007e3db2d136e3cb1c291bfd7396e384ee76025fc1a3932b4" +checksum = "4da9a32f3fed317401fa3c862968128267c3106685286e15d5aaa3d7389c2f60" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.58", ] [[package]] name = "byteorder" -version = "1.4.3" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "cc" -version = "1.0.78" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d" +checksum = "1fd97381a8cc6493395a5afc4c691c1084b3768db713b73aa215217aa245d153" dependencies = [ "jobserver", + "libc", ] [[package]] @@ -478,11 +660,10 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.23" +version = "0.4.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f" +checksum = "8a0d04d43504c61aa6c7531f1871dd0d418d91130162063b789da00fd7057a5e" dependencies = [ - "num-integer", "num-traits", ] @@ -495,16 +676,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "cipher" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1873270f8f7942c191139cb8a40fd228da6c3fd2fc376d7e92d47aa14aeb59e" -dependencies = [ - "crypto-common", - "inout", -] - [[package]] name = "console_error_panic_hook" version = "0.1.7" @@ -517,9 +688,9 @@ dependencies = [ [[package]] name = "console_log" -version = "0.2.0" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "501a375961cef1a0d44767200e66e4a559283097e91d0730b1d75dfb2f8a1494" +checksum = "e89f72f65e8501878b8a004d5a1afb780987e2ce2b4532c562e367a72c57499f" dependencies = [ "log", "web-sys", @@ -527,9 +698,9 @@ dependencies = [ [[package]] name = "constant_time_eq" -version = "0.2.4" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3ad85c1f65dc7b37604eb0e89748faf0b9653065f2a8ef69f96a687ec1e9279" +checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" [[package]] name = "cpufeatures" @@ -615,7 +786,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "049bb91fb4aaf0e3c7efa6cd5ef877dbbbd15b39dad06d9948de4ec8a75761ea" dependencies = [ - "cipher 0.3.0", + "cipher", ] [[package]] @@ -638,8 +809,18 @@ version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" dependencies = [ - "darling_core", - "darling_macro", + "darling_core 0.13.4", + "darling_macro 0.13.4", +] + +[[package]] +name = "darling" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391" +dependencies = [ + "darling_core 0.20.8", + "darling_macro 0.20.8", ] [[package]] @@ -653,7 +834,21 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn", + "syn 1.0.107", +] + +[[package]] +name = "darling_core" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.58", ] [[package]] @@ -662,9 +857,20 @@ version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" dependencies = [ - "darling_core", + "darling_core 0.13.4", "quote", - "syn", + "syn 1.0.107", +] + +[[package]] +name = "darling_macro" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" +dependencies = [ + "darling_core 0.20.8", + "quote", + "syn 2.0.58", ] [[package]] @@ -673,6 +879,17 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e5c37193a1db1d8ed868c03ec7b152175f26160a5b740e5e484143877e0adf0" +[[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.107", +] + [[package]] name = "digest" version = "0.9.0" @@ -684,11 +901,11 @@ dependencies = [ [[package]] name = "digest" -version = "0.10.6" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "block-buffer 0.10.3", + "block-buffer 0.10.4", "crypto-common", "subtle", ] @@ -725,14 +942,14 @@ dependencies = [ "derivation-path", "ed25519-dalek", "hmac 0.12.1", - "sha2 0.10.6", + "sha2 0.10.8", ] [[package]] name = "either" -version = "1.8.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" +checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" [[package]] name = "env_logger" @@ -747,6 +964,12 @@ dependencies = [ "termcolor", ] +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + [[package]] name = "fastrand" version = "1.8.0" @@ -770,9 +993,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "generic-array" -version = "0.14.6" +version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "serde", "typenum", @@ -794,9 +1017,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.8" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" +checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" dependencies = [ "cfg-if", "js-sys", @@ -811,18 +1034,24 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" dependencies = [ - "ahash", + "ahash 0.7.6", ] [[package]] name = "hashbrown" -version = "0.12.3" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" dependencies = [ - "ahash", + "ahash 0.8.5", ] +[[package]] +name = "hashbrown" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" + [[package]] name = "heck" version = "0.3.3" @@ -872,7 +1101,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "digest 0.10.6", + "digest 0.10.7", ] [[package]] @@ -915,12 +1144,13 @@ dependencies = [ ] [[package]] -name = "inout" -version = "0.1.3" +name = "indexmap" +version = "2.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ - "generic-array", + "equivalent", + "hashbrown 0.14.3", ] [[package]] @@ -958,9 +1188,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.60" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" dependencies = [ "wasm-bindgen", ] @@ -982,9 +1212,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.139" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "libsecp256k1" @@ -1034,6 +1264,18 @@ 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.9" @@ -1046,12 +1288,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.17" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if", -] +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" [[package]] name = "memchr" @@ -1061,22 +1300,13 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "memmap2" -version = "0.5.8" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b182332558b18d807c4ce1ca8ca983b34c3ee32765e47b3f0f69b90355cc1dc" +checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" dependencies = [ "libc", ] -[[package]] -name = "memoffset" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" -dependencies = [ - "autocfg", -] - [[package]] name = "memoffset" version = "0.7.1" @@ -1086,6 +1316,15 @@ dependencies = [ "autocfg", ] +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + [[package]] name = "merlin" version = "3.0.0" @@ -1099,63 +1338,14 @@ dependencies = [ ] [[package]] -name = "mpl-token-auth-rules" -version = "1.2.0" +name = "num-bigint" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a69803fbfbc4bb0327de86f49d2639692c7c60276cb87d6cced84bb8189f2000" +checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" dependencies = [ - "borsh", - "mpl-token-metadata-context-derive", - "num-derive", + "autocfg", + "num-integer", "num-traits", - "rmp-serde", - "serde", - "shank", - "solana-program", - "solana-zk-token-sdk", - "thiserror", -] - -[[package]] -name = "mpl-token-metadata" -version = "1.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6678bb3110abc45bb32e81f80ede7420ce9069d0feb872e7423779bf9a20d1f0" -dependencies = [ - "arrayref", - "borsh", - "mpl-token-auth-rules", - "mpl-token-metadata-context-derive", - "mpl-utils", - "num-derive", - "num-traits", - "shank", - "solana-program", - "spl-associated-token-account", - "spl-token", - "thiserror", -] - -[[package]] -name = "mpl-token-metadata-context-derive" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12989bc45715b0ee91944855130131479f9c772e198a910c3eb0ea327d5bffc3" -dependencies = [ - "quote", - "syn", -] - -[[package]] -name = "mpl-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fc48e64c50dba956acb46eec86d6968ef0401ef37031426da479f1f2b592066" -dependencies = [ - "arrayref", - "borsh", - "solana-program", - "spl-token", ] [[package]] @@ -1166,7 +1356,18 @@ checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.107", +] + +[[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.58", ] [[package]] @@ -1181,9 +1382,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.15" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" dependencies = [ "autocfg", ] @@ -1204,7 +1405,25 @@ version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf5395665662ef45796a4ff5486c5d41d29e0c09640af4c5f17fd94ee2c119c9" dependencies = [ - "num_enum_derive", + "num_enum_derive 0.5.7", +] + +[[package]] +name = "num_enum" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a015b430d3c108a207fd776d2e2196aaf8b1cf8cf93253e3a097ff3085076a1" +dependencies = [ + "num_enum_derive 0.6.1", +] + +[[package]] +name = "num_enum" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02339744ee7253741199f897151b38e72257d13802d4ee837285cc2990a90845" +dependencies = [ + "num_enum_derive 0.7.2", ] [[package]] @@ -1216,14 +1435,38 @@ dependencies = [ "proc-macro-crate 1.2.1", "proc-macro2", "quote", - "syn", + "syn 1.0.107", +] + +[[package]] +name = "num_enum_derive" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96667db765a921f7b295ffee8b60472b686a51d4f21c2ee4ffdb94c7013b65a6" +dependencies = [ + "proc-macro-crate 1.2.1", + "proc-macro2", + "quote", + "syn 2.0.58", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" +dependencies = [ + "proc-macro-crate 3.1.0", + "proc-macro2", + "quote", + "syn 2.0.58", ] [[package]] name = "once_cell" -version = "1.17.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "opaque-debug" @@ -1275,7 +1518,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" dependencies = [ - "digest 0.10.6", + "digest 0.10.7", ] [[package]] @@ -1323,25 +1566,21 @@ dependencies = [ ] [[package]] -name = "proc-macro2" -version = "1.0.49" +name = "proc-macro-crate" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5" +checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" dependencies = [ - "unicode-ident", + "toml_edit", ] [[package]] -name = "proc-macro2-diagnostics" -version = "0.9.1" +name = "proc-macro2" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bf29726d67464d49fa6224a1d07936a8c08bb3fba727c7493f6cf1616fdaada" +checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" dependencies = [ - "proc-macro2", - "quote", - "syn", - "version_check", - "yansi", + "unicode-ident", ] [[package]] @@ -1351,7 +1590,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e0d9cc07f18492d879586c92b485def06bc850da3118075cd45d50e9c95b0e5" dependencies = [ "bit-set", - "bitflags", + "bitflags 1.3.2", "byteorder", "lazy_static", "num-traits", @@ -1373,6 +1612,17 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "qualifier_attr" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e2e25ee72f5b24d773cae88422baddefff7714f97aab68d96fe2b6fc4a28fb2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.58", +] + [[package]] name = "quick-error" version = "1.2.3" @@ -1387,9 +1637,9 @@ checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" [[package]] name = "quote" -version = "1.0.23" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] @@ -1453,7 +1703,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.8", + "getrandom 0.2.14", ] [[package]] @@ -1511,7 +1761,7 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -1540,28 +1790,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "rmp" -version = "0.8.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44519172358fd6d58656c86ab8e7fbc9e1490c3e8f14d35ed78ca0dd07403c9f" -dependencies = [ - "byteorder", - "num-traits", - "paste", -] - -[[package]] -name = "rmp-serde" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5b13be192e0220b8afb7222aa5813cb62cc269ebb5cac346ca6487681d2913e" -dependencies = [ - "byteorder", - "rmp", - "serde", -] - [[package]] name = "rustc-hash" version = "1.1.0" @@ -1579,9 +1807,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.11" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5583e89e108996506031660fe09baa5011b9dd0341b89029313006d1fb508d70" +checksum = "80af6f9131f277a45a3fba6ce8e2258037bb0477a67e610d3c1fe046ab31de47" [[package]] name = "rusty-fork" @@ -1615,38 +1843,38 @@ checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a" [[package]] name = "serde" -version = "1.0.152" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" dependencies = [ "serde_derive", ] [[package]] name = "serde_bytes" -version = "0.11.8" +version = "0.11.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "718dc5fff5b36f99093fc49b280cfc96ce6fc824317783bff5a1fed0c7a64819" +checksum = "8b8497c313fd43ab992087548117643f6fcd935cbf36f176ffda0aacf9591734" dependencies = [ "serde", ] [[package]] name = "serde_derive" -version = "1.0.152" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.58", ] [[package]] name = "serde_json" -version = "1.0.91" +version = "1.0.115" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883" +checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd" dependencies = [ "itoa", "ryu", @@ -1661,7 +1889,17 @@ checksum = "678b5a069e50bf00ecd22d0cd8ddf7c236f68581b03db652061ed5eb13a312ff" dependencies = [ "serde", "serde_json", - "serde_with_macros", + "serde_with_macros 1.5.2", +] + +[[package]] +name = "serde_with" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07ff71d2c147a7b57362cead5e22f772cd52f6ab31cfcd9edcd7f6aeb2a0afbe" +dependencies = [ + "serde", + "serde_with_macros 2.3.3", ] [[package]] @@ -1670,10 +1908,22 @@ version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e182d6ec6f05393cc0e5ed1bf81ad6db3a8feedf8ee515ecdd369809bcce8082" dependencies = [ - "darling", + "darling 0.13.4", "proc-macro2", "quote", - "syn", + "syn 1.0.107", +] + +[[package]] +name = "serde_with_macros" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "881b6f881b17d13214e5d494c939ebab463d01264ce1811e9d4ac3a882e7695f" +dependencies = [ + "darling 0.20.8", + "proc-macro2", + "quote", + "syn 2.0.58", ] [[package]] @@ -1691,13 +1941,13 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.6" +version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if", "cpufeatures", - "digest 0.10.6", + "digest 0.10.7", ] [[package]] @@ -1718,44 +1968,10 @@ version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bdf0c33fae925bdc080598b84bc15c55e7b9a4a43b3c704da051f977469691c9" dependencies = [ - "digest 0.10.6", + "digest 0.10.7", "keccak", ] -[[package]] -name = "shank" -version = "0.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b63e565b5e95ad88ab38f312e89444c749360641c509ef2de0093b49f55974a5" -dependencies = [ - "shank_macro", -] - -[[package]] -name = "shank_macro" -version = "0.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63927d22a1e8b74bda98cc6e151fcdf178b7abb0dc6c4f81e0bbf5ffe2fc4ec8" -dependencies = [ - "proc-macro2", - "quote", - "shank_macro_impl", - "syn", -] - -[[package]] -name = "shank_macro_impl" -version = "0.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ce03403df682f80f4dc1efafa87a4d0cb89b03726d0565e6364bdca5b9a441" -dependencies = [ - "anyhow", - "proc-macro2", - "quote", - "serde", - "syn", -] - [[package]] name = "signature" version = "1.6.4" @@ -1780,33 +1996,29 @@ checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" [[package]] name = "solana-frozen-abi" -version = "1.14.12" +version = "1.17.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c39813ee5b249cb8ccb325d3639323eb3616e7bb9a2b1502936d7ea20530097" +checksum = "62192fbc1c9f235f44ee771c1fb4f97435a221c0e4fdfc28c66409e3a5aa282a" dependencies = [ - "ahash", + "ahash 0.8.5", "blake3", - "block-buffer 0.9.0", + "block-buffer 0.10.4", "bs58 0.4.0", "bv", "byteorder", "cc", "either", "generic-array", - "getrandom 0.1.16", - "hashbrown 0.12.3", "im", "lazy_static", "log", "memmap2", - "once_cell", - "rand_core 0.6.4", "rustc_version", "serde", "serde_bytes", "serde_derive", "serde_json", - "sha2 0.10.6", + "sha2 0.10.8", "solana-frozen-abi-macro", "subtle", "thiserror", @@ -1814,21 +2026,21 @@ dependencies = [ [[package]] name = "solana-frozen-abi-macro" -version = "1.14.12" +version = "1.17.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dad43ac27c4b8d7a3ce0e2cb8642a7e3b8ea5e3c29ecea38045a8518519adccf" +checksum = "f21b8dacc3627447bf9cbd8025db49eff8750ab309c7ac759c9707c8840fcbab" dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn", + "syn 2.0.58", ] [[package]] name = "solana-logger" -version = "1.14.12" +version = "1.17.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13a18f8d7490f712a4340998fca2b0d35afcdef671320a0e51f40b537363d592" +checksum = "f53d546a360f02bf75a4656b11883d67fad5d2e277f2f7a914e7749840d13cdb" dependencies = [ "env_logger", "lazy_static", @@ -1837,16 +2049,20 @@ dependencies = [ [[package]] name = "solana-program" -version = "1.14.12" +version = "1.17.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dafff676128fe508ab83147b6fb19534fc33f43ec14789da1f1867e9ea06887" +checksum = "a995ee30bf9437532de1e645430feb7582c29dce6a4176cc2f7c3ed00ffc3269" dependencies = [ - "base64 0.13.1", + "ark-bn254", + "ark-ec", + "ark-ff", + "ark-serialize", + "base64 0.21.7", "bincode", - "bitflags", + "bitflags 2.5.0", "blake3", - "borsh", - "borsh-derive", + "borsh 0.10.3", + "borsh 0.9.3", "bs58 0.4.0", "bv", "bytemuck", @@ -1854,26 +2070,27 @@ dependencies = [ "console_error_panic_hook", "console_log", "curve25519-dalek", - "getrandom 0.2.8", + "getrandom 0.2.14", "itertools", "js-sys", "lazy_static", "libc", "libsecp256k1", + "light-poseidon", "log", - "memoffset 0.6.5", - "num-derive", + "memoffset 0.9.1", + "num-bigint", + "num-derive 0.3.3", "num-traits", "parking_lot", - "rand 0.7.3", - "rand_chacha 0.2.2", + "rand 0.8.5", "rustc_version", "rustversion", "serde", "serde_bytes", "serde_derive", "serde_json", - "sha2 0.10.6", + "sha2 0.10.8", "sha3 0.10.6", "solana-frozen-abi", "solana-frozen-abi-macro", @@ -1886,21 +2103,21 @@ dependencies = [ [[package]] name = "solana-sdk" -version = "1.14.12" +version = "1.17.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c702cc57432bc16eab54ad7b5668c2a3cdc72b0f820175972b4857e26ac4f49" +checksum = "eca21ecf52c49fc06189fd69eefc2d20b8dfc22525270423ef072162aaa2fdb9" dependencies = [ "assert_matches", - "base64 0.13.1", + "base64 0.21.7", "bincode", - "bitflags", - "borsh", + "bitflags 2.5.0", + "borsh 0.10.3", "bs58 0.4.0", "bytemuck", "byteorder", "chrono", "derivation-path", - "digest 0.10.6", + "digest 0.10.7", "ed25519-dalek", "ed25519-dalek-bip32", "generic-array", @@ -1911,19 +2128,22 @@ dependencies = [ "libsecp256k1", "log", "memmap2", - "num-derive", + "num-derive 0.3.3", "num-traits", + "num_enum 0.6.1", "pbkdf2 0.11.0", "qstring", + "qualifier_attr", "rand 0.7.3", - "rand_chacha 0.2.2", + "rand 0.8.5", "rustc_version", "rustversion", "serde", "serde_bytes", "serde_derive", "serde_json", - "sha2 0.10.6", + "serde_with 2.3.3", + "sha2 0.10.8", "sha3 0.10.6", "solana-frozen-abi", "solana-frozen-abi-macro", @@ -1937,36 +2157,40 @@ dependencies = [ [[package]] name = "solana-sdk-macro" -version = "1.14.12" +version = "1.17.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f89a14a8f1e7708fe19ee3140125e9d8279945ead74cb09e65c94dd5cf0640c3" +checksum = "3a33c648b1d37f54b0be531b3501230cf5c291bcfd2c9ee0703d654fdfd9e2e9" dependencies = [ "bs58 0.4.0", "proc-macro2", "quote", "rustversion", - "syn", + "syn 2.0.58", ] [[package]] -name = "solana-zk-token-sdk" -version = "1.14.12" +name = "solana-security-txt" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32395c4561673f7b4aa1f3a5b5a654eaa363041f67d92f5d680de72293ef7d1b" +checksum = "468aa43b7edb1f9b7b7b686d5c3aeb6630dc1708e86e31343499dd5c4d775183" + +[[package]] +name = "solana-zk-token-sdk" +version = "1.17.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "845164281a77e06c6c0573d39145a37a3a664936be7106d564c53a61f451ce94" dependencies = [ "aes-gcm-siv", - "arrayref", - "base64 0.13.1", + "base64 0.21.7", "bincode", "bytemuck", "byteorder", - "cipher 0.4.3", "curve25519-dalek", "getrandom 0.1.16", "itertools", "lazy_static", "merlin", - "num-derive", + "num-derive 0.3.3", "num-traits", "rand 0.7.3", "serde", @@ -1981,29 +2205,130 @@ dependencies = [ [[package]] name = "spl-associated-token-account" -version = "1.1.2" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbc000f0fdf1f12f99d77d398137c1751345b18c88258ce0f99b7872cf6c9bd6" +checksum = "4414117bead33f2a5cf059cefac0685592bdd36f31f3caac49b89bff7f6bbf32" dependencies = [ "assert_matches", - "borsh", - "num-derive", + "borsh 0.10.3", + "num-derive 0.4.2", "num-traits", "solana-program", - "spl-token", - "spl-token-2022", + "spl-token 4.0.1", + "spl-token-2022 2.0.1", + "thiserror", +] + +[[package]] +name = "spl-discriminator" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daa600f2fe56f32e923261719bae640d873edadbc5237681a39b8e37bfd4d263" +dependencies = [ + "bytemuck", + "solana-program", + "spl-discriminator-derive", +] + +[[package]] +name = "spl-discriminator-derive" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07fd7858fc4ff8fb0e34090e41d7eb06a823e1057945c26d480bfc21d2338a93" +dependencies = [ + "quote", + "spl-discriminator-syn", + "syn 2.0.58", +] + +[[package]] +name = "spl-discriminator-syn" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18fea7be851bd98d10721782ea958097c03a0c2a07d8d4997041d0ece6319a63" +dependencies = [ + "proc-macro2", + "quote", + "sha2 0.10.8", + "syn 2.0.58", "thiserror", ] [[package]] name = "spl-memo" -version = "3.0.1" +version = "4.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd0dc6f70db6bacea7ff25870b016a65ba1d1b6013536f08e4fd79a8f9005325" +checksum = "58e9bae02de3405079a057fe244c867a08f92d48327d231fc60da831f94caf0a" dependencies = [ "solana-program", ] +[[package]] +name = "spl-pod" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85a5db7e4efb1107b0b8e52a13f035437cdcb36ef99c58f6d467f089d9b2915a" +dependencies = [ + "borsh 0.10.3", + "bytemuck", + "solana-program", + "solana-zk-token-sdk", + "spl-program-error", +] + +[[package]] +name = "spl-program-error" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e0657b6490196971d9e729520ba934911ff41fbb2cb9004463dbe23cf8b4b4f" +dependencies = [ + "num-derive 0.4.2", + "num-traits", + "solana-program", + "spl-program-error-derive", + "thiserror", +] + +[[package]] +name = "spl-program-error-derive" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1845dfe71fd68f70382232742e758557afe973ae19e6c06807b2c30f5d5cb474" +dependencies = [ + "proc-macro2", + "quote", + "sha2 0.10.8", + "syn 2.0.58", +] + +[[package]] +name = "spl-tlv-account-resolution" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "062e148d3eab7b165582757453632ffeef490c02c86a48bfdb4988f63eefb3b9" +dependencies = [ + "bytemuck", + "solana-program", + "spl-discriminator", + "spl-pod", + "spl-program-error", + "spl-type-length-value", +] + +[[package]] +name = "spl-tlv-account-resolution" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f335787add7fa711819f9e7c573f8145a5358a709446fe2d24bf2a88117c90" +dependencies = [ + "bytemuck", + "solana-program", + "spl-discriminator", + "spl-pod", + "spl-program-error", + "spl-type-length-value", +] + [[package]] name = "spl-token" version = "3.5.0" @@ -2012,31 +2337,146 @@ checksum = "8e85e168a785e82564160dcb87b2a8e04cee9bfd1f4d488c729d53d6a4bd300d" dependencies = [ "arrayref", "bytemuck", - "num-derive", + "num-derive 0.3.3", "num-traits", - "num_enum", + "num_enum 0.5.7", + "solana-program", + "thiserror", +] + +[[package]] +name = "spl-token" +version = "4.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95ae123223633a389f95d1da9d49c2d0a50d499e7060b9624626a69e536ad2a4" +dependencies = [ + "arrayref", + "bytemuck", + "num-derive 0.4.2", + "num-traits", + "num_enum 0.7.2", "solana-program", "thiserror", ] [[package]] name = "spl-token-2022" -version = "0.5.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0edb869dbe159b018f17fb9bfa67118c30f232d7f54a73742bc96794dff77ed8" +checksum = "e4abf34a65ba420584a0c35f3903f8d727d1f13ababbdc3f714c6b065a686e86" dependencies = [ "arrayref", "bytemuck", - "num-derive", + "num-derive 0.4.2", "num-traits", - "num_enum", + "num_enum 0.7.2", "solana-program", "solana-zk-token-sdk", "spl-memo", - "spl-token", + "spl-pod", + "spl-token 4.0.1", + "spl-token-metadata-interface", + "spl-transfer-hook-interface 0.3.0", + "spl-type-length-value", "thiserror", ] +[[package]] +name = "spl-token-2022" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9fec83597cf7be923c5c3bdfd2fcc08cdfacd2eeb6c4e413da06b6916f50827" +dependencies = [ + "arrayref", + "bytemuck", + "num-derive 0.4.2", + "num-traits", + "num_enum 0.7.2", + "solana-program", + "solana-security-txt", + "solana-zk-token-sdk", + "spl-memo", + "spl-pod", + "spl-token 4.0.1", + "spl-token-group-interface", + "spl-token-metadata-interface", + "spl-transfer-hook-interface 0.5.1", + "spl-type-length-value", + "thiserror", +] + +[[package]] +name = "spl-token-group-interface" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7eb67fbacd587377a400aba81718abe4424d0e9d5ea510034d3b7f130d102153" +dependencies = [ + "bytemuck", + "solana-program", + "spl-discriminator", + "spl-pod", + "spl-program-error", +] + +[[package]] +name = "spl-token-metadata-interface" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e16aa8f64b6e0eaab3f5034e84d867c8435d8216497b4543a4978a31f4b6e8a8" +dependencies = [ + "borsh 0.10.3", + "solana-program", + "spl-discriminator", + "spl-pod", + "spl-program-error", + "spl-type-length-value", +] + +[[package]] +name = "spl-transfer-hook-interface" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "051d31803f873cabe71aec3c1b849f35248beae5d19a347d93a5c9cccc5d5a9b" +dependencies = [ + "arrayref", + "bytemuck", + "solana-program", + "spl-discriminator", + "spl-pod", + "spl-program-error", + "spl-tlv-account-resolution 0.4.0", + "spl-type-length-value", +] + +[[package]] +name = "spl-transfer-hook-interface" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f6dfe329fcff44cbe2eea994bd8f737f0b0a69faed39e56f9b6ee03badf7e14" +dependencies = [ + "arrayref", + "bytemuck", + "solana-program", + "spl-discriminator", + "spl-pod", + "spl-program-error", + "spl-tlv-account-resolution 0.5.2", + "spl-type-length-value", +] + +[[package]] +name = "spl-type-length-value" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f9ebd75d29c5f48de5f6a9c114e08531030b75b8ac2c557600ac7da0b73b1e8" +dependencies = [ + "bytemuck", + "solana-program", + "spl-discriminator", + "spl-pod", + "spl-program-error", +] + [[package]] name = "static_assertions" version = "1.1.0" @@ -2066,6 +2506,17 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "syn" +version = "2.0.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "synstructure" version = "0.12.6" @@ -2074,7 +2525,7 @@ checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.107", "unicode-xid", ] @@ -2103,22 +2554,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.38" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0" +checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.38" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" +checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.58", ] [[package]] @@ -2164,6 +2615,23 @@ dependencies = [ "serde", ] +[[package]] +name = "toml_datetime" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" + +[[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 = "typenum" version = "1.16.0" @@ -2258,9 +2726,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.83" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -2268,24 +2736,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.83" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn", + "syn 2.0.58", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.83" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2293,22 +2761,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.83" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.58", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.83" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] name = "web-sys" @@ -2321,19 +2789,19 @@ dependencies = [ ] [[package]] -name = "whirlpool" +name = "whirlpool-client" version = "0.2.0" dependencies = [ "anchor-lang", "anchor-spl", - "borsh", - "mpl-token-metadata", + "borsh 0.10.3", + "bytemuck", "proptest", "serde", "serde_json", - "serde_with", + "serde_with 1.14.0", "solana-program", - "spl-token", + "spl-token 3.5.0", "thiserror", "uint", ] @@ -2427,10 +2895,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" [[package]] -name = "yansi" -version = "0.5.1" +name = "winnow" +version = "0.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] + +[[package]] +name = "zerocopy" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.58", +] [[package]] name = "zeroize" @@ -2449,6 +2940,6 @@ checksum = "44bf07cb3e50ea2003396695d58bf46bc9887a1f362260446fad6bc4e79bd36c" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.107", "synstructure", ] diff --git a/docs/.nojekyll b/docs/.nojekyll deleted file mode 100644 index e2ac661..0000000 --- a/docs/.nojekyll +++ /dev/null @@ -1 +0,0 @@ -TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/docs/assets/highlight.css b/docs/assets/highlight.css deleted file mode 100644 index 652dc23..0000000 --- a/docs/assets/highlight.css +++ /dev/null @@ -1,43 +0,0 @@ -:root { - --light-hl-0: #001080; - --dark-hl-0: #9CDCFE; - --light-hl-1: #000000; - --dark-hl-1: #D4D4D4; - --light-hl-2: #A31515; - --dark-hl-2: #CE9178; - --light-code-background: #F5F5F5; - --dark-code-background: #1E1E1E; -} - -@media (prefers-color-scheme: light) { :root { - --hl-0: var(--light-hl-0); - --hl-1: var(--light-hl-1); - --hl-2: var(--light-hl-2); - --code-background: var(--light-code-background); -} } - -@media (prefers-color-scheme: dark) { :root { - --hl-0: var(--dark-hl-0); - --hl-1: var(--dark-hl-1); - --hl-2: var(--dark-hl-2); - --code-background: var(--dark-code-background); -} } - -body.light { - --hl-0: var(--light-hl-0); - --hl-1: var(--light-hl-1); - --hl-2: var(--light-hl-2); - --code-background: var(--light-code-background); -} - -body.dark { - --hl-0: var(--dark-hl-0); - --hl-1: var(--dark-hl-1); - --hl-2: var(--dark-hl-2); - --code-background: var(--dark-code-background); -} - -.hl-0 { color: var(--hl-0); } -.hl-1 { color: var(--hl-1); } -.hl-2 { color: var(--hl-2); } -pre, code { background: var(--code-background); } diff --git a/docs/assets/icons.css b/docs/assets/icons.css deleted file mode 100644 index 776a356..0000000 --- a/docs/assets/icons.css +++ /dev/null @@ -1,1043 +0,0 @@ -.tsd-kind-icon { - display: block; - position: relative; - padding-left: 20px; - text-indent: -20px; -} -.tsd-kind-icon:before { - content: ""; - display: inline-block; - vertical-align: middle; - width: 17px; - height: 17px; - margin: 0 3px 2px 0; - background-image: url(./icons.png); -} -@media (-webkit-min-device-pixel-ratio: 1.5), (min-resolution: 144dpi) { - .tsd-kind-icon:before { - background-image: url(./icons@2x.png); - background-size: 238px 204px; - } -} - -.tsd-signature.tsd-kind-icon:before { - background-position: 0 -153px; -} - -.tsd-kind-object-literal > .tsd-kind-icon:before { - background-position: 0px -17px; -} -.tsd-kind-object-literal.tsd-is-protected > .tsd-kind-icon:before { - background-position: -17px -17px; -} -.tsd-kind-object-literal.tsd-is-private > .tsd-kind-icon:before { - background-position: -34px -17px; -} - -.tsd-kind-class > .tsd-kind-icon:before { - background-position: 0px -34px; -} -.tsd-kind-class.tsd-is-protected > .tsd-kind-icon:before { - background-position: -17px -34px; -} -.tsd-kind-class.tsd-is-private > .tsd-kind-icon:before { - background-position: -34px -34px; -} - -.tsd-kind-class.tsd-has-type-parameter > .tsd-kind-icon:before { - background-position: 0px -51px; -} -.tsd-kind-class.tsd-has-type-parameter.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -17px -51px; -} -.tsd-kind-class.tsd-has-type-parameter.tsd-is-private > .tsd-kind-icon:before { - background-position: -34px -51px; -} - -.tsd-kind-interface > .tsd-kind-icon:before { - background-position: 0px -68px; -} -.tsd-kind-interface.tsd-is-protected > .tsd-kind-icon:before { - background-position: -17px -68px; -} -.tsd-kind-interface.tsd-is-private > .tsd-kind-icon:before { - background-position: -34px -68px; -} - -.tsd-kind-interface.tsd-has-type-parameter > .tsd-kind-icon:before { - background-position: 0px -85px; -} -.tsd-kind-interface.tsd-has-type-parameter.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -17px -85px; -} -.tsd-kind-interface.tsd-has-type-parameter.tsd-is-private - > .tsd-kind-icon:before { - background-position: -34px -85px; -} - -.tsd-kind-namespace > .tsd-kind-icon:before { - background-position: 0px -102px; -} -.tsd-kind-namespace.tsd-is-protected > .tsd-kind-icon:before { - background-position: -17px -102px; -} -.tsd-kind-namespace.tsd-is-private > .tsd-kind-icon:before { - background-position: -34px -102px; -} - -.tsd-kind-module > .tsd-kind-icon:before { - background-position: 0px -102px; -} -.tsd-kind-module.tsd-is-protected > .tsd-kind-icon:before { - background-position: -17px -102px; -} -.tsd-kind-module.tsd-is-private > .tsd-kind-icon:before { - background-position: -34px -102px; -} - -.tsd-kind-enum > .tsd-kind-icon:before { - background-position: 0px -119px; -} -.tsd-kind-enum.tsd-is-protected > .tsd-kind-icon:before { - background-position: -17px -119px; -} -.tsd-kind-enum.tsd-is-private > .tsd-kind-icon:before { - background-position: -34px -119px; -} - -.tsd-kind-enum-member > .tsd-kind-icon:before { - background-position: 0px -136px; -} -.tsd-kind-enum-member.tsd-is-protected > .tsd-kind-icon:before { - background-position: -17px -136px; -} -.tsd-kind-enum-member.tsd-is-private > .tsd-kind-icon:before { - background-position: -34px -136px; -} - -.tsd-kind-signature > .tsd-kind-icon:before { - background-position: 0px -153px; -} -.tsd-kind-signature.tsd-is-protected > .tsd-kind-icon:before { - background-position: -17px -153px; -} -.tsd-kind-signature.tsd-is-private > .tsd-kind-icon:before { - background-position: -34px -153px; -} - -.tsd-kind-type-alias > .tsd-kind-icon:before { - background-position: 0px -170px; -} -.tsd-kind-type-alias.tsd-is-protected > .tsd-kind-icon:before { - background-position: -17px -170px; -} -.tsd-kind-type-alias.tsd-is-private > .tsd-kind-icon:before { - background-position: -34px -170px; -} - -.tsd-kind-type-alias.tsd-has-type-parameter > .tsd-kind-icon:before { - background-position: 0px -187px; -} -.tsd-kind-type-alias.tsd-has-type-parameter.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -17px -187px; -} -.tsd-kind-type-alias.tsd-has-type-parameter.tsd-is-private - > .tsd-kind-icon:before { - background-position: -34px -187px; -} - -.tsd-kind-variable > .tsd-kind-icon:before { - background-position: -136px -0px; -} -.tsd-kind-variable.tsd-is-protected > .tsd-kind-icon:before { - background-position: -153px -0px; -} -.tsd-kind-variable.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -0px; -} -.tsd-kind-variable.tsd-parent-kind-class > .tsd-kind-icon:before { - background-position: -51px -0px; -} -.tsd-kind-variable.tsd-parent-kind-class.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -68px -0px; -} -.tsd-kind-variable.tsd-parent-kind-class.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -85px -0px; -} -.tsd-kind-variable.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -102px -0px; -} -.tsd-kind-variable.tsd-parent-kind-class.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -0px; -} -.tsd-kind-variable.tsd-parent-kind-enum > .tsd-kind-icon:before { - background-position: -170px -0px; -} -.tsd-kind-variable.tsd-parent-kind-enum.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -187px -0px; -} -.tsd-kind-variable.tsd-parent-kind-enum.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -0px; -} -.tsd-kind-variable.tsd-parent-kind-interface > .tsd-kind-icon:before { - background-position: -204px -0px; -} -.tsd-kind-variable.tsd-parent-kind-interface.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -221px -0px; -} - -.tsd-kind-property > .tsd-kind-icon:before { - background-position: -136px -0px; -} -.tsd-kind-property.tsd-is-protected > .tsd-kind-icon:before { - background-position: -153px -0px; -} -.tsd-kind-property.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -0px; -} -.tsd-kind-property.tsd-parent-kind-class > .tsd-kind-icon:before { - background-position: -51px -0px; -} -.tsd-kind-property.tsd-parent-kind-class.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -68px -0px; -} -.tsd-kind-property.tsd-parent-kind-class.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -85px -0px; -} -.tsd-kind-property.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -102px -0px; -} -.tsd-kind-property.tsd-parent-kind-class.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -0px; -} -.tsd-kind-property.tsd-parent-kind-enum > .tsd-kind-icon:before { - background-position: -170px -0px; -} -.tsd-kind-property.tsd-parent-kind-enum.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -187px -0px; -} -.tsd-kind-property.tsd-parent-kind-enum.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -0px; -} -.tsd-kind-property.tsd-parent-kind-interface > .tsd-kind-icon:before { - background-position: -204px -0px; -} -.tsd-kind-property.tsd-parent-kind-interface.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -221px -0px; -} - -.tsd-kind-get-signature > .tsd-kind-icon:before { - background-position: -136px -17px; -} -.tsd-kind-get-signature.tsd-is-protected > .tsd-kind-icon:before { - background-position: -153px -17px; -} -.tsd-kind-get-signature.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -17px; -} -.tsd-kind-get-signature.tsd-parent-kind-class > .tsd-kind-icon:before { - background-position: -51px -17px; -} -.tsd-kind-get-signature.tsd-parent-kind-class.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -68px -17px; -} -.tsd-kind-get-signature.tsd-parent-kind-class.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -85px -17px; -} -.tsd-kind-get-signature.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -102px -17px; -} -.tsd-kind-get-signature.tsd-parent-kind-class.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -17px; -} -.tsd-kind-get-signature.tsd-parent-kind-enum > .tsd-kind-icon:before { - background-position: -170px -17px; -} -.tsd-kind-get-signature.tsd-parent-kind-enum.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -187px -17px; -} -.tsd-kind-get-signature.tsd-parent-kind-enum.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -17px; -} -.tsd-kind-get-signature.tsd-parent-kind-interface > .tsd-kind-icon:before { - background-position: -204px -17px; -} -.tsd-kind-get-signature.tsd-parent-kind-interface.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -221px -17px; -} - -.tsd-kind-set-signature > .tsd-kind-icon:before { - background-position: -136px -34px; -} -.tsd-kind-set-signature.tsd-is-protected > .tsd-kind-icon:before { - background-position: -153px -34px; -} -.tsd-kind-set-signature.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -34px; -} -.tsd-kind-set-signature.tsd-parent-kind-class > .tsd-kind-icon:before { - background-position: -51px -34px; -} -.tsd-kind-set-signature.tsd-parent-kind-class.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -68px -34px; -} -.tsd-kind-set-signature.tsd-parent-kind-class.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -85px -34px; -} -.tsd-kind-set-signature.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -102px -34px; -} -.tsd-kind-set-signature.tsd-parent-kind-class.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -34px; -} -.tsd-kind-set-signature.tsd-parent-kind-enum > .tsd-kind-icon:before { - background-position: -170px -34px; -} -.tsd-kind-set-signature.tsd-parent-kind-enum.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -187px -34px; -} -.tsd-kind-set-signature.tsd-parent-kind-enum.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -34px; -} -.tsd-kind-set-signature.tsd-parent-kind-interface > .tsd-kind-icon:before { - background-position: -204px -34px; -} -.tsd-kind-set-signature.tsd-parent-kind-interface.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -221px -34px; -} - -.tsd-kind-accessor > .tsd-kind-icon:before { - background-position: -136px -51px; -} -.tsd-kind-accessor.tsd-is-protected > .tsd-kind-icon:before { - background-position: -153px -51px; -} -.tsd-kind-accessor.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -51px; -} -.tsd-kind-accessor.tsd-parent-kind-class > .tsd-kind-icon:before { - background-position: -51px -51px; -} -.tsd-kind-accessor.tsd-parent-kind-class.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -68px -51px; -} -.tsd-kind-accessor.tsd-parent-kind-class.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -85px -51px; -} -.tsd-kind-accessor.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -102px -51px; -} -.tsd-kind-accessor.tsd-parent-kind-class.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -51px; -} -.tsd-kind-accessor.tsd-parent-kind-enum > .tsd-kind-icon:before { - background-position: -170px -51px; -} -.tsd-kind-accessor.tsd-parent-kind-enum.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -187px -51px; -} -.tsd-kind-accessor.tsd-parent-kind-enum.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -51px; -} -.tsd-kind-accessor.tsd-parent-kind-interface > .tsd-kind-icon:before { - background-position: -204px -51px; -} -.tsd-kind-accessor.tsd-parent-kind-interface.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -221px -51px; -} - -.tsd-kind-function > .tsd-kind-icon:before { - background-position: -136px -68px; -} -.tsd-kind-function.tsd-is-protected > .tsd-kind-icon:before { - background-position: -153px -68px; -} -.tsd-kind-function.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -68px; -} -.tsd-kind-function.tsd-parent-kind-class > .tsd-kind-icon:before { - background-position: -51px -68px; -} -.tsd-kind-function.tsd-parent-kind-class.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -68px -68px; -} -.tsd-kind-function.tsd-parent-kind-class.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -85px -68px; -} -.tsd-kind-function.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -102px -68px; -} -.tsd-kind-function.tsd-parent-kind-class.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -68px; -} -.tsd-kind-function.tsd-parent-kind-enum > .tsd-kind-icon:before { - background-position: -170px -68px; -} -.tsd-kind-function.tsd-parent-kind-enum.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -187px -68px; -} -.tsd-kind-function.tsd-parent-kind-enum.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -68px; -} -.tsd-kind-function.tsd-parent-kind-interface > .tsd-kind-icon:before { - background-position: -204px -68px; -} -.tsd-kind-function.tsd-parent-kind-interface.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -221px -68px; -} - -.tsd-kind-method > .tsd-kind-icon:before { - background-position: -136px -68px; -} -.tsd-kind-method.tsd-is-protected > .tsd-kind-icon:before { - background-position: -153px -68px; -} -.tsd-kind-method.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -68px; -} -.tsd-kind-method.tsd-parent-kind-class > .tsd-kind-icon:before { - background-position: -51px -68px; -} -.tsd-kind-method.tsd-parent-kind-class.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -68px -68px; -} -.tsd-kind-method.tsd-parent-kind-class.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -85px -68px; -} -.tsd-kind-method.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -102px -68px; -} -.tsd-kind-method.tsd-parent-kind-class.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -68px; -} -.tsd-kind-method.tsd-parent-kind-enum > .tsd-kind-icon:before { - background-position: -170px -68px; -} -.tsd-kind-method.tsd-parent-kind-enum.tsd-is-protected > .tsd-kind-icon:before { - background-position: -187px -68px; -} -.tsd-kind-method.tsd-parent-kind-enum.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -68px; -} -.tsd-kind-method.tsd-parent-kind-interface > .tsd-kind-icon:before { - background-position: -204px -68px; -} -.tsd-kind-method.tsd-parent-kind-interface.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -221px -68px; -} - -.tsd-kind-call-signature > .tsd-kind-icon:before { - background-position: -136px -68px; -} -.tsd-kind-call-signature.tsd-is-protected > .tsd-kind-icon:before { - background-position: -153px -68px; -} -.tsd-kind-call-signature.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -68px; -} -.tsd-kind-call-signature.tsd-parent-kind-class > .tsd-kind-icon:before { - background-position: -51px -68px; -} -.tsd-kind-call-signature.tsd-parent-kind-class.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -68px -68px; -} -.tsd-kind-call-signature.tsd-parent-kind-class.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -85px -68px; -} -.tsd-kind-call-signature.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -102px -68px; -} -.tsd-kind-call-signature.tsd-parent-kind-class.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -68px; -} -.tsd-kind-call-signature.tsd-parent-kind-enum > .tsd-kind-icon:before { - background-position: -170px -68px; -} -.tsd-kind-call-signature.tsd-parent-kind-enum.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -187px -68px; -} -.tsd-kind-call-signature.tsd-parent-kind-enum.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -68px; -} -.tsd-kind-call-signature.tsd-parent-kind-interface > .tsd-kind-icon:before { - background-position: -204px -68px; -} -.tsd-kind-call-signature.tsd-parent-kind-interface.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -221px -68px; -} - -.tsd-kind-function.tsd-has-type-parameter > .tsd-kind-icon:before { - background-position: -136px -85px; -} -.tsd-kind-function.tsd-has-type-parameter.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -153px -85px; -} -.tsd-kind-function.tsd-has-type-parameter.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -85px; -} -.tsd-kind-function.tsd-has-type-parameter.tsd-parent-kind-class - > .tsd-kind-icon:before { - background-position: -51px -85px; -} -.tsd-kind-function.tsd-has-type-parameter.tsd-parent-kind-class.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -68px -85px; -} -.tsd-kind-function.tsd-has-type-parameter.tsd-parent-kind-class.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -85px -85px; -} -.tsd-kind-function.tsd-has-type-parameter.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -102px -85px; -} -.tsd-kind-function.tsd-has-type-parameter.tsd-parent-kind-class.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -85px; -} -.tsd-kind-function.tsd-has-type-parameter.tsd-parent-kind-enum - > .tsd-kind-icon:before { - background-position: -170px -85px; -} -.tsd-kind-function.tsd-has-type-parameter.tsd-parent-kind-enum.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -187px -85px; -} -.tsd-kind-function.tsd-has-type-parameter.tsd-parent-kind-enum.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -85px; -} -.tsd-kind-function.tsd-has-type-parameter.tsd-parent-kind-interface - > .tsd-kind-icon:before { - background-position: -204px -85px; -} -.tsd-kind-function.tsd-has-type-parameter.tsd-parent-kind-interface.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -221px -85px; -} - -.tsd-kind-method.tsd-has-type-parameter > .tsd-kind-icon:before { - background-position: -136px -85px; -} -.tsd-kind-method.tsd-has-type-parameter.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -153px -85px; -} -.tsd-kind-method.tsd-has-type-parameter.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -85px; -} -.tsd-kind-method.tsd-has-type-parameter.tsd-parent-kind-class - > .tsd-kind-icon:before { - background-position: -51px -85px; -} -.tsd-kind-method.tsd-has-type-parameter.tsd-parent-kind-class.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -68px -85px; -} -.tsd-kind-method.tsd-has-type-parameter.tsd-parent-kind-class.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -85px -85px; -} -.tsd-kind-method.tsd-has-type-parameter.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -102px -85px; -} -.tsd-kind-method.tsd-has-type-parameter.tsd-parent-kind-class.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -85px; -} -.tsd-kind-method.tsd-has-type-parameter.tsd-parent-kind-enum - > .tsd-kind-icon:before { - background-position: -170px -85px; -} -.tsd-kind-method.tsd-has-type-parameter.tsd-parent-kind-enum.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -187px -85px; -} -.tsd-kind-method.tsd-has-type-parameter.tsd-parent-kind-enum.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -85px; -} -.tsd-kind-method.tsd-has-type-parameter.tsd-parent-kind-interface - > .tsd-kind-icon:before { - background-position: -204px -85px; -} -.tsd-kind-method.tsd-has-type-parameter.tsd-parent-kind-interface.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -221px -85px; -} - -.tsd-kind-constructor > .tsd-kind-icon:before { - background-position: -136px -102px; -} -.tsd-kind-constructor.tsd-is-protected > .tsd-kind-icon:before { - background-position: -153px -102px; -} -.tsd-kind-constructor.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -102px; -} -.tsd-kind-constructor.tsd-parent-kind-class > .tsd-kind-icon:before { - background-position: -51px -102px; -} -.tsd-kind-constructor.tsd-parent-kind-class.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -68px -102px; -} -.tsd-kind-constructor.tsd-parent-kind-class.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -85px -102px; -} -.tsd-kind-constructor.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -102px -102px; -} -.tsd-kind-constructor.tsd-parent-kind-class.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -102px; -} -.tsd-kind-constructor.tsd-parent-kind-enum > .tsd-kind-icon:before { - background-position: -170px -102px; -} -.tsd-kind-constructor.tsd-parent-kind-enum.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -187px -102px; -} -.tsd-kind-constructor.tsd-parent-kind-enum.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -102px; -} -.tsd-kind-constructor.tsd-parent-kind-interface > .tsd-kind-icon:before { - background-position: -204px -102px; -} -.tsd-kind-constructor.tsd-parent-kind-interface.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -221px -102px; -} - -.tsd-kind-constructor-signature > .tsd-kind-icon:before { - background-position: -136px -102px; -} -.tsd-kind-constructor-signature.tsd-is-protected > .tsd-kind-icon:before { - background-position: -153px -102px; -} -.tsd-kind-constructor-signature.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -102px; -} -.tsd-kind-constructor-signature.tsd-parent-kind-class > .tsd-kind-icon:before { - background-position: -51px -102px; -} -.tsd-kind-constructor-signature.tsd-parent-kind-class.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -68px -102px; -} -.tsd-kind-constructor-signature.tsd-parent-kind-class.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -85px -102px; -} -.tsd-kind-constructor-signature.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -102px -102px; -} -.tsd-kind-constructor-signature.tsd-parent-kind-class.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -102px; -} -.tsd-kind-constructor-signature.tsd-parent-kind-enum > .tsd-kind-icon:before { - background-position: -170px -102px; -} -.tsd-kind-constructor-signature.tsd-parent-kind-enum.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -187px -102px; -} -.tsd-kind-constructor-signature.tsd-parent-kind-enum.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -102px; -} -.tsd-kind-constructor-signature.tsd-parent-kind-interface - > .tsd-kind-icon:before { - background-position: -204px -102px; -} -.tsd-kind-constructor-signature.tsd-parent-kind-interface.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -221px -102px; -} - -.tsd-kind-index-signature > .tsd-kind-icon:before { - background-position: -136px -119px; -} -.tsd-kind-index-signature.tsd-is-protected > .tsd-kind-icon:before { - background-position: -153px -119px; -} -.tsd-kind-index-signature.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -119px; -} -.tsd-kind-index-signature.tsd-parent-kind-class > .tsd-kind-icon:before { - background-position: -51px -119px; -} -.tsd-kind-index-signature.tsd-parent-kind-class.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -68px -119px; -} -.tsd-kind-index-signature.tsd-parent-kind-class.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -85px -119px; -} -.tsd-kind-index-signature.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -102px -119px; -} -.tsd-kind-index-signature.tsd-parent-kind-class.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -119px; -} -.tsd-kind-index-signature.tsd-parent-kind-enum > .tsd-kind-icon:before { - background-position: -170px -119px; -} -.tsd-kind-index-signature.tsd-parent-kind-enum.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -187px -119px; -} -.tsd-kind-index-signature.tsd-parent-kind-enum.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -119px; -} -.tsd-kind-index-signature.tsd-parent-kind-interface > .tsd-kind-icon:before { - background-position: -204px -119px; -} -.tsd-kind-index-signature.tsd-parent-kind-interface.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -221px -119px; -} - -.tsd-kind-event > .tsd-kind-icon:before { - background-position: -136px -136px; -} -.tsd-kind-event.tsd-is-protected > .tsd-kind-icon:before { - background-position: -153px -136px; -} -.tsd-kind-event.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -136px; -} -.tsd-kind-event.tsd-parent-kind-class > .tsd-kind-icon:before { - background-position: -51px -136px; -} -.tsd-kind-event.tsd-parent-kind-class.tsd-is-inherited > .tsd-kind-icon:before { - background-position: -68px -136px; -} -.tsd-kind-event.tsd-parent-kind-class.tsd-is-protected > .tsd-kind-icon:before { - background-position: -85px -136px; -} -.tsd-kind-event.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -102px -136px; -} -.tsd-kind-event.tsd-parent-kind-class.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -136px; -} -.tsd-kind-event.tsd-parent-kind-enum > .tsd-kind-icon:before { - background-position: -170px -136px; -} -.tsd-kind-event.tsd-parent-kind-enum.tsd-is-protected > .tsd-kind-icon:before { - background-position: -187px -136px; -} -.tsd-kind-event.tsd-parent-kind-enum.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -136px; -} -.tsd-kind-event.tsd-parent-kind-interface > .tsd-kind-icon:before { - background-position: -204px -136px; -} -.tsd-kind-event.tsd-parent-kind-interface.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -221px -136px; -} - -.tsd-is-static > .tsd-kind-icon:before { - background-position: -136px -153px; -} -.tsd-is-static.tsd-is-protected > .tsd-kind-icon:before { - background-position: -153px -153px; -} -.tsd-is-static.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -153px; -} -.tsd-is-static.tsd-parent-kind-class > .tsd-kind-icon:before { - background-position: -51px -153px; -} -.tsd-is-static.tsd-parent-kind-class.tsd-is-inherited > .tsd-kind-icon:before { - background-position: -68px -153px; -} -.tsd-is-static.tsd-parent-kind-class.tsd-is-protected > .tsd-kind-icon:before { - background-position: -85px -153px; -} -.tsd-is-static.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -102px -153px; -} -.tsd-is-static.tsd-parent-kind-class.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -153px; -} -.tsd-is-static.tsd-parent-kind-enum > .tsd-kind-icon:before { - background-position: -170px -153px; -} -.tsd-is-static.tsd-parent-kind-enum.tsd-is-protected > .tsd-kind-icon:before { - background-position: -187px -153px; -} -.tsd-is-static.tsd-parent-kind-enum.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -153px; -} -.tsd-is-static.tsd-parent-kind-interface > .tsd-kind-icon:before { - background-position: -204px -153px; -} -.tsd-is-static.tsd-parent-kind-interface.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -221px -153px; -} - -.tsd-is-static.tsd-kind-function > .tsd-kind-icon:before { - background-position: -136px -170px; -} -.tsd-is-static.tsd-kind-function.tsd-is-protected > .tsd-kind-icon:before { - background-position: -153px -170px; -} -.tsd-is-static.tsd-kind-function.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -170px; -} -.tsd-is-static.tsd-kind-function.tsd-parent-kind-class > .tsd-kind-icon:before { - background-position: -51px -170px; -} -.tsd-is-static.tsd-kind-function.tsd-parent-kind-class.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -68px -170px; -} -.tsd-is-static.tsd-kind-function.tsd-parent-kind-class.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -85px -170px; -} -.tsd-is-static.tsd-kind-function.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -102px -170px; -} -.tsd-is-static.tsd-kind-function.tsd-parent-kind-class.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -170px; -} -.tsd-is-static.tsd-kind-function.tsd-parent-kind-enum > .tsd-kind-icon:before { - background-position: -170px -170px; -} -.tsd-is-static.tsd-kind-function.tsd-parent-kind-enum.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -187px -170px; -} -.tsd-is-static.tsd-kind-function.tsd-parent-kind-enum.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -170px; -} -.tsd-is-static.tsd-kind-function.tsd-parent-kind-interface - > .tsd-kind-icon:before { - background-position: -204px -170px; -} -.tsd-is-static.tsd-kind-function.tsd-parent-kind-interface.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -221px -170px; -} - -.tsd-is-static.tsd-kind-method > .tsd-kind-icon:before { - background-position: -136px -170px; -} -.tsd-is-static.tsd-kind-method.tsd-is-protected > .tsd-kind-icon:before { - background-position: -153px -170px; -} -.tsd-is-static.tsd-kind-method.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -170px; -} -.tsd-is-static.tsd-kind-method.tsd-parent-kind-class > .tsd-kind-icon:before { - background-position: -51px -170px; -} -.tsd-is-static.tsd-kind-method.tsd-parent-kind-class.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -68px -170px; -} -.tsd-is-static.tsd-kind-method.tsd-parent-kind-class.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -85px -170px; -} -.tsd-is-static.tsd-kind-method.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -102px -170px; -} -.tsd-is-static.tsd-kind-method.tsd-parent-kind-class.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -170px; -} -.tsd-is-static.tsd-kind-method.tsd-parent-kind-enum > .tsd-kind-icon:before { - background-position: -170px -170px; -} -.tsd-is-static.tsd-kind-method.tsd-parent-kind-enum.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -187px -170px; -} -.tsd-is-static.tsd-kind-method.tsd-parent-kind-enum.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -170px; -} -.tsd-is-static.tsd-kind-method.tsd-parent-kind-interface - > .tsd-kind-icon:before { - background-position: -204px -170px; -} -.tsd-is-static.tsd-kind-method.tsd-parent-kind-interface.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -221px -170px; -} - -.tsd-is-static.tsd-kind-call-signature > .tsd-kind-icon:before { - background-position: -136px -170px; -} -.tsd-is-static.tsd-kind-call-signature.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -153px -170px; -} -.tsd-is-static.tsd-kind-call-signature.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -170px; -} -.tsd-is-static.tsd-kind-call-signature.tsd-parent-kind-class - > .tsd-kind-icon:before { - background-position: -51px -170px; -} -.tsd-is-static.tsd-kind-call-signature.tsd-parent-kind-class.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -68px -170px; -} -.tsd-is-static.tsd-kind-call-signature.tsd-parent-kind-class.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -85px -170px; -} -.tsd-is-static.tsd-kind-call-signature.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -102px -170px; -} -.tsd-is-static.tsd-kind-call-signature.tsd-parent-kind-class.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -170px; -} -.tsd-is-static.tsd-kind-call-signature.tsd-parent-kind-enum - > .tsd-kind-icon:before { - background-position: -170px -170px; -} -.tsd-is-static.tsd-kind-call-signature.tsd-parent-kind-enum.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -187px -170px; -} -.tsd-is-static.tsd-kind-call-signature.tsd-parent-kind-enum.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -170px; -} -.tsd-is-static.tsd-kind-call-signature.tsd-parent-kind-interface - > .tsd-kind-icon:before { - background-position: -204px -170px; -} -.tsd-is-static.tsd-kind-call-signature.tsd-parent-kind-interface.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -221px -170px; -} - -.tsd-is-static.tsd-kind-event > .tsd-kind-icon:before { - background-position: -136px -187px; -} -.tsd-is-static.tsd-kind-event.tsd-is-protected > .tsd-kind-icon:before { - background-position: -153px -187px; -} -.tsd-is-static.tsd-kind-event.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -187px; -} -.tsd-is-static.tsd-kind-event.tsd-parent-kind-class > .tsd-kind-icon:before { - background-position: -51px -187px; -} -.tsd-is-static.tsd-kind-event.tsd-parent-kind-class.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -68px -187px; -} -.tsd-is-static.tsd-kind-event.tsd-parent-kind-class.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -85px -187px; -} -.tsd-is-static.tsd-kind-event.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -102px -187px; -} -.tsd-is-static.tsd-kind-event.tsd-parent-kind-class.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -187px; -} -.tsd-is-static.tsd-kind-event.tsd-parent-kind-enum > .tsd-kind-icon:before { - background-position: -170px -187px; -} -.tsd-is-static.tsd-kind-event.tsd-parent-kind-enum.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -187px -187px; -} -.tsd-is-static.tsd-kind-event.tsd-parent-kind-enum.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -187px; -} -.tsd-is-static.tsd-kind-event.tsd-parent-kind-interface - > .tsd-kind-icon:before { - background-position: -204px -187px; -} -.tsd-is-static.tsd-kind-event.tsd-parent-kind-interface.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -221px -187px; -} diff --git a/docs/assets/icons.png b/docs/assets/icons.png deleted file mode 100644 index 3836d5f..0000000 Binary files a/docs/assets/icons.png and /dev/null differ diff --git a/docs/assets/icons@2x.png b/docs/assets/icons@2x.png deleted file mode 100644 index 5a209e2..0000000 Binary files a/docs/assets/icons@2x.png and /dev/null differ diff --git a/docs/assets/main.js b/docs/assets/main.js deleted file mode 100644 index bd45452..0000000 --- a/docs/assets/main.js +++ /dev/null @@ -1,52 +0,0 @@ -(()=>{var Ce=Object.create;var ue=Object.defineProperty;var Pe=Object.getOwnPropertyDescriptor;var Oe=Object.getOwnPropertyNames;var Re=Object.getPrototypeOf,_e=Object.prototype.hasOwnProperty;var Me=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports);var De=(t,e,r,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of Oe(e))!_e.call(t,i)&&i!==r&&ue(t,i,{get:()=>e[i],enumerable:!(n=Pe(e,i))||n.enumerable});return t};var Fe=(t,e,r)=>(r=t!=null?Ce(Re(t)):{},De(e||!t||!t.__esModule?ue(r,"default",{value:t,enumerable:!0}):r,t));var pe=Me((de,fe)=>{(function(){var t=function(e){var r=new t.Builder;return r.pipeline.add(t.trimmer,t.stopWordFilter,t.stemmer),r.searchPipeline.add(t.stemmer),e.call(r,r),r.build()};t.version="2.3.9";t.utils={},t.utils.warn=function(e){return function(r){e.console&&console.warn&&console.warn(r)}}(this),t.utils.asString=function(e){return e==null?"":e.toString()},t.utils.clone=function(e){if(e==null)return e;for(var r=Object.create(null),n=Object.keys(e),i=0;i0){var h=t.utils.clone(r)||{};h.position=[a,u],h.index=s.length,s.push(new t.Token(n.slice(a,o),h))}a=o+1}}return s},t.tokenizer.separator=/[\s\-]+/;t.Pipeline=function(){this._stack=[]},t.Pipeline.registeredFunctions=Object.create(null),t.Pipeline.registerFunction=function(e,r){r in this.registeredFunctions&&t.utils.warn("Overwriting existing registered function: "+r),e.label=r,t.Pipeline.registeredFunctions[e.label]=e},t.Pipeline.warnIfFunctionNotRegistered=function(e){var r=e.label&&e.label in this.registeredFunctions;r||t.utils.warn(`Function is not registered with pipeline. This may cause problems when serialising the index. -`,e)},t.Pipeline.load=function(e){var r=new t.Pipeline;return e.forEach(function(n){var i=t.Pipeline.registeredFunctions[n];if(i)r.add(i);else throw new Error("Cannot load unregistered function: "+n)}),r},t.Pipeline.prototype.add=function(){var e=Array.prototype.slice.call(arguments);e.forEach(function(r){t.Pipeline.warnIfFunctionNotRegistered(r),this._stack.push(r)},this)},t.Pipeline.prototype.after=function(e,r){t.Pipeline.warnIfFunctionNotRegistered(r);var n=this._stack.indexOf(e);if(n==-1)throw new Error("Cannot find existingFn");n=n+1,this._stack.splice(n,0,r)},t.Pipeline.prototype.before=function(e,r){t.Pipeline.warnIfFunctionNotRegistered(r);var n=this._stack.indexOf(e);if(n==-1)throw new Error("Cannot find existingFn");this._stack.splice(n,0,r)},t.Pipeline.prototype.remove=function(e){var r=this._stack.indexOf(e);r!=-1&&this._stack.splice(r,1)},t.Pipeline.prototype.run=function(e){for(var r=this._stack.length,n=0;n1&&(oe&&(n=s),o!=e);)i=n-r,s=r+Math.floor(i/2),o=this.elements[s*2];if(o==e||o>e)return s*2;if(ol?h+=2:a==l&&(r+=n[u+1]*i[h+1],u+=2,h+=2);return r},t.Vector.prototype.similarity=function(e){return this.dot(e)/this.magnitude()||0},t.Vector.prototype.toArray=function(){for(var e=new Array(this.elements.length/2),r=1,n=0;r0){var o=s.str.charAt(0),a;o in s.node.edges?a=s.node.edges[o]:(a=new t.TokenSet,s.node.edges[o]=a),s.str.length==1&&(a.final=!0),i.push({node:a,editsRemaining:s.editsRemaining,str:s.str.slice(1)})}if(s.editsRemaining!=0){if("*"in s.node.edges)var l=s.node.edges["*"];else{var l=new t.TokenSet;s.node.edges["*"]=l}if(s.str.length==0&&(l.final=!0),i.push({node:l,editsRemaining:s.editsRemaining-1,str:s.str}),s.str.length>1&&i.push({node:s.node,editsRemaining:s.editsRemaining-1,str:s.str.slice(1)}),s.str.length==1&&(s.node.final=!0),s.str.length>=1){if("*"in s.node.edges)var u=s.node.edges["*"];else{var u=new t.TokenSet;s.node.edges["*"]=u}s.str.length==1&&(u.final=!0),i.push({node:u,editsRemaining:s.editsRemaining-1,str:s.str.slice(1)})}if(s.str.length>1){var h=s.str.charAt(0),f=s.str.charAt(1),p;f in s.node.edges?p=s.node.edges[f]:(p=new t.TokenSet,s.node.edges[f]=p),s.str.length==1&&(p.final=!0),i.push({node:p,editsRemaining:s.editsRemaining-1,str:h+s.str.slice(2)})}}}return n},t.TokenSet.fromString=function(e){for(var r=new t.TokenSet,n=r,i=0,s=e.length;i=e;r--){var n=this.uncheckedNodes[r],i=n.child.toString();i in this.minimizedNodes?n.parent.edges[n.char]=this.minimizedNodes[i]:(n.child._str=i,this.minimizedNodes[i]=n.child),this.uncheckedNodes.pop()}};t.Index=function(e){this.invertedIndex=e.invertedIndex,this.fieldVectors=e.fieldVectors,this.tokenSet=e.tokenSet,this.fields=e.fields,this.pipeline=e.pipeline},t.Index.prototype.search=function(e){return this.query(function(r){var n=new t.QueryParser(e,r);n.parse()})},t.Index.prototype.query=function(e){for(var r=new t.Query(this.fields),n=Object.create(null),i=Object.create(null),s=Object.create(null),o=Object.create(null),a=Object.create(null),l=0;l1?this._b=1:this._b=e},t.Builder.prototype.k1=function(e){this._k1=e},t.Builder.prototype.add=function(e,r){var n=e[this._ref],i=Object.keys(this._fields);this._documents[n]=r||{},this.documentCount+=1;for(var s=0;s=this.length)return t.QueryLexer.EOS;var e=this.str.charAt(this.pos);return this.pos+=1,e},t.QueryLexer.prototype.width=function(){return this.pos-this.start},t.QueryLexer.prototype.ignore=function(){this.start==this.pos&&(this.pos+=1),this.start=this.pos},t.QueryLexer.prototype.backup=function(){this.pos-=1},t.QueryLexer.prototype.acceptDigitRun=function(){var e,r;do e=this.next(),r=e.charCodeAt(0);while(r>47&&r<58);e!=t.QueryLexer.EOS&&this.backup()},t.QueryLexer.prototype.more=function(){return this.pos1&&(e.backup(),e.emit(t.QueryLexer.TERM)),e.ignore(),e.more())return t.QueryLexer.lexText},t.QueryLexer.lexEditDistance=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(t.QueryLexer.EDIT_DISTANCE),t.QueryLexer.lexText},t.QueryLexer.lexBoost=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(t.QueryLexer.BOOST),t.QueryLexer.lexText},t.QueryLexer.lexEOS=function(e){e.width()>0&&e.emit(t.QueryLexer.TERM)},t.QueryLexer.termSeparator=t.tokenizer.separator,t.QueryLexer.lexText=function(e){for(;;){var r=e.next();if(r==t.QueryLexer.EOS)return t.QueryLexer.lexEOS;if(r.charCodeAt(0)==92){e.escapeCharacter();continue}if(r==":")return t.QueryLexer.lexField;if(r=="~")return e.backup(),e.width()>0&&e.emit(t.QueryLexer.TERM),t.QueryLexer.lexEditDistance;if(r=="^")return e.backup(),e.width()>0&&e.emit(t.QueryLexer.TERM),t.QueryLexer.lexBoost;if(r=="+"&&e.width()===1||r=="-"&&e.width()===1)return e.emit(t.QueryLexer.PRESENCE),t.QueryLexer.lexText;if(r.match(t.QueryLexer.termSeparator))return t.QueryLexer.lexTerm}},t.QueryParser=function(e,r){this.lexer=new t.QueryLexer(e),this.query=r,this.currentClause={},this.lexemeIdx=0},t.QueryParser.prototype.parse=function(){this.lexer.run(),this.lexemes=this.lexer.lexemes;for(var e=t.QueryParser.parseClause;e;)e=e(this);return this.query},t.QueryParser.prototype.peekLexeme=function(){return this.lexemes[this.lexemeIdx]},t.QueryParser.prototype.consumeLexeme=function(){var e=this.peekLexeme();return this.lexemeIdx+=1,e},t.QueryParser.prototype.nextClause=function(){var e=this.currentClause;this.query.clause(e),this.currentClause={}},t.QueryParser.parseClause=function(e){var r=e.peekLexeme();if(r!=null)switch(r.type){case t.QueryLexer.PRESENCE:return t.QueryParser.parsePresence;case t.QueryLexer.FIELD:return t.QueryParser.parseField;case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var n="expected either a field or a term, found "+r.type;throw r.str.length>=1&&(n+=" with value '"+r.str+"'"),new t.QueryParseError(n,r.start,r.end)}},t.QueryParser.parsePresence=function(e){var r=e.consumeLexeme();if(r!=null){switch(r.str){case"-":e.currentClause.presence=t.Query.presence.PROHIBITED;break;case"+":e.currentClause.presence=t.Query.presence.REQUIRED;break;default:var n="unrecognised presence operator'"+r.str+"'";throw new t.QueryParseError(n,r.start,r.end)}var i=e.peekLexeme();if(i==null){var n="expecting term or field, found nothing";throw new t.QueryParseError(n,r.start,r.end)}switch(i.type){case t.QueryLexer.FIELD:return t.QueryParser.parseField;case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var n="expecting term or field, found '"+i.type+"'";throw new t.QueryParseError(n,i.start,i.end)}}},t.QueryParser.parseField=function(e){var r=e.consumeLexeme();if(r!=null){if(e.query.allFields.indexOf(r.str)==-1){var n=e.query.allFields.map(function(o){return"'"+o+"'"}).join(", "),i="unrecognised field '"+r.str+"', possible fields: "+n;throw new t.QueryParseError(i,r.start,r.end)}e.currentClause.fields=[r.str];var s=e.peekLexeme();if(s==null){var i="expecting term, found nothing";throw new t.QueryParseError(i,r.start,r.end)}switch(s.type){case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var i="expecting term, found '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},t.QueryParser.parseTerm=function(e){var r=e.consumeLexeme();if(r!=null){e.currentClause.term=r.str.toLowerCase(),r.str.indexOf("*")!=-1&&(e.currentClause.usePipeline=!1);var n=e.peekLexeme();if(n==null){e.nextClause();return}switch(n.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+n.type+"'";throw new t.QueryParseError(i,n.start,n.end)}}},t.QueryParser.parseEditDistance=function(e){var r=e.consumeLexeme();if(r!=null){var n=parseInt(r.str,10);if(isNaN(n)){var i="edit distance must be numeric";throw new t.QueryParseError(i,r.start,r.end)}e.currentClause.editDistance=n;var s=e.peekLexeme();if(s==null){e.nextClause();return}switch(s.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},t.QueryParser.parseBoost=function(e){var r=e.consumeLexeme();if(r!=null){var n=parseInt(r.str,10);if(isNaN(n)){var i="boost must be numeric";throw new t.QueryParseError(i,r.start,r.end)}e.currentClause.boost=n;var s=e.peekLexeme();if(s==null){e.nextClause();return}switch(s.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},function(e,r){typeof define=="function"&&define.amd?define(r):typeof de=="object"?fe.exports=r():e.lunr=r()}(this,function(){return t})})()});var ce=[];function N(t,e){ce.push({selector:e,constructor:t})}var Y=class{constructor(){this.createComponents(document.body)}createComponents(e){ce.forEach(r=>{e.querySelectorAll(r.selector).forEach(n=>{n.dataset.hasInstance||(new r.constructor({el:n}),n.dataset.hasInstance=String(!0))})})}};var k=class{constructor(e){this.el=e.el}};var J=class{constructor(){this.listeners={}}addEventListener(e,r){e in this.listeners||(this.listeners[e]=[]),this.listeners[e].push(r)}removeEventListener(e,r){if(!(e in this.listeners))return;let n=this.listeners[e];for(let i=0,s=n.length;i{let r=Date.now();return(...n)=>{r+e-Date.now()<0&&(t(...n),r=Date.now())}};var ie=class extends J{constructor(){super();this.scrollTop=0;this.lastY=0;this.width=0;this.height=0;this.showToolbar=!0;this.toolbar=document.querySelector(".tsd-page-toolbar"),this.secondaryNav=document.querySelector(".tsd-navigation.secondary"),window.addEventListener("scroll",ne(()=>this.onScroll(),10)),window.addEventListener("resize",ne(()=>this.onResize(),10)),this.onResize(),this.onScroll()}triggerResize(){let r=new CustomEvent("resize",{detail:{width:this.width,height:this.height}});this.dispatchEvent(r)}onResize(){this.width=window.innerWidth||0,this.height=window.innerHeight||0;let r=new CustomEvent("resize",{detail:{width:this.width,height:this.height}});this.dispatchEvent(r)}onScroll(){this.scrollTop=window.scrollY||0;let r=new CustomEvent("scroll",{detail:{scrollTop:this.scrollTop}});this.dispatchEvent(r),this.hideShowToolbar()}hideShowToolbar(){var n;let r=this.showToolbar;this.showToolbar=this.lastY>=this.scrollTop||this.scrollTop<=0,r!==this.showToolbar&&(this.toolbar.classList.toggle("tsd-page-toolbar--hide"),(n=this.secondaryNav)==null||n.classList.toggle("tsd-navigation--toolbar-hide")),this.lastY=this.scrollTop}},Q=ie;Q.instance=new ie;var X=class extends k{constructor(r){super(r);this.anchors=[];this.index=-1;Q.instance.addEventListener("resize",()=>this.onResize()),Q.instance.addEventListener("scroll",n=>this.onScroll(n)),this.createAnchors()}createAnchors(){let r=window.location.href;r.indexOf("#")!=-1&&(r=r.substr(0,r.indexOf("#"))),this.el.querySelectorAll("a").forEach(n=>{let i=n.href;if(i.indexOf("#")==-1||i.substr(0,r.length)!=r)return;let s=i.substr(i.indexOf("#")+1),o=document.querySelector("a.tsd-anchor[name="+s+"]"),a=n.parentNode;!o||!a||this.anchors.push({link:a,anchor:o,position:0})}),this.onResize()}onResize(){let r;for(let i=0,s=this.anchors.length;ii.position-s.position);let n=new CustomEvent("scroll",{detail:{scrollTop:Q.instance.scrollTop}});this.onScroll(n)}onScroll(r){let n=r.detail.scrollTop+5,i=this.anchors,s=i.length-1,o=this.index;for(;o>-1&&i[o].position>n;)o-=1;for(;o-1&&this.anchors[this.index].link.classList.remove("focus"),this.index=o,this.index>-1&&this.anchors[this.index].link.classList.add("focus"))}};var he=(t,e=100)=>{let r;return(...n)=>{clearTimeout(r),r=setTimeout(()=>t(n),e)}};var ge=Fe(pe());function ye(){let t=document.getElementById("tsd-search");if(!t)return;let e=document.getElementById("search-script");t.classList.add("loading"),e&&(e.addEventListener("error",()=>{t.classList.remove("loading"),t.classList.add("failure")}),e.addEventListener("load",()=>{t.classList.remove("loading"),t.classList.add("ready")}),window.searchData&&t.classList.remove("loading"));let r=document.querySelector("#tsd-search input"),n=document.querySelector("#tsd-search .results");if(!r||!n)throw new Error("The input field or the result list wrapper was not found");let i=!1;n.addEventListener("mousedown",()=>i=!0),n.addEventListener("mouseup",()=>{i=!1,t.classList.remove("has-focus")}),r.addEventListener("focus",()=>t.classList.add("has-focus")),r.addEventListener("blur",()=>{i||(i=!1,t.classList.remove("has-focus"))});let s={base:t.dataset.base+"/"};Ae(t,n,r,s)}function Ae(t,e,r,n){r.addEventListener("input",he(()=>{He(t,e,r,n)},200));let i=!1;r.addEventListener("keydown",s=>{i=!0,s.key=="Enter"?ze(e,r):s.key=="Escape"?r.blur():s.key=="ArrowUp"?me(e,-1):s.key==="ArrowDown"?me(e,1):i=!1}),r.addEventListener("keypress",s=>{i&&s.preventDefault()}),document.body.addEventListener("keydown",s=>{s.altKey||s.ctrlKey||s.metaKey||!r.matches(":focus")&&s.key==="/"&&(r.focus(),s.preventDefault())})}function Ve(t,e){t.index||window.searchData&&(e.classList.remove("loading"),e.classList.add("ready"),t.data=window.searchData,t.index=ge.Index.load(window.searchData.index))}function He(t,e,r,n){var o,a;if(Ve(n,t),!n.index||!n.data)return;e.textContent="";let i=r.value.trim(),s=i?n.index.search(`*${i}*`):[];for(let l=0;lu.score-l.score);for(let l=0,u=Math.min(10,s.length);l${ve(h.parent,i)}.${f}`);let p=document.createElement("li");p.classList.value=(a=h.classes)!=null?a:"";let E=document.createElement("a");E.href=n.base+h.url,E.classList.add("tsd-kind-icon"),E.innerHTML=f,p.append(E),e.appendChild(p)}}function me(t,e){var n,i;let r=t.querySelector(".current");if(!r)r=t.querySelector(e==1?"li:first-child":"li:last-child"),r&&r.classList.add("current");else{let s=r;if(e===1)do s=(n=s.nextElementSibling)!=null?n:void 0;while(s instanceof HTMLElement&&s.offsetParent==null);else do s=(i=s.previousElementSibling)!=null?i:void 0;while(s instanceof HTMLElement&&s.offsetParent==null);s&&(r.classList.remove("current"),s.classList.add("current"))}}function ze(t,e){let r=t.querySelector(".current");if(r||(r=t.querySelector("li:first-child")),r){let n=r.querySelector("a");n&&(window.location.href=n.href),e.blur()}}function ve(t,e){if(e==="")return t;let r=t.toLocaleLowerCase(),n=e.toLocaleLowerCase(),i=[],s=0,o=r.indexOf(n);for(;o!=-1;)i.push(se(t.substring(s,o)),`${se(t.substring(o,o+n.length))}`),s=o+n.length,o=r.indexOf(n,s);return i.push(se(t.substring(s))),i.join("")}var Ne={"&":"&","<":"<",">":">","'":"'",'"':"""};function se(t){return t.replace(/[&<>"'"]/g,e=>Ne[e])}var oe=class{constructor(e,r){this.signature=e,this.description=r}addClass(e){return this.signature.classList.add(e),this.description.classList.add(e),this}removeClass(e){return this.signature.classList.remove(e),this.description.classList.remove(e),this}},Z=class extends k{constructor(r){super(r);this.groups=[];this.index=-1;this.createGroups(),this.container&&(this.el.classList.add("active"),Array.from(this.el.children).forEach(n=>{n.addEventListener("touchstart",i=>this.onClick(i)),n.addEventListener("click",i=>this.onClick(i))}),this.container.classList.add("active"),this.setIndex(0))}setIndex(r){if(r<0&&(r=0),r>this.groups.length-1&&(r=this.groups.length-1),this.index==r)return;let n=this.groups[r];if(this.index>-1){let i=this.groups[this.index];i.removeClass("current").addClass("fade-out"),n.addClass("current"),n.addClass("fade-in"),Q.instance.triggerResize(),setTimeout(()=>{i.removeClass("fade-out"),n.removeClass("fade-in")},300)}else n.addClass("current"),Q.instance.triggerResize();this.index=r}createGroups(){let r=this.el.children;if(r.length<2)return;this.container=this.el.nextElementSibling;let n=this.container.children;this.groups=[];for(let i=0;i{n.signature===r.currentTarget&&this.setIndex(i)})}};var C="mousedown",Le="mousemove",_="mouseup",K={x:0,y:0},xe=!1,ae=!1,je=!1,A=!1,Ee=/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);document.documentElement.classList.add(Ee?"is-mobile":"not-mobile");Ee&&"ontouchstart"in document.documentElement&&(je=!0,C="touchstart",Le="touchmove",_="touchend");document.addEventListener(C,t=>{ae=!0,A=!1;let e=C=="touchstart"?t.targetTouches[0]:t;K.y=e.pageY||0,K.x=e.pageX||0});document.addEventListener(Le,t=>{if(!!ae&&!A){let e=C=="touchstart"?t.targetTouches[0]:t,r=K.x-(e.pageX||0),n=K.y-(e.pageY||0);A=Math.sqrt(r*r+n*n)>10}});document.addEventListener(_,()=>{ae=!1});document.addEventListener("click",t=>{xe&&(t.preventDefault(),t.stopImmediatePropagation(),xe=!1)});var ee=class extends k{constructor(r){super(r);this.className=this.el.dataset.toggle||"",this.el.addEventListener(_,n=>this.onPointerUp(n)),this.el.addEventListener("click",n=>n.preventDefault()),document.addEventListener(C,n=>this.onDocumentPointerDown(n)),document.addEventListener(_,n=>this.onDocumentPointerUp(n))}setActive(r){if(this.active==r)return;this.active=r,document.documentElement.classList.toggle("has-"+this.className,r),this.el.classList.toggle("active",r);let n=(this.active?"to-has-":"from-has-")+this.className;document.documentElement.classList.add(n),setTimeout(()=>document.documentElement.classList.remove(n),500)}onPointerUp(r){A||(this.setActive(!0),r.preventDefault())}onDocumentPointerDown(r){if(this.active){if(r.target.closest(".col-menu, .tsd-filter-group"))return;this.setActive(!1)}}onDocumentPointerUp(r){if(!A&&this.active&&r.target.closest(".col-menu")){let n=r.target.closest("a");if(n){let i=window.location.href;i.indexOf("#")!=-1&&(i=i.substr(0,i.indexOf("#"))),n.href.substr(0,i.length)==i&&setTimeout(()=>this.setActive(!1),250)}}}};var te=class{constructor(e,r){this.key=e,this.value=r,this.defaultValue=r,this.initialize(),window.localStorage[this.key]&&this.setValue(this.fromLocalStorage(window.localStorage[this.key]))}initialize(){}setValue(e){if(this.value==e)return;let r=this.value;this.value=e,window.localStorage[this.key]=this.toLocalStorage(e),this.handleValueChange(r,e)}},re=class extends te{initialize(){let r=document.querySelector("#tsd-filter-"+this.key);!r||(this.checkbox=r,this.checkbox.addEventListener("change",()=>{this.setValue(this.checkbox.checked)}))}handleValueChange(r,n){!this.checkbox||(this.checkbox.checked=this.value,document.documentElement.classList.toggle("toggle-"+this.key,this.value!=this.defaultValue))}fromLocalStorage(r){return r=="true"}toLocalStorage(r){return r?"true":"false"}},le=class extends te{initialize(){document.documentElement.classList.add("toggle-"+this.key+this.value);let r=document.querySelector("#tsd-filter-"+this.key);if(!r)return;this.select=r;let n=()=>{this.select.classList.add("active")},i=()=>{this.select.classList.remove("active")};this.select.addEventListener(C,n),this.select.addEventListener("mouseover",n),this.select.addEventListener("mouseleave",i),this.select.querySelectorAll("li").forEach(s=>{s.addEventListener(_,o=>{r.classList.remove("active"),this.setValue(o.target.dataset.value||"")})}),document.addEventListener(C,s=>{this.select.contains(s.target)||this.select.classList.remove("active")})}handleValueChange(r,n){this.select.querySelectorAll("li.selected").forEach(o=>{o.classList.remove("selected")});let i=this.select.querySelector('li[data-value="'+n+'"]'),s=this.select.querySelector(".tsd-select-label");i&&s&&(i.classList.add("selected"),s.textContent=i.textContent),document.documentElement.classList.remove("toggle-"+r),document.documentElement.classList.add("toggle-"+n)}fromLocalStorage(r){return r}toLocalStorage(r){return r}},j=class extends k{constructor(r){super(r);this.optionVisibility=new le("visibility","private"),this.optionInherited=new re("inherited",!0),this.optionExternals=new re("externals",!0)}static isSupported(){try{return typeof window.localStorage!="undefined"}catch{return!1}}};function we(t){let e=localStorage.getItem("tsd-theme")||"os";t.value=e,be(e),t.addEventListener("change",()=>{localStorage.setItem("tsd-theme",t.value),be(t.value)})}function be(t){switch(t){case"os":document.body.classList.remove("light","dark");break;case"light":document.body.classList.remove("dark"),document.body.classList.add("light");break;case"dark":document.body.classList.remove("light"),document.body.classList.add("dark");break}}ye();N(X,".menu-highlight");N(Z,".tsd-signatures");N(ee,"a[data-toggle]");j.isSupported()?N(j,"#tsd-filter"):document.documentElement.classList.add("no-filter");var Te=document.getElementById("theme");Te&&we(Te);var Be=new Y;Object.defineProperty(window,"app",{value:Be});})(); -/*! - * lunr.Builder - * Copyright (C) 2020 Oliver Nightingale - */ -/*! - * lunr.Index - * Copyright (C) 2020 Oliver Nightingale - */ -/*! - * lunr.Pipeline - * Copyright (C) 2020 Oliver Nightingale - */ -/*! - * lunr.Set - * Copyright (C) 2020 Oliver Nightingale - */ -/*! - * lunr.TokenSet - * Copyright (C) 2020 Oliver Nightingale - */ -/*! - * lunr.Vector - * Copyright (C) 2020 Oliver Nightingale - */ -/*! - * lunr.stemmer - * Copyright (C) 2020 Oliver Nightingale - * Includes code from - http://tartarus.org/~martin/PorterStemmer/js.txt - */ -/*! - * lunr.stopWordFilter - * Copyright (C) 2020 Oliver Nightingale - */ -/*! - * lunr.tokenizer - * Copyright (C) 2020 Oliver Nightingale - */ -/*! - * lunr.trimmer - * Copyright (C) 2020 Oliver Nightingale - */ -/*! - * lunr.utils - * Copyright (C) 2020 Oliver Nightingale - */ -/** - * lunr - http://lunrjs.com - A bit like Solr, but much smaller and not as bright - 2.3.9 - * Copyright (C) 2020 Oliver Nightingale - * @license MIT - */ diff --git a/docs/assets/search.js b/docs/assets/search.js deleted file mode 100644 index c7c68dc..0000000 --- a/docs/assets/search.js +++ /dev/null @@ -1 +0,0 @@ -window.searchData = JSON.parse("{\"kinds\":{\"8\":\"Enumeration\",\"16\":\"Enumeration Member\",\"32\":\"Variable\",\"64\":\"Function\",\"128\":\"Class\",\"256\":\"Interface\",\"512\":\"Constructor\",\"1024\":\"Property\",\"2048\":\"Method\",\"65536\":\"Type literal\",\"4194304\":\"Type alias\"},\"rows\":[{\"id\":0,\"kind\":4194304,\"name\":\"WhirlpoolContextOpts\",\"url\":\"modules.html#WhirlpoolContextOpts\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":1,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#WhirlpoolContextOpts.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"WhirlpoolContextOpts\"},{\"id\":2,\"kind\":1024,\"name\":\"userDefaultBuildOptions\",\"url\":\"modules.html#WhirlpoolContextOpts.__type.userDefaultBuildOptions\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"WhirlpoolContextOpts.__type\"},{\"id\":3,\"kind\":1024,\"name\":\"userDefaultSendOptions\",\"url\":\"modules.html#WhirlpoolContextOpts.__type.userDefaultSendOptions\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"WhirlpoolContextOpts.__type\"},{\"id\":4,\"kind\":1024,\"name\":\"userDefaultConfirmCommitment\",\"url\":\"modules.html#WhirlpoolContextOpts.__type.userDefaultConfirmCommitment\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"WhirlpoolContextOpts.__type\"},{\"id\":5,\"kind\":1024,\"name\":\"accountResolverOptions\",\"url\":\"modules.html#WhirlpoolContextOpts.__type.accountResolverOptions\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"WhirlpoolContextOpts.__type\"},{\"id\":6,\"kind\":4194304,\"name\":\"AccountResolverOptions\",\"url\":\"modules.html#AccountResolverOptions\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":7,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#AccountResolverOptions.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"AccountResolverOptions\"},{\"id\":8,\"kind\":1024,\"name\":\"createWrappedSolAccountMethod\",\"url\":\"modules.html#AccountResolverOptions.__type.createWrappedSolAccountMethod\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"AccountResolverOptions.__type\"},{\"id\":9,\"kind\":1024,\"name\":\"allowPDAOwnerAddress\",\"url\":\"modules.html#AccountResolverOptions.__type.allowPDAOwnerAddress\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"AccountResolverOptions.__type\"},{\"id\":10,\"kind\":128,\"name\":\"WhirlpoolContext\",\"url\":\"classes/WhirlpoolContext.html\",\"classes\":\"tsd-kind-class\"},{\"id\":11,\"kind\":2048,\"name\":\"from\",\"url\":\"classes/WhirlpoolContext.html#from\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"WhirlpoolContext\"},{\"id\":12,\"kind\":2048,\"name\":\"fromWorkspace\",\"url\":\"classes/WhirlpoolContext.html#fromWorkspace\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"WhirlpoolContext\"},{\"id\":13,\"kind\":2048,\"name\":\"withProvider\",\"url\":\"classes/WhirlpoolContext.html#withProvider\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"WhirlpoolContext\"},{\"id\":14,\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/WhirlpoolContext.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"WhirlpoolContext\"},{\"id\":15,\"kind\":1024,\"name\":\"connection\",\"url\":\"classes/WhirlpoolContext.html#connection\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"WhirlpoolContext\"},{\"id\":16,\"kind\":1024,\"name\":\"wallet\",\"url\":\"classes/WhirlpoolContext.html#wallet\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"WhirlpoolContext\"},{\"id\":17,\"kind\":1024,\"name\":\"program\",\"url\":\"classes/WhirlpoolContext.html#program\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"WhirlpoolContext\"},{\"id\":18,\"kind\":1024,\"name\":\"provider\",\"url\":\"classes/WhirlpoolContext.html#provider\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"WhirlpoolContext\"},{\"id\":19,\"kind\":1024,\"name\":\"fetcher\",\"url\":\"classes/WhirlpoolContext.html#fetcher\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"WhirlpoolContext\"},{\"id\":20,\"kind\":1024,\"name\":\"lookupTableFetcher\",\"url\":\"classes/WhirlpoolContext.html#lookupTableFetcher\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"WhirlpoolContext\"},{\"id\":21,\"kind\":1024,\"name\":\"opts\",\"url\":\"classes/WhirlpoolContext.html#opts\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"WhirlpoolContext\"},{\"id\":22,\"kind\":1024,\"name\":\"txBuilderOpts\",\"url\":\"classes/WhirlpoolContext.html#txBuilderOpts\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"WhirlpoolContext\"},{\"id\":23,\"kind\":1024,\"name\":\"accountResolverOpts\",\"url\":\"classes/WhirlpoolContext.html#accountResolverOpts\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"WhirlpoolContext\"},{\"id\":24,\"kind\":128,\"name\":\"WhirlpoolIx\",\"url\":\"classes/WhirlpoolIx.html\",\"classes\":\"tsd-kind-class\"},{\"id\":25,\"kind\":2048,\"name\":\"initializeConfigIx\",\"url\":\"classes/WhirlpoolIx.html#initializeConfigIx\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"WhirlpoolIx\"},{\"id\":26,\"kind\":2048,\"name\":\"initializeFeeTierIx\",\"url\":\"classes/WhirlpoolIx.html#initializeFeeTierIx\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"WhirlpoolIx\"},{\"id\":27,\"kind\":2048,\"name\":\"initializePoolIx\",\"url\":\"classes/WhirlpoolIx.html#initializePoolIx\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"WhirlpoolIx\"},{\"id\":28,\"kind\":2048,\"name\":\"initializeRewardIx\",\"url\":\"classes/WhirlpoolIx.html#initializeRewardIx\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"WhirlpoolIx\"},{\"id\":29,\"kind\":2048,\"name\":\"initTickArrayIx\",\"url\":\"classes/WhirlpoolIx.html#initTickArrayIx\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"WhirlpoolIx\"},{\"id\":30,\"kind\":2048,\"name\":\"openPositionIx\",\"url\":\"classes/WhirlpoolIx.html#openPositionIx\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"WhirlpoolIx\"},{\"id\":31,\"kind\":2048,\"name\":\"openPositionWithMetadataIx\",\"url\":\"classes/WhirlpoolIx.html#openPositionWithMetadataIx\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"WhirlpoolIx\"},{\"id\":32,\"kind\":2048,\"name\":\"increaseLiquidityIx\",\"url\":\"classes/WhirlpoolIx.html#increaseLiquidityIx\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"WhirlpoolIx\"},{\"id\":33,\"kind\":2048,\"name\":\"decreaseLiquidityIx\",\"url\":\"classes/WhirlpoolIx.html#decreaseLiquidityIx\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"WhirlpoolIx\"},{\"id\":34,\"kind\":2048,\"name\":\"closePositionIx\",\"url\":\"classes/WhirlpoolIx.html#closePositionIx\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"WhirlpoolIx\"},{\"id\":35,\"kind\":2048,\"name\":\"swapIx\",\"url\":\"classes/WhirlpoolIx.html#swapIx\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"WhirlpoolIx\"},{\"id\":36,\"kind\":2048,\"name\":\"twoHopSwapIx\",\"url\":\"classes/WhirlpoolIx.html#twoHopSwapIx\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"WhirlpoolIx\"},{\"id\":37,\"kind\":2048,\"name\":\"updateFeesAndRewardsIx\",\"url\":\"classes/WhirlpoolIx.html#updateFeesAndRewardsIx\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"WhirlpoolIx\"},{\"id\":38,\"kind\":2048,\"name\":\"collectFeesIx\",\"url\":\"classes/WhirlpoolIx.html#collectFeesIx\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"WhirlpoolIx\"},{\"id\":39,\"kind\":2048,\"name\":\"collectProtocolFeesIx\",\"url\":\"classes/WhirlpoolIx.html#collectProtocolFeesIx\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"WhirlpoolIx\"},{\"id\":40,\"kind\":2048,\"name\":\"collectRewardIx\",\"url\":\"classes/WhirlpoolIx.html#collectRewardIx\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"WhirlpoolIx\"},{\"id\":41,\"kind\":2048,\"name\":\"setCollectProtocolFeesAuthorityIx\",\"url\":\"classes/WhirlpoolIx.html#setCollectProtocolFeesAuthorityIx\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"WhirlpoolIx\"},{\"id\":42,\"kind\":2048,\"name\":\"setDefaultFeeRateIx\",\"url\":\"classes/WhirlpoolIx.html#setDefaultFeeRateIx\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"WhirlpoolIx\"},{\"id\":43,\"kind\":2048,\"name\":\"setDefaultProtocolFeeRateIx\",\"url\":\"classes/WhirlpoolIx.html#setDefaultProtocolFeeRateIx\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"WhirlpoolIx\"},{\"id\":44,\"kind\":2048,\"name\":\"setFeeAuthorityIx\",\"url\":\"classes/WhirlpoolIx.html#setFeeAuthorityIx\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"WhirlpoolIx\"},{\"id\":45,\"kind\":2048,\"name\":\"setFeeRateIx\",\"url\":\"classes/WhirlpoolIx.html#setFeeRateIx\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"WhirlpoolIx\"},{\"id\":46,\"kind\":2048,\"name\":\"setProtocolFeeRateIx\",\"url\":\"classes/WhirlpoolIx.html#setProtocolFeeRateIx\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"WhirlpoolIx\"},{\"id\":47,\"kind\":2048,\"name\":\"setRewardAuthorityBySuperAuthorityIx\",\"url\":\"classes/WhirlpoolIx.html#setRewardAuthorityBySuperAuthorityIx\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"WhirlpoolIx\"},{\"id\":48,\"kind\":2048,\"name\":\"setRewardAuthorityIx\",\"url\":\"classes/WhirlpoolIx.html#setRewardAuthorityIx\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"WhirlpoolIx\"},{\"id\":49,\"kind\":2048,\"name\":\"setRewardEmissionsIx\",\"url\":\"classes/WhirlpoolIx.html#setRewardEmissionsIx\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"WhirlpoolIx\"},{\"id\":50,\"kind\":2048,\"name\":\"setRewardEmissionsSuperAuthorityIx\",\"url\":\"classes/WhirlpoolIx.html#setRewardEmissionsSuperAuthorityIx\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"WhirlpoolIx\"},{\"id\":51,\"kind\":2048,\"name\":\"initializePositionBundleIx\",\"url\":\"classes/WhirlpoolIx.html#initializePositionBundleIx\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"WhirlpoolIx\"},{\"id\":52,\"kind\":2048,\"name\":\"initializePositionBundleWithMetadataIx\",\"url\":\"classes/WhirlpoolIx.html#initializePositionBundleWithMetadataIx\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"WhirlpoolIx\"},{\"id\":53,\"kind\":2048,\"name\":\"deletePositionBundleIx\",\"url\":\"classes/WhirlpoolIx.html#deletePositionBundleIx\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"WhirlpoolIx\"},{\"id\":54,\"kind\":2048,\"name\":\"openBundledPositionIx\",\"url\":\"classes/WhirlpoolIx.html#openBundledPositionIx\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"WhirlpoolIx\"},{\"id\":55,\"kind\":2048,\"name\":\"closeBundledPositionIx\",\"url\":\"classes/WhirlpoolIx.html#closeBundledPositionIx\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"WhirlpoolIx\"},{\"id\":56,\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/WhirlpoolIx.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"WhirlpoolIx\"},{\"id\":57,\"kind\":64,\"name\":\"buildDefaultAccountFetcher\",\"url\":\"modules.html#buildDefaultAccountFetcher\",\"classes\":\"tsd-kind-function\"},{\"id\":58,\"kind\":128,\"name\":\"WhirlpoolAccountFetcher\",\"url\":\"classes/WhirlpoolAccountFetcher.html\",\"classes\":\"tsd-kind-class\"},{\"id\":59,\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/WhirlpoolAccountFetcher.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"WhirlpoolAccountFetcher\"},{\"id\":60,\"kind\":1024,\"name\":\"connection\",\"url\":\"classes/WhirlpoolAccountFetcher.html#connection\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"WhirlpoolAccountFetcher\"},{\"id\":61,\"kind\":1024,\"name\":\"fetcher\",\"url\":\"classes/WhirlpoolAccountFetcher.html#fetcher\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"WhirlpoolAccountFetcher\"},{\"id\":62,\"kind\":2048,\"name\":\"getAccountRentExempt\",\"url\":\"classes/WhirlpoolAccountFetcher.html#getAccountRentExempt\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"WhirlpoolAccountFetcher\"},{\"id\":63,\"kind\":2048,\"name\":\"getPool\",\"url\":\"classes/WhirlpoolAccountFetcher.html#getPool\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"WhirlpoolAccountFetcher\"},{\"id\":64,\"kind\":2048,\"name\":\"getPools\",\"url\":\"classes/WhirlpoolAccountFetcher.html#getPools\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"WhirlpoolAccountFetcher\"},{\"id\":65,\"kind\":2048,\"name\":\"getPosition\",\"url\":\"classes/WhirlpoolAccountFetcher.html#getPosition\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"WhirlpoolAccountFetcher\"},{\"id\":66,\"kind\":2048,\"name\":\"getPositions\",\"url\":\"classes/WhirlpoolAccountFetcher.html#getPositions\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"WhirlpoolAccountFetcher\"},{\"id\":67,\"kind\":2048,\"name\":\"getTickArray\",\"url\":\"classes/WhirlpoolAccountFetcher.html#getTickArray\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"WhirlpoolAccountFetcher\"},{\"id\":68,\"kind\":2048,\"name\":\"getTickArrays\",\"url\":\"classes/WhirlpoolAccountFetcher.html#getTickArrays\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"WhirlpoolAccountFetcher\"},{\"id\":69,\"kind\":2048,\"name\":\"getFeeTier\",\"url\":\"classes/WhirlpoolAccountFetcher.html#getFeeTier\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"WhirlpoolAccountFetcher\"},{\"id\":70,\"kind\":2048,\"name\":\"getFeeTiers\",\"url\":\"classes/WhirlpoolAccountFetcher.html#getFeeTiers\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"WhirlpoolAccountFetcher\"},{\"id\":71,\"kind\":2048,\"name\":\"getTokenInfo\",\"url\":\"classes/WhirlpoolAccountFetcher.html#getTokenInfo\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"WhirlpoolAccountFetcher\"},{\"id\":72,\"kind\":2048,\"name\":\"getTokenInfos\",\"url\":\"classes/WhirlpoolAccountFetcher.html#getTokenInfos\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"WhirlpoolAccountFetcher\"},{\"id\":73,\"kind\":2048,\"name\":\"getMintInfo\",\"url\":\"classes/WhirlpoolAccountFetcher.html#getMintInfo\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"WhirlpoolAccountFetcher\"},{\"id\":74,\"kind\":2048,\"name\":\"getMintInfos\",\"url\":\"classes/WhirlpoolAccountFetcher.html#getMintInfos\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"WhirlpoolAccountFetcher\"},{\"id\":75,\"kind\":2048,\"name\":\"getConfig\",\"url\":\"classes/WhirlpoolAccountFetcher.html#getConfig\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"WhirlpoolAccountFetcher\"},{\"id\":76,\"kind\":2048,\"name\":\"getConfigs\",\"url\":\"classes/WhirlpoolAccountFetcher.html#getConfigs\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"WhirlpoolAccountFetcher\"},{\"id\":77,\"kind\":2048,\"name\":\"getPositionBundle\",\"url\":\"classes/WhirlpoolAccountFetcher.html#getPositionBundle\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"WhirlpoolAccountFetcher\"},{\"id\":78,\"kind\":2048,\"name\":\"getPositionBundles\",\"url\":\"classes/WhirlpoolAccountFetcher.html#getPositionBundles\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"WhirlpoolAccountFetcher\"},{\"id\":79,\"kind\":2048,\"name\":\"populateCache\",\"url\":\"classes/WhirlpoolAccountFetcher.html#populateCache\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-has-type-parameter\",\"parent\":\"WhirlpoolAccountFetcher\"},{\"id\":80,\"kind\":4194304,\"name\":\"WhirlpoolSupportedTypes\",\"url\":\"modules.html#WhirlpoolSupportedTypes\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":81,\"kind\":32,\"name\":\"DEFAULT_WHIRLPOOL_RETENTION_POLICY\",\"url\":\"modules.html#DEFAULT_WHIRLPOOL_RETENTION_POLICY\",\"classes\":\"tsd-kind-variable\"},{\"id\":82,\"kind\":4194304,\"name\":\"WhirlpoolAccountFetchOptions\",\"url\":\"modules.html#WhirlpoolAccountFetchOptions\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":83,\"kind\":32,\"name\":\"IGNORE_CACHE\",\"url\":\"modules.html#IGNORE_CACHE\",\"classes\":\"tsd-kind-variable\"},{\"id\":84,\"kind\":32,\"name\":\"PREFER_CACHE\",\"url\":\"modules.html#PREFER_CACHE\",\"classes\":\"tsd-kind-variable\"},{\"id\":85,\"kind\":256,\"name\":\"WhirlpoolAccountFetcherInterface\",\"url\":\"interfaces/WhirlpoolAccountFetcherInterface.html\",\"classes\":\"tsd-kind-interface\"},{\"id\":86,\"kind\":2048,\"name\":\"getAccountRentExempt\",\"url\":\"interfaces/WhirlpoolAccountFetcherInterface.html#getAccountRentExempt\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"WhirlpoolAccountFetcherInterface\"},{\"id\":87,\"kind\":2048,\"name\":\"getPool\",\"url\":\"interfaces/WhirlpoolAccountFetcherInterface.html#getPool\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"WhirlpoolAccountFetcherInterface\"},{\"id\":88,\"kind\":2048,\"name\":\"getPools\",\"url\":\"interfaces/WhirlpoolAccountFetcherInterface.html#getPools\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"WhirlpoolAccountFetcherInterface\"},{\"id\":89,\"kind\":2048,\"name\":\"getPosition\",\"url\":\"interfaces/WhirlpoolAccountFetcherInterface.html#getPosition\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"WhirlpoolAccountFetcherInterface\"},{\"id\":90,\"kind\":2048,\"name\":\"getPositions\",\"url\":\"interfaces/WhirlpoolAccountFetcherInterface.html#getPositions\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"WhirlpoolAccountFetcherInterface\"},{\"id\":91,\"kind\":2048,\"name\":\"getTickArray\",\"url\":\"interfaces/WhirlpoolAccountFetcherInterface.html#getTickArray\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"WhirlpoolAccountFetcherInterface\"},{\"id\":92,\"kind\":2048,\"name\":\"getTickArrays\",\"url\":\"interfaces/WhirlpoolAccountFetcherInterface.html#getTickArrays\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"WhirlpoolAccountFetcherInterface\"},{\"id\":93,\"kind\":2048,\"name\":\"getFeeTier\",\"url\":\"interfaces/WhirlpoolAccountFetcherInterface.html#getFeeTier\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"WhirlpoolAccountFetcherInterface\"},{\"id\":94,\"kind\":2048,\"name\":\"getFeeTiers\",\"url\":\"interfaces/WhirlpoolAccountFetcherInterface.html#getFeeTiers\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"WhirlpoolAccountFetcherInterface\"},{\"id\":95,\"kind\":2048,\"name\":\"getTokenInfo\",\"url\":\"interfaces/WhirlpoolAccountFetcherInterface.html#getTokenInfo\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"WhirlpoolAccountFetcherInterface\"},{\"id\":96,\"kind\":2048,\"name\":\"getTokenInfos\",\"url\":\"interfaces/WhirlpoolAccountFetcherInterface.html#getTokenInfos\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"WhirlpoolAccountFetcherInterface\"},{\"id\":97,\"kind\":2048,\"name\":\"getMintInfo\",\"url\":\"interfaces/WhirlpoolAccountFetcherInterface.html#getMintInfo\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"WhirlpoolAccountFetcherInterface\"},{\"id\":98,\"kind\":2048,\"name\":\"getMintInfos\",\"url\":\"interfaces/WhirlpoolAccountFetcherInterface.html#getMintInfos\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"WhirlpoolAccountFetcherInterface\"},{\"id\":99,\"kind\":2048,\"name\":\"getConfig\",\"url\":\"interfaces/WhirlpoolAccountFetcherInterface.html#getConfig\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"WhirlpoolAccountFetcherInterface\"},{\"id\":100,\"kind\":2048,\"name\":\"getConfigs\",\"url\":\"interfaces/WhirlpoolAccountFetcherInterface.html#getConfigs\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"WhirlpoolAccountFetcherInterface\"},{\"id\":101,\"kind\":2048,\"name\":\"getPositionBundle\",\"url\":\"interfaces/WhirlpoolAccountFetcherInterface.html#getPositionBundle\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"WhirlpoolAccountFetcherInterface\"},{\"id\":102,\"kind\":2048,\"name\":\"getPositionBundles\",\"url\":\"interfaces/WhirlpoolAccountFetcherInterface.html#getPositionBundles\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"WhirlpoolAccountFetcherInterface\"},{\"id\":103,\"kind\":2048,\"name\":\"populateCache\",\"url\":\"interfaces/WhirlpoolAccountFetcherInterface.html#populateCache\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface tsd-has-type-parameter\",\"parent\":\"WhirlpoolAccountFetcherInterface\"},{\"id\":104,\"kind\":64,\"name\":\"getAllWhirlpoolAccountsForConfig\",\"url\":\"modules.html#getAllWhirlpoolAccountsForConfig\",\"classes\":\"tsd-kind-function\"},{\"id\":105,\"kind\":128,\"name\":\"ParsableWhirlpoolsConfig\",\"url\":\"classes/ParsableWhirlpoolsConfig.html\",\"classes\":\"tsd-kind-class\"},{\"id\":106,\"kind\":2048,\"name\":\"parse\",\"url\":\"classes/ParsableWhirlpoolsConfig.html#parse\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"ParsableWhirlpoolsConfig\"},{\"id\":107,\"kind\":128,\"name\":\"ParsableWhirlpool\",\"url\":\"classes/ParsableWhirlpool.html\",\"classes\":\"tsd-kind-class\"},{\"id\":108,\"kind\":2048,\"name\":\"parse\",\"url\":\"classes/ParsableWhirlpool.html#parse\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"ParsableWhirlpool\"},{\"id\":109,\"kind\":128,\"name\":\"ParsablePosition\",\"url\":\"classes/ParsablePosition.html\",\"classes\":\"tsd-kind-class\"},{\"id\":110,\"kind\":2048,\"name\":\"parse\",\"url\":\"classes/ParsablePosition.html#parse\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"ParsablePosition\"},{\"id\":111,\"kind\":128,\"name\":\"ParsableTickArray\",\"url\":\"classes/ParsableTickArray.html\",\"classes\":\"tsd-kind-class\"},{\"id\":112,\"kind\":2048,\"name\":\"parse\",\"url\":\"classes/ParsableTickArray.html#parse\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"ParsableTickArray\"},{\"id\":113,\"kind\":128,\"name\":\"ParsableFeeTier\",\"url\":\"classes/ParsableFeeTier.html\",\"classes\":\"tsd-kind-class\"},{\"id\":114,\"kind\":2048,\"name\":\"parse\",\"url\":\"classes/ParsableFeeTier.html#parse\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"ParsableFeeTier\"},{\"id\":115,\"kind\":128,\"name\":\"ParsablePositionBundle\",\"url\":\"classes/ParsablePositionBundle.html\",\"classes\":\"tsd-kind-class\"},{\"id\":116,\"kind\":2048,\"name\":\"parse\",\"url\":\"classes/ParsablePositionBundle.html#parse\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"ParsablePositionBundle\"},{\"id\":117,\"kind\":4194304,\"name\":\"GetPricesConfig\",\"url\":\"modules.html#GetPricesConfig\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":118,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#GetPricesConfig.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"GetPricesConfig\"},{\"id\":119,\"kind\":1024,\"name\":\"quoteTokens\",\"url\":\"modules.html#GetPricesConfig.__type.quoteTokens\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"GetPricesConfig.__type\"},{\"id\":120,\"kind\":1024,\"name\":\"tickSpacings\",\"url\":\"modules.html#GetPricesConfig.__type.tickSpacings\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"GetPricesConfig.__type\"},{\"id\":121,\"kind\":1024,\"name\":\"programId\",\"url\":\"modules.html#GetPricesConfig.__type.programId\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"GetPricesConfig.__type\"},{\"id\":122,\"kind\":1024,\"name\":\"whirlpoolsConfig\",\"url\":\"modules.html#GetPricesConfig.__type.whirlpoolsConfig\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"GetPricesConfig.__type\"},{\"id\":123,\"kind\":4194304,\"name\":\"GetPricesThresholdConfig\",\"url\":\"modules.html#GetPricesThresholdConfig\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":124,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#GetPricesThresholdConfig.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"GetPricesThresholdConfig\"},{\"id\":125,\"kind\":1024,\"name\":\"amountOut\",\"url\":\"modules.html#GetPricesThresholdConfig.__type.amountOut\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"GetPricesThresholdConfig.__type\"},{\"id\":126,\"kind\":1024,\"name\":\"priceImpactThreshold\",\"url\":\"modules.html#GetPricesThresholdConfig.__type.priceImpactThreshold\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"GetPricesThresholdConfig.__type\"},{\"id\":127,\"kind\":4194304,\"name\":\"PriceCalculationData\",\"url\":\"modules.html#PriceCalculationData\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":128,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#PriceCalculationData.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"PriceCalculationData\"},{\"id\":129,\"kind\":1024,\"name\":\"poolMap\",\"url\":\"modules.html#PriceCalculationData.__type.poolMap\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"PriceCalculationData.__type\"},{\"id\":130,\"kind\":1024,\"name\":\"tickArrayMap\",\"url\":\"modules.html#PriceCalculationData.__type.tickArrayMap\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"PriceCalculationData.__type\"},{\"id\":131,\"kind\":1024,\"name\":\"decimalsMap\",\"url\":\"modules.html#PriceCalculationData.__type.decimalsMap\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"PriceCalculationData.__type\"},{\"id\":132,\"kind\":4194304,\"name\":\"PoolMap\",\"url\":\"modules.html#PoolMap\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":133,\"kind\":4194304,\"name\":\"TickArrayMap\",\"url\":\"modules.html#TickArrayMap\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":134,\"kind\":4194304,\"name\":\"PriceMap\",\"url\":\"modules.html#PriceMap\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":135,\"kind\":4194304,\"name\":\"DecimalsMap\",\"url\":\"modules.html#DecimalsMap\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":136,\"kind\":32,\"name\":\"defaultQuoteTokens\",\"url\":\"modules.html#defaultQuoteTokens\",\"classes\":\"tsd-kind-variable\"},{\"id\":137,\"kind\":32,\"name\":\"defaultGetPricesConfig\",\"url\":\"modules.html#defaultGetPricesConfig\",\"classes\":\"tsd-kind-variable\"},{\"id\":138,\"kind\":32,\"name\":\"defaultGetPricesThresholdConfig\",\"url\":\"modules.html#defaultGetPricesThresholdConfig\",\"classes\":\"tsd-kind-variable\"},{\"id\":139,\"kind\":128,\"name\":\"PriceModule\",\"url\":\"classes/PriceModule.html\",\"classes\":\"tsd-kind-class\"},{\"id\":140,\"kind\":2048,\"name\":\"fetchTokenPricesByMints\",\"url\":\"classes/PriceModule.html#fetchTokenPricesByMints\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"PriceModule\"},{\"id\":141,\"kind\":2048,\"name\":\"fetchTokenPricesByPools\",\"url\":\"classes/PriceModule.html#fetchTokenPricesByPools\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"PriceModule\"},{\"id\":142,\"kind\":2048,\"name\":\"calculateTokenPrices\",\"url\":\"classes/PriceModule.html#calculateTokenPrices\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"PriceModule\"},{\"id\":143,\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/PriceModule.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"PriceModule\"},{\"id\":144,\"kind\":128,\"name\":\"PriceModuleUtils\",\"url\":\"classes/PriceModuleUtils.html\",\"classes\":\"tsd-kind-class\"},{\"id\":145,\"kind\":2048,\"name\":\"fetchPoolDataFromMints\",\"url\":\"classes/PriceModuleUtils.html#fetchPoolDataFromMints\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"PriceModuleUtils\"},{\"id\":146,\"kind\":2048,\"name\":\"fetchTickArraysForPools\",\"url\":\"classes/PriceModuleUtils.html#fetchTickArraysForPools\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"PriceModuleUtils\"},{\"id\":147,\"kind\":2048,\"name\":\"fetchDecimalsForMints\",\"url\":\"classes/PriceModuleUtils.html#fetchDecimalsForMints\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"PriceModuleUtils\"},{\"id\":148,\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/PriceModuleUtils.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"PriceModuleUtils\"},{\"id\":149,\"kind\":64,\"name\":\"increaseLiquidityQuoteByInputToken\",\"url\":\"modules.html#increaseLiquidityQuoteByInputToken\",\"classes\":\"tsd-kind-function\"},{\"id\":150,\"kind\":64,\"name\":\"increaseLiquidityQuoteByInputTokenWithParams\",\"url\":\"modules.html#increaseLiquidityQuoteByInputTokenWithParams\",\"classes\":\"tsd-kind-function\"},{\"id\":151,\"kind\":4194304,\"name\":\"IncreaseLiquidityQuoteParam\",\"url\":\"modules.html#IncreaseLiquidityQuoteParam\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":152,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#IncreaseLiquidityQuoteParam.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"IncreaseLiquidityQuoteParam\"},{\"id\":153,\"kind\":1024,\"name\":\"inputTokenAmount\",\"url\":\"modules.html#IncreaseLiquidityQuoteParam.__type.inputTokenAmount\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"IncreaseLiquidityQuoteParam.__type\"},{\"id\":154,\"kind\":1024,\"name\":\"inputTokenMint\",\"url\":\"modules.html#IncreaseLiquidityQuoteParam.__type.inputTokenMint\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"IncreaseLiquidityQuoteParam.__type\"},{\"id\":155,\"kind\":1024,\"name\":\"tokenMintA\",\"url\":\"modules.html#IncreaseLiquidityQuoteParam.__type.tokenMintA\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"IncreaseLiquidityQuoteParam.__type\"},{\"id\":156,\"kind\":1024,\"name\":\"tokenMintB\",\"url\":\"modules.html#IncreaseLiquidityQuoteParam.__type.tokenMintB\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"IncreaseLiquidityQuoteParam.__type\"},{\"id\":157,\"kind\":1024,\"name\":\"tickCurrentIndex\",\"url\":\"modules.html#IncreaseLiquidityQuoteParam.__type.tickCurrentIndex\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"IncreaseLiquidityQuoteParam.__type\"},{\"id\":158,\"kind\":1024,\"name\":\"sqrtPrice\",\"url\":\"modules.html#IncreaseLiquidityQuoteParam.__type.sqrtPrice\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"IncreaseLiquidityQuoteParam.__type\"},{\"id\":159,\"kind\":1024,\"name\":\"tickLowerIndex\",\"url\":\"modules.html#IncreaseLiquidityQuoteParam.__type.tickLowerIndex\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"IncreaseLiquidityQuoteParam.__type\"},{\"id\":160,\"kind\":1024,\"name\":\"tickUpperIndex\",\"url\":\"modules.html#IncreaseLiquidityQuoteParam.__type.tickUpperIndex\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"IncreaseLiquidityQuoteParam.__type\"},{\"id\":161,\"kind\":1024,\"name\":\"slippageTolerance\",\"url\":\"modules.html#IncreaseLiquidityQuoteParam.__type.slippageTolerance\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"IncreaseLiquidityQuoteParam.__type\"},{\"id\":162,\"kind\":4194304,\"name\":\"IncreaseLiquidityQuote\",\"url\":\"modules.html#IncreaseLiquidityQuote\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":163,\"kind\":64,\"name\":\"decreaseLiquidityQuoteByLiquidity\",\"url\":\"modules.html#decreaseLiquidityQuoteByLiquidity\",\"classes\":\"tsd-kind-function\"},{\"id\":164,\"kind\":64,\"name\":\"decreaseLiquidityQuoteByLiquidityWithParams\",\"url\":\"modules.html#decreaseLiquidityQuoteByLiquidityWithParams\",\"classes\":\"tsd-kind-function\"},{\"id\":165,\"kind\":4194304,\"name\":\"DecreaseLiquidityQuoteParam\",\"url\":\"modules.html#DecreaseLiquidityQuoteParam\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":166,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#DecreaseLiquidityQuoteParam.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"DecreaseLiquidityQuoteParam\"},{\"id\":167,\"kind\":1024,\"name\":\"liquidity\",\"url\":\"modules.html#DecreaseLiquidityQuoteParam.__type.liquidity\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"DecreaseLiquidityQuoteParam.__type\"},{\"id\":168,\"kind\":1024,\"name\":\"tickCurrentIndex\",\"url\":\"modules.html#DecreaseLiquidityQuoteParam.__type.tickCurrentIndex\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"DecreaseLiquidityQuoteParam.__type\"},{\"id\":169,\"kind\":1024,\"name\":\"sqrtPrice\",\"url\":\"modules.html#DecreaseLiquidityQuoteParam.__type.sqrtPrice\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"DecreaseLiquidityQuoteParam.__type\"},{\"id\":170,\"kind\":1024,\"name\":\"tickLowerIndex\",\"url\":\"modules.html#DecreaseLiquidityQuoteParam.__type.tickLowerIndex\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"DecreaseLiquidityQuoteParam.__type\"},{\"id\":171,\"kind\":1024,\"name\":\"tickUpperIndex\",\"url\":\"modules.html#DecreaseLiquidityQuoteParam.__type.tickUpperIndex\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"DecreaseLiquidityQuoteParam.__type\"},{\"id\":172,\"kind\":1024,\"name\":\"slippageTolerance\",\"url\":\"modules.html#DecreaseLiquidityQuoteParam.__type.slippageTolerance\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"DecreaseLiquidityQuoteParam.__type\"},{\"id\":173,\"kind\":4194304,\"name\":\"DecreaseLiquidityQuote\",\"url\":\"modules.html#DecreaseLiquidityQuote\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":174,\"kind\":64,\"name\":\"collectFeesQuote\",\"url\":\"modules.html#collectFeesQuote\",\"classes\":\"tsd-kind-function\"},{\"id\":175,\"kind\":4194304,\"name\":\"CollectFeesQuoteParam\",\"url\":\"modules.html#CollectFeesQuoteParam\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":176,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#CollectFeesQuoteParam.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"CollectFeesQuoteParam\"},{\"id\":177,\"kind\":1024,\"name\":\"whirlpool\",\"url\":\"modules.html#CollectFeesQuoteParam.__type.whirlpool\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"CollectFeesQuoteParam.__type\"},{\"id\":178,\"kind\":1024,\"name\":\"position\",\"url\":\"modules.html#CollectFeesQuoteParam.__type.position\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"CollectFeesQuoteParam.__type\"},{\"id\":179,\"kind\":1024,\"name\":\"tickLower\",\"url\":\"modules.html#CollectFeesQuoteParam.__type.tickLower\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"CollectFeesQuoteParam.__type\"},{\"id\":180,\"kind\":1024,\"name\":\"tickUpper\",\"url\":\"modules.html#CollectFeesQuoteParam.__type.tickUpper\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"CollectFeesQuoteParam.__type\"},{\"id\":181,\"kind\":4194304,\"name\":\"CollectFeesQuote\",\"url\":\"modules.html#CollectFeesQuote\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":182,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#CollectFeesQuote.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"CollectFeesQuote\"},{\"id\":183,\"kind\":1024,\"name\":\"feeOwedA\",\"url\":\"modules.html#CollectFeesQuote.__type.feeOwedA\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"CollectFeesQuote.__type\"},{\"id\":184,\"kind\":1024,\"name\":\"feeOwedB\",\"url\":\"modules.html#CollectFeesQuote.__type.feeOwedB\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"CollectFeesQuote.__type\"},{\"id\":185,\"kind\":64,\"name\":\"collectRewardsQuote\",\"url\":\"modules.html#collectRewardsQuote\",\"classes\":\"tsd-kind-function\"},{\"id\":186,\"kind\":4194304,\"name\":\"CollectRewardsQuoteParam\",\"url\":\"modules.html#CollectRewardsQuoteParam\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":187,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#CollectRewardsQuoteParam.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"CollectRewardsQuoteParam\"},{\"id\":188,\"kind\":1024,\"name\":\"whirlpool\",\"url\":\"modules.html#CollectRewardsQuoteParam.__type.whirlpool\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"CollectRewardsQuoteParam.__type\"},{\"id\":189,\"kind\":1024,\"name\":\"position\",\"url\":\"modules.html#CollectRewardsQuoteParam.__type.position\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"CollectRewardsQuoteParam.__type\"},{\"id\":190,\"kind\":1024,\"name\":\"tickLower\",\"url\":\"modules.html#CollectRewardsQuoteParam.__type.tickLower\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"CollectRewardsQuoteParam.__type\"},{\"id\":191,\"kind\":1024,\"name\":\"tickUpper\",\"url\":\"modules.html#CollectRewardsQuoteParam.__type.tickUpper\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"CollectRewardsQuoteParam.__type\"},{\"id\":192,\"kind\":1024,\"name\":\"timeStampInSeconds\",\"url\":\"modules.html#CollectRewardsQuoteParam.__type.timeStampInSeconds\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"CollectRewardsQuoteParam.__type\"},{\"id\":193,\"kind\":4194304,\"name\":\"CollectRewardsQuote\",\"url\":\"modules.html#CollectRewardsQuote\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":194,\"kind\":64,\"name\":\"swapQuoteByInputToken\",\"url\":\"modules.html#swapQuoteByInputToken\",\"classes\":\"tsd-kind-function\"},{\"id\":195,\"kind\":64,\"name\":\"swapQuoteByOutputToken\",\"url\":\"modules.html#swapQuoteByOutputToken\",\"classes\":\"tsd-kind-function\"},{\"id\":196,\"kind\":64,\"name\":\"swapQuoteWithParams\",\"url\":\"modules.html#swapQuoteWithParams\",\"classes\":\"tsd-kind-function\"},{\"id\":197,\"kind\":4194304,\"name\":\"SwapQuoteParam\",\"url\":\"modules.html#SwapQuoteParam\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":198,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#SwapQuoteParam.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"SwapQuoteParam\"},{\"id\":199,\"kind\":1024,\"name\":\"whirlpoolData\",\"url\":\"modules.html#SwapQuoteParam.__type.whirlpoolData\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SwapQuoteParam.__type\"},{\"id\":200,\"kind\":1024,\"name\":\"tokenAmount\",\"url\":\"modules.html#SwapQuoteParam.__type.tokenAmount\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SwapQuoteParam.__type\"},{\"id\":201,\"kind\":1024,\"name\":\"otherAmountThreshold\",\"url\":\"modules.html#SwapQuoteParam.__type.otherAmountThreshold\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SwapQuoteParam.__type\"},{\"id\":202,\"kind\":1024,\"name\":\"sqrtPriceLimit\",\"url\":\"modules.html#SwapQuoteParam.__type.sqrtPriceLimit\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SwapQuoteParam.__type\"},{\"id\":203,\"kind\":1024,\"name\":\"aToB\",\"url\":\"modules.html#SwapQuoteParam.__type.aToB\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SwapQuoteParam.__type\"},{\"id\":204,\"kind\":1024,\"name\":\"amountSpecifiedIsInput\",\"url\":\"modules.html#SwapQuoteParam.__type.amountSpecifiedIsInput\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SwapQuoteParam.__type\"},{\"id\":205,\"kind\":1024,\"name\":\"tickArrays\",\"url\":\"modules.html#SwapQuoteParam.__type.tickArrays\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SwapQuoteParam.__type\"},{\"id\":206,\"kind\":4194304,\"name\":\"SwapQuote\",\"url\":\"modules.html#SwapQuote\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":207,\"kind\":4194304,\"name\":\"SwapEstimates\",\"url\":\"modules.html#SwapEstimates\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":208,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#SwapEstimates.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"SwapEstimates\"},{\"id\":209,\"kind\":1024,\"name\":\"estimatedAmountIn\",\"url\":\"modules.html#SwapEstimates.__type.estimatedAmountIn\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SwapEstimates.__type\"},{\"id\":210,\"kind\":1024,\"name\":\"estimatedAmountOut\",\"url\":\"modules.html#SwapEstimates.__type.estimatedAmountOut\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SwapEstimates.__type\"},{\"id\":211,\"kind\":1024,\"name\":\"estimatedEndTickIndex\",\"url\":\"modules.html#SwapEstimates.__type.estimatedEndTickIndex\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SwapEstimates.__type\"},{\"id\":212,\"kind\":1024,\"name\":\"estimatedEndSqrtPrice\",\"url\":\"modules.html#SwapEstimates.__type.estimatedEndSqrtPrice\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SwapEstimates.__type\"},{\"id\":213,\"kind\":1024,\"name\":\"estimatedFeeAmount\",\"url\":\"modules.html#SwapEstimates.__type.estimatedFeeAmount\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SwapEstimates.__type\"},{\"id\":214,\"kind\":4194304,\"name\":\"NormalSwapQuote\",\"url\":\"modules.html#NormalSwapQuote\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":215,\"kind\":64,\"name\":\"swapQuoteByInputTokenWithDevFees\",\"url\":\"modules.html#swapQuoteByInputTokenWithDevFees\",\"classes\":\"tsd-kind-function\"},{\"id\":216,\"kind\":4194304,\"name\":\"DevFeeSwapQuote\",\"url\":\"modules.html#DevFeeSwapQuote\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":217,\"kind\":64,\"name\":\"twoHopSwapQuoteFromSwapQuotes\",\"url\":\"modules.html#twoHopSwapQuoteFromSwapQuotes\",\"classes\":\"tsd-kind-function\"},{\"id\":218,\"kind\":4194304,\"name\":\"TwoHopSwapQuote\",\"url\":\"modules.html#TwoHopSwapQuote\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":219,\"kind\":4194304,\"name\":\"NormalTwoHopSwapQuote\",\"url\":\"modules.html#NormalTwoHopSwapQuote\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":220,\"kind\":4194304,\"name\":\"Trade\",\"url\":\"modules.html#Trade\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":221,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#Trade.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"Trade\"},{\"id\":222,\"kind\":1024,\"name\":\"tokenIn\",\"url\":\"modules.html#Trade.__type.tokenIn\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"Trade.__type\"},{\"id\":223,\"kind\":1024,\"name\":\"tokenOut\",\"url\":\"modules.html#Trade.__type.tokenOut\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"Trade.__type\"},{\"id\":224,\"kind\":1024,\"name\":\"tradeAmount\",\"url\":\"modules.html#Trade.__type.tradeAmount\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"Trade.__type\"},{\"id\":225,\"kind\":1024,\"name\":\"amountSpecifiedIsInput\",\"url\":\"modules.html#Trade.__type.amountSpecifiedIsInput\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"Trade.__type\"},{\"id\":226,\"kind\":4194304,\"name\":\"RoutingOptions\",\"url\":\"modules.html#RoutingOptions\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":227,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#RoutingOptions.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"RoutingOptions\"},{\"id\":228,\"kind\":1024,\"name\":\"percentIncrement\",\"url\":\"modules.html#RoutingOptions.__type.percentIncrement\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"RoutingOptions.__type\"},{\"id\":229,\"kind\":1024,\"name\":\"numTopRoutes\",\"url\":\"modules.html#RoutingOptions.__type.numTopRoutes\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"RoutingOptions.__type\"},{\"id\":230,\"kind\":1024,\"name\":\"numTopPartialQuotes\",\"url\":\"modules.html#RoutingOptions.__type.numTopPartialQuotes\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"RoutingOptions.__type\"},{\"id\":231,\"kind\":1024,\"name\":\"maxSplits\",\"url\":\"modules.html#RoutingOptions.__type.maxSplits\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"RoutingOptions.__type\"},{\"id\":232,\"kind\":4194304,\"name\":\"TradeRoute\",\"url\":\"modules.html#TradeRoute\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":233,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#TradeRoute.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"TradeRoute\"},{\"id\":234,\"kind\":1024,\"name\":\"subRoutes\",\"url\":\"modules.html#TradeRoute.__type.subRoutes\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"TradeRoute.__type\"},{\"id\":235,\"kind\":1024,\"name\":\"totalAmountIn\",\"url\":\"modules.html#TradeRoute.__type.totalAmountIn\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"TradeRoute.__type\"},{\"id\":236,\"kind\":1024,\"name\":\"totalAmountOut\",\"url\":\"modules.html#TradeRoute.__type.totalAmountOut\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"TradeRoute.__type\"},{\"id\":237,\"kind\":4194304,\"name\":\"SubTradeRoute\",\"url\":\"modules.html#SubTradeRoute\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":238,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#SubTradeRoute.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"SubTradeRoute\"},{\"id\":239,\"kind\":1024,\"name\":\"path\",\"url\":\"modules.html#SubTradeRoute.__type.path\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SubTradeRoute.__type\"},{\"id\":240,\"kind\":1024,\"name\":\"splitPercent\",\"url\":\"modules.html#SubTradeRoute.__type.splitPercent\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SubTradeRoute.__type\"},{\"id\":241,\"kind\":1024,\"name\":\"amountIn\",\"url\":\"modules.html#SubTradeRoute.__type.amountIn\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SubTradeRoute.__type\"},{\"id\":242,\"kind\":1024,\"name\":\"amountOut\",\"url\":\"modules.html#SubTradeRoute.__type.amountOut\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SubTradeRoute.__type\"},{\"id\":243,\"kind\":1024,\"name\":\"hopQuotes\",\"url\":\"modules.html#SubTradeRoute.__type.hopQuotes\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SubTradeRoute.__type\"},{\"id\":244,\"kind\":4194304,\"name\":\"TradeHop\",\"url\":\"modules.html#TradeHop\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":245,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#TradeHop.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"TradeHop\"},{\"id\":246,\"kind\":1024,\"name\":\"amountIn\",\"url\":\"modules.html#TradeHop.__type.amountIn\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"TradeHop.__type\"},{\"id\":247,\"kind\":1024,\"name\":\"amountOut\",\"url\":\"modules.html#TradeHop.__type.amountOut\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"TradeHop.__type\"},{\"id\":248,\"kind\":1024,\"name\":\"whirlpool\",\"url\":\"modules.html#TradeHop.__type.whirlpool\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"TradeHop.__type\"},{\"id\":249,\"kind\":1024,\"name\":\"inputMint\",\"url\":\"modules.html#TradeHop.__type.inputMint\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"TradeHop.__type\"},{\"id\":250,\"kind\":1024,\"name\":\"outputMint\",\"url\":\"modules.html#TradeHop.__type.outputMint\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"TradeHop.__type\"},{\"id\":251,\"kind\":1024,\"name\":\"mintA\",\"url\":\"modules.html#TradeHop.__type.mintA\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"TradeHop.__type\"},{\"id\":252,\"kind\":1024,\"name\":\"mintB\",\"url\":\"modules.html#TradeHop.__type.mintB\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"TradeHop.__type\"},{\"id\":253,\"kind\":1024,\"name\":\"vaultA\",\"url\":\"modules.html#TradeHop.__type.vaultA\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"TradeHop.__type\"},{\"id\":254,\"kind\":1024,\"name\":\"vaultB\",\"url\":\"modules.html#TradeHop.__type.vaultB\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"TradeHop.__type\"},{\"id\":255,\"kind\":1024,\"name\":\"quote\",\"url\":\"modules.html#TradeHop.__type.quote\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"TradeHop.__type\"},{\"id\":256,\"kind\":1024,\"name\":\"snapshot\",\"url\":\"modules.html#TradeHop.__type.snapshot\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"TradeHop.__type\"},{\"id\":257,\"kind\":4194304,\"name\":\"TradeHopSnapshot\",\"url\":\"modules.html#TradeHopSnapshot\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":258,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#TradeHopSnapshot.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"TradeHopSnapshot\"},{\"id\":259,\"kind\":1024,\"name\":\"aToB\",\"url\":\"modules.html#TradeHopSnapshot.__type.aToB\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"TradeHopSnapshot.__type\"},{\"id\":260,\"kind\":1024,\"name\":\"sqrtPrice\",\"url\":\"modules.html#TradeHopSnapshot.__type.sqrtPrice\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"TradeHopSnapshot.__type\"},{\"id\":261,\"kind\":1024,\"name\":\"feeRate\",\"url\":\"modules.html#TradeHopSnapshot.__type.feeRate\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"TradeHopSnapshot.__type\"},{\"id\":262,\"kind\":4194304,\"name\":\"ExecutableRoute\",\"url\":\"modules.html#ExecutableRoute\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":263,\"kind\":256,\"name\":\"WhirlpoolRouter\",\"url\":\"interfaces/WhirlpoolRouter.html\",\"classes\":\"tsd-kind-interface\"},{\"id\":264,\"kind\":2048,\"name\":\"findAllRoutes\",\"url\":\"interfaces/WhirlpoolRouter.html#findAllRoutes\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"WhirlpoolRouter\"},{\"id\":265,\"kind\":2048,\"name\":\"findBestRoute\",\"url\":\"interfaces/WhirlpoolRouter.html#findBestRoute\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"WhirlpoolRouter\"},{\"id\":266,\"kind\":2048,\"name\":\"swap\",\"url\":\"interfaces/WhirlpoolRouter.html#swap\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"WhirlpoolRouter\"},{\"id\":267,\"kind\":128,\"name\":\"WhirlpoolRouterBuilder\",\"url\":\"classes/WhirlpoolRouterBuilder.html\",\"classes\":\"tsd-kind-class\"},{\"id\":268,\"kind\":2048,\"name\":\"buildWithPoolGraph\",\"url\":\"classes/WhirlpoolRouterBuilder.html#buildWithPoolGraph\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"WhirlpoolRouterBuilder\"},{\"id\":269,\"kind\":2048,\"name\":\"buildWithPools\",\"url\":\"classes/WhirlpoolRouterBuilder.html#buildWithPools\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"WhirlpoolRouterBuilder\"},{\"id\":270,\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/WhirlpoolRouterBuilder.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"WhirlpoolRouterBuilder\"},{\"id\":271,\"kind\":4194304,\"name\":\"AtaAccountInfo\",\"url\":\"modules.html#AtaAccountInfo\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":272,\"kind\":4194304,\"name\":\"RouteSelectOptions\",\"url\":\"modules.html#RouteSelectOptions\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":273,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#RouteSelectOptions.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"RouteSelectOptions\"},{\"id\":274,\"kind\":1024,\"name\":\"maxSupportedTransactionVersion\",\"url\":\"modules.html#RouteSelectOptions.__type.maxSupportedTransactionVersion\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"RouteSelectOptions.__type\"},{\"id\":275,\"kind\":1024,\"name\":\"maxTransactionSize\",\"url\":\"modules.html#RouteSelectOptions.__type.maxTransactionSize\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"RouteSelectOptions.__type\"},{\"id\":276,\"kind\":1024,\"name\":\"availableAtaAccounts\",\"url\":\"modules.html#RouteSelectOptions.__type.availableAtaAccounts\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"RouteSelectOptions.__type\"},{\"id\":277,\"kind\":2048,\"name\":\"onRouteEvaluation\",\"url\":\"modules.html#RouteSelectOptions.__type.onRouteEvaluation\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"RouteSelectOptions.__type\"},{\"id\":278,\"kind\":128,\"name\":\"RouterUtils\",\"url\":\"classes/RouterUtils.html\",\"classes\":\"tsd-kind-class\"},{\"id\":279,\"kind\":2048,\"name\":\"selectFirstExecutableRoute\",\"url\":\"classes/RouterUtils.html#selectFirstExecutableRoute\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"RouterUtils\"},{\"id\":280,\"kind\":2048,\"name\":\"getPriceImpactForRoute\",\"url\":\"classes/RouterUtils.html#getPriceImpactForRoute\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"RouterUtils\"},{\"id\":281,\"kind\":2048,\"name\":\"getTouchedTickArraysFromRoute\",\"url\":\"classes/RouterUtils.html#getTouchedTickArraysFromRoute\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"RouterUtils\"},{\"id\":282,\"kind\":2048,\"name\":\"getDefaultRouteOptions\",\"url\":\"classes/RouterUtils.html#getDefaultRouteOptions\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"RouterUtils\"},{\"id\":283,\"kind\":2048,\"name\":\"getDefaultSelectOptions\",\"url\":\"classes/RouterUtils.html#getDefaultSelectOptions\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"RouterUtils\"},{\"id\":284,\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/RouterUtils.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"RouterUtils\"},{\"id\":285,\"kind\":64,\"name\":\"getAccountSize\",\"url\":\"modules.html#getAccountSize\",\"classes\":\"tsd-kind-function\"},{\"id\":286,\"kind\":8,\"name\":\"AccountName\",\"url\":\"enums/AccountName.html\",\"classes\":\"tsd-kind-enum\"},{\"id\":287,\"kind\":16,\"name\":\"WhirlpoolsConfig\",\"url\":\"enums/AccountName.html#WhirlpoolsConfig\",\"classes\":\"tsd-kind-enum-member tsd-parent-kind-enum\",\"parent\":\"AccountName\"},{\"id\":288,\"kind\":16,\"name\":\"Position\",\"url\":\"enums/AccountName.html#Position\",\"classes\":\"tsd-kind-enum-member tsd-parent-kind-enum\",\"parent\":\"AccountName\"},{\"id\":289,\"kind\":16,\"name\":\"TickArray\",\"url\":\"enums/AccountName.html#TickArray\",\"classes\":\"tsd-kind-enum-member tsd-parent-kind-enum\",\"parent\":\"AccountName\"},{\"id\":290,\"kind\":16,\"name\":\"Whirlpool\",\"url\":\"enums/AccountName.html#Whirlpool\",\"classes\":\"tsd-kind-enum-member tsd-parent-kind-enum\",\"parent\":\"AccountName\"},{\"id\":291,\"kind\":16,\"name\":\"FeeTier\",\"url\":\"enums/AccountName.html#FeeTier\",\"classes\":\"tsd-kind-enum-member tsd-parent-kind-enum\",\"parent\":\"AccountName\"},{\"id\":292,\"kind\":16,\"name\":\"PositionBundle\",\"url\":\"enums/AccountName.html#PositionBundle\",\"classes\":\"tsd-kind-enum-member tsd-parent-kind-enum\",\"parent\":\"AccountName\"},{\"id\":293,\"kind\":32,\"name\":\"WHIRLPOOL_IDL\",\"url\":\"modules.html#WHIRLPOOL_IDL\",\"classes\":\"tsd-kind-variable\"},{\"id\":294,\"kind\":32,\"name\":\"WHIRLPOOL_CODER\",\"url\":\"modules.html#WHIRLPOOL_CODER\",\"classes\":\"tsd-kind-variable\"},{\"id\":295,\"kind\":32,\"name\":\"WHIRLPOOL_ACCOUNT_SIZE\",\"url\":\"modules.html#WHIRLPOOL_ACCOUNT_SIZE\",\"classes\":\"tsd-kind-variable\"},{\"id\":296,\"kind\":4194304,\"name\":\"WhirlpoolsConfigData\",\"url\":\"modules.html#WhirlpoolsConfigData\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":297,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#WhirlpoolsConfigData.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"WhirlpoolsConfigData\"},{\"id\":298,\"kind\":1024,\"name\":\"feeAuthority\",\"url\":\"modules.html#WhirlpoolsConfigData.__type.feeAuthority\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"WhirlpoolsConfigData.__type\"},{\"id\":299,\"kind\":1024,\"name\":\"collectProtocolFeesAuthority\",\"url\":\"modules.html#WhirlpoolsConfigData.__type.collectProtocolFeesAuthority\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"WhirlpoolsConfigData.__type\"},{\"id\":300,\"kind\":1024,\"name\":\"rewardEmissionsSuperAuthority\",\"url\":\"modules.html#WhirlpoolsConfigData.__type.rewardEmissionsSuperAuthority\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"WhirlpoolsConfigData.__type\"},{\"id\":301,\"kind\":1024,\"name\":\"defaultFeeRate\",\"url\":\"modules.html#WhirlpoolsConfigData.__type.defaultFeeRate\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"WhirlpoolsConfigData.__type\"},{\"id\":302,\"kind\":1024,\"name\":\"defaultProtocolFeeRate\",\"url\":\"modules.html#WhirlpoolsConfigData.__type.defaultProtocolFeeRate\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"WhirlpoolsConfigData.__type\"},{\"id\":303,\"kind\":4194304,\"name\":\"WhirlpoolRewardInfoData\",\"url\":\"modules.html#WhirlpoolRewardInfoData\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":304,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#WhirlpoolRewardInfoData.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"WhirlpoolRewardInfoData\"},{\"id\":305,\"kind\":1024,\"name\":\"mint\",\"url\":\"modules.html#WhirlpoolRewardInfoData.__type.mint\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"WhirlpoolRewardInfoData.__type\"},{\"id\":306,\"kind\":1024,\"name\":\"vault\",\"url\":\"modules.html#WhirlpoolRewardInfoData.__type.vault\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"WhirlpoolRewardInfoData.__type\"},{\"id\":307,\"kind\":1024,\"name\":\"authority\",\"url\":\"modules.html#WhirlpoolRewardInfoData.__type.authority\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"WhirlpoolRewardInfoData.__type\"},{\"id\":308,\"kind\":1024,\"name\":\"emissionsPerSecondX64\",\"url\":\"modules.html#WhirlpoolRewardInfoData.__type.emissionsPerSecondX64\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"WhirlpoolRewardInfoData.__type\"},{\"id\":309,\"kind\":1024,\"name\":\"growthGlobalX64\",\"url\":\"modules.html#WhirlpoolRewardInfoData.__type.growthGlobalX64\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"WhirlpoolRewardInfoData.__type\"},{\"id\":310,\"kind\":4194304,\"name\":\"WhirlpoolBumpsData\",\"url\":\"modules.html#WhirlpoolBumpsData\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":311,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#WhirlpoolBumpsData.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"WhirlpoolBumpsData\"},{\"id\":312,\"kind\":1024,\"name\":\"whirlpoolBump\",\"url\":\"modules.html#WhirlpoolBumpsData.__type.whirlpoolBump\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"WhirlpoolBumpsData.__type\"},{\"id\":313,\"kind\":4194304,\"name\":\"WhirlpoolData\",\"url\":\"modules.html#WhirlpoolData\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":314,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#WhirlpoolData.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"WhirlpoolData\"},{\"id\":315,\"kind\":1024,\"name\":\"whirlpoolsConfig\",\"url\":\"modules.html#WhirlpoolData.__type.whirlpoolsConfig\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"WhirlpoolData.__type\"},{\"id\":316,\"kind\":1024,\"name\":\"whirlpoolBump\",\"url\":\"modules.html#WhirlpoolData.__type.whirlpoolBump\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"WhirlpoolData.__type\"},{\"id\":317,\"kind\":1024,\"name\":\"feeRate\",\"url\":\"modules.html#WhirlpoolData.__type.feeRate\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"WhirlpoolData.__type\"},{\"id\":318,\"kind\":1024,\"name\":\"protocolFeeRate\",\"url\":\"modules.html#WhirlpoolData.__type.protocolFeeRate\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"WhirlpoolData.__type\"},{\"id\":319,\"kind\":1024,\"name\":\"liquidity\",\"url\":\"modules.html#WhirlpoolData.__type.liquidity\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"WhirlpoolData.__type\"},{\"id\":320,\"kind\":1024,\"name\":\"sqrtPrice\",\"url\":\"modules.html#WhirlpoolData.__type.sqrtPrice\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"WhirlpoolData.__type\"},{\"id\":321,\"kind\":1024,\"name\":\"tickCurrentIndex\",\"url\":\"modules.html#WhirlpoolData.__type.tickCurrentIndex\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"WhirlpoolData.__type\"},{\"id\":322,\"kind\":1024,\"name\":\"protocolFeeOwedA\",\"url\":\"modules.html#WhirlpoolData.__type.protocolFeeOwedA\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"WhirlpoolData.__type\"},{\"id\":323,\"kind\":1024,\"name\":\"protocolFeeOwedB\",\"url\":\"modules.html#WhirlpoolData.__type.protocolFeeOwedB\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"WhirlpoolData.__type\"},{\"id\":324,\"kind\":1024,\"name\":\"tokenMintA\",\"url\":\"modules.html#WhirlpoolData.__type.tokenMintA\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"WhirlpoolData.__type\"},{\"id\":325,\"kind\":1024,\"name\":\"tokenVaultA\",\"url\":\"modules.html#WhirlpoolData.__type.tokenVaultA\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"WhirlpoolData.__type\"},{\"id\":326,\"kind\":1024,\"name\":\"feeGrowthGlobalA\",\"url\":\"modules.html#WhirlpoolData.__type.feeGrowthGlobalA\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"WhirlpoolData.__type\"},{\"id\":327,\"kind\":1024,\"name\":\"tokenMintB\",\"url\":\"modules.html#WhirlpoolData.__type.tokenMintB\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"WhirlpoolData.__type\"},{\"id\":328,\"kind\":1024,\"name\":\"tokenVaultB\",\"url\":\"modules.html#WhirlpoolData.__type.tokenVaultB\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"WhirlpoolData.__type\"},{\"id\":329,\"kind\":1024,\"name\":\"feeGrowthGlobalB\",\"url\":\"modules.html#WhirlpoolData.__type.feeGrowthGlobalB\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"WhirlpoolData.__type\"},{\"id\":330,\"kind\":1024,\"name\":\"rewardLastUpdatedTimestamp\",\"url\":\"modules.html#WhirlpoolData.__type.rewardLastUpdatedTimestamp\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"WhirlpoolData.__type\"},{\"id\":331,\"kind\":1024,\"name\":\"rewardInfos\",\"url\":\"modules.html#WhirlpoolData.__type.rewardInfos\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"WhirlpoolData.__type\"},{\"id\":332,\"kind\":1024,\"name\":\"tickSpacing\",\"url\":\"modules.html#WhirlpoolData.__type.tickSpacing\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"WhirlpoolData.__type\"},{\"id\":333,\"kind\":4194304,\"name\":\"TickArrayData\",\"url\":\"modules.html#TickArrayData\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":334,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#TickArrayData.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"TickArrayData\"},{\"id\":335,\"kind\":1024,\"name\":\"whirlpool\",\"url\":\"modules.html#TickArrayData.__type.whirlpool\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"TickArrayData.__type\"},{\"id\":336,\"kind\":1024,\"name\":\"startTickIndex\",\"url\":\"modules.html#TickArrayData.__type.startTickIndex\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"TickArrayData.__type\"},{\"id\":337,\"kind\":1024,\"name\":\"ticks\",\"url\":\"modules.html#TickArrayData.__type.ticks\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"TickArrayData.__type\"},{\"id\":338,\"kind\":4194304,\"name\":\"TickData\",\"url\":\"modules.html#TickData\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":339,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#TickData.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"TickData\"},{\"id\":340,\"kind\":1024,\"name\":\"initialized\",\"url\":\"modules.html#TickData.__type.initialized\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"TickData.__type\"},{\"id\":341,\"kind\":1024,\"name\":\"liquidityNet\",\"url\":\"modules.html#TickData.__type.liquidityNet\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"TickData.__type\"},{\"id\":342,\"kind\":1024,\"name\":\"liquidityGross\",\"url\":\"modules.html#TickData.__type.liquidityGross\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"TickData.__type\"},{\"id\":343,\"kind\":1024,\"name\":\"feeGrowthOutsideA\",\"url\":\"modules.html#TickData.__type.feeGrowthOutsideA\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"TickData.__type\"},{\"id\":344,\"kind\":1024,\"name\":\"feeGrowthOutsideB\",\"url\":\"modules.html#TickData.__type.feeGrowthOutsideB\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"TickData.__type\"},{\"id\":345,\"kind\":1024,\"name\":\"rewardGrowthsOutside\",\"url\":\"modules.html#TickData.__type.rewardGrowthsOutside\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"TickData.__type\"},{\"id\":346,\"kind\":4194304,\"name\":\"PositionRewardInfoData\",\"url\":\"modules.html#PositionRewardInfoData\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":347,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#PositionRewardInfoData.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"PositionRewardInfoData\"},{\"id\":348,\"kind\":1024,\"name\":\"growthInsideCheckpoint\",\"url\":\"modules.html#PositionRewardInfoData.__type.growthInsideCheckpoint\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"PositionRewardInfoData.__type\"},{\"id\":349,\"kind\":1024,\"name\":\"amountOwed\",\"url\":\"modules.html#PositionRewardInfoData.__type.amountOwed\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"PositionRewardInfoData.__type\"},{\"id\":350,\"kind\":4194304,\"name\":\"OpenPositionBumpsData\",\"url\":\"modules.html#OpenPositionBumpsData\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":351,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#OpenPositionBumpsData.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"OpenPositionBumpsData\"},{\"id\":352,\"kind\":1024,\"name\":\"positionBump\",\"url\":\"modules.html#OpenPositionBumpsData.__type.positionBump\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"OpenPositionBumpsData.__type\"},{\"id\":353,\"kind\":4194304,\"name\":\"OpenPositionWithMetadataBumpsData\",\"url\":\"modules.html#OpenPositionWithMetadataBumpsData\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":354,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#OpenPositionWithMetadataBumpsData.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"OpenPositionWithMetadataBumpsData\"},{\"id\":355,\"kind\":1024,\"name\":\"positionBump\",\"url\":\"modules.html#OpenPositionWithMetadataBumpsData.__type.positionBump\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"OpenPositionWithMetadataBumpsData.__type\"},{\"id\":356,\"kind\":1024,\"name\":\"metadataBump\",\"url\":\"modules.html#OpenPositionWithMetadataBumpsData.__type.metadataBump\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"OpenPositionWithMetadataBumpsData.__type\"},{\"id\":357,\"kind\":4194304,\"name\":\"PositionData\",\"url\":\"modules.html#PositionData\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":358,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#PositionData.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"PositionData\"},{\"id\":359,\"kind\":1024,\"name\":\"whirlpool\",\"url\":\"modules.html#PositionData.__type.whirlpool\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"PositionData.__type\"},{\"id\":360,\"kind\":1024,\"name\":\"positionMint\",\"url\":\"modules.html#PositionData.__type.positionMint\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"PositionData.__type\"},{\"id\":361,\"kind\":1024,\"name\":\"liquidity\",\"url\":\"modules.html#PositionData.__type.liquidity\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"PositionData.__type\"},{\"id\":362,\"kind\":1024,\"name\":\"tickLowerIndex\",\"url\":\"modules.html#PositionData.__type.tickLowerIndex\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"PositionData.__type\"},{\"id\":363,\"kind\":1024,\"name\":\"tickUpperIndex\",\"url\":\"modules.html#PositionData.__type.tickUpperIndex\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"PositionData.__type\"},{\"id\":364,\"kind\":1024,\"name\":\"feeGrowthCheckpointA\",\"url\":\"modules.html#PositionData.__type.feeGrowthCheckpointA\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"PositionData.__type\"},{\"id\":365,\"kind\":1024,\"name\":\"feeOwedA\",\"url\":\"modules.html#PositionData.__type.feeOwedA\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"PositionData.__type\"},{\"id\":366,\"kind\":1024,\"name\":\"feeGrowthCheckpointB\",\"url\":\"modules.html#PositionData.__type.feeGrowthCheckpointB\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"PositionData.__type\"},{\"id\":367,\"kind\":1024,\"name\":\"feeOwedB\",\"url\":\"modules.html#PositionData.__type.feeOwedB\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"PositionData.__type\"},{\"id\":368,\"kind\":1024,\"name\":\"rewardInfos\",\"url\":\"modules.html#PositionData.__type.rewardInfos\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"PositionData.__type\"},{\"id\":369,\"kind\":4194304,\"name\":\"FeeTierData\",\"url\":\"modules.html#FeeTierData\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":370,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#FeeTierData.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"FeeTierData\"},{\"id\":371,\"kind\":1024,\"name\":\"whirlpoolsConfig\",\"url\":\"modules.html#FeeTierData.__type.whirlpoolsConfig\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"FeeTierData.__type\"},{\"id\":372,\"kind\":1024,\"name\":\"tickSpacing\",\"url\":\"modules.html#FeeTierData.__type.tickSpacing\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"FeeTierData.__type\"},{\"id\":373,\"kind\":1024,\"name\":\"defaultFeeRate\",\"url\":\"modules.html#FeeTierData.__type.defaultFeeRate\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"FeeTierData.__type\"},{\"id\":374,\"kind\":4194304,\"name\":\"PositionBundleData\",\"url\":\"modules.html#PositionBundleData\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":375,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#PositionBundleData.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"PositionBundleData\"},{\"id\":376,\"kind\":1024,\"name\":\"positionBundleMint\",\"url\":\"modules.html#PositionBundleData.__type.positionBundleMint\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"PositionBundleData.__type\"},{\"id\":377,\"kind\":1024,\"name\":\"positionBitmap\",\"url\":\"modules.html#PositionBundleData.__type.positionBitmap\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"PositionBundleData.__type\"},{\"id\":378,\"kind\":4194304,\"name\":\"TokenInfo\",\"url\":\"modules.html#TokenInfo\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":379,\"kind\":4194304,\"name\":\"TokenAccountInfo\",\"url\":\"modules.html#TokenAccountInfo\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":380,\"kind\":4194304,\"name\":\"WhirlpoolRewardInfo\",\"url\":\"modules.html#WhirlpoolRewardInfo\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":381,\"kind\":4194304,\"name\":\"TickArray\",\"url\":\"modules.html#TickArray\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":382,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#TickArray.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"TickArray\"},{\"id\":383,\"kind\":1024,\"name\":\"address\",\"url\":\"modules.html#TickArray.__type.address\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"TickArray.__type\"},{\"id\":384,\"kind\":1024,\"name\":\"data\",\"url\":\"modules.html#TickArray.__type.data\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"TickArray.__type\"},{\"id\":385,\"kind\":32,\"name\":\"ORCA_WHIRLPOOL_PROGRAM_ID\",\"url\":\"modules.html#ORCA_WHIRLPOOL_PROGRAM_ID\",\"classes\":\"tsd-kind-variable\"},{\"id\":386,\"kind\":32,\"name\":\"ORCA_WHIRLPOOLS_CONFIG\",\"url\":\"modules.html#ORCA_WHIRLPOOLS_CONFIG\",\"classes\":\"tsd-kind-variable\"},{\"id\":387,\"kind\":32,\"name\":\"ORCA_SUPPORTED_TICK_SPACINGS\",\"url\":\"modules.html#ORCA_SUPPORTED_TICK_SPACINGS\",\"classes\":\"tsd-kind-variable\"},{\"id\":388,\"kind\":32,\"name\":\"NUM_REWARDS\",\"url\":\"modules.html#NUM_REWARDS\",\"classes\":\"tsd-kind-variable\"},{\"id\":389,\"kind\":32,\"name\":\"MAX_TICK_INDEX\",\"url\":\"modules.html#MAX_TICK_INDEX\",\"classes\":\"tsd-kind-variable\"},{\"id\":390,\"kind\":32,\"name\":\"MIN_TICK_INDEX\",\"url\":\"modules.html#MIN_TICK_INDEX\",\"classes\":\"tsd-kind-variable\"},{\"id\":391,\"kind\":32,\"name\":\"MAX_SQRT_PRICE\",\"url\":\"modules.html#MAX_SQRT_PRICE\",\"classes\":\"tsd-kind-variable\"},{\"id\":392,\"kind\":32,\"name\":\"MIN_SQRT_PRICE\",\"url\":\"modules.html#MIN_SQRT_PRICE\",\"classes\":\"tsd-kind-variable\"},{\"id\":393,\"kind\":32,\"name\":\"TICK_ARRAY_SIZE\",\"url\":\"modules.html#TICK_ARRAY_SIZE\",\"classes\":\"tsd-kind-variable\"},{\"id\":394,\"kind\":32,\"name\":\"POSITION_BUNDLE_SIZE\",\"url\":\"modules.html#POSITION_BUNDLE_SIZE\",\"classes\":\"tsd-kind-variable\"},{\"id\":395,\"kind\":32,\"name\":\"METADATA_PROGRAM_ADDRESS\",\"url\":\"modules.html#METADATA_PROGRAM_ADDRESS\",\"classes\":\"tsd-kind-variable\"},{\"id\":396,\"kind\":32,\"name\":\"MAX_SWAP_TICK_ARRAYS\",\"url\":\"modules.html#MAX_SWAP_TICK_ARRAYS\",\"classes\":\"tsd-kind-variable\"},{\"id\":397,\"kind\":32,\"name\":\"PROTOCOL_FEE_RATE_MUL_VALUE\",\"url\":\"modules.html#PROTOCOL_FEE_RATE_MUL_VALUE\",\"classes\":\"tsd-kind-variable\"},{\"id\":398,\"kind\":32,\"name\":\"FEE_RATE_MUL_VALUE\",\"url\":\"modules.html#FEE_RATE_MUL_VALUE\",\"classes\":\"tsd-kind-variable\"},{\"id\":399,\"kind\":32,\"name\":\"WHIRLPOOL_NFT_UPDATE_AUTH\",\"url\":\"modules.html#WHIRLPOOL_NFT_UPDATE_AUTH\",\"classes\":\"tsd-kind-variable\"},{\"id\":400,\"kind\":4194304,\"name\":\"ClosePositionParams\",\"url\":\"modules.html#ClosePositionParams\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":401,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#ClosePositionParams.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"ClosePositionParams\"},{\"id\":402,\"kind\":1024,\"name\":\"receiver\",\"url\":\"modules.html#ClosePositionParams.__type.receiver\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"ClosePositionParams.__type\"},{\"id\":403,\"kind\":1024,\"name\":\"position\",\"url\":\"modules.html#ClosePositionParams.__type.position\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"ClosePositionParams.__type\"},{\"id\":404,\"kind\":1024,\"name\":\"positionMint\",\"url\":\"modules.html#ClosePositionParams.__type.positionMint\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"ClosePositionParams.__type\"},{\"id\":405,\"kind\":1024,\"name\":\"positionTokenAccount\",\"url\":\"modules.html#ClosePositionParams.__type.positionTokenAccount\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"ClosePositionParams.__type\"},{\"id\":406,\"kind\":1024,\"name\":\"positionAuthority\",\"url\":\"modules.html#ClosePositionParams.__type.positionAuthority\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"ClosePositionParams.__type\"},{\"id\":407,\"kind\":4194304,\"name\":\"CollectFeesParams\",\"url\":\"modules.html#CollectFeesParams\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":408,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#CollectFeesParams.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"CollectFeesParams\"},{\"id\":409,\"kind\":1024,\"name\":\"whirlpool\",\"url\":\"modules.html#CollectFeesParams.__type.whirlpool\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"CollectFeesParams.__type\"},{\"id\":410,\"kind\":1024,\"name\":\"position\",\"url\":\"modules.html#CollectFeesParams.__type.position\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"CollectFeesParams.__type\"},{\"id\":411,\"kind\":1024,\"name\":\"positionTokenAccount\",\"url\":\"modules.html#CollectFeesParams.__type.positionTokenAccount\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"CollectFeesParams.__type\"},{\"id\":412,\"kind\":1024,\"name\":\"tokenOwnerAccountA\",\"url\":\"modules.html#CollectFeesParams.__type.tokenOwnerAccountA\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"CollectFeesParams.__type\"},{\"id\":413,\"kind\":1024,\"name\":\"tokenOwnerAccountB\",\"url\":\"modules.html#CollectFeesParams.__type.tokenOwnerAccountB\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"CollectFeesParams.__type\"},{\"id\":414,\"kind\":1024,\"name\":\"tokenVaultA\",\"url\":\"modules.html#CollectFeesParams.__type.tokenVaultA\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"CollectFeesParams.__type\"},{\"id\":415,\"kind\":1024,\"name\":\"tokenVaultB\",\"url\":\"modules.html#CollectFeesParams.__type.tokenVaultB\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"CollectFeesParams.__type\"},{\"id\":416,\"kind\":1024,\"name\":\"positionAuthority\",\"url\":\"modules.html#CollectFeesParams.__type.positionAuthority\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"CollectFeesParams.__type\"},{\"id\":417,\"kind\":4194304,\"name\":\"CollectProtocolFeesParams\",\"url\":\"modules.html#CollectProtocolFeesParams\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":418,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#CollectProtocolFeesParams.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"CollectProtocolFeesParams\"},{\"id\":419,\"kind\":1024,\"name\":\"whirlpoolsConfig\",\"url\":\"modules.html#CollectProtocolFeesParams.__type.whirlpoolsConfig\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"CollectProtocolFeesParams.__type\"},{\"id\":420,\"kind\":1024,\"name\":\"whirlpool\",\"url\":\"modules.html#CollectProtocolFeesParams.__type.whirlpool\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"CollectProtocolFeesParams.__type\"},{\"id\":421,\"kind\":1024,\"name\":\"tokenVaultA\",\"url\":\"modules.html#CollectProtocolFeesParams.__type.tokenVaultA\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"CollectProtocolFeesParams.__type\"},{\"id\":422,\"kind\":1024,\"name\":\"tokenVaultB\",\"url\":\"modules.html#CollectProtocolFeesParams.__type.tokenVaultB\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"CollectProtocolFeesParams.__type\"},{\"id\":423,\"kind\":1024,\"name\":\"tokenOwnerAccountA\",\"url\":\"modules.html#CollectProtocolFeesParams.__type.tokenOwnerAccountA\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"CollectProtocolFeesParams.__type\"},{\"id\":424,\"kind\":1024,\"name\":\"tokenOwnerAccountB\",\"url\":\"modules.html#CollectProtocolFeesParams.__type.tokenOwnerAccountB\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"CollectProtocolFeesParams.__type\"},{\"id\":425,\"kind\":1024,\"name\":\"collectProtocolFeesAuthority\",\"url\":\"modules.html#CollectProtocolFeesParams.__type.collectProtocolFeesAuthority\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"CollectProtocolFeesParams.__type\"},{\"id\":426,\"kind\":4194304,\"name\":\"CollectRewardParams\",\"url\":\"modules.html#CollectRewardParams\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":427,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#CollectRewardParams.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"CollectRewardParams\"},{\"id\":428,\"kind\":1024,\"name\":\"whirlpool\",\"url\":\"modules.html#CollectRewardParams.__type.whirlpool\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"CollectRewardParams.__type\"},{\"id\":429,\"kind\":1024,\"name\":\"position\",\"url\":\"modules.html#CollectRewardParams.__type.position\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"CollectRewardParams.__type\"},{\"id\":430,\"kind\":1024,\"name\":\"positionTokenAccount\",\"url\":\"modules.html#CollectRewardParams.__type.positionTokenAccount\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"CollectRewardParams.__type\"},{\"id\":431,\"kind\":1024,\"name\":\"rewardIndex\",\"url\":\"modules.html#CollectRewardParams.__type.rewardIndex\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"CollectRewardParams.__type\"},{\"id\":432,\"kind\":1024,\"name\":\"rewardOwnerAccount\",\"url\":\"modules.html#CollectRewardParams.__type.rewardOwnerAccount\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"CollectRewardParams.__type\"},{\"id\":433,\"kind\":1024,\"name\":\"rewardVault\",\"url\":\"modules.html#CollectRewardParams.__type.rewardVault\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"CollectRewardParams.__type\"},{\"id\":434,\"kind\":1024,\"name\":\"positionAuthority\",\"url\":\"modules.html#CollectRewardParams.__type.positionAuthority\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"CollectRewardParams.__type\"},{\"id\":435,\"kind\":4194304,\"name\":\"DecreaseLiquidityInput\",\"url\":\"modules.html#DecreaseLiquidityInput\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":436,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#DecreaseLiquidityInput.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"DecreaseLiquidityInput\"},{\"id\":437,\"kind\":1024,\"name\":\"tokenMinA\",\"url\":\"modules.html#DecreaseLiquidityInput.__type.tokenMinA\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"DecreaseLiquidityInput.__type\"},{\"id\":438,\"kind\":1024,\"name\":\"tokenMinB\",\"url\":\"modules.html#DecreaseLiquidityInput.__type.tokenMinB\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"DecreaseLiquidityInput.__type\"},{\"id\":439,\"kind\":1024,\"name\":\"liquidityAmount\",\"url\":\"modules.html#DecreaseLiquidityInput.__type.liquidityAmount\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"DecreaseLiquidityInput.__type\"},{\"id\":440,\"kind\":4194304,\"name\":\"DecreaseLiquidityParams\",\"url\":\"modules.html#DecreaseLiquidityParams\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":441,\"kind\":4194304,\"name\":\"DevFeeSwapInput\",\"url\":\"modules.html#DevFeeSwapInput\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":442,\"kind\":4194304,\"name\":\"IncreaseLiquidityInput\",\"url\":\"modules.html#IncreaseLiquidityInput\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":443,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#IncreaseLiquidityInput.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"IncreaseLiquidityInput\"},{\"id\":444,\"kind\":1024,\"name\":\"tokenMaxA\",\"url\":\"modules.html#IncreaseLiquidityInput.__type.tokenMaxA\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"IncreaseLiquidityInput.__type\"},{\"id\":445,\"kind\":1024,\"name\":\"tokenMaxB\",\"url\":\"modules.html#IncreaseLiquidityInput.__type.tokenMaxB\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"IncreaseLiquidityInput.__type\"},{\"id\":446,\"kind\":1024,\"name\":\"liquidityAmount\",\"url\":\"modules.html#IncreaseLiquidityInput.__type.liquidityAmount\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"IncreaseLiquidityInput.__type\"},{\"id\":447,\"kind\":4194304,\"name\":\"IncreaseLiquidityParams\",\"url\":\"modules.html#IncreaseLiquidityParams\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":448,\"kind\":4194304,\"name\":\"InitConfigParams\",\"url\":\"modules.html#InitConfigParams\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":449,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#InitConfigParams.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"InitConfigParams\"},{\"id\":450,\"kind\":1024,\"name\":\"whirlpoolsConfigKeypair\",\"url\":\"modules.html#InitConfigParams.__type.whirlpoolsConfigKeypair\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"InitConfigParams.__type\"},{\"id\":451,\"kind\":1024,\"name\":\"feeAuthority\",\"url\":\"modules.html#InitConfigParams.__type.feeAuthority\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"InitConfigParams.__type\"},{\"id\":452,\"kind\":1024,\"name\":\"collectProtocolFeesAuthority\",\"url\":\"modules.html#InitConfigParams.__type.collectProtocolFeesAuthority\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"InitConfigParams.__type\"},{\"id\":453,\"kind\":1024,\"name\":\"rewardEmissionsSuperAuthority\",\"url\":\"modules.html#InitConfigParams.__type.rewardEmissionsSuperAuthority\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"InitConfigParams.__type\"},{\"id\":454,\"kind\":1024,\"name\":\"defaultProtocolFeeRate\",\"url\":\"modules.html#InitConfigParams.__type.defaultProtocolFeeRate\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"InitConfigParams.__type\"},{\"id\":455,\"kind\":1024,\"name\":\"funder\",\"url\":\"modules.html#InitConfigParams.__type.funder\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"InitConfigParams.__type\"},{\"id\":456,\"kind\":4194304,\"name\":\"InitFeeTierParams\",\"url\":\"modules.html#InitFeeTierParams\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":457,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#InitFeeTierParams.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"InitFeeTierParams\"},{\"id\":458,\"kind\":1024,\"name\":\"whirlpoolsConfig\",\"url\":\"modules.html#InitFeeTierParams.__type.whirlpoolsConfig\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"InitFeeTierParams.__type\"},{\"id\":459,\"kind\":1024,\"name\":\"feeTierPda\",\"url\":\"modules.html#InitFeeTierParams.__type.feeTierPda\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"InitFeeTierParams.__type\"},{\"id\":460,\"kind\":1024,\"name\":\"tickSpacing\",\"url\":\"modules.html#InitFeeTierParams.__type.tickSpacing\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"InitFeeTierParams.__type\"},{\"id\":461,\"kind\":1024,\"name\":\"defaultFeeRate\",\"url\":\"modules.html#InitFeeTierParams.__type.defaultFeeRate\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"InitFeeTierParams.__type\"},{\"id\":462,\"kind\":1024,\"name\":\"feeAuthority\",\"url\":\"modules.html#InitFeeTierParams.__type.feeAuthority\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"InitFeeTierParams.__type\"},{\"id\":463,\"kind\":1024,\"name\":\"funder\",\"url\":\"modules.html#InitFeeTierParams.__type.funder\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"InitFeeTierParams.__type\"},{\"id\":464,\"kind\":4194304,\"name\":\"InitializeRewardParams\",\"url\":\"modules.html#InitializeRewardParams\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":465,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#InitializeRewardParams.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"InitializeRewardParams\"},{\"id\":466,\"kind\":1024,\"name\":\"whirlpool\",\"url\":\"modules.html#InitializeRewardParams.__type.whirlpool\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"InitializeRewardParams.__type\"},{\"id\":467,\"kind\":1024,\"name\":\"rewardIndex\",\"url\":\"modules.html#InitializeRewardParams.__type.rewardIndex\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"InitializeRewardParams.__type\"},{\"id\":468,\"kind\":1024,\"name\":\"rewardMint\",\"url\":\"modules.html#InitializeRewardParams.__type.rewardMint\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"InitializeRewardParams.__type\"},{\"id\":469,\"kind\":1024,\"name\":\"rewardVaultKeypair\",\"url\":\"modules.html#InitializeRewardParams.__type.rewardVaultKeypair\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"InitializeRewardParams.__type\"},{\"id\":470,\"kind\":1024,\"name\":\"rewardAuthority\",\"url\":\"modules.html#InitializeRewardParams.__type.rewardAuthority\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"InitializeRewardParams.__type\"},{\"id\":471,\"kind\":1024,\"name\":\"funder\",\"url\":\"modules.html#InitializeRewardParams.__type.funder\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"InitializeRewardParams.__type\"},{\"id\":472,\"kind\":4194304,\"name\":\"InitPoolParams\",\"url\":\"modules.html#InitPoolParams\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":473,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#InitPoolParams.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"InitPoolParams\"},{\"id\":474,\"kind\":1024,\"name\":\"initSqrtPrice\",\"url\":\"modules.html#InitPoolParams.__type.initSqrtPrice\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"InitPoolParams.__type\"},{\"id\":475,\"kind\":1024,\"name\":\"whirlpoolsConfig\",\"url\":\"modules.html#InitPoolParams.__type.whirlpoolsConfig\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"InitPoolParams.__type\"},{\"id\":476,\"kind\":1024,\"name\":\"whirlpoolPda\",\"url\":\"modules.html#InitPoolParams.__type.whirlpoolPda\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"InitPoolParams.__type\"},{\"id\":477,\"kind\":1024,\"name\":\"tokenMintA\",\"url\":\"modules.html#InitPoolParams.__type.tokenMintA\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"InitPoolParams.__type\"},{\"id\":478,\"kind\":1024,\"name\":\"tokenMintB\",\"url\":\"modules.html#InitPoolParams.__type.tokenMintB\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"InitPoolParams.__type\"},{\"id\":479,\"kind\":1024,\"name\":\"tokenVaultAKeypair\",\"url\":\"modules.html#InitPoolParams.__type.tokenVaultAKeypair\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"InitPoolParams.__type\"},{\"id\":480,\"kind\":1024,\"name\":\"tokenVaultBKeypair\",\"url\":\"modules.html#InitPoolParams.__type.tokenVaultBKeypair\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"InitPoolParams.__type\"},{\"id\":481,\"kind\":1024,\"name\":\"feeTierKey\",\"url\":\"modules.html#InitPoolParams.__type.feeTierKey\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"InitPoolParams.__type\"},{\"id\":482,\"kind\":1024,\"name\":\"tickSpacing\",\"url\":\"modules.html#InitPoolParams.__type.tickSpacing\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"InitPoolParams.__type\"},{\"id\":483,\"kind\":1024,\"name\":\"funder\",\"url\":\"modules.html#InitPoolParams.__type.funder\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"InitPoolParams.__type\"},{\"id\":484,\"kind\":4194304,\"name\":\"InitTickArrayParams\",\"url\":\"modules.html#InitTickArrayParams\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":485,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#InitTickArrayParams.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"InitTickArrayParams\"},{\"id\":486,\"kind\":1024,\"name\":\"whirlpool\",\"url\":\"modules.html#InitTickArrayParams.__type.whirlpool\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"InitTickArrayParams.__type\"},{\"id\":487,\"kind\":1024,\"name\":\"tickArrayPda\",\"url\":\"modules.html#InitTickArrayParams.__type.tickArrayPda\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"InitTickArrayParams.__type\"},{\"id\":488,\"kind\":1024,\"name\":\"startTick\",\"url\":\"modules.html#InitTickArrayParams.__type.startTick\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"InitTickArrayParams.__type\"},{\"id\":489,\"kind\":1024,\"name\":\"funder\",\"url\":\"modules.html#InitTickArrayParams.__type.funder\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"InitTickArrayParams.__type\"},{\"id\":490,\"kind\":4194304,\"name\":\"OpenPositionParams\",\"url\":\"modules.html#OpenPositionParams\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":491,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#OpenPositionParams.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"OpenPositionParams\"},{\"id\":492,\"kind\":1024,\"name\":\"whirlpool\",\"url\":\"modules.html#OpenPositionParams.__type.whirlpool\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"OpenPositionParams.__type\"},{\"id\":493,\"kind\":1024,\"name\":\"owner\",\"url\":\"modules.html#OpenPositionParams.__type.owner\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"OpenPositionParams.__type\"},{\"id\":494,\"kind\":1024,\"name\":\"positionPda\",\"url\":\"modules.html#OpenPositionParams.__type.positionPda\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"OpenPositionParams.__type\"},{\"id\":495,\"kind\":1024,\"name\":\"positionMintAddress\",\"url\":\"modules.html#OpenPositionParams.__type.positionMintAddress\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"OpenPositionParams.__type\"},{\"id\":496,\"kind\":1024,\"name\":\"positionTokenAccount\",\"url\":\"modules.html#OpenPositionParams.__type.positionTokenAccount\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"OpenPositionParams.__type\"},{\"id\":497,\"kind\":1024,\"name\":\"tickLowerIndex\",\"url\":\"modules.html#OpenPositionParams.__type.tickLowerIndex\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"OpenPositionParams.__type\"},{\"id\":498,\"kind\":1024,\"name\":\"tickUpperIndex\",\"url\":\"modules.html#OpenPositionParams.__type.tickUpperIndex\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"OpenPositionParams.__type\"},{\"id\":499,\"kind\":1024,\"name\":\"funder\",\"url\":\"modules.html#OpenPositionParams.__type.funder\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"OpenPositionParams.__type\"},{\"id\":500,\"kind\":4194304,\"name\":\"SetCollectProtocolFeesAuthorityParams\",\"url\":\"modules.html#SetCollectProtocolFeesAuthorityParams\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":501,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#SetCollectProtocolFeesAuthorityParams.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"SetCollectProtocolFeesAuthorityParams\"},{\"id\":502,\"kind\":1024,\"name\":\"whirlpoolsConfig\",\"url\":\"modules.html#SetCollectProtocolFeesAuthorityParams.__type.whirlpoolsConfig\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SetCollectProtocolFeesAuthorityParams.__type\"},{\"id\":503,\"kind\":1024,\"name\":\"collectProtocolFeesAuthority\",\"url\":\"modules.html#SetCollectProtocolFeesAuthorityParams.__type.collectProtocolFeesAuthority\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SetCollectProtocolFeesAuthorityParams.__type\"},{\"id\":504,\"kind\":1024,\"name\":\"newCollectProtocolFeesAuthority\",\"url\":\"modules.html#SetCollectProtocolFeesAuthorityParams.__type.newCollectProtocolFeesAuthority\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SetCollectProtocolFeesAuthorityParams.__type\"},{\"id\":505,\"kind\":4194304,\"name\":\"SetDefaultFeeRateParams\",\"url\":\"modules.html#SetDefaultFeeRateParams\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":506,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#SetDefaultFeeRateParams.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"SetDefaultFeeRateParams\"},{\"id\":507,\"kind\":1024,\"name\":\"whirlpoolsConfig\",\"url\":\"modules.html#SetDefaultFeeRateParams.__type.whirlpoolsConfig\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SetDefaultFeeRateParams.__type\"},{\"id\":508,\"kind\":1024,\"name\":\"feeAuthority\",\"url\":\"modules.html#SetDefaultFeeRateParams.__type.feeAuthority\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SetDefaultFeeRateParams.__type\"},{\"id\":509,\"kind\":1024,\"name\":\"tickSpacing\",\"url\":\"modules.html#SetDefaultFeeRateParams.__type.tickSpacing\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SetDefaultFeeRateParams.__type\"},{\"id\":510,\"kind\":1024,\"name\":\"defaultFeeRate\",\"url\":\"modules.html#SetDefaultFeeRateParams.__type.defaultFeeRate\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SetDefaultFeeRateParams.__type\"},{\"id\":511,\"kind\":4194304,\"name\":\"SetDefaultProtocolFeeRateParams\",\"url\":\"modules.html#SetDefaultProtocolFeeRateParams\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":512,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#SetDefaultProtocolFeeRateParams.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"SetDefaultProtocolFeeRateParams\"},{\"id\":513,\"kind\":1024,\"name\":\"whirlpoolsConfig\",\"url\":\"modules.html#SetDefaultProtocolFeeRateParams.__type.whirlpoolsConfig\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SetDefaultProtocolFeeRateParams.__type\"},{\"id\":514,\"kind\":1024,\"name\":\"feeAuthority\",\"url\":\"modules.html#SetDefaultProtocolFeeRateParams.__type.feeAuthority\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SetDefaultProtocolFeeRateParams.__type\"},{\"id\":515,\"kind\":1024,\"name\":\"defaultProtocolFeeRate\",\"url\":\"modules.html#SetDefaultProtocolFeeRateParams.__type.defaultProtocolFeeRate\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SetDefaultProtocolFeeRateParams.__type\"},{\"id\":516,\"kind\":4194304,\"name\":\"SetFeeAuthorityParams\",\"url\":\"modules.html#SetFeeAuthorityParams\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":517,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#SetFeeAuthorityParams.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"SetFeeAuthorityParams\"},{\"id\":518,\"kind\":1024,\"name\":\"whirlpoolsConfig\",\"url\":\"modules.html#SetFeeAuthorityParams.__type.whirlpoolsConfig\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SetFeeAuthorityParams.__type\"},{\"id\":519,\"kind\":1024,\"name\":\"feeAuthority\",\"url\":\"modules.html#SetFeeAuthorityParams.__type.feeAuthority\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SetFeeAuthorityParams.__type\"},{\"id\":520,\"kind\":1024,\"name\":\"newFeeAuthority\",\"url\":\"modules.html#SetFeeAuthorityParams.__type.newFeeAuthority\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SetFeeAuthorityParams.__type\"},{\"id\":521,\"kind\":4194304,\"name\":\"SetFeeRateParams\",\"url\":\"modules.html#SetFeeRateParams\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":522,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#SetFeeRateParams.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"SetFeeRateParams\"},{\"id\":523,\"kind\":1024,\"name\":\"whirlpool\",\"url\":\"modules.html#SetFeeRateParams.__type.whirlpool\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SetFeeRateParams.__type\"},{\"id\":524,\"kind\":1024,\"name\":\"whirlpoolsConfig\",\"url\":\"modules.html#SetFeeRateParams.__type.whirlpoolsConfig\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SetFeeRateParams.__type\"},{\"id\":525,\"kind\":1024,\"name\":\"feeAuthority\",\"url\":\"modules.html#SetFeeRateParams.__type.feeAuthority\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SetFeeRateParams.__type\"},{\"id\":526,\"kind\":1024,\"name\":\"feeRate\",\"url\":\"modules.html#SetFeeRateParams.__type.feeRate\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SetFeeRateParams.__type\"},{\"id\":527,\"kind\":4194304,\"name\":\"SetProtocolFeeRateParams\",\"url\":\"modules.html#SetProtocolFeeRateParams\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":528,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#SetProtocolFeeRateParams.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"SetProtocolFeeRateParams\"},{\"id\":529,\"kind\":1024,\"name\":\"whirlpool\",\"url\":\"modules.html#SetProtocolFeeRateParams.__type.whirlpool\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SetProtocolFeeRateParams.__type\"},{\"id\":530,\"kind\":1024,\"name\":\"whirlpoolsConfig\",\"url\":\"modules.html#SetProtocolFeeRateParams.__type.whirlpoolsConfig\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SetProtocolFeeRateParams.__type\"},{\"id\":531,\"kind\":1024,\"name\":\"feeAuthority\",\"url\":\"modules.html#SetProtocolFeeRateParams.__type.feeAuthority\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SetProtocolFeeRateParams.__type\"},{\"id\":532,\"kind\":1024,\"name\":\"protocolFeeRate\",\"url\":\"modules.html#SetProtocolFeeRateParams.__type.protocolFeeRate\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SetProtocolFeeRateParams.__type\"},{\"id\":533,\"kind\":4194304,\"name\":\"SetRewardAuthorityBySuperAuthorityParams\",\"url\":\"modules.html#SetRewardAuthorityBySuperAuthorityParams\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":534,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#SetRewardAuthorityBySuperAuthorityParams.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"SetRewardAuthorityBySuperAuthorityParams\"},{\"id\":535,\"kind\":1024,\"name\":\"whirlpool\",\"url\":\"modules.html#SetRewardAuthorityBySuperAuthorityParams.__type.whirlpool\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SetRewardAuthorityBySuperAuthorityParams.__type\"},{\"id\":536,\"kind\":1024,\"name\":\"whirlpoolsConfig\",\"url\":\"modules.html#SetRewardAuthorityBySuperAuthorityParams.__type.whirlpoolsConfig\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SetRewardAuthorityBySuperAuthorityParams.__type\"},{\"id\":537,\"kind\":1024,\"name\":\"rewardIndex\",\"url\":\"modules.html#SetRewardAuthorityBySuperAuthorityParams.__type.rewardIndex\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SetRewardAuthorityBySuperAuthorityParams.__type\"},{\"id\":538,\"kind\":1024,\"name\":\"rewardEmissionsSuperAuthority\",\"url\":\"modules.html#SetRewardAuthorityBySuperAuthorityParams.__type.rewardEmissionsSuperAuthority\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SetRewardAuthorityBySuperAuthorityParams.__type\"},{\"id\":539,\"kind\":1024,\"name\":\"newRewardAuthority\",\"url\":\"modules.html#SetRewardAuthorityBySuperAuthorityParams.__type.newRewardAuthority\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SetRewardAuthorityBySuperAuthorityParams.__type\"},{\"id\":540,\"kind\":4194304,\"name\":\"SetRewardAuthorityParams\",\"url\":\"modules.html#SetRewardAuthorityParams\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":541,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#SetRewardAuthorityParams.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"SetRewardAuthorityParams\"},{\"id\":542,\"kind\":1024,\"name\":\"whirlpool\",\"url\":\"modules.html#SetRewardAuthorityParams.__type.whirlpool\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SetRewardAuthorityParams.__type\"},{\"id\":543,\"kind\":1024,\"name\":\"rewardIndex\",\"url\":\"modules.html#SetRewardAuthorityParams.__type.rewardIndex\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SetRewardAuthorityParams.__type\"},{\"id\":544,\"kind\":1024,\"name\":\"rewardAuthority\",\"url\":\"modules.html#SetRewardAuthorityParams.__type.rewardAuthority\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SetRewardAuthorityParams.__type\"},{\"id\":545,\"kind\":1024,\"name\":\"newRewardAuthority\",\"url\":\"modules.html#SetRewardAuthorityParams.__type.newRewardAuthority\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SetRewardAuthorityParams.__type\"},{\"id\":546,\"kind\":4194304,\"name\":\"SetRewardEmissionsParams\",\"url\":\"modules.html#SetRewardEmissionsParams\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":547,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#SetRewardEmissionsParams.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"SetRewardEmissionsParams\"},{\"id\":548,\"kind\":1024,\"name\":\"whirlpool\",\"url\":\"modules.html#SetRewardEmissionsParams.__type.whirlpool\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SetRewardEmissionsParams.__type\"},{\"id\":549,\"kind\":1024,\"name\":\"rewardIndex\",\"url\":\"modules.html#SetRewardEmissionsParams.__type.rewardIndex\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SetRewardEmissionsParams.__type\"},{\"id\":550,\"kind\":1024,\"name\":\"rewardVaultKey\",\"url\":\"modules.html#SetRewardEmissionsParams.__type.rewardVaultKey\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SetRewardEmissionsParams.__type\"},{\"id\":551,\"kind\":1024,\"name\":\"rewardAuthority\",\"url\":\"modules.html#SetRewardEmissionsParams.__type.rewardAuthority\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SetRewardEmissionsParams.__type\"},{\"id\":552,\"kind\":1024,\"name\":\"emissionsPerSecondX64\",\"url\":\"modules.html#SetRewardEmissionsParams.__type.emissionsPerSecondX64\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SetRewardEmissionsParams.__type\"},{\"id\":553,\"kind\":4194304,\"name\":\"SetRewardEmissionsSuperAuthorityParams\",\"url\":\"modules.html#SetRewardEmissionsSuperAuthorityParams\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":554,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#SetRewardEmissionsSuperAuthorityParams.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"SetRewardEmissionsSuperAuthorityParams\"},{\"id\":555,\"kind\":1024,\"name\":\"whirlpoolsConfig\",\"url\":\"modules.html#SetRewardEmissionsSuperAuthorityParams.__type.whirlpoolsConfig\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SetRewardEmissionsSuperAuthorityParams.__type\"},{\"id\":556,\"kind\":1024,\"name\":\"rewardEmissionsSuperAuthority\",\"url\":\"modules.html#SetRewardEmissionsSuperAuthorityParams.__type.rewardEmissionsSuperAuthority\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SetRewardEmissionsSuperAuthorityParams.__type\"},{\"id\":557,\"kind\":1024,\"name\":\"newRewardEmissionsSuperAuthority\",\"url\":\"modules.html#SetRewardEmissionsSuperAuthorityParams.__type.newRewardEmissionsSuperAuthority\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SetRewardEmissionsSuperAuthorityParams.__type\"},{\"id\":558,\"kind\":4194304,\"name\":\"SwapInput\",\"url\":\"modules.html#SwapInput\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":559,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#SwapInput.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"SwapInput\"},{\"id\":560,\"kind\":1024,\"name\":\"amount\",\"url\":\"modules.html#SwapInput.__type.amount\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SwapInput.__type\"},{\"id\":561,\"kind\":1024,\"name\":\"otherAmountThreshold\",\"url\":\"modules.html#SwapInput.__type.otherAmountThreshold\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SwapInput.__type\"},{\"id\":562,\"kind\":1024,\"name\":\"sqrtPriceLimit\",\"url\":\"modules.html#SwapInput.__type.sqrtPriceLimit\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SwapInput.__type\"},{\"id\":563,\"kind\":1024,\"name\":\"amountSpecifiedIsInput\",\"url\":\"modules.html#SwapInput.__type.amountSpecifiedIsInput\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SwapInput.__type\"},{\"id\":564,\"kind\":1024,\"name\":\"aToB\",\"url\":\"modules.html#SwapInput.__type.aToB\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SwapInput.__type\"},{\"id\":565,\"kind\":1024,\"name\":\"tickArray0\",\"url\":\"modules.html#SwapInput.__type.tickArray0\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SwapInput.__type\"},{\"id\":566,\"kind\":1024,\"name\":\"tickArray1\",\"url\":\"modules.html#SwapInput.__type.tickArray1\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SwapInput.__type\"},{\"id\":567,\"kind\":1024,\"name\":\"tickArray2\",\"url\":\"modules.html#SwapInput.__type.tickArray2\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SwapInput.__type\"},{\"id\":568,\"kind\":4194304,\"name\":\"SwapParams\",\"url\":\"modules.html#SwapParams\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":569,\"kind\":4194304,\"name\":\"UpdateFeesAndRewardsParams\",\"url\":\"modules.html#UpdateFeesAndRewardsParams\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":570,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#UpdateFeesAndRewardsParams.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"UpdateFeesAndRewardsParams\"},{\"id\":571,\"kind\":1024,\"name\":\"whirlpool\",\"url\":\"modules.html#UpdateFeesAndRewardsParams.__type.whirlpool\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"UpdateFeesAndRewardsParams.__type\"},{\"id\":572,\"kind\":1024,\"name\":\"position\",\"url\":\"modules.html#UpdateFeesAndRewardsParams.__type.position\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"UpdateFeesAndRewardsParams.__type\"},{\"id\":573,\"kind\":1024,\"name\":\"tickArrayLower\",\"url\":\"modules.html#UpdateFeesAndRewardsParams.__type.tickArrayLower\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"UpdateFeesAndRewardsParams.__type\"},{\"id\":574,\"kind\":1024,\"name\":\"tickArrayUpper\",\"url\":\"modules.html#UpdateFeesAndRewardsParams.__type.tickArrayUpper\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"UpdateFeesAndRewardsParams.__type\"},{\"id\":575,\"kind\":4194304,\"name\":\"InitializePositionBundleParams\",\"url\":\"modules.html#InitializePositionBundleParams\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":576,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#InitializePositionBundleParams.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"InitializePositionBundleParams\"},{\"id\":577,\"kind\":1024,\"name\":\"owner\",\"url\":\"modules.html#InitializePositionBundleParams.__type.owner\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"InitializePositionBundleParams.__type\"},{\"id\":578,\"kind\":1024,\"name\":\"positionBundlePda\",\"url\":\"modules.html#InitializePositionBundleParams.__type.positionBundlePda\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"InitializePositionBundleParams.__type\"},{\"id\":579,\"kind\":1024,\"name\":\"positionBundleMintKeypair\",\"url\":\"modules.html#InitializePositionBundleParams.__type.positionBundleMintKeypair\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"InitializePositionBundleParams.__type\"},{\"id\":580,\"kind\":1024,\"name\":\"positionBundleTokenAccount\",\"url\":\"modules.html#InitializePositionBundleParams.__type.positionBundleTokenAccount\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"InitializePositionBundleParams.__type\"},{\"id\":581,\"kind\":1024,\"name\":\"funder\",\"url\":\"modules.html#InitializePositionBundleParams.__type.funder\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"InitializePositionBundleParams.__type\"},{\"id\":582,\"kind\":4194304,\"name\":\"DeletePositionBundleParams\",\"url\":\"modules.html#DeletePositionBundleParams\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":583,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#DeletePositionBundleParams.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"DeletePositionBundleParams\"},{\"id\":584,\"kind\":1024,\"name\":\"owner\",\"url\":\"modules.html#DeletePositionBundleParams.__type.owner\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"DeletePositionBundleParams.__type\"},{\"id\":585,\"kind\":1024,\"name\":\"positionBundle\",\"url\":\"modules.html#DeletePositionBundleParams.__type.positionBundle\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"DeletePositionBundleParams.__type\"},{\"id\":586,\"kind\":1024,\"name\":\"positionBundleMint\",\"url\":\"modules.html#DeletePositionBundleParams.__type.positionBundleMint\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"DeletePositionBundleParams.__type\"},{\"id\":587,\"kind\":1024,\"name\":\"positionBundleTokenAccount\",\"url\":\"modules.html#DeletePositionBundleParams.__type.positionBundleTokenAccount\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"DeletePositionBundleParams.__type\"},{\"id\":588,\"kind\":1024,\"name\":\"receiver\",\"url\":\"modules.html#DeletePositionBundleParams.__type.receiver\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"DeletePositionBundleParams.__type\"},{\"id\":589,\"kind\":4194304,\"name\":\"OpenBundledPositionParams\",\"url\":\"modules.html#OpenBundledPositionParams\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":590,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#OpenBundledPositionParams.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"OpenBundledPositionParams\"},{\"id\":591,\"kind\":1024,\"name\":\"whirlpool\",\"url\":\"modules.html#OpenBundledPositionParams.__type.whirlpool\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"OpenBundledPositionParams.__type\"},{\"id\":592,\"kind\":1024,\"name\":\"bundledPositionPda\",\"url\":\"modules.html#OpenBundledPositionParams.__type.bundledPositionPda\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"OpenBundledPositionParams.__type\"},{\"id\":593,\"kind\":1024,\"name\":\"positionBundle\",\"url\":\"modules.html#OpenBundledPositionParams.__type.positionBundle\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"OpenBundledPositionParams.__type\"},{\"id\":594,\"kind\":1024,\"name\":\"positionBundleTokenAccount\",\"url\":\"modules.html#OpenBundledPositionParams.__type.positionBundleTokenAccount\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"OpenBundledPositionParams.__type\"},{\"id\":595,\"kind\":1024,\"name\":\"positionBundleAuthority\",\"url\":\"modules.html#OpenBundledPositionParams.__type.positionBundleAuthority\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"OpenBundledPositionParams.__type\"},{\"id\":596,\"kind\":1024,\"name\":\"bundleIndex\",\"url\":\"modules.html#OpenBundledPositionParams.__type.bundleIndex\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"OpenBundledPositionParams.__type\"},{\"id\":597,\"kind\":1024,\"name\":\"tickLowerIndex\",\"url\":\"modules.html#OpenBundledPositionParams.__type.tickLowerIndex\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"OpenBundledPositionParams.__type\"},{\"id\":598,\"kind\":1024,\"name\":\"tickUpperIndex\",\"url\":\"modules.html#OpenBundledPositionParams.__type.tickUpperIndex\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"OpenBundledPositionParams.__type\"},{\"id\":599,\"kind\":1024,\"name\":\"funder\",\"url\":\"modules.html#OpenBundledPositionParams.__type.funder\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"OpenBundledPositionParams.__type\"},{\"id\":600,\"kind\":4194304,\"name\":\"CloseBundledPositionParams\",\"url\":\"modules.html#CloseBundledPositionParams\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":601,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#CloseBundledPositionParams.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"CloseBundledPositionParams\"},{\"id\":602,\"kind\":1024,\"name\":\"bundledPosition\",\"url\":\"modules.html#CloseBundledPositionParams.__type.bundledPosition\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"CloseBundledPositionParams.__type\"},{\"id\":603,\"kind\":1024,\"name\":\"positionBundle\",\"url\":\"modules.html#CloseBundledPositionParams.__type.positionBundle\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"CloseBundledPositionParams.__type\"},{\"id\":604,\"kind\":1024,\"name\":\"positionBundleTokenAccount\",\"url\":\"modules.html#CloseBundledPositionParams.__type.positionBundleTokenAccount\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"CloseBundledPositionParams.__type\"},{\"id\":605,\"kind\":1024,\"name\":\"positionBundleAuthority\",\"url\":\"modules.html#CloseBundledPositionParams.__type.positionBundleAuthority\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"CloseBundledPositionParams.__type\"},{\"id\":606,\"kind\":1024,\"name\":\"bundleIndex\",\"url\":\"modules.html#CloseBundledPositionParams.__type.bundleIndex\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"CloseBundledPositionParams.__type\"},{\"id\":607,\"kind\":1024,\"name\":\"receiver\",\"url\":\"modules.html#CloseBundledPositionParams.__type.receiver\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"CloseBundledPositionParams.__type\"},{\"id\":608,\"kind\":4194304,\"name\":\"CollectAllParams\",\"url\":\"modules.html#CollectAllParams\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":609,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#CollectAllParams.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"CollectAllParams\"},{\"id\":610,\"kind\":1024,\"name\":\"receiver\",\"url\":\"modules.html#CollectAllParams.__type.receiver\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"CollectAllParams.__type\"},{\"id\":611,\"kind\":1024,\"name\":\"positionOwner\",\"url\":\"modules.html#CollectAllParams.__type.positionOwner\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"CollectAllParams.__type\"},{\"id\":612,\"kind\":1024,\"name\":\"positionAuthority\",\"url\":\"modules.html#CollectAllParams.__type.positionAuthority\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"CollectAllParams.__type\"},{\"id\":613,\"kind\":1024,\"name\":\"payer\",\"url\":\"modules.html#CollectAllParams.__type.payer\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"CollectAllParams.__type\"},{\"id\":614,\"kind\":4194304,\"name\":\"CollectAllPositionAddressParams\",\"url\":\"modules.html#CollectAllPositionAddressParams\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":615,\"kind\":4194304,\"name\":\"CollectAllPositionParams\",\"url\":\"modules.html#CollectAllPositionParams\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":616,\"kind\":256,\"name\":\"PoolTokenPair\",\"url\":\"interfaces/PoolTokenPair.html\",\"classes\":\"tsd-kind-interface\"},{\"id\":617,\"kind\":1024,\"name\":\"address\",\"url\":\"interfaces/PoolTokenPair.html#address\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"PoolTokenPair\"},{\"id\":618,\"kind\":1024,\"name\":\"tokenMintA\",\"url\":\"interfaces/PoolTokenPair.html#tokenMintA\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"PoolTokenPair\"},{\"id\":619,\"kind\":1024,\"name\":\"tokenMintB\",\"url\":\"interfaces/PoolTokenPair.html#tokenMintB\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"PoolTokenPair\"},{\"id\":620,\"kind\":4194304,\"name\":\"PathSearchEntries\",\"url\":\"modules.html#PathSearchEntries\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":621,\"kind\":4194304,\"name\":\"Path\",\"url\":\"modules.html#Path\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":622,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#Path.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"Path\"},{\"id\":623,\"kind\":1024,\"name\":\"startTokenMint\",\"url\":\"modules.html#Path.__type.startTokenMint\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"Path.__type\"},{\"id\":624,\"kind\":1024,\"name\":\"endTokenMint\",\"url\":\"modules.html#Path.__type.endTokenMint\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"Path.__type\"},{\"id\":625,\"kind\":1024,\"name\":\"edges\",\"url\":\"modules.html#Path.__type.edges\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"Path.__type\"},{\"id\":626,\"kind\":4194304,\"name\":\"Edge\",\"url\":\"modules.html#Edge\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":627,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#Edge.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"Edge\"},{\"id\":628,\"kind\":1024,\"name\":\"poolAddress\",\"url\":\"modules.html#Edge.__type.poolAddress\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"Edge.__type\"},{\"id\":629,\"kind\":4194304,\"name\":\"PathSearchOptions\",\"url\":\"modules.html#PathSearchOptions\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":630,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#PathSearchOptions.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"PathSearchOptions\"},{\"id\":631,\"kind\":1024,\"name\":\"intermediateTokens\",\"url\":\"modules.html#PathSearchOptions.__type.intermediateTokens\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"PathSearchOptions.__type\"},{\"id\":632,\"kind\":4194304,\"name\":\"PoolGraph\",\"url\":\"modules.html#PoolGraph\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":633,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#PoolGraph.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"PoolGraph\"},{\"id\":634,\"kind\":2048,\"name\":\"getPath\",\"url\":\"modules.html#PoolGraph.__type.getPath\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"PoolGraph.__type\"},{\"id\":635,\"kind\":2048,\"name\":\"getPathsForPairs\",\"url\":\"modules.html#PoolGraph.__type.getPathsForPairs\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"PoolGraph.__type\"},{\"id\":636,\"kind\":2048,\"name\":\"getAllPaths\",\"url\":\"modules.html#PoolGraph.__type.getAllPaths\",\"classes\":\"tsd-kind-method tsd-parent-kind-type-literal\",\"parent\":\"PoolGraph.__type\"},{\"id\":637,\"kind\":128,\"name\":\"PoolGraphBuilder\",\"url\":\"classes/PoolGraphBuilder.html\",\"classes\":\"tsd-kind-class\"},{\"id\":638,\"kind\":2048,\"name\":\"buildPoolGraphWithFetch\",\"url\":\"classes/PoolGraphBuilder.html#buildPoolGraphWithFetch\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"PoolGraphBuilder\"},{\"id\":639,\"kind\":2048,\"name\":\"buildPoolGraph\",\"url\":\"classes/PoolGraphBuilder.html#buildPoolGraph\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"PoolGraphBuilder\"},{\"id\":640,\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/PoolGraphBuilder.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"PoolGraphBuilder\"},{\"id\":641,\"kind\":128,\"name\":\"PoolGraphUtils\",\"url\":\"classes/PoolGraphUtils.html\",\"classes\":\"tsd-kind-class\"},{\"id\":642,\"kind\":1024,\"name\":\"PATH_ID_DELIMITER\",\"url\":\"classes/PoolGraphUtils.html#PATH_ID_DELIMITER\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-static\",\"parent\":\"PoolGraphUtils\"},{\"id\":643,\"kind\":2048,\"name\":\"getSearchPathId\",\"url\":\"classes/PoolGraphUtils.html#getSearchPathId\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"PoolGraphUtils\"},{\"id\":644,\"kind\":2048,\"name\":\"deconstructPathId\",\"url\":\"classes/PoolGraphUtils.html#deconstructPathId\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"PoolGraphUtils\"},{\"id\":645,\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/PoolGraphUtils.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"PoolGraphUtils\"},{\"id\":646,\"kind\":64,\"name\":\"toTx\",\"url\":\"modules.html#toTx\",\"classes\":\"tsd-kind-function\"},{\"id\":647,\"kind\":128,\"name\":\"PDAUtil\",\"url\":\"classes/PDAUtil.html\",\"classes\":\"tsd-kind-class\"},{\"id\":648,\"kind\":2048,\"name\":\"getWhirlpool\",\"url\":\"classes/PDAUtil.html#getWhirlpool\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"PDAUtil\"},{\"id\":649,\"kind\":2048,\"name\":\"getPosition\",\"url\":\"classes/PDAUtil.html#getPosition\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"PDAUtil\"},{\"id\":650,\"kind\":2048,\"name\":\"getPositionMetadata\",\"url\":\"classes/PDAUtil.html#getPositionMetadata\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"PDAUtil\"},{\"id\":651,\"kind\":2048,\"name\":\"getTickArray\",\"url\":\"classes/PDAUtil.html#getTickArray\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"PDAUtil\"},{\"id\":652,\"kind\":2048,\"name\":\"getTickArrayFromTickIndex\",\"url\":\"classes/PDAUtil.html#getTickArrayFromTickIndex\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"PDAUtil\"},{\"id\":653,\"kind\":2048,\"name\":\"getTickArrayFromSqrtPrice\",\"url\":\"classes/PDAUtil.html#getTickArrayFromSqrtPrice\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"PDAUtil\"},{\"id\":654,\"kind\":2048,\"name\":\"getFeeTier\",\"url\":\"classes/PDAUtil.html#getFeeTier\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"PDAUtil\"},{\"id\":655,\"kind\":2048,\"name\":\"getOracle\",\"url\":\"classes/PDAUtil.html#getOracle\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"PDAUtil\"},{\"id\":656,\"kind\":2048,\"name\":\"getBundledPosition\",\"url\":\"classes/PDAUtil.html#getBundledPosition\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"PDAUtil\"},{\"id\":657,\"kind\":2048,\"name\":\"getPositionBundle\",\"url\":\"classes/PDAUtil.html#getPositionBundle\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"PDAUtil\"},{\"id\":658,\"kind\":2048,\"name\":\"getPositionBundleMetadata\",\"url\":\"classes/PDAUtil.html#getPositionBundleMetadata\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"PDAUtil\"},{\"id\":659,\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/PDAUtil.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"PDAUtil\"},{\"id\":660,\"kind\":64,\"name\":\"toTokenAmount\",\"url\":\"modules.html#toTokenAmount\",\"classes\":\"tsd-kind-function\"},{\"id\":661,\"kind\":128,\"name\":\"PoolUtil\",\"url\":\"classes/PoolUtil.html\",\"classes\":\"tsd-kind-class\"},{\"id\":662,\"kind\":2048,\"name\":\"isRewardInitialized\",\"url\":\"classes/PoolUtil.html#isRewardInitialized\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"PoolUtil\"},{\"id\":663,\"kind\":2048,\"name\":\"getTokenType\",\"url\":\"classes/PoolUtil.html#getTokenType\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"PoolUtil\"},{\"id\":664,\"kind\":2048,\"name\":\"getFeeRate\",\"url\":\"classes/PoolUtil.html#getFeeRate\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"PoolUtil\"},{\"id\":665,\"kind\":2048,\"name\":\"getProtocolFeeRate\",\"url\":\"classes/PoolUtil.html#getProtocolFeeRate\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"PoolUtil\"},{\"id\":666,\"kind\":2048,\"name\":\"orderMints\",\"url\":\"classes/PoolUtil.html#orderMints\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"PoolUtil\"},{\"id\":667,\"kind\":2048,\"name\":\"compareMints\",\"url\":\"classes/PoolUtil.html#compareMints\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"PoolUtil\"},{\"id\":668,\"kind\":2048,\"name\":\"getTokenAmountsFromLiquidity\",\"url\":\"classes/PoolUtil.html#getTokenAmountsFromLiquidity\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"PoolUtil\"},{\"id\":669,\"kind\":2048,\"name\":\"estimateLiquidityFromTokenAmounts\",\"url\":\"classes/PoolUtil.html#estimateLiquidityFromTokenAmounts\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"PoolUtil\"},{\"id\":670,\"kind\":2048,\"name\":\"toBaseQuoteOrder\",\"url\":\"classes/PoolUtil.html#toBaseQuoteOrder\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"PoolUtil\"},{\"id\":671,\"kind\":4194304,\"name\":\"TokenAmounts\",\"url\":\"modules.html#TokenAmounts\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":672,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#TokenAmounts.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"TokenAmounts\"},{\"id\":673,\"kind\":1024,\"name\":\"tokenA\",\"url\":\"modules.html#TokenAmounts.__type.tokenA\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"TokenAmounts.__type\"},{\"id\":674,\"kind\":1024,\"name\":\"tokenB\",\"url\":\"modules.html#TokenAmounts.__type.tokenB\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"TokenAmounts.__type\"},{\"id\":675,\"kind\":128,\"name\":\"PositionBundleUtil\",\"url\":\"classes/PositionBundleUtil.html\",\"classes\":\"tsd-kind-class\"},{\"id\":676,\"kind\":2048,\"name\":\"checkBundleIndexInBounds\",\"url\":\"classes/PositionBundleUtil.html#checkBundleIndexInBounds\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"PositionBundleUtil\"},{\"id\":677,\"kind\":2048,\"name\":\"isOccupied\",\"url\":\"classes/PositionBundleUtil.html#isOccupied\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"PositionBundleUtil\"},{\"id\":678,\"kind\":2048,\"name\":\"isUnoccupied\",\"url\":\"classes/PositionBundleUtil.html#isUnoccupied\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"PositionBundleUtil\"},{\"id\":679,\"kind\":2048,\"name\":\"isFull\",\"url\":\"classes/PositionBundleUtil.html#isFull\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"PositionBundleUtil\"},{\"id\":680,\"kind\":2048,\"name\":\"isEmpty\",\"url\":\"classes/PositionBundleUtil.html#isEmpty\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"PositionBundleUtil\"},{\"id\":681,\"kind\":2048,\"name\":\"getOccupiedBundleIndexes\",\"url\":\"classes/PositionBundleUtil.html#getOccupiedBundleIndexes\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"PositionBundleUtil\"},{\"id\":682,\"kind\":2048,\"name\":\"getUnoccupiedBundleIndexes\",\"url\":\"classes/PositionBundleUtil.html#getUnoccupiedBundleIndexes\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"PositionBundleUtil\"},{\"id\":683,\"kind\":2048,\"name\":\"findUnoccupiedBundleIndex\",\"url\":\"classes/PositionBundleUtil.html#findUnoccupiedBundleIndex\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"PositionBundleUtil\"},{\"id\":684,\"kind\":2048,\"name\":\"convertBitmapToArray\",\"url\":\"classes/PositionBundleUtil.html#convertBitmapToArray\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"PositionBundleUtil\"},{\"id\":685,\"kind\":128,\"name\":\"PriceMath\",\"url\":\"classes/PriceMath.html\",\"classes\":\"tsd-kind-class\"},{\"id\":686,\"kind\":2048,\"name\":\"priceToSqrtPriceX64\",\"url\":\"classes/PriceMath.html#priceToSqrtPriceX64\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"PriceMath\"},{\"id\":687,\"kind\":2048,\"name\":\"sqrtPriceX64ToPrice\",\"url\":\"classes/PriceMath.html#sqrtPriceX64ToPrice\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"PriceMath\"},{\"id\":688,\"kind\":2048,\"name\":\"tickIndexToSqrtPriceX64\",\"url\":\"classes/PriceMath.html#tickIndexToSqrtPriceX64\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"PriceMath\"},{\"id\":689,\"kind\":2048,\"name\":\"sqrtPriceX64ToTickIndex\",\"url\":\"classes/PriceMath.html#sqrtPriceX64ToTickIndex\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"PriceMath\"},{\"id\":690,\"kind\":2048,\"name\":\"tickIndexToPrice\",\"url\":\"classes/PriceMath.html#tickIndexToPrice\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"PriceMath\"},{\"id\":691,\"kind\":2048,\"name\":\"priceToTickIndex\",\"url\":\"classes/PriceMath.html#priceToTickIndex\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"PriceMath\"},{\"id\":692,\"kind\":2048,\"name\":\"priceToInitializableTickIndex\",\"url\":\"classes/PriceMath.html#priceToInitializableTickIndex\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"PriceMath\"},{\"id\":693,\"kind\":2048,\"name\":\"invertPrice\",\"url\":\"classes/PriceMath.html#invertPrice\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"PriceMath\"},{\"id\":694,\"kind\":2048,\"name\":\"invertSqrtPriceX64\",\"url\":\"classes/PriceMath.html#invertSqrtPriceX64\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"PriceMath\"},{\"id\":695,\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/PriceMath.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"PriceMath\"},{\"id\":696,\"kind\":256,\"name\":\"TickArrayRequest\",\"url\":\"interfaces/TickArrayRequest.html\",\"classes\":\"tsd-kind-interface\"},{\"id\":697,\"kind\":1024,\"name\":\"whirlpoolAddress\",\"url\":\"interfaces/TickArrayRequest.html#whirlpoolAddress\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"TickArrayRequest\"},{\"id\":698,\"kind\":1024,\"name\":\"aToB\",\"url\":\"interfaces/TickArrayRequest.html#aToB\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"TickArrayRequest\"},{\"id\":699,\"kind\":1024,\"name\":\"tickCurrentIndex\",\"url\":\"interfaces/TickArrayRequest.html#tickCurrentIndex\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"TickArrayRequest\"},{\"id\":700,\"kind\":1024,\"name\":\"tickSpacing\",\"url\":\"interfaces/TickArrayRequest.html#tickSpacing\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"TickArrayRequest\"},{\"id\":701,\"kind\":128,\"name\":\"SwapUtils\",\"url\":\"classes/SwapUtils.html\",\"classes\":\"tsd-kind-class\"},{\"id\":702,\"kind\":2048,\"name\":\"getDefaultSqrtPriceLimit\",\"url\":\"classes/SwapUtils.html#getDefaultSqrtPriceLimit\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"SwapUtils\"},{\"id\":703,\"kind\":2048,\"name\":\"getDefaultOtherAmountThreshold\",\"url\":\"classes/SwapUtils.html#getDefaultOtherAmountThreshold\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"SwapUtils\"},{\"id\":704,\"kind\":2048,\"name\":\"getSwapDirection\",\"url\":\"classes/SwapUtils.html#getSwapDirection\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"SwapUtils\"},{\"id\":705,\"kind\":2048,\"name\":\"getTickArrayPublicKeys\",\"url\":\"classes/SwapUtils.html#getTickArrayPublicKeys\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"SwapUtils\"},{\"id\":706,\"kind\":2048,\"name\":\"getTickArrays\",\"url\":\"classes/SwapUtils.html#getTickArrays\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"SwapUtils\"},{\"id\":707,\"kind\":2048,\"name\":\"getBatchTickArrays\",\"url\":\"classes/SwapUtils.html#getBatchTickArrays\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"SwapUtils\"},{\"id\":708,\"kind\":2048,\"name\":\"calculateSwapAmountsFromQuote\",\"url\":\"classes/SwapUtils.html#calculateSwapAmountsFromQuote\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"SwapUtils\"},{\"id\":709,\"kind\":2048,\"name\":\"getSwapParamsFromQuote\",\"url\":\"classes/SwapUtils.html#getSwapParamsFromQuote\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"SwapUtils\"},{\"id\":710,\"kind\":2048,\"name\":\"getSwapParamsFromQuoteKeys\",\"url\":\"classes/SwapUtils.html#getSwapParamsFromQuoteKeys\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"SwapUtils\"},{\"id\":711,\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/SwapUtils.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"SwapUtils\"},{\"id\":712,\"kind\":128,\"name\":\"TickUtil\",\"url\":\"classes/TickUtil.html\",\"classes\":\"tsd-kind-class\"},{\"id\":713,\"kind\":2048,\"name\":\"getOffsetIndex\",\"url\":\"classes/TickUtil.html#getOffsetIndex\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"TickUtil\"},{\"id\":714,\"kind\":2048,\"name\":\"getStartTickIndex\",\"url\":\"classes/TickUtil.html#getStartTickIndex\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"TickUtil\"},{\"id\":715,\"kind\":2048,\"name\":\"getInitializableTickIndex\",\"url\":\"classes/TickUtil.html#getInitializableTickIndex\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"TickUtil\"},{\"id\":716,\"kind\":2048,\"name\":\"getNextInitializableTickIndex\",\"url\":\"classes/TickUtil.html#getNextInitializableTickIndex\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"TickUtil\"},{\"id\":717,\"kind\":2048,\"name\":\"getPrevInitializableTickIndex\",\"url\":\"classes/TickUtil.html#getPrevInitializableTickIndex\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"TickUtil\"},{\"id\":718,\"kind\":2048,\"name\":\"findPreviousInitializedTickIndex\",\"url\":\"classes/TickUtil.html#findPreviousInitializedTickIndex\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"TickUtil\"},{\"id\":719,\"kind\":2048,\"name\":\"findNextInitializedTickIndex\",\"url\":\"classes/TickUtil.html#findNextInitializedTickIndex\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"TickUtil\"},{\"id\":720,\"kind\":2048,\"name\":\"checkTickInBounds\",\"url\":\"classes/TickUtil.html#checkTickInBounds\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"TickUtil\"},{\"id\":721,\"kind\":2048,\"name\":\"isTickInitializable\",\"url\":\"classes/TickUtil.html#isTickInitializable\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"TickUtil\"},{\"id\":722,\"kind\":2048,\"name\":\"invertTick\",\"url\":\"classes/TickUtil.html#invertTick\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"TickUtil\"},{\"id\":723,\"kind\":2048,\"name\":\"getFullRangeTickIndex\",\"url\":\"classes/TickUtil.html#getFullRangeTickIndex\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"TickUtil\"},{\"id\":724,\"kind\":2048,\"name\":\"isFullRange\",\"url\":\"classes/TickUtil.html#isFullRange\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"TickUtil\"},{\"id\":725,\"kind\":128,\"name\":\"TickArrayUtil\",\"url\":\"classes/TickArrayUtil.html\",\"classes\":\"tsd-kind-class\"},{\"id\":726,\"kind\":2048,\"name\":\"getTickFromArray\",\"url\":\"classes/TickArrayUtil.html#getTickFromArray\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"TickArrayUtil\"},{\"id\":727,\"kind\":2048,\"name\":\"getTickArrayPDAs\",\"url\":\"classes/TickArrayUtil.html#getTickArrayPDAs\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"TickArrayUtil\"},{\"id\":728,\"kind\":2048,\"name\":\"getUninitializedArraysString\",\"url\":\"classes/TickArrayUtil.html#getUninitializedArraysString\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"TickArrayUtil\"},{\"id\":729,\"kind\":2048,\"name\":\"getUninitializedArraysPDAs\",\"url\":\"classes/TickArrayUtil.html#getUninitializedArraysPDAs\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"TickArrayUtil\"},{\"id\":730,\"kind\":2048,\"name\":\"getUninitializedArrays\",\"url\":\"classes/TickArrayUtil.html#getUninitializedArrays\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-static\",\"parent\":\"TickArrayUtil\"},{\"id\":731,\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/TickArrayUtil.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"TickArrayUtil\"},{\"id\":732,\"kind\":8,\"name\":\"SwapDirection\",\"url\":\"enums/SwapDirection.html\",\"classes\":\"tsd-kind-enum\"},{\"id\":733,\"kind\":16,\"name\":\"AtoB\",\"url\":\"enums/SwapDirection.html#AtoB\",\"classes\":\"tsd-kind-enum-member tsd-parent-kind-enum\",\"parent\":\"SwapDirection\"},{\"id\":734,\"kind\":16,\"name\":\"BtoA\",\"url\":\"enums/SwapDirection.html#BtoA\",\"classes\":\"tsd-kind-enum-member tsd-parent-kind-enum\",\"parent\":\"SwapDirection\"},{\"id\":735,\"kind\":8,\"name\":\"TokenType\",\"url\":\"enums/TokenType.html\",\"classes\":\"tsd-kind-enum\"},{\"id\":736,\"kind\":16,\"name\":\"TokenA\",\"url\":\"enums/TokenType.html#TokenA\",\"classes\":\"tsd-kind-enum-member tsd-parent-kind-enum\",\"parent\":\"TokenType\"},{\"id\":737,\"kind\":16,\"name\":\"TokenB\",\"url\":\"enums/TokenType.html#TokenB\",\"classes\":\"tsd-kind-enum-member tsd-parent-kind-enum\",\"parent\":\"TokenType\"},{\"id\":738,\"kind\":64,\"name\":\"buildWhirlpoolClient\",\"url\":\"modules.html#buildWhirlpoolClient\",\"classes\":\"tsd-kind-function\"},{\"id\":739,\"kind\":256,\"name\":\"WhirlpoolClient\",\"url\":\"interfaces/WhirlpoolClient.html\",\"classes\":\"tsd-kind-interface\"},{\"id\":740,\"kind\":2048,\"name\":\"getContext\",\"url\":\"interfaces/WhirlpoolClient.html#getContext\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"WhirlpoolClient\"},{\"id\":741,\"kind\":2048,\"name\":\"getFetcher\",\"url\":\"interfaces/WhirlpoolClient.html#getFetcher\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"WhirlpoolClient\"},{\"id\":742,\"kind\":2048,\"name\":\"getRouter\",\"url\":\"interfaces/WhirlpoolClient.html#getRouter\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"WhirlpoolClient\"},{\"id\":743,\"kind\":2048,\"name\":\"getPool\",\"url\":\"interfaces/WhirlpoolClient.html#getPool\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"WhirlpoolClient\"},{\"id\":744,\"kind\":2048,\"name\":\"getPools\",\"url\":\"interfaces/WhirlpoolClient.html#getPools\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"WhirlpoolClient\"},{\"id\":745,\"kind\":2048,\"name\":\"getPosition\",\"url\":\"interfaces/WhirlpoolClient.html#getPosition\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"WhirlpoolClient\"},{\"id\":746,\"kind\":2048,\"name\":\"getPositions\",\"url\":\"interfaces/WhirlpoolClient.html#getPositions\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"WhirlpoolClient\"},{\"id\":747,\"kind\":2048,\"name\":\"collectFeesAndRewardsForPositions\",\"url\":\"interfaces/WhirlpoolClient.html#collectFeesAndRewardsForPositions\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"WhirlpoolClient\"},{\"id\":748,\"kind\":2048,\"name\":\"createPool\",\"url\":\"interfaces/WhirlpoolClient.html#createPool\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"WhirlpoolClient\"},{\"id\":749,\"kind\":2048,\"name\":\"collectProtocolFeesForPools\",\"url\":\"interfaces/WhirlpoolClient.html#collectProtocolFeesForPools\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"WhirlpoolClient\"},{\"id\":750,\"kind\":256,\"name\":\"Whirlpool\",\"url\":\"interfaces/Whirlpool.html\",\"classes\":\"tsd-kind-interface\"},{\"id\":751,\"kind\":2048,\"name\":\"getAddress\",\"url\":\"interfaces/Whirlpool.html#getAddress\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"Whirlpool\"},{\"id\":752,\"kind\":2048,\"name\":\"getData\",\"url\":\"interfaces/Whirlpool.html#getData\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"Whirlpool\"},{\"id\":753,\"kind\":2048,\"name\":\"refreshData\",\"url\":\"interfaces/Whirlpool.html#refreshData\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"Whirlpool\"},{\"id\":754,\"kind\":2048,\"name\":\"getTokenAInfo\",\"url\":\"interfaces/Whirlpool.html#getTokenAInfo\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"Whirlpool\"},{\"id\":755,\"kind\":2048,\"name\":\"getTokenBInfo\",\"url\":\"interfaces/Whirlpool.html#getTokenBInfo\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"Whirlpool\"},{\"id\":756,\"kind\":2048,\"name\":\"getTokenVaultAInfo\",\"url\":\"interfaces/Whirlpool.html#getTokenVaultAInfo\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"Whirlpool\"},{\"id\":757,\"kind\":2048,\"name\":\"getTokenVaultBInfo\",\"url\":\"interfaces/Whirlpool.html#getTokenVaultBInfo\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"Whirlpool\"},{\"id\":758,\"kind\":2048,\"name\":\"getRewardInfos\",\"url\":\"interfaces/Whirlpool.html#getRewardInfos\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"Whirlpool\"},{\"id\":759,\"kind\":2048,\"name\":\"initTickArrayForTicks\",\"url\":\"interfaces/Whirlpool.html#initTickArrayForTicks\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"Whirlpool\"},{\"id\":760,\"kind\":2048,\"name\":\"openPosition\",\"url\":\"interfaces/Whirlpool.html#openPosition\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"Whirlpool\"},{\"id\":761,\"kind\":2048,\"name\":\"openPositionWithMetadata\",\"url\":\"interfaces/Whirlpool.html#openPositionWithMetadata\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"Whirlpool\"},{\"id\":762,\"kind\":2048,\"name\":\"closePosition\",\"url\":\"interfaces/Whirlpool.html#closePosition\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"Whirlpool\"},{\"id\":763,\"kind\":2048,\"name\":\"swap\",\"url\":\"interfaces/Whirlpool.html#swap\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"Whirlpool\"},{\"id\":764,\"kind\":2048,\"name\":\"swapWithDevFees\",\"url\":\"interfaces/Whirlpool.html#swapWithDevFees\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"Whirlpool\"},{\"id\":765,\"kind\":256,\"name\":\"Position\",\"url\":\"interfaces/Position.html\",\"classes\":\"tsd-kind-interface\"},{\"id\":766,\"kind\":2048,\"name\":\"getAddress\",\"url\":\"interfaces/Position.html#getAddress\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"Position\"},{\"id\":767,\"kind\":2048,\"name\":\"getData\",\"url\":\"interfaces/Position.html#getData\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"Position\"},{\"id\":768,\"kind\":2048,\"name\":\"getWhirlpoolData\",\"url\":\"interfaces/Position.html#getWhirlpoolData\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"Position\"},{\"id\":769,\"kind\":2048,\"name\":\"getLowerTickData\",\"url\":\"interfaces/Position.html#getLowerTickData\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"Position\"},{\"id\":770,\"kind\":2048,\"name\":\"getUpperTickData\",\"url\":\"interfaces/Position.html#getUpperTickData\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"Position\"},{\"id\":771,\"kind\":2048,\"name\":\"refreshData\",\"url\":\"interfaces/Position.html#refreshData\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"Position\"},{\"id\":772,\"kind\":2048,\"name\":\"increaseLiquidity\",\"url\":\"interfaces/Position.html#increaseLiquidity\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"Position\"},{\"id\":773,\"kind\":2048,\"name\":\"decreaseLiquidity\",\"url\":\"interfaces/Position.html#decreaseLiquidity\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"Position\"},{\"id\":774,\"kind\":2048,\"name\":\"collectFees\",\"url\":\"interfaces/Position.html#collectFees\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"Position\"},{\"id\":775,\"kind\":2048,\"name\":\"collectRewards\",\"url\":\"interfaces/Position.html#collectRewards\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"Position\"}],\"index\":{\"version\":\"2.3.9\",\"fields\":[\"name\",\"parent\"],\"fieldVectors\":[[\"name/0\",[0,57.391]],[\"parent/0\",[]],[\"name/1\",[1,24.582]],[\"parent/1\",[0,5.168]],[\"name/2\",[2,62.5]],[\"parent/2\",[3,4.639]],[\"name/3\",[4,62.5]],[\"parent/3\",[3,4.639]],[\"name/4\",[5,62.5]],[\"parent/4\",[3,4.639]],[\"name/5\",[6,54.027]],[\"parent/5\",[3,4.639]],[\"name/6\",[6,54.027]],[\"parent/6\",[]],[\"name/7\",[1,24.582]],[\"parent/7\",[6,4.865]],[\"name/8\",[7,62.5]],[\"parent/8\",[8,5.168]],[\"name/9\",[9,62.5]],[\"parent/9\",[8,5.168]],[\"name/10\",[10,39.813]],[\"parent/10\",[]],[\"name/11\",[11,62.5]],[\"parent/11\",[10,3.585]],[\"name/12\",[12,62.5]],[\"parent/12\",[10,3.585]],[\"name/13\",[13,62.5]],[\"parent/13\",[10,3.585]],[\"name/14\",[14,40.528]],[\"parent/14\",[10,3.585]],[\"name/15\",[15,57.391]],[\"parent/15\",[10,3.585]],[\"name/16\",[16,62.5]],[\"parent/16\",[10,3.585]],[\"name/17\",[17,62.5]],[\"parent/17\",[10,3.585]],[\"name/18\",[18,62.5]],[\"parent/18\",[10,3.585]],[\"name/19\",[19,57.391]],[\"parent/19\",[10,3.585]],[\"name/20\",[20,62.5]],[\"parent/20\",[10,3.585]],[\"name/21\",[21,62.5]],[\"parent/21\",[10,3.585]],[\"name/22\",[22,62.5]],[\"parent/22\",[10,3.585]],[\"name/23\",[23,62.5]],[\"parent/23\",[10,3.585]],[\"name/24\",[24,31.439]],[\"parent/24\",[]],[\"name/25\",[25,62.5]],[\"parent/25\",[24,2.831]],[\"name/26\",[26,62.5]],[\"parent/26\",[24,2.831]],[\"name/27\",[27,62.5]],[\"parent/27\",[24,2.831]],[\"name/28\",[28,62.5]],[\"parent/28\",[24,2.831]],[\"name/29\",[29,62.5]],[\"parent/29\",[24,2.831]],[\"name/30\",[30,62.5]],[\"parent/30\",[24,2.831]],[\"name/31\",[31,62.5]],[\"parent/31\",[24,2.831]],[\"name/32\",[32,62.5]],[\"parent/32\",[24,2.831]],[\"name/33\",[33,62.5]],[\"parent/33\",[24,2.831]],[\"name/34\",[34,62.5]],[\"parent/34\",[24,2.831]],[\"name/35\",[35,62.5]],[\"parent/35\",[24,2.831]],[\"name/36\",[36,62.5]],[\"parent/36\",[24,2.831]],[\"name/37\",[37,62.5]],[\"parent/37\",[24,2.831]],[\"name/38\",[38,62.5]],[\"parent/38\",[24,2.831]],[\"name/39\",[39,62.5]],[\"parent/39\",[24,2.831]],[\"name/40\",[40,62.5]],[\"parent/40\",[24,2.831]],[\"name/41\",[41,62.5]],[\"parent/41\",[24,2.831]],[\"name/42\",[42,62.5]],[\"parent/42\",[24,2.831]],[\"name/43\",[43,62.5]],[\"parent/43\",[24,2.831]],[\"name/44\",[44,62.5]],[\"parent/44\",[24,2.831]],[\"name/45\",[45,62.5]],[\"parent/45\",[24,2.831]],[\"name/46\",[46,62.5]],[\"parent/46\",[24,2.831]],[\"name/47\",[47,62.5]],[\"parent/47\",[24,2.831]],[\"name/48\",[48,62.5]],[\"parent/48\",[24,2.831]],[\"name/49\",[49,62.5]],[\"parent/49\",[24,2.831]],[\"name/50\",[50,62.5]],[\"parent/50\",[24,2.831]],[\"name/51\",[51,62.5]],[\"parent/51\",[24,2.831]],[\"name/52\",[52,62.5]],[\"parent/52\",[24,2.831]],[\"name/53\",[53,62.5]],[\"parent/53\",[24,2.831]],[\"name/54\",[54,62.5]],[\"parent/54\",[24,2.831]],[\"name/55\",[55,62.5]],[\"parent/55\",[24,2.831]],[\"name/56\",[14,40.528]],[\"parent/56\",[24,2.831]],[\"name/57\",[56,62.5]],[\"parent/57\",[]],[\"name/58\",[57,35.419]],[\"parent/58\",[]],[\"name/59\",[14,40.528]],[\"parent/59\",[57,3.19]],[\"name/60\",[15,57.391]],[\"parent/60\",[57,3.19]],[\"name/61\",[19,57.391]],[\"parent/61\",[57,3.19]],[\"name/62\",[58,57.391]],[\"parent/62\",[57,3.19]],[\"name/63\",[59,54.027]],[\"parent/63\",[57,3.19]],[\"name/64\",[60,54.027]],[\"parent/64\",[57,3.19]],[\"name/65\",[61,51.514]],[\"parent/65\",[57,3.19]],[\"name/66\",[62,54.027]],[\"parent/66\",[57,3.19]],[\"name/67\",[63,54.027]],[\"parent/67\",[57,3.19]],[\"name/68\",[64,54.027]],[\"parent/68\",[57,3.19]],[\"name/69\",[65,54.027]],[\"parent/69\",[57,3.19]],[\"name/70\",[66,57.391]],[\"parent/70\",[57,3.19]],[\"name/71\",[67,57.391]],[\"parent/71\",[57,3.19]],[\"name/72\",[68,57.391]],[\"parent/72\",[57,3.19]],[\"name/73\",[69,57.391]],[\"parent/73\",[57,3.19]],[\"name/74\",[70,57.391]],[\"parent/74\",[57,3.19]],[\"name/75\",[71,57.391]],[\"parent/75\",[57,3.19]],[\"name/76\",[72,57.391]],[\"parent/76\",[57,3.19]],[\"name/77\",[73,54.027]],[\"parent/77\",[57,3.19]],[\"name/78\",[74,57.391]],[\"parent/78\",[57,3.19]],[\"name/79\",[75,57.391]],[\"parent/79\",[57,3.19]],[\"name/80\",[76,62.5]],[\"parent/80\",[]],[\"name/81\",[77,62.5]],[\"parent/81\",[]],[\"name/82\",[78,62.5]],[\"parent/82\",[]],[\"name/83\",[79,62.5]],[\"parent/83\",[]],[\"name/84\",[80,62.5]],[\"parent/84\",[]],[\"name/85\",[81,36.85]],[\"parent/85\",[]],[\"name/86\",[58,57.391]],[\"parent/86\",[81,3.318]],[\"name/87\",[59,54.027]],[\"parent/87\",[81,3.318]],[\"name/88\",[60,54.027]],[\"parent/88\",[81,3.318]],[\"name/89\",[61,51.514]],[\"parent/89\",[81,3.318]],[\"name/90\",[62,54.027]],[\"parent/90\",[81,3.318]],[\"name/91\",[63,54.027]],[\"parent/91\",[81,3.318]],[\"name/92\",[64,54.027]],[\"parent/92\",[81,3.318]],[\"name/93\",[65,54.027]],[\"parent/93\",[81,3.318]],[\"name/94\",[66,57.391]],[\"parent/94\",[81,3.318]],[\"name/95\",[67,57.391]],[\"parent/95\",[81,3.318]],[\"name/96\",[68,57.391]],[\"parent/96\",[81,3.318]],[\"name/97\",[69,57.391]],[\"parent/97\",[81,3.318]],[\"name/98\",[70,57.391]],[\"parent/98\",[81,3.318]],[\"name/99\",[71,57.391]],[\"parent/99\",[81,3.318]],[\"name/100\",[72,57.391]],[\"parent/100\",[81,3.318]],[\"name/101\",[73,54.027]],[\"parent/101\",[81,3.318]],[\"name/102\",[74,57.391]],[\"parent/102\",[81,3.318]],[\"name/103\",[75,57.391]],[\"parent/103\",[81,3.318]],[\"name/104\",[82,62.5]],[\"parent/104\",[]],[\"name/105\",[83,57.391]],[\"parent/105\",[]],[\"name/106\",[84,47.836]],[\"parent/106\",[83,5.168]],[\"name/107\",[85,57.391]],[\"parent/107\",[]],[\"name/108\",[84,47.836]],[\"parent/108\",[85,5.168]],[\"name/109\",[86,57.391]],[\"parent/109\",[]],[\"name/110\",[84,47.836]],[\"parent/110\",[86,5.168]],[\"name/111\",[87,57.391]],[\"parent/111\",[]],[\"name/112\",[84,47.836]],[\"parent/112\",[87,5.168]],[\"name/113\",[88,57.391]],[\"parent/113\",[]],[\"name/114\",[84,47.836]],[\"parent/114\",[88,5.168]],[\"name/115\",[89,57.391]],[\"parent/115\",[]],[\"name/116\",[84,47.836]],[\"parent/116\",[89,5.168]],[\"name/117\",[90,57.391]],[\"parent/117\",[]],[\"name/118\",[1,24.582]],[\"parent/118\",[90,5.168]],[\"name/119\",[91,62.5]],[\"parent/119\",[92,4.639]],[\"name/120\",[93,62.5]],[\"parent/120\",[92,4.639]],[\"name/121\",[94,62.5]],[\"parent/121\",[92,4.639]],[\"name/122\",[95,39.146]],[\"parent/122\",[92,4.639]],[\"name/123\",[96,57.391]],[\"parent/123\",[]],[\"name/124\",[1,24.582]],[\"parent/124\",[96,5.168]],[\"name/125\",[97,54.027]],[\"parent/125\",[98,5.168]],[\"name/126\",[99,62.5]],[\"parent/126\",[98,5.168]],[\"name/127\",[100,57.391]],[\"parent/127\",[]],[\"name/128\",[1,24.582]],[\"parent/128\",[100,5.168]],[\"name/129\",[101,57.391]],[\"parent/129\",[102,4.865]],[\"name/130\",[103,57.391]],[\"parent/130\",[102,4.865]],[\"name/131\",[104,57.391]],[\"parent/131\",[102,4.865]],[\"name/132\",[101,57.391]],[\"parent/132\",[]],[\"name/133\",[103,57.391]],[\"parent/133\",[]],[\"name/134\",[105,62.5]],[\"parent/134\",[]],[\"name/135\",[104,57.391]],[\"parent/135\",[]],[\"name/136\",[106,62.5]],[\"parent/136\",[]],[\"name/137\",[107,62.5]],[\"parent/137\",[]],[\"name/138\",[108,62.5]],[\"parent/138\",[]],[\"name/139\",[109,49.507]],[\"parent/139\",[]],[\"name/140\",[110,62.5]],[\"parent/140\",[109,4.458]],[\"name/141\",[111,62.5]],[\"parent/141\",[109,4.458]],[\"name/142\",[112,62.5]],[\"parent/142\",[109,4.458]],[\"name/143\",[14,40.528]],[\"parent/143\",[109,4.458]],[\"name/144\",[113,49.507]],[\"parent/144\",[]],[\"name/145\",[114,62.5]],[\"parent/145\",[113,4.458]],[\"name/146\",[115,62.5]],[\"parent/146\",[113,4.458]],[\"name/147\",[116,62.5]],[\"parent/147\",[113,4.458]],[\"name/148\",[14,40.528]],[\"parent/148\",[113,4.458]],[\"name/149\",[117,62.5]],[\"parent/149\",[]],[\"name/150\",[118,62.5]],[\"parent/150\",[]],[\"name/151\",[119,57.391]],[\"parent/151\",[]],[\"name/152\",[1,24.582]],[\"parent/152\",[119,5.168]],[\"name/153\",[120,62.5]],[\"parent/153\",[121,3.966]],[\"name/154\",[122,62.5]],[\"parent/154\",[121,3.966]],[\"name/155\",[123,51.514]],[\"parent/155\",[121,3.966]],[\"name/156\",[124,51.514]],[\"parent/156\",[121,3.966]],[\"name/157\",[125,51.514]],[\"parent/157\",[121,3.966]],[\"name/158\",[126,51.514]],[\"parent/158\",[121,3.966]],[\"name/159\",[127,49.507]],[\"parent/159\",[121,3.966]],[\"name/160\",[128,49.507]],[\"parent/160\",[121,3.966]],[\"name/161\",[129,57.391]],[\"parent/161\",[121,3.966]],[\"name/162\",[130,62.5]],[\"parent/162\",[]],[\"name/163\",[131,62.5]],[\"parent/163\",[]],[\"name/164\",[132,62.5]],[\"parent/164\",[]],[\"name/165\",[133,57.391]],[\"parent/165\",[]],[\"name/166\",[1,24.582]],[\"parent/166\",[133,5.168]],[\"name/167\",[134,54.027]],[\"parent/167\",[135,4.308]],[\"name/168\",[125,51.514]],[\"parent/168\",[135,4.308]],[\"name/169\",[126,51.514]],[\"parent/169\",[135,4.308]],[\"name/170\",[127,49.507]],[\"parent/170\",[135,4.308]],[\"name/171\",[128,49.507]],[\"parent/171\",[135,4.308]],[\"name/172\",[129,57.391]],[\"parent/172\",[135,4.308]],[\"name/173\",[136,62.5]],[\"parent/173\",[]],[\"name/174\",[137,54.027]],[\"parent/174\",[]],[\"name/175\",[138,57.391]],[\"parent/175\",[]],[\"name/176\",[1,24.582]],[\"parent/176\",[138,5.168]],[\"name/177\",[139,31.145]],[\"parent/177\",[140,4.639]],[\"name/178\",[141,37.377]],[\"parent/178\",[140,4.639]],[\"name/179\",[142,57.391]],[\"parent/179\",[140,4.639]],[\"name/180\",[143,57.391]],[\"parent/180\",[140,4.639]],[\"name/181\",[137,54.027]],[\"parent/181\",[]],[\"name/182\",[1,24.582]],[\"parent/182\",[137,4.865]],[\"name/183\",[144,57.391]],[\"parent/183\",[145,5.168]],[\"name/184\",[146,57.391]],[\"parent/184\",[145,5.168]],[\"name/185\",[147,57.391]],[\"parent/185\",[]],[\"name/186\",[148,57.391]],[\"parent/186\",[]],[\"name/187\",[1,24.582]],[\"parent/187\",[148,5.168]],[\"name/188\",[139,31.145]],[\"parent/188\",[149,4.458]],[\"name/189\",[141,37.377]],[\"parent/189\",[149,4.458]],[\"name/190\",[142,57.391]],[\"parent/190\",[149,4.458]],[\"name/191\",[143,57.391]],[\"parent/191\",[149,4.458]],[\"name/192\",[150,62.5]],[\"parent/192\",[149,4.458]],[\"name/193\",[147,57.391]],[\"parent/193\",[]],[\"name/194\",[151,62.5]],[\"parent/194\",[]],[\"name/195\",[152,62.5]],[\"parent/195\",[]],[\"name/196\",[153,62.5]],[\"parent/196\",[]],[\"name/197\",[154,57.391]],[\"parent/197\",[]],[\"name/198\",[1,24.582]],[\"parent/198\",[154,5.168]],[\"name/199\",[155,54.027]],[\"parent/199\",[156,4.179]],[\"name/200\",[157,62.5]],[\"parent/200\",[156,4.179]],[\"name/201\",[158,57.391]],[\"parent/201\",[156,4.179]],[\"name/202\",[159,57.391]],[\"parent/202\",[156,4.179]],[\"name/203\",[160,49.507]],[\"parent/203\",[156,4.179]],[\"name/204\",[161,54.027]],[\"parent/204\",[156,4.179]],[\"name/205\",[162,62.5]],[\"parent/205\",[156,4.179]],[\"name/206\",[163,62.5]],[\"parent/206\",[]],[\"name/207\",[164,57.391]],[\"parent/207\",[]],[\"name/208\",[1,24.582]],[\"parent/208\",[164,5.168]],[\"name/209\",[165,62.5]],[\"parent/209\",[166,4.458]],[\"name/210\",[167,62.5]],[\"parent/210\",[166,4.458]],[\"name/211\",[168,62.5]],[\"parent/211\",[166,4.458]],[\"name/212\",[169,62.5]],[\"parent/212\",[166,4.458]],[\"name/213\",[170,62.5]],[\"parent/213\",[166,4.458]],[\"name/214\",[171,62.5]],[\"parent/214\",[]],[\"name/215\",[172,62.5]],[\"parent/215\",[]],[\"name/216\",[173,62.5]],[\"parent/216\",[]],[\"name/217\",[174,62.5]],[\"parent/217\",[]],[\"name/218\",[175,62.5]],[\"parent/218\",[]],[\"name/219\",[176,62.5]],[\"parent/219\",[]],[\"name/220\",[177,57.391]],[\"parent/220\",[]],[\"name/221\",[1,24.582]],[\"parent/221\",[177,5.168]],[\"name/222\",[178,62.5]],[\"parent/222\",[179,4.639]],[\"name/223\",[180,62.5]],[\"parent/223\",[179,4.639]],[\"name/224\",[181,62.5]],[\"parent/224\",[179,4.639]],[\"name/225\",[161,54.027]],[\"parent/225\",[179,4.639]],[\"name/226\",[182,57.391]],[\"parent/226\",[]],[\"name/227\",[1,24.582]],[\"parent/227\",[182,5.168]],[\"name/228\",[183,62.5]],[\"parent/228\",[184,4.639]],[\"name/229\",[185,62.5]],[\"parent/229\",[184,4.639]],[\"name/230\",[186,62.5]],[\"parent/230\",[184,4.639]],[\"name/231\",[187,62.5]],[\"parent/231\",[184,4.639]],[\"name/232\",[188,57.391]],[\"parent/232\",[]],[\"name/233\",[1,24.582]],[\"parent/233\",[188,5.168]],[\"name/234\",[189,62.5]],[\"parent/234\",[190,4.865]],[\"name/235\",[191,62.5]],[\"parent/235\",[190,4.865]],[\"name/236\",[192,62.5]],[\"parent/236\",[190,4.865]],[\"name/237\",[193,57.391]],[\"parent/237\",[]],[\"name/238\",[1,24.582]],[\"parent/238\",[193,5.168]],[\"name/239\",[194,54.027]],[\"parent/239\",[195,4.458]],[\"name/240\",[196,62.5]],[\"parent/240\",[195,4.458]],[\"name/241\",[197,57.391]],[\"parent/241\",[195,4.458]],[\"name/242\",[97,54.027]],[\"parent/242\",[195,4.458]],[\"name/243\",[198,62.5]],[\"parent/243\",[195,4.458]],[\"name/244\",[199,57.391]],[\"parent/244\",[]],[\"name/245\",[1,24.582]],[\"parent/245\",[199,5.168]],[\"name/246\",[197,57.391]],[\"parent/246\",[200,3.794]],[\"name/247\",[97,54.027]],[\"parent/247\",[200,3.794]],[\"name/248\",[139,31.145]],[\"parent/248\",[200,3.794]],[\"name/249\",[201,62.5]],[\"parent/249\",[200,3.794]],[\"name/250\",[202,62.5]],[\"parent/250\",[200,3.794]],[\"name/251\",[203,62.5]],[\"parent/251\",[200,3.794]],[\"name/252\",[204,62.5]],[\"parent/252\",[200,3.794]],[\"name/253\",[205,62.5]],[\"parent/253\",[200,3.794]],[\"name/254\",[206,62.5]],[\"parent/254\",[200,3.794]],[\"name/255\",[207,62.5]],[\"parent/255\",[200,3.794]],[\"name/256\",[208,62.5]],[\"parent/256\",[200,3.794]],[\"name/257\",[209,57.391]],[\"parent/257\",[]],[\"name/258\",[1,24.582]],[\"parent/258\",[209,5.168]],[\"name/259\",[160,49.507]],[\"parent/259\",[210,4.865]],[\"name/260\",[126,51.514]],[\"parent/260\",[210,4.865]],[\"name/261\",[211,54.027]],[\"parent/261\",[210,4.865]],[\"name/262\",[212,62.5]],[\"parent/262\",[]],[\"name/263\",[213,51.514]],[\"parent/263\",[]],[\"name/264\",[214,62.5]],[\"parent/264\",[213,4.639]],[\"name/265\",[215,62.5]],[\"parent/265\",[213,4.639]],[\"name/266\",[216,57.391]],[\"parent/266\",[213,4.639]],[\"name/267\",[217,51.514]],[\"parent/267\",[]],[\"name/268\",[218,62.5]],[\"parent/268\",[217,4.639]],[\"name/269\",[219,62.5]],[\"parent/269\",[217,4.639]],[\"name/270\",[14,40.528]],[\"parent/270\",[217,4.639]],[\"name/271\",[220,62.5]],[\"parent/271\",[]],[\"name/272\",[221,57.391]],[\"parent/272\",[]],[\"name/273\",[1,24.582]],[\"parent/273\",[221,5.168]],[\"name/274\",[222,62.5]],[\"parent/274\",[223,4.639]],[\"name/275\",[224,62.5]],[\"parent/275\",[223,4.639]],[\"name/276\",[225,62.5]],[\"parent/276\",[223,4.639]],[\"name/277\",[226,62.5]],[\"parent/277\",[223,4.639]],[\"name/278\",[227,46.405]],[\"parent/278\",[]],[\"name/279\",[228,62.5]],[\"parent/279\",[227,4.179]],[\"name/280\",[229,62.5]],[\"parent/280\",[227,4.179]],[\"name/281\",[230,62.5]],[\"parent/281\",[227,4.179]],[\"name/282\",[231,62.5]],[\"parent/282\",[227,4.179]],[\"name/283\",[232,62.5]],[\"parent/283\",[227,4.179]],[\"name/284\",[14,40.528]],[\"parent/284\",[227,4.179]],[\"name/285\",[233,62.5]],[\"parent/285\",[]],[\"name/286\",[234,46.405]],[\"parent/286\",[]],[\"name/287\",[95,39.146]],[\"parent/287\",[234,4.179]],[\"name/288\",[141,37.377]],[\"parent/288\",[234,4.179]],[\"name/289\",[235,54.027]],[\"parent/289\",[234,4.179]],[\"name/290\",[139,31.145]],[\"parent/290\",[234,4.179]],[\"name/291\",[236,62.5]],[\"parent/291\",[234,4.179]],[\"name/292\",[237,51.514]],[\"parent/292\",[234,4.179]],[\"name/293\",[238,62.5]],[\"parent/293\",[]],[\"name/294\",[239,62.5]],[\"parent/294\",[]],[\"name/295\",[240,62.5]],[\"parent/295\",[]],[\"name/296\",[241,57.391]],[\"parent/296\",[]],[\"name/297\",[1,24.582]],[\"parent/297\",[241,5.168]],[\"name/298\",[242,45.154]],[\"parent/298\",[243,4.458]],[\"name/299\",[244,51.514]],[\"parent/299\",[243,4.458]],[\"name/300\",[245,51.514]],[\"parent/300\",[243,4.458]],[\"name/301\",[246,51.514]],[\"parent/301\",[243,4.458]],[\"name/302\",[247,54.027]],[\"parent/302\",[243,4.458]],[\"name/303\",[248,57.391]],[\"parent/303\",[]],[\"name/304\",[1,24.582]],[\"parent/304\",[248,5.168]],[\"name/305\",[249,62.5]],[\"parent/305\",[250,4.458]],[\"name/306\",[251,62.5]],[\"parent/306\",[250,4.458]],[\"name/307\",[252,62.5]],[\"parent/307\",[250,4.458]],[\"name/308\",[253,57.391]],[\"parent/308\",[250,4.458]],[\"name/309\",[254,62.5]],[\"parent/309\",[250,4.458]],[\"name/310\",[255,57.391]],[\"parent/310\",[]],[\"name/311\",[1,24.582]],[\"parent/311\",[255,5.168]],[\"name/312\",[256,57.391]],[\"parent/312\",[257,5.628]],[\"name/313\",[155,54.027]],[\"parent/313\",[]],[\"name/314\",[1,24.582]],[\"parent/314\",[155,4.865]],[\"name/315\",[95,39.146]],[\"parent/315\",[258,3.366]],[\"name/316\",[256,57.391]],[\"parent/316\",[258,3.366]],[\"name/317\",[211,54.027]],[\"parent/317\",[258,3.366]],[\"name/318\",[259,57.391]],[\"parent/318\",[258,3.366]],[\"name/319\",[134,54.027]],[\"parent/319\",[258,3.366]],[\"name/320\",[126,51.514]],[\"parent/320\",[258,3.366]],[\"name/321\",[125,51.514]],[\"parent/321\",[258,3.366]],[\"name/322\",[260,62.5]],[\"parent/322\",[258,3.366]],[\"name/323\",[261,62.5]],[\"parent/323\",[258,3.366]],[\"name/324\",[123,51.514]],[\"parent/324\",[258,3.366]],[\"name/325\",[262,54.027]],[\"parent/325\",[258,3.366]],[\"name/326\",[263,62.5]],[\"parent/326\",[258,3.366]],[\"name/327\",[124,51.514]],[\"parent/327\",[258,3.366]],[\"name/328\",[264,54.027]],[\"parent/328\",[258,3.366]],[\"name/329\",[265,62.5]],[\"parent/329\",[258,3.366]],[\"name/330\",[266,62.5]],[\"parent/330\",[258,3.366]],[\"name/331\",[267,57.391]],[\"parent/331\",[258,3.366]],[\"name/332\",[268,47.836]],[\"parent/332\",[258,3.366]],[\"name/333\",[269,57.391]],[\"parent/333\",[]],[\"name/334\",[1,24.582]],[\"parent/334\",[269,5.168]],[\"name/335\",[139,31.145]],[\"parent/335\",[270,4.865]],[\"name/336\",[271,62.5]],[\"parent/336\",[270,4.865]],[\"name/337\",[272,62.5]],[\"parent/337\",[270,4.865]],[\"name/338\",[273,57.391]],[\"parent/338\",[]],[\"name/339\",[1,24.582]],[\"parent/339\",[273,5.168]],[\"name/340\",[274,62.5]],[\"parent/340\",[275,4.308]],[\"name/341\",[276,62.5]],[\"parent/341\",[275,4.308]],[\"name/342\",[277,62.5]],[\"parent/342\",[275,4.308]],[\"name/343\",[278,62.5]],[\"parent/343\",[275,4.308]],[\"name/344\",[279,62.5]],[\"parent/344\",[275,4.308]],[\"name/345\",[280,62.5]],[\"parent/345\",[275,4.308]],[\"name/346\",[281,57.391]],[\"parent/346\",[]],[\"name/347\",[1,24.582]],[\"parent/347\",[281,5.168]],[\"name/348\",[282,62.5]],[\"parent/348\",[283,5.168]],[\"name/349\",[284,62.5]],[\"parent/349\",[283,5.168]],[\"name/350\",[285,57.391]],[\"parent/350\",[]],[\"name/351\",[1,24.582]],[\"parent/351\",[285,5.168]],[\"name/352\",[286,57.391]],[\"parent/352\",[287,5.628]],[\"name/353\",[288,57.391]],[\"parent/353\",[]],[\"name/354\",[1,24.582]],[\"parent/354\",[288,5.168]],[\"name/355\",[286,57.391]],[\"parent/355\",[289,5.168]],[\"name/356\",[290,62.5]],[\"parent/356\",[289,5.168]],[\"name/357\",[291,57.391]],[\"parent/357\",[]],[\"name/358\",[1,24.582]],[\"parent/358\",[291,5.168]],[\"name/359\",[139,31.145]],[\"parent/359\",[292,3.876]],[\"name/360\",[293,57.391]],[\"parent/360\",[292,3.876]],[\"name/361\",[134,54.027]],[\"parent/361\",[292,3.876]],[\"name/362\",[127,49.507]],[\"parent/362\",[292,3.876]],[\"name/363\",[128,49.507]],[\"parent/363\",[292,3.876]],[\"name/364\",[294,62.5]],[\"parent/364\",[292,3.876]],[\"name/365\",[144,57.391]],[\"parent/365\",[292,3.876]],[\"name/366\",[295,62.5]],[\"parent/366\",[292,3.876]],[\"name/367\",[146,57.391]],[\"parent/367\",[292,3.876]],[\"name/368\",[267,57.391]],[\"parent/368\",[292,3.876]],[\"name/369\",[296,57.391]],[\"parent/369\",[]],[\"name/370\",[1,24.582]],[\"parent/370\",[296,5.168]],[\"name/371\",[95,39.146]],[\"parent/371\",[297,4.865]],[\"name/372\",[268,47.836]],[\"parent/372\",[297,4.865]],[\"name/373\",[246,51.514]],[\"parent/373\",[297,4.865]],[\"name/374\",[298,57.391]],[\"parent/374\",[]],[\"name/375\",[1,24.582]],[\"parent/375\",[298,5.168]],[\"name/376\",[299,57.391]],[\"parent/376\",[300,5.168]],[\"name/377\",[301,62.5]],[\"parent/377\",[300,5.168]],[\"name/378\",[302,62.5]],[\"parent/378\",[]],[\"name/379\",[303,62.5]],[\"parent/379\",[]],[\"name/380\",[304,62.5]],[\"parent/380\",[]],[\"name/381\",[235,54.027]],[\"parent/381\",[]],[\"name/382\",[1,24.582]],[\"parent/382\",[235,4.865]],[\"name/383\",[305,57.391]],[\"parent/383\",[306,5.168]],[\"name/384\",[307,62.5]],[\"parent/384\",[306,5.168]],[\"name/385\",[308,62.5]],[\"parent/385\",[]],[\"name/386\",[309,62.5]],[\"parent/386\",[]],[\"name/387\",[310,62.5]],[\"parent/387\",[]],[\"name/388\",[311,62.5]],[\"parent/388\",[]],[\"name/389\",[312,62.5]],[\"parent/389\",[]],[\"name/390\",[313,62.5]],[\"parent/390\",[]],[\"name/391\",[314,62.5]],[\"parent/391\",[]],[\"name/392\",[315,62.5]],[\"parent/392\",[]],[\"name/393\",[316,62.5]],[\"parent/393\",[]],[\"name/394\",[317,62.5]],[\"parent/394\",[]],[\"name/395\",[318,62.5]],[\"parent/395\",[]],[\"name/396\",[319,62.5]],[\"parent/396\",[]],[\"name/397\",[320,62.5]],[\"parent/397\",[]],[\"name/398\",[321,62.5]],[\"parent/398\",[]],[\"name/399\",[322,62.5]],[\"parent/399\",[]],[\"name/400\",[323,57.391]],[\"parent/400\",[]],[\"name/401\",[1,24.582]],[\"parent/401\",[323,5.168]],[\"name/402\",[324,51.514]],[\"parent/402\",[325,4.458]],[\"name/403\",[141,37.377]],[\"parent/403\",[325,4.458]],[\"name/404\",[293,57.391]],[\"parent/404\",[325,4.458]],[\"name/405\",[326,51.514]],[\"parent/405\",[325,4.458]],[\"name/406\",[327,51.514]],[\"parent/406\",[325,4.458]],[\"name/407\",[328,57.391]],[\"parent/407\",[]],[\"name/408\",[1,24.582]],[\"parent/408\",[328,5.168]],[\"name/409\",[139,31.145]],[\"parent/409\",[329,4.066]],[\"name/410\",[141,37.377]],[\"parent/410\",[329,4.066]],[\"name/411\",[326,51.514]],[\"parent/411\",[329,4.066]],[\"name/412\",[330,57.391]],[\"parent/412\",[329,4.066]],[\"name/413\",[331,57.391]],[\"parent/413\",[329,4.066]],[\"name/414\",[262,54.027]],[\"parent/414\",[329,4.066]],[\"name/415\",[264,54.027]],[\"parent/415\",[329,4.066]],[\"name/416\",[327,51.514]],[\"parent/416\",[329,4.066]],[\"name/417\",[332,57.391]],[\"parent/417\",[]],[\"name/418\",[1,24.582]],[\"parent/418\",[332,5.168]],[\"name/419\",[95,39.146]],[\"parent/419\",[333,4.179]],[\"name/420\",[139,31.145]],[\"parent/420\",[333,4.179]],[\"name/421\",[262,54.027]],[\"parent/421\",[333,4.179]],[\"name/422\",[264,54.027]],[\"parent/422\",[333,4.179]],[\"name/423\",[330,57.391]],[\"parent/423\",[333,4.179]],[\"name/424\",[331,57.391]],[\"parent/424\",[333,4.179]],[\"name/425\",[244,51.514]],[\"parent/425\",[333,4.179]],[\"name/426\",[334,57.391]],[\"parent/426\",[]],[\"name/427\",[1,24.582]],[\"parent/427\",[334,5.168]],[\"name/428\",[139,31.145]],[\"parent/428\",[335,4.179]],[\"name/429\",[141,37.377]],[\"parent/429\",[335,4.179]],[\"name/430\",[326,51.514]],[\"parent/430\",[335,4.179]],[\"name/431\",[336,49.507]],[\"parent/431\",[335,4.179]],[\"name/432\",[337,62.5]],[\"parent/432\",[335,4.179]],[\"name/433\",[338,62.5]],[\"parent/433\",[335,4.179]],[\"name/434\",[327,51.514]],[\"parent/434\",[335,4.179]],[\"name/435\",[339,57.391]],[\"parent/435\",[]],[\"name/436\",[1,24.582]],[\"parent/436\",[339,5.168]],[\"name/437\",[340,62.5]],[\"parent/437\",[341,4.865]],[\"name/438\",[342,62.5]],[\"parent/438\",[341,4.865]],[\"name/439\",[343,57.391]],[\"parent/439\",[341,4.865]],[\"name/440\",[344,62.5]],[\"parent/440\",[]],[\"name/441\",[345,62.5]],[\"parent/441\",[]],[\"name/442\",[346,57.391]],[\"parent/442\",[]],[\"name/443\",[1,24.582]],[\"parent/443\",[346,5.168]],[\"name/444\",[347,62.5]],[\"parent/444\",[348,4.865]],[\"name/445\",[349,62.5]],[\"parent/445\",[348,4.865]],[\"name/446\",[343,57.391]],[\"parent/446\",[348,4.865]],[\"name/447\",[350,62.5]],[\"parent/447\",[]],[\"name/448\",[351,57.391]],[\"parent/448\",[]],[\"name/449\",[1,24.582]],[\"parent/449\",[351,5.168]],[\"name/450\",[352,62.5]],[\"parent/450\",[353,4.308]],[\"name/451\",[242,45.154]],[\"parent/451\",[353,4.308]],[\"name/452\",[244,51.514]],[\"parent/452\",[353,4.308]],[\"name/453\",[245,51.514]],[\"parent/453\",[353,4.308]],[\"name/454\",[247,54.027]],[\"parent/454\",[353,4.308]],[\"name/455\",[354,45.154]],[\"parent/455\",[353,4.308]],[\"name/456\",[355,57.391]],[\"parent/456\",[]],[\"name/457\",[1,24.582]],[\"parent/457\",[355,5.168]],[\"name/458\",[95,39.146]],[\"parent/458\",[356,4.308]],[\"name/459\",[357,62.5]],[\"parent/459\",[356,4.308]],[\"name/460\",[268,47.836]],[\"parent/460\",[356,4.308]],[\"name/461\",[246,51.514]],[\"parent/461\",[356,4.308]],[\"name/462\",[242,45.154]],[\"parent/462\",[356,4.308]],[\"name/463\",[354,45.154]],[\"parent/463\",[356,4.308]],[\"name/464\",[358,57.391]],[\"parent/464\",[]],[\"name/465\",[1,24.582]],[\"parent/465\",[358,5.168]],[\"name/466\",[139,31.145]],[\"parent/466\",[359,4.308]],[\"name/467\",[336,49.507]],[\"parent/467\",[359,4.308]],[\"name/468\",[360,62.5]],[\"parent/468\",[359,4.308]],[\"name/469\",[361,62.5]],[\"parent/469\",[359,4.308]],[\"name/470\",[362,54.027]],[\"parent/470\",[359,4.308]],[\"name/471\",[354,45.154]],[\"parent/471\",[359,4.308]],[\"name/472\",[363,57.391]],[\"parent/472\",[]],[\"name/473\",[1,24.582]],[\"parent/473\",[363,5.168]],[\"name/474\",[364,62.5]],[\"parent/474\",[365,3.876]],[\"name/475\",[95,39.146]],[\"parent/475\",[365,3.876]],[\"name/476\",[366,62.5]],[\"parent/476\",[365,3.876]],[\"name/477\",[123,51.514]],[\"parent/477\",[365,3.876]],[\"name/478\",[124,51.514]],[\"parent/478\",[365,3.876]],[\"name/479\",[367,62.5]],[\"parent/479\",[365,3.876]],[\"name/480\",[368,62.5]],[\"parent/480\",[365,3.876]],[\"name/481\",[369,62.5]],[\"parent/481\",[365,3.876]],[\"name/482\",[268,47.836]],[\"parent/482\",[365,3.876]],[\"name/483\",[354,45.154]],[\"parent/483\",[365,3.876]],[\"name/484\",[370,57.391]],[\"parent/484\",[]],[\"name/485\",[1,24.582]],[\"parent/485\",[370,5.168]],[\"name/486\",[139,31.145]],[\"parent/486\",[371,4.639]],[\"name/487\",[372,62.5]],[\"parent/487\",[371,4.639]],[\"name/488\",[373,62.5]],[\"parent/488\",[371,4.639]],[\"name/489\",[354,45.154]],[\"parent/489\",[371,4.639]],[\"name/490\",[374,57.391]],[\"parent/490\",[]],[\"name/491\",[1,24.582]],[\"parent/491\",[374,5.168]],[\"name/492\",[139,31.145]],[\"parent/492\",[375,4.066]],[\"name/493\",[376,54.027]],[\"parent/493\",[375,4.066]],[\"name/494\",[377,62.5]],[\"parent/494\",[375,4.066]],[\"name/495\",[378,62.5]],[\"parent/495\",[375,4.066]],[\"name/496\",[326,51.514]],[\"parent/496\",[375,4.066]],[\"name/497\",[127,49.507]],[\"parent/497\",[375,4.066]],[\"name/498\",[128,49.507]],[\"parent/498\",[375,4.066]],[\"name/499\",[354,45.154]],[\"parent/499\",[375,4.066]],[\"name/500\",[379,57.391]],[\"parent/500\",[]],[\"name/501\",[1,24.582]],[\"parent/501\",[379,5.168]],[\"name/502\",[95,39.146]],[\"parent/502\",[380,4.865]],[\"name/503\",[244,51.514]],[\"parent/503\",[380,4.865]],[\"name/504\",[381,62.5]],[\"parent/504\",[380,4.865]],[\"name/505\",[382,57.391]],[\"parent/505\",[]],[\"name/506\",[1,24.582]],[\"parent/506\",[382,5.168]],[\"name/507\",[95,39.146]],[\"parent/507\",[383,4.639]],[\"name/508\",[242,45.154]],[\"parent/508\",[383,4.639]],[\"name/509\",[268,47.836]],[\"parent/509\",[383,4.639]],[\"name/510\",[246,51.514]],[\"parent/510\",[383,4.639]],[\"name/511\",[384,57.391]],[\"parent/511\",[]],[\"name/512\",[1,24.582]],[\"parent/512\",[384,5.168]],[\"name/513\",[95,39.146]],[\"parent/513\",[385,4.865]],[\"name/514\",[242,45.154]],[\"parent/514\",[385,4.865]],[\"name/515\",[247,54.027]],[\"parent/515\",[385,4.865]],[\"name/516\",[386,57.391]],[\"parent/516\",[]],[\"name/517\",[1,24.582]],[\"parent/517\",[386,5.168]],[\"name/518\",[95,39.146]],[\"parent/518\",[387,4.865]],[\"name/519\",[242,45.154]],[\"parent/519\",[387,4.865]],[\"name/520\",[388,62.5]],[\"parent/520\",[387,4.865]],[\"name/521\",[389,57.391]],[\"parent/521\",[]],[\"name/522\",[1,24.582]],[\"parent/522\",[389,5.168]],[\"name/523\",[139,31.145]],[\"parent/523\",[390,4.639]],[\"name/524\",[95,39.146]],[\"parent/524\",[390,4.639]],[\"name/525\",[242,45.154]],[\"parent/525\",[390,4.639]],[\"name/526\",[211,54.027]],[\"parent/526\",[390,4.639]],[\"name/527\",[391,57.391]],[\"parent/527\",[]],[\"name/528\",[1,24.582]],[\"parent/528\",[391,5.168]],[\"name/529\",[139,31.145]],[\"parent/529\",[392,4.639]],[\"name/530\",[95,39.146]],[\"parent/530\",[392,4.639]],[\"name/531\",[242,45.154]],[\"parent/531\",[392,4.639]],[\"name/532\",[259,57.391]],[\"parent/532\",[392,4.639]],[\"name/533\",[393,57.391]],[\"parent/533\",[]],[\"name/534\",[1,24.582]],[\"parent/534\",[393,5.168]],[\"name/535\",[139,31.145]],[\"parent/535\",[394,4.458]],[\"name/536\",[95,39.146]],[\"parent/536\",[394,4.458]],[\"name/537\",[336,49.507]],[\"parent/537\",[394,4.458]],[\"name/538\",[245,51.514]],[\"parent/538\",[394,4.458]],[\"name/539\",[395,57.391]],[\"parent/539\",[394,4.458]],[\"name/540\",[396,57.391]],[\"parent/540\",[]],[\"name/541\",[1,24.582]],[\"parent/541\",[396,5.168]],[\"name/542\",[139,31.145]],[\"parent/542\",[397,4.639]],[\"name/543\",[336,49.507]],[\"parent/543\",[397,4.639]],[\"name/544\",[362,54.027]],[\"parent/544\",[397,4.639]],[\"name/545\",[395,57.391]],[\"parent/545\",[397,4.639]],[\"name/546\",[398,57.391]],[\"parent/546\",[]],[\"name/547\",[1,24.582]],[\"parent/547\",[398,5.168]],[\"name/548\",[139,31.145]],[\"parent/548\",[399,4.458]],[\"name/549\",[336,49.507]],[\"parent/549\",[399,4.458]],[\"name/550\",[400,62.5]],[\"parent/550\",[399,4.458]],[\"name/551\",[362,54.027]],[\"parent/551\",[399,4.458]],[\"name/552\",[253,57.391]],[\"parent/552\",[399,4.458]],[\"name/553\",[401,57.391]],[\"parent/553\",[]],[\"name/554\",[1,24.582]],[\"parent/554\",[401,5.168]],[\"name/555\",[95,39.146]],[\"parent/555\",[402,4.865]],[\"name/556\",[245,51.514]],[\"parent/556\",[402,4.865]],[\"name/557\",[403,62.5]],[\"parent/557\",[402,4.865]],[\"name/558\",[404,57.391]],[\"parent/558\",[]],[\"name/559\",[1,24.582]],[\"parent/559\",[404,5.168]],[\"name/560\",[405,62.5]],[\"parent/560\",[406,4.066]],[\"name/561\",[158,57.391]],[\"parent/561\",[406,4.066]],[\"name/562\",[159,57.391]],[\"parent/562\",[406,4.066]],[\"name/563\",[161,54.027]],[\"parent/563\",[406,4.066]],[\"name/564\",[160,49.507]],[\"parent/564\",[406,4.066]],[\"name/565\",[407,62.5]],[\"parent/565\",[406,4.066]],[\"name/566\",[408,62.5]],[\"parent/566\",[406,4.066]],[\"name/567\",[409,62.5]],[\"parent/567\",[406,4.066]],[\"name/568\",[410,62.5]],[\"parent/568\",[]],[\"name/569\",[411,57.391]],[\"parent/569\",[]],[\"name/570\",[1,24.582]],[\"parent/570\",[411,5.168]],[\"name/571\",[139,31.145]],[\"parent/571\",[412,4.639]],[\"name/572\",[141,37.377]],[\"parent/572\",[412,4.639]],[\"name/573\",[413,62.5]],[\"parent/573\",[412,4.639]],[\"name/574\",[414,62.5]],[\"parent/574\",[412,4.639]],[\"name/575\",[415,57.391]],[\"parent/575\",[]],[\"name/576\",[1,24.582]],[\"parent/576\",[415,5.168]],[\"name/577\",[376,54.027]],[\"parent/577\",[416,4.458]],[\"name/578\",[417,62.5]],[\"parent/578\",[416,4.458]],[\"name/579\",[418,62.5]],[\"parent/579\",[416,4.458]],[\"name/580\",[419,51.514]],[\"parent/580\",[416,4.458]],[\"name/581\",[354,45.154]],[\"parent/581\",[416,4.458]],[\"name/582\",[420,57.391]],[\"parent/582\",[]],[\"name/583\",[1,24.582]],[\"parent/583\",[420,5.168]],[\"name/584\",[376,54.027]],[\"parent/584\",[421,4.458]],[\"name/585\",[237,51.514]],[\"parent/585\",[421,4.458]],[\"name/586\",[299,57.391]],[\"parent/586\",[421,4.458]],[\"name/587\",[419,51.514]],[\"parent/587\",[421,4.458]],[\"name/588\",[324,51.514]],[\"parent/588\",[421,4.458]],[\"name/589\",[422,57.391]],[\"parent/589\",[]],[\"name/590\",[1,24.582]],[\"parent/590\",[422,5.168]],[\"name/591\",[139,31.145]],[\"parent/591\",[423,3.966]],[\"name/592\",[424,62.5]],[\"parent/592\",[423,3.966]],[\"name/593\",[237,51.514]],[\"parent/593\",[423,3.966]],[\"name/594\",[419,51.514]],[\"parent/594\",[423,3.966]],[\"name/595\",[425,57.391]],[\"parent/595\",[423,3.966]],[\"name/596\",[426,57.391]],[\"parent/596\",[423,3.966]],[\"name/597\",[127,49.507]],[\"parent/597\",[423,3.966]],[\"name/598\",[128,49.507]],[\"parent/598\",[423,3.966]],[\"name/599\",[354,45.154]],[\"parent/599\",[423,3.966]],[\"name/600\",[427,57.391]],[\"parent/600\",[]],[\"name/601\",[1,24.582]],[\"parent/601\",[427,5.168]],[\"name/602\",[428,62.5]],[\"parent/602\",[429,4.308]],[\"name/603\",[237,51.514]],[\"parent/603\",[429,4.308]],[\"name/604\",[419,51.514]],[\"parent/604\",[429,4.308]],[\"name/605\",[425,57.391]],[\"parent/605\",[429,4.308]],[\"name/606\",[426,57.391]],[\"parent/606\",[429,4.308]],[\"name/607\",[324,51.514]],[\"parent/607\",[429,4.308]],[\"name/608\",[430,57.391]],[\"parent/608\",[]],[\"name/609\",[1,24.582]],[\"parent/609\",[430,5.168]],[\"name/610\",[324,51.514]],[\"parent/610\",[431,4.639]],[\"name/611\",[432,62.5]],[\"parent/611\",[431,4.639]],[\"name/612\",[327,51.514]],[\"parent/612\",[431,4.639]],[\"name/613\",[433,62.5]],[\"parent/613\",[431,4.639]],[\"name/614\",[434,62.5]],[\"parent/614\",[]],[\"name/615\",[435,62.5]],[\"parent/615\",[]],[\"name/616\",[436,51.514]],[\"parent/616\",[]],[\"name/617\",[305,57.391]],[\"parent/617\",[436,4.639]],[\"name/618\",[123,51.514]],[\"parent/618\",[436,4.639]],[\"name/619\",[124,51.514]],[\"parent/619\",[436,4.639]],[\"name/620\",[437,62.5]],[\"parent/620\",[]],[\"name/621\",[194,54.027]],[\"parent/621\",[]],[\"name/622\",[1,24.582]],[\"parent/622\",[194,4.865]],[\"name/623\",[438,62.5]],[\"parent/623\",[439,4.865]],[\"name/624\",[440,62.5]],[\"parent/624\",[439,4.865]],[\"name/625\",[441,62.5]],[\"parent/625\",[439,4.865]],[\"name/626\",[442,57.391]],[\"parent/626\",[]],[\"name/627\",[1,24.582]],[\"parent/627\",[442,5.168]],[\"name/628\",[443,62.5]],[\"parent/628\",[444,5.628]],[\"name/629\",[445,57.391]],[\"parent/629\",[]],[\"name/630\",[1,24.582]],[\"parent/630\",[445,5.168]],[\"name/631\",[446,62.5]],[\"parent/631\",[447,5.628]],[\"name/632\",[448,57.391]],[\"parent/632\",[]],[\"name/633\",[1,24.582]],[\"parent/633\",[448,5.168]],[\"name/634\",[449,62.5]],[\"parent/634\",[450,4.865]],[\"name/635\",[451,62.5]],[\"parent/635\",[450,4.865]],[\"name/636\",[452,62.5]],[\"parent/636\",[450,4.865]],[\"name/637\",[453,51.514]],[\"parent/637\",[]],[\"name/638\",[454,62.5]],[\"parent/638\",[453,4.639]],[\"name/639\",[455,62.5]],[\"parent/639\",[453,4.639]],[\"name/640\",[14,40.528]],[\"parent/640\",[453,4.639]],[\"name/641\",[456,49.507]],[\"parent/641\",[]],[\"name/642\",[457,62.5]],[\"parent/642\",[456,4.458]],[\"name/643\",[458,62.5]],[\"parent/643\",[456,4.458]],[\"name/644\",[459,62.5]],[\"parent/644\",[456,4.458]],[\"name/645\",[14,40.528]],[\"parent/645\",[456,4.458]],[\"name/646\",[460,62.5]],[\"parent/646\",[]],[\"name/647\",[461,40.528]],[\"parent/647\",[]],[\"name/648\",[462,62.5]],[\"parent/648\",[461,3.65]],[\"name/649\",[61,51.514]],[\"parent/649\",[461,3.65]],[\"name/650\",[463,62.5]],[\"parent/650\",[461,3.65]],[\"name/651\",[63,54.027]],[\"parent/651\",[461,3.65]],[\"name/652\",[464,62.5]],[\"parent/652\",[461,3.65]],[\"name/653\",[465,62.5]],[\"parent/653\",[461,3.65]],[\"name/654\",[65,54.027]],[\"parent/654\",[461,3.65]],[\"name/655\",[466,62.5]],[\"parent/655\",[461,3.65]],[\"name/656\",[467,62.5]],[\"parent/656\",[461,3.65]],[\"name/657\",[73,54.027]],[\"parent/657\",[461,3.65]],[\"name/658\",[468,62.5]],[\"parent/658\",[461,3.65]],[\"name/659\",[14,40.528]],[\"parent/659\",[461,3.65]],[\"name/660\",[469,62.5]],[\"parent/660\",[]],[\"name/661\",[470,43.041]],[\"parent/661\",[]],[\"name/662\",[471,62.5]],[\"parent/662\",[470,3.876]],[\"name/663\",[472,62.5]],[\"parent/663\",[470,3.876]],[\"name/664\",[473,62.5]],[\"parent/664\",[470,3.876]],[\"name/665\",[474,62.5]],[\"parent/665\",[470,3.876]],[\"name/666\",[475,62.5]],[\"parent/666\",[470,3.876]],[\"name/667\",[476,62.5]],[\"parent/667\",[470,3.876]],[\"name/668\",[477,62.5]],[\"parent/668\",[470,3.876]],[\"name/669\",[478,62.5]],[\"parent/669\",[470,3.876]],[\"name/670\",[479,62.5]],[\"parent/670\",[470,3.876]],[\"name/671\",[480,57.391]],[\"parent/671\",[]],[\"name/672\",[1,24.582]],[\"parent/672\",[480,5.168]],[\"name/673\",[481,57.391]],[\"parent/673\",[482,5.168]],[\"name/674\",[483,57.391]],[\"parent/674\",[482,5.168]],[\"name/675\",[484,43.041]],[\"parent/675\",[]],[\"name/676\",[485,62.5]],[\"parent/676\",[484,3.876]],[\"name/677\",[486,62.5]],[\"parent/677\",[484,3.876]],[\"name/678\",[487,62.5]],[\"parent/678\",[484,3.876]],[\"name/679\",[488,62.5]],[\"parent/679\",[484,3.876]],[\"name/680\",[489,62.5]],[\"parent/680\",[484,3.876]],[\"name/681\",[490,62.5]],[\"parent/681\",[484,3.876]],[\"name/682\",[491,62.5]],[\"parent/682\",[484,3.876]],[\"name/683\",[492,62.5]],[\"parent/683\",[484,3.876]],[\"name/684\",[493,62.5]],[\"parent/684\",[484,3.876]],[\"name/685\",[494,42.131]],[\"parent/685\",[]],[\"name/686\",[495,62.5]],[\"parent/686\",[494,3.794]],[\"name/687\",[496,62.5]],[\"parent/687\",[494,3.794]],[\"name/688\",[497,62.5]],[\"parent/688\",[494,3.794]],[\"name/689\",[498,62.5]],[\"parent/689\",[494,3.794]],[\"name/690\",[499,62.5]],[\"parent/690\",[494,3.794]],[\"name/691\",[500,62.5]],[\"parent/691\",[494,3.794]],[\"name/692\",[501,62.5]],[\"parent/692\",[494,3.794]],[\"name/693\",[502,62.5]],[\"parent/693\",[494,3.794]],[\"name/694\",[503,62.5]],[\"parent/694\",[494,3.794]],[\"name/695\",[14,40.528]],[\"parent/695\",[494,3.794]],[\"name/696\",[504,49.507]],[\"parent/696\",[]],[\"name/697\",[505,62.5]],[\"parent/697\",[504,4.458]],[\"name/698\",[160,49.507]],[\"parent/698\",[504,4.458]],[\"name/699\",[125,51.514]],[\"parent/699\",[504,4.458]],[\"name/700\",[268,47.836]],[\"parent/700\",[504,4.458]],[\"name/701\",[506,42.131]],[\"parent/701\",[]],[\"name/702\",[507,62.5]],[\"parent/702\",[506,3.794]],[\"name/703\",[508,62.5]],[\"parent/703\",[506,3.794]],[\"name/704\",[509,62.5]],[\"parent/704\",[506,3.794]],[\"name/705\",[510,62.5]],[\"parent/705\",[506,3.794]],[\"name/706\",[64,54.027]],[\"parent/706\",[506,3.794]],[\"name/707\",[511,62.5]],[\"parent/707\",[506,3.794]],[\"name/708\",[512,62.5]],[\"parent/708\",[506,3.794]],[\"name/709\",[513,62.5]],[\"parent/709\",[506,3.794]],[\"name/710\",[514,62.5]],[\"parent/710\",[506,3.794]],[\"name/711\",[14,40.528]],[\"parent/711\",[506,3.794]],[\"name/712\",[515,40.528]],[\"parent/712\",[]],[\"name/713\",[516,62.5]],[\"parent/713\",[515,3.65]],[\"name/714\",[517,62.5]],[\"parent/714\",[515,3.65]],[\"name/715\",[518,62.5]],[\"parent/715\",[515,3.65]],[\"name/716\",[519,62.5]],[\"parent/716\",[515,3.65]],[\"name/717\",[520,62.5]],[\"parent/717\",[515,3.65]],[\"name/718\",[521,62.5]],[\"parent/718\",[515,3.65]],[\"name/719\",[522,62.5]],[\"parent/719\",[515,3.65]],[\"name/720\",[523,62.5]],[\"parent/720\",[515,3.65]],[\"name/721\",[524,62.5]],[\"parent/721\",[515,3.65]],[\"name/722\",[525,62.5]],[\"parent/722\",[515,3.65]],[\"name/723\",[526,62.5]],[\"parent/723\",[515,3.65]],[\"name/724\",[527,62.5]],[\"parent/724\",[515,3.65]],[\"name/725\",[528,46.405]],[\"parent/725\",[]],[\"name/726\",[529,62.5]],[\"parent/726\",[528,4.179]],[\"name/727\",[530,62.5]],[\"parent/727\",[528,4.179]],[\"name/728\",[531,62.5]],[\"parent/728\",[528,4.179]],[\"name/729\",[532,62.5]],[\"parent/729\",[528,4.179]],[\"name/730\",[533,62.5]],[\"parent/730\",[528,4.179]],[\"name/731\",[14,40.528]],[\"parent/731\",[528,4.179]],[\"name/732\",[534,54.027]],[\"parent/732\",[]],[\"name/733\",[160,49.507]],[\"parent/733\",[534,4.865]],[\"name/734\",[535,62.5]],[\"parent/734\",[534,4.865]],[\"name/735\",[536,54.027]],[\"parent/735\",[]],[\"name/736\",[481,57.391]],[\"parent/736\",[536,4.865]],[\"name/737\",[483,57.391]],[\"parent/737\",[536,4.865]],[\"name/738\",[537,62.5]],[\"parent/738\",[]],[\"name/739\",[538,42.131]],[\"parent/739\",[]],[\"name/740\",[539,62.5]],[\"parent/740\",[538,3.794]],[\"name/741\",[540,62.5]],[\"parent/741\",[538,3.794]],[\"name/742\",[541,62.5]],[\"parent/742\",[538,3.794]],[\"name/743\",[59,54.027]],[\"parent/743\",[538,3.794]],[\"name/744\",[60,54.027]],[\"parent/744\",[538,3.794]],[\"name/745\",[61,51.514]],[\"parent/745\",[538,3.794]],[\"name/746\",[62,54.027]],[\"parent/746\",[538,3.794]],[\"name/747\",[542,62.5]],[\"parent/747\",[538,3.794]],[\"name/748\",[543,62.5]],[\"parent/748\",[538,3.794]],[\"name/749\",[544,62.5]],[\"parent/749\",[538,3.794]],[\"name/750\",[139,31.145]],[\"parent/750\",[]],[\"name/751\",[545,57.391]],[\"parent/751\",[139,2.805]],[\"name/752\",[546,57.391]],[\"parent/752\",[139,2.805]],[\"name/753\",[547,57.391]],[\"parent/753\",[139,2.805]],[\"name/754\",[548,62.5]],[\"parent/754\",[139,2.805]],[\"name/755\",[549,62.5]],[\"parent/755\",[139,2.805]],[\"name/756\",[550,62.5]],[\"parent/756\",[139,2.805]],[\"name/757\",[551,62.5]],[\"parent/757\",[139,2.805]],[\"name/758\",[552,62.5]],[\"parent/758\",[139,2.805]],[\"name/759\",[553,62.5]],[\"parent/759\",[139,2.805]],[\"name/760\",[554,62.5]],[\"parent/760\",[139,2.805]],[\"name/761\",[555,62.5]],[\"parent/761\",[139,2.805]],[\"name/762\",[556,62.5]],[\"parent/762\",[139,2.805]],[\"name/763\",[216,57.391]],[\"parent/763\",[139,2.805]],[\"name/764\",[557,62.5]],[\"parent/764\",[139,2.805]],[\"name/765\",[141,37.377]],[\"parent/765\",[]],[\"name/766\",[545,57.391]],[\"parent/766\",[141,3.366]],[\"name/767\",[546,57.391]],[\"parent/767\",[141,3.366]],[\"name/768\",[558,62.5]],[\"parent/768\",[141,3.366]],[\"name/769\",[559,62.5]],[\"parent/769\",[141,3.366]],[\"name/770\",[560,62.5]],[\"parent/770\",[141,3.366]],[\"name/771\",[547,57.391]],[\"parent/771\",[141,3.366]],[\"name/772\",[561,62.5]],[\"parent/772\",[141,3.366]],[\"name/773\",[562,62.5]],[\"parent/773\",[141,3.366]],[\"name/774\",[563,62.5]],[\"parent/774\",[141,3.366]],[\"name/775\",[564,62.5]],[\"parent/775\",[141,3.366]]],\"invertedIndex\":[[\"__type\",{\"_index\":1,\"name\":{\"1\":{},\"7\":{},\"118\":{},\"124\":{},\"128\":{},\"152\":{},\"166\":{},\"176\":{},\"182\":{},\"187\":{},\"198\":{},\"208\":{},\"221\":{},\"227\":{},\"233\":{},\"238\":{},\"245\":{},\"258\":{},\"273\":{},\"297\":{},\"304\":{},\"311\":{},\"314\":{},\"334\":{},\"339\":{},\"347\":{},\"351\":{},\"354\":{},\"358\":{},\"370\":{},\"375\":{},\"382\":{},\"401\":{},\"408\":{},\"418\":{},\"427\":{},\"436\":{},\"443\":{},\"449\":{},\"457\":{},\"465\":{},\"473\":{},\"485\":{},\"491\":{},\"501\":{},\"506\":{},\"512\":{},\"517\":{},\"522\":{},\"528\":{},\"534\":{},\"541\":{},\"547\":{},\"554\":{},\"559\":{},\"570\":{},\"576\":{},\"583\":{},\"590\":{},\"601\":{},\"609\":{},\"622\":{},\"627\":{},\"630\":{},\"633\":{},\"672\":{}},\"parent\":{}}],[\"accountname\",{\"_index\":234,\"name\":{\"286\":{}},\"parent\":{\"287\":{},\"288\":{},\"289\":{},\"290\":{},\"291\":{},\"292\":{}}}],[\"accountresolveroptions\",{\"_index\":6,\"name\":{\"5\":{},\"6\":{}},\"parent\":{\"7\":{}}}],[\"accountresolveroptions.__type\",{\"_index\":8,\"name\":{},\"parent\":{\"8\":{},\"9\":{}}}],[\"accountresolveropts\",{\"_index\":23,\"name\":{\"23\":{}},\"parent\":{}}],[\"address\",{\"_index\":305,\"name\":{\"383\":{},\"617\":{}},\"parent\":{}}],[\"allowpdaowneraddress\",{\"_index\":9,\"name\":{\"9\":{}},\"parent\":{}}],[\"amount\",{\"_index\":405,\"name\":{\"560\":{}},\"parent\":{}}],[\"amountin\",{\"_index\":197,\"name\":{\"241\":{},\"246\":{}},\"parent\":{}}],[\"amountout\",{\"_index\":97,\"name\":{\"125\":{},\"242\":{},\"247\":{}},\"parent\":{}}],[\"amountowed\",{\"_index\":284,\"name\":{\"349\":{}},\"parent\":{}}],[\"amountspecifiedisinput\",{\"_index\":161,\"name\":{\"204\":{},\"225\":{},\"563\":{}},\"parent\":{}}],[\"ataaccountinfo\",{\"_index\":220,\"name\":{\"271\":{}},\"parent\":{}}],[\"atob\",{\"_index\":160,\"name\":{\"203\":{},\"259\":{},\"564\":{},\"698\":{},\"733\":{}},\"parent\":{}}],[\"authority\",{\"_index\":252,\"name\":{\"307\":{}},\"parent\":{}}],[\"availableataaccounts\",{\"_index\":225,\"name\":{\"276\":{}},\"parent\":{}}],[\"btoa\",{\"_index\":535,\"name\":{\"734\":{}},\"parent\":{}}],[\"builddefaultaccountfetcher\",{\"_index\":56,\"name\":{\"57\":{}},\"parent\":{}}],[\"buildpoolgraph\",{\"_index\":455,\"name\":{\"639\":{}},\"parent\":{}}],[\"buildpoolgraphwithfetch\",{\"_index\":454,\"name\":{\"638\":{}},\"parent\":{}}],[\"buildwhirlpoolclient\",{\"_index\":537,\"name\":{\"738\":{}},\"parent\":{}}],[\"buildwithpoolgraph\",{\"_index\":218,\"name\":{\"268\":{}},\"parent\":{}}],[\"buildwithpools\",{\"_index\":219,\"name\":{\"269\":{}},\"parent\":{}}],[\"bundledposition\",{\"_index\":428,\"name\":{\"602\":{}},\"parent\":{}}],[\"bundledpositionpda\",{\"_index\":424,\"name\":{\"592\":{}},\"parent\":{}}],[\"bundleindex\",{\"_index\":426,\"name\":{\"596\":{},\"606\":{}},\"parent\":{}}],[\"calculateswapamountsfromquote\",{\"_index\":512,\"name\":{\"708\":{}},\"parent\":{}}],[\"calculatetokenprices\",{\"_index\":112,\"name\":{\"142\":{}},\"parent\":{}}],[\"checkbundleindexinbounds\",{\"_index\":485,\"name\":{\"676\":{}},\"parent\":{}}],[\"checktickinbounds\",{\"_index\":523,\"name\":{\"720\":{}},\"parent\":{}}],[\"closebundledpositionix\",{\"_index\":55,\"name\":{\"55\":{}},\"parent\":{}}],[\"closebundledpositionparams\",{\"_index\":427,\"name\":{\"600\":{}},\"parent\":{\"601\":{}}}],[\"closebundledpositionparams.__type\",{\"_index\":429,\"name\":{},\"parent\":{\"602\":{},\"603\":{},\"604\":{},\"605\":{},\"606\":{},\"607\":{}}}],[\"closeposition\",{\"_index\":556,\"name\":{\"762\":{}},\"parent\":{}}],[\"closepositionix\",{\"_index\":34,\"name\":{\"34\":{}},\"parent\":{}}],[\"closepositionparams\",{\"_index\":323,\"name\":{\"400\":{}},\"parent\":{\"401\":{}}}],[\"closepositionparams.__type\",{\"_index\":325,\"name\":{},\"parent\":{\"402\":{},\"403\":{},\"404\":{},\"405\":{},\"406\":{}}}],[\"collectallparams\",{\"_index\":430,\"name\":{\"608\":{}},\"parent\":{\"609\":{}}}],[\"collectallparams.__type\",{\"_index\":431,\"name\":{},\"parent\":{\"610\":{},\"611\":{},\"612\":{},\"613\":{}}}],[\"collectallpositionaddressparams\",{\"_index\":434,\"name\":{\"614\":{}},\"parent\":{}}],[\"collectallpositionparams\",{\"_index\":435,\"name\":{\"615\":{}},\"parent\":{}}],[\"collectfees\",{\"_index\":563,\"name\":{\"774\":{}},\"parent\":{}}],[\"collectfeesandrewardsforpositions\",{\"_index\":542,\"name\":{\"747\":{}},\"parent\":{}}],[\"collectfeesix\",{\"_index\":38,\"name\":{\"38\":{}},\"parent\":{}}],[\"collectfeesparams\",{\"_index\":328,\"name\":{\"407\":{}},\"parent\":{\"408\":{}}}],[\"collectfeesparams.__type\",{\"_index\":329,\"name\":{},\"parent\":{\"409\":{},\"410\":{},\"411\":{},\"412\":{},\"413\":{},\"414\":{},\"415\":{},\"416\":{}}}],[\"collectfeesquote\",{\"_index\":137,\"name\":{\"174\":{},\"181\":{}},\"parent\":{\"182\":{}}}],[\"collectfeesquote.__type\",{\"_index\":145,\"name\":{},\"parent\":{\"183\":{},\"184\":{}}}],[\"collectfeesquoteparam\",{\"_index\":138,\"name\":{\"175\":{}},\"parent\":{\"176\":{}}}],[\"collectfeesquoteparam.__type\",{\"_index\":140,\"name\":{},\"parent\":{\"177\":{},\"178\":{},\"179\":{},\"180\":{}}}],[\"collectprotocolfeesauthority\",{\"_index\":244,\"name\":{\"299\":{},\"425\":{},\"452\":{},\"503\":{}},\"parent\":{}}],[\"collectprotocolfeesforpools\",{\"_index\":544,\"name\":{\"749\":{}},\"parent\":{}}],[\"collectprotocolfeesix\",{\"_index\":39,\"name\":{\"39\":{}},\"parent\":{}}],[\"collectprotocolfeesparams\",{\"_index\":332,\"name\":{\"417\":{}},\"parent\":{\"418\":{}}}],[\"collectprotocolfeesparams.__type\",{\"_index\":333,\"name\":{},\"parent\":{\"419\":{},\"420\":{},\"421\":{},\"422\":{},\"423\":{},\"424\":{},\"425\":{}}}],[\"collectrewardix\",{\"_index\":40,\"name\":{\"40\":{}},\"parent\":{}}],[\"collectrewardparams\",{\"_index\":334,\"name\":{\"426\":{}},\"parent\":{\"427\":{}}}],[\"collectrewardparams.__type\",{\"_index\":335,\"name\":{},\"parent\":{\"428\":{},\"429\":{},\"430\":{},\"431\":{},\"432\":{},\"433\":{},\"434\":{}}}],[\"collectrewards\",{\"_index\":564,\"name\":{\"775\":{}},\"parent\":{}}],[\"collectrewardsquote\",{\"_index\":147,\"name\":{\"185\":{},\"193\":{}},\"parent\":{}}],[\"collectrewardsquoteparam\",{\"_index\":148,\"name\":{\"186\":{}},\"parent\":{\"187\":{}}}],[\"collectrewardsquoteparam.__type\",{\"_index\":149,\"name\":{},\"parent\":{\"188\":{},\"189\":{},\"190\":{},\"191\":{},\"192\":{}}}],[\"comparemints\",{\"_index\":476,\"name\":{\"667\":{}},\"parent\":{}}],[\"connection\",{\"_index\":15,\"name\":{\"15\":{},\"60\":{}},\"parent\":{}}],[\"constructor\",{\"_index\":14,\"name\":{\"14\":{},\"56\":{},\"59\":{},\"143\":{},\"148\":{},\"270\":{},\"284\":{},\"640\":{},\"645\":{},\"659\":{},\"695\":{},\"711\":{},\"731\":{}},\"parent\":{}}],[\"convertbitmaptoarray\",{\"_index\":493,\"name\":{\"684\":{}},\"parent\":{}}],[\"createpool\",{\"_index\":543,\"name\":{\"748\":{}},\"parent\":{}}],[\"createwrappedsolaccountmethod\",{\"_index\":7,\"name\":{\"8\":{}},\"parent\":{}}],[\"data\",{\"_index\":307,\"name\":{\"384\":{}},\"parent\":{}}],[\"decimalsmap\",{\"_index\":104,\"name\":{\"131\":{},\"135\":{}},\"parent\":{}}],[\"deconstructpathid\",{\"_index\":459,\"name\":{\"644\":{}},\"parent\":{}}],[\"decreaseliquidity\",{\"_index\":562,\"name\":{\"773\":{}},\"parent\":{}}],[\"decreaseliquidityinput\",{\"_index\":339,\"name\":{\"435\":{}},\"parent\":{\"436\":{}}}],[\"decreaseliquidityinput.__type\",{\"_index\":341,\"name\":{},\"parent\":{\"437\":{},\"438\":{},\"439\":{}}}],[\"decreaseliquidityix\",{\"_index\":33,\"name\":{\"33\":{}},\"parent\":{}}],[\"decreaseliquidityparams\",{\"_index\":344,\"name\":{\"440\":{}},\"parent\":{}}],[\"decreaseliquidityquote\",{\"_index\":136,\"name\":{\"173\":{}},\"parent\":{}}],[\"decreaseliquidityquotebyliquidity\",{\"_index\":131,\"name\":{\"163\":{}},\"parent\":{}}],[\"decreaseliquidityquotebyliquiditywithparams\",{\"_index\":132,\"name\":{\"164\":{}},\"parent\":{}}],[\"decreaseliquidityquoteparam\",{\"_index\":133,\"name\":{\"165\":{}},\"parent\":{\"166\":{}}}],[\"decreaseliquidityquoteparam.__type\",{\"_index\":135,\"name\":{},\"parent\":{\"167\":{},\"168\":{},\"169\":{},\"170\":{},\"171\":{},\"172\":{}}}],[\"default_whirlpool_retention_policy\",{\"_index\":77,\"name\":{\"81\":{}},\"parent\":{}}],[\"defaultfeerate\",{\"_index\":246,\"name\":{\"301\":{},\"373\":{},\"461\":{},\"510\":{}},\"parent\":{}}],[\"defaultgetpricesconfig\",{\"_index\":107,\"name\":{\"137\":{}},\"parent\":{}}],[\"defaultgetpricesthresholdconfig\",{\"_index\":108,\"name\":{\"138\":{}},\"parent\":{}}],[\"defaultprotocolfeerate\",{\"_index\":247,\"name\":{\"302\":{},\"454\":{},\"515\":{}},\"parent\":{}}],[\"defaultquotetokens\",{\"_index\":106,\"name\":{\"136\":{}},\"parent\":{}}],[\"deletepositionbundleix\",{\"_index\":53,\"name\":{\"53\":{}},\"parent\":{}}],[\"deletepositionbundleparams\",{\"_index\":420,\"name\":{\"582\":{}},\"parent\":{\"583\":{}}}],[\"deletepositionbundleparams.__type\",{\"_index\":421,\"name\":{},\"parent\":{\"584\":{},\"585\":{},\"586\":{},\"587\":{},\"588\":{}}}],[\"devfeeswapinput\",{\"_index\":345,\"name\":{\"441\":{}},\"parent\":{}}],[\"devfeeswapquote\",{\"_index\":173,\"name\":{\"216\":{}},\"parent\":{}}],[\"edge\",{\"_index\":442,\"name\":{\"626\":{}},\"parent\":{\"627\":{}}}],[\"edge.__type\",{\"_index\":444,\"name\":{},\"parent\":{\"628\":{}}}],[\"edges\",{\"_index\":441,\"name\":{\"625\":{}},\"parent\":{}}],[\"emissionspersecondx64\",{\"_index\":253,\"name\":{\"308\":{},\"552\":{}},\"parent\":{}}],[\"endtokenmint\",{\"_index\":440,\"name\":{\"624\":{}},\"parent\":{}}],[\"estimatedamountin\",{\"_index\":165,\"name\":{\"209\":{}},\"parent\":{}}],[\"estimatedamountout\",{\"_index\":167,\"name\":{\"210\":{}},\"parent\":{}}],[\"estimatedendsqrtprice\",{\"_index\":169,\"name\":{\"212\":{}},\"parent\":{}}],[\"estimatedendtickindex\",{\"_index\":168,\"name\":{\"211\":{}},\"parent\":{}}],[\"estimatedfeeamount\",{\"_index\":170,\"name\":{\"213\":{}},\"parent\":{}}],[\"estimateliquidityfromtokenamounts\",{\"_index\":478,\"name\":{\"669\":{}},\"parent\":{}}],[\"executableroute\",{\"_index\":212,\"name\":{\"262\":{}},\"parent\":{}}],[\"fee_rate_mul_value\",{\"_index\":321,\"name\":{\"398\":{}},\"parent\":{}}],[\"feeauthority\",{\"_index\":242,\"name\":{\"298\":{},\"451\":{},\"462\":{},\"508\":{},\"514\":{},\"519\":{},\"525\":{},\"531\":{}},\"parent\":{}}],[\"feegrowthcheckpointa\",{\"_index\":294,\"name\":{\"364\":{}},\"parent\":{}}],[\"feegrowthcheckpointb\",{\"_index\":295,\"name\":{\"366\":{}},\"parent\":{}}],[\"feegrowthglobala\",{\"_index\":263,\"name\":{\"326\":{}},\"parent\":{}}],[\"feegrowthglobalb\",{\"_index\":265,\"name\":{\"329\":{}},\"parent\":{}}],[\"feegrowthoutsidea\",{\"_index\":278,\"name\":{\"343\":{}},\"parent\":{}}],[\"feegrowthoutsideb\",{\"_index\":279,\"name\":{\"344\":{}},\"parent\":{}}],[\"feeoweda\",{\"_index\":144,\"name\":{\"183\":{},\"365\":{}},\"parent\":{}}],[\"feeowedb\",{\"_index\":146,\"name\":{\"184\":{},\"367\":{}},\"parent\":{}}],[\"feerate\",{\"_index\":211,\"name\":{\"261\":{},\"317\":{},\"526\":{}},\"parent\":{}}],[\"feetier\",{\"_index\":236,\"name\":{\"291\":{}},\"parent\":{}}],[\"feetierdata\",{\"_index\":296,\"name\":{\"369\":{}},\"parent\":{\"370\":{}}}],[\"feetierdata.__type\",{\"_index\":297,\"name\":{},\"parent\":{\"371\":{},\"372\":{},\"373\":{}}}],[\"feetierkey\",{\"_index\":369,\"name\":{\"481\":{}},\"parent\":{}}],[\"feetierpda\",{\"_index\":357,\"name\":{\"459\":{}},\"parent\":{}}],[\"fetchdecimalsformints\",{\"_index\":116,\"name\":{\"147\":{}},\"parent\":{}}],[\"fetcher\",{\"_index\":19,\"name\":{\"19\":{},\"61\":{}},\"parent\":{}}],[\"fetchpooldatafrommints\",{\"_index\":114,\"name\":{\"145\":{}},\"parent\":{}}],[\"fetchtickarraysforpools\",{\"_index\":115,\"name\":{\"146\":{}},\"parent\":{}}],[\"fetchtokenpricesbymints\",{\"_index\":110,\"name\":{\"140\":{}},\"parent\":{}}],[\"fetchtokenpricesbypools\",{\"_index\":111,\"name\":{\"141\":{}},\"parent\":{}}],[\"findallroutes\",{\"_index\":214,\"name\":{\"264\":{}},\"parent\":{}}],[\"findbestroute\",{\"_index\":215,\"name\":{\"265\":{}},\"parent\":{}}],[\"findnextinitializedtickindex\",{\"_index\":522,\"name\":{\"719\":{}},\"parent\":{}}],[\"findpreviousinitializedtickindex\",{\"_index\":521,\"name\":{\"718\":{}},\"parent\":{}}],[\"findunoccupiedbundleindex\",{\"_index\":492,\"name\":{\"683\":{}},\"parent\":{}}],[\"from\",{\"_index\":11,\"name\":{\"11\":{}},\"parent\":{}}],[\"fromworkspace\",{\"_index\":12,\"name\":{\"12\":{}},\"parent\":{}}],[\"funder\",{\"_index\":354,\"name\":{\"455\":{},\"463\":{},\"471\":{},\"483\":{},\"489\":{},\"499\":{},\"581\":{},\"599\":{}},\"parent\":{}}],[\"getaccountrentexempt\",{\"_index\":58,\"name\":{\"62\":{},\"86\":{}},\"parent\":{}}],[\"getaccountsize\",{\"_index\":233,\"name\":{\"285\":{}},\"parent\":{}}],[\"getaddress\",{\"_index\":545,\"name\":{\"751\":{},\"766\":{}},\"parent\":{}}],[\"getallpaths\",{\"_index\":452,\"name\":{\"636\":{}},\"parent\":{}}],[\"getallwhirlpoolaccountsforconfig\",{\"_index\":82,\"name\":{\"104\":{}},\"parent\":{}}],[\"getbatchtickarrays\",{\"_index\":511,\"name\":{\"707\":{}},\"parent\":{}}],[\"getbundledposition\",{\"_index\":467,\"name\":{\"656\":{}},\"parent\":{}}],[\"getconfig\",{\"_index\":71,\"name\":{\"75\":{},\"99\":{}},\"parent\":{}}],[\"getconfigs\",{\"_index\":72,\"name\":{\"76\":{},\"100\":{}},\"parent\":{}}],[\"getcontext\",{\"_index\":539,\"name\":{\"740\":{}},\"parent\":{}}],[\"getdata\",{\"_index\":546,\"name\":{\"752\":{},\"767\":{}},\"parent\":{}}],[\"getdefaultotheramountthreshold\",{\"_index\":508,\"name\":{\"703\":{}},\"parent\":{}}],[\"getdefaultrouteoptions\",{\"_index\":231,\"name\":{\"282\":{}},\"parent\":{}}],[\"getdefaultselectoptions\",{\"_index\":232,\"name\":{\"283\":{}},\"parent\":{}}],[\"getdefaultsqrtpricelimit\",{\"_index\":507,\"name\":{\"702\":{}},\"parent\":{}}],[\"getfeerate\",{\"_index\":473,\"name\":{\"664\":{}},\"parent\":{}}],[\"getfeetier\",{\"_index\":65,\"name\":{\"69\":{},\"93\":{},\"654\":{}},\"parent\":{}}],[\"getfeetiers\",{\"_index\":66,\"name\":{\"70\":{},\"94\":{}},\"parent\":{}}],[\"getfetcher\",{\"_index\":540,\"name\":{\"741\":{}},\"parent\":{}}],[\"getfullrangetickindex\",{\"_index\":526,\"name\":{\"723\":{}},\"parent\":{}}],[\"getinitializabletickindex\",{\"_index\":518,\"name\":{\"715\":{}},\"parent\":{}}],[\"getlowertickdata\",{\"_index\":559,\"name\":{\"769\":{}},\"parent\":{}}],[\"getmintinfo\",{\"_index\":69,\"name\":{\"73\":{},\"97\":{}},\"parent\":{}}],[\"getmintinfos\",{\"_index\":70,\"name\":{\"74\":{},\"98\":{}},\"parent\":{}}],[\"getnextinitializabletickindex\",{\"_index\":519,\"name\":{\"716\":{}},\"parent\":{}}],[\"getoccupiedbundleindexes\",{\"_index\":490,\"name\":{\"681\":{}},\"parent\":{}}],[\"getoffsetindex\",{\"_index\":516,\"name\":{\"713\":{}},\"parent\":{}}],[\"getoracle\",{\"_index\":466,\"name\":{\"655\":{}},\"parent\":{}}],[\"getpath\",{\"_index\":449,\"name\":{\"634\":{}},\"parent\":{}}],[\"getpathsforpairs\",{\"_index\":451,\"name\":{\"635\":{}},\"parent\":{}}],[\"getpool\",{\"_index\":59,\"name\":{\"63\":{},\"87\":{},\"743\":{}},\"parent\":{}}],[\"getpools\",{\"_index\":60,\"name\":{\"64\":{},\"88\":{},\"744\":{}},\"parent\":{}}],[\"getposition\",{\"_index\":61,\"name\":{\"65\":{},\"89\":{},\"649\":{},\"745\":{}},\"parent\":{}}],[\"getpositionbundle\",{\"_index\":73,\"name\":{\"77\":{},\"101\":{},\"657\":{}},\"parent\":{}}],[\"getpositionbundlemetadata\",{\"_index\":468,\"name\":{\"658\":{}},\"parent\":{}}],[\"getpositionbundles\",{\"_index\":74,\"name\":{\"78\":{},\"102\":{}},\"parent\":{}}],[\"getpositionmetadata\",{\"_index\":463,\"name\":{\"650\":{}},\"parent\":{}}],[\"getpositions\",{\"_index\":62,\"name\":{\"66\":{},\"90\":{},\"746\":{}},\"parent\":{}}],[\"getprevinitializabletickindex\",{\"_index\":520,\"name\":{\"717\":{}},\"parent\":{}}],[\"getpriceimpactforroute\",{\"_index\":229,\"name\":{\"280\":{}},\"parent\":{}}],[\"getpricesconfig\",{\"_index\":90,\"name\":{\"117\":{}},\"parent\":{\"118\":{}}}],[\"getpricesconfig.__type\",{\"_index\":92,\"name\":{},\"parent\":{\"119\":{},\"120\":{},\"121\":{},\"122\":{}}}],[\"getpricesthresholdconfig\",{\"_index\":96,\"name\":{\"123\":{}},\"parent\":{\"124\":{}}}],[\"getpricesthresholdconfig.__type\",{\"_index\":98,\"name\":{},\"parent\":{\"125\":{},\"126\":{}}}],[\"getprotocolfeerate\",{\"_index\":474,\"name\":{\"665\":{}},\"parent\":{}}],[\"getrewardinfos\",{\"_index\":552,\"name\":{\"758\":{}},\"parent\":{}}],[\"getrouter\",{\"_index\":541,\"name\":{\"742\":{}},\"parent\":{}}],[\"getsearchpathid\",{\"_index\":458,\"name\":{\"643\":{}},\"parent\":{}}],[\"getstarttickindex\",{\"_index\":517,\"name\":{\"714\":{}},\"parent\":{}}],[\"getswapdirection\",{\"_index\":509,\"name\":{\"704\":{}},\"parent\":{}}],[\"getswapparamsfromquote\",{\"_index\":513,\"name\":{\"709\":{}},\"parent\":{}}],[\"getswapparamsfromquotekeys\",{\"_index\":514,\"name\":{\"710\":{}},\"parent\":{}}],[\"gettickarray\",{\"_index\":63,\"name\":{\"67\":{},\"91\":{},\"651\":{}},\"parent\":{}}],[\"gettickarrayfromsqrtprice\",{\"_index\":465,\"name\":{\"653\":{}},\"parent\":{}}],[\"gettickarrayfromtickindex\",{\"_index\":464,\"name\":{\"652\":{}},\"parent\":{}}],[\"gettickarraypdas\",{\"_index\":530,\"name\":{\"727\":{}},\"parent\":{}}],[\"gettickarraypublickeys\",{\"_index\":510,\"name\":{\"705\":{}},\"parent\":{}}],[\"gettickarrays\",{\"_index\":64,\"name\":{\"68\":{},\"92\":{},\"706\":{}},\"parent\":{}}],[\"gettickfromarray\",{\"_index\":529,\"name\":{\"726\":{}},\"parent\":{}}],[\"gettokenainfo\",{\"_index\":548,\"name\":{\"754\":{}},\"parent\":{}}],[\"gettokenamountsfromliquidity\",{\"_index\":477,\"name\":{\"668\":{}},\"parent\":{}}],[\"gettokenbinfo\",{\"_index\":549,\"name\":{\"755\":{}},\"parent\":{}}],[\"gettokeninfo\",{\"_index\":67,\"name\":{\"71\":{},\"95\":{}},\"parent\":{}}],[\"gettokeninfos\",{\"_index\":68,\"name\":{\"72\":{},\"96\":{}},\"parent\":{}}],[\"gettokentype\",{\"_index\":472,\"name\":{\"663\":{}},\"parent\":{}}],[\"gettokenvaultainfo\",{\"_index\":550,\"name\":{\"756\":{}},\"parent\":{}}],[\"gettokenvaultbinfo\",{\"_index\":551,\"name\":{\"757\":{}},\"parent\":{}}],[\"gettouchedtickarraysfromroute\",{\"_index\":230,\"name\":{\"281\":{}},\"parent\":{}}],[\"getuninitializedarrays\",{\"_index\":533,\"name\":{\"730\":{}},\"parent\":{}}],[\"getuninitializedarrayspdas\",{\"_index\":532,\"name\":{\"729\":{}},\"parent\":{}}],[\"getuninitializedarraysstring\",{\"_index\":531,\"name\":{\"728\":{}},\"parent\":{}}],[\"getunoccupiedbundleindexes\",{\"_index\":491,\"name\":{\"682\":{}},\"parent\":{}}],[\"getuppertickdata\",{\"_index\":560,\"name\":{\"770\":{}},\"parent\":{}}],[\"getwhirlpool\",{\"_index\":462,\"name\":{\"648\":{}},\"parent\":{}}],[\"getwhirlpooldata\",{\"_index\":558,\"name\":{\"768\":{}},\"parent\":{}}],[\"growthglobalx64\",{\"_index\":254,\"name\":{\"309\":{}},\"parent\":{}}],[\"growthinsidecheckpoint\",{\"_index\":282,\"name\":{\"348\":{}},\"parent\":{}}],[\"hopquotes\",{\"_index\":198,\"name\":{\"243\":{}},\"parent\":{}}],[\"ignore_cache\",{\"_index\":79,\"name\":{\"83\":{}},\"parent\":{}}],[\"increaseliquidity\",{\"_index\":561,\"name\":{\"772\":{}},\"parent\":{}}],[\"increaseliquidityinput\",{\"_index\":346,\"name\":{\"442\":{}},\"parent\":{\"443\":{}}}],[\"increaseliquidityinput.__type\",{\"_index\":348,\"name\":{},\"parent\":{\"444\":{},\"445\":{},\"446\":{}}}],[\"increaseliquidityix\",{\"_index\":32,\"name\":{\"32\":{}},\"parent\":{}}],[\"increaseliquidityparams\",{\"_index\":350,\"name\":{\"447\":{}},\"parent\":{}}],[\"increaseliquidityquote\",{\"_index\":130,\"name\":{\"162\":{}},\"parent\":{}}],[\"increaseliquidityquotebyinputtoken\",{\"_index\":117,\"name\":{\"149\":{}},\"parent\":{}}],[\"increaseliquidityquotebyinputtokenwithparams\",{\"_index\":118,\"name\":{\"150\":{}},\"parent\":{}}],[\"increaseliquidityquoteparam\",{\"_index\":119,\"name\":{\"151\":{}},\"parent\":{\"152\":{}}}],[\"increaseliquidityquoteparam.__type\",{\"_index\":121,\"name\":{},\"parent\":{\"153\":{},\"154\":{},\"155\":{},\"156\":{},\"157\":{},\"158\":{},\"159\":{},\"160\":{},\"161\":{}}}],[\"initconfigparams\",{\"_index\":351,\"name\":{\"448\":{}},\"parent\":{\"449\":{}}}],[\"initconfigparams.__type\",{\"_index\":353,\"name\":{},\"parent\":{\"450\":{},\"451\":{},\"452\":{},\"453\":{},\"454\":{},\"455\":{}}}],[\"initfeetierparams\",{\"_index\":355,\"name\":{\"456\":{}},\"parent\":{\"457\":{}}}],[\"initfeetierparams.__type\",{\"_index\":356,\"name\":{},\"parent\":{\"458\":{},\"459\":{},\"460\":{},\"461\":{},\"462\":{},\"463\":{}}}],[\"initializeconfigix\",{\"_index\":25,\"name\":{\"25\":{}},\"parent\":{}}],[\"initialized\",{\"_index\":274,\"name\":{\"340\":{}},\"parent\":{}}],[\"initializefeetierix\",{\"_index\":26,\"name\":{\"26\":{}},\"parent\":{}}],[\"initializepoolix\",{\"_index\":27,\"name\":{\"27\":{}},\"parent\":{}}],[\"initializepositionbundleix\",{\"_index\":51,\"name\":{\"51\":{}},\"parent\":{}}],[\"initializepositionbundleparams\",{\"_index\":415,\"name\":{\"575\":{}},\"parent\":{\"576\":{}}}],[\"initializepositionbundleparams.__type\",{\"_index\":416,\"name\":{},\"parent\":{\"577\":{},\"578\":{},\"579\":{},\"580\":{},\"581\":{}}}],[\"initializepositionbundlewithmetadataix\",{\"_index\":52,\"name\":{\"52\":{}},\"parent\":{}}],[\"initializerewardix\",{\"_index\":28,\"name\":{\"28\":{}},\"parent\":{}}],[\"initializerewardparams\",{\"_index\":358,\"name\":{\"464\":{}},\"parent\":{\"465\":{}}}],[\"initializerewardparams.__type\",{\"_index\":359,\"name\":{},\"parent\":{\"466\":{},\"467\":{},\"468\":{},\"469\":{},\"470\":{},\"471\":{}}}],[\"initpoolparams\",{\"_index\":363,\"name\":{\"472\":{}},\"parent\":{\"473\":{}}}],[\"initpoolparams.__type\",{\"_index\":365,\"name\":{},\"parent\":{\"474\":{},\"475\":{},\"476\":{},\"477\":{},\"478\":{},\"479\":{},\"480\":{},\"481\":{},\"482\":{},\"483\":{}}}],[\"initsqrtprice\",{\"_index\":364,\"name\":{\"474\":{}},\"parent\":{}}],[\"inittickarrayforticks\",{\"_index\":553,\"name\":{\"759\":{}},\"parent\":{}}],[\"inittickarrayix\",{\"_index\":29,\"name\":{\"29\":{}},\"parent\":{}}],[\"inittickarrayparams\",{\"_index\":370,\"name\":{\"484\":{}},\"parent\":{\"485\":{}}}],[\"inittickarrayparams.__type\",{\"_index\":371,\"name\":{},\"parent\":{\"486\":{},\"487\":{},\"488\":{},\"489\":{}}}],[\"inputmint\",{\"_index\":201,\"name\":{\"249\":{}},\"parent\":{}}],[\"inputtokenamount\",{\"_index\":120,\"name\":{\"153\":{}},\"parent\":{}}],[\"inputtokenmint\",{\"_index\":122,\"name\":{\"154\":{}},\"parent\":{}}],[\"intermediatetokens\",{\"_index\":446,\"name\":{\"631\":{}},\"parent\":{}}],[\"invertprice\",{\"_index\":502,\"name\":{\"693\":{}},\"parent\":{}}],[\"invertsqrtpricex64\",{\"_index\":503,\"name\":{\"694\":{}},\"parent\":{}}],[\"inverttick\",{\"_index\":525,\"name\":{\"722\":{}},\"parent\":{}}],[\"isempty\",{\"_index\":489,\"name\":{\"680\":{}},\"parent\":{}}],[\"isfull\",{\"_index\":488,\"name\":{\"679\":{}},\"parent\":{}}],[\"isfullrange\",{\"_index\":527,\"name\":{\"724\":{}},\"parent\":{}}],[\"isoccupied\",{\"_index\":486,\"name\":{\"677\":{}},\"parent\":{}}],[\"isrewardinitialized\",{\"_index\":471,\"name\":{\"662\":{}},\"parent\":{}}],[\"istickinitializable\",{\"_index\":524,\"name\":{\"721\":{}},\"parent\":{}}],[\"isunoccupied\",{\"_index\":487,\"name\":{\"678\":{}},\"parent\":{}}],[\"liquidity\",{\"_index\":134,\"name\":{\"167\":{},\"319\":{},\"361\":{}},\"parent\":{}}],[\"liquidityamount\",{\"_index\":343,\"name\":{\"439\":{},\"446\":{}},\"parent\":{}}],[\"liquiditygross\",{\"_index\":277,\"name\":{\"342\":{}},\"parent\":{}}],[\"liquiditynet\",{\"_index\":276,\"name\":{\"341\":{}},\"parent\":{}}],[\"lookuptablefetcher\",{\"_index\":20,\"name\":{\"20\":{}},\"parent\":{}}],[\"max_sqrt_price\",{\"_index\":314,\"name\":{\"391\":{}},\"parent\":{}}],[\"max_swap_tick_arrays\",{\"_index\":319,\"name\":{\"396\":{}},\"parent\":{}}],[\"max_tick_index\",{\"_index\":312,\"name\":{\"389\":{}},\"parent\":{}}],[\"maxsplits\",{\"_index\":187,\"name\":{\"231\":{}},\"parent\":{}}],[\"maxsupportedtransactionversion\",{\"_index\":222,\"name\":{\"274\":{}},\"parent\":{}}],[\"maxtransactionsize\",{\"_index\":224,\"name\":{\"275\":{}},\"parent\":{}}],[\"metadata_program_address\",{\"_index\":318,\"name\":{\"395\":{}},\"parent\":{}}],[\"metadatabump\",{\"_index\":290,\"name\":{\"356\":{}},\"parent\":{}}],[\"min_sqrt_price\",{\"_index\":315,\"name\":{\"392\":{}},\"parent\":{}}],[\"min_tick_index\",{\"_index\":313,\"name\":{\"390\":{}},\"parent\":{}}],[\"mint\",{\"_index\":249,\"name\":{\"305\":{}},\"parent\":{}}],[\"minta\",{\"_index\":203,\"name\":{\"251\":{}},\"parent\":{}}],[\"mintb\",{\"_index\":204,\"name\":{\"252\":{}},\"parent\":{}}],[\"newcollectprotocolfeesauthority\",{\"_index\":381,\"name\":{\"504\":{}},\"parent\":{}}],[\"newfeeauthority\",{\"_index\":388,\"name\":{\"520\":{}},\"parent\":{}}],[\"newrewardauthority\",{\"_index\":395,\"name\":{\"539\":{},\"545\":{}},\"parent\":{}}],[\"newrewardemissionssuperauthority\",{\"_index\":403,\"name\":{\"557\":{}},\"parent\":{}}],[\"normalswapquote\",{\"_index\":171,\"name\":{\"214\":{}},\"parent\":{}}],[\"normaltwohopswapquote\",{\"_index\":176,\"name\":{\"219\":{}},\"parent\":{}}],[\"num_rewards\",{\"_index\":311,\"name\":{\"388\":{}},\"parent\":{}}],[\"numtoppartialquotes\",{\"_index\":186,\"name\":{\"230\":{}},\"parent\":{}}],[\"numtoproutes\",{\"_index\":185,\"name\":{\"229\":{}},\"parent\":{}}],[\"onrouteevaluation\",{\"_index\":226,\"name\":{\"277\":{}},\"parent\":{}}],[\"openbundledpositionix\",{\"_index\":54,\"name\":{\"54\":{}},\"parent\":{}}],[\"openbundledpositionparams\",{\"_index\":422,\"name\":{\"589\":{}},\"parent\":{\"590\":{}}}],[\"openbundledpositionparams.__type\",{\"_index\":423,\"name\":{},\"parent\":{\"591\":{},\"592\":{},\"593\":{},\"594\":{},\"595\":{},\"596\":{},\"597\":{},\"598\":{},\"599\":{}}}],[\"openposition\",{\"_index\":554,\"name\":{\"760\":{}},\"parent\":{}}],[\"openpositionbumpsdata\",{\"_index\":285,\"name\":{\"350\":{}},\"parent\":{\"351\":{}}}],[\"openpositionbumpsdata.__type\",{\"_index\":287,\"name\":{},\"parent\":{\"352\":{}}}],[\"openpositionix\",{\"_index\":30,\"name\":{\"30\":{}},\"parent\":{}}],[\"openpositionparams\",{\"_index\":374,\"name\":{\"490\":{}},\"parent\":{\"491\":{}}}],[\"openpositionparams.__type\",{\"_index\":375,\"name\":{},\"parent\":{\"492\":{},\"493\":{},\"494\":{},\"495\":{},\"496\":{},\"497\":{},\"498\":{},\"499\":{}}}],[\"openpositionwithmetadata\",{\"_index\":555,\"name\":{\"761\":{}},\"parent\":{}}],[\"openpositionwithmetadatabumpsdata\",{\"_index\":288,\"name\":{\"353\":{}},\"parent\":{\"354\":{}}}],[\"openpositionwithmetadatabumpsdata.__type\",{\"_index\":289,\"name\":{},\"parent\":{\"355\":{},\"356\":{}}}],[\"openpositionwithmetadataix\",{\"_index\":31,\"name\":{\"31\":{}},\"parent\":{}}],[\"opts\",{\"_index\":21,\"name\":{\"21\":{}},\"parent\":{}}],[\"orca_supported_tick_spacings\",{\"_index\":310,\"name\":{\"387\":{}},\"parent\":{}}],[\"orca_whirlpool_program_id\",{\"_index\":308,\"name\":{\"385\":{}},\"parent\":{}}],[\"orca_whirlpools_config\",{\"_index\":309,\"name\":{\"386\":{}},\"parent\":{}}],[\"ordermints\",{\"_index\":475,\"name\":{\"666\":{}},\"parent\":{}}],[\"otheramountthreshold\",{\"_index\":158,\"name\":{\"201\":{},\"561\":{}},\"parent\":{}}],[\"outputmint\",{\"_index\":202,\"name\":{\"250\":{}},\"parent\":{}}],[\"owner\",{\"_index\":376,\"name\":{\"493\":{},\"577\":{},\"584\":{}},\"parent\":{}}],[\"parsablefeetier\",{\"_index\":88,\"name\":{\"113\":{}},\"parent\":{\"114\":{}}}],[\"parsableposition\",{\"_index\":86,\"name\":{\"109\":{}},\"parent\":{\"110\":{}}}],[\"parsablepositionbundle\",{\"_index\":89,\"name\":{\"115\":{}},\"parent\":{\"116\":{}}}],[\"parsabletickarray\",{\"_index\":87,\"name\":{\"111\":{}},\"parent\":{\"112\":{}}}],[\"parsablewhirlpool\",{\"_index\":85,\"name\":{\"107\":{}},\"parent\":{\"108\":{}}}],[\"parsablewhirlpoolsconfig\",{\"_index\":83,\"name\":{\"105\":{}},\"parent\":{\"106\":{}}}],[\"parse\",{\"_index\":84,\"name\":{\"106\":{},\"108\":{},\"110\":{},\"112\":{},\"114\":{},\"116\":{}},\"parent\":{}}],[\"path\",{\"_index\":194,\"name\":{\"239\":{},\"621\":{}},\"parent\":{\"622\":{}}}],[\"path.__type\",{\"_index\":439,\"name\":{},\"parent\":{\"623\":{},\"624\":{},\"625\":{}}}],[\"path_id_delimiter\",{\"_index\":457,\"name\":{\"642\":{}},\"parent\":{}}],[\"pathsearchentries\",{\"_index\":437,\"name\":{\"620\":{}},\"parent\":{}}],[\"pathsearchoptions\",{\"_index\":445,\"name\":{\"629\":{}},\"parent\":{\"630\":{}}}],[\"pathsearchoptions.__type\",{\"_index\":447,\"name\":{},\"parent\":{\"631\":{}}}],[\"payer\",{\"_index\":433,\"name\":{\"613\":{}},\"parent\":{}}],[\"pdautil\",{\"_index\":461,\"name\":{\"647\":{}},\"parent\":{\"648\":{},\"649\":{},\"650\":{},\"651\":{},\"652\":{},\"653\":{},\"654\":{},\"655\":{},\"656\":{},\"657\":{},\"658\":{},\"659\":{}}}],[\"percentincrement\",{\"_index\":183,\"name\":{\"228\":{}},\"parent\":{}}],[\"pooladdress\",{\"_index\":443,\"name\":{\"628\":{}},\"parent\":{}}],[\"poolgraph\",{\"_index\":448,\"name\":{\"632\":{}},\"parent\":{\"633\":{}}}],[\"poolgraph.__type\",{\"_index\":450,\"name\":{},\"parent\":{\"634\":{},\"635\":{},\"636\":{}}}],[\"poolgraphbuilder\",{\"_index\":453,\"name\":{\"637\":{}},\"parent\":{\"638\":{},\"639\":{},\"640\":{}}}],[\"poolgraphutils\",{\"_index\":456,\"name\":{\"641\":{}},\"parent\":{\"642\":{},\"643\":{},\"644\":{},\"645\":{}}}],[\"poolmap\",{\"_index\":101,\"name\":{\"129\":{},\"132\":{}},\"parent\":{}}],[\"pooltokenpair\",{\"_index\":436,\"name\":{\"616\":{}},\"parent\":{\"617\":{},\"618\":{},\"619\":{}}}],[\"poolutil\",{\"_index\":470,\"name\":{\"661\":{}},\"parent\":{\"662\":{},\"663\":{},\"664\":{},\"665\":{},\"666\":{},\"667\":{},\"668\":{},\"669\":{},\"670\":{}}}],[\"populatecache\",{\"_index\":75,\"name\":{\"79\":{},\"103\":{}},\"parent\":{}}],[\"position\",{\"_index\":141,\"name\":{\"178\":{},\"189\":{},\"288\":{},\"403\":{},\"410\":{},\"429\":{},\"572\":{},\"765\":{}},\"parent\":{\"766\":{},\"767\":{},\"768\":{},\"769\":{},\"770\":{},\"771\":{},\"772\":{},\"773\":{},\"774\":{},\"775\":{}}}],[\"position_bundle_size\",{\"_index\":317,\"name\":{\"394\":{}},\"parent\":{}}],[\"positionauthority\",{\"_index\":327,\"name\":{\"406\":{},\"416\":{},\"434\":{},\"612\":{}},\"parent\":{}}],[\"positionbitmap\",{\"_index\":301,\"name\":{\"377\":{}},\"parent\":{}}],[\"positionbump\",{\"_index\":286,\"name\":{\"352\":{},\"355\":{}},\"parent\":{}}],[\"positionbundle\",{\"_index\":237,\"name\":{\"292\":{},\"585\":{},\"593\":{},\"603\":{}},\"parent\":{}}],[\"positionbundleauthority\",{\"_index\":425,\"name\":{\"595\":{},\"605\":{}},\"parent\":{}}],[\"positionbundledata\",{\"_index\":298,\"name\":{\"374\":{}},\"parent\":{\"375\":{}}}],[\"positionbundledata.__type\",{\"_index\":300,\"name\":{},\"parent\":{\"376\":{},\"377\":{}}}],[\"positionbundlemint\",{\"_index\":299,\"name\":{\"376\":{},\"586\":{}},\"parent\":{}}],[\"positionbundlemintkeypair\",{\"_index\":418,\"name\":{\"579\":{}},\"parent\":{}}],[\"positionbundlepda\",{\"_index\":417,\"name\":{\"578\":{}},\"parent\":{}}],[\"positionbundletokenaccount\",{\"_index\":419,\"name\":{\"580\":{},\"587\":{},\"594\":{},\"604\":{}},\"parent\":{}}],[\"positionbundleutil\",{\"_index\":484,\"name\":{\"675\":{}},\"parent\":{\"676\":{},\"677\":{},\"678\":{},\"679\":{},\"680\":{},\"681\":{},\"682\":{},\"683\":{},\"684\":{}}}],[\"positiondata\",{\"_index\":291,\"name\":{\"357\":{}},\"parent\":{\"358\":{}}}],[\"positiondata.__type\",{\"_index\":292,\"name\":{},\"parent\":{\"359\":{},\"360\":{},\"361\":{},\"362\":{},\"363\":{},\"364\":{},\"365\":{},\"366\":{},\"367\":{},\"368\":{}}}],[\"positionmint\",{\"_index\":293,\"name\":{\"360\":{},\"404\":{}},\"parent\":{}}],[\"positionmintaddress\",{\"_index\":378,\"name\":{\"495\":{}},\"parent\":{}}],[\"positionowner\",{\"_index\":432,\"name\":{\"611\":{}},\"parent\":{}}],[\"positionpda\",{\"_index\":377,\"name\":{\"494\":{}},\"parent\":{}}],[\"positionrewardinfodata\",{\"_index\":281,\"name\":{\"346\":{}},\"parent\":{\"347\":{}}}],[\"positionrewardinfodata.__type\",{\"_index\":283,\"name\":{},\"parent\":{\"348\":{},\"349\":{}}}],[\"positiontokenaccount\",{\"_index\":326,\"name\":{\"405\":{},\"411\":{},\"430\":{},\"496\":{}},\"parent\":{}}],[\"prefer_cache\",{\"_index\":80,\"name\":{\"84\":{}},\"parent\":{}}],[\"pricecalculationdata\",{\"_index\":100,\"name\":{\"127\":{}},\"parent\":{\"128\":{}}}],[\"pricecalculationdata.__type\",{\"_index\":102,\"name\":{},\"parent\":{\"129\":{},\"130\":{},\"131\":{}}}],[\"priceimpactthreshold\",{\"_index\":99,\"name\":{\"126\":{}},\"parent\":{}}],[\"pricemap\",{\"_index\":105,\"name\":{\"134\":{}},\"parent\":{}}],[\"pricemath\",{\"_index\":494,\"name\":{\"685\":{}},\"parent\":{\"686\":{},\"687\":{},\"688\":{},\"689\":{},\"690\":{},\"691\":{},\"692\":{},\"693\":{},\"694\":{},\"695\":{}}}],[\"pricemodule\",{\"_index\":109,\"name\":{\"139\":{}},\"parent\":{\"140\":{},\"141\":{},\"142\":{},\"143\":{}}}],[\"pricemoduleutils\",{\"_index\":113,\"name\":{\"144\":{}},\"parent\":{\"145\":{},\"146\":{},\"147\":{},\"148\":{}}}],[\"pricetoinitializabletickindex\",{\"_index\":501,\"name\":{\"692\":{}},\"parent\":{}}],[\"pricetosqrtpricex64\",{\"_index\":495,\"name\":{\"686\":{}},\"parent\":{}}],[\"pricetotickindex\",{\"_index\":500,\"name\":{\"691\":{}},\"parent\":{}}],[\"program\",{\"_index\":17,\"name\":{\"17\":{}},\"parent\":{}}],[\"programid\",{\"_index\":94,\"name\":{\"121\":{}},\"parent\":{}}],[\"protocol_fee_rate_mul_value\",{\"_index\":320,\"name\":{\"397\":{}},\"parent\":{}}],[\"protocolfeeoweda\",{\"_index\":260,\"name\":{\"322\":{}},\"parent\":{}}],[\"protocolfeeowedb\",{\"_index\":261,\"name\":{\"323\":{}},\"parent\":{}}],[\"protocolfeerate\",{\"_index\":259,\"name\":{\"318\":{},\"532\":{}},\"parent\":{}}],[\"provider\",{\"_index\":18,\"name\":{\"18\":{}},\"parent\":{}}],[\"quote\",{\"_index\":207,\"name\":{\"255\":{}},\"parent\":{}}],[\"quotetokens\",{\"_index\":91,\"name\":{\"119\":{}},\"parent\":{}}],[\"receiver\",{\"_index\":324,\"name\":{\"402\":{},\"588\":{},\"607\":{},\"610\":{}},\"parent\":{}}],[\"refreshdata\",{\"_index\":547,\"name\":{\"753\":{},\"771\":{}},\"parent\":{}}],[\"rewardauthority\",{\"_index\":362,\"name\":{\"470\":{},\"544\":{},\"551\":{}},\"parent\":{}}],[\"rewardemissionssuperauthority\",{\"_index\":245,\"name\":{\"300\":{},\"453\":{},\"538\":{},\"556\":{}},\"parent\":{}}],[\"rewardgrowthsoutside\",{\"_index\":280,\"name\":{\"345\":{}},\"parent\":{}}],[\"rewardindex\",{\"_index\":336,\"name\":{\"431\":{},\"467\":{},\"537\":{},\"543\":{},\"549\":{}},\"parent\":{}}],[\"rewardinfos\",{\"_index\":267,\"name\":{\"331\":{},\"368\":{}},\"parent\":{}}],[\"rewardlastupdatedtimestamp\",{\"_index\":266,\"name\":{\"330\":{}},\"parent\":{}}],[\"rewardmint\",{\"_index\":360,\"name\":{\"468\":{}},\"parent\":{}}],[\"rewardowneraccount\",{\"_index\":337,\"name\":{\"432\":{}},\"parent\":{}}],[\"rewardvault\",{\"_index\":338,\"name\":{\"433\":{}},\"parent\":{}}],[\"rewardvaultkey\",{\"_index\":400,\"name\":{\"550\":{}},\"parent\":{}}],[\"rewardvaultkeypair\",{\"_index\":361,\"name\":{\"469\":{}},\"parent\":{}}],[\"routerutils\",{\"_index\":227,\"name\":{\"278\":{}},\"parent\":{\"279\":{},\"280\":{},\"281\":{},\"282\":{},\"283\":{},\"284\":{}}}],[\"routeselectoptions\",{\"_index\":221,\"name\":{\"272\":{}},\"parent\":{\"273\":{}}}],[\"routeselectoptions.__type\",{\"_index\":223,\"name\":{},\"parent\":{\"274\":{},\"275\":{},\"276\":{},\"277\":{}}}],[\"routingoptions\",{\"_index\":182,\"name\":{\"226\":{}},\"parent\":{\"227\":{}}}],[\"routingoptions.__type\",{\"_index\":184,\"name\":{},\"parent\":{\"228\":{},\"229\":{},\"230\":{},\"231\":{}}}],[\"selectfirstexecutableroute\",{\"_index\":228,\"name\":{\"279\":{}},\"parent\":{}}],[\"setcollectprotocolfeesauthorityix\",{\"_index\":41,\"name\":{\"41\":{}},\"parent\":{}}],[\"setcollectprotocolfeesauthorityparams\",{\"_index\":379,\"name\":{\"500\":{}},\"parent\":{\"501\":{}}}],[\"setcollectprotocolfeesauthorityparams.__type\",{\"_index\":380,\"name\":{},\"parent\":{\"502\":{},\"503\":{},\"504\":{}}}],[\"setdefaultfeerateix\",{\"_index\":42,\"name\":{\"42\":{}},\"parent\":{}}],[\"setdefaultfeerateparams\",{\"_index\":382,\"name\":{\"505\":{}},\"parent\":{\"506\":{}}}],[\"setdefaultfeerateparams.__type\",{\"_index\":383,\"name\":{},\"parent\":{\"507\":{},\"508\":{},\"509\":{},\"510\":{}}}],[\"setdefaultprotocolfeerateix\",{\"_index\":43,\"name\":{\"43\":{}},\"parent\":{}}],[\"setdefaultprotocolfeerateparams\",{\"_index\":384,\"name\":{\"511\":{}},\"parent\":{\"512\":{}}}],[\"setdefaultprotocolfeerateparams.__type\",{\"_index\":385,\"name\":{},\"parent\":{\"513\":{},\"514\":{},\"515\":{}}}],[\"setfeeauthorityix\",{\"_index\":44,\"name\":{\"44\":{}},\"parent\":{}}],[\"setfeeauthorityparams\",{\"_index\":386,\"name\":{\"516\":{}},\"parent\":{\"517\":{}}}],[\"setfeeauthorityparams.__type\",{\"_index\":387,\"name\":{},\"parent\":{\"518\":{},\"519\":{},\"520\":{}}}],[\"setfeerateix\",{\"_index\":45,\"name\":{\"45\":{}},\"parent\":{}}],[\"setfeerateparams\",{\"_index\":389,\"name\":{\"521\":{}},\"parent\":{\"522\":{}}}],[\"setfeerateparams.__type\",{\"_index\":390,\"name\":{},\"parent\":{\"523\":{},\"524\":{},\"525\":{},\"526\":{}}}],[\"setprotocolfeerateix\",{\"_index\":46,\"name\":{\"46\":{}},\"parent\":{}}],[\"setprotocolfeerateparams\",{\"_index\":391,\"name\":{\"527\":{}},\"parent\":{\"528\":{}}}],[\"setprotocolfeerateparams.__type\",{\"_index\":392,\"name\":{},\"parent\":{\"529\":{},\"530\":{},\"531\":{},\"532\":{}}}],[\"setrewardauthoritybysuperauthorityix\",{\"_index\":47,\"name\":{\"47\":{}},\"parent\":{}}],[\"setrewardauthoritybysuperauthorityparams\",{\"_index\":393,\"name\":{\"533\":{}},\"parent\":{\"534\":{}}}],[\"setrewardauthoritybysuperauthorityparams.__type\",{\"_index\":394,\"name\":{},\"parent\":{\"535\":{},\"536\":{},\"537\":{},\"538\":{},\"539\":{}}}],[\"setrewardauthorityix\",{\"_index\":48,\"name\":{\"48\":{}},\"parent\":{}}],[\"setrewardauthorityparams\",{\"_index\":396,\"name\":{\"540\":{}},\"parent\":{\"541\":{}}}],[\"setrewardauthorityparams.__type\",{\"_index\":397,\"name\":{},\"parent\":{\"542\":{},\"543\":{},\"544\":{},\"545\":{}}}],[\"setrewardemissionsix\",{\"_index\":49,\"name\":{\"49\":{}},\"parent\":{}}],[\"setrewardemissionsparams\",{\"_index\":398,\"name\":{\"546\":{}},\"parent\":{\"547\":{}}}],[\"setrewardemissionsparams.__type\",{\"_index\":399,\"name\":{},\"parent\":{\"548\":{},\"549\":{},\"550\":{},\"551\":{},\"552\":{}}}],[\"setrewardemissionssuperauthorityix\",{\"_index\":50,\"name\":{\"50\":{}},\"parent\":{}}],[\"setrewardemissionssuperauthorityparams\",{\"_index\":401,\"name\":{\"553\":{}},\"parent\":{\"554\":{}}}],[\"setrewardemissionssuperauthorityparams.__type\",{\"_index\":402,\"name\":{},\"parent\":{\"555\":{},\"556\":{},\"557\":{}}}],[\"slippagetolerance\",{\"_index\":129,\"name\":{\"161\":{},\"172\":{}},\"parent\":{}}],[\"snapshot\",{\"_index\":208,\"name\":{\"256\":{}},\"parent\":{}}],[\"splitpercent\",{\"_index\":196,\"name\":{\"240\":{}},\"parent\":{}}],[\"sqrtprice\",{\"_index\":126,\"name\":{\"158\":{},\"169\":{},\"260\":{},\"320\":{}},\"parent\":{}}],[\"sqrtpricelimit\",{\"_index\":159,\"name\":{\"202\":{},\"562\":{}},\"parent\":{}}],[\"sqrtpricex64toprice\",{\"_index\":496,\"name\":{\"687\":{}},\"parent\":{}}],[\"sqrtpricex64totickindex\",{\"_index\":498,\"name\":{\"689\":{}},\"parent\":{}}],[\"starttick\",{\"_index\":373,\"name\":{\"488\":{}},\"parent\":{}}],[\"starttickindex\",{\"_index\":271,\"name\":{\"336\":{}},\"parent\":{}}],[\"starttokenmint\",{\"_index\":438,\"name\":{\"623\":{}},\"parent\":{}}],[\"subroutes\",{\"_index\":189,\"name\":{\"234\":{}},\"parent\":{}}],[\"subtraderoute\",{\"_index\":193,\"name\":{\"237\":{}},\"parent\":{\"238\":{}}}],[\"subtraderoute.__type\",{\"_index\":195,\"name\":{},\"parent\":{\"239\":{},\"240\":{},\"241\":{},\"242\":{},\"243\":{}}}],[\"swap\",{\"_index\":216,\"name\":{\"266\":{},\"763\":{}},\"parent\":{}}],[\"swapdirection\",{\"_index\":534,\"name\":{\"732\":{}},\"parent\":{\"733\":{},\"734\":{}}}],[\"swapestimates\",{\"_index\":164,\"name\":{\"207\":{}},\"parent\":{\"208\":{}}}],[\"swapestimates.__type\",{\"_index\":166,\"name\":{},\"parent\":{\"209\":{},\"210\":{},\"211\":{},\"212\":{},\"213\":{}}}],[\"swapinput\",{\"_index\":404,\"name\":{\"558\":{}},\"parent\":{\"559\":{}}}],[\"swapinput.__type\",{\"_index\":406,\"name\":{},\"parent\":{\"560\":{},\"561\":{},\"562\":{},\"563\":{},\"564\":{},\"565\":{},\"566\":{},\"567\":{}}}],[\"swapix\",{\"_index\":35,\"name\":{\"35\":{}},\"parent\":{}}],[\"swapparams\",{\"_index\":410,\"name\":{\"568\":{}},\"parent\":{}}],[\"swapquote\",{\"_index\":163,\"name\":{\"206\":{}},\"parent\":{}}],[\"swapquotebyinputtoken\",{\"_index\":151,\"name\":{\"194\":{}},\"parent\":{}}],[\"swapquotebyinputtokenwithdevfees\",{\"_index\":172,\"name\":{\"215\":{}},\"parent\":{}}],[\"swapquotebyoutputtoken\",{\"_index\":152,\"name\":{\"195\":{}},\"parent\":{}}],[\"swapquoteparam\",{\"_index\":154,\"name\":{\"197\":{}},\"parent\":{\"198\":{}}}],[\"swapquoteparam.__type\",{\"_index\":156,\"name\":{},\"parent\":{\"199\":{},\"200\":{},\"201\":{},\"202\":{},\"203\":{},\"204\":{},\"205\":{}}}],[\"swapquotewithparams\",{\"_index\":153,\"name\":{\"196\":{}},\"parent\":{}}],[\"swaputils\",{\"_index\":506,\"name\":{\"701\":{}},\"parent\":{\"702\":{},\"703\":{},\"704\":{},\"705\":{},\"706\":{},\"707\":{},\"708\":{},\"709\":{},\"710\":{},\"711\":{}}}],[\"swapwithdevfees\",{\"_index\":557,\"name\":{\"764\":{}},\"parent\":{}}],[\"tick_array_size\",{\"_index\":316,\"name\":{\"393\":{}},\"parent\":{}}],[\"tickarray\",{\"_index\":235,\"name\":{\"289\":{},\"381\":{}},\"parent\":{\"382\":{}}}],[\"tickarray.__type\",{\"_index\":306,\"name\":{},\"parent\":{\"383\":{},\"384\":{}}}],[\"tickarray0\",{\"_index\":407,\"name\":{\"565\":{}},\"parent\":{}}],[\"tickarray1\",{\"_index\":408,\"name\":{\"566\":{}},\"parent\":{}}],[\"tickarray2\",{\"_index\":409,\"name\":{\"567\":{}},\"parent\":{}}],[\"tickarraydata\",{\"_index\":269,\"name\":{\"333\":{}},\"parent\":{\"334\":{}}}],[\"tickarraydata.__type\",{\"_index\":270,\"name\":{},\"parent\":{\"335\":{},\"336\":{},\"337\":{}}}],[\"tickarraylower\",{\"_index\":413,\"name\":{\"573\":{}},\"parent\":{}}],[\"tickarraymap\",{\"_index\":103,\"name\":{\"130\":{},\"133\":{}},\"parent\":{}}],[\"tickarraypda\",{\"_index\":372,\"name\":{\"487\":{}},\"parent\":{}}],[\"tickarrayrequest\",{\"_index\":504,\"name\":{\"696\":{}},\"parent\":{\"697\":{},\"698\":{},\"699\":{},\"700\":{}}}],[\"tickarrays\",{\"_index\":162,\"name\":{\"205\":{}},\"parent\":{}}],[\"tickarrayupper\",{\"_index\":414,\"name\":{\"574\":{}},\"parent\":{}}],[\"tickarrayutil\",{\"_index\":528,\"name\":{\"725\":{}},\"parent\":{\"726\":{},\"727\":{},\"728\":{},\"729\":{},\"730\":{},\"731\":{}}}],[\"tickcurrentindex\",{\"_index\":125,\"name\":{\"157\":{},\"168\":{},\"321\":{},\"699\":{}},\"parent\":{}}],[\"tickdata\",{\"_index\":273,\"name\":{\"338\":{}},\"parent\":{\"339\":{}}}],[\"tickdata.__type\",{\"_index\":275,\"name\":{},\"parent\":{\"340\":{},\"341\":{},\"342\":{},\"343\":{},\"344\":{},\"345\":{}}}],[\"tickindextoprice\",{\"_index\":499,\"name\":{\"690\":{}},\"parent\":{}}],[\"tickindextosqrtpricex64\",{\"_index\":497,\"name\":{\"688\":{}},\"parent\":{}}],[\"ticklower\",{\"_index\":142,\"name\":{\"179\":{},\"190\":{}},\"parent\":{}}],[\"ticklowerindex\",{\"_index\":127,\"name\":{\"159\":{},\"170\":{},\"362\":{},\"497\":{},\"597\":{}},\"parent\":{}}],[\"ticks\",{\"_index\":272,\"name\":{\"337\":{}},\"parent\":{}}],[\"tickspacing\",{\"_index\":268,\"name\":{\"332\":{},\"372\":{},\"460\":{},\"482\":{},\"509\":{},\"700\":{}},\"parent\":{}}],[\"tickspacings\",{\"_index\":93,\"name\":{\"120\":{}},\"parent\":{}}],[\"tickupper\",{\"_index\":143,\"name\":{\"180\":{},\"191\":{}},\"parent\":{}}],[\"tickupperindex\",{\"_index\":128,\"name\":{\"160\":{},\"171\":{},\"363\":{},\"498\":{},\"598\":{}},\"parent\":{}}],[\"tickutil\",{\"_index\":515,\"name\":{\"712\":{}},\"parent\":{\"713\":{},\"714\":{},\"715\":{},\"716\":{},\"717\":{},\"718\":{},\"719\":{},\"720\":{},\"721\":{},\"722\":{},\"723\":{},\"724\":{}}}],[\"timestampinseconds\",{\"_index\":150,\"name\":{\"192\":{}},\"parent\":{}}],[\"tobasequoteorder\",{\"_index\":479,\"name\":{\"670\":{}},\"parent\":{}}],[\"tokena\",{\"_index\":481,\"name\":{\"673\":{},\"736\":{}},\"parent\":{}}],[\"tokenaccountinfo\",{\"_index\":303,\"name\":{\"379\":{}},\"parent\":{}}],[\"tokenamount\",{\"_index\":157,\"name\":{\"200\":{}},\"parent\":{}}],[\"tokenamounts\",{\"_index\":480,\"name\":{\"671\":{}},\"parent\":{\"672\":{}}}],[\"tokenamounts.__type\",{\"_index\":482,\"name\":{},\"parent\":{\"673\":{},\"674\":{}}}],[\"tokenb\",{\"_index\":483,\"name\":{\"674\":{},\"737\":{}},\"parent\":{}}],[\"tokenin\",{\"_index\":178,\"name\":{\"222\":{}},\"parent\":{}}],[\"tokeninfo\",{\"_index\":302,\"name\":{\"378\":{}},\"parent\":{}}],[\"tokenmaxa\",{\"_index\":347,\"name\":{\"444\":{}},\"parent\":{}}],[\"tokenmaxb\",{\"_index\":349,\"name\":{\"445\":{}},\"parent\":{}}],[\"tokenmina\",{\"_index\":340,\"name\":{\"437\":{}},\"parent\":{}}],[\"tokenminb\",{\"_index\":342,\"name\":{\"438\":{}},\"parent\":{}}],[\"tokenminta\",{\"_index\":123,\"name\":{\"155\":{},\"324\":{},\"477\":{},\"618\":{}},\"parent\":{}}],[\"tokenmintb\",{\"_index\":124,\"name\":{\"156\":{},\"327\":{},\"478\":{},\"619\":{}},\"parent\":{}}],[\"tokenout\",{\"_index\":180,\"name\":{\"223\":{}},\"parent\":{}}],[\"tokenowneraccounta\",{\"_index\":330,\"name\":{\"412\":{},\"423\":{}},\"parent\":{}}],[\"tokenowneraccountb\",{\"_index\":331,\"name\":{\"413\":{},\"424\":{}},\"parent\":{}}],[\"tokentype\",{\"_index\":536,\"name\":{\"735\":{}},\"parent\":{\"736\":{},\"737\":{}}}],[\"tokenvaulta\",{\"_index\":262,\"name\":{\"325\":{},\"414\":{},\"421\":{}},\"parent\":{}}],[\"tokenvaultakeypair\",{\"_index\":367,\"name\":{\"479\":{}},\"parent\":{}}],[\"tokenvaultb\",{\"_index\":264,\"name\":{\"328\":{},\"415\":{},\"422\":{}},\"parent\":{}}],[\"tokenvaultbkeypair\",{\"_index\":368,\"name\":{\"480\":{}},\"parent\":{}}],[\"totalamountin\",{\"_index\":191,\"name\":{\"235\":{}},\"parent\":{}}],[\"totalamountout\",{\"_index\":192,\"name\":{\"236\":{}},\"parent\":{}}],[\"totokenamount\",{\"_index\":469,\"name\":{\"660\":{}},\"parent\":{}}],[\"totx\",{\"_index\":460,\"name\":{\"646\":{}},\"parent\":{}}],[\"trade\",{\"_index\":177,\"name\":{\"220\":{}},\"parent\":{\"221\":{}}}],[\"trade.__type\",{\"_index\":179,\"name\":{},\"parent\":{\"222\":{},\"223\":{},\"224\":{},\"225\":{}}}],[\"tradeamount\",{\"_index\":181,\"name\":{\"224\":{}},\"parent\":{}}],[\"tradehop\",{\"_index\":199,\"name\":{\"244\":{}},\"parent\":{\"245\":{}}}],[\"tradehop.__type\",{\"_index\":200,\"name\":{},\"parent\":{\"246\":{},\"247\":{},\"248\":{},\"249\":{},\"250\":{},\"251\":{},\"252\":{},\"253\":{},\"254\":{},\"255\":{},\"256\":{}}}],[\"tradehopsnapshot\",{\"_index\":209,\"name\":{\"257\":{}},\"parent\":{\"258\":{}}}],[\"tradehopsnapshot.__type\",{\"_index\":210,\"name\":{},\"parent\":{\"259\":{},\"260\":{},\"261\":{}}}],[\"traderoute\",{\"_index\":188,\"name\":{\"232\":{}},\"parent\":{\"233\":{}}}],[\"traderoute.__type\",{\"_index\":190,\"name\":{},\"parent\":{\"234\":{},\"235\":{},\"236\":{}}}],[\"twohopswapix\",{\"_index\":36,\"name\":{\"36\":{}},\"parent\":{}}],[\"twohopswapquote\",{\"_index\":175,\"name\":{\"218\":{}},\"parent\":{}}],[\"twohopswapquotefromswapquotes\",{\"_index\":174,\"name\":{\"217\":{}},\"parent\":{}}],[\"txbuilderopts\",{\"_index\":22,\"name\":{\"22\":{}},\"parent\":{}}],[\"updatefeesandrewardsix\",{\"_index\":37,\"name\":{\"37\":{}},\"parent\":{}}],[\"updatefeesandrewardsparams\",{\"_index\":411,\"name\":{\"569\":{}},\"parent\":{\"570\":{}}}],[\"updatefeesandrewardsparams.__type\",{\"_index\":412,\"name\":{},\"parent\":{\"571\":{},\"572\":{},\"573\":{},\"574\":{}}}],[\"userdefaultbuildoptions\",{\"_index\":2,\"name\":{\"2\":{}},\"parent\":{}}],[\"userdefaultconfirmcommitment\",{\"_index\":5,\"name\":{\"4\":{}},\"parent\":{}}],[\"userdefaultsendoptions\",{\"_index\":4,\"name\":{\"3\":{}},\"parent\":{}}],[\"vault\",{\"_index\":251,\"name\":{\"306\":{}},\"parent\":{}}],[\"vaulta\",{\"_index\":205,\"name\":{\"253\":{}},\"parent\":{}}],[\"vaultb\",{\"_index\":206,\"name\":{\"254\":{}},\"parent\":{}}],[\"wallet\",{\"_index\":16,\"name\":{\"16\":{}},\"parent\":{}}],[\"whirlpool\",{\"_index\":139,\"name\":{\"177\":{},\"188\":{},\"248\":{},\"290\":{},\"335\":{},\"359\":{},\"409\":{},\"420\":{},\"428\":{},\"466\":{},\"486\":{},\"492\":{},\"523\":{},\"529\":{},\"535\":{},\"542\":{},\"548\":{},\"571\":{},\"591\":{},\"750\":{}},\"parent\":{\"751\":{},\"752\":{},\"753\":{},\"754\":{},\"755\":{},\"756\":{},\"757\":{},\"758\":{},\"759\":{},\"760\":{},\"761\":{},\"762\":{},\"763\":{},\"764\":{}}}],[\"whirlpool_account_size\",{\"_index\":240,\"name\":{\"295\":{}},\"parent\":{}}],[\"whirlpool_coder\",{\"_index\":239,\"name\":{\"294\":{}},\"parent\":{}}],[\"whirlpool_idl\",{\"_index\":238,\"name\":{\"293\":{}},\"parent\":{}}],[\"whirlpool_nft_update_auth\",{\"_index\":322,\"name\":{\"399\":{}},\"parent\":{}}],[\"whirlpoolaccountfetcher\",{\"_index\":57,\"name\":{\"58\":{}},\"parent\":{\"59\":{},\"60\":{},\"61\":{},\"62\":{},\"63\":{},\"64\":{},\"65\":{},\"66\":{},\"67\":{},\"68\":{},\"69\":{},\"70\":{},\"71\":{},\"72\":{},\"73\":{},\"74\":{},\"75\":{},\"76\":{},\"77\":{},\"78\":{},\"79\":{}}}],[\"whirlpoolaccountfetcherinterface\",{\"_index\":81,\"name\":{\"85\":{}},\"parent\":{\"86\":{},\"87\":{},\"88\":{},\"89\":{},\"90\":{},\"91\":{},\"92\":{},\"93\":{},\"94\":{},\"95\":{},\"96\":{},\"97\":{},\"98\":{},\"99\":{},\"100\":{},\"101\":{},\"102\":{},\"103\":{}}}],[\"whirlpoolaccountfetchoptions\",{\"_index\":78,\"name\":{\"82\":{}},\"parent\":{}}],[\"whirlpooladdress\",{\"_index\":505,\"name\":{\"697\":{}},\"parent\":{}}],[\"whirlpoolbump\",{\"_index\":256,\"name\":{\"312\":{},\"316\":{}},\"parent\":{}}],[\"whirlpoolbumpsdata\",{\"_index\":255,\"name\":{\"310\":{}},\"parent\":{\"311\":{}}}],[\"whirlpoolbumpsdata.__type\",{\"_index\":257,\"name\":{},\"parent\":{\"312\":{}}}],[\"whirlpoolclient\",{\"_index\":538,\"name\":{\"739\":{}},\"parent\":{\"740\":{},\"741\":{},\"742\":{},\"743\":{},\"744\":{},\"745\":{},\"746\":{},\"747\":{},\"748\":{},\"749\":{}}}],[\"whirlpoolcontext\",{\"_index\":10,\"name\":{\"10\":{}},\"parent\":{\"11\":{},\"12\":{},\"13\":{},\"14\":{},\"15\":{},\"16\":{},\"17\":{},\"18\":{},\"19\":{},\"20\":{},\"21\":{},\"22\":{},\"23\":{}}}],[\"whirlpoolcontextopts\",{\"_index\":0,\"name\":{\"0\":{}},\"parent\":{\"1\":{}}}],[\"whirlpoolcontextopts.__type\",{\"_index\":3,\"name\":{},\"parent\":{\"2\":{},\"3\":{},\"4\":{},\"5\":{}}}],[\"whirlpooldata\",{\"_index\":155,\"name\":{\"199\":{},\"313\":{}},\"parent\":{\"314\":{}}}],[\"whirlpooldata.__type\",{\"_index\":258,\"name\":{},\"parent\":{\"315\":{},\"316\":{},\"317\":{},\"318\":{},\"319\":{},\"320\":{},\"321\":{},\"322\":{},\"323\":{},\"324\":{},\"325\":{},\"326\":{},\"327\":{},\"328\":{},\"329\":{},\"330\":{},\"331\":{},\"332\":{}}}],[\"whirlpoolix\",{\"_index\":24,\"name\":{\"24\":{}},\"parent\":{\"25\":{},\"26\":{},\"27\":{},\"28\":{},\"29\":{},\"30\":{},\"31\":{},\"32\":{},\"33\":{},\"34\":{},\"35\":{},\"36\":{},\"37\":{},\"38\":{},\"39\":{},\"40\":{},\"41\":{},\"42\":{},\"43\":{},\"44\":{},\"45\":{},\"46\":{},\"47\":{},\"48\":{},\"49\":{},\"50\":{},\"51\":{},\"52\":{},\"53\":{},\"54\":{},\"55\":{},\"56\":{}}}],[\"whirlpoolpda\",{\"_index\":366,\"name\":{\"476\":{}},\"parent\":{}}],[\"whirlpoolrewardinfo\",{\"_index\":304,\"name\":{\"380\":{}},\"parent\":{}}],[\"whirlpoolrewardinfodata\",{\"_index\":248,\"name\":{\"303\":{}},\"parent\":{\"304\":{}}}],[\"whirlpoolrewardinfodata.__type\",{\"_index\":250,\"name\":{},\"parent\":{\"305\":{},\"306\":{},\"307\":{},\"308\":{},\"309\":{}}}],[\"whirlpoolrouter\",{\"_index\":213,\"name\":{\"263\":{}},\"parent\":{\"264\":{},\"265\":{},\"266\":{}}}],[\"whirlpoolrouterbuilder\",{\"_index\":217,\"name\":{\"267\":{}},\"parent\":{\"268\":{},\"269\":{},\"270\":{}}}],[\"whirlpoolsconfig\",{\"_index\":95,\"name\":{\"122\":{},\"287\":{},\"315\":{},\"371\":{},\"419\":{},\"458\":{},\"475\":{},\"502\":{},\"507\":{},\"513\":{},\"518\":{},\"524\":{},\"530\":{},\"536\":{},\"555\":{}},\"parent\":{}}],[\"whirlpoolsconfigdata\",{\"_index\":241,\"name\":{\"296\":{}},\"parent\":{\"297\":{}}}],[\"whirlpoolsconfigdata.__type\",{\"_index\":243,\"name\":{},\"parent\":{\"298\":{},\"299\":{},\"300\":{},\"301\":{},\"302\":{}}}],[\"whirlpoolsconfigkeypair\",{\"_index\":352,\"name\":{\"450\":{}},\"parent\":{}}],[\"whirlpoolsupportedtypes\",{\"_index\":76,\"name\":{\"80\":{}},\"parent\":{}}],[\"withprovider\",{\"_index\":13,\"name\":{\"13\":{}},\"parent\":{}}]],\"pipeline\":[]}}"); \ No newline at end of file diff --git a/docs/assets/style.css b/docs/assets/style.css deleted file mode 100644 index 6127b27..0000000 --- a/docs/assets/style.css +++ /dev/null @@ -1,1414 +0,0 @@ -@import url("./icons.css"); - -:root { - /* Light */ - --light-color-background: #fcfcfc; - --light-color-secondary-background: #fff; - --light-color-text: #222; - --light-color-text-aside: #707070; - --light-color-link: #4da6ff; - --light-color-menu-divider: #eee; - --light-color-menu-divider-focus: #000; - --light-color-menu-label: #707070; - --light-color-panel: var(--light-color-secondary-background); - --light-color-panel-divider: #eee; - --light-color-comment-tag: #707070; - --light-color-comment-tag-text: #fff; - --light-color-ts: #9600ff; - --light-color-ts-interface: #647f1b; - --light-color-ts-enum: #937210; - --light-color-ts-class: #0672de; - --light-color-ts-private: #707070; - --light-color-toolbar: #fff; - --light-color-toolbar-text: #333; - --light-icon-filter: invert(0); - --light-external-icon: url("data:image/svg+xml;utf8,"); - - /* Dark */ - --dark-color-background: #36393f; - --dark-color-secondary-background: #2f3136; - --dark-color-text: #ffffff; - --dark-color-text-aside: #e6e4e4; - --dark-color-link: #00aff4; - --dark-color-menu-divider: #eee; - --dark-color-menu-divider-focus: #000; - --dark-color-menu-label: #707070; - --dark-color-panel: var(--dark-color-secondary-background); - --dark-color-panel-divider: #818181; - --dark-color-comment-tag: #dcddde; - --dark-color-comment-tag-text: #2f3136; - --dark-color-ts: #c97dff; - --dark-color-ts-interface: #9cbe3c; - --dark-color-ts-enum: #d6ab29; - --dark-color-ts-class: #3695f3; - --dark-color-ts-private: #e2e2e2; - --dark-color-toolbar: #34373c; - --dark-color-toolbar-text: #ffffff; - --dark-icon-filter: invert(1); - --dark-external-icon: url("data:image/svg+xml;utf8,"); -} - -@media (prefers-color-scheme: light) { - :root { - --color-background: var(--light-color-background); - --color-secondary-background: var(--light-color-secondary-background); - --color-text: var(--light-color-text); - --color-text-aside: var(--light-color-text-aside); - --color-link: var(--light-color-link); - --color-menu-divider: var(--light-color-menu-divider); - --color-menu-divider-focus: var(--light-color-menu-divider-focus); - --color-menu-label: var(--light-color-menu-label); - --color-panel: var(--light-color-panel); - --color-panel-divider: var(--light-color-panel-divider); - --color-comment-tag: var(--light-color-comment-tag); - --color-comment-tag-text: var(--light-color-comment-tag-text); - --color-ts: var(--light-color-ts); - --color-ts-interface: var(--light-color-ts-interface); - --color-ts-enum: var(--light-color-ts-enum); - --color-ts-class: var(--light-color-ts-class); - --color-ts-private: var(--light-color-ts-private); - --color-toolbar: var(--light-color-toolbar); - --color-toolbar-text: var(--light-color-toolbar-text); - --icon-filter: var(--light-icon-filter); - --external-icon: var(--light-external-icon); - } -} - -@media (prefers-color-scheme: dark) { - :root { - --color-background: var(--dark-color-background); - --color-secondary-background: var(--dark-color-secondary-background); - --color-text: var(--dark-color-text); - --color-text-aside: var(--dark-color-text-aside); - --color-link: var(--dark-color-link); - --color-menu-divider: var(--dark-color-menu-divider); - --color-menu-divider-focus: var(--dark-color-menu-divider-focus); - --color-menu-label: var(--dark-color-menu-label); - --color-panel: var(--dark-color-panel); - --color-panel-divider: var(--dark-color-panel-divider); - --color-comment-tag: var(--dark-color-comment-tag); - --color-comment-tag-text: var(--dark-color-comment-tag-text); - --color-ts: var(--dark-color-ts); - --color-ts-interface: var(--dark-color-ts-interface); - --color-ts-enum: var(--dark-color-ts-enum); - --color-ts-class: var(--dark-color-ts-class); - --color-ts-private: var(--dark-color-ts-private); - --color-toolbar: var(--dark-color-toolbar); - --color-toolbar-text: var(--dark-color-toolbar-text); - --icon-filter: var(--dark-icon-filter); - --external-icon: var(--dark-external-icon); - } -} - -body { - margin: 0; -} - -body.light { - --color-background: var(--light-color-background); - --color-secondary-background: var(--light-color-secondary-background); - --color-text: var(--light-color-text); - --color-text-aside: var(--light-color-text-aside); - --color-link: var(--light-color-link); - --color-menu-divider: var(--light-color-menu-divider); - --color-menu-divider-focus: var(--light-color-menu-divider-focus); - --color-menu-label: var(--light-color-menu-label); - --color-panel: var(--light-color-panel); - --color-panel-divider: var(--light-color-panel-divider); - --color-comment-tag: var(--light-color-comment-tag); - --color-comment-tag-text: var(--light-color-comment-tag-text); - --color-ts: var(--light-color-ts); - --color-ts-interface: var(--light-color-ts-interface); - --color-ts-enum: var(--light-color-ts-enum); - --color-ts-class: var(--light-color-ts-class); - --color-ts-private: var(--light-color-ts-private); - --color-toolbar: var(--light-color-toolbar); - --color-toolbar-text: var(--light-color-toolbar-text); - --icon-filter: var(--light-icon-filter); - --external-icon: var(--light-external-icon); -} - -body.dark { - --color-background: var(--dark-color-background); - --color-secondary-background: var(--dark-color-secondary-background); - --color-text: var(--dark-color-text); - --color-text-aside: var(--dark-color-text-aside); - --color-link: var(--dark-color-link); - --color-menu-divider: var(--dark-color-menu-divider); - --color-menu-divider-focus: var(--dark-color-menu-divider-focus); - --color-menu-label: var(--dark-color-menu-label); - --color-panel: var(--dark-color-panel); - --color-panel-divider: var(--dark-color-panel-divider); - --color-comment-tag: var(--dark-color-comment-tag); - --color-comment-tag-text: var(--dark-color-comment-tag-text); - --color-ts: var(--dark-color-ts); - --color-ts-interface: var(--dark-color-ts-interface); - --color-ts-enum: var(--dark-color-ts-enum); - --color-ts-class: var(--dark-color-ts-class); - --color-ts-private: var(--dark-color-ts-private); - --color-toolbar: var(--dark-color-toolbar); - --color-toolbar-text: var(--dark-color-toolbar-text); - --icon-filter: var(--dark-icon-filter); - --external-icon: var(--dark-external-icon); -} - -h1, -h2, -h3, -h4, -h5, -h6 { - line-height: 1.2; -} - -h1 { - font-size: 2em; - margin: 0.67em 0; -} - -h2 { - font-size: 1.5em; - margin: 0.83em 0; -} - -h3 { - font-size: 1.17em; - margin: 1em 0; -} - -h4, -.tsd-index-panel h3 { - font-size: 1em; - margin: 1.33em 0; -} - -h5 { - font-size: 0.83em; - margin: 1.67em 0; -} - -h6 { - font-size: 0.67em; - margin: 2.33em 0; -} - -pre { - white-space: pre; - white-space: pre-wrap; - word-wrap: break-word; -} - -dl, -menu, -ol, -ul { - margin: 1em 0; -} - -dd { - margin: 0 0 0 40px; -} - -.container { - max-width: 1200px; - margin: 0 auto; - padding: 0 40px; -} -@media (max-width: 640px) { - .container { - padding: 0 20px; - } -} - -.container-main { - padding-bottom: 200px; -} - -.row { - display: flex; - position: relative; - margin: 0 -10px; -} -.row:after { - visibility: hidden; - display: block; - content: ""; - clear: both; - height: 0; -} - -.col-4, -.col-8 { - box-sizing: border-box; - float: left; - padding: 0 10px; -} - -.col-4 { - width: 33.3333333333%; -} -.col-8 { - width: 66.6666666667%; -} - -ul.tsd-descriptions > li > :first-child, -.tsd-panel > :first-child, -.col-8 > :first-child, -.col-4 > :first-child, -ul.tsd-descriptions > li > :first-child > :first-child, -.tsd-panel > :first-child > :first-child, -.col-8 > :first-child > :first-child, -.col-4 > :first-child > :first-child, -ul.tsd-descriptions > li > :first-child > :first-child > :first-child, -.tsd-panel > :first-child > :first-child > :first-child, -.col-8 > :first-child > :first-child > :first-child, -.col-4 > :first-child > :first-child > :first-child { - margin-top: 0; -} -ul.tsd-descriptions > li > :last-child, -.tsd-panel > :last-child, -.col-8 > :last-child, -.col-4 > :last-child, -ul.tsd-descriptions > li > :last-child > :last-child, -.tsd-panel > :last-child > :last-child, -.col-8 > :last-child > :last-child, -.col-4 > :last-child > :last-child, -ul.tsd-descriptions > li > :last-child > :last-child > :last-child, -.tsd-panel > :last-child > :last-child > :last-child, -.col-8 > :last-child > :last-child > :last-child, -.col-4 > :last-child > :last-child > :last-child { - margin-bottom: 0; -} - -@keyframes fade-in { - from { - opacity: 0; - } - to { - opacity: 1; - } -} -@keyframes fade-out { - from { - opacity: 1; - visibility: visible; - } - to { - opacity: 0; - } -} -@keyframes fade-in-delayed { - 0% { - opacity: 0; - } - 33% { - opacity: 0; - } - 100% { - opacity: 1; - } -} -@keyframes fade-out-delayed { - 0% { - opacity: 1; - visibility: visible; - } - 66% { - opacity: 0; - } - 100% { - opacity: 0; - } -} -@keyframes shift-to-left { - from { - transform: translate(0, 0); - } - to { - transform: translate(-25%, 0); - } -} -@keyframes unshift-to-left { - from { - transform: translate(-25%, 0); - } - to { - transform: translate(0, 0); - } -} -@keyframes pop-in-from-right { - from { - transform: translate(100%, 0); - } - to { - transform: translate(0, 0); - } -} -@keyframes pop-out-to-right { - from { - transform: translate(0, 0); - visibility: visible; - } - to { - transform: translate(100%, 0); - } -} -body { - background: var(--color-background); - font-family: "Segoe UI", sans-serif; - font-size: 16px; - color: var(--color-text); -} - -a { - color: var(--color-link); - text-decoration: none; -} -a:hover { - text-decoration: underline; -} -a.external[target="_blank"] { - background-image: var(--external-icon); - background-position: top 3px right; - background-repeat: no-repeat; - padding-right: 13px; -} - -code, -pre { - font-family: Menlo, Monaco, Consolas, "Courier New", monospace; - padding: 0.2em; - margin: 0; - font-size: 14px; -} - -pre { - padding: 10px; -} -pre code { - padding: 0; - font-size: 100%; -} - -blockquote { - margin: 1em 0; - padding-left: 1em; - border-left: 4px solid gray; -} - -.tsd-typography { - line-height: 1.333em; -} -.tsd-typography ul { - list-style: square; - padding: 0 0 0 20px; - margin: 0; -} -.tsd-typography h4, -.tsd-typography .tsd-index-panel h3, -.tsd-index-panel .tsd-typography h3, -.tsd-typography h5, -.tsd-typography h6 { - font-size: 1em; - margin: 0; -} -.tsd-typography h5, -.tsd-typography h6 { - font-weight: normal; -} -.tsd-typography p, -.tsd-typography ul, -.tsd-typography ol { - margin: 1em 0; -} - -@media (min-width: 901px) and (max-width: 1024px) { - html .col-content { - width: 72%; - } - html .col-menu { - width: 28%; - } - html .tsd-navigation { - padding-left: 10px; - } -} -@media (max-width: 900px) { - html .col-content { - float: none; - width: 100%; - } - html .col-menu { - position: fixed !important; - overflow: auto; - -webkit-overflow-scrolling: touch; - z-index: 1024; - top: 0 !important; - bottom: 0 !important; - left: auto !important; - right: 0 !important; - width: 100%; - padding: 20px 20px 0 0; - max-width: 450px; - visibility: hidden; - background-color: var(--color-panel); - transform: translate(100%, 0); - } - html .col-menu > *:last-child { - padding-bottom: 20px; - } - html .overlay { - content: ""; - display: block; - position: fixed; - z-index: 1023; - top: 0; - left: 0; - right: 0; - bottom: 0; - background-color: rgba(0, 0, 0, 0.75); - visibility: hidden; - } - - .to-has-menu .overlay { - animation: fade-in 0.4s; - } - - .to-has-menu :is(header, footer, .col-content) { - animation: shift-to-left 0.4s; - } - - .to-has-menu .col-menu { - animation: pop-in-from-right 0.4s; - } - - .from-has-menu .overlay { - animation: fade-out 0.4s; - } - - .from-has-menu :is(header, footer, .col-content) { - animation: unshift-to-left 0.4s; - } - - .from-has-menu .col-menu { - animation: pop-out-to-right 0.4s; - } - - .has-menu body { - overflow: hidden; - } - .has-menu .overlay { - visibility: visible; - } - .has-menu :is(header, footer, .col-content) { - transform: translate(-25%, 0); - } - .has-menu .col-menu { - visibility: visible; - transform: translate(0, 0); - display: grid; - grid-template-rows: auto 1fr; - max-height: 100vh; - } - .has-menu .tsd-navigation { - max-height: 100%; - } -} - -.tsd-page-title { - padding: 70px 0 20px 0; - margin: 0 0 40px 0; - background: var(--color-panel); - box-shadow: 0 0 5px rgba(0, 0, 0, 0.35); -} -.tsd-page-title h1 { - margin: 0; -} - -.tsd-breadcrumb { - margin: 0; - padding: 0; - color: var(--color-text-aside); -} -.tsd-breadcrumb a { - color: var(--color-text-aside); - text-decoration: none; -} -.tsd-breadcrumb a:hover { - text-decoration: underline; -} -.tsd-breadcrumb li { - display: inline; -} -.tsd-breadcrumb li:after { - content: " / "; -} - -dl.tsd-comment-tags { - overflow: hidden; -} -dl.tsd-comment-tags dt { - float: left; - padding: 1px 5px; - margin: 0 10px 0 0; - border-radius: 4px; - border: 1px solid var(--color-comment-tag); - color: var(--color-comment-tag); - font-size: 0.8em; - font-weight: normal; -} -dl.tsd-comment-tags dd { - margin: 0 0 10px 0; -} -dl.tsd-comment-tags dd:before, -dl.tsd-comment-tags dd:after { - display: table; - content: " "; -} -dl.tsd-comment-tags dd pre, -dl.tsd-comment-tags dd:after { - clear: both; -} -dl.tsd-comment-tags p { - margin: 0; -} - -.tsd-panel.tsd-comment .lead { - font-size: 1.1em; - line-height: 1.333em; - margin-bottom: 2em; -} -.tsd-panel.tsd-comment .lead:last-child { - margin-bottom: 0; -} - -.toggle-protected .tsd-is-private { - display: none; -} - -.toggle-public .tsd-is-private, -.toggle-public .tsd-is-protected, -.toggle-public .tsd-is-private-protected { - display: none; -} - -.toggle-inherited .tsd-is-inherited { - display: none; -} - -.toggle-externals .tsd-is-external { - display: none; -} - -#tsd-filter { - position: relative; - display: inline-block; - height: 40px; - vertical-align: bottom; -} -.no-filter #tsd-filter { - display: none; -} -#tsd-filter .tsd-filter-group { - display: inline-block; - height: 40px; - vertical-align: bottom; - white-space: nowrap; -} -#tsd-filter input { - display: none; -} -@media (max-width: 900px) { - #tsd-filter .tsd-filter-group { - display: block; - position: absolute; - top: 40px; - right: 20px; - height: auto; - background-color: var(--color-panel); - visibility: hidden; - transform: translate(50%, 0); - box-shadow: 0 0 4px rgba(0, 0, 0, 0.25); - } - .has-options #tsd-filter .tsd-filter-group { - visibility: visible; - } - .to-has-options #tsd-filter .tsd-filter-group { - animation: fade-in 0.2s; - } - .from-has-options #tsd-filter .tsd-filter-group { - animation: fade-out 0.2s; - } - #tsd-filter label, - #tsd-filter .tsd-select { - display: block; - padding-right: 20px; - } -} - -footer { - border-top: 1px solid var(--color-panel-divider); - background-color: var(--color-panel); -} -footer:after { - content: ""; - display: table; -} -footer.with-border-bottom { - border-bottom: 1px solid var(--color-panel-divider); -} -footer .tsd-legend-group { - font-size: 0; -} -footer .tsd-legend { - display: inline-block; - width: 25%; - padding: 0; - font-size: 16px; - list-style: none; - line-height: 1.333em; - vertical-align: top; -} -@media (max-width: 900px) { - footer .tsd-legend { - width: 50%; - } -} - -.tsd-hierarchy { - list-style: square; - padding: 0 0 0 20px; - margin: 0; -} -.tsd-hierarchy .target { - font-weight: bold; -} - -.tsd-index-panel .tsd-index-content { - margin-bottom: -30px !important; -} -.tsd-index-panel .tsd-index-section { - margin-bottom: 30px !important; -} -.tsd-index-panel h3 { - margin: 0 -20px 10px -20px; - padding: 0 20px 10px 20px; - border-bottom: 1px solid var(--color-panel-divider); -} -.tsd-index-panel ul.tsd-index-list { - -webkit-column-count: 3; - -moz-column-count: 3; - -ms-column-count: 3; - -o-column-count: 3; - column-count: 3; - -webkit-column-gap: 20px; - -moz-column-gap: 20px; - -ms-column-gap: 20px; - -o-column-gap: 20px; - column-gap: 20px; - padding: 0; - list-style: none; - line-height: 1.333em; -} -@media (max-width: 900px) { - .tsd-index-panel ul.tsd-index-list { - -webkit-column-count: 1; - -moz-column-count: 1; - -ms-column-count: 1; - -o-column-count: 1; - column-count: 1; - } -} -@media (min-width: 901px) and (max-width: 1024px) { - .tsd-index-panel ul.tsd-index-list { - -webkit-column-count: 2; - -moz-column-count: 2; - -ms-column-count: 2; - -o-column-count: 2; - column-count: 2; - } -} -.tsd-index-panel ul.tsd-index-list li { - -webkit-page-break-inside: avoid; - -moz-page-break-inside: avoid; - -ms-page-break-inside: avoid; - -o-page-break-inside: avoid; - page-break-inside: avoid; -} -.tsd-index-panel a, -.tsd-index-panel .tsd-parent-kind-module a { - color: var(--color-ts); -} -.tsd-index-panel .tsd-parent-kind-interface a { - color: var(--color-ts-interface); -} -.tsd-index-panel .tsd-parent-kind-enum a { - color: var(--color-ts-enum); -} -.tsd-index-panel .tsd-parent-kind-class a { - color: var(--color-ts-class); -} -.tsd-index-panel .tsd-kind-module a { - color: var(--color-ts); -} -.tsd-index-panel .tsd-kind-interface a { - color: var(--color-ts-interface); -} -.tsd-index-panel .tsd-kind-enum a { - color: var(--color-ts-enum); -} -.tsd-index-panel .tsd-kind-class a { - color: var(--color-ts-class); -} -.tsd-index-panel .tsd-is-private a { - color: var(--color-ts-private); -} - -.tsd-flag { - display: inline-block; - padding: 0.25em 0.4em; - border-radius: 4px; - color: var(--color-comment-tag-text); - background-color: var(--color-comment-tag); - text-indent: 0; - font-size: 75%; - line-height: 1; - font-weight: normal; -} - -.tsd-anchor { - position: absolute; - top: -100px; -} - -.tsd-member { - position: relative; -} -.tsd-member .tsd-anchor + h3 { - margin-top: 0; - margin-bottom: 0; - border-bottom: none; -} -.tsd-member [data-tsd-kind] { - color: var(--color-ts); -} -.tsd-member [data-tsd-kind="Interface"] { - color: var(--color-ts-interface); -} -.tsd-member [data-tsd-kind="Enum"] { - color: var(--color-ts-enum); -} -.tsd-member [data-tsd-kind="Class"] { - color: var(--color-ts-class); -} -.tsd-member [data-tsd-kind="Private"] { - color: var(--color-ts-private); -} - -.tsd-navigation { - margin: 0 0 0 40px; -} -.tsd-navigation a { - display: block; - padding-top: 2px; - padding-bottom: 2px; - border-left: 2px solid transparent; - color: var(--color-text); - text-decoration: none; - transition: border-left-color 0.1s; -} -.tsd-navigation a:hover { - text-decoration: underline; -} -.tsd-navigation ul { - margin: 0; - padding: 0; - list-style: none; -} -.tsd-navigation li { - padding: 0; -} - -.tsd-navigation.primary { - padding-bottom: 40px; -} -.tsd-navigation.primary a { - display: block; - padding-top: 6px; - padding-bottom: 6px; -} -.tsd-navigation.primary ul li a { - padding-left: 5px; -} -.tsd-navigation.primary ul li li a { - padding-left: 25px; -} -.tsd-navigation.primary ul li li li a { - padding-left: 45px; -} -.tsd-navigation.primary ul li li li li a { - padding-left: 65px; -} -.tsd-navigation.primary ul li li li li li a { - padding-left: 85px; -} -.tsd-navigation.primary ul li li li li li li a { - padding-left: 105px; -} -.tsd-navigation.primary > ul { - border-bottom: 1px solid var(--color-panel-divider); -} -.tsd-navigation.primary li { - border-top: 1px solid var(--color-panel-divider); -} -.tsd-navigation.primary li.current > a { - font-weight: bold; -} -.tsd-navigation.primary li.label span { - display: block; - padding: 20px 0 6px 5px; - color: var(--color-menu-label); -} -.tsd-navigation.primary li.globals + li > span, -.tsd-navigation.primary li.globals + li > a { - padding-top: 20px; -} - -.tsd-navigation.secondary { - max-height: calc(100vh - 1rem - 40px); - overflow: auto; - position: sticky; - top: calc(0.5rem + 40px); - transition: 0.3s; -} -.tsd-navigation.secondary.tsd-navigation--toolbar-hide { - max-height: calc(100vh - 1rem); - top: 0.5rem; -} -.tsd-navigation.secondary ul { - transition: opacity 0.2s; -} -.tsd-navigation.secondary ul li a { - padding-left: 25px; -} -.tsd-navigation.secondary ul li li a { - padding-left: 45px; -} -.tsd-navigation.secondary ul li li li a { - padding-left: 65px; -} -.tsd-navigation.secondary ul li li li li a { - padding-left: 85px; -} -.tsd-navigation.secondary ul li li li li li a { - padding-left: 105px; -} -.tsd-navigation.secondary ul li li li li li li a { - padding-left: 125px; -} -.tsd-navigation.secondary ul.current a { - border-left-color: var(--color-panel-divider); -} -.tsd-navigation.secondary li.focus > a, -.tsd-navigation.secondary ul.current li.focus > a { - border-left-color: var(--color-menu-divider-focus); -} -.tsd-navigation.secondary li.current { - margin-top: 20px; - margin-bottom: 20px; - border-left-color: var(--color-panel-divider); -} -.tsd-navigation.secondary li.current > a { - font-weight: bold; -} - -@media (min-width: 901px) { - .menu-sticky-wrap { - position: static; - } -} - -.tsd-panel { - margin: 20px 0; - padding: 20px; - background-color: var(--color-panel); - box-shadow: 0 0 4px rgba(0, 0, 0, 0.25); -} -.tsd-panel:empty { - display: none; -} -.tsd-panel > h1, -.tsd-panel > h2, -.tsd-panel > h3 { - margin: 1.5em -20px 10px -20px; - padding: 0 20px 10px 20px; - border-bottom: 1px solid var(--color-panel-divider); -} -.tsd-panel > h1.tsd-before-signature, -.tsd-panel > h2.tsd-before-signature, -.tsd-panel > h3.tsd-before-signature { - margin-bottom: 0; - border-bottom: 0; -} -.tsd-panel table { - display: block; - width: 100%; - overflow: auto; - margin-top: 10px; - word-break: normal; - word-break: keep-all; - border-collapse: collapse; -} -.tsd-panel table th { - font-weight: bold; -} -.tsd-panel table th, -.tsd-panel table td { - padding: 6px 13px; - border: 1px solid var(--color-panel-divider); -} -.tsd-panel table tr { - background: var(--color-background); -} -.tsd-panel table tr:nth-child(even) { - background: var(--color-secondary-background); -} - -.tsd-panel-group { - margin: 60px 0; -} -.tsd-panel-group > h1, -.tsd-panel-group > h2, -.tsd-panel-group > h3 { - padding-left: 20px; - padding-right: 20px; -} - -#tsd-search { - transition: background-color 0.2s; -} -#tsd-search .title { - position: relative; - z-index: 2; -} -#tsd-search .field { - position: absolute; - left: 0; - top: 0; - right: 40px; - height: 40px; -} -#tsd-search .field input { - box-sizing: border-box; - position: relative; - top: -50px; - z-index: 1; - width: 100%; - padding: 0 10px; - opacity: 0; - outline: 0; - border: 0; - background: transparent; - color: var(--color-text); -} -#tsd-search .field label { - position: absolute; - overflow: hidden; - right: -40px; -} -#tsd-search .field input, -#tsd-search .title { - transition: opacity 0.2s; -} -#tsd-search .results { - position: absolute; - visibility: hidden; - top: 40px; - width: 100%; - margin: 0; - padding: 0; - list-style: none; - box-shadow: 0 0 4px rgba(0, 0, 0, 0.25); -} -#tsd-search .results li { - padding: 0 10px; - background-color: var(--color-background); -} -#tsd-search .results li:nth-child(even) { - background-color: var(--color-panel); -} -#tsd-search .results li.state { - display: none; -} -#tsd-search .results li.current, -#tsd-search .results li:hover { - background-color: var(--color-panel-divider); -} -#tsd-search .results a { - display: block; -} -#tsd-search .results a:before { - top: 10px; -} -#tsd-search .results span.parent { - color: var(--color-text-aside); - font-weight: normal; -} -#tsd-search.has-focus { - background-color: var(--color-panel-divider); -} -#tsd-search.has-focus .field input { - top: 0; - opacity: 1; -} -#tsd-search.has-focus .title { - z-index: 0; - opacity: 0; -} -#tsd-search.has-focus .results { - visibility: visible; -} -#tsd-search.loading .results li.state.loading { - display: block; -} -#tsd-search.failure .results li.state.failure { - display: block; -} - -.tsd-signature { - margin: 0 0 1em 0; - padding: 10px; - border: 1px solid var(--color-panel-divider); - font-family: Menlo, Monaco, Consolas, "Courier New", monospace; - font-size: 14px; - overflow-x: auto; -} -.tsd-signature.tsd-kind-icon { - padding-left: 30px; -} -.tsd-signature.tsd-kind-icon:before { - top: 10px; - left: 10px; -} -.tsd-panel > .tsd-signature { - margin-left: -20px; - margin-right: -20px; - border-width: 1px 0; -} -.tsd-panel > .tsd-signature.tsd-kind-icon { - padding-left: 40px; -} -.tsd-panel > .tsd-signature.tsd-kind-icon:before { - left: 20px; -} - -.tsd-signature-symbol { - color: var(--color-text-aside); - font-weight: normal; -} - -.tsd-signature-type { - font-style: italic; - font-weight: normal; -} - -.tsd-signatures { - padding: 0; - margin: 0 0 1em 0; - border: 1px solid var(--color-panel-divider); -} -.tsd-signatures .tsd-signature { - margin: 0; - border-width: 1px 0 0 0; - transition: background-color 0.1s; -} -.tsd-signatures .tsd-signature:first-child { - border-top-width: 0; -} -.tsd-signatures .tsd-signature.current { - background-color: var(--color-panel-divider); -} -.tsd-signatures.active > .tsd-signature { - cursor: pointer; -} -.tsd-panel > .tsd-signatures { - margin-left: -20px; - margin-right: -20px; - border-width: 1px 0; -} -.tsd-panel > .tsd-signatures .tsd-signature.tsd-kind-icon { - padding-left: 40px; -} -.tsd-panel > .tsd-signatures .tsd-signature.tsd-kind-icon:before { - left: 20px; -} -.tsd-panel > a.anchor + .tsd-signatures { - border-top-width: 0; - margin-top: -20px; -} - -ul.tsd-descriptions { - position: relative; - overflow: hidden; - padding: 0; - list-style: none; -} -ul.tsd-descriptions.active > .tsd-description { - display: none; -} -ul.tsd-descriptions.active > .tsd-description.current { - display: block; -} -ul.tsd-descriptions.active > .tsd-description.fade-in { - animation: fade-in-delayed 0.3s; -} -ul.tsd-descriptions.active > .tsd-description.fade-out { - animation: fade-out-delayed 0.3s; - position: absolute; - display: block; - top: 0; - left: 0; - right: 0; - opacity: 0; - visibility: hidden; -} -ul.tsd-descriptions h4, -ul.tsd-descriptions .tsd-index-panel h3, -.tsd-index-panel ul.tsd-descriptions h3 { - font-size: 16px; - margin: 1em 0 0.5em 0; -} - -ul.tsd-parameters, -ul.tsd-type-parameters { - list-style: square; - margin: 0; - padding-left: 20px; -} -ul.tsd-parameters > li.tsd-parameter-signature, -ul.tsd-type-parameters > li.tsd-parameter-signature { - list-style: none; - margin-left: -20px; -} -ul.tsd-parameters h5, -ul.tsd-type-parameters h5 { - font-size: 16px; - margin: 1em 0 0.5em 0; -} -ul.tsd-parameters .tsd-comment, -ul.tsd-type-parameters .tsd-comment { - margin-top: -0.5em; -} - -.tsd-sources { - font-size: 14px; - color: var(--color-text-aside); - margin: 0 0 1em 0; -} -.tsd-sources a { - color: var(--color-text-aside); - text-decoration: underline; -} -.tsd-sources ul, -.tsd-sources p { - margin: 0 !important; -} -.tsd-sources ul { - list-style: none; - padding: 0; -} - -.tsd-page-toolbar { - position: fixed; - z-index: 1; - top: 0; - left: 0; - width: 100%; - height: 40px; - color: var(--color-toolbar-text); - background: var(--color-toolbar); - border-bottom: 1px solid var(--color-panel-divider); - transition: transform 0.3s linear; -} -.tsd-page-toolbar a { - color: var(--color-toolbar-text); - text-decoration: none; -} -.tsd-page-toolbar a.title { - font-weight: bold; -} -.tsd-page-toolbar a.title:hover { - text-decoration: underline; -} -.tsd-page-toolbar .table-wrap { - display: table; - width: 100%; - height: 40px; -} -.tsd-page-toolbar .table-cell { - display: table-cell; - position: relative; - white-space: nowrap; - line-height: 40px; -} -.tsd-page-toolbar .table-cell:first-child { - width: 100%; -} - -.tsd-page-toolbar--hide { - transform: translateY(-100%); -} - -.tsd-select .tsd-select-list li:before, -.tsd-select .tsd-select-label:before, -.tsd-widget:before { - content: ""; - display: inline-block; - width: 40px; - height: 40px; - margin: 0 -8px 0 0; - background-image: url(./widgets.png); - background-repeat: no-repeat; - text-indent: -1024px; - vertical-align: bottom; - filter: var(--icon-filter); -} -@media (-webkit-min-device-pixel-ratio: 1.5), (min-resolution: 144dpi) { - .tsd-select .tsd-select-list li:before, - .tsd-select .tsd-select-label:before, - .tsd-widget:before { - background-image: url(./widgets@2x.png); - background-size: 320px 40px; - } -} - -.tsd-widget { - display: inline-block; - overflow: hidden; - opacity: 0.8; - height: 40px; - transition: opacity 0.1s, background-color 0.2s; - vertical-align: bottom; - cursor: pointer; -} -.tsd-widget:hover { - opacity: 0.9; -} -.tsd-widget.active { - opacity: 1; - background-color: var(--color-panel-divider); -} -.tsd-widget.no-caption { - width: 40px; -} -.tsd-widget.no-caption:before { - margin: 0; -} -.tsd-widget.search:before { - background-position: 0 0; -} -.tsd-widget.menu:before { - background-position: -40px 0; -} -.tsd-widget.options:before { - background-position: -80px 0; -} -.tsd-widget.options, -.tsd-widget.menu { - display: none; -} -@media (max-width: 900px) { - .tsd-widget.options, - .tsd-widget.menu { - display: inline-block; - } -} -input[type="checkbox"] + .tsd-widget:before { - background-position: -120px 0; -} -input[type="checkbox"]:checked + .tsd-widget:before { - background-position: -160px 0; -} - -.tsd-select { - position: relative; - display: inline-block; - height: 40px; - transition: opacity 0.1s, background-color 0.2s; - vertical-align: bottom; - cursor: pointer; -} -.tsd-select .tsd-select-label { - opacity: 0.6; - transition: opacity 0.2s; -} -.tsd-select .tsd-select-label:before { - background-position: -240px 0; -} -.tsd-select.active .tsd-select-label { - opacity: 0.8; -} -.tsd-select.active .tsd-select-list { - visibility: visible; - opacity: 1; - transition-delay: 0s; -} -.tsd-select .tsd-select-list { - position: absolute; - visibility: hidden; - top: 40px; - left: 0; - margin: 0; - padding: 0; - opacity: 0; - list-style: none; - box-shadow: 0 0 4px rgba(0, 0, 0, 0.25); - transition: visibility 0s 0.2s, opacity 0.2s; -} -.tsd-select .tsd-select-list li { - padding: 0 20px 0 0; - background-color: var(--color-background); -} -.tsd-select .tsd-select-list li:before { - background-position: 40px 0; -} -.tsd-select .tsd-select-list li:nth-child(even) { - background-color: var(--color-panel); -} -.tsd-select .tsd-select-list li:hover { - background-color: var(--color-panel-divider); -} -.tsd-select .tsd-select-list li.selected:before { - background-position: -200px 0; -} -@media (max-width: 900px) { - .tsd-select .tsd-select-list { - top: 0; - left: auto; - right: 100%; - margin-right: -5px; - } - .tsd-select .tsd-select-label:before { - background-position: -280px 0; - } -} - -img { - max-width: 100%; -} - -.tsd-anchor-icon { - margin-left: 10px; - vertical-align: middle; - color: var(--color-text); -} - -.tsd-anchor-icon svg { - width: 1em; - height: 1em; - visibility: hidden; -} - -.tsd-anchor-link:hover > .tsd-anchor-icon svg { - visibility: visible; -} diff --git a/docs/assets/widgets.png b/docs/assets/widgets.png deleted file mode 100644 index c738053..0000000 Binary files a/docs/assets/widgets.png and /dev/null differ diff --git a/docs/assets/widgets@2x.png b/docs/assets/widgets@2x.png deleted file mode 100644 index 4bbbd57..0000000 Binary files a/docs/assets/widgets@2x.png and /dev/null differ diff --git a/docs/classes/PDAUtil.html b/docs/classes/PDAUtil.html deleted file mode 100644 index 49c2026..0000000 --- a/docs/classes/PDAUtil.html +++ /dev/null @@ -1,4 +0,0 @@ -PDAUtil | @orca-so/whirlpools-sdk
Options
All
  • Public
  • Public/Protected
  • All
Menu

Hierarchy

  • PDAUtil

Index

Other

  • getTickArrayFromSqrtPrice(sqrtPriceX64: BN, tickSpacing: number, whirlpool: PublicKey, programId: PublicKey, tickArrayOffset?: number): PDA
  • Parameters

    • sqrtPriceX64: BN
    • tickSpacing: number
    • whirlpool: PublicKey
    • programId: PublicKey
    • tickArrayOffset: number = 0

    Returns PDA

  • getTickArrayFromTickIndex(tickIndex: number, tickSpacing: number, whirlpool: PublicKey, programId: PublicKey, tickArrayOffset?: number): PDA
  • -

    Get the PDA of the tick array containing tickIndex. -tickArrayOffset can be used to get neighboring tick arrays.

    -

    Parameters

    • tickIndex: number
    • tickSpacing: number
    • whirlpool: PublicKey
    • programId: PublicKey
    • tickArrayOffset: number = 0

    Returns PDA

  • getWhirlpool(programId: PublicKey, whirlpoolsConfigKey: PublicKey, tokenMintAKey: PublicKey, tokenMintBKey: PublicKey, tickSpacing: number): PDA
  • Parameters

    • programId: PublicKey
    • whirlpoolsConfigKey: PublicKey
    • tokenMintAKey: PublicKey
    • tokenMintBKey: PublicKey
    • tickSpacing: number

    Returns PDA

Program Derived Addresses

  • getBundledPosition(programId: PublicKey, positionBundleMintKey: PublicKey, bundleIndex: number): PDA
  • getFeeTier(programId: PublicKey, whirlpoolsConfigAddress: PublicKey, tickSpacing: number): PDA
  • getOracle(programId: PublicKey, whirlpoolAddress: PublicKey): PDA
  • getPosition(programId: PublicKey, positionMintKey: PublicKey): PDA
  • getPositionBundle(programId: PublicKey, positionBundleMintKey: PublicKey): PDA
  • getPositionBundleMetadata(positionBundleMintKey: PublicKey): PDA
  • getPositionMetadata(positionMintKey: PublicKey): PDA
  • getTickArray(programId: PublicKey, whirlpoolAddress: PublicKey, startTick: number): PDA

Legend

  • Constructor
  • Property
  • Method
  • Property
  • Method
  • Static property
  • Static method

Settings

Theme

Generated using TypeDoc

\ No newline at end of file diff --git a/docs/classes/ParsableFeeTier.html b/docs/classes/ParsableFeeTier.html deleted file mode 100644 index 9353f80..0000000 --- a/docs/classes/ParsableFeeTier.html +++ /dev/null @@ -1 +0,0 @@ -ParsableFeeTier | @orca-so/whirlpools-sdk
Options
All
  • Public
  • Public/Protected
  • All
Menu

Hierarchy

  • ParsableFeeTier

Index

Methods

Methods

  • parse(address: PublicKey, accountData: undefined | null | AccountInfo<Buffer>): null | FeeTierData

Legend

  • Constructor
  • Property
  • Method
  • Property
  • Method
  • Static property
  • Static method

Settings

Theme

Generated using TypeDoc

\ No newline at end of file diff --git a/docs/classes/ParsablePosition.html b/docs/classes/ParsablePosition.html deleted file mode 100644 index 26976b3..0000000 --- a/docs/classes/ParsablePosition.html +++ /dev/null @@ -1 +0,0 @@ -ParsablePosition | @orca-so/whirlpools-sdk
Options
All
  • Public
  • Public/Protected
  • All
Menu

Hierarchy

  • ParsablePosition

Index

Methods

Methods

  • parse(address: PublicKey, accountData: undefined | null | AccountInfo<Buffer>): null | PositionData

Legend

  • Constructor
  • Property
  • Method
  • Property
  • Method
  • Static property
  • Static method

Settings

Theme

Generated using TypeDoc

\ No newline at end of file diff --git a/docs/classes/ParsablePositionBundle.html b/docs/classes/ParsablePositionBundle.html deleted file mode 100644 index 05a06a1..0000000 --- a/docs/classes/ParsablePositionBundle.html +++ /dev/null @@ -1 +0,0 @@ -ParsablePositionBundle | @orca-so/whirlpools-sdk
Options
All
  • Public
  • Public/Protected
  • All
Menu

Hierarchy

  • ParsablePositionBundle

Index

Methods

Methods

  • parse(address: PublicKey, accountData: undefined | null | AccountInfo<Buffer>): null | PositionBundleData

Legend

  • Constructor
  • Property
  • Method
  • Property
  • Method
  • Static property
  • Static method

Settings

Theme

Generated using TypeDoc

\ No newline at end of file diff --git a/docs/classes/ParsableTickArray.html b/docs/classes/ParsableTickArray.html deleted file mode 100644 index 53f2bd7..0000000 --- a/docs/classes/ParsableTickArray.html +++ /dev/null @@ -1 +0,0 @@ -ParsableTickArray | @orca-so/whirlpools-sdk
Options
All
  • Public
  • Public/Protected
  • All
Menu

Hierarchy

  • ParsableTickArray

Index

Methods

Methods

  • parse(address: PublicKey, accountData: undefined | null | AccountInfo<Buffer>): null | TickArrayData

Legend

  • Constructor
  • Property
  • Method
  • Property
  • Method
  • Static property
  • Static method

Settings

Theme

Generated using TypeDoc

\ No newline at end of file diff --git a/docs/classes/ParsableWhirlpool.html b/docs/classes/ParsableWhirlpool.html deleted file mode 100644 index c0d077d..0000000 --- a/docs/classes/ParsableWhirlpool.html +++ /dev/null @@ -1 +0,0 @@ -ParsableWhirlpool | @orca-so/whirlpools-sdk
Options
All
  • Public
  • Public/Protected
  • All
Menu

Hierarchy

  • ParsableWhirlpool

Index

Methods

Methods

  • parse(address: PublicKey, accountData: undefined | null | AccountInfo<Buffer>): null | WhirlpoolData

Legend

  • Constructor
  • Property
  • Method
  • Property
  • Method
  • Static property
  • Static method

Settings

Theme

Generated using TypeDoc

\ No newline at end of file diff --git a/docs/classes/ParsableWhirlpoolsConfig.html b/docs/classes/ParsableWhirlpoolsConfig.html deleted file mode 100644 index 1adc54e..0000000 --- a/docs/classes/ParsableWhirlpoolsConfig.html +++ /dev/null @@ -1 +0,0 @@ -ParsableWhirlpoolsConfig | @orca-so/whirlpools-sdk
Options
All
  • Public
  • Public/Protected
  • All
Menu

Hierarchy

  • ParsableWhirlpoolsConfig

Index

Methods

Methods

  • parse(address: PublicKey, accountData: undefined | null | AccountInfo<Buffer>): null | WhirlpoolsConfigData

Legend

  • Constructor
  • Property
  • Method
  • Property
  • Method
  • Static property
  • Static method

Settings

Theme

Generated using TypeDoc

\ No newline at end of file diff --git a/docs/classes/PoolGraphBuilder.html b/docs/classes/PoolGraphBuilder.html deleted file mode 100644 index 7abae05..0000000 --- a/docs/classes/PoolGraphBuilder.html +++ /dev/null @@ -1,15 +0,0 @@ -PoolGraphBuilder | @orca-so/whirlpools-sdk
Options
All
  • Public
  • Public/Protected
  • All
Menu
-

A builder class for creating a PoolGraph

-

Note: we use an adjacency list as a representation of our pool graph, -since we assume that most token pairings don't exist as pools

-

Hierarchy

  • PoolGraphBuilder

Index

Constructors

Methods

Legend

  • Constructor
  • Property
  • Method
  • Property
  • Method
  • Static property
  • Static method

Settings

Theme

Generated using TypeDoc

\ No newline at end of file diff --git a/docs/classes/PoolGraphUtils.html b/docs/classes/PoolGraphUtils.html deleted file mode 100644 index a5498b5..0000000 --- a/docs/classes/PoolGraphUtils.html +++ /dev/null @@ -1,15 +0,0 @@ -PoolGraphUtils | @orca-so/whirlpools-sdk
Options
All
  • Public
  • Public/Protected
  • All
Menu
-

A utility class for working with pool graphs

-

Hierarchy

  • PoolGraphUtils

Index

Constructors

Properties

PATH_ID_DELIMITER: "-" = "-"

Methods

  • deconstructPathId(pathId: string): readonly [string, string]
  • -

    Deconstruct a path id into the two tokens it represents

    -

    Parameters

    • pathId: string
      -

      The path id to deconstruct

      -

    Returns readonly [string, string]

    A tuple of the two tokens in the path id. Returns undefined if the provided pathId is invalid.

    -
  • getSearchPathId(tokenA: Address, tokenB: Address): string
  • -

    Get a search path id from two tokens. The id can be used to identify a path between the two tokens in PathSearchEntries.

    -

    Parameters

    • tokenA: Address
      -

      The first token in the path

      -
    • tokenB: Address
      -

      The second token in the path

      -

    Returns string

    A path id that can be used to identify a path between the two tokens in PathSearchEntries.

    -

Legend

  • Constructor
  • Property
  • Method
  • Property
  • Method
  • Static property
  • Static method

Settings

Theme

Generated using TypeDoc

\ No newline at end of file diff --git a/docs/classes/PoolUtil.html b/docs/classes/PoolUtil.html deleted file mode 100644 index d110918..0000000 --- a/docs/classes/PoolUtil.html +++ /dev/null @@ -1,29 +0,0 @@ -PoolUtil | @orca-so/whirlpools-sdk
Options
All
  • Public
  • Public/Protected
  • All
Menu

Hierarchy

  • PoolUtil

Index

Other

  • compareMints(mintX: Address, mintY: Address): number
  • getFeeRate(feeRate: number): Percentage
  • getProtocolFeeRate(protocolFeeRate: number): Percentage
  • -

    Return the corresponding token type (TokenA/B) for this mint key for a Whirlpool.

    -

    Parameters

    • pool: WhirlpoolData
      -

      The Whirlpool to evaluate the mint against

      -
    • mint: PublicKey
      -

      The token mint PublicKey

      -

    Returns undefined | TokenType

    The match result in the form of TokenType enum. undefined if the token mint is not part of the trade pair of the pool.

    -
  • orderMints(mintX: Address, mintY: Address): [Address, Address]

Whirlpool Utils

  • estimateLiquidityFromTokenAmounts(currTick: number, lowerTick: number, upperTick: number, tokenAmount: TokenAmounts): BN
  • -

    Estimate the liquidity amount required to increase/decrease liquidity.

    -

    // TODO: At the top end of the price range, tick calcuation is off therefore the results can be off

    -

    Parameters

    • currTick: number
      -

      Whirlpool's current tick index (aka price)

      -
    • lowerTick: number
      -

      Position lower tick index

      -
    • upperTick: number
      -

      Position upper tick index

      -
    • tokenAmount: TokenAmounts
      -

      The desired amount of tokens to deposit/withdraw

      -

    Returns BN

    An estimated amount of liquidity needed to deposit/withdraw the desired amount of tokens.

    -
  • getTokenAmountsFromLiquidity(liquidity: BN, currentSqrtPrice: BN, lowerSqrtPrice: BN, upperSqrtPrice: BN, round_up: boolean): TokenAmounts
  • toBaseQuoteOrder(tokenMintAKey: PublicKey, tokenMintBKey: PublicKey): [PublicKey, PublicKey]
  • -

    Given an arbitrary pair of token mints, this function returns an ordering of the token mints -in the format [base, quote]. USD based stable coins are prioritized as the quote currency -followed by variants of SOL.

    -

    Parameters

    • tokenMintAKey: PublicKey
      -

      The mint of token A in the token pair.

      -
    • tokenMintBKey: PublicKey
      -

      The mint of token B in the token pair.

      -

    Returns [PublicKey, PublicKey]

    A two-element array with the tokens sorted in the order of [baseToken, quoteToken].

    -

Legend

  • Constructor
  • Property
  • Method
  • Property
  • Method
  • Static property
  • Static method

Settings

Theme

Generated using TypeDoc

\ No newline at end of file diff --git a/docs/classes/PositionBundleUtil.html b/docs/classes/PositionBundleUtil.html deleted file mode 100644 index c634ce6..0000000 --- a/docs/classes/PositionBundleUtil.html +++ /dev/null @@ -1,52 +0,0 @@ -PositionBundleUtil | @orca-so/whirlpools-sdk
Options
All
  • Public
  • Public/Protected
  • All
Menu
-

A collection of utility functions when interacting with a PositionBundle.

-

Hierarchy

  • PositionBundleUtil

Index

Methods

  • checkBundleIndexInBounds(bundleIndex: number): boolean
  • -

    Check if the bundle index is in the correct range.

    -

    Parameters

    • bundleIndex: number
      -

      The bundle index to be checked

      -

    Returns boolean

    true if bundle index is in the correct range

    -
  • -

    Convert position bitmap to the array of boolean which represent if Bundled Position is open.

    -

    Parameters

    Returns boolean[]

    The array of boolean representing if Bundled Position is open

    -
  • -

    Get the first unoccupied bundle index in the position bundle.

    -

    Parameters

    Returns null | number

    The first unoccupied bundle index, null if the position bundle is full

    -
  • -

    Get all bundle indexes where the corresponding Bundled Position is open.

    -

    Parameters

    Returns number[]

    The array of bundle index where the corresponding Bundled Position is open

    -
  • -

    Get all bundle indexes where the corresponding Bundled Position is not open.

    -

    Parameters

    Returns number[]

    The array of bundle index where the corresponding Bundled Position is not open

    -
  • -

    Check if the Bundled Position corresponding to the bundle index has been opened.

    -

    Parameters

    • positionBundle: PositionBundleData
      -

      The position bundle to be checked

      -
    • bundleIndex: number
      -

      The bundle index to be checked

      -

    Returns boolean

    true if Bundled Position has been opened

    -
  • -

    Check if the Bundled Position corresponding to the bundle index has not been opened.

    -

    Parameters

    • positionBundle: PositionBundleData
      -

      The position bundle to be checked

      -
    • bundleIndex: number
      -

      The bundle index to be checked

      -

    Returns boolean

    true if Bundled Position has not been opened

    -

Legend

  • Constructor
  • Property
  • Method
  • Property
  • Method
  • Static property
  • Static method

Settings

Theme

Generated using TypeDoc

\ No newline at end of file diff --git a/docs/classes/PriceMath.html b/docs/classes/PriceMath.html deleted file mode 100644 index a128545..0000000 --- a/docs/classes/PriceMath.html +++ /dev/null @@ -1,19 +0,0 @@ -PriceMath | @orca-so/whirlpools-sdk
Options
All
  • Public
  • Public/Protected
  • All
Menu
-

A collection of utility functions to convert between price, tickIndex and sqrtPrice.

-

Hierarchy

  • PriceMath

Index

Constructors

Methods

  • invertPrice(price: Decimal, decimalsA: number, decimalsB: number): Decimal
  • -

    Utility to invert the price Pb/Pa to Pa/Pb -NOTE: precision is lost in this conversion

    -

    Parameters

    • price: Decimal
      -

      Pb / Pa

      -
    • decimalsA: number
      -

      Decimals of original token A (i.e. token A in the given Pb / Pa price)

      -
    • decimalsB: number
      -

      Decimals of original token B (i.e. token B in the given Pb / Pa price)

      -

    Returns Decimal

    inverted price, i.e. Pa / Pb

    -
  • invertSqrtPriceX64(sqrtPriceX64: BN): BN
  • -

    Utility to invert the sqrtPriceX64 from X64 repr. of sqrt(Pb/Pa) to X64 repr. of sqrt(Pa/Pb) -NOTE: precision is lost in this conversion

    -

    Parameters

    • sqrtPriceX64: BN
      -

      X64 representation of sqrt(Pb / Pa)

      -

    Returns BN

    inverted sqrtPriceX64, i.e. X64 representation of sqrt(Pa / Pb)

    -
  • priceToInitializableTickIndex(price: Decimal, decimalsA: number, decimalsB: number, tickSpacing: number): number
  • priceToSqrtPriceX64(price: Decimal, decimalsA: number, decimalsB: number): BN
  • priceToTickIndex(price: Decimal, decimalsA: number, decimalsB: number): number
  • sqrtPriceX64ToPrice(sqrtPriceX64: BN, decimalsA: number, decimalsB: number): Decimal
  • sqrtPriceX64ToTickIndex(sqrtPriceX64: BN): number
  • tickIndexToPrice(tickIndex: number, decimalsA: number, decimalsB: number): Decimal
  • tickIndexToSqrtPriceX64(tickIndex: number): BN

Legend

  • Constructor
  • Property
  • Method
  • Property
  • Method
  • Static property
  • Static method

Settings

Theme

Generated using TypeDoc

\ No newline at end of file diff --git a/docs/classes/PriceModule.html b/docs/classes/PriceModule.html deleted file mode 100644 index 06b13e0..0000000 --- a/docs/classes/PriceModule.html +++ /dev/null @@ -1,49 +0,0 @@ -PriceModule | @orca-so/whirlpools-sdk
Options
All
  • Public
  • Public/Protected
  • All
Menu
-

PriceModule is a static class that provides functions for fetching and calculating -token prices for a set of pools or mints.

-

Hierarchy

  • PriceModule

Index

Other

PriceModule

  • -

    Calculate the price of each token in the mints array.

    -

    Each token will be priced against the first quote token in the config.quoteTokens array -with sufficient liquidity. If a token does not have sufficient liquidity against the -first quote token, then it will be priced against the next quote token in the array. -If a token does not have sufficient liquidity against any quote token, -then the price will be set to null.

    -

    Parameters

    • mints: Address[]
      -

      The mints to calculate prices for.

      -
    • priceCalcData: PriceCalculationData
      -

      The data required to calculate prices.

      -
    • config: GetPricesConfig = defaultGetPricesConfig
      -

      The configuration for the price calculation.

      -
    • thresholdConfig: GetPricesThresholdConfig = defaultGetPricesThresholdConfig
      -

      The threshold configuration for the price calculation.

      -

    Returns PriceMap

    A map of token addresses to prices.

    -

Legend

  • Constructor
  • Property
  • Method
  • Property
  • Method
  • Static property
  • Static method

Settings

Theme

Generated using TypeDoc

\ No newline at end of file diff --git a/docs/classes/PriceModuleUtils.html b/docs/classes/PriceModuleUtils.html deleted file mode 100644 index 3c52bfe..0000000 --- a/docs/classes/PriceModuleUtils.html +++ /dev/null @@ -1,35 +0,0 @@ -PriceModuleUtils | @orca-so/whirlpools-sdk
Options
All
  • Public
  • Public/Protected
  • All
Menu
-

A list of utility functions for the price module.

-

Hierarchy

  • PriceModuleUtils

Index

Constructors

Methods

Legend

  • Constructor
  • Property
  • Method
  • Property
  • Method
  • Static property
  • Static method

Settings

Theme

Generated using TypeDoc

\ No newline at end of file diff --git a/docs/classes/RouterUtils.html b/docs/classes/RouterUtils.html deleted file mode 100644 index cbf0e80..0000000 --- a/docs/classes/RouterUtils.html +++ /dev/null @@ -1,32 +0,0 @@ -RouterUtils | @orca-so/whirlpools-sdk
Options
All
  • Public
  • Public/Protected
  • All
Menu
-

A selection of utility functions for the WhirlpoolRouter.

-

Hierarchy

  • RouterUtils

Index

Constructors

Methods

  • -

    Calculate the price impact for a route.

    -

    Parameters

    • trade: Trade
      -

      The trade the user used to derive the route.

      -
    • route: TradeRoute
      -

      The route to calculate the price impact for.

      -

    Returns Decimal

    A Decimal object representing the percentage value of the price impact (ex. 3.01%)

    -
  • getTouchedTickArraysFromRoute(route: TradeRoute): PublicKey[]
  • -

    Get the tick arrays addresses that are touched by a route.

    -

    Parameters

    • route: TradeRoute
      -

      The route to get the tick arrays from.

      -

    Returns PublicKey[]

    The tick arrays addresses that are touched by the route.

    -
  • -

    Selects the best executable route from a list of routes using the current execution environment. -The wallet support type, available ATA accounts, existance of lookup tables all effect the transaction size -and eligibility of a route.

    -

    Parameters

    Returns Promise<null | ExecutableRoute>

    The best ExecutableRoute that can be used to execute a swap. If no executable route is found, null is returned.

    -

Legend

  • Constructor
  • Property
  • Method
  • Property
  • Method
  • Static property
  • Static method

Settings

Theme

Generated using TypeDoc

\ No newline at end of file diff --git a/docs/classes/SwapUtils.html b/docs/classes/SwapUtils.html deleted file mode 100644 index f5953c6..0000000 --- a/docs/classes/SwapUtils.html +++ /dev/null @@ -1,88 +0,0 @@ -SwapUtils | @orca-so/whirlpools-sdk
Options
All
  • Public
  • Public/Protected
  • All
Menu

Hierarchy

  • SwapUtils

Index

Other

  • calculateSwapAmountsFromQuote(amount: BN, estAmountIn: BN, estAmountOut: BN, slippageTolerance: Percentage, amountSpecifiedIsInput: boolean): Pick<SwapInput, "amount" | "otherAmountThreshold">
  • -

    Calculate the SwapInput parameters amount & otherAmountThreshold based on the amountIn & amountOut estimates from a quote.

    -

    Parameters

    • amount: BN
      -

      The amount of tokens the user wanted to swap from.

      -
    • estAmountIn: BN
      -

      The estimated amount of input tokens expected in a SwapQuote

      -
    • estAmountOut: BN
      -

      The estimated amount of output tokens expected from a SwapQuote

      -
    • slippageTolerance: Percentage
      -

      The amount of slippage to adjust for.

      -
    • amountSpecifiedIsInput: boolean
      -

      Specifies the token the parameter amountrepresents in the swap quote. If true, the amount represents - the input token of the swap.

      -

    Returns Pick<SwapInput, "amount" | "otherAmountThreshold">

    A Partial SwapInput object containing the slippage adjusted 'amount' & 'otherAmountThreshold' parameters.

    -
  • getDefaultOtherAmountThreshold(amountSpecifiedIsInput: boolean): BN
  • -

    Get the default values for the otherAmountThreshold parameter in a swap.

    -

    Parameters

    • amountSpecifiedIsInput: boolean
      -

      The direction of a swap

      -

    Returns BN

    The default values for the otherAmountThreshold parameter in a swap.

    -
  • getDefaultSqrtPriceLimit(aToB: boolean): BN
  • -

    Get the default values for the sqrtPriceLimit parameter in a swap.

    -

    Parameters

    • aToB: boolean
      -

      The direction of a swap

      -

    Returns BN

    The default values for the sqrtPriceLimit parameter in a swap.

    -
  • -

    Given the intended token mint to swap, return the swap direction of a swap for a Whirlpool

    -

    Parameters

    • pool: WhirlpoolData
      -

      The Whirlpool to evaluate the mint against

      -
    • swapTokenMint: PublicKey
      -

      The token mint PublicKey the user bases their swap against

      -
    • swapTokenIsInput: boolean
      -

      Whether the swap token is the input token. (similar to amountSpecifiedIsInput from swap Ix)

      -

    Returns undefined | SwapDirection

    The direction of the swap given the swapTokenMint. undefined if the token mint is not part of the trade pair of the pool.

    -
  • getSwapParamsFromQuoteKeys(quote: SwapInput, ctx: WhirlpoolContext, whirlpool: PublicKey, tokenVaultA: PublicKey, tokenVaultB: PublicKey, inputTokenAssociatedAddress: Address, outputTokenAssociatedAddress: Address, wallet: PublicKey): SwapParams

Whirlpool Utils

  • getTickArrayPublicKeys(tickCurrentIndex: number, tickSpacing: number, aToB: boolean, programId: PublicKey, whirlpoolAddress: PublicKey): PublicKey[]
  • -

    Given the current tick-index, returns the dervied PDA and fetched data -for the tick-arrays that this swap may traverse across.

    -

    Parameters

    • tickCurrentIndex: number
      -

      The current tickIndex for the Whirlpool to swap on.

      -
    • tickSpacing: number
      -

      The tickSpacing for the Whirlpool.

      -
    • aToB: boolean
      -

      The direction of the trade.

      -
    • programId: PublicKey
      -

      The Whirlpool programId which the Whirlpool lives on.

      -
    • whirlpoolAddress: PublicKey
      -

      PublicKey of the whirlpool to swap on.

      -

    Returns PublicKey[]

    An array of PublicKey[] for the tickArray accounts that this swap may traverse across.

    -
  • getTickArrays(tickCurrentIndex: number, tickSpacing: number, aToB: boolean, programId: PublicKey, whirlpoolAddress: PublicKey, fetcher: WhirlpoolAccountFetcherInterface, opts?: SimpleAccountFetchOptions): Promise<TickArray[]>
  • -

    Given the current tick-index, returns TickArray objects that this swap may traverse across.

    -

    Parameters

    • tickCurrentIndex: number
      -

      The current tickIndex for the Whirlpool to swap on.

      -
    • tickSpacing: number
      -

      The tickSpacing for the Whirlpool.

      -
    • aToB: boolean
      -

      The direction of the trade.

      -
    • programId: PublicKey
      -

      The Whirlpool programId which the Whirlpool lives on.

      -
    • whirlpoolAddress: PublicKey
      -

      PublicKey of the whirlpool to swap on.

      -
    • fetcher: WhirlpoolAccountFetcherInterface
    • Optional opts: SimpleAccountFetchOptions
      -

      an WhirlpoolAccountFetchOptions object to define fetch and cache options when accessing on-chain accounts

      -

    Returns Promise<TickArray[]>

    An array of PublicKey[] for the tickArray accounts that this swap may traverse across.

    -

Legend

  • Constructor
  • Property
  • Method
  • Property
  • Method
  • Static property
  • Static method

Settings

Theme

Generated using TypeDoc

\ No newline at end of file diff --git a/docs/classes/TickArrayUtil.html b/docs/classes/TickArrayUtil.html deleted file mode 100644 index f03c883..0000000 --- a/docs/classes/TickArrayUtil.html +++ /dev/null @@ -1,31 +0,0 @@ -TickArrayUtil | @orca-so/whirlpools-sdk
Options
All
  • Public
  • Public/Protected
  • All
Menu
-

A collection of utility functions when interacting with a TickArray.

-

Hierarchy

  • TickArrayUtil

Index

Constructors

Methods

  • getTickArrayPDAs(tick: number, tickSpacing: number, numOfTickArrays: number, programId: PublicKey, whirlpoolAddress: PublicKey, aToB: boolean): PDA[]
  • -

    Return a sequence of tick array pdas based on the sequence start index.

    -

    Parameters

    • tick: number
      -

      A tick in the first tick-array of your sequence

      -
    • tickSpacing: number
      -

      Tick spacing for the whirlpool

      -
    • numOfTickArrays: number
      -

      The number of TickArray PDAs to generate

      -
    • programId: PublicKey
      -

      Program Id of the whirlpool for these tick-arrays

      -
    • whirlpoolAddress: PublicKey
      -

      Address for the Whirlpool for these tick-arrays

      -
    • aToB: boolean

    Returns PDA[]

    TickArray PDAs for the sequence`

    -
  • getUninitializedArrays(tickArrays: readonly (null | TickArrayData)[]): number[]
  • -

    Evaluate a list of tick-array data and return the array of indices which the tick-arrays are not initialized.

    -

    Parameters

    • tickArrays: readonly (null | TickArrayData)[]
      -

      a list of TickArrayData or null objects from WhirlpoolAccountCacheInterface.getTickArrays

      -

    Returns number[]

    an array of array-index for the input tickArrays that requires initialization.

    -
  • getUninitializedArraysPDAs(ticks: number[], programId: PublicKey, whirlpoolAddress: PublicKey, tickSpacing: number, fetcher: WhirlpoolAccountFetcherInterface, opts: SimpleAccountFetchOptions): Promise<{ pda: PDA; startIndex: number }[]>
  • -

    Return a string containing all of the uninitialized arrays in the provided addresses. -Useful for creating error messages.

    -

    Parameters

    Returns Promise<null | string>

    A string of all uninitialized tick array addresses, delimited by ",". Falsy value if all arrays are initialized.

    -

Legend

  • Constructor
  • Property
  • Method
  • Property
  • Method
  • Static property
  • Static method

Settings

Theme

Generated using TypeDoc

\ No newline at end of file diff --git a/docs/classes/TickUtil.html b/docs/classes/TickUtil.html deleted file mode 100644 index f9ff16d..0000000 --- a/docs/classes/TickUtil.html +++ /dev/null @@ -1,43 +0,0 @@ -TickUtil | @orca-so/whirlpools-sdk
Options
All
  • Public
  • Public/Protected
  • All
Menu
-

A collection of utility functions when interacting with Ticks.

-

Hierarchy

  • TickUtil

Index

Methods

  • checkTickInBounds(tick: number): boolean
  • findNextInitializedTickIndex(account: TickArrayData, currentTickIndex: number, tickSpacing: number): null | number
  • findPreviousInitializedTickIndex(account: TickArrayData, currentTickIndex: number, tickSpacing: number): null | number
  • getFullRangeTickIndex(tickSpacing: number): [number, number]
  • -

    Get the minimum and maximum tick index that can be initialized.

    -

    Parameters

    • tickSpacing: number
      -

      The tickSpacing for the Whirlpool

      -

    Returns [number, number]

    An array of numbers where the first element is the minimum tick index and the second element is the maximum tick index.

    -
  • getInitializableTickIndex(tickIndex: number, tickSpacing: number): number
  • -

    Get the nearest (rounding down) valid tick index from the tickIndex. -A valid tick index is a point on the tick spacing grid line.

    -

    Parameters

    • tickIndex: number
    • tickSpacing: number

    Returns number

  • getNextInitializableTickIndex(tickIndex: number, tickSpacing: number): number
  • getOffsetIndex(tickIndex: number, arrayStartIndex: number, tickSpacing: number): number
  • -

    Get the offset index to access a tick at a given tick-index in a tick-array

    -

    Parameters

    • tickIndex: number
      -

      The tick index for the tick that this offset would access

      -
    • arrayStartIndex: number
      -

      The starting tick for the array that this tick-index resides in

      -
    • tickSpacing: number
      -

      The tickSpacing for the Whirlpool that this tickArray belongs to

      -

    Returns number

    The offset index that can access the desired tick at the given tick-array

    -
  • getPrevInitializableTickIndex(tickIndex: number, tickSpacing: number): number
  • getStartTickIndex(tickIndex: number, tickSpacing: number, offset?: number): number
  • -

    Get the startIndex of the tick array containing tickIndex.

    -

    Parameters

    • tickIndex: number
    • tickSpacing: number
    • offset: number = 0
      -

      can be used to get neighboring tick array startIndex.

      -

    Returns number

  • invertTick(tick: number): number
  • -

    Returns the tick 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: number
      -

      The tick to invert

      -

    Returns number

  • isFullRange(tickSpacing: number, tickLowerIndex: number, tickUpperIndex: number): boolean
  • -

    Check if the tick range is the full range of the Whirlpool.

    -

    Parameters

    • tickSpacing: number
      -

      The tickSpacing for the Whirlpool

      -
    • tickLowerIndex: number
      -

      The lower tick index of the range

      -
    • tickUpperIndex: number
      -

      The upper tick index of the range

      -

    Returns boolean

    true if the range is the full range of the Whirlpool, false otherwise.

    -
  • isTickInitializable(tick: number, tickSpacing: number): boolean

Legend

  • Constructor
  • Property
  • Method
  • Property
  • Method
  • Static property
  • Static method

Settings

Theme

Generated using TypeDoc

\ No newline at end of file diff --git a/docs/classes/WhirlpoolAccountFetcher.html b/docs/classes/WhirlpoolAccountFetcher.html deleted file mode 100644 index 84d62c5..0000000 --- a/docs/classes/WhirlpoolAccountFetcher.html +++ /dev/null @@ -1,40 +0,0 @@ -WhirlpoolAccountFetcher | @orca-so/whirlpools-sdk
Options
All
  • Public
  • Public/Protected
  • All
Menu
-

Fetcher and cache layer for fetching WhirlpoolSupportedTypes from the network -Default implementation for WhirlpoolAccountFetcherInterface

-

Hierarchy

  • WhirlpoolAccountFetcher

Implements

Index

Constructors

Properties

connection: Connection
fetcher: AccountFetcher<WhirlpoolSupportedTypes, SimpleAccountFetchOptions>

Methods

  • getAccountRentExempt(refresh?: boolean): Promise<number>
  • getConfigs(addresses: Address[], opts?: SimpleAccountFetchOptions): Promise<ReadonlyMap<string, null | WhirlpoolsConfigData>>
  • getFeeTier(address: Address, opts?: SimpleAccountFetchOptions): Promise<null | FeeTierData>
  • getFeeTiers(addresses: Address[], opts?: SimpleAccountFetchOptions): Promise<ReadonlyMap<string, null | FeeTierData>>
  • getMintInfo(address: Address, opts?: SimpleAccountFetchOptions): Promise<null | Mint>
  • getMintInfos(addresses: Address[], opts?: SimpleAccountFetchOptions): Promise<ReadonlyMap<string, null | Mint>>
  • getPool(address: Address, opts?: SimpleAccountFetchOptions): Promise<null | WhirlpoolData>
  • getPools(addresses: Address[], opts?: SimpleAccountFetchOptions): Promise<ReadonlyMap<string, null | WhirlpoolData>>
  • getPosition(address: Address, opts?: SimpleAccountFetchOptions): Promise<null | PositionData>
  • getPositionBundle(address: Address, opts?: SimpleAccountFetchOptions): Promise<null | PositionBundleData>
  • getPositionBundles(addresses: Address[], opts?: SimpleAccountFetchOptions): Promise<ReadonlyMap<string, null | PositionBundleData>>
  • getPositions(addresses: Address[], opts?: SimpleAccountFetchOptions): Promise<ReadonlyMap<string, null | PositionData>>
  • getTickArray(address: Address, opts?: SimpleAccountFetchOptions): Promise<null | TickArrayData>
  • getTickArrays(addresses: Address[], opts?: SimpleAccountFetchOptions): Promise<readonly (null | TickArrayData)[]>
  • getTokenInfo(address: Address, opts?: SimpleAccountFetchOptions): Promise<null | Account>
  • getTokenInfos(addresses: Address[], opts?: SimpleAccountFetchOptions): Promise<ReadonlyMap<string, null | Account>>
  • populateCache<T>(accounts: ReadonlyMap<string, T>, parser: ParsableEntity<T>, now?: number): void

Legend

  • Constructor
  • Property
  • Method
  • Property
  • Method
  • Static property
  • Static method

Settings

Theme

Generated using TypeDoc

\ No newline at end of file diff --git a/docs/classes/WhirlpoolContext.html b/docs/classes/WhirlpoolContext.html deleted file mode 100644 index 052a13f..0000000 --- a/docs/classes/WhirlpoolContext.html +++ /dev/null @@ -1,3 +0,0 @@ -WhirlpoolContext | @orca-so/whirlpools-sdk
Options
All
  • Public
  • Public/Protected
  • All
Menu
-

Context for storing environment classes and objects for usage throughout the SDK

-

Hierarchy

  • WhirlpoolContext

Index

Constructors

Properties

accountResolverOpts: AccountResolverOptions
connection: Connection
lookupTableFetcher: undefined | LookupTableFetcher
program: Program<Whirlpool>
provider: AnchorProvider
txBuilderOpts: undefined | TransactionBuilderOptions
wallet: Wallet

Methods

Legend

  • Constructor
  • Property
  • Method
  • Property
  • Method
  • Static property
  • Static method

Settings

Theme

Generated using TypeDoc

\ No newline at end of file diff --git a/docs/classes/WhirlpoolIx.html b/docs/classes/WhirlpoolIx.html deleted file mode 100644 index b151092..0000000 --- a/docs/classes/WhirlpoolIx.html +++ /dev/null @@ -1,462 +0,0 @@ -WhirlpoolIx | @orca-so/whirlpools-sdk
Options
All
  • Public
  • Public/Protected
  • All
Menu
-

Instruction builders for the Whirlpools program.

-

Hierarchy

  • WhirlpoolIx

Index

Constructors

Methods

  • -

    Close a bundled position in a Whirlpool.

    -
    - -

    Special Errors

    -
    -

    InvalidBundleIndex - If the provided bundle index is out of bounds. -ClosePositionNotEmpty - The provided position account is not empty.

    -

    Parameters

    • program: Program<Whirlpool>
      -

      program object containing services required to generate the instruction

      -
    • params: CloseBundledPositionParams
      -

      CloseBundledPositionParams object

      -

    Returns Instruction

      -
    • Instruction to perform the action.
    • -
    -
  • -

    Close a position in a Whirlpool. Burns the position token in the owner's wallet.

    -

    Parameters

    • program: Program<Whirlpool>
      -

      program object containing services required to generate the instruction

      -
    • params: ClosePositionParams
      -

      ClosePositionParams object

      -

    Returns Instruction

      -
    • Instruction to perform the action.
    • -
    -
  • -

    Collect fees accrued for this position. -Call updateFeesAndRewards before this to update the position to the newest accrued values.

    -

    Parameters

    • program: Program<Whirlpool>
      -

      program object containing services required to generate the instruction

      -
    • params: CollectFeesParams
      -

      CollectFeesParams object

      -

    Returns Instruction

      -
    • Instruction to perform the action.
    • -
    -
  • -

    Collect protocol fees accrued in this Whirlpool.

    -

    Parameters

    • program: Program<Whirlpool>
      -

      program object containing services required to generate the instruction

      -
    • params: CollectProtocolFeesParams
      -

      CollectProtocolFeesParams object

      -

    Returns Instruction

      -
    • Instruction to perform the action.
    • -
    -
  • -

    Collect rewards accrued for this reward index in a position. -Call updateFeesAndRewards before this to update the position to the newest accrued values.

    -

    Parameters

    • program: Program<Whirlpool>
      -

      program object containing services required to generate the instruction

      -
    • params: CollectRewardParams
      -

      CollectRewardParams object

      -

    Returns Instruction

      -
    • Instruction to perform the action.
    • -
    -
  • -

    Remove liquidity to a position in the Whirlpool. This call also updates the position's accrued fees and rewards.

    -
    - -

    Special Errors

    -
    -
      -
    • LiquidityZero - Provided liquidity amount is zero.
    • -
    • LiquidityTooHigh - Provided liquidity exceeds u128::max.
    • -
    • TokenMinSubceeded - The required token to perform this operation subceeds the user defined amount.
    • -
    -

    Parameters

    • program: Program<Whirlpool>
      -

      program object containing services required to generate the instruction

      -
    • params: DecreaseLiquidityParams
      -

      DecreaseLiquidityParams object

      -

    Returns Instruction

      -
    • Instruction to perform the action.
    • -
    -
  • -

    Deletes a PositionBundle account.

    -
    - -

    Special Errors

    -
    -

    PositionBundleNotDeletable - The provided position bundle has open positions.

    -

    Parameters

    • program: Program<Whirlpool>
      -

      program object containing services required to generate the instruction

      -
    • params: DeletePositionBundleParams
      -

      DeletePositionBundleParams object

      -

    Returns Instruction

      -
    • Instruction to perform the action.
    • -
    -
  • -

    Add liquidity to a position in the Whirlpool. This call also updates the position's accrued fees and rewards.

    -
    - -

    Special Errors

    -
    -

    LiquidityZero - Provided liquidity amount is zero. -LiquidityTooHigh - Provided liquidity exceeds u128::max. -TokenMaxExceeded - The required token to perform this operation exceeds the user defined amount.

    -

    Parameters

    • program: Program<Whirlpool>
      -

      program object containing services required to generate the instruction

      -
    • params: IncreaseLiquidityParams
      -

      IncreaseLiquidityParams object

      -

    Returns Instruction

      -
    • Instruction to perform the action.
    • -
    -
  • -

    Initializes a TickArray account.

    -
    - -

    Special Errors

    -
    -

    InvalidStartTick - if the provided start tick is out of bounds or is not a multiple of TICK_ARRAY_SIZE * tick spacing.

    -

    Parameters

    • program: Program<Whirlpool>
      -

      program object containing services required to generate the instruction

      -
    • params: InitTickArrayParams
      -

      InitTickArrayParams object

      -

    Returns Instruction

      -
    • Instruction to perform the action.
    • -
    -
  • initializeConfigIx(program: Program<Whirlpool>, params: InitConfigParams): Instruction
  • -

    Initializes a WhirlpoolsConfig account that hosts info & authorities -required to govern a set of Whirlpools.

    -

    Parameters

    • program: Program<Whirlpool>
      -

      program object containing services required to generate the instruction

      -
    • params: InitConfigParams
      -

      InitConfigParams object

      -

    Returns Instruction

      -
    • Instruction to perform the action.
    • -
    -
  • initializeFeeTierIx(program: Program<Whirlpool>, params: InitFeeTierParams): Instruction
  • -

    Initializes a fee tier account usable by Whirlpools in this WhirlpoolsConfig space.

    -

    Special Errors -FeeRateMaxExceeded - If the provided default_fee_rate exceeds MAX_FEE_RATE.

    -

    Parameters

    • program: Program<Whirlpool>
      -

      program object containing services required to generate the instruction

      -
    • params: InitFeeTierParams
      -

      InitFeeTierParams object

      -

    Returns Instruction

      -
    • Instruction to perform the action.
    • -
    -
  • initializePoolIx(program: Program<Whirlpool>, params: InitPoolParams): Instruction
  • -

    Initializes a tick_array account to represent a tick-range in a Whirlpool.

    -

    Special Errors -InvalidTokenMintOrder - The order of mints have to be ordered by -SqrtPriceOutOfBounds - provided initial_sqrt_price is not between 2^-64 to 2^64

    -

    Parameters

    • program: Program<Whirlpool>
      -

      program object containing services required to generate the instruction

      -
    • params: InitPoolParams
      -

      InitPoolParams object

      -

    Returns Instruction

      -
    • Instruction to perform the action.
    • -
    -
  • -

    Initializes a PositionBundle account.

    -

    Parameters

    • program: Program<Whirlpool>
      -

      program object containing services required to generate the instruction

      -
    • params: InitializePositionBundleParams
      -

      InitializePositionBundleParams object

      -

    Returns Instruction

      -
    • Instruction to perform the action.
    • -
    -
  • initializePositionBundleWithMetadataIx(program: Program<Whirlpool>, params: InitializePositionBundleParams & { positionBundleMetadataPda: PDA }): Instruction
  • -

    Initializes a PositionBundle account. -Additional Metaplex metadata is appended to identify the token.

    -

    Parameters

    • program: Program<Whirlpool>
      -

      program object containing services required to generate the instruction

      -
    • params: InitializePositionBundleParams & { positionBundleMetadataPda: PDA }
      -

      InitializePositionBundleParams object

      -

    Returns Instruction

      -
    • Instruction to perform the action.
    • -
    -
  • -

    Initialize reward for a Whirlpool. A pool can only support up to a set number of rewards. -The initial emissionsPerSecond is set to 0.

    -
    - -

    Special Errors

    -
    -
      -
    • InvalidRewardIndex - If the provided reward index doesn't match the lowest uninitialized index in this pool, - or exceeds NUM_REWARDS, or all reward slots for this pool has been initialized.
    • -
    -

    Parameters

    • program: Program<Whirlpool>
      -

      program object containing services required to generate the instruction

      -
    • params: InitializeRewardParams
      -

      InitializeRewardParams object

      -

    Returns Instruction

      -
    • Instruction to perform the action.
    • -
    -
  • -

    Open a bundled position in a Whirlpool. -No new tokens are issued because the owner of the position bundle becomes the owner of the position. -The position will start off with 0 liquidity.

    -
    - -

    Special Errors

    -
    -

    InvalidBundleIndex - If the provided bundle index is out of bounds. -InvalidTickIndex - If a provided tick is out of bounds, out of order or not a multiple of the tick-spacing in this pool.

    -

    Parameters

    • program: Program<Whirlpool>
      -

      program object containing services required to generate the instruction

      -
    • params: OpenBundledPositionParams
      -

      OpenBundledPositionParams object

      -

    Returns Instruction

      -
    • Instruction to perform the action.
    • -
    -
  • -

    Open a position in a Whirlpool. A unique token will be minted to represent the position in the users wallet. -The position will start off with 0 liquidity.

    -
    - -

    Special Errors

    -
    -

    InvalidTickIndex - If a provided tick is out of bounds, out of order or not a multiple of the tick-spacing in this pool.

    -

    Parameters

    • program: Program<Whirlpool>
      -

      program object containing services required to generate the instruction

      -
    • params: OpenPositionParams
      -

      OpenPositionParams object

      -

    Returns Instruction

      -
    • Instruction to perform the action.
    • -
    -
  • openPositionWithMetadataIx(program: Program<Whirlpool>, params: OpenPositionParams & { metadataPda: PDA }): Instruction
  • -

    Open a position in a Whirlpool. A unique token will be minted to represent the position -in the users wallet. Additional Metaplex metadata is appended to identify the token. -The position will start off with 0 liquidity.

    -
    - -

    Special Errors

    -
    -

    InvalidTickIndex - If a provided tick is out of bounds, out of order or not a multiple of the tick-spacing in this pool.

    -

    Parameters

    • program: Program<Whirlpool>
      -

      program object containing services required to generate the instruction

      -
    • params: OpenPositionParams & { metadataPda: PDA }
      -

      OpenPositionParams object and a derived PDA that hosts the position's metadata.

      -

    Returns Instruction

      -
    • Instruction to perform the action.
    • -
    -
  • -

    Sets the fee authority to collect protocol fees for a WhirlpoolsConfig. -Only the current collect protocol fee authority has permission to invoke this instruction.

    -

    Parameters

    • program: Program<Whirlpool>
      -

      program object containing services required to generate the instruction

      -
    • params: SetCollectProtocolFeesAuthorityParams
      -

      SetCollectProtocolFeesAuthorityParams object

      -

    Returns Instruction

      -
    • Instruction to perform the action.
    • -
    -
  • -

    Updates a fee tier account with a new default fee rate. The new rate will not retroactively update -initialized pools.

    -
    - -

    Special Errors

    -
    -
      -
    • FeeRateMaxExceeded - If the provided default_fee_rate exceeds MAX_FEE_RATE.
    • -
    -

    Parameters

    • program: Program<Whirlpool>
      -

      program object containing services required to generate the instruction

      -
    • params: SetDefaultFeeRateParams
      -

      SetDefaultFeeRateParams object

      -

    Returns Instruction

      -
    • Instruction to perform the action.
    • -
    -
  • -

    Updates a WhirlpoolsConfig with a new default protocol fee rate. The new rate will not retroactively update -initialized pools.

    -
    - -

    Special Errors

    -
    -
      -
    • ProtocolFeeRateMaxExceeded - If the provided default_protocol_fee_rate exceeds MAX_PROTOCOL_FEE_RATE.
    • -
    -

    Parameters

    • program: Program<Whirlpool>
      -

      program object containing services required to generate the instruction

      -
    • params: SetDefaultProtocolFeeRateParams
      -

      SetDefaultFeeRateParams object

      -

    Returns Instruction

      -
    • Instruction to perform the action.
    • -
    -
  • -

    Sets the fee authority for a WhirlpoolsConfig. -The fee authority can set the fee & protocol fee rate for individual pools or set the default fee rate for newly minted pools. -Only the current fee authority has permission to invoke this instruction.

    -

    Parameters

    • program: Program<Whirlpool>
      -

      program object containing services required to generate the instruction

      -
    • params: SetFeeAuthorityParams
      -

      SetFeeAuthorityParams object

      -

    Returns Instruction

      -
    • Instruction to perform the action.
    • -
    -
  • setFeeRateIx(program: Program<Whirlpool>, params: SetFeeRateParams): Instruction
  • -

    Sets the fee rate for a Whirlpool. -Only the current fee authority has permission to invoke this instruction.

    -
    - -

    Special Errors

    -
    -
      -
    • FeeRateMaxExceeded - If the provided fee_rate exceeds MAX_FEE_RATE.
    • -
    -

    Parameters

    • program: Program<Whirlpool>
      -

      program object containing services required to generate the instruction

      -
    • params: SetFeeRateParams
      -

      SetFeeRateParams object

      -

    Returns Instruction

      -
    • Instruction to perform the action.
    • -
    -
  • -

    Sets the protocol fee rate for a Whirlpool. -Only the current fee authority has permission to invoke this instruction.

    -
    - -

    Special Errors

    -
    -
      -
    • ProtocolFeeRateMaxExceeded - If the provided default_protocol_fee_rate exceeds MAX_PROTOCOL_FEE_RATE.
    • -
    -

    Parameters

    • program: Program<Whirlpool>
      -

      program object containing services required to generate the instruction

      -
    • params: SetProtocolFeeRateParams
      -

      SetFeeRateParams object

      -

    Returns Instruction

      -
    • Instruction to perform the action.
    • -
    -
  • -

    Set the whirlpool reward authority at the provided reward_index. -Only the current reward super authority has permission to invoke this instruction.

    -
    - -

    Special Errors

    -
    -
      -
    • InvalidRewardIndex - If the provided reward index doesn't match the lowest uninitialized index in this pool, - or exceeds NUM_REWARDS.
    • -
    -

    Parameters

    Returns Instruction

      -
    • Instruction to perform the action.
    • -
    -
  • -

    Set the whirlpool reward authority at the provided reward_index. -Only the current reward authority for this reward index has permission to invoke this instruction.

    -
    - -

    Special Errors

    -
    -
      -
    • InvalidRewardIndex - If the provided reward index doesn't match the lowest uninitialized index in this pool, - or exceeds NUM_REWARDS.
    • -
    -

    Parameters

    • program: Program<Whirlpool>
      -

      program object containing services required to generate the instruction

      -
    • params: SetRewardAuthorityParams
      -

      SetRewardAuthorityParams object

      -

    Returns Instruction

      -
    • Instruction to perform the action.
    • -
    -
  • -

    Set the reward emissions for a reward in a Whirlpool.

    -
    - -

    Special Errors

    -
    -
      -
    • RewardVaultAmountInsufficient - The amount of rewards in the reward vault cannot emit more than a day of desired emissions.
    • -
    • InvalidTimestamp - Provided timestamp is not in order with the previous timestamp.
    • -
    • InvalidRewardIndex - If the provided reward index doesn't match the lowest uninitialized index in this pool, - or exceeds NUM_REWARDS.
    • -
    -

    Parameters

    • program: Program<Whirlpool>
      -

      program object containing services required to generate the instruction

      -
    • params: SetRewardEmissionsParams
      -

      SetRewardEmissionsParams object

      -

    Returns Instruction

      -
    • Instruction to perform the action.
    • -
    -
  • -

    Set the whirlpool reward super authority for a WhirlpoolsConfig -Only the current reward super authority has permission to invoke this instruction. -This instruction will not change the authority on any WhirlpoolRewardInfo whirlpool rewards.

    -

    Parameters

    • program: Program<Whirlpool>
      -

      program object containing services required to generate the instruction

      -
    • params: SetRewardEmissionsSuperAuthorityParams
      -

      SetRewardEmissionsSuperAuthorityParams object

      -

    Returns Instruction

      -
    • Instruction to perform the action.
    • -
    -
  • swapIx(program: Program<Whirlpool>, params: SwapParams): Instruction
  • -

    Perform a swap in this Whirlpool

    -
    - -

    Special Errors

    -
    -
      -
    • ZeroTradableAmount - User provided parameter amount is 0.
    • -
    • InvalidSqrtPriceLimitDirection - User provided parameter sqrt_price_limit does not match the direction of the trade.
    • -
    • SqrtPriceOutOfBounds - User provided parameter sqrt_price_limit is over Whirlppool's max/min bounds for sqrt-price.
    • -
    • InvalidTickArraySequence - User provided tick-arrays are not in sequential order required to proceed in this trade direction.
    • -
    • TickArraySequenceInvalidIndex - The swap loop attempted to access an invalid array index during the query of the next initialized tick.
    • -
    • TickArrayIndexOutofBounds - The swap loop attempted to access an invalid array index during tick crossing.
    • -
    • LiquidityOverflow - Liquidity value overflowed 128bits during tick crossing.
    • -
    • InvalidTickSpacing - The swap pool was initialized with tick-spacing of 0.
    • -
    - - -

    Parameters

    -
    -

    Parameters

    • program: Program<Whirlpool>
      -

      program object containing services required to generate the instruction

      -
    • params: SwapParams

    Returns Instruction

      -
    • Instruction to perform the action.
    • -
    -
  • twoHopSwapIx(program: Program<Whirlpool>, params: TwoHopSwapParams): Instruction
  • -

    Perform a two-hop-swap in this Whirlpool

    -
    - -

    Special Errors

    -
    -
      -
    • ZeroTradableAmount - User provided parameter amount is 0.
    • -
    • InvalidSqrtPriceLimitDirection - User provided parameter sqrt_price_limit does not match the direction of the trade.
    • -
    • SqrtPriceOutOfBounds - User provided parameter sqrt_price_limit is over Whirlppool's max/min bounds for sqrt-price.
    • -
    • InvalidTickArraySequence - User provided tick-arrays are not in sequential order required to proceed in this trade direction.
    • -
    • TickArraySequenceInvalidIndex - The swap loop attempted to access an invalid array index during the query of the next initialized tick.
    • -
    • TickArrayIndexOutofBounds - The swap loop attempted to access an invalid array index during tick crossing.
    • -
    • LiquidityOverflow - Liquidity value overflowed 128bits during tick crossing.
    • -
    • InvalidTickSpacing - The swap pool was initialized with tick-spacing of 0.
    • -
    • DuplicateTwoHopPool - Swaps on the same pool are not allowed.
    • -
    • InvalidIntermediaryMint - The first and second leg of the hops do not share a common token.
    • -
    - - -

    Parameters

    -
    -

    Parameters

    • program: Program<Whirlpool>
      -

      program object containing services required to generate the instruction

      -
    • params: TwoHopSwapParams
      -

      TwoHopSwapParams object

      -

    Returns Instruction

      -
    • Instruction to perform the action.
    • -
    -
  • -

    Update the accrued fees and rewards for a position.

    -
    - -

    Special Errors

    -
    -

    TickNotFound - Provided tick array account does not contain the tick for this position. -LiquidityZero - Position has zero liquidity and therefore already has the most updated fees and reward values.

    -

    Parameters

    • program: Program<Whirlpool>
      -

      program object containing services required to generate the instruction

      -
    • params: UpdateFeesAndRewardsParams
      -

      UpdateFeesAndRewardsParams object

      -

    Returns Instruction

      -
    • Instruction to perform the action.
    • -
    -

Legend

  • Constructor
  • Property
  • Method
  • Property
  • Method
  • Static property
  • Static method

Settings

Theme

Generated using TypeDoc

\ No newline at end of file diff --git a/docs/classes/WhirlpoolRouterBuilder.html b/docs/classes/WhirlpoolRouterBuilder.html deleted file mode 100644 index 6418467..0000000 --- a/docs/classes/WhirlpoolRouterBuilder.html +++ /dev/null @@ -1,17 +0,0 @@ -WhirlpoolRouterBuilder | @orca-so/whirlpools-sdk
Options
All
  • Public
  • Public/Protected
  • All
Menu
-

Builder to build instances of the WhirlpoolRouter

-

Hierarchy

  • WhirlpoolRouterBuilder

Index

Constructors

Methods

Legend

  • Constructor
  • Property
  • Method
  • Property
  • Method
  • Static property
  • Static method

Settings

Theme

Generated using TypeDoc

\ No newline at end of file diff --git a/docs/enums/AccountName.html b/docs/enums/AccountName.html deleted file mode 100644 index 1f690bf..0000000 --- a/docs/enums/AccountName.html +++ /dev/null @@ -1,3 +0,0 @@ -AccountName | @orca-so/whirlpools-sdk
Options
All
  • Public
  • Public/Protected
  • All
Menu

Enumeration AccountName

-

Supported parasable account names from the Whirlpool contract.

-

Index

Enumeration Members

FeeTier: "FeeTier"
Position: "Position"
PositionBundle: "PositionBundle"
TickArray: "TickArray"
Whirlpool: "Whirlpool"
WhirlpoolsConfig: "WhirlpoolsConfig"

Legend

  • Constructor
  • Property
  • Method
  • Property
  • Method
  • Static property
  • Static method

Settings

Theme

Generated using TypeDoc

\ No newline at end of file diff --git a/docs/enums/SwapDirection.html b/docs/enums/SwapDirection.html deleted file mode 100644 index 89d47d5..0000000 --- a/docs/enums/SwapDirection.html +++ /dev/null @@ -1,3 +0,0 @@ -SwapDirection | @orca-so/whirlpools-sdk
Options
All
  • Public
  • Public/Protected
  • All
Menu

Enumeration SwapDirection

-

An enum for the direction of a swap.

-

Index

Enumeration Members

Enumeration Members

AtoB: "aToB"
BtoA: "bToA"

Legend

  • Constructor
  • Property
  • Method
  • Property
  • Method
  • Static property
  • Static method

Settings

Theme

Generated using TypeDoc

\ No newline at end of file diff --git a/docs/enums/TokenType.html b/docs/enums/TokenType.html deleted file mode 100644 index e265548..0000000 --- a/docs/enums/TokenType.html +++ /dev/null @@ -1,3 +0,0 @@ -TokenType | @orca-so/whirlpools-sdk
Options
All
  • Public
  • Public/Protected
  • All
Menu

Enumeration TokenType

-

An enum for the token type in a Whirlpool.

-

Index

Enumeration Members

Enumeration Members

TokenA: 1
TokenB: 2

Legend

  • Constructor
  • Property
  • Method
  • Property
  • Method
  • Static property
  • Static method

Settings

Theme

Generated using TypeDoc

\ No newline at end of file diff --git a/docs/index.html b/docs/index.html deleted file mode 100644 index c6a16a7..0000000 --- a/docs/index.html +++ /dev/null @@ -1,37 +0,0 @@ -@orca-so/whirlpools-sdk
Options
All
  • Public
  • Public/Protected
  • All
Menu

@orca-so/whirlpools-sdk

- -

Whirlpools

-
-

Whirpools is an open-source concentrated liquidity AMM contract on the Solana blockchain. -The Whirlpools Typescript SDK (@orca-so/whirlpools-sdk) allows for easy interaction with a deployed Whirlpools program.

-

The contract has been audited by Kudelski and Neodyme.

- - -

Whirlpool SDK

-
-

Use the SDK to interact with a deployed Whirlpools program via Typescript.

- - -

Installation

-
-

In your package, run:

-
yarn add `@orca-so/whirlpools-sdk`
yarn add "@coral-xyz/anchor"
yarn add "decimal.js" -
- - -

Usage

-
-

Read instructions on how to use the SDK on the Orca Developer Portal.

- - -

Tests

-
-

To run tests for the SDK, setup your anchor environment and run:

-
anchor test
-
- - -

License

-
-

Apache 2.0

-

Legend

  • Constructor
  • Property
  • Method
  • Property
  • Method
  • Static property
  • Static method

Settings

Theme

Generated using TypeDoc

\ No newline at end of file diff --git a/docs/interfaces/PoolTokenPair.html b/docs/interfaces/PoolTokenPair.html deleted file mode 100644 index a078b8a..0000000 --- a/docs/interfaces/PoolTokenPair.html +++ /dev/null @@ -1,3 +0,0 @@ -PoolTokenPair | @orca-so/whirlpools-sdk
Options
All
  • Public
  • Public/Protected
  • All
Menu

Interface PoolTokenPair

-

An object containing the token pairs of a Whirlpool.

-

Hierarchy

  • PoolTokenPair

Index

Properties

address: Address
tokenMintA: Address
tokenMintB: Address

Legend

  • Constructor
  • Property
  • Method
  • Property
  • Method
  • Static property
  • Static method

Settings

Theme

Generated using TypeDoc

\ No newline at end of file diff --git a/docs/interfaces/Position.html b/docs/interfaces/Position.html deleted file mode 100644 index 58919bd..0000000 --- a/docs/interfaces/Position.html +++ /dev/null @@ -1,84 +0,0 @@ -Position | @orca-so/whirlpools-sdk
Options
All
  • Public
  • Public/Protected
  • All
Menu
-

Helper class to interact with a Position account and build complex transactions.

-

Hierarchy

  • Position

Index

Methods

  • collectFees(updateFeesAndRewards?: boolean, ownerTokenAccountMap?: Partial<Record<string, Address>>, destinationWallet?: Address, positionWallet?: Address, ataPayer?: Address, opts?: SimpleAccountFetchOptions): Promise<TransactionBuilder>
  • -

    Collect fees from this position

    -

    If positionWallet is provided, the wallet owners have to sign this transaction.

    -

    Parameters

    • Optional updateFeesAndRewards: boolean
      -

      if true, add instructions to refresh the accumulated fees and rewards data (default to true unless you know that the collect fees quote and on-chain data match for the "feeOwedA" and "feeOwedB" fields in the Position account)

      -
    • Optional ownerTokenAccountMap: Partial<Record<string, Address>>
      -

      A record that maps a given mint to the owner's token account for that mint (if an entry doesn't exist, it will be automatically resolved)

      -
    • Optional destinationWallet: Address
      -

      the wallet to deposit tokens into when withdrawing from the position. If null, the WhirlpoolContext wallet is used.

      -
    • Optional positionWallet: Address
      -

      the wallet to that houses the position token. If null, the WhirlpoolContext wallet is used.

      -
    • Optional ataPayer: Address
      -

      wallet that will fund the creation of the new associated token accounts

      -
    • Optional opts: SimpleAccountFetchOptions
      -

      an options object to define fetch and cache options when accessing on-chain accounts

      -

    Returns Promise<TransactionBuilder>

    the transaction that will collect fees from the position

    -
  • collectRewards(rewardsToCollect?: Address[], updateFeesAndRewards?: boolean, ownerTokenAccountMap?: Partial<Record<string, Address>>, destinationWallet?: Address, positionWallet?: Address, ataPayer?: Address, opts?: SimpleAccountFetchOptions): Promise<TransactionBuilder>
  • -

    Collect rewards from this position

    -

    If positionWallet is provided, the wallet owners have to sign this transaction.

    -

    Parameters

    • Optional rewardsToCollect: Address[]
      -

      reward mints to collect (omitting this parameter means all rewards will be collected)

      -
    • Optional updateFeesAndRewards: boolean
      -

      if true, add instructions to refresh the accumulated fees and rewards data (default to true unless you know that the collect fees quote and on-chain data match for the "feeOwedA" and "feeOwedB" fields in the Position account)

      -
    • Optional ownerTokenAccountMap: Partial<Record<string, Address>>
      -

      A record that maps a given mint to the owner's token account for that mint (if an entry doesn't exist, it will be automatically resolved)

      -
    • Optional destinationWallet: Address
      -

      the wallet to deposit tokens into when withdrawing from the position. If null, the WhirlpoolContext wallet is used.

      -
    • Optional positionWallet: Address
      -

      the wallet to that houses the position token. If null, the WhirlpoolContext wallet is used.

      -
    • Optional ataPayer: Address
      -

      wallet that will fund the creation of the new associated token accounts

      -
    • Optional opts: SimpleAccountFetchOptions
      -

      an options object to define fetch and cache options when accessing on-chain accounts

      -

    Returns Promise<TransactionBuilder>

    the transaction that will collect fees from the position

    -
  • decreaseLiquidity(liquidityInput: DecreaseLiquidityInput, resolveATA?: boolean, destinationWallet?: Address, positionWallet?: Address, ataPayer?: Address): Promise<TransactionBuilder>
  • -

    Withdraw liquidity from this position.

    -

    If positionWallet is provided, the wallet owners have to sign this transaction.

    -

    Parameters

    • liquidityInput: DecreaseLiquidityInput
      -

      input that defines the desired liquidity amount and minimum tokens willing to be to withdrawn from the position.

      -
    • Optional resolveATA: boolean
      -

      if true, add instructions to create associated token accounts for tokenA,B for the destinationWallet if necessary. (RPC call required)

      -
    • Optional destinationWallet: Address
      -

      the wallet to deposit tokens into when withdrawing from the position. If null, the WhirlpoolContext wallet is used.

      -
    • Optional positionWallet: Address
      -

      the wallet to that houses the position token. If null, the WhirlpoolContext wallet is used.

      -
    • Optional ataPayer: Address
      -

      wallet that will fund the creation of the new associated token accounts

      -

    Returns Promise<TransactionBuilder>

    the transaction that will deposit the tokens into the position when executed.

    -
  • getAddress(): PublicKey
  • -

    Return the address for this Whirlpool instance.

    -

    Returns PublicKey

    the PublicKey for this Whirlpool instance.

    -
  • -

    Return the most recently fetched TickData account data for this position's lower tick.

    -

    Returns TickData

    most recently fetched TickData for this position's lower tick.

    -
  • -

    Return the most recently fetched TickData account data for this position's upper tick.

    -

    Returns TickData

    most recently fetched TickData for this position's upper tick.

    -
  • -

    Return the most recently fetched Whirlpool account data for this position.

    -

    Returns WhirlpoolData

    most recently fetched WhirlpoolData for this position.

    -
  • increaseLiquidity(liquidityInput: IncreaseLiquidityInput, resolveATA?: boolean, wallet?: Address, positionWallet?: Address, ataPayer?: Address): Promise<TransactionBuilder>
  • -

    Deposit additional tokens into this postiion. -The wallet must contain the position token and the necessary token A & B to complete the deposit. -If positionWallet and wallet is provided, the wallet owners have to sign this transaction.

    -

    Parameters

    • liquidityInput: IncreaseLiquidityInput
      -

      input that defines the desired liquidity amount and maximum tokens willing to be to deposited.

      -
    • Optional resolveATA: boolean
      -

      if true, add instructions to create associated token accounts for tokenA,B for the destinationWallet if necessary. (RPC call required)

      -
    • Optional wallet: Address
      -

      to withdraw tokens to deposit into the position. If null, the WhirlpoolContext wallet is used.

      -
    • Optional positionWallet: Address
      -

      the wallet to that houses the position token. If null, the WhirlpoolContext wallet is used.

      -
    • Optional ataPayer: Address
      -

      wallet that will fund the creation of the new associated token accounts

      -

    Returns Promise<TransactionBuilder>

    the transaction that will deposit the tokens into the position when executed.

    -
  • -

    Fetch and return the most recently fetched Position account data.

    -

    Returns Promise<PositionData>

    the most up to date PositionData for this address.

    -

Legend

  • Constructor
  • Property
  • Method
  • Property
  • Method
  • Static property
  • Static method

Settings

Theme

Generated using TypeDoc

\ No newline at end of file diff --git a/docs/interfaces/TickArrayRequest.html b/docs/interfaces/TickArrayRequest.html deleted file mode 100644 index 2cdffb5..0000000 --- a/docs/interfaces/TickArrayRequest.html +++ /dev/null @@ -1,3 +0,0 @@ -TickArrayRequest | @orca-so/whirlpools-sdk
Options
All
  • Public
  • Public/Protected
  • All
Menu

Interface TickArrayRequest

-

A request to fetch the tick-arrays that a swap may traverse across.

-

Hierarchy

  • TickArrayRequest

Index

Properties

aToB: boolean
tickCurrentIndex: number
tickSpacing: number
whirlpoolAddress: PublicKey

Legend

  • Constructor
  • Property
  • Method
  • Property
  • Method
  • Static property
  • Static method

Settings

Theme

Generated using TypeDoc

\ No newline at end of file diff --git a/docs/interfaces/Whirlpool.html b/docs/interfaces/Whirlpool.html deleted file mode 100644 index b2da15a..0000000 --- a/docs/interfaces/Whirlpool.html +++ /dev/null @@ -1,103 +0,0 @@ -Whirlpool | @orca-so/whirlpools-sdk
Options
All
  • Public
  • Public/Protected
  • All
Menu
-

Helper class to interact with a Whirlpool account and build complex transactions.

-

Hierarchy

  • Whirlpool

Index

Methods

  • closePosition(positionAddress: Address, slippageTolerance: Percentage, destinationWallet?: Address, positionWallet?: Address, payer?: Address): Promise<TransactionBuilder[]>
  • -

    Withdraw all tokens from a position, close the account and burn the position token.

    -

    Users have to collect all fees and rewards from this position prior to closing the account.

    -

    If positionWallet, payer is provided, the wallet owner has to sign this transaction.

    -

    Parameters

    • positionAddress: Address
      -

      The address of the position account.

      -
    • slippageTolerance: Percentage
      -

      The amount of slippage the caller is willing to accept when withdrawing liquidity.

      -
    • Optional destinationWallet: Address
      -

      The wallet that the tokens withdrawn and rent lamports will be sent to. If null, the WhirlpoolContext wallet is used.

      -
    • Optional positionWallet: Address
      -

      The wallet that houses the position token that corresponds to this position address. If null, the WhirlpoolContext wallet is used.

      -
    • Optional payer: Address
      -

      the wallet that will fund the cost needed to initialize the token ATA accounts. If null, the WhirlpoolContext wallet is used.

      -

    Returns Promise<TransactionBuilder[]>

  • getAddress(): PublicKey
  • -

    Return the address for this Whirlpool instance.

    -

    Returns PublicKey

    the PublicKey for this Whirlpool instance.

    -
  • -

    Get the WhirlpoolRewardInfos for this pool.

    -

    Returns WhirlpoolRewardInfo[]

    Array of 3 WhirlpoolRewardInfos. However, not all of them may be initialized. Use the initialized field on WhirlpoolRewardInfo to check if the reward is active.

    -
  • getTokenVaultAInfo(): Account
  • -

    Get the TokenAccountInfo for token vault A of this pool.

    -

    Returns Account

    TokenAccountInfo for token vault A

    -
  • getTokenVaultBInfo(): Account
  • -

    Get the TokenAccountInfo for token vault B of this pool.

    -

    Returns Account

    TokenAccountInfo for token vault B

    -
  • initTickArrayForTicks(ticks: number[], funder?: Address, opts?: SimpleAccountFetchOptions): Promise<null | TransactionBuilder>
  • -

    Initialize a set of tick-arrays that encompasses the provided ticks.

    -

    If funder is provided, the funder wallet has to sign this transaction.

    -

    Parameters

    • ticks: number[]
      -

      A group of ticks that define the desired tick-arrays to initialize. If the tick's array has been initialized, it will be ignored.

      -
    • Optional funder: Address
      -

      the wallet that will fund the cost needed to initialize the position. If null, the WhirlpoolContext wallet is used.

      -
    • Optional opts: SimpleAccountFetchOptions
      -

      an WhirlpoolAccountFetchOptions object to define fetch and cache options when accessing on-chain accounts

      -

    Returns Promise<null | TransactionBuilder>

    a transaction that will initialize the defined tick-arrays if executed. Return null if all of the tick's arrays are initialized.

    -
  • openPosition(tickLower: number, tickUpper: number, liquidityInput: IncreaseLiquidityInput, wallet?: Address, funder?: Address, positionMint?: PublicKey): Promise<{ positionMint: PublicKey; tx: TransactionBuilder }>
  • -

    Open and fund a position on this Whirlpool.

    -

    User has to ensure the TickArray for tickLower and tickUpper has been initialized prior to calling this function.

    -

    If wallet or funder is provided, those wallets have to sign this transaction.

    -

    Parameters

    • tickLower: number
      -

      the tick index for the lower bound of this position

      -
    • tickUpper: number
      -

      the tick index for the upper bound of this position

      -
    • liquidityInput: IncreaseLiquidityInput
      -

      an InputLiquidityInput type to define the desired liquidity amount to deposit

      -
    • Optional wallet: Address
      -

      the wallet to withdraw tokens to deposit into the position and house the position token. If null, the WhirlpoolContext wallet is used.

      -
    • Optional funder: Address
      -

      the wallet that will fund the cost needed to initialize the position. If null, the WhirlpoolContext wallet is used.

      -
    • Optional positionMint: PublicKey
      -

      the mint address of the position token to be created. If null, a new mint address will be created.

      -

    Returns Promise<{ positionMint: PublicKey; tx: TransactionBuilder }>

    positionMint - the position to be created. tx - The transaction containing the instructions to perform the operation on chain.

    -
  • openPositionWithMetadata(tickLower: number, tickUpper: number, liquidityInput: IncreaseLiquidityInput, wallet?: Address, funder?: Address, positionMint?: PublicKey): Promise<{ positionMint: PublicKey; tx: TransactionBuilder }>
  • -

    Open and fund a position with meta-data on this Whirlpool.

    -

    User has to ensure the TickArray for tickLower and tickUpper has been initialized prior to calling this function.

    -

    If wallet or funder is provided, the wallet owners have to sign this transaction.

    -

    Parameters

    • tickLower: number
      -

      the tick index for the lower bound of this position

      -
    • tickUpper: number
      -

      the tick index for the upper bound of this position

      -
    • liquidityInput: IncreaseLiquidityInput
      -

      input that defines the desired liquidity amount and maximum tokens willing to be to deposited.

      -
    • Optional wallet: Address
      -

      the wallet to withdraw tokens to deposit into the position and house the position token. If null, the WhirlpoolContext wallet is used.

      -
    • Optional funder: Address
      -

      the wallet that will fund the cost needed to initialize the position. If null, the WhirlpoolContext wallet is used.

      -
    • Optional positionMint: PublicKey
      -

      the mint address of the position token to be created. If null, a new mint address will be created.

      -

    Returns Promise<{ positionMint: PublicKey; tx: TransactionBuilder }>

    positionMint - the position to be created. tx - The transaction containing the instructions to perform the operation on chain.

    -
  • -

    Fetch and return the most recently fetched Whirlpool account data.

    -

    Returns Promise<WhirlpoolData>

    the most up to date WhirlpoolData for this address.

    -
  • swap(input: SwapInput, wallet?: PublicKey): Promise<TransactionBuilder>
  • -

    Perform a swap between tokenA and tokenB on this pool.

    -

    Parameters

    • input: SwapInput
      -

      A quote on the desired tokenIn and tokenOut for this swap. Use swapQuoteWithParams or other swap quote functions to generate this object.

      -
    • Optional wallet: PublicKey
      -

      The wallet that tokens will be withdrawn and deposit into. If null, the WhirlpoolContext wallet is used.

      -

    Returns Promise<TransactionBuilder>

    a transaction that will perform the swap once executed.

    -
  • swapWithDevFees(input: DevFeeSwapInput, devFeeWallet: PublicKey, wallet?: PublicKey, payer?: PublicKey): Promise<TransactionBuilder>
  • -

    Collect a developer fee and perform a swap between tokenA and tokenB on this pool.

    -

    Parameters

    • input: DevFeeSwapInput
      -

      A quote on the desired tokenIn and tokenOut for this swap. Use swapQuoteByInputTokenWithDevFees to generate this object.

      -
    • devFeeWallet: PublicKey
      -

      The wallet that developer fees will be deposited into.

      -
    • Optional wallet: PublicKey
      -

      The wallet that swap tokens will be withdrawn and deposit into. If null, the WhirlpoolContext wallet is used.

      -
    • Optional payer: PublicKey
      -

      The wallet that will fund the cost needed to initialize the dev wallet token ATA accounts. If null, the WhirlpoolContext wallet is used.

      -

    Returns Promise<TransactionBuilder>

    a transaction that will perform the swap once executed.

    -

Legend

  • Constructor
  • Property
  • Method
  • Property
  • Method
  • Static property
  • Static method

Settings

Theme

Generated using TypeDoc

\ No newline at end of file diff --git a/docs/interfaces/WhirlpoolAccountFetcherInterface.html b/docs/interfaces/WhirlpoolAccountFetcherInterface.html deleted file mode 100644 index 1661dff..0000000 --- a/docs/interfaces/WhirlpoolAccountFetcherInterface.html +++ /dev/null @@ -1,111 +0,0 @@ -WhirlpoolAccountFetcherInterface | @orca-so/whirlpools-sdk
Options
All
  • Public
  • Public/Protected
  • All
Menu

Interface WhirlpoolAccountFetcherInterface

-

Fetcher interface for fetching WhirlpoolSupportedTypes from the network

-

Hierarchy

  • WhirlpoolAccountFetcherInterface

Implemented by

Index

Methods

  • getAccountRentExempt(refresh?: boolean): Promise<number>
  • getConfigs(addresses: Address[], opts?: SimpleAccountFetchOptions): Promise<ReadonlyMap<string, null | WhirlpoolsConfigData>>
  • getFeeTier(address: Address, opts?: SimpleAccountFetchOptions): Promise<null | FeeTierData>
  • getFeeTiers(addresses: Address[], opts?: SimpleAccountFetchOptions): Promise<ReadonlyMap<string, null | FeeTierData>>
  • getMintInfo(address: Address, opts?: SimpleAccountFetchOptions): Promise<null | Mint>
  • getMintInfos(addresses: Address[], opts?: SimpleAccountFetchOptions): Promise<ReadonlyMap<string, null | Mint>>
  • getPool(address: Address, opts?: SimpleAccountFetchOptions): Promise<null | WhirlpoolData>
  • getPools(addresses: Address[], opts?: SimpleAccountFetchOptions): Promise<ReadonlyMap<string, null | WhirlpoolData>>
  • getPosition(address: Address, opts?: SimpleAccountFetchOptions): Promise<null | PositionData>
  • getPositionBundle(address: Address, opts?: SimpleAccountFetchOptions): Promise<null | PositionBundleData>
  • getPositionBundles(addresses: Address[], opts?: SimpleAccountFetchOptions): Promise<ReadonlyMap<string, null | PositionBundleData>>
  • getPositions(addresses: Address[], opts?: SimpleAccountFetchOptions): Promise<ReadonlyMap<string, null | PositionData>>
  • getTickArray(address: Address, opts?: SimpleAccountFetchOptions): Promise<null | TickArrayData>
  • getTickArrays(addresses: Address[], opts?: SimpleAccountFetchOptions): Promise<readonly (null | TickArrayData)[]>
  • getTokenInfo(address: Address, opts?: SimpleAccountFetchOptions): Promise<null | Account>
  • getTokenInfos(addresses: Address[], opts?: SimpleAccountFetchOptions): Promise<ReadonlyMap<string, null | Account>>
  • -

    Fetch and cache the accounts for a given array of TokenAccount addresses

    -

    Parameters

    • addresses: Address[]
      -

      The array of token account addresses

      -
    • Optional opts: SimpleAccountFetchOptions
      -

      WhirlpoolAccountFetchOptions instance to dictate fetch behavior

      -

    Returns Promise<ReadonlyMap<string, null | Account>>

  • populateCache<T>(accounts: ReadonlyMap<string, T>, parser: ParsableEntity<T>, now: number): void
  • -

    Populate the fetcher's cache with the given {@link WhirlpoolsData} accounts

    -

    Type Parameters

    Parameters

    • accounts: ReadonlyMap<string, T>
      -

      The map of addresses to on-chain account data

      -
    • parser: ParsableEntity<T>
      -

      The {@link ParsableEntity} instance to parse the accounts

      -
    • now: number
      -

      The current timestamp to use for the cache

      -

    Returns void

Legend

  • Constructor
  • Property
  • Method
  • Property
  • Method
  • Static property
  • Static method

Settings

Theme

Generated using TypeDoc

\ No newline at end of file diff --git a/docs/interfaces/WhirlpoolClient.html b/docs/interfaces/WhirlpoolClient.html deleted file mode 100644 index 27460bc..0000000 --- a/docs/interfaces/WhirlpoolClient.html +++ /dev/null @@ -1,65 +0,0 @@ -WhirlpoolClient | @orca-so/whirlpools-sdk
Options
All
  • Public
  • Public/Protected
  • All
Menu

Interface WhirlpoolClient

-

Helper class to help interact with Whirlpool Accounts with a simpler interface.

-

Hierarchy

  • WhirlpoolClient

Index

Methods

  • collectFeesAndRewardsForPositions(positionAddresses: Address[], opts?: SimpleAccountFetchOptions): Promise<TransactionBuilder[]>
  • -

    Collect all fees and rewards from a list of positions.

    -
    experimental

    Parameters

    • positionAddresses: Address[]
    • Optional opts: SimpleAccountFetchOptions
      -

      an options object to define fetch and cache options when accessing on-chain accounts

      -

    Returns Promise<TransactionBuilder[]>

    A set of transaction-builders to resolve ATA for affliated tokens, collect fee & rewards for all positions.

    -
  • collectProtocolFeesForPools(poolAddresses: Address[]): Promise<TransactionBuilder>
  • -

    Collect protocol fees from a list of pools

    -

    Parameters

    • poolAddresses: Address[]
      -

      the addresses of the Whirlpool accounts to collect protocol fees from

      -

    Returns Promise<TransactionBuilder>

    A transaction builder to resolve ATA for tokenA and tokenB if needed, and collect protocol fees for all pools

    -
  • createPool(whirlpoolsConfig: Address, tokenMintA: Address, tokenMintB: Address, tickSpacing: number, initialTick: number, funder: Address): Promise<{ poolKey: PublicKey; tx: TransactionBuilder }>
  • -

    Create a Whirlpool account for a group of token A, token B and tick spacing

    -
    throws

    error when the tokens are not in the canonical byte-based ordering. To resolve this, invert the token order and the initialTick (see TickUtil.invertTick(), PriceMath.invertSqrtPriceX64(), or PriceMath.invertPrice()).

    -

    Parameters

    • whirlpoolsConfig: Address
    • tokenMintA: Address
      -

      the address of the token A

      -
    • tokenMintB: Address
      -

      the address of the token B

      -
    • tickSpacing: number
      -

      the space between two ticks in the tick array

      -
    • initialTick: number
      -

      the initial tick that the pool is set to (derived from initial price)

      -
    • funder: Address
      -

      the account to debit SOL from to fund the creation of the account(s)

      -

    Returns Promise<{ poolKey: PublicKey; tx: TransactionBuilder }>

    poolKey: The public key of the newly created whirlpool account. tx: The transaction containing instructions for the on-chain operations.

    -
  • getPool(poolAddress: Address, opts?: SimpleAccountFetchOptions): Promise<Whirlpool>
  • -

    Get a Whirlpool object to interact with the Whirlpool account at the given address.

    -

    Parameters

    • poolAddress: Address
      -

      the address of the Whirlpool account

      -
    • Optional opts: SimpleAccountFetchOptions
      -

      an options object to define fetch and cache options when accessing on-chain accounts

      -

    Returns Promise<Whirlpool>

    a Whirlpool object to interact with

    -
  • getPools(poolAddresses: Address[], opts?: SimpleAccountFetchOptions): Promise<Whirlpool[]>
  • -

    Get a list of Whirlpool objects matching the provided list of addresses.

    -

    Parameters

    • poolAddresses: Address[]
      -

      the addresses of the Whirlpool accounts

      -
    • Optional opts: SimpleAccountFetchOptions
      -

      an options object to define fetch and cache options when accessing on-chain accounts

      -

    Returns Promise<Whirlpool[]>

    a list of Whirlpool objects to interact with

    -
  • getPosition(positionAddress: Address, opts?: SimpleAccountFetchOptions): Promise<Position>
  • -

    Get a Position object to interact with the Position account at the given address.

    -
    throws

    error when address does not return a Position account.

    -

    Parameters

    • positionAddress: Address
      -

      the address of the Position account

      -
    • Optional opts: SimpleAccountFetchOptions
      -

      an options object to define fetch and cache options when accessing on-chain accounts

      -

    Returns Promise<Position>

    a Position object to interact with.

    -
  • getPositions(positionAddresses: Address[], opts?: SimpleAccountFetchOptions): Promise<Record<string, null | Position>>
  • -

    Get a list of Position objects to interact with the Position account at the given addresses.

    -

    Parameters

    • positionAddresses: Address[]
    • Optional opts: SimpleAccountFetchOptions
      -

      an options object to define fetch and cache options when accessing on-chain accounts

      -

    Returns Promise<Record<string, null | Position>>

    a Record object between account address and Position. If an address is not a Position account, it will be null.

    -
  • -

    Get a WhirlpoolRouter to help generate the best prices when transacting across a set of pools.

    -

    Parameters

    • poolAddresses: Address[]
      -

      the addresses of the Whirlpool account addresses to route through

      -

    Returns Promise<WhirlpoolRouter>

    a WhirlpoolRouter instance

    -

Legend

  • Constructor
  • Property
  • Method
  • Property
  • Method
  • Static property
  • Static method

Settings

Theme

Generated using TypeDoc

\ No newline at end of file diff --git a/docs/interfaces/WhirlpoolRouter.html b/docs/interfaces/WhirlpoolRouter.html deleted file mode 100644 index f56c01f..0000000 --- a/docs/interfaces/WhirlpoolRouter.html +++ /dev/null @@ -1,40 +0,0 @@ -WhirlpoolRouter | @orca-so/whirlpools-sdk
Options
All
  • Public
  • Public/Protected
  • All
Menu

Interface WhirlpoolRouter

-

Convienience class to find routes through a set of Whirlpools and execute a swap across them. -The router only supports up to 2-hop trades between pools and does not support arbitrage trades -between the same token.

-

Hierarchy

  • WhirlpoolRouter

Index

Methods

  • -

    Finds all possible routes for a trade and select the best route that is executable -under the current execution environment.

    -

    Parameters

    Returns Promise<null | ExecutableRoute>

    The best ExecutableRoute that can be used to execute a swap. If no executable route is found, null is returned.

    -
  • -

    Construct a {@link TransactionBuilder} to help execute a trade route.

    -

    Parameters

    • trade: TradeRoute
      -

      The trade route to execute.

      -
    • slippage: Percentage
      -

      The slippage tolerance for the trade.

      -
    • resolvedAtas: null | AtaAccountInfo[]
      -

      The ATA accounts that the executing wallet owns / needed by the execution. -If not provided, the router will attempt to resolve them.

      -

    Returns Promise<TransactionBuilder>

    A {@link TransactionBuilder}that can be used to execute the trade. -If provvided from ExecutableRoute, plug the {@link AddressLookupTableAccount}s -into builder to lower the transaction size.

    -

Legend

  • Constructor
  • Property
  • Method
  • Property
  • Method
  • Static property
  • Static method

Settings

Theme

Generated using TypeDoc

\ No newline at end of file diff --git a/docs/modules.html b/docs/modules.html deleted file mode 100644 index a1750ce..0000000 --- a/docs/modules.html +++ /dev/null @@ -1,652 +0,0 @@ -@orca-so/whirlpools-sdk
Options
All
  • Public
  • Public/Protected
  • All
Menu

@orca-so/whirlpools-sdk

Index

Constants

Core

Instruction Types

Network

Other

PoolGraph

PriceModule

Quotes

Router

Solana Accounts

Whirlpool Utils

WhirlpoolClient

Constants

FEE_RATE_MUL_VALUE: BN = ...
-

The denominator which the fee rate is divided on.

-
MAX_SQRT_PRICE: "79226673515401279992447579055" = "79226673515401279992447579055"
-

The maximum sqrt-price supported by the Whirlpool program.

-
MAX_SWAP_TICK_ARRAYS: 3 = 3
-

The maximum number of tick-arrays that can traversed across in a swap.

-
MAX_TICK_INDEX: 443636 = 443636
-

The maximum tick index supported by the Whirlpool program.

-
METADATA_PROGRAM_ADDRESS: PublicKey = ...
MIN_SQRT_PRICE: "4295048016" = "4295048016"
-

The minimum sqrt-price supported by the Whirlpool program.

-
MIN_TICK_INDEX: -443636 = -443636
-

The minimum tick index supported by the Whirlpool program.

-
NUM_REWARDS: 3 = 3
-

The number of rewards supported by this whirlpool.

-
ORCA_SUPPORTED_TICK_SPACINGS: number[] = ...
-

Orca's supported tick spacings.

-
ORCA_WHIRLPOOLS_CONFIG: PublicKey = ...
-

Orca's WhirlpoolsConfig PublicKey.

-
ORCA_WHIRLPOOL_PROGRAM_ID: PublicKey = ...
-

Program ID hosting Orca's Whirlpool program.

-
POSITION_BUNDLE_SIZE: 256 = 256
-

The number of bundled positions that a position-bundle account can hold.

-
PROTOCOL_FEE_RATE_MUL_VALUE: BN = ...
-

The denominator which the protocol fee rate is divided on.

-
TICK_ARRAY_SIZE: 88 = 88
-

The number of initialized ticks that a tick-array account can hold.

-
WHIRLPOOL_NFT_UPDATE_AUTH: PublicKey = ...
-

The public key that is allowed to update the metadata of Whirlpool NFTs.

-

Core

AccountResolverOptions: { allowPDAOwnerAddress: boolean; createWrappedSolAccountMethod: WrappedSolAccountCreateMethod }
-

Default settings used when resolving token accounts.

-

Type declaration

  • allowPDAOwnerAddress: boolean
  • createWrappedSolAccountMethod: WrappedSolAccountCreateMethod
WhirlpoolContextOpts: { accountResolverOptions?: AccountResolverOptions; userDefaultBuildOptions?: Partial<BuildOptions>; userDefaultConfirmCommitment?: Commitment; userDefaultSendOptions?: Partial<SendOptions> }
-

Default settings used when interacting with transactions.

-

Type declaration

  • Optional accountResolverOptions?: AccountResolverOptions
  • Optional userDefaultBuildOptions?: Partial<BuildOptions>
  • Optional userDefaultConfirmCommitment?: Commitment
  • Optional userDefaultSendOptions?: Partial<SendOptions>

Instruction Types

CloseBundledPositionParams: { bundleIndex: number; bundledPosition: PublicKey; positionBundle: PublicKey; positionBundleAuthority: PublicKey; positionBundleTokenAccount: PublicKey; receiver: PublicKey }
-

Parameters to close a bundled position in a Whirlpool.

-
param bundledPosition

PublicKey for the bundled position.

-
param positionBundle

PublicKey for the position bundle.

-
param positionBundleTokenAccount

The associated token address for the position bundle token in the owners wallet.

-
param positionBundleAuthority

authority that owns the token corresponding to this desired bundled position.

-
param bundleIndex

The bundle index that holds the bundled position.

-
param receiver

PublicKey for the wallet that will receive the rented lamports.

-

Type declaration

  • bundleIndex: number
  • bundledPosition: PublicKey
  • positionBundle: PublicKey
  • positionBundleAuthority: PublicKey
  • positionBundleTokenAccount: PublicKey
  • receiver: PublicKey
ClosePositionParams: { position: PublicKey; positionAuthority: PublicKey; positionMint: PublicKey; positionTokenAccount: PublicKey; receiver: PublicKey }
-

Parameters to close a position in a Whirlpool.

-
param receiver

PublicKey for the wallet that will receive the rented lamports.

-
param position

PublicKey for the position.

-
param positionMint

PublicKey for the mint token for the Position token.

-
param positionTokenAccount

The associated token address for the position token in the owners wallet.

-
param positionAuthority

Authority that owns the position token.

-

Type declaration

  • position: PublicKey
  • positionAuthority: PublicKey
  • positionMint: PublicKey
  • positionTokenAccount: PublicKey
  • receiver: PublicKey
CollectAllParams: { payer?: PublicKey; positionAuthority?: PublicKey; positionOwner?: PublicKey; receiver?: PublicKey }
param receiver

The destination wallet that collected fees & reward will be sent to. Defaults to ctx.wallet key.

-
param positionOwner

The wallet key that contains the position token. Defaults to ctx.wallet key.

-
param positionAuthority

The authority key that can authorize operation on the position. Defaults to ctx.wallet key.

-
param payer

The key that will pay for the initialization of ATA token accounts. Defaults to ctx.wallet key.

-

Type declaration

  • Optional payer?: PublicKey
  • Optional positionAuthority?: PublicKey
  • Optional positionOwner?: PublicKey
  • Optional receiver?: PublicKey
CollectAllPositionAddressParams: { positions: Address[] } & CollectAllParams
-

Parameters to collect all fees and rewards from a list of positions.

-
param positionAddrs

An array of Whirlpool position addresses.

-
param receiver

The destination wallet that collected fees & reward will be sent to. Defaults to ctx.wallet key.

-
param positionOwner

The wallet key that contains the position token. Defaults to ctx.wallet key.

-
param positionAuthority

The authority key that can authorize operation on the position. Defaults to ctx.wallet key.

-
param payer

The key that will pay for the initialization of ATA token accounts. Defaults to ctx.wallet key.

-
CollectAllPositionParams: { positions: Record<string, PositionData> } & CollectAllParams
-

Parameters to collect all fees and rewards from a list of positions.

-
param positions

An array of Whirlpool positions.

-
param receiver

The destination wallet that collected fees & reward will be sent to. Defaults to ctx.wallet key.

-
param positionOwner

The wallet key that contains the position token. Defaults to ctx.wallet key.

-
param positionAuthority

The authority key that can authorize operation on the position. Defaults to ctx.wallet key.

-
param payer

The key that will pay for the initialization of ATA token accounts. Defaults to ctx.wallet key.

-
CollectFeesParams: { position: PublicKey; positionAuthority: PublicKey; positionTokenAccount: PublicKey; tokenOwnerAccountA: PublicKey; tokenOwnerAccountB: PublicKey; tokenVaultA: PublicKey; tokenVaultB: PublicKey; whirlpool: PublicKey }
-

Parameters to collect fees from a position.

-
param whirlpool

PublicKey for the whirlpool that the position will be opened for.

-
param position

PublicKey for the position will be opened for.

-
param positionTokenAccount

PublicKey for the position token's associated token address.

-
param tokenOwnerAccountA

PublicKey for the token A account that will be withdrawed from.

-
param tokenOwnerAccountB

PublicKey for the token B account that will be withdrawed from.

-
param tokenVaultA

PublicKey for the tokenA vault for this whirlpool.

-
param tokenVaultB

PublicKey for the tokenB vault for this whirlpool.

-
param positionAuthority

authority that owns the token corresponding to this desired position.

-

Type declaration

  • position: PublicKey
  • positionAuthority: PublicKey
  • positionTokenAccount: PublicKey
  • tokenOwnerAccountA: PublicKey
  • tokenOwnerAccountB: PublicKey
  • tokenVaultA: PublicKey
  • tokenVaultB: PublicKey
  • whirlpool: PublicKey
CollectProtocolFeesParams: { collectProtocolFeesAuthority: PublicKey; tokenOwnerAccountA: PublicKey; tokenOwnerAccountB: PublicKey; tokenVaultA: PublicKey; tokenVaultB: PublicKey; whirlpool: PublicKey; whirlpoolsConfig: PublicKey }
-

Parameters to collect protocol fees for a Whirlpool

-
param whirlpoolsConfig

The public key for the WhirlpoolsConfig this pool is initialized in

-
param whirlpool

PublicKey for the whirlpool that the position will be opened for.

-
param tokenVaultA

PublicKey for the tokenA vault for this whirlpool.

-
param tokenVaultB

PublicKey for the tokenB vault for this whirlpool.

-
param tokenOwnerAccountA

PublicKey for the associated token account for tokenA in the collection wallet

-
param tokenOwnerAccountB

PublicKey for the associated token account for tokenA in the collection wallet

-
param collectProtocolFeesAuthority

assigned authority in the WhirlpoolsConfig that can collect protocol fees

-

Type declaration

  • collectProtocolFeesAuthority: PublicKey
  • tokenOwnerAccountA: PublicKey
  • tokenOwnerAccountB: PublicKey
  • tokenVaultA: PublicKey
  • tokenVaultB: PublicKey
  • whirlpool: PublicKey
  • whirlpoolsConfig: PublicKey
CollectRewardParams: { position: PublicKey; positionAuthority: PublicKey; positionTokenAccount: PublicKey; rewardIndex: number; rewardOwnerAccount: PublicKey; rewardVault: PublicKey; whirlpool: PublicKey }
-

Parameters to collect rewards from a reward index in a position.

-
param whirlpool

PublicKey for the whirlpool that the position will be opened for.

-
param position

PublicKey for the position will be opened for.

-
param positionTokenAccount

PublicKey for the position token's associated token address.

-
param rewardIndex

The reward index that we'd like to initialize. (0 <= index <= NUM_REWARDS).

-
param rewardOwnerAccount

PublicKey for the reward token account that the reward will deposit into.

-
param rewardVault

PublicKey of the vault account that reward will be withdrawn from.

-
param positionAuthority

authority that owns the token corresponding to this desired position.

-

Type declaration

  • position: PublicKey
  • positionAuthority: PublicKey
  • positionTokenAccount: PublicKey
  • rewardIndex: number
  • rewardOwnerAccount: PublicKey
  • rewardVault: PublicKey
  • whirlpool: PublicKey
DecreaseLiquidityInput: { liquidityAmount: BN; tokenMinA: BN; tokenMinB: BN }

Type declaration

  • liquidityAmount: BN
  • tokenMinA: BN
  • tokenMinB: BN
DecreaseLiquidityParams: { position: PublicKey; positionAuthority: PublicKey; positionTokenAccount: PublicKey; tickArrayLower: PublicKey; tickArrayUpper: PublicKey; tokenOwnerAccountA: PublicKey; tokenOwnerAccountB: PublicKey; tokenVaultA: PublicKey; tokenVaultB: PublicKey; whirlpool: PublicKey } & DecreaseLiquidityInput
-

Parameters to remove liquidity from a position.

-
param liquidityAmount

The total amount of Liquidity the user is withdrawing

-
param tokenMinA

The minimum amount of token A to remove from the position.

-
param tokenMinB

The minimum amount of token B to remove from the position.

-
param whirlpool

PublicKey for the whirlpool that the position will be opened for.

-
param position

PublicKey for the position will be opened for.

-
param positionTokenAccount

PublicKey for the position token's associated token address.

-
param tokenOwnerAccountA

PublicKey for the token A account that will be withdrawed from.

-
param tokenOwnerAccountB

PublicKey for the token B account that will be withdrawed from.

-
param tokenVaultA

PublicKey for the tokenA vault for this whirlpool.

-
param tokenVaultB

PublicKey for the tokenB vault for this whirlpool.

-
param tickArrayLower

PublicKey for the tick-array account that hosts the tick at the lower tick index.

-
param tickArrayUpper

PublicKey for the tick-array account that hosts the tick at the upper tick index.

-
param positionAuthority

authority that owns the token corresponding to this desired position.

-
DeletePositionBundleParams: { owner: PublicKey; positionBundle: PublicKey; positionBundleMint: PublicKey; positionBundleTokenAccount: PublicKey; receiver: PublicKey }
-

Parameters to delete a PositionBundle account.

-
param owner

PublicKey for the wallet that owns the position bundle token.

-
param positionBundle

PublicKey for the position bundle.

-
param positionBundleMint

PublicKey for the mint for the position bundle token.

-
param positionBundleTokenAccount

The associated token address for the position bundle token in the owners wallet.

-
param receiver

PublicKey for the wallet that will receive the rented lamports.

-

Type declaration

  • owner: PublicKey
  • positionBundle: PublicKey
  • positionBundleMint: PublicKey
  • positionBundleTokenAccount: PublicKey
  • receiver: PublicKey
DevFeeSwapInput: SwapInput & { devFeeAmount: BN }
-

Parameters to swap on a Whirlpool with developer fees

-
param swapInput

Parameters in SwapInput

-
param devFeeAmount

FeeAmount (developer fees) charged on this swap

-
IncreaseLiquidityInput: { liquidityAmount: BN; tokenMaxA: BN; tokenMaxB: BN }
-

Input parameters to deposit liquidity into a position.

-

This type is usually generated by a quote class to estimate the amount of tokens required to -deposit a certain amount of liquidity into a position.

-
param tokenMaxA

the maximum amount of tokenA allowed to withdraw from the source wallet.

-
param tokenMaxB

the maximum amount of tokenB allowed to withdraw from the source wallet.

-
param liquidityAmount

the desired amount of liquidity to deposit into the position/

-

Type declaration

  • liquidityAmount: BN
  • tokenMaxA: BN
  • tokenMaxB: BN
IncreaseLiquidityParams: { position: PublicKey; positionAuthority: PublicKey; positionTokenAccount: PublicKey; tickArrayLower: PublicKey; tickArrayUpper: PublicKey; tokenOwnerAccountA: PublicKey; tokenOwnerAccountB: PublicKey; tokenVaultA: PublicKey; tokenVaultB: PublicKey; whirlpool: PublicKey } & IncreaseLiquidityInput
-

Parameters to increase liquidity for a position.

-
param liquidityAmount

The total amount of Liquidity the user is willing to deposit.

-
param tokenMaxA

The maximum amount of token A to add to the position.

-
param tokenMaxB

The maximum amount of token B to add to the position.

-
param whirlpool

PublicKey for the whirlpool that the position will be opened for.

-
param position

PublicKey for the position will be opened for.

-
param positionTokenAccount

PublicKey for the position token's associated token address.

-
param tokenOwnerAccountA

PublicKey for the token A account that will be withdrawed from.

-
param tokenOwnerAccountB

PublicKey for the token B account that will be withdrawed from.

-
param tokenVaultA

PublicKey for the tokenA vault for this whirlpool.

-
param tokenVaultB

PublicKey for the tokenB vault for this whirlpool.

-
param tickArrayLower

PublicKey for the tick-array account that hosts the tick at the lower tick index.

-
param tickArrayUpper

PublicKey for the tick-array account that hosts the tick at the upper tick index.

-
param positionAuthority

authority that owns the token corresponding to this desired position.

-
InitConfigParams: { collectProtocolFeesAuthority: PublicKey; defaultProtocolFeeRate: number; feeAuthority: PublicKey; funder: PublicKey; rewardEmissionsSuperAuthority: PublicKey; whirlpoolsConfigKeypair: Keypair }
-

Parameters to initialize a WhirlpoolsConfig account.

-
param whirlpoolsConfigKeypair

Generated keypair for the WhirlpoolsConfig.

-
param feeAuthority

Authority authorized to initialize fee-tiers and set customs fees.

-
param collect_protocol_fees_authority

Authority authorized to collect protocol fees.

-
param rewardEmissionsSuperAuthority

Authority authorized to set reward authorities in pools.

-
param defaultProtocolFeeRate

The default protocol fee rate. Stored as a basis point of the total fees collected by feeRate.

-
param funder

The account that would fund the creation of this account

-

Type declaration

  • collectProtocolFeesAuthority: PublicKey
  • defaultProtocolFeeRate: number
  • feeAuthority: PublicKey
  • funder: PublicKey
  • rewardEmissionsSuperAuthority: PublicKey
  • whirlpoolsConfigKeypair: Keypair
InitFeeTierParams: { defaultFeeRate: number; feeAuthority: PublicKey; feeTierPda: PDA; funder: PublicKey; tickSpacing: number; whirlpoolsConfig: PublicKey }
-

Parameters to initialize a FeeTier account.

-
param whirlpoolsConfig

PublicKey for the whirlpool config space that the fee-tier will be initialized for.

-
param feeTierPda

PDA for the fee-tier account that will be initialized

-
param tickSpacing

The tick spacing this fee tier recommends its default fee rate for.

-
param defaultFeeRate

The default fee rate for this fee-tier. Stored as a hundredths of a basis point.

-
param feeAuthority

Authority authorized to initialize fee-tiers and set customs fees.

-
param funder

The account that would fund the creation of this account

-

Type declaration

  • defaultFeeRate: number
  • feeAuthority: PublicKey
  • feeTierPda: PDA
  • funder: PublicKey
  • tickSpacing: number
  • whirlpoolsConfig: PublicKey
InitPoolParams: { feeTierKey: PublicKey; funder: PublicKey; initSqrtPrice: BN; tickSpacing: number; tokenMintA: PublicKey; tokenMintB: PublicKey; tokenVaultAKeypair: Keypair; tokenVaultBKeypair: Keypair; whirlpoolPda: PDA; whirlpoolsConfig: PublicKey }
-

Parameters to initialize a Whirlpool account.

-
param initSqrtPrice

The desired initial sqrt-price for this pool

-
param whirlpoolsConfig

The public key for the WhirlpoolsConfig this pool is initialized in

-
param whirlpoolPda

PDA for the whirlpool account that would be initialized

-
param tokenMintA

Mint public key for token A

-
param tokenMintB

Mint public key for token B

-
param tokenVaultAKeypair

Keypair of the token A vault for this pool

-
param tokenVaultBKeypair

Keypair of the token B vault for this pool

-
param feeTierKey

PublicKey of the fee-tier account that this pool would use for the fee-rate

-
param tickSpacing

The desired tick spacing for this pool.

-
param funder

The account that would fund the creation of this account

-

Type declaration

  • feeTierKey: PublicKey
  • funder: PublicKey
  • initSqrtPrice: BN
  • tickSpacing: number
  • tokenMintA: PublicKey
  • tokenMintB: PublicKey
  • tokenVaultAKeypair: Keypair
  • tokenVaultBKeypair: Keypair
  • whirlpoolPda: PDA
  • whirlpoolsConfig: PublicKey
InitTickArrayParams: { funder: PublicKey; startTick: number; tickArrayPda: PDA; whirlpool: PublicKey }
-

Parameters to initialize a TickArray account.

-
param whirlpool

PublicKey for the whirlpool that the initialized tick-array will host ticks for.

-
param tickArrayPda

PDA for the tick array account that will be initialized

-
param startTick

The starting tick index for this tick-array. Has to be a multiple of TickArray size & the tick spacing of this pool.

-
param funder

The account that would fund the creation of this account

-

Type declaration

  • funder: PublicKey
  • startTick: number
  • tickArrayPda: PDA
  • whirlpool: PublicKey
InitializePositionBundleParams: { funder: PublicKey; owner: PublicKey; positionBundleMintKeypair: Keypair; positionBundlePda: PDA; positionBundleTokenAccount: PublicKey }
-

Parameters to initialize a PositionBundle account.

-
param owner

PublicKey for the wallet that will host the minted position bundle token.

-
param positionBundlePda

PDA for the derived position bundle address.

-
param positionBundleMintKeypair

Keypair for the mint for the position bundle token.

-
param positionBundleTokenAccount

The associated token address for the position bundle token in the owners wallet.

-
param funder

The account that would fund the creation of this account

-

Type declaration

  • funder: PublicKey
  • owner: PublicKey
  • positionBundleMintKeypair: Keypair
  • positionBundlePda: PDA
  • positionBundleTokenAccount: PublicKey
InitializeRewardParams: { funder: PublicKey; rewardAuthority: PublicKey; rewardIndex: number; rewardMint: PublicKey; rewardVaultKeypair: Keypair; whirlpool: PublicKey }
-

Parameters to initialize a rewards for a Whirlpool

-
param whirlpool

PublicKey for the whirlpool config space that the fee-tier will be initialized for.

-
param rewardIndex

The reward index that we'd like to initialize. (0 <= index <= NUM_REWARDS).

-
param rewardMint

PublicKey for the reward mint that we'd use for the reward index.

-
param rewardVaultKeypair

Keypair of the vault for this reward index.

-
param rewardAuthority

Assigned authority by the reward_super_authority for the specified reward-index in this Whirlpool

-
param funder

The account that would fund the creation of this account

-

Type declaration

  • funder: PublicKey
  • rewardAuthority: PublicKey
  • rewardIndex: number
  • rewardMint: PublicKey
  • rewardVaultKeypair: Keypair
  • whirlpool: PublicKey
OpenBundledPositionParams: { bundleIndex: number; bundledPositionPda: PDA; funder: PublicKey; positionBundle: PublicKey; positionBundleAuthority: PublicKey; positionBundleTokenAccount: PublicKey; tickLowerIndex: number; tickUpperIndex: number; whirlpool: PublicKey }
-

Parameters to open a bundled position in a Whirlpool.

-
param whirlpool

PublicKey for the whirlpool that the bundled position will be opened for.

-
param bundledPositionPda

PDA for the derived bundled position address.

-
param positionBundle

PublicKey for the position bundle.

-
param positionBundleTokenAccount

The associated token address for the position bundle token in the owners wallet.

-
param positionBundleAuthority

authority that owns the token corresponding to this desired bundled position.

-
param bundleIndex

The bundle index that holds the bundled position.

-
param tickLowerIndex

The tick specifying the lower end of the bundled position range.

-
param tickUpperIndex

The tick specifying the upper end of the bundled position range.

-
param funder

The account that would fund the creation of this account

-

Type declaration

  • bundleIndex: number
  • bundledPositionPda: PDA
  • funder: PublicKey
  • positionBundle: PublicKey
  • positionBundleAuthority: PublicKey
  • positionBundleTokenAccount: PublicKey
  • tickLowerIndex: number
  • tickUpperIndex: number
  • whirlpool: PublicKey
OpenPositionParams: { funder: PublicKey; owner: PublicKey; positionMintAddress: PublicKey; positionPda: PDA; positionTokenAccount: PublicKey; tickLowerIndex: number; tickUpperIndex: number; whirlpool: PublicKey }
-

Parameters to open a position in a Whirlpool.

-
param whirlpool

PublicKey for the whirlpool that the position will be opened for.

-
param ownerKey

PublicKey for the wallet that will host the minted position token.

-
param positionPda

PDA for the derived position address.

-
param positionMintAddress

PublicKey for the mint token for the Position token.

-
param positionTokenAccount

The associated token address for the position token in the owners wallet.

-
param tickLowerIndex

The tick specifying the lower end of the position range.

-
param tickUpperIndex

The tick specifying the upper end of the position range.

-
param funder

The account that would fund the creation of this account

-

Type declaration

  • funder: PublicKey
  • owner: PublicKey
  • positionMintAddress: PublicKey
  • positionPda: PDA
  • positionTokenAccount: PublicKey
  • tickLowerIndex: number
  • tickUpperIndex: number
  • whirlpool: PublicKey
SetCollectProtocolFeesAuthorityParams: { collectProtocolFeesAuthority: PublicKey; newCollectProtocolFeesAuthority: PublicKey; whirlpoolsConfig: PublicKey }
-

Parameters to set the collect fee authority in a WhirlpoolsConfig

-
param whirlpoolsConfig

The public key for the WhirlpoolsConfig this pool is initialized in

-
param collectProtocolFeesAuthority

The current collectProtocolFeesAuthority in the WhirlpoolsConfig

-
param newCollectProtocolFeesAuthority

The new collectProtocolFeesAuthority in the WhirlpoolsConfig

-

Type declaration

  • collectProtocolFeesAuthority: PublicKey
  • newCollectProtocolFeesAuthority: PublicKey
  • whirlpoolsConfig: PublicKey
SetDefaultFeeRateParams: { defaultFeeRate: number; feeAuthority: PublicKey; tickSpacing: number; whirlpoolsConfig: PublicKey }
-

Parameters to set the default fee rate for a FeeTier.

-
param whirlpoolsConfig

The public key for the WhirlpoolsConfig this fee-tier is initialized in

-
param feeAuthority

Authority authorized in the WhirlpoolsConfig to set default fee rates.

-
param tickSpacing

The tick spacing of the fee-tier that we would like to update.

-
param defaultFeeRate

The new default fee rate for this fee-tier. Stored as a hundredths of a basis point.

-

Type declaration

  • defaultFeeRate: number
  • feeAuthority: PublicKey
  • tickSpacing: number
  • whirlpoolsConfig: PublicKey
SetDefaultProtocolFeeRateParams: { defaultProtocolFeeRate: number; feeAuthority: PublicKey; whirlpoolsConfig: PublicKey }
-

Parameters to set the default fee rate for a FeeTier.

-
param whirlpoolsConfig

The public key for the WhirlpoolsConfig this pool is initialized in

-
param feeAuthority

Authority authorized in the WhirlpoolsConfig to set default fee rates.

-
param defaultProtocolFeeRate

The new default protocol fee rate for this config. Stored as a basis point of the total fees collected by feeRate.

-

Type declaration

  • defaultProtocolFeeRate: number
  • feeAuthority: PublicKey
  • whirlpoolsConfig: PublicKey
SetFeeAuthorityParams: { feeAuthority: PublicKey; newFeeAuthority: PublicKey; whirlpoolsConfig: PublicKey }
-

Parameters to set the fee authority in a WhirlpoolsConfig

-
param whirlpoolsConfig

The public key for the WhirlpoolsConfig this pool is initialized in

-
param feeAuthority

The current feeAuthority in the WhirlpoolsConfig

-
param newFeeAuthority

The new feeAuthority in the WhirlpoolsConfig

-

Type declaration

  • feeAuthority: PublicKey
  • newFeeAuthority: PublicKey
  • whirlpoolsConfig: PublicKey
SetFeeRateParams: { feeAuthority: PublicKey; feeRate: number; whirlpool: PublicKey; whirlpoolsConfig: PublicKey }
-

Parameters to set fee rate for a Whirlpool.

-
param whirlpool

PublicKey for the whirlpool to update. This whirlpool has to be part of the provided WhirlpoolsConfig space.

-
param whirlpoolsConfig

The public key for the WhirlpoolsConfig this pool is initialized in

-
param feeAuthority

Authority authorized in the WhirlpoolsConfig to set default fee rates.

-
param feeRate

The new fee rate for this fee-tier. Stored as a hundredths of a basis point.

-

Type declaration

  • feeAuthority: PublicKey
  • feeRate: number
  • whirlpool: PublicKey
  • whirlpoolsConfig: PublicKey
SetProtocolFeeRateParams: { feeAuthority: PublicKey; protocolFeeRate: number; whirlpool: PublicKey; whirlpoolsConfig: PublicKey }
-

Parameters to set fee rate for a Whirlpool.

-
param whirlpool

PublicKey for the whirlpool to update. This whirlpool has to be part of the provided WhirlpoolsConfig space.

-
param whirlpoolsConfig

The public key for the WhirlpoolsConfig this pool is initialized in

-
param feeAuthority

Authority authorized in the WhirlpoolsConfig to set default fee rates.

-
param protocolFeeRate

The new default protocol fee rate for this pool. Stored as a basis point of the total fees collected by feeRate.

-

Type declaration

  • feeAuthority: PublicKey
  • protocolFeeRate: number
  • whirlpool: PublicKey
  • whirlpoolsConfig: PublicKey
SetRewardAuthorityBySuperAuthorityParams: { newRewardAuthority: PublicKey; rewardEmissionsSuperAuthority: PublicKey; rewardIndex: number; whirlpool: PublicKey; whirlpoolsConfig: PublicKey }
-

Parameters to update the reward authority at a particular rewardIndex on a Whirlpool.

-
param whirlpool

PublicKey for the whirlpool to update. This whirlpool has to be part of the provided WhirlpoolsConfig space.

-
param whirlpoolsConfig

The public key for the WhirlpoolsConfig this pool is initialized in

-
param rewardIndex

The reward index that we'd like to update. (0 <= index <= NUM_REWARDS).

-
param rewardEmissionsSuperAuthority

The current rewardEmissionsSuperAuthority in the WhirlpoolsConfig

-
param newRewardAuthority

The new rewardAuthority in the Whirlpool at the rewardIndex

-

Type declaration

  • newRewardAuthority: PublicKey
  • rewardEmissionsSuperAuthority: PublicKey
  • rewardIndex: number
  • whirlpool: PublicKey
  • whirlpoolsConfig: PublicKey
SetRewardAuthorityParams: { newRewardAuthority: PublicKey; rewardAuthority: PublicKey; rewardIndex: number; whirlpool: PublicKey }
-

Parameters to update the reward authority at a particular rewardIndex on a Whirlpool.

-
param whirlpool

PublicKey for the whirlpool to update.

-
param rewardIndex

The reward index that we'd like to update. (0 <= index <= NUM_REWARDS).

-
param rewardAuthority

The current rewardAuthority in the Whirlpool at the rewardIndex

-
param newRewardAuthority

The new rewardAuthority in the Whirlpool at the rewardIndex

-

Type declaration

  • newRewardAuthority: PublicKey
  • rewardAuthority: PublicKey
  • rewardIndex: number
  • whirlpool: PublicKey
SetRewardEmissionsParams: { emissionsPerSecondX64: BN; rewardAuthority: PublicKey; rewardIndex: number; rewardVaultKey: PublicKey; whirlpool: PublicKey }
-

Parameters to set rewards emissions for a reward in a Whirlpool

-
param whirlpool

PublicKey for the whirlpool which the reward resides in.

-
param rewardIndex

The reward index that we'd like to initialize. (0 <= index <= NUM_REWARDS).

-
param rewardVaultKey

PublicKey of the vault for this reward index.

-
param rewardAuthority

Assigned authority by the reward_super_authority for the specified reward-index in this Whirlpool

-
param emissionsPerSecondX64

The new emissions per second to set for this reward.

-

Type declaration

  • emissionsPerSecondX64: BN
  • rewardAuthority: PublicKey
  • rewardIndex: number
  • rewardVaultKey: PublicKey
  • whirlpool: PublicKey
SetRewardEmissionsSuperAuthorityParams: { newRewardEmissionsSuperAuthority: PublicKey; rewardEmissionsSuperAuthority: PublicKey; whirlpoolsConfig: PublicKey }
-

Parameters to set rewards emissions for a reward in a Whirlpool

-
param whirlpoolsConfig

PublicKey for the WhirlpoolsConfig that we want to update.

-
param rewardEmissionsSuperAuthority

Current reward emission super authority in this WhirlpoolsConfig

-
param newRewardEmissionsSuperAuthority

New reward emission super authority for this WhirlpoolsConfig

-

Type declaration

  • newRewardEmissionsSuperAuthority: PublicKey
  • rewardEmissionsSuperAuthority: PublicKey
  • whirlpoolsConfig: PublicKey
SwapInput: { aToB: boolean; amount: BN; amountSpecifiedIsInput: boolean; otherAmountThreshold: BN; sqrtPriceLimit: BN; tickArray0: PublicKey; tickArray1: PublicKey; tickArray2: PublicKey }
-

Parameters that describe the nature of a swap on a Whirlpool.

-
param aToB

The direction of the swap. True if swapping from A to B. False if swapping from B to A.

-
param amountSpecifiedIsInput

Specifies the token the parameter amountrepresents. If true, the amount represents - the input token of the swap.

-
param amount

The amount of input or output token to swap from (depending on amountSpecifiedIsInput).

-
param otherAmountThreshold

The maximum/minimum of input/output token to swap into (depending on amountSpecifiedIsInput).

-
param sqrtPriceLimit

The maximum/minimum price the swap will swap to.

-
param tickArray0

PublicKey of the tick-array where the Whirlpool's currentTickIndex resides in

-
param tickArray1

The next tick-array in the swap direction. If the swap will not reach the next tick-aray, input the same array as tickArray0.

-
param tickArray2

The next tick-array in the swap direction after tickArray2. If the swap will not reach the next tick-aray, input the same array as tickArray1.

-

Type declaration

  • aToB: boolean
  • amount: BN
  • amountSpecifiedIsInput: boolean
  • otherAmountThreshold: BN
  • sqrtPriceLimit: BN
  • tickArray0: PublicKey
  • tickArray1: PublicKey
  • tickArray2: PublicKey
SwapParams: SwapInput & { oracle: PublicKey; tokenAuthority: PublicKey; tokenOwnerAccountA: PublicKey; tokenOwnerAccountB: PublicKey; tokenVaultA: PublicKey; tokenVaultB: PublicKey; whirlpool: PublicKey }
-

Raw parameters and accounts to swap on a Whirlpool

-
param swapInput

Parameters in SwapInput

-
param whirlpool

PublicKey for the whirlpool that the swap will occur on

-
param tokenOwnerAccountA

PublicKey for the associated token account for tokenA in the collection wallet

-
param tokenOwnerAccountB

PublicKey for the associated token account for tokenB in the collection wallet

-
param tokenVaultA

PublicKey for the tokenA vault for this whirlpool.

-
param tokenVaultB

PublicKey for the tokenB vault for this whirlpool.

-
param oracle

PublicKey for the oracle account for this Whirlpool.

-
param tokenAuthority

authority to withdraw tokens from the input token account

-
UpdateFeesAndRewardsParams: { position: PublicKey; tickArrayLower: PublicKey; tickArrayUpper: PublicKey; whirlpool: PublicKey }
-

Parameters to update fees and reward values for a position.

-
param whirlpool

PublicKey for the whirlpool that the position will be opened for.

-
param position

PublicKey for the position will be opened for.

-
param tickArrayLower

PublicKey for the tick-array account that hosts the tick at the lower tick index.

-
param tickArrayUpper

PublicKey for the tick-array account that hosts the tick at the upper tick index.

-

Type declaration

  • position: PublicKey
  • tickArrayLower: PublicKey
  • tickArrayUpper: PublicKey
  • whirlpool: PublicKey

Network

WhirlpoolAccountFetchOptions: SimpleAccountFetchOptions
-

Type to define fetch options for the WhirlpoolAccountFetcherInterface

-
WhirlpoolSupportedTypes: WhirlpoolsConfigData | WhirlpoolData | PositionData | TickArrayData | FeeTierData | PositionBundleData | BasicSupportedTypes
-

Union type of all the {@link ParsableEntity} types that can be cached in the WhirlpoolAccountFetcherInterface

-
DEFAULT_WHIRLPOOL_RETENTION_POLICY: ReadonlyMap<ParsableEntity<WhirlpoolSupportedTypes>, number> = ...
-

The default retention periods for each {@link ParsableEntity} type in the WhirlpoolAccountFetcherInterface

-
IGNORE_CACHE: WhirlpoolAccountFetchOptions = ...
-

Default fetch option for always fetching when making an account request to the WhirlpoolAccountFetcherInterface

-
PREFER_CACHE: WhirlpoolAccountFetchOptions = ...
-

Default fetch option for always using the cached value for an account request to the WhirlpoolAccountFetcherInterface

-
  • getAllWhirlpoolAccountsForConfig(__namedParameters: { configId: Address; connection: Connection; programId: Address }): Promise<ReadonlyMap<string, WhirlpoolData>>
  • -

    Retrieve a list of whirlpool addresses and accounts filtered by the given params using -getProgramAccounts.

    -

    Parameters

    • __namedParameters: { configId: Address; connection: Connection; programId: Address }
      • configId: Address
      • connection: Connection
      • programId: Address

    Returns Promise<ReadonlyMap<string, WhirlpoolData>>

    tuple of whirlpool addresses and accounts

    -

Other

AtaAccountInfo: Pick<Account, "address" | "owner" | "mint">
-

A type representing a Associated Token Account

-
param address

The address of the ATA account.

-
param owner

The owner address of the ATA.

-
param mint

The mint of the token the ATA represents.

-
WHIRLPOOL_IDL: Idl = ...
  • -

    Get the size of an account owned by the Whirlpool program in bytes.

    -

    Parameters

    Returns number

    Size in bytes of the account

    -

PoolGraph

Edge: { poolAddress: Address }
-

A type representing a pool graph edge.

-

Type declaration

  • poolAddress: Address
Path: { edges: Edge[]; endTokenMint: string; startTokenMint: string }
-

A path to trade from start token mint to end token mint.

-
param startMint

The token the path starts with

-
param endMint

The token the path ends with

-
param edges

An ordered list of edges (pool addresses) that make up the path

-

Type declaration

  • edges: Edge[]
  • endTokenMint: string
  • startTokenMint: string
PathSearchEntries: (readonly [string, Path[]])[]
-

Results for a series of graph search queries between two tokens. -The search id for each entry can be obtained from {@link PoolGraphUtils.getSearchRouteId} -If a path exist between tokens for that search id, it will be an array of paths. -If paths do not exist, it will be an empty array.

-
PathSearchOptions: { intermediateTokens: Address[] }
-

Options for finding a path between two tokens

-
param intermediateTokens

A list of tokens that can be used as intermediate hops

-

Type declaration

  • intermediateTokens: Address[]
PoolGraph: { getAllPaths: any; getPath: any; getPathsForPairs: any }
-

A type representing an undirected graph of pools that can be used to find paths between two tokens. -In this graph, nodes are token mints, and edges are pools

-

Type declaration

  • getAllPaths:function
  • getPath:function
    • -

      Get a list of paths between two tokens for this pool graph.

      -

      Notes:

      -
        -
      • Only support paths with up to 2 edges
      • -
      • Paths searching between two identical token mints are not supported.
      • -
      -

      Parameters

      • startMint: Address
        -

        The token the path starts from

        -
      • endMint: Address
        -

        The token the path ends in

        -
      • Optional options: PathSearchOptions
        -

        Options for finding a path

        -

      Returns Path[]

      A list of path between the two tokens. If no path are found, it will be an empty array.

      -
  • getPathsForPairs:function
    • -

      Get a map of paths from a list of token pairs for this pool graph.

      -

      Notes:

      -
        -
      • Only support paths with up to 2 edges
      • -
      • Paths searching between two identical token mints are not supported.
      • -
      -

      Parameters

      • searchTokenPairs: [Address, Address][]
        -

        A list of token pairs to find paths for. The first token in the pair is the start token, and the second token is the end token.

        -
      • Optional options: PathSearchOptions
        -

        Options for finding a path

        -

      Returns PathSearchEntries

      An array of search result entires in the same order as the searchTokenPairs.

      -

PriceModule

DecimalsMap: Record<string, number>
-

A map of token mint addresses against token decimals.

-
GetPricesConfig: { programId: PublicKey; quoteTokens: PublicKey[]; tickSpacings: number[]; whirlpoolsConfig: PublicKey }
-

A config object for the PriceModule functions.

-
param quoteTokens

The group of quote tokens that you want to search Whirlpools for. - The first token must be the token that is being priced against the other tokens. - The subsequent tokens are alternative tokens that can be used to price the first token.

-
param tickSpacings

The group of tick spacings that you want to search Whirlpools for.

-
param programId

The public key of the Whirlpool Program account that you want to search Whirlpools for.

-
param whirlpoolsConfig

The public key of the WhirlpoolsConfig account that you want to search Whirlpools for.

-

Type declaration

  • programId: PublicKey
  • quoteTokens: PublicKey[]
  • tickSpacings: number[]
  • whirlpoolsConfig: PublicKey
GetPricesThresholdConfig: { amountOut: BN; priceImpactThreshold: number }
-

A config object for the PriceModule functions to define thresholds for price calculations. -Whirlpools that do not fit the criteria set by the parameters below will be excluded in the price calculation.

-
param amountOut

The token amount in terms of the first quote token amount to evaluate a Whirlpool's liquidity against.

-
param priceImpactThreshold

Using amountOut to perform a swap quote on a pool, this value is the maximum price impact - that a Whirlpool can have to be included in the price calculation.

-

Type declaration

  • amountOut: BN
  • priceImpactThreshold: number
PoolMap: Record<string, WhirlpoolData>
-

A map of whirlpool addresses against WhirlpoolData accounts

-
PriceCalculationData: { decimalsMap: DecimalsMap; poolMap: PoolMap; tickArrayMap: TickArrayMap }
-

A set of fetched accounts that are used for price calculations in PriceModule functions.

-
param poolMap

A map of WhirlpoolData accounts that are used for price calculations.

-
param tickArrayMap

A map of TickArrayData accounts that are used for price calculations.

-
param decimalsMap

A map of token decimals that are used for price calculations.

-

Type declaration

PriceMap: Record<string, Decimal | null>
-

A map of token mint addresses against price values. If a price is not available, the value will be null.

-
TickArrayMap: Record<string, TickArrayData>
-

A map of tick-array addresses against TickArrayData accounts

-
defaultGetPricesConfig: GetPricesConfig = ...
-

The default GetPricesConfig config for Orca's mainnet deployment.

-
defaultGetPricesThresholdConfig: GetPricesThresholdConfig = ...
-

The default GetPricesThresholdConfig config for Orca's mainnet deployment.

-
defaultQuoteTokens: PublicKey[] = ...
-

The default quote tokens used for Orca's mainnet deployment. -Supply your own if you are using a different deployment.

-

Quotes

CollectFeesQuote: { feeOwedA: BN; feeOwedB: BN }

Type declaration

  • feeOwedA: BN
  • feeOwedB: BN
CollectFeesQuoteParam: { position: PositionData; tickLower: TickData; tickUpper: TickData; whirlpool: WhirlpoolData }

Type declaration

CollectRewardsQuote: [BN | undefined, BN | undefined, BN | undefined]
-

An array of reward amounts that is collectible on a position.

-
CollectRewardsQuoteParam: { position: PositionData; tickLower: TickData; tickUpper: TickData; timeStampInSeconds?: BN; whirlpool: WhirlpoolData }
-

Parameters needed to generate a quote on collectible rewards on a position.

-
param whirlpool

the account data for the whirlpool this position belongs to

-
param position

the account data for the position

-
param tickLower

the TickData account for the lower bound of this position

-
param tickUpper

the TickData account for the upper bound of this position

-
param timeStampInSeconds

optional parameter to generate this quote to a unix time stamp.

-

Type declaration

DecreaseLiquidityQuote: DecreaseLiquidityInput & { tokenEstA: BN; tokenEstB: BN }
-

Return object from decrease liquidity quote functions.

-
DecreaseLiquidityQuoteParam: { liquidity: BN; slippageTolerance: Percentage; sqrtPrice: BN; tickCurrentIndex: number; tickLowerIndex: number; tickUpperIndex: number }
param liquidity

The desired liquidity to withdraw from the Whirlpool

-
param tickCurrentIndex

The Whirlpool's current tickIndex

-
param sqrtPrice

The Whirlpool's current sqrtPrice

-
param tickLowerIndex

The lower index of the position that we are withdrawing from.

-
param tickUpperIndex

The upper index of the position that we are withdrawing from.

-
param slippageTolerance

The maximum slippage allowed when calculating the minimum tokens received.

-

Type declaration

  • liquidity: BN
  • slippageTolerance: Percentage
  • sqrtPrice: BN
  • tickCurrentIndex: number
  • tickLowerIndex: number
  • tickUpperIndex: number
DevFeeSwapQuote: NormalSwapQuote & { amountSpecifiedIsInput: true; devFeeAmount: BN; estimatedSwapFeeAmount: BN }
-

A collection of estimated values from quoting a swap that collects a developer-fee.

-
param estimatedAmountIn

Approximate number of input token swapped in the swap

-
param estimatedAmountOut

Approximate number of output token swapped in the swap

-
param estimatedEndTickIndex

Approximate tick-index the Whirlpool will land on after this swap

-
param estimatedEndSqrtPrice

Approximate sqrtPrice the Whirlpool will land on after this swap

-
param estimatedFeeAmount

Approximate feeAmount (all fees) charged on this swap

-
param estimatedSwapFeeAmount

Approximate feeAmount (LP + protocol fees) charged on this swap

-
param devFeeAmount

FeeAmount (developer fees) charged on this swap

-
IncreaseLiquidityQuote: IncreaseLiquidityInput & { tokenEstA: BN; tokenEstB: BN }
-

Return object from increase liquidity quote functions.

-
IncreaseLiquidityQuoteParam: { inputTokenAmount: BN; inputTokenMint: PublicKey; slippageTolerance: Percentage; sqrtPrice: BN; tickCurrentIndex: number; tickLowerIndex: number; tickUpperIndex: number; tokenMintA: PublicKey; tokenMintB: PublicKey }
param inputTokenAmount

The amount of input tokens to deposit.

-
param inputTokenMint

The mint of the input token the user would like to deposit.

-
param tokenMintA

The mint of tokenA in the Whirlpool the user is depositing into.

-
param tokenMintB

-The mint of tokenB in the Whirlpool the user is depositing into.

-
param tickCurrentIndex

The Whirlpool's current tickIndex

-
param sqrtPrice

The Whirlpool's current sqrtPrice

-
param tickLowerIndex

The lower index of the position that we are withdrawing from.

-
param tickUpperIndex

The upper index of the position that we are withdrawing from.

-
param slippageTolerance

The maximum slippage allowed when calculating the minimum tokens received.

-

Type declaration

  • inputTokenAmount: BN
  • inputTokenMint: PublicKey
  • slippageTolerance: Percentage
  • sqrtPrice: BN
  • tickCurrentIndex: number
  • tickLowerIndex: number
  • tickUpperIndex: number
  • tokenMintA: PublicKey
  • tokenMintB: PublicKey
NormalSwapQuote: SwapInput & SwapEstimates
-

A collection of estimated values from quoting a swap. Object can be directly used in a swap transaction.

-
NormalTwoHopSwapQuote: { swapOneEstimates: SwapEstimates; swapTwoEstimates: SwapEstimates } & TwoHopSwapInput
-

A collection of estimated values from quoting a two-hop-swap.

-
param swapOneEstimates

Estimates for the first leg of the two-hop-swap

-
param swapTwoEstimates

Estimates for the second leg of the two-hop-swap

-
experimental

Not yet ready for use

-
SwapEstimates: { estimatedAmountIn: BN; estimatedAmountOut: BN; estimatedEndSqrtPrice: BN; estimatedEndTickIndex: number; estimatedFeeAmount: BN }
-

A collection of estimated values from quoting a swap.

-
param estimatedAmountIn

Approximate number of input token swapped in the swap

-
param estimatedAmountOut

Approximate number of output token swapped in the swap

-
param estimatedEndTickIndex

Approximate tick-index the Whirlpool will land on after this swap

-
param estimatedEndSqrtPrice

Approximate sqrtPrice the Whirlpool will land on after this swap

-
param estimatedFeeAmount

Approximate feeAmount (all fees) charged on this swap

-

Type declaration

  • estimatedAmountIn: BN
  • estimatedAmountOut: BN
  • estimatedEndSqrtPrice: BN
  • estimatedEndTickIndex: number
  • estimatedFeeAmount: BN
-

A collection of estimated values from quoting a swap.

-
link

{BaseSwapQuote}

-
link

{DevFeeSwapQuote}

-
SwapQuoteParam: { aToB: boolean; amountSpecifiedIsInput: boolean; otherAmountThreshold: BN; sqrtPriceLimit: BN; tickArrays: TickArray[]; tokenAmount: BN; whirlpoolData: WhirlpoolData }
param tokenAmount

The amount of input or output token to swap from (depending on amountSpecifiedIsInput).

-
param otherAmountThreshold

The maximum/minimum of input/output token to swap into (depending on amountSpecifiedIsInput).

-
param sqrtPriceLimit

The maximum/minimum price the swap will swap to.

-
param aToB

The direction of the swap. True if swapping from A to B. False if swapping from B to A.

-
param amountSpecifiedIsInput

Specifies the token the parameter amountrepresents. If true, the amount represents - the input token of the swap.

-
param tickArrays

An sequential array of tick-array objects in the direction of the trade to swap on

-

Type declaration

  • aToB: boolean
  • amountSpecifiedIsInput: boolean
  • otherAmountThreshold: BN
  • sqrtPriceLimit: BN
  • tickArrays: TickArray[]
  • tokenAmount: BN
  • whirlpoolData: WhirlpoolData
TwoHopSwapQuote: NormalTwoHopSwapQuote
-

A collection of estimated values from quoting a swap.

-
link

{NormalTwoHopSwapQuote}

-
experimental

Not yet ready for use

-
  • -

    Get an estimated quote on the minimum tokens receivable based on the desired withdraw liquidity value.

    -

    Parameters

    • liquidity: BN
      -

      The desired liquidity to withdraw from the Whirlpool

      -
    • slippageTolerance: Percentage
      -

      The maximum slippage allowed when calculating the minimum tokens received.

      -
    • position: Position
      -

      A Position helper class to help interact with the Position account.

      -
    • whirlpool: Whirlpool
      -

      A Whirlpool helper class to help interact with the Whirlpool account.

      -

    Returns DecreaseLiquidityQuote

    An DecreaseLiquidityQuote object detailing the tokenMin & liquidity values to use when calling decrease-liquidity-ix.

    -
  • increaseLiquidityQuoteByInputToken(inputTokenMint: Address, inputTokenAmount: Decimal, tickLower: number, tickUpper: number, slippageTolerance: Percentage, whirlpool: Whirlpool): IncreaseLiquidityQuote
  • -

    Get an estimated quote on the maximum tokens required to deposit based on a specified input token amount.

    -

    Parameters

    • inputTokenMint: Address
      -

      The mint of the input token the user would like to deposit.

      -
    • inputTokenAmount: Decimal
      -

      The amount of input tokens to deposit.

      -
    • tickLower: number
      -

      The lower index of the position that we are withdrawing from.

      -
    • tickUpper: number
      -

      The upper index of the position that we are withdrawing from.

      -
    • slippageTolerance: Percentage
      -

      The maximum slippage allowed when calculating the minimum tokens received.

      -
    • whirlpool: Whirlpool
      -

      A Whirlpool helper class to help interact with the Whirlpool account.

      -

    Returns IncreaseLiquidityQuote

    An IncreaseLiquidityInput object detailing the required token amounts & liquidity values to use when calling increase-liquidity-ix.

    -
  • -

    Get an estimated swap quote using input token amount.

    -

    Parameters

    • whirlpool: Whirlpool
      -

      Whirlpool to perform the swap on

      -
    • inputTokenMint: Address
      -

      PublicKey for the input token mint to swap with

      -
    • tokenAmount: BN
      -

      The amount of input token to swap from

      -
    • slippageTolerance: Percentage
      -

      The amount of slippage to account for in this quote

      -
    • programId: Address
      -

      PublicKey for the Whirlpool ProgramId

      -
    • fetcher: WhirlpoolAccountFetcherInterface
    • Optional opts: SimpleAccountFetchOptions
      -

      an WhirlpoolAccountFetchOptions object to define fetch and cache options when accessing on-chain accounts

      -

    Returns Promise<SwapQuote>

    a SwapQuote object with slippage adjusted SwapInput parameters & estimates on token amounts, fee & end whirlpool states.

    -
  • swapQuoteByInputTokenWithDevFees(whirlpool: Whirlpool, inputTokenMint: Address, tokenAmount: BN, slippageTolerance: Percentage, programId: Address, fetcher: WhirlpoolAccountFetcherInterface, devFeePercentage: Percentage, opts?: SimpleAccountFetchOptions): Promise<DevFeeSwapQuote>
  • -

    Get an estimated swap quote using input token amount while collecting dev fees.

    -

    Parameters

    • whirlpool: Whirlpool
      -

      Whirlpool to perform the swap on

      -
    • inputTokenMint: Address
      -

      PublicKey for the input token mint to swap with

      -
    • tokenAmount: BN
      -

      The amount of input token to swap from

      -
    • slippageTolerance: Percentage
      -

      The amount of slippage to account for in this quote

      -
    • programId: Address
      -

      PublicKey for the Whirlpool ProgramId

      -
    • fetcher: WhirlpoolAccountFetcherInterface
    • devFeePercentage: Percentage
      -

      The percentage amount to send to developer wallet prior to the swap. Percentage num/dem values has to match token decimal.

      -
    • Optional opts: SimpleAccountFetchOptions
      -

      an WhirlpoolAccountFetchOptions object to define fetch and cache options when accessing on-chain accounts

      -

    Returns Promise<DevFeeSwapQuote>

    a SwapQuote object with slippage adjusted SwapInput parameters & estimates on token amounts, fee & end whirlpool states.

    -
  • -

    Get an estimated swap quote using an output token amount.

    -

    Use this quote to get an estimated amount of input token needed to receive -the defined output token amount.

    -

    Parameters

    • whirlpool: Whirlpool
      -

      Whirlpool to perform the swap on

      -
    • outputTokenMint: Address
      -

      PublicKey for the output token mint to swap into

      -
    • tokenAmount: BN
      -

      The maximum amount of output token to receive in this swap.

      -
    • slippageTolerance: Percentage
      -

      The amount of slippage to account for in this quote

      -
    • programId: Address
      -

      PublicKey for the Whirlpool ProgramId

      -
    • fetcher: WhirlpoolAccountFetcherInterface
    • Optional opts: SimpleAccountFetchOptions
      -

      an WhirlpoolAccountFetchOptions object to define fetch and cache options when accessing on-chain accounts

      -

    Returns Promise<SwapQuote>

    a SwapQuote object with slippage adjusted SwapInput parameters & estimates on token amounts, fee & end whirlpool states.

    -
  • -

    Perform a sync swap quote based on the basic swap instruction parameters.

    -

    Parameters

    • params: SwapQuoteParam
      -

      SwapQuote parameters

      -
    • slippageTolerance: Percentage
      -

      The amount of slippage to account for when generating the final quote.

      -

    Returns SwapQuote

    a SwapQuote object with slippage adjusted SwapInput parameters & estimates on token amounts, fee & end whirlpool states.

    -

Router

ExecutableRoute: readonly [TradeRoute, AddressLookupTableAccount[] | undefined]
-

A trade route that is ready to execute. -Contains the TradeRoute and a possible set of {@link AddressLookupTableAccount} that -is needed to successfully execute the trade.

-

If the lookup table accounts are undefined, then the trade can be executed with a legacy transaction.

-
RouteSelectOptions: { availableAtaAccounts?: AtaAccountInfo[]; maxSupportedTransactionVersion: "legacy" | number; maxTransactionSize: number; onRouteEvaluation?: any }
-

Parameters to configure the selection of the best route.

-
param maxSupportedTransactionVersion

The maximum transaction version that the wallet supports.

-
param maxTransactionSize

The maximum transaction size that the wallet supports.

-
param availableAtaAccounts

A list of ATA accounts that are available in this wallet to use for the swap.

-
param onRouteEvaluation

A callback that is called right before a route is evaluated. Users have a chance to add additional instructions -to be added for an accurate txn size measurement. (ex. Adding a priority fee ix to the transaction)

-

Type declaration

  • Optional availableAtaAccounts?: AtaAccountInfo[]
  • maxSupportedTransactionVersion: "legacy" | number
  • maxTransactionSize: number
  • onRouteEvaluation?:function
    • onRouteEvaluation(route: Readonly<TradeRoute>, tx: TransactionBuilder): void
RoutingOptions: { maxSplits: number; numTopPartialQuotes: number; numTopRoutes: number; percentIncrement: number }
-

Options to configure the router.

-
param percentIncrement

The percent increment to use when splitting a trade into multiple trades.

-
param numTopRoutes

The number of top routes to return from the router.

-
param numTopPartialQuotes

The number of top partial quotes to return from the router.

-
param maxSplits

The maximum number of splits to perform on a trade.

-

Type declaration

  • maxSplits: number
  • numTopPartialQuotes: number
  • numTopRoutes: number
  • percentIncrement: number
SubTradeRoute: { amountIn: BN; amountOut: BN; hopQuotes: TradeHop[]; path: Path; splitPercent: number }
-

Represents a fragment of a trade that was splitted into multiple trades for more efficient execution.

-
param path

The path of pool addresses that make up this sub trade.

-
param splitPercent

The percent of the trade that this sub trade represents.

-
param amountIn

The amount of token being traded in within this sub-route.

-
param amountOut

The amount of token being traded out within this sub-routes.

-
param hopQuotes

The quotes for each hop in the path of this trade.

-

Type declaration

  • amountIn: BN
  • amountOut: BN
  • hopQuotes: TradeHop[]
  • path: Path
  • splitPercent: number
Trade: { amountSpecifiedIsInput: boolean; tokenIn: Address; tokenOut: Address; tradeAmount: BN }
-

A Trade type that represents a trade between two tokens

-
param tokenIn

The token that is being traded in

-
param tokenOut

The token that is being traded out

-
param tradeAmount

The amount of token being traded in or out

-
param amountSpecifiedIsInput

Whether the trade amount is the amount being traded in or out

-

Type declaration

  • amountSpecifiedIsInput: boolean
  • tokenIn: Address
  • tokenOut: Address
  • tradeAmount: BN
TradeHop: { amountIn: BN; amountOut: BN; inputMint: Address; mintA: Address; mintB: Address; outputMint: Address; quote: SwapQuote; snapshot: TradeHopSnapshot; vaultA: Address; vaultB: Address; whirlpool: Address }
-

Represents a quote for a single hop in the path of a SubTradeRoute.

-
param amountIn

The amount of token being traded in for this hop.

-
param amountOut

The amount of token being traded out for this hop.

-
param whirlpool

The address of the whirlpool that this hop is trading through.

-
param inputMint

The address of the input token mint.

-
param outputMint

The address of the output token mint.

-
param mintA

The address of the first mint in the pool.

-
param mintB

The address of the second mint in the pool.

-
param vaultA

The address of the first vault in the pool.

-
param vaultB

The address of the second vault in the pool.

-
param quote

The SwapQuote for this hop.

-
param snapshot

A snapshot of the whirlpool condition when this hop was made

-

Type declaration

  • amountIn: BN
  • amountOut: BN
  • inputMint: Address
  • mintA: Address
  • mintB: Address
  • outputMint: Address
  • quote: SwapQuote
  • snapshot: TradeHopSnapshot
  • vaultA: Address
  • vaultB: Address
  • whirlpool: Address
TradeHopSnapshot: { aToB: boolean; feeRate: Percentage; sqrtPrice: BN }
-

A snapshot of the whirlpool condition when a trade hop was made.

-

Type declaration

  • aToB: boolean
  • feeRate: Percentage
  • sqrtPrice: BN
TradeRoute: { subRoutes: SubTradeRoute[]; totalAmountIn: BN; totalAmountOut: BN }
-

A trade route that is ready to execute. -A trade can be broken into multiple sub-trades for potentially better trades.

-
param subRoutes

The sub-routes that make up the trade route. The sum of all splitPercent should equal 100.

-
param totalAmountIn

The total amount of token being traded in for this trade.

-
param totalAmountOut

The total amount of token being traded out for this trade.

-

Type declaration

Solana Accounts

FeeTierData: { defaultFeeRate: number; tickSpacing: number; whirlpoolsConfig: PublicKey }

Type declaration

  • defaultFeeRate: number
  • tickSpacing: number
  • whirlpoolsConfig: PublicKey
OpenPositionBumpsData: { positionBump: number }

Type declaration

  • positionBump: number
OpenPositionWithMetadataBumpsData: { metadataBump: number; positionBump: number }

Type declaration

  • metadataBump: number
  • positionBump: number
PositionBundleData: { positionBitmap: number[]; positionBundleMint: PublicKey }

Type declaration

  • positionBitmap: number[]
  • positionBundleMint: PublicKey
PositionData: { feeGrowthCheckpointA: BN; feeGrowthCheckpointB: BN; feeOwedA: BN; feeOwedB: BN; liquidity: BN; positionMint: PublicKey; rewardInfos: PositionRewardInfoData[]; tickLowerIndex: number; tickUpperIndex: number; whirlpool: PublicKey }

Type declaration

  • feeGrowthCheckpointA: BN
  • feeGrowthCheckpointB: BN
  • feeOwedA: BN
  • feeOwedB: BN
  • liquidity: BN
  • positionMint: PublicKey
  • rewardInfos: PositionRewardInfoData[]
  • tickLowerIndex: number
  • tickUpperIndex: number
  • whirlpool: PublicKey
PositionRewardInfoData: { amountOwed: BN; growthInsideCheckpoint: BN }

Type declaration

  • amountOwed: BN
  • growthInsideCheckpoint: BN
TickArrayData: { startTickIndex: number; ticks: TickData[]; whirlpool: PublicKey }

Type declaration

  • startTickIndex: number
  • ticks: TickData[]
  • whirlpool: PublicKey
TickData: { feeGrowthOutsideA: BN; feeGrowthOutsideB: BN; initialized: boolean; liquidityGross: BN; liquidityNet: BN; rewardGrowthsOutside: BN[] }

Type declaration

  • feeGrowthOutsideA: BN
  • feeGrowthOutsideB: BN
  • initialized: boolean
  • liquidityGross: BN
  • liquidityNet: BN
  • rewardGrowthsOutside: BN[]
WhirlpoolBumpsData: { whirlpoolBump: number }

Type declaration

  • whirlpoolBump: number
WhirlpoolData: { feeGrowthGlobalA: BN; feeGrowthGlobalB: BN; feeRate: number; liquidity: BN; protocolFeeOwedA: BN; protocolFeeOwedB: BN; protocolFeeRate: number; rewardInfos: WhirlpoolRewardInfoData[]; rewardLastUpdatedTimestamp: BN; sqrtPrice: BN; tickCurrentIndex: number; tickSpacing: number; tokenMintA: PublicKey; tokenMintB: PublicKey; tokenVaultA: PublicKey; tokenVaultB: PublicKey; whirlpoolBump: number[]; whirlpoolsConfig: PublicKey }

Type declaration

  • feeGrowthGlobalA: BN
  • feeGrowthGlobalB: BN
  • feeRate: number
  • liquidity: BN
  • protocolFeeOwedA: BN
  • protocolFeeOwedB: BN
  • protocolFeeRate: number
  • rewardInfos: WhirlpoolRewardInfoData[]
  • rewardLastUpdatedTimestamp: BN
  • sqrtPrice: BN
  • tickCurrentIndex: number
  • tickSpacing: number
  • tokenMintA: PublicKey
  • tokenMintB: PublicKey
  • tokenVaultA: PublicKey
  • tokenVaultB: PublicKey
  • whirlpoolBump: number[]
  • whirlpoolsConfig: PublicKey
WhirlpoolRewardInfoData: { authority: PublicKey; emissionsPerSecondX64: BN; growthGlobalX64: BN; mint: PublicKey; vault: PublicKey }

Type declaration

  • authority: PublicKey
  • emissionsPerSecondX64: BN
  • growthGlobalX64: BN
  • mint: PublicKey
  • vault: PublicKey
WhirlpoolsConfigData: { collectProtocolFeesAuthority: PublicKey; defaultFeeRate: number; defaultProtocolFeeRate: number; feeAuthority: PublicKey; rewardEmissionsSuperAuthority: PublicKey }

Type declaration

  • collectProtocolFeesAuthority: PublicKey
  • defaultFeeRate: number
  • defaultProtocolFeeRate: number
  • feeAuthority: PublicKey
  • rewardEmissionsSuperAuthority: PublicKey
WHIRLPOOL_ACCOUNT_SIZE: number = ...
-

Size of the Whirlpool account in bytes.

-
deprecated

Please use getAccountSize instead.

-
WHIRLPOOL_CODER: BorshAccountsCoder<string> = ...
-

The Anchor coder for the Whirlpool program.

-

Whirlpool Utils

TokenAmounts: { tokenA: BN; tokenB: BN }

Type declaration

  • tokenA: BN
  • tokenB: BN

WhirlpoolClient

TickArray: { address: PublicKey; data: TickArrayData | null }
-

A wrapper class of a TickArray on a Whirlpool

-

Type declaration

TokenAccountInfo: Account
-

Extended (token) Account type to host account info for a Token.

-
TokenInfo: Mint & { mint: PublicKey }
-

Extended Mint type to host token info.

-
WhirlpoolRewardInfo: WhirlpoolRewardInfoData & { initialized: boolean; vaultAmount: BN }
-

Type to represent a reward for a reward index on a Whirlpool.

-
  • -

    Construct a WhirlpoolClient instance to help interact with Whirlpools accounts with.

    -

    Parameters

    Returns WhirlpoolClient

    a WhirlpoolClient instance to help with interacting with Whirlpools accounts.

    -

Legend

  • Constructor
  • Property
  • Method
  • Property
  • Method
  • Static property
  • Static method

Settings

Theme

Generated using TypeDoc

\ No newline at end of file diff --git a/migrations/deploy.js b/migrations/deploy.js deleted file mode 100644 index 325cf3d..0000000 --- a/migrations/deploy.js +++ /dev/null @@ -1,12 +0,0 @@ -// Migrations are an early feature. Currently, they're nothing more than this -// single deploy script that's invoked from the CLI, injecting a provider -// configured from the workspace's Anchor.toml. - -const anchor = require("@project-serum/anchor"); - -module.exports = async function (provider) { - // Configure client to use the provider. - anchor.setProvider(provider); - - // Add your deploy script here. -} diff --git a/package.json b/package.json deleted file mode 100644 index 79bfc09..0000000 --- a/package.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "name": "orca-whirlpools", - "private": true, - "workspaces": [ - "sdk", - "scripts" - ], - "scripts": { - "idl": "anchor build -i $INIT_CWD/sdk/src/artifacts -t $INIT_CWD/sdk/src/artifacts" - } -} diff --git a/programs/whirlpool/Cargo.toml b/programs/whirlpool/Cargo.toml index 88fec26..cb1765f 100644 --- a/programs/whirlpool/Cargo.toml +++ b/programs/whirlpool/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "whirlpool" +name = "whirlpool-client" version = "0.2.0" description = "Created with Anchor" edition = "2018" @@ -15,14 +15,14 @@ cpi = ["no-entrypoint"] default = [] [dependencies] -anchor-lang = "0.26" -anchor-spl = "0.26" +anchor-lang = "0.29" +anchor-spl = "0.29" spl-token = {version = "3.3", features = ["no-entrypoint"]} -solana-program = "1.14.12" +solana-program = "~1.17.0" thiserror = "1.0" uint = {version = "0.9.1", default-features = false} -borsh = "0.9.1" -mpl-token-metadata = { version = "1.7", features = ["no-entrypoint"] } +borsh = "0.10.3" +bytemuck = { version = "1.7.2" } [dev-dependencies] proptest = "1.0" diff --git a/programs/whirlpool/src/instructions/initialize_pool.rs b/programs/whirlpool/src/instructions/initialize_pool.rs index ff5a583..bbc43cb 100644 --- a/programs/whirlpool/src/instructions/initialize_pool.rs +++ b/programs/whirlpool/src/instructions/initialize_pool.rs @@ -46,33 +46,3 @@ pub struct InitializePool<'info> { pub system_program: Program<'info, System>, pub rent: Sysvar<'info, Rent>, } - -pub fn handler( - ctx: Context, - _bumps: WhirlpoolBumps, - tick_spacing: u16, - initial_sqrt_price: u128, -) -> Result<()> { - let token_mint_a = ctx.accounts.token_mint_a.key(); - let token_mint_b = ctx.accounts.token_mint_b.key(); - - let whirlpool = &mut ctx.accounts.whirlpool; - let whirlpools_config = &ctx.accounts.whirlpools_config; - - let default_fee_rate = ctx.accounts.fee_tier.default_fee_rate; - - // ignore the bump passed and use one Anchor derived - let bump = *ctx.bumps.get("whirlpool").unwrap(); - - Ok(whirlpool.initialize( - whirlpools_config, - bump, - tick_spacing, - initial_sqrt_price, - default_fee_rate, - token_mint_a, - ctx.accounts.token_vault_a.key(), - token_mint_b, - ctx.accounts.token_vault_b.key(), - )?) -} diff --git a/programs/whirlpool/src/instructions/initialize_position_bundle.rs b/programs/whirlpool/src/instructions/initialize_position_bundle.rs index ffd0429..d71faf6 100644 --- a/programs/whirlpool/src/instructions/initialize_position_bundle.rs +++ b/programs/whirlpool/src/instructions/initialize_position_bundle.rs @@ -41,23 +41,3 @@ pub struct InitializePositionBundle<'info> { pub associated_token_program: Program<'info, AssociatedToken>, } -pub fn handler(ctx: Context) -> Result<()> { - let position_bundle_mint = &ctx.accounts.position_bundle_mint; - let position_bundle = &mut ctx.accounts.position_bundle; - - position_bundle.initialize(position_bundle_mint.key())?; - - let bump = *ctx.bumps.get("position_bundle").unwrap(); - - mint_position_bundle_token_and_remove_authority( - &ctx.accounts.position_bundle, - position_bundle_mint, - &ctx.accounts.position_bundle_token_account, - &ctx.accounts.token_program, - &[ - b"position_bundle".as_ref(), - position_bundle_mint.key().as_ref(), - &[bump], - ], - ) -} diff --git a/programs/whirlpool/src/instructions/initialize_position_bundle_with_metadata.rs b/programs/whirlpool/src/instructions/initialize_position_bundle_with_metadata.rs index 98a9553..3843536 100644 --- a/programs/whirlpool/src/instructions/initialize_position_bundle_with_metadata.rs +++ b/programs/whirlpool/src/instructions/initialize_position_bundle_with_metadata.rs @@ -3,7 +3,7 @@ use anchor_spl::associated_token::AssociatedToken; use anchor_spl::token::{self, Mint, Token, TokenAccount}; use crate::constants::nft::whirlpool_nft_update_auth::ID as WPB_NFT_UPDATE_AUTH; -use crate::{state::*, util::mint_position_bundle_token_with_metadata_and_remove_authority}; +use crate::{state::*}; #[derive(Accounts)] pub struct InitializePositionBundleWithMetadata<'info> { @@ -51,33 +51,6 @@ pub struct InitializePositionBundleWithMetadata<'info> { pub associated_token_program: Program<'info, AssociatedToken>, /// CHECK: checked via account constraints - #[account(address = mpl_token_metadata::ID)] pub metadata_program: UncheckedAccount<'info>, } -pub fn handler(ctx: Context) -> Result<()> { - let position_bundle_mint = &ctx.accounts.position_bundle_mint; - let position_bundle = &mut ctx.accounts.position_bundle; - - position_bundle.initialize(position_bundle_mint.key())?; - - let bump = *ctx.bumps.get("position_bundle").unwrap(); - - mint_position_bundle_token_with_metadata_and_remove_authority( - &ctx.accounts.funder, - &ctx.accounts.position_bundle, - position_bundle_mint, - &ctx.accounts.position_bundle_token_account, - &ctx.accounts.position_bundle_metadata, - &ctx.accounts.metadata_update_auth, - &ctx.accounts.metadata_program, - &ctx.accounts.token_program, - &ctx.accounts.system_program, - &ctx.accounts.rent, - &[ - b"position_bundle".as_ref(), - position_bundle_mint.key().as_ref(), - &[bump], - ], - ) -} diff --git a/programs/whirlpool/src/instructions/open_position.rs b/programs/whirlpool/src/instructions/open_position.rs index 8738b83..7dfe49a 100644 --- a/programs/whirlpool/src/instructions/open_position.rs +++ b/programs/whirlpool/src/instructions/open_position.rs @@ -5,7 +5,6 @@ use anchor_spl::token::{self, Mint, Token, TokenAccount}; use crate::{state::*, util::mint_position_token_and_remove_authority}; #[derive(Accounts)] -#[instruction(bumps: OpenPositionBumps)] pub struct OpenPosition<'info> { #[account(mut)] pub funder: Signer<'info>, @@ -44,30 +43,3 @@ pub struct OpenPosition<'info> { pub associated_token_program: Program<'info, AssociatedToken>, } -/* - Opens a new Whirlpool Position. -*/ -pub fn handler( - ctx: Context, - _bumps: OpenPositionBumps, - tick_lower_index: i32, - tick_upper_index: i32, -) -> Result<()> { - let whirlpool = &ctx.accounts.whirlpool; - let position_mint = &ctx.accounts.position_mint; - let position = &mut ctx.accounts.position; - - position.open_position( - whirlpool, - position_mint.key(), - tick_lower_index, - tick_upper_index, - )?; - - mint_position_token_and_remove_authority( - whirlpool, - position_mint, - &ctx.accounts.position_token_account, - &ctx.accounts.token_program, - ) -} diff --git a/programs/whirlpool/src/instructions/open_position_with_metadata.rs b/programs/whirlpool/src/instructions/open_position_with_metadata.rs index 7505d7c..7dd0209 100644 --- a/programs/whirlpool/src/instructions/open_position_with_metadata.rs +++ b/programs/whirlpool/src/instructions/open_position_with_metadata.rs @@ -2,12 +2,11 @@ use anchor_lang::prelude::*; use anchor_spl::associated_token::AssociatedToken; use anchor_spl::token::{self, Mint, Token, TokenAccount}; -use crate::{state::*, util::mint_position_token_with_metadata_and_remove_authority}; +use crate::{state::*}; use crate::constants::nft::whirlpool_nft_update_auth::ID as WP_NFT_UPDATE_AUTH; #[derive(Accounts)] -#[instruction(bumps: OpenPositionWithMetadataBumps)] pub struct OpenPositionWithMetadata<'info> { #[account(mut)] pub funder: Signer<'info>, @@ -51,7 +50,6 @@ pub struct OpenPositionWithMetadata<'info> { pub associated_token_program: Program<'info, AssociatedToken>, /// CHECK: checked via account constraints - #[account(address = mpl_token_metadata::ID)] pub metadata_program: UncheckedAccount<'info>, /// CHECK: checked via account constraints @@ -59,36 +57,3 @@ pub struct OpenPositionWithMetadata<'info> { pub metadata_update_auth: UncheckedAccount<'info>, } -/* - Opens a new Whirlpool Position with Metadata account. -*/ -pub fn handler( - ctx: Context, - _bumps: OpenPositionWithMetadataBumps, - tick_lower_index: i32, - tick_upper_index: i32, -) -> Result<()> { - let whirlpool = &ctx.accounts.whirlpool; - let position_mint = &ctx.accounts.position_mint; - let position = &mut ctx.accounts.position; - - position.open_position( - whirlpool, - position_mint.key(), - tick_lower_index, - tick_upper_index, - )?; - - mint_position_token_with_metadata_and_remove_authority( - whirlpool, - position_mint, - &ctx.accounts.position_token_account, - &ctx.accounts.position_metadata_account, - &ctx.accounts.metadata_update_auth, - &ctx.accounts.funder, - &ctx.accounts.metadata_program, - &ctx.accounts.token_program, - &ctx.accounts.system_program, - &ctx.accounts.rent, - ) -} diff --git a/programs/whirlpool/src/lib.rs b/programs/whirlpool/src/lib.rs index 2c6864e..4dc737a 100644 --- a/programs/whirlpool/src/lib.rs +++ b/programs/whirlpool/src/lib.rs @@ -6,10 +6,10 @@ declare_id!("whirLbMiicVdio4qvUfM5KAg6Ct8VwpYzGff3uctyCc"); #[doc(hidden)] pub mod constants; #[doc(hidden)] -pub mod errors; -#[doc(hidden)] pub mod instructions; #[doc(hidden)] +pub mod errors; +#[doc(hidden)] pub mod manager; #[doc(hidden)] pub mod math; @@ -40,13 +40,7 @@ pub mod whirlpool { reward_emissions_super_authority: Pubkey, default_protocol_fee_rate: u16, ) -> Result<()> { - return instructions::initialize_config::handler( - ctx, - fee_authority, - collect_protocol_fees_authority, - reward_emissions_super_authority, - default_protocol_fee_rate, - ); + Ok(()) } /// Initializes a Whirlpool account. @@ -67,12 +61,7 @@ pub mod whirlpool { tick_spacing: u16, initial_sqrt_price: u128, ) -> Result<()> { - return instructions::initialize_pool::handler( - ctx, - bumps, - tick_spacing, - initial_sqrt_price, - ); + Ok(()) } /// Initializes a tick_array account to represent a tick-range in a Whirlpool. @@ -88,7 +77,7 @@ pub mod whirlpool { ctx: Context, start_tick_index: i32, ) -> Result<()> { - return instructions::initialize_tick_array::handler(ctx, start_tick_index); + Ok(()) } /// Initializes a fee_tier account usable by Whirlpools in a WhirlpoolConfig space. @@ -108,7 +97,7 @@ pub mod whirlpool { tick_spacing: u16, default_fee_rate: u16, ) -> Result<()> { - return instructions::initialize_fee_tier::handler(ctx, tick_spacing, default_fee_rate); + Ok(()) } /// Initialize reward for a Whirlpool. A pool can only support up to a set number of rewards. @@ -125,7 +114,7 @@ pub mod whirlpool { /// index in this pool, or exceeds NUM_REWARDS, or /// all reward slots for this pool has been initialized. pub fn initialize_reward(ctx: Context, reward_index: u8) -> Result<()> { - return instructions::initialize_reward::handler(ctx, reward_index); + Ok(()) } /// Set the reward emissions for a reward in a Whirlpool. @@ -150,11 +139,7 @@ pub mod whirlpool { reward_index: u8, emissions_per_second_x64: u128, ) -> Result<()> { - return instructions::set_reward_emissions::handler( - ctx, - reward_index, - emissions_per_second_x64, - ); + Ok(()) } /// Open a position in a Whirlpool. A unique token will be minted to represent the position @@ -173,12 +158,7 @@ pub mod whirlpool { tick_lower_index: i32, tick_upper_index: i32, ) -> Result<()> { - return instructions::open_position::handler( - ctx, - bumps, - tick_lower_index, - tick_upper_index, - ); + Ok(()) } /// Open a position in a Whirlpool. A unique token will be minted to represent the position @@ -198,12 +178,7 @@ pub mod whirlpool { tick_lower_index: i32, tick_upper_index: i32, ) -> Result<()> { - return instructions::open_position_with_metadata::handler( - ctx, - bumps, - tick_lower_index, - tick_upper_index, - ); + Ok(()) } /// Add liquidity to a position in the Whirlpool. This call also updates the position's accrued fees and rewards. @@ -226,12 +201,7 @@ pub mod whirlpool { token_max_a: u64, token_max_b: u64, ) -> Result<()> { - return instructions::increase_liquidity::handler( - ctx, - liquidity_amount, - token_max_a, - token_max_b, - ); + Ok(()) } /// Withdraw liquidity from a position in the Whirlpool. This call also updates the position's accrued fees and rewards. @@ -254,12 +224,7 @@ pub mod whirlpool { token_min_a: u64, token_min_b: u64, ) -> Result<()> { - return instructions::decrease_liquidity::handler( - ctx, - liquidity_amount, - token_min_a, - token_min_b, - ); + Ok(()) } /// Update the accrued fees and rewards for a position. @@ -268,7 +233,7 @@ pub mod whirlpool { /// - `TickNotFound` - Provided tick array account does not contain the tick for this position. /// - `LiquidityZero` - Position has zero liquidity and therefore already has the most updated fees and reward values. pub fn update_fees_and_rewards(ctx: Context) -> Result<()> { - return instructions::update_fees_and_rewards::handler(ctx); + Ok(()) } /// Collect fees accrued for this position. @@ -276,7 +241,7 @@ pub mod whirlpool { /// ### Authority /// - `position_authority` - authority that owns the token corresponding to this desired position. pub fn collect_fees(ctx: Context) -> Result<()> { - return instructions::collect_fees::handler(ctx); + Ok(()) } /// Collect rewards accrued for this position. @@ -284,7 +249,7 @@ pub mod whirlpool { /// ### Authority /// - `position_authority` - authority that owns the token corresponding to this desired position. pub fn collect_reward(ctx: Context, reward_index: u8) -> Result<()> { - return instructions::collect_reward::handler(ctx, reward_index); + Ok(()) } /// Collect the protocol fees accrued in this Whirlpool @@ -292,7 +257,7 @@ pub mod whirlpool { /// ### Authority /// - `collect_protocol_fees_authority` - assigned authority in the WhirlpoolConfig that can collect protocol fees pub fn collect_protocol_fees(ctx: Context) -> Result<()> { - return instructions::collect_protocol_fees::handler(ctx); + Ok(()) } /// Perform a swap in this Whirlpool @@ -324,14 +289,7 @@ pub mod whirlpool { amount_specified_is_input: bool, a_to_b: bool, ) -> Result<()> { - return instructions::swap::handler( - ctx, - amount, - other_amount_threshold, - sqrt_price_limit, - amount_specified_is_input, - a_to_b, - ); + Ok(()) } /// Close a position in a Whirlpool. Burns the position token in the owner's wallet. @@ -342,7 +300,7 @@ pub mod whirlpool { /// #### Special Errors /// - `ClosePositionNotEmpty` - The provided position account is not empty. pub fn close_position(ctx: Context) -> Result<()> { - return instructions::close_position::handler(ctx); + Ok(()) } /// Set the default_fee_rate for a FeeTier @@ -361,7 +319,7 @@ pub mod whirlpool { ctx: Context, default_fee_rate: u16, ) -> Result<()> { - return instructions::set_default_fee_rate::handler(ctx, default_fee_rate); + Ok(()) } /// Sets the default protocol fee rate for a WhirlpoolConfig @@ -380,10 +338,7 @@ pub mod whirlpool { ctx: Context, default_protocol_fee_rate: u16, ) -> Result<()> { - return instructions::set_default_protocol_fee_rate::handler( - ctx, - default_protocol_fee_rate, - ); + Ok(()) } /// Sets the fee rate for a Whirlpool. @@ -399,7 +354,7 @@ pub mod whirlpool { /// #### Special Errors /// - `FeeRateMaxExceeded` - If the provided fee_rate exceeds MAX_FEE_RATE. pub fn set_fee_rate(ctx: Context, fee_rate: u16) -> Result<()> { - return instructions::set_fee_rate::handler(ctx, fee_rate); + Ok(()) } /// Sets the protocol fee rate for a Whirlpool. @@ -418,7 +373,7 @@ pub mod whirlpool { ctx: Context, protocol_fee_rate: u16, ) -> Result<()> { - return instructions::set_protocol_fee_rate::handler(ctx, protocol_fee_rate); + Ok(()) } /// Sets the fee authority for a WhirlpoolConfig. @@ -429,7 +384,7 @@ pub mod whirlpool { /// ### Authority /// - "fee_authority" - Set authority that can modify pool fees in the WhirlpoolConfig pub fn set_fee_authority(ctx: Context) -> Result<()> { - return instructions::set_fee_authority::handler(ctx); + Ok(()) } /// Sets the fee authority to collect protocol fees for a WhirlpoolConfig. @@ -440,7 +395,7 @@ pub mod whirlpool { pub fn set_collect_protocol_fees_authority( ctx: Context, ) -> Result<()> { - return instructions::set_collect_protocol_fees_authority::handler(ctx); + Ok(()) } /// Set the whirlpool reward authority at the provided `reward_index`. @@ -454,7 +409,7 @@ pub mod whirlpool { /// index in this pool, or exceeds NUM_REWARDS, or /// all reward slots for this pool has been initialized. pub fn set_reward_authority(ctx: Context, reward_index: u8) -> Result<()> { - return instructions::set_reward_authority::handler(ctx, reward_index); + Ok(()) } /// Set the whirlpool reward authority at the provided `reward_index`. @@ -471,7 +426,7 @@ pub mod whirlpool { ctx: Context, reward_index: u8, ) -> Result<()> { - return instructions::set_reward_authority_by_super_authority::handler(ctx, reward_index); + Ok(()) } /// Set the whirlpool reward super authority for a WhirlpoolConfig @@ -483,7 +438,7 @@ pub mod whirlpool { pub fn set_reward_emissions_super_authority( ctx: Context, ) -> Result<()> { - return instructions::set_reward_emissions_super_authority::handler(ctx); + Ok(()) } /// Perform a two-hop swap in this Whirlpool @@ -521,22 +476,13 @@ pub mod whirlpool { sqrt_price_limit_one: u128, sqrt_price_limit_two: u128, ) -> Result<()> { - return instructions::two_hop_swap::handler( - ctx, - amount, - other_amount_threshold, - amount_specified_is_input, - a_to_b_one, - a_to_b_two, - sqrt_price_limit_one, - sqrt_price_limit_two, - ); + Ok(()) } /// Initializes a PositionBundle account that bundles several positions. /// A unique token will be minted to represent the position bundle in the users wallet. pub fn initialize_position_bundle(ctx: Context) -> Result<()> { - return instructions::initialize_position_bundle::handler(ctx); + Ok(()) } /// Initializes a PositionBundle account that bundles several positions. @@ -545,7 +491,7 @@ pub mod whirlpool { pub fn initialize_position_bundle_with_metadata( ctx: Context, ) -> Result<()> { - return instructions::initialize_position_bundle_with_metadata::handler(ctx); + Ok(()) } /// Delete a PositionBundle account. Burns the position bundle token in the owner's wallet. @@ -556,7 +502,7 @@ pub mod whirlpool { /// ### Special Errors /// - `PositionBundleNotDeletable` - The provided position bundle has open positions. pub fn delete_position_bundle(ctx: Context) -> Result<()> { - return instructions::delete_position_bundle::handler(ctx); + Ok(()) } /// Open a bundled position in a Whirlpool. No new tokens are issued @@ -581,12 +527,7 @@ pub mod whirlpool { tick_lower_index: i32, tick_upper_index: i32, ) -> Result<()> { - return instructions::open_bundled_position::handler( - ctx, - bundle_index, - tick_lower_index, - tick_upper_index, - ); + Ok(()) } /// Close a bundled position in a Whirlpool. @@ -604,6 +545,6 @@ pub mod whirlpool { ctx: Context, bundle_index: u16, ) -> Result<()> { - return instructions::close_bundled_position::handler(ctx, bundle_index); + Ok(()) } } diff --git a/programs/whirlpool/src/math/bn.rs b/programs/whirlpool/src/math/bn.rs index 612b4b9..0cc55fc 100644 --- a/programs/whirlpool/src/math/bn.rs +++ b/programs/whirlpool/src/math/bn.rs @@ -22,7 +22,7 @@ use borsh::{BorshDeserialize, BorshSerialize}; use std::borrow::BorrowMut; use std::convert::TryInto; -use std::io::{Error, ErrorKind, Write}; +use std::io::{Error, ErrorKind, Write, Read}; use std::mem::size_of; use uint::construct_uint; @@ -44,15 +44,10 @@ macro_rules! impl_borsh_deserialize_for_bn { ($type: ident) => { impl BorshDeserialize for $type { #[inline] - fn deserialize(buf: &mut &[u8]) -> std::io::Result { - if buf.len() < size_of::<$type>() { - return Err(Error::new( - ErrorKind::InvalidInput, - "Unexpected length of input", - )); - } - let res = $type::from_le_bytes(buf[..size_of::<$type>()].try_into().unwrap()); - *buf = &buf[size_of::<$type>()..]; + fn deserialize_reader(reader: &mut R) -> std::io::Result { + let mut buffer = [0u8; size_of::<$type>()]; + reader.read_exact(&mut buffer)?; + let res = $type::from_le_bytes(buffer.try_into().unwrap()); Ok(res) } } diff --git a/programs/whirlpool/src/state/tick.rs b/programs/whirlpool/src/state/tick.rs index a59b420..cc33674 100644 --- a/programs/whirlpool/src/state/tick.rs +++ b/programs/whirlpool/src/state/tick.rs @@ -13,7 +13,7 @@ pub const MIN_TICK_INDEX: i32 = -443636; pub const TICK_ARRAY_SIZE: i32 = 88; pub const TICK_ARRAY_SIZE_USIZE: usize = 88; -#[zero_copy] +#[zero_copy(unsafe)] #[repr(packed)] #[derive(Default, Debug, PartialEq)] pub struct Tick { @@ -138,7 +138,7 @@ impl TickUpdate { } } -#[account(zero_copy)] +#[account(zero_copy(unsafe))] #[repr(packed)] pub struct TickArray { pub start_tick_index: i32, diff --git a/programs/whirlpool/src/util/token.rs b/programs/whirlpool/src/util/token.rs index 24c8a8d..1f3d632 100644 --- a/programs/whirlpool/src/util/token.rs +++ b/programs/whirlpool/src/util/token.rs @@ -1,7 +1,6 @@ use crate::state::{PositionBundle, Whirlpool}; use anchor_lang::prelude::*; use anchor_spl::token::{self, Mint, Token, TokenAccount, Transfer}; -use mpl_token_metadata::instruction::create_metadata_accounts_v3; use solana_program::program::invoke_signed; use spl_token::instruction::{burn_checked, close_account, mint_to, set_authority, AuthorityType}; @@ -113,60 +112,6 @@ pub fn mint_position_token_and_remove_authority<'info>( remove_position_token_mint_authority(whirlpool, position_mint, token_program) } -pub fn mint_position_token_with_metadata_and_remove_authority<'info>( - whirlpool: &Account<'info, Whirlpool>, - position_mint: &Account<'info, Mint>, - position_token_account: &Account<'info, TokenAccount>, - position_metadata_account: &UncheckedAccount<'info>, - metadata_update_auth: &UncheckedAccount<'info>, - funder: &Signer<'info>, - metadata_program: &UncheckedAccount<'info>, - token_program: &Program<'info, Token>, - system_program: &Program<'info, System>, - rent: &Sysvar<'info, Rent>, -) -> Result<()> { - mint_position_token( - whirlpool, - position_mint, - position_token_account, - token_program, - )?; - - let metadata_mint_auth_account = whirlpool; - invoke_signed( - &create_metadata_accounts_v3( - metadata_program.key(), - position_metadata_account.key(), - position_mint.key(), - metadata_mint_auth_account.key(), - funder.key(), - metadata_update_auth.key(), - WP_METADATA_NAME.to_string(), - WP_METADATA_SYMBOL.to_string(), - WP_METADATA_URI.to_string(), - None, - 0, - false, - true, - None, - None, - None, - ), - &[ - position_metadata_account.to_account_info(), - position_mint.to_account_info(), - metadata_mint_auth_account.to_account_info(), - metadata_update_auth.to_account_info(), - funder.to_account_info(), - metadata_program.to_account_info(), - system_program.to_account_info(), - rent.to_account_info(), - ], - &[&metadata_mint_auth_account.seeds()], - )?; - - remove_position_token_mint_authority(whirlpool, position_mint, token_program) -} fn mint_position_token<'info>( whirlpool: &Account<'info, Whirlpool>, @@ -240,77 +185,6 @@ pub fn mint_position_bundle_token_and_remove_authority<'info>( ) } -pub fn mint_position_bundle_token_with_metadata_and_remove_authority<'info>( - funder: &Signer<'info>, - position_bundle: &Account<'info, PositionBundle>, - position_bundle_mint: &Account<'info, Mint>, - position_bundle_token_account: &Account<'info, TokenAccount>, - position_bundle_metadata: &UncheckedAccount<'info>, - metadata_update_auth: &UncheckedAccount<'info>, - metadata_program: &UncheckedAccount<'info>, - token_program: &Program<'info, Token>, - system_program: &Program<'info, System>, - rent: &Sysvar<'info, Rent>, - position_bundle_seeds: &[&[u8]], -) -> Result<()> { - mint_position_bundle_token( - position_bundle, - position_bundle_mint, - position_bundle_token_account, - token_program, - position_bundle_seeds, - )?; - - // Create Metadata - // Orca Position Bundle xxxx...yyyy - // xxxx and yyyy are the first and last 4 chars of mint address - let mint_address = position_bundle_mint.key().to_string(); - let mut nft_name = String::from(WPB_METADATA_NAME_PREFIX); - nft_name += " "; - nft_name += &mint_address[0..4]; - nft_name += "..."; - nft_name += &mint_address[mint_address.len() - 4..]; - - invoke_signed( - &create_metadata_accounts_v3( - metadata_program.key(), - position_bundle_metadata.key(), - position_bundle_mint.key(), - position_bundle.key(), - funder.key(), - metadata_update_auth.key(), - nft_name, - WPB_METADATA_SYMBOL.to_string(), - WPB_METADATA_URI.to_string(), - None, - 0, - false, - true, - None, - None, - None, - ), - &[ - position_bundle.to_account_info(), - position_bundle_metadata.to_account_info(), - position_bundle_mint.to_account_info(), - metadata_update_auth.to_account_info(), - funder.to_account_info(), - metadata_program.to_account_info(), - system_program.to_account_info(), - rent.to_account_info(), - ], - &[position_bundle_seeds], - )?; - - remove_position_bundle_token_mint_authority( - position_bundle, - position_bundle_mint, - token_program, - position_bundle_seeds, - ) -} - fn mint_position_bundle_token<'info>( position_bundle: &Account<'info, PositionBundle>, position_bundle_mint: &Account<'info, Mint>, diff --git a/scripts/calcRentExempt.ts b/scripts/calcRentExempt.ts deleted file mode 100644 index bd019bb..0000000 --- a/scripts/calcRentExempt.ts +++ /dev/null @@ -1,53 +0,0 @@ -import * as anchor from "@project-serum/anchor"; -import { readFile } from "mz/fs"; -import Decimal from "decimal.js"; -import { Keypair } from "@solana/web3.js"; - -const toBuffer = (arr: Buffer | Uint8Array | Array): Buffer => { - if (arr instanceof Buffer) { - return arr; - } else if (arr instanceof Uint8Array) { - return Buffer.from(arr.buffer, arr.byteOffset, arr.byteLength); - } else { - return Buffer.from(arr); - } -}; - -async function getKeyPair(keyPath: string): Promise { - const buffer = await readFile(keyPath); - let data = JSON.parse(buffer.toString()); - return Keypair.fromSecretKey(toBuffer(data)); -} - -async function run() { - // https://api.mainnet-beta.solana.com - const wallet = new anchor.Wallet( - await getKeyPair("/Users/ottocheung/dev/solana/pub.json") - ); - const connection = new anchor.web3.Connection( - "https://api.mainnet-beta.solana.com" - ); - const provider = new anchor.AnchorProvider( - connection, - wallet, - anchor.AnchorProvider.defaultOptions() - ); - - const sizeInBytes = [ - 1024, 5000, 10000, 50000, 1000000, 3000000, 5000000, 10000000, - ]; - const solPrice = 160; - sizeInBytes.forEach(async (size) => { - const result = await provider.connection.getMinimumBalanceForRentExemption( - size - ); - const sol = new Decimal(result).mul(0.000000001); - console.log( - `size - ${size} lamports - ${result} SOL- ${sol} price - ${sol.mul( - solPrice - )}` - ); - }); -} - -run(); diff --git a/scripts/expLogTestCaseConversion.ts b/scripts/expLogTestCaseConversion.ts deleted file mode 100644 index 7530f40..0000000 --- a/scripts/expLogTestCaseConversion.ts +++ /dev/null @@ -1,15 +0,0 @@ -import Decimal from "decimal.js"; -Decimal.set({ precision: 40, rounding: 4 }); - -const x64 = new Decimal(2).pow(64); - -const number = new Decimal(1).mul(x64); -console.log(`number - ${number}`); - -const exp = new Decimal(1.0001).sqrt().pow(1).mul(x64); -console.log(`exp - ${exp.toFixed(0, 1)}`); - -const log = new Decimal(18445821805675392311) - .div(x64) - .log(new Decimal(1.0001).sqrt()); -console.log(`log - ${log.toString()}`); diff --git a/scripts/genExpBitConstants.ts b/scripts/genExpBitConstants.ts deleted file mode 100644 index aa0fd8d..0000000 --- a/scripts/genExpBitConstants.ts +++ /dev/null @@ -1,68 +0,0 @@ -import Decimal from "decimal.js"; -Decimal.set({ precision: 40, rounding: 4 }); - -/** - * This script is to generate the magic numbers & unit tests needed for the exponent function - * in Whirlpools. - * - * Explanation on what magic numbers are: - * https://www.notion.so/orcaso/Fixed-Point-Arithmetic-in-Whirlpools-63f9817a852b4029a6eb15dc755c7baf#5df2cfe5d62b4b0aa7e58f5f381c2d55 - */ - -const x32 = new Decimal(2).pow(32); -const x64 = new Decimal(2).pow(64); -const x128 = new Decimal(2).pow(128); -const b = new Decimal("1.0001"); -// Qm.n = Q32.64 -const n = 64; - -console.log( - `Printing bit constants for whirlpool exponent of base ${b.toDecimalPlaces( - 4 - )}` -); -console.log(``); -console.log(`1.0001 x64 const - ${b.mul(x64).toFixed(0, 1)}`); -console.log(``); - -console.log(`With a maximum tick of +/-443636, we'll need 19 bit constants:`); - -for (let j = 0; j <= 18; j++) { - const power = new Decimal(2).pow(j - 1); - const sqrtBPower = b.pow(power); - const iSqrtBPower = new Decimal(1).div(sqrtBPower).mul(x64); - console.log(`${iSqrtBPower.toFixed(0, 1)}`); -} - -const genUnitTestCases = (cases: number[]) => { - console.log(`tick | positive index result | negative index result`); - for (const tick of cases) { - const jsResult = new Decimal(b) - .pow(tick) - .sqrt() - .mul(new Decimal(2).pow(n)) - .toFixed(0, 1); - const njsResult = new Decimal(b) - .pow(-tick) - .sqrt() - .mul(new Decimal(2).pow(n)) - .toFixed(0, 1); - - console.log(tick + " - " + jsResult + " , " + njsResult); - } -}; - -let bitGroup = [ - 0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, - 32768, 65536, 131072, 262144, 524288, -]; -let randGroup = [2493, 23750, 395, 129, 39502, 395730, 245847, 120821].sort( - (n1, n2) => n1 - n2 -); - -console.log(" "); -console.log("Printing unit test cases for binary fraction bit cases:"); -genUnitTestCases(bitGroup); -console.log(" "); -console.log("Printing unit test cases for random values:"); -genUnitTestCases(randGroup); diff --git a/scripts/genPositiveExpBitConstants.ts b/scripts/genPositiveExpBitConstants.ts deleted file mode 100644 index 40b6fc0..0000000 --- a/scripts/genPositiveExpBitConstants.ts +++ /dev/null @@ -1,17 +0,0 @@ -import Decimal from "decimal.js"; -Decimal.set({ toExpPos: 100, toExpNeg: -100, precision: 100 }) - -const b = new Decimal(1.0001); - -const targetBitShift = 64; -const resolution = Decimal.pow(2, targetBitShift); - -const results = []; -for (let j = 0; j < 19; j++) { - // Calculate target price - const index = Decimal.pow(2, j); - console.log("index", index); - const rawPrice = b.pow(index.div(2)); - const targetPrice = rawPrice.mul(Decimal.pow(2, 96)).floor(); - console.log("targetPrice", targetPrice); -} diff --git a/scripts/package.json b/scripts/package.json deleted file mode 100644 index 9ad0688..0000000 --- a/scripts/package.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "name": "scripts", - "version": "1.0.0", - "dependencies": { - "@project-serum/anchor": "~0.25.0", - "@solana/spl-token": "^0.1.8" - }, - "devDependencies": { - "@types/mocha": "^9.0.0", - "@types/mz": "^2.7.3", - "chai": "^4.3.4", - "mocha": "^9.0.3", - "mz": "^2.7.0" - } -} diff --git a/scripts/tsconfig.json b/scripts/tsconfig.json deleted file mode 100644 index 8b05245..0000000 --- a/scripts/tsconfig.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "compilerOptions": { - "composite": true, - "target": "es6", - "module": "commonjs", - "allowJs": false, - "declaration": true, - "outDir": "./dist", - "strict": true, - "esModuleInterop": true, - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, - "resolveJsonModule": true - }, - "references": [ - { - "path": "../sdk/src" - } - ] -} diff --git a/scripts/whirlpoolNft.json b/scripts/whirlpoolNft.json deleted file mode 100644 index 6a3d0fd..0000000 --- a/scripts/whirlpoolNft.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "name": "Orca Whirlpool Position", - "symbol": "OWP", - "description": "Orca Whirlpool Position", - "image": "data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 581.4 581.4' width='120px' height='120px'%3e%3cdefs%3e%3cstyle%3e.cls-1%7bfill:%23ffd15c;%7d%3c/style%3e%3c/defs%3e%3cg id='Layer_3' data-name='Layer 3'%3e%3cpath class='cls-1' d='M523.54,249.16a233.55,233.55,0,0,0-6.7-41.53,222.48,222.48,0,0,0-35.59-75.46,219.47,219.47,0,0,0-27.72-31.06A222.1,222.1,0,0,0,420.62,76,236.75,236.75,0,0,0,384,57.44a260.8,260.8,0,0,0-38.87-12.08,304.15,304.15,0,0,0-80-6.79,4,4,0,0,0,0,8c27.6,1.25,53.31,5.45,76.45,12.49a246,246,0,0,1,35.68,13.78,225.16,225.16,0,0,1,32.68,19.26,209.66,209.66,0,0,1,28.49,24.51,197.65,197.65,0,0,1,40.51,62A199.88,199.88,0,0,1,489.64,214a205.08,205.08,0,0,1,4.22,36.61,218.73,218.73,0,0,1-2.25,36.81A194,194,0,0,1,468.46,356a178.27,178.27,0,0,1-20.76,29.22,167.18,167.18,0,0,1-26.15,24.12,177.22,177.22,0,0,1-64.3,29.73,208.44,208.44,0,0,1-35.61,5.42c-6.45.43-12.39.61-18.26.53-1,0-1.89,0-2.79-.05l-1.47,0-1.34-.07c-.95,0-1.9-.09-2.92-.17-2.93-.2-5.91-.57-8.39-.9a125,125,0,0,1-61.23-26.55,122.38,122.38,0,0,1-38.44-53.58,106.39,106.39,0,0,1-6.14-31.94c-.13-3-.06-5.92,0-8.19s.26-4.91.6-8.2a106.41,106.41,0,0,1,3-16,96.59,96.59,0,0,1,13-28.91A92.54,92.54,0,0,1,219,247.72a102.29,102.29,0,0,1,28.35-14.82,120.85,120.85,0,0,1,32.37-6.14c2.39-.15,5.12-.22,8.35-.22a43.55,43.55,0,0,1,6.33.5,27.2,27.2,0,0,1,9.92,3.39,18.74,18.74,0,0,1,6.23,6,19.74,19.74,0,0,1,2.91,8.37,20.74,20.74,0,0,1-.92,9,19.24,19.24,0,0,1-1.81,3.88,17.87,17.87,0,0,1-2.62,3.24,18.58,18.58,0,0,1-7.5,4.38,27.88,27.88,0,0,1-5.14,1.14l-.72.08c-.24,0-.48.06-.71.07l-1.57.11-4.53.1a91.91,91.91,0,0,0-13.33,1.32A79.66,79.66,0,0,0,261,271.79a68.1,68.1,0,0,0-25.36,16.26,64.19,64.19,0,0,0-15.72,26.82,66.54,66.54,0,0,0,10.52,58.55,68.6,68.6,0,0,0,22.74,19.51,78.85,78.85,0,0,0,26.66,8.55,94.71,94.71,0,0,0,13,.94h1.6l1.39,0c1,0,1.93,0,2.84-.07,1.87-.05,3.79-.14,5.69-.26a167.14,167.14,0,0,0,45-9A148.35,148.35,0,0,0,390.39,371,140,140,0,0,0,441.5,293.6,155.89,155.89,0,0,0,446,247.79a162,162,0,0,0-8.29-44.93,152.92,152.92,0,0,0-21-40.87,155.5,155.5,0,0,0-32-32.74A167,167,0,0,0,301.71,96.4a185.25,185.25,0,0,0-22.24-1.11c-7.17.09-14.4.49-21.51,1.2a239.16,239.16,0,0,0-42.29,8.1,225.88,225.88,0,0,0-76.51,38.84,211.35,211.35,0,0,0-55.49,65.3,219.75,219.75,0,0,0-25.05,81.15A247.29,247.29,0,0,0,57.84,332a234.14,234.14,0,0,0,6.66,41.54A221.33,221.33,0,0,0,100.17,449,217.9,217.9,0,0,0,128,480,220.46,220.46,0,0,0,160.85,505a244.85,244.85,0,0,0,75.4,30.85,295.93,295.93,0,0,0,66,7.27q7,0,14.07-.31a4,4,0,0,0,0-8c-27.43-1.23-53.14-5.48-76.39-12.62-6.29-1.94-12.4-4.05-18.14-6.27-5.94-2.32-11.84-4.9-17.54-7.66A223.72,223.72,0,0,1,171.58,489a200.79,200.79,0,0,1-51.82-53.66,194.09,194.09,0,0,1-28.09-68.13,206.75,206.75,0,0,1-4.18-36.61,218.06,218.06,0,0,1,2.28-36.77,185.5,185.5,0,0,1,23.84-68.1,178.87,178.87,0,0,1,48-52.74,189,189,0,0,1,64.53-30.34,198.5,198.5,0,0,1,35.38-5.81c5.93-.44,12-.62,17.91-.53a141.29,141.29,0,0,1,17.22,1.33c23.12,3.11,44.43,12,61.64,25.75a111.63,111.63,0,0,1,37,53.48,116.89,116.89,0,0,1,5.49,32.61A110.59,110.59,0,0,1,397.11,282,96.37,96.37,0,0,1,384,310.82a93.81,93.81,0,0,1-21.79,22.79,103.63,103.63,0,0,1-28.39,14.88,120,120,0,0,1-32.31,6.19c-1.4.08-2.8.13-4.23.16-.61,0-1.21,0-1.82,0h-2.27a48.07,48.07,0,0,1-6.6-.5A31.48,31.48,0,0,1,275.78,351a20.8,20.8,0,0,1-7-6,19,19,0,0,1-3.41-7.94,18.61,18.61,0,0,1,.46-8.53,16.47,16.47,0,0,1,4.08-6.92,20.27,20.27,0,0,1,7.66-4.76,31.63,31.63,0,0,1,5.38-1.43,45.37,45.37,0,0,1,6.31-.6l5.28-.11h.18l3.31-.23c.85-.06,1.7-.16,2.55-.26l.95-.11a76.87,76.87,0,0,0,14-3.15A65.75,65.75,0,0,0,351.41,283,67.38,67.38,0,0,0,358,269.07,68.91,68.91,0,0,0,361,239.13a67.56,67.56,0,0,0-10.24-28.54,66,66,0,0,0-22-21.15A74.29,74.29,0,0,0,301.6,180a92,92,0,0,0-13.36-1c-4.5,0-8,.13-11.37.36a167.85,167.85,0,0,0-45,8.94,147.55,147.55,0,0,0-41.19,22,139.57,139.57,0,0,0-51,77.56,152.89,152.89,0,0,0-3.93,22.9c-.39,4.39-.61,8-.67,11.48-.09,4.46,0,8.13.16,11.54a151.39,151.39,0,0,0,9.4,45.25,159.53,159.53,0,0,0,21.92,40.09,169,169,0,0,0,70.93,54.75,166.11,166.11,0,0,0,43.7,11.25c4.51.48,8,.75,11.18.88,1.44.08,2.87.11,4.25.14l1.37,0h1.71c1.32,0,2.67,0,3.87,0,6.76-.09,13.92-.49,21.29-1.18a248.58,248.58,0,0,0,42.22-7.6,220.77,220.77,0,0,0,40.43-15.29,208.26,208.26,0,0,0,36.61-23.25,205.59,205.59,0,0,0,54.56-66.34,225.76,225.76,0,0,0,24.06-81.22A248.76,248.76,0,0,0,523.54,249.16Z'/%3e%3c/g%3e%3c/svg%3e", - "external_url": "https://www.orca.so/whirlpools/", - "collection": { - "name": "Orca Whirlpool Position", - "family": "Orca Whirlpool Position" - } -} diff --git a/sdk/.gitignore b/sdk/.gitignore deleted file mode 100644 index d2a0cb3..0000000 --- a/sdk/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.npmrc diff --git a/sdk/.prettierignore b/sdk/.prettierignore deleted file mode 100644 index 046f212..0000000 --- a/sdk/.prettierignore +++ /dev/null @@ -1,2 +0,0 @@ -# Ignore artifacts: -src/artifacts diff --git a/sdk/.prettierrc b/sdk/.prettierrc deleted file mode 100644 index de753c5..0000000 --- a/sdk/.prettierrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "printWidth": 100 -} diff --git a/sdk/README.md b/sdk/README.md deleted file mode 100644 index 3a5c6e6..0000000 --- a/sdk/README.md +++ /dev/null @@ -1,36 +0,0 @@ -# Whirlpools - -Whirpools is an open-source concentrated liquidity AMM contract on the Solana blockchain. -The Whirlpools Typescript SDK (`@orca-so/whirlpools-sdk`) allows for easy interaction with a deployed Whirlpools program. - -The contract has been audited by Kudelski and Neodyme. - -# Whirlpool SDK - -Use the SDK to interact with a deployed Whirlpools program via Typescript. - -## Installation - -In your package, run: - -``` -yarn add `@orca-so/whirlpools-sdk` -yarn add "@coral-xyz/anchor" -yarn add "decimal.js" -``` - -## Usage - -Read instructions on how to use the SDK on the [Orca Developer Portal](https://orca-so.gitbook.io/orca-developer-portal/orca/welcome). - -## Tests - -To run tests for the SDK, setup your anchor environment and run: - -``` -anchor test -``` - -# License - -[Apache 2.0](https://choosealicense.com/licenses/apache-2.0/) diff --git a/sdk/jest.config.js b/sdk/jest.config.js deleted file mode 100644 index bd77c07..0000000 --- a/sdk/jest.config.js +++ /dev/null @@ -1,20 +0,0 @@ -module.exports = { - "roots": [ - "/src", - "/tests/sdk", - "/tests/integration" - ], - "testMatch": [ - "**/__tests__/**/*.+(ts|tsx|js)", - "**/?(*.)+(spec|test).+(ts|tsx|js)" - ], - "transform": { - "^.+\\.(ts|tsx)$": "ts-jest" - }, - globals: { - "ts-jest": { - tsconfig: "./tests/tsconfig.json" - } - }, - testTimeout: 30 * 1000 -} diff --git a/sdk/package.json b/sdk/package.json deleted file mode 100644 index 182daa8..0000000 --- a/sdk/package.json +++ /dev/null @@ -1,76 +0,0 @@ -{ - "name": "@orca-so/whirlpools-sdk", - "version": "0.12.5", - "description": "Typescript SDK to interact with Orca's Whirlpool program.", - "license": "Apache-2.0", - "main": "dist/index.js", - "types": "dist/index.d.ts", - "peerDependencies": { - "@coral-xyz/anchor": "~0.27.0", - "@orca-so/common-sdk": "^0.5.2", - "@solana/spl-token": "^0.3.8", - "@solana/web3.js": "^1.75.0", - "decimal.js": "^10.3.1" - }, - "dependencies": { - "tiny-invariant": "^1.3.1" - }, - "devDependencies": { - "@coral-xyz/anchor": "^0.27.0", - "@metaplex-foundation/mpl-token-metadata": "2.12.0", - "@orca-so/common-sdk": "^0.5.3", - "@solana/spl-token": "^0.3.11", - "@solana/web3.js": "^1.88.0", - "@types/bn.js": "~5.1.5", - "@types/mocha": "^10.0.6", - "@types/node": "^20.10.8", - "@typescript-eslint/eslint-plugin": "^6.18.1", - "@typescript-eslint/parser": "^6.18.1", - "chai": "^5.0.0", - "decimal.js": "^10.4.3", - "eslint": "^8.56.0", - "eslint-config-prettier": "^9.1.0", - "mocha": "^10.2.0", - "prettier": "^3.1.1", - "process": "^0.11.10", - "rimraf": "^5.0.5", - "ts-mocha": "^10.0.0", - "ts-node": "^10.9.2", - "typedoc": "~0.25.7", - "typescript": "^5.3.3" - }, - "scripts": { - "build": "rimraf dist && tsc -p src", - "clean": "rimraf dist", - "watch": "tsc -w -p src", - "prepublishOnly": "yarn build", - "prettier-format": "prettier --config .prettierrc 'src/**/*.ts' --write", - "test": "anchor test", - "docs": "npx typedoc --options typedoc.json" - }, - "lint-staged": { - "*.{ts,md}": "yarn run prettier-format" - }, - "files": [ - ".yalc", - "/dist" - ], - "repository": { - "type": "git", - "url": "git+https://github.com/orca-so/whirlpools.git" - }, - "keywords": [ - "orca_so", - "orca", - "solana", - "typescript", - "sdk", - "crypto", - "dex" - ], - "author": "team@orca.so", - "bugs": { - "url": "https://github.com/orca-so/whirlpools/issues" - }, - "homepage": "https://www.orca.so" -} diff --git a/sdk/src/artifacts/whirlpool.json b/sdk/src/artifacts/whirlpool.json deleted file mode 100644 index be5999c..0000000 --- a/sdk/src/artifacts/whirlpool.json +++ /dev/null @@ -1,2525 +0,0 @@ -{ - "version": "0.2.0", - "name": "whirlpool", - "instructions": [ - { - "name": "initializeConfig", - "docs": [ - "Initializes a WhirlpoolsConfig account that hosts info & authorities", - "required to govern a set of Whirlpools.", - "", - "### Parameters", - "- `fee_authority` - Authority authorized to initialize fee-tiers and set customs fees.", - "- `collect_protocol_fees_authority` - Authority authorized to collect protocol fees.", - "- `reward_emissions_super_authority` - Authority authorized to set reward authorities in pools." - ], - "accounts": [ - { - "name": "config", - "isMut": true, - "isSigner": true - }, - { - "name": "funder", - "isMut": true, - "isSigner": true - }, - { - "name": "systemProgram", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "feeAuthority", - "type": "publicKey" - }, - { - "name": "collectProtocolFeesAuthority", - "type": "publicKey" - }, - { - "name": "rewardEmissionsSuperAuthority", - "type": "publicKey" - }, - { - "name": "defaultProtocolFeeRate", - "type": "u16" - } - ] - }, - { - "name": "initializePool", - "docs": [ - "Initializes a Whirlpool account.", - "Fee rate is set to the default values on the config and supplied fee_tier.", - "", - "### Parameters", - "- `bumps` - The bump value when deriving the PDA of the Whirlpool address.", - "- `tick_spacing` - The desired tick spacing for this pool.", - "- `initial_sqrt_price` - The desired initial sqrt-price for this pool", - "", - "#### Special Errors", - "`InvalidTokenMintOrder` - The order of mints have to be ordered by", - "`SqrtPriceOutOfBounds` - provided initial_sqrt_price is not between 2^-64 to 2^64", - "" - ], - "accounts": [ - { - "name": "whirlpoolsConfig", - "isMut": false, - "isSigner": false - }, - { - "name": "tokenMintA", - "isMut": false, - "isSigner": false - }, - { - "name": "tokenMintB", - "isMut": false, - "isSigner": false - }, - { - "name": "funder", - "isMut": true, - "isSigner": true - }, - { - "name": "whirlpool", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenVaultA", - "isMut": true, - "isSigner": true - }, - { - "name": "tokenVaultB", - "isMut": true, - "isSigner": true - }, - { - "name": "feeTier", - "isMut": false, - "isSigner": false - }, - { - "name": "tokenProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "systemProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "rent", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "bumps", - "type": { - "defined": "WhirlpoolBumps" - } - }, - { - "name": "tickSpacing", - "type": "u16" - }, - { - "name": "initialSqrtPrice", - "type": "u128" - } - ] - }, - { - "name": "initializeTickArray", - "docs": [ - "Initializes a tick_array account to represent a tick-range in a Whirlpool.", - "", - "### Parameters", - "- `start_tick_index` - The starting tick index for this tick-array.", - "Has to be a multiple of TickArray size & the tick spacing of this pool.", - "", - "#### Special Errors", - "- `InvalidStartTick` - if the provided start tick is out of bounds or is not a multiple of", - "TICK_ARRAY_SIZE * tick spacing." - ], - "accounts": [ - { - "name": "whirlpool", - "isMut": false, - "isSigner": false - }, - { - "name": "funder", - "isMut": true, - "isSigner": true - }, - { - "name": "tickArray", - "isMut": true, - "isSigner": false - }, - { - "name": "systemProgram", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "startTickIndex", - "type": "i32" - } - ] - }, - { - "name": "initializeFeeTier", - "docs": [ - "Initializes a fee_tier account usable by Whirlpools in a WhirlpoolConfig space.", - "", - "### Authority", - "- \"fee_authority\" - Set authority in the WhirlpoolConfig", - "", - "### Parameters", - "- `tick_spacing` - The tick-spacing that this fee-tier suggests the default_fee_rate for.", - "- `default_fee_rate` - The default fee rate that a pool will use if the pool uses this", - "fee tier during initialization.", - "", - "#### Special Errors", - "- `FeeRateMaxExceeded` - If the provided default_fee_rate exceeds MAX_FEE_RATE." - ], - "accounts": [ - { - "name": "config", - "isMut": false, - "isSigner": false - }, - { - "name": "feeTier", - "isMut": true, - "isSigner": false - }, - { - "name": "funder", - "isMut": true, - "isSigner": true - }, - { - "name": "feeAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "systemProgram", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "tickSpacing", - "type": "u16" - }, - { - "name": "defaultFeeRate", - "type": "u16" - } - ] - }, - { - "name": "initializeReward", - "docs": [ - "Initialize reward for a Whirlpool. A pool can only support up to a set number of rewards.", - "", - "### Authority", - "- \"reward_authority\" - assigned authority by the reward_super_authority for the specified", - "reward-index in this Whirlpool", - "", - "### Parameters", - "- `reward_index` - The reward index that we'd like to initialize. (0 <= index <= NUM_REWARDS)", - "", - "#### Special Errors", - "- `InvalidRewardIndex` - If the provided reward index doesn't match the lowest uninitialized", - "index in this pool, or exceeds NUM_REWARDS, or", - "all reward slots for this pool has been initialized." - ], - "accounts": [ - { - "name": "rewardAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "funder", - "isMut": true, - "isSigner": true - }, - { - "name": "whirlpool", - "isMut": true, - "isSigner": false - }, - { - "name": "rewardMint", - "isMut": false, - "isSigner": false - }, - { - "name": "rewardVault", - "isMut": true, - "isSigner": true - }, - { - "name": "tokenProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "systemProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "rent", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "rewardIndex", - "type": "u8" - } - ] - }, - { - "name": "setRewardEmissions", - "docs": [ - "Set the reward emissions for a reward in a Whirlpool.", - "", - "### Authority", - "- \"reward_authority\" - assigned authority by the reward_super_authority for the specified", - "reward-index in this Whirlpool", - "", - "### Parameters", - "- `reward_index` - The reward index (0 <= index <= NUM_REWARDS) that we'd like to modify.", - "- `emissions_per_second_x64` - The amount of rewards emitted in this pool.", - "", - "#### Special Errors", - "- `RewardVaultAmountInsufficient` - The amount of rewards in the reward vault cannot emit", - "more than a day of desired emissions.", - "- `InvalidTimestamp` - Provided timestamp is not in order with the previous timestamp.", - "- `InvalidRewardIndex` - If the provided reward index doesn't match the lowest uninitialized", - "index in this pool, or exceeds NUM_REWARDS, or", - "all reward slots for this pool has been initialized." - ], - "accounts": [ - { - "name": "whirlpool", - "isMut": true, - "isSigner": false - }, - { - "name": "rewardAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "rewardVault", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "rewardIndex", - "type": "u8" - }, - { - "name": "emissionsPerSecondX64", - "type": "u128" - } - ] - }, - { - "name": "openPosition", - "docs": [ - "Open a position in a Whirlpool. A unique token will be minted to represent the position", - "in the users wallet. The position will start off with 0 liquidity.", - "", - "### Parameters", - "- `tick_lower_index` - The tick specifying the lower end of the position range.", - "- `tick_upper_index` - The tick specifying the upper end of the position range.", - "", - "#### Special Errors", - "- `InvalidTickIndex` - If a provided tick is out of bounds, out of order or not a multiple of", - "the tick-spacing in this pool." - ], - "accounts": [ - { - "name": "funder", - "isMut": true, - "isSigner": true - }, - { - "name": "owner", - "isMut": false, - "isSigner": false - }, - { - "name": "position", - "isMut": true, - "isSigner": false - }, - { - "name": "positionMint", - "isMut": true, - "isSigner": true - }, - { - "name": "positionTokenAccount", - "isMut": true, - "isSigner": false - }, - { - "name": "whirlpool", - "isMut": false, - "isSigner": false - }, - { - "name": "tokenProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "systemProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "rent", - "isMut": false, - "isSigner": false - }, - { - "name": "associatedTokenProgram", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "bumps", - "type": { - "defined": "OpenPositionBumps" - } - }, - { - "name": "tickLowerIndex", - "type": "i32" - }, - { - "name": "tickUpperIndex", - "type": "i32" - } - ] - }, - { - "name": "openPositionWithMetadata", - "docs": [ - "Open a position in a Whirlpool. A unique token will be minted to represent the position", - "in the users wallet. Additional Metaplex metadata is appended to identify the token.", - "The position will start off with 0 liquidity.", - "", - "### Parameters", - "- `tick_lower_index` - The tick specifying the lower end of the position range.", - "- `tick_upper_index` - The tick specifying the upper end of the position range.", - "", - "#### Special Errors", - "- `InvalidTickIndex` - If a provided tick is out of bounds, out of order or not a multiple of", - "the tick-spacing in this pool." - ], - "accounts": [ - { - "name": "funder", - "isMut": true, - "isSigner": true - }, - { - "name": "owner", - "isMut": false, - "isSigner": false - }, - { - "name": "position", - "isMut": true, - "isSigner": false - }, - { - "name": "positionMint", - "isMut": true, - "isSigner": true - }, - { - "name": "positionMetadataAccount", - "isMut": true, - "isSigner": false, - "docs": [ - "https://github.com/metaplex-foundation/metaplex-program-library/blob/master/token-metadata/program/src/utils.rs#L873" - ] - }, - { - "name": "positionTokenAccount", - "isMut": true, - "isSigner": false - }, - { - "name": "whirlpool", - "isMut": false, - "isSigner": false - }, - { - "name": "tokenProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "systemProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "rent", - "isMut": false, - "isSigner": false - }, - { - "name": "associatedTokenProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "metadataProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "metadataUpdateAuth", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "bumps", - "type": { - "defined": "OpenPositionWithMetadataBumps" - } - }, - { - "name": "tickLowerIndex", - "type": "i32" - }, - { - "name": "tickUpperIndex", - "type": "i32" - } - ] - }, - { - "name": "increaseLiquidity", - "docs": [ - "Add liquidity to a position in the Whirlpool. This call also updates the position's accrued fees and rewards.", - "", - "### Authority", - "- `position_authority` - authority that owns the token corresponding to this desired position.", - "", - "### Parameters", - "- `liquidity_amount` - The total amount of Liquidity the user is willing to deposit.", - "- `token_max_a` - The maximum amount of tokenA the user is willing to deposit.", - "- `token_max_b` - The maximum amount of tokenB the user is willing to deposit.", - "", - "#### Special Errors", - "- `LiquidityZero` - Provided liquidity amount is zero.", - "- `LiquidityTooHigh` - Provided liquidity exceeds u128::max.", - "- `TokenMaxExceeded` - The required token to perform this operation exceeds the user defined amount." - ], - "accounts": [ - { - "name": "whirlpool", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "positionAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "position", - "isMut": true, - "isSigner": false - }, - { - "name": "positionTokenAccount", - "isMut": false, - "isSigner": false - }, - { - "name": "tokenOwnerAccountA", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenOwnerAccountB", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenVaultA", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenVaultB", - "isMut": true, - "isSigner": false - }, - { - "name": "tickArrayLower", - "isMut": true, - "isSigner": false - }, - { - "name": "tickArrayUpper", - "isMut": true, - "isSigner": false - } - ], - "args": [ - { - "name": "liquidityAmount", - "type": "u128" - }, - { - "name": "tokenMaxA", - "type": "u64" - }, - { - "name": "tokenMaxB", - "type": "u64" - } - ] - }, - { - "name": "decreaseLiquidity", - "docs": [ - "Withdraw liquidity from a position in the Whirlpool. This call also updates the position's accrued fees and rewards.", - "", - "### Authority", - "- `position_authority` - authority that owns the token corresponding to this desired position.", - "", - "### Parameters", - "- `liquidity_amount` - The total amount of Liquidity the user desires to withdraw.", - "- `token_min_a` - The minimum amount of tokenA the user is willing to withdraw.", - "- `token_min_b` - The minimum amount of tokenB the user is willing to withdraw.", - "", - "#### Special Errors", - "- `LiquidityZero` - Provided liquidity amount is zero.", - "- `LiquidityTooHigh` - Provided liquidity exceeds u128::max.", - "- `TokenMinSubceeded` - The required token to perform this operation subceeds the user defined amount." - ], - "accounts": [ - { - "name": "whirlpool", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "positionAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "position", - "isMut": true, - "isSigner": false - }, - { - "name": "positionTokenAccount", - "isMut": false, - "isSigner": false - }, - { - "name": "tokenOwnerAccountA", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenOwnerAccountB", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenVaultA", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenVaultB", - "isMut": true, - "isSigner": false - }, - { - "name": "tickArrayLower", - "isMut": true, - "isSigner": false - }, - { - "name": "tickArrayUpper", - "isMut": true, - "isSigner": false - } - ], - "args": [ - { - "name": "liquidityAmount", - "type": "u128" - }, - { - "name": "tokenMinA", - "type": "u64" - }, - { - "name": "tokenMinB", - "type": "u64" - } - ] - }, - { - "name": "updateFeesAndRewards", - "docs": [ - "Update the accrued fees and rewards for a position.", - "", - "#### Special Errors", - "- `TickNotFound` - Provided tick array account does not contain the tick for this position.", - "- `LiquidityZero` - Position has zero liquidity and therefore already has the most updated fees and reward values." - ], - "accounts": [ - { - "name": "whirlpool", - "isMut": true, - "isSigner": false - }, - { - "name": "position", - "isMut": true, - "isSigner": false - }, - { - "name": "tickArrayLower", - "isMut": false, - "isSigner": false - }, - { - "name": "tickArrayUpper", - "isMut": false, - "isSigner": false - } - ], - "args": [] - }, - { - "name": "collectFees", - "docs": [ - "Collect fees accrued for this position.", - "", - "### Authority", - "- `position_authority` - authority that owns the token corresponding to this desired position." - ], - "accounts": [ - { - "name": "whirlpool", - "isMut": false, - "isSigner": false - }, - { - "name": "positionAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "position", - "isMut": true, - "isSigner": false - }, - { - "name": "positionTokenAccount", - "isMut": false, - "isSigner": false - }, - { - "name": "tokenOwnerAccountA", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenVaultA", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenOwnerAccountB", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenVaultB", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenProgram", - "isMut": false, - "isSigner": false - } - ], - "args": [] - }, - { - "name": "collectReward", - "docs": [ - "Collect rewards accrued for this position.", - "", - "### Authority", - "- `position_authority` - authority that owns the token corresponding to this desired position." - ], - "accounts": [ - { - "name": "whirlpool", - "isMut": false, - "isSigner": false - }, - { - "name": "positionAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "position", - "isMut": true, - "isSigner": false - }, - { - "name": "positionTokenAccount", - "isMut": false, - "isSigner": false - }, - { - "name": "rewardOwnerAccount", - "isMut": true, - "isSigner": false - }, - { - "name": "rewardVault", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenProgram", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "rewardIndex", - "type": "u8" - } - ] - }, - { - "name": "collectProtocolFees", - "docs": [ - "Collect the protocol fees accrued in this Whirlpool", - "", - "### Authority", - "- `collect_protocol_fees_authority` - assigned authority in the WhirlpoolConfig that can collect protocol fees" - ], - "accounts": [ - { - "name": "whirlpoolsConfig", - "isMut": false, - "isSigner": false - }, - { - "name": "whirlpool", - "isMut": true, - "isSigner": false - }, - { - "name": "collectProtocolFeesAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "tokenVaultA", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenVaultB", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenDestinationA", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenDestinationB", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenProgram", - "isMut": false, - "isSigner": false - } - ], - "args": [] - }, - { - "name": "swap", - "docs": [ - "Perform a swap in this Whirlpool", - "", - "### Authority", - "- \"token_authority\" - The authority to withdraw tokens from the input token account.", - "", - "### Parameters", - "- `amount` - The amount of input or output token to swap from (depending on amount_specified_is_input).", - "- `other_amount_threshold` - The maximum/minimum of input/output token to swap into (depending on amount_specified_is_input).", - "- `sqrt_price_limit` - The maximum/minimum price the swap will swap to.", - "- `amount_specified_is_input` - Specifies the token the parameter `amount`represents. If true, the amount represents the input token of the swap.", - "- `a_to_b` - The direction of the swap. True if swapping from A to B. False if swapping from B to A.", - "", - "#### Special Errors", - "- `ZeroTradableAmount` - User provided parameter `amount` is 0.", - "- `InvalidSqrtPriceLimitDirection` - User provided parameter `sqrt_price_limit` does not match the direction of the trade.", - "- `SqrtPriceOutOfBounds` - User provided parameter `sqrt_price_limit` is over Whirlppool's max/min bounds for sqrt-price.", - "- `InvalidTickArraySequence` - User provided tick-arrays are not in sequential order required to proceed in this trade direction.", - "- `TickArraySequenceInvalidIndex` - The swap loop attempted to access an invalid array index during the query of the next initialized tick.", - "- `TickArrayIndexOutofBounds` - The swap loop attempted to access an invalid array index during tick crossing.", - "- `LiquidityOverflow` - Liquidity value overflowed 128bits during tick crossing.", - "- `InvalidTickSpacing` - The swap pool was initialized with tick-spacing of 0." - ], - "accounts": [ - { - "name": "tokenProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "tokenAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "whirlpool", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenOwnerAccountA", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenVaultA", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenOwnerAccountB", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenVaultB", - "isMut": true, - "isSigner": false - }, - { - "name": "tickArray0", - "isMut": true, - "isSigner": false - }, - { - "name": "tickArray1", - "isMut": true, - "isSigner": false - }, - { - "name": "tickArray2", - "isMut": true, - "isSigner": false - }, - { - "name": "oracle", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "amount", - "type": "u64" - }, - { - "name": "otherAmountThreshold", - "type": "u64" - }, - { - "name": "sqrtPriceLimit", - "type": "u128" - }, - { - "name": "amountSpecifiedIsInput", - "type": "bool" - }, - { - "name": "aToB", - "type": "bool" - } - ] - }, - { - "name": "closePosition", - "docs": [ - "Close a position in a Whirlpool. Burns the position token in the owner's wallet.", - "", - "### Authority", - "- \"position_authority\" - The authority that owns the position token.", - "", - "#### Special Errors", - "- `ClosePositionNotEmpty` - The provided position account is not empty." - ], - "accounts": [ - { - "name": "positionAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "receiver", - "isMut": true, - "isSigner": false - }, - { - "name": "position", - "isMut": true, - "isSigner": false - }, - { - "name": "positionMint", - "isMut": true, - "isSigner": false - }, - { - "name": "positionTokenAccount", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenProgram", - "isMut": false, - "isSigner": false - } - ], - "args": [] - }, - { - "name": "setDefaultFeeRate", - "docs": [ - "Set the default_fee_rate for a FeeTier", - "Only the current fee authority has permission to invoke this instruction.", - "", - "### Authority", - "- \"fee_authority\" - Set authority in the WhirlpoolConfig", - "", - "### Parameters", - "- `default_fee_rate` - The default fee rate that a pool will use if the pool uses this", - "fee tier during initialization.", - "", - "#### Special Errors", - "- `FeeRateMaxExceeded` - If the provided default_fee_rate exceeds MAX_FEE_RATE." - ], - "accounts": [ - { - "name": "whirlpoolsConfig", - "isMut": false, - "isSigner": false - }, - { - "name": "feeTier", - "isMut": true, - "isSigner": false - }, - { - "name": "feeAuthority", - "isMut": false, - "isSigner": true - } - ], - "args": [ - { - "name": "defaultFeeRate", - "type": "u16" - } - ] - }, - { - "name": "setDefaultProtocolFeeRate", - "docs": [ - "Sets the default protocol fee rate for a WhirlpoolConfig", - "Protocol fee rate is represented as a basis point.", - "Only the current fee authority has permission to invoke this instruction.", - "", - "### Authority", - "- \"fee_authority\" - Set authority that can modify pool fees in the WhirlpoolConfig", - "", - "### Parameters", - "- `default_protocol_fee_rate` - Rate that is referenced during the initialization of a Whirlpool using this config.", - "", - "#### Special Errors", - "- `ProtocolFeeRateMaxExceeded` - If the provided default_protocol_fee_rate exceeds MAX_PROTOCOL_FEE_RATE." - ], - "accounts": [ - { - "name": "whirlpoolsConfig", - "isMut": true, - "isSigner": false - }, - { - "name": "feeAuthority", - "isMut": false, - "isSigner": true - } - ], - "args": [ - { - "name": "defaultProtocolFeeRate", - "type": "u16" - } - ] - }, - { - "name": "setFeeRate", - "docs": [ - "Sets the fee rate for a Whirlpool.", - "Fee rate is represented as hundredths of a basis point.", - "Only the current fee authority has permission to invoke this instruction.", - "", - "### Authority", - "- \"fee_authority\" - Set authority that can modify pool fees in the WhirlpoolConfig", - "", - "### Parameters", - "- `fee_rate` - The rate that the pool will use to calculate fees going onwards.", - "", - "#### Special Errors", - "- `FeeRateMaxExceeded` - If the provided fee_rate exceeds MAX_FEE_RATE." - ], - "accounts": [ - { - "name": "whirlpoolsConfig", - "isMut": false, - "isSigner": false - }, - { - "name": "whirlpool", - "isMut": true, - "isSigner": false - }, - { - "name": "feeAuthority", - "isMut": false, - "isSigner": true - } - ], - "args": [ - { - "name": "feeRate", - "type": "u16" - } - ] - }, - { - "name": "setProtocolFeeRate", - "docs": [ - "Sets the protocol fee rate for a Whirlpool.", - "Protocol fee rate is represented as a basis point.", - "Only the current fee authority has permission to invoke this instruction.", - "", - "### Authority", - "- \"fee_authority\" - Set authority that can modify pool fees in the WhirlpoolConfig", - "", - "### Parameters", - "- `protocol_fee_rate` - The rate that the pool will use to calculate protocol fees going onwards.", - "", - "#### Special Errors", - "- `ProtocolFeeRateMaxExceeded` - If the provided default_protocol_fee_rate exceeds MAX_PROTOCOL_FEE_RATE." - ], - "accounts": [ - { - "name": "whirlpoolsConfig", - "isMut": false, - "isSigner": false - }, - { - "name": "whirlpool", - "isMut": true, - "isSigner": false - }, - { - "name": "feeAuthority", - "isMut": false, - "isSigner": true - } - ], - "args": [ - { - "name": "protocolFeeRate", - "type": "u16" - } - ] - }, - { - "name": "setFeeAuthority", - "docs": [ - "Sets the fee authority for a WhirlpoolConfig.", - "The fee authority can set the fee & protocol fee rate for individual pools or", - "set the default fee rate for newly minted pools.", - "Only the current fee authority has permission to invoke this instruction.", - "", - "### Authority", - "- \"fee_authority\" - Set authority that can modify pool fees in the WhirlpoolConfig" - ], - "accounts": [ - { - "name": "whirlpoolsConfig", - "isMut": true, - "isSigner": false - }, - { - "name": "feeAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "newFeeAuthority", - "isMut": false, - "isSigner": false - } - ], - "args": [] - }, - { - "name": "setCollectProtocolFeesAuthority", - "docs": [ - "Sets the fee authority to collect protocol fees for a WhirlpoolConfig.", - "Only the current collect protocol fee authority has permission to invoke this instruction.", - "", - "### Authority", - "- \"fee_authority\" - Set authority that can collect protocol fees in the WhirlpoolConfig" - ], - "accounts": [ - { - "name": "whirlpoolsConfig", - "isMut": true, - "isSigner": false - }, - { - "name": "collectProtocolFeesAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "newCollectProtocolFeesAuthority", - "isMut": false, - "isSigner": false - } - ], - "args": [] - }, - { - "name": "setRewardAuthority", - "docs": [ - "Set the whirlpool reward authority at the provided `reward_index`.", - "Only the current reward authority for this reward index has permission to invoke this instruction.", - "", - "### Authority", - "- \"reward_authority\" - Set authority that can control reward emission for this particular reward.", - "", - "#### Special Errors", - "- `InvalidRewardIndex` - If the provided reward index doesn't match the lowest uninitialized", - "index in this pool, or exceeds NUM_REWARDS, or", - "all reward slots for this pool has been initialized." - ], - "accounts": [ - { - "name": "whirlpool", - "isMut": true, - "isSigner": false - }, - { - "name": "rewardAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "newRewardAuthority", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "rewardIndex", - "type": "u8" - } - ] - }, - { - "name": "setRewardAuthorityBySuperAuthority", - "docs": [ - "Set the whirlpool reward authority at the provided `reward_index`.", - "Only the current reward super authority has permission to invoke this instruction.", - "", - "### Authority", - "- \"reward_authority\" - Set authority that can control reward emission for this particular reward.", - "", - "#### Special Errors", - "- `InvalidRewardIndex` - If the provided reward index doesn't match the lowest uninitialized", - "index in this pool, or exceeds NUM_REWARDS, or", - "all reward slots for this pool has been initialized." - ], - "accounts": [ - { - "name": "whirlpoolsConfig", - "isMut": false, - "isSigner": false - }, - { - "name": "whirlpool", - "isMut": true, - "isSigner": false - }, - { - "name": "rewardEmissionsSuperAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "newRewardAuthority", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "rewardIndex", - "type": "u8" - } - ] - }, - { - "name": "setRewardEmissionsSuperAuthority", - "docs": [ - "Set the whirlpool reward super authority for a WhirlpoolConfig", - "Only the current reward super authority has permission to invoke this instruction.", - "This instruction will not change the authority on any `WhirlpoolRewardInfo` whirlpool rewards.", - "", - "### Authority", - "- \"reward_emissions_super_authority\" - Set authority that can control reward authorities for all pools in this config space." - ], - "accounts": [ - { - "name": "whirlpoolsConfig", - "isMut": true, - "isSigner": false - }, - { - "name": "rewardEmissionsSuperAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "newRewardEmissionsSuperAuthority", - "isMut": false, - "isSigner": false - } - ], - "args": [] - }, - { - "name": "twoHopSwap", - "docs": [ - "Perform a two-hop swap in this Whirlpool", - "", - "### Authority", - "- \"token_authority\" - The authority to withdraw tokens from the input token account.", - "", - "### Parameters", - "- `amount` - The amount of input or output token to swap from (depending on amount_specified_is_input).", - "- `other_amount_threshold` - The maximum/minimum of input/output token to swap into (depending on amount_specified_is_input).", - "- `amount_specified_is_input` - Specifies the token the parameter `amount`represents. If true, the amount represents the input token of the swap.", - "- `a_to_b_one` - The direction of the swap of hop one. True if swapping from A to B. False if swapping from B to A.", - "- `a_to_b_two` - The direction of the swap of hop two. True if swapping from A to B. False if swapping from B to A.", - "- `sqrt_price_limit_one` - The maximum/minimum price the swap will swap to in the first hop.", - "- `sqrt_price_limit_two` - The maximum/minimum price the swap will swap to in the second hop.", - "", - "#### Special Errors", - "- `ZeroTradableAmount` - User provided parameter `amount` is 0.", - "- `InvalidSqrtPriceLimitDirection` - User provided parameter `sqrt_price_limit` does not match the direction of the trade.", - "- `SqrtPriceOutOfBounds` - User provided parameter `sqrt_price_limit` is over Whirlppool's max/min bounds for sqrt-price.", - "- `InvalidTickArraySequence` - User provided tick-arrays are not in sequential order required to proceed in this trade direction.", - "- `TickArraySequenceInvalidIndex` - The swap loop attempted to access an invalid array index during the query of the next initialized tick.", - "- `TickArrayIndexOutofBounds` - The swap loop attempted to access an invalid array index during tick crossing.", - "- `LiquidityOverflow` - Liquidity value overflowed 128bits during tick crossing.", - "- `InvalidTickSpacing` - The swap pool was initialized with tick-spacing of 0.", - "- `InvalidIntermediaryMint` - Error if the intermediary mint between hop one and two do not equal.", - "- `DuplicateTwoHopPool` - Error if whirlpool one & two are the same pool." - ], - "accounts": [ - { - "name": "tokenProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "tokenAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "whirlpoolOne", - "isMut": true, - "isSigner": false - }, - { - "name": "whirlpoolTwo", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenOwnerAccountOneA", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenVaultOneA", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenOwnerAccountOneB", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenVaultOneB", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenOwnerAccountTwoA", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenVaultTwoA", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenOwnerAccountTwoB", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenVaultTwoB", - "isMut": true, - "isSigner": false - }, - { - "name": "tickArrayOne0", - "isMut": true, - "isSigner": false - }, - { - "name": "tickArrayOne1", - "isMut": true, - "isSigner": false - }, - { - "name": "tickArrayOne2", - "isMut": true, - "isSigner": false - }, - { - "name": "tickArrayTwo0", - "isMut": true, - "isSigner": false - }, - { - "name": "tickArrayTwo1", - "isMut": true, - "isSigner": false - }, - { - "name": "tickArrayTwo2", - "isMut": true, - "isSigner": false - }, - { - "name": "oracleOne", - "isMut": false, - "isSigner": false - }, - { - "name": "oracleTwo", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "amount", - "type": "u64" - }, - { - "name": "otherAmountThreshold", - "type": "u64" - }, - { - "name": "amountSpecifiedIsInput", - "type": "bool" - }, - { - "name": "aToBOne", - "type": "bool" - }, - { - "name": "aToBTwo", - "type": "bool" - }, - { - "name": "sqrtPriceLimitOne", - "type": "u128" - }, - { - "name": "sqrtPriceLimitTwo", - "type": "u128" - } - ] - }, - { - "name": "initializePositionBundle", - "docs": [ - "Initializes a PositionBundle account that bundles several positions.", - "A unique token will be minted to represent the position bundle in the users wallet." - ], - "accounts": [ - { - "name": "positionBundle", - "isMut": true, - "isSigner": false - }, - { - "name": "positionBundleMint", - "isMut": true, - "isSigner": true - }, - { - "name": "positionBundleTokenAccount", - "isMut": true, - "isSigner": false - }, - { - "name": "positionBundleOwner", - "isMut": false, - "isSigner": false - }, - { - "name": "funder", - "isMut": true, - "isSigner": true - }, - { - "name": "tokenProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "systemProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "rent", - "isMut": false, - "isSigner": false - }, - { - "name": "associatedTokenProgram", - "isMut": false, - "isSigner": false - } - ], - "args": [] - }, - { - "name": "initializePositionBundleWithMetadata", - "docs": [ - "Initializes a PositionBundle account that bundles several positions.", - "A unique token will be minted to represent the position bundle in the users wallet.", - "Additional Metaplex metadata is appended to identify the token." - ], - "accounts": [ - { - "name": "positionBundle", - "isMut": true, - "isSigner": false - }, - { - "name": "positionBundleMint", - "isMut": true, - "isSigner": true - }, - { - "name": "positionBundleMetadata", - "isMut": true, - "isSigner": false, - "docs": [ - "https://github.com/metaplex-foundation/metaplex-program-library/blob/773a574c4b34e5b9f248a81306ec24db064e255f/token-metadata/program/src/utils/metadata.rs#L100" - ] - }, - { - "name": "positionBundleTokenAccount", - "isMut": true, - "isSigner": false - }, - { - "name": "positionBundleOwner", - "isMut": false, - "isSigner": false - }, - { - "name": "funder", - "isMut": true, - "isSigner": true - }, - { - "name": "metadataUpdateAuth", - "isMut": false, - "isSigner": false - }, - { - "name": "tokenProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "systemProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "rent", - "isMut": false, - "isSigner": false - }, - { - "name": "associatedTokenProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "metadataProgram", - "isMut": false, - "isSigner": false - } - ], - "args": [] - }, - { - "name": "deletePositionBundle", - "docs": [ - "Delete a PositionBundle account. Burns the position bundle token in the owner's wallet.", - "", - "### Authority", - "- `position_bundle_owner` - The owner that owns the position bundle token.", - "", - "### Special Errors", - "- `PositionBundleNotDeletable` - The provided position bundle has open positions." - ], - "accounts": [ - { - "name": "positionBundle", - "isMut": true, - "isSigner": false - }, - { - "name": "positionBundleMint", - "isMut": true, - "isSigner": false - }, - { - "name": "positionBundleTokenAccount", - "isMut": true, - "isSigner": false - }, - { - "name": "positionBundleOwner", - "isMut": false, - "isSigner": true - }, - { - "name": "receiver", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenProgram", - "isMut": false, - "isSigner": false - } - ], - "args": [] - }, - { - "name": "openBundledPosition", - "docs": [ - "Open a bundled position in a Whirlpool. No new tokens are issued", - "because the owner of the position bundle becomes the owner of the position.", - "The position will start off with 0 liquidity.", - "", - "### Authority", - "- `position_bundle_authority` - authority that owns the token corresponding to this desired position bundle.", - "", - "### Parameters", - "- `bundle_index` - The bundle index that we'd like to open.", - "- `tick_lower_index` - The tick specifying the lower end of the position range.", - "- `tick_upper_index` - The tick specifying the upper end of the position range.", - "", - "#### Special Errors", - "- `InvalidBundleIndex` - If the provided bundle index is out of bounds.", - "- `InvalidTickIndex` - If a provided tick is out of bounds, out of order or not a multiple of", - "the tick-spacing in this pool." - ], - "accounts": [ - { - "name": "bundledPosition", - "isMut": true, - "isSigner": false - }, - { - "name": "positionBundle", - "isMut": true, - "isSigner": false - }, - { - "name": "positionBundleTokenAccount", - "isMut": false, - "isSigner": false - }, - { - "name": "positionBundleAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "whirlpool", - "isMut": false, - "isSigner": false - }, - { - "name": "funder", - "isMut": true, - "isSigner": true - }, - { - "name": "systemProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "rent", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "bundleIndex", - "type": "u16" - }, - { - "name": "tickLowerIndex", - "type": "i32" - }, - { - "name": "tickUpperIndex", - "type": "i32" - } - ] - }, - { - "name": "closeBundledPosition", - "docs": [ - "Close a bundled position in a Whirlpool.", - "", - "### Authority", - "- `position_bundle_authority` - authority that owns the token corresponding to this desired position bundle.", - "", - "### Parameters", - "- `bundle_index` - The bundle index that we'd like to close.", - "", - "#### Special Errors", - "- `InvalidBundleIndex` - If the provided bundle index is out of bounds.", - "- `ClosePositionNotEmpty` - The provided position account is not empty." - ], - "accounts": [ - { - "name": "bundledPosition", - "isMut": true, - "isSigner": false - }, - { - "name": "positionBundle", - "isMut": true, - "isSigner": false - }, - { - "name": "positionBundleTokenAccount", - "isMut": false, - "isSigner": false - }, - { - "name": "positionBundleAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "receiver", - "isMut": true, - "isSigner": false - } - ], - "args": [ - { - "name": "bundleIndex", - "type": "u16" - } - ] - } - ], - "accounts": [ - { - "name": "WhirlpoolsConfig", - "type": { - "kind": "struct", - "fields": [ - { - "name": "feeAuthority", - "type": "publicKey" - }, - { - "name": "collectProtocolFeesAuthority", - "type": "publicKey" - }, - { - "name": "rewardEmissionsSuperAuthority", - "type": "publicKey" - }, - { - "name": "defaultProtocolFeeRate", - "type": "u16" - } - ] - } - }, - { - "name": "FeeTier", - "type": { - "kind": "struct", - "fields": [ - { - "name": "whirlpoolsConfig", - "type": "publicKey" - }, - { - "name": "tickSpacing", - "type": "u16" - }, - { - "name": "defaultFeeRate", - "type": "u16" - } - ] - } - }, - { - "name": "PositionBundle", - "type": { - "kind": "struct", - "fields": [ - { - "name": "positionBundleMint", - "type": "publicKey" - }, - { - "name": "positionBitmap", - "type": { - "array": [ - "u8", - 32 - ] - } - } - ] - } - }, - { - "name": "Position", - "type": { - "kind": "struct", - "fields": [ - { - "name": "whirlpool", - "type": "publicKey" - }, - { - "name": "positionMint", - "type": "publicKey" - }, - { - "name": "liquidity", - "type": "u128" - }, - { - "name": "tickLowerIndex", - "type": "i32" - }, - { - "name": "tickUpperIndex", - "type": "i32" - }, - { - "name": "feeGrowthCheckpointA", - "type": "u128" - }, - { - "name": "feeOwedA", - "type": "u64" - }, - { - "name": "feeGrowthCheckpointB", - "type": "u128" - }, - { - "name": "feeOwedB", - "type": "u64" - }, - { - "name": "rewardInfos", - "type": { - "array": [ - { - "defined": "PositionRewardInfo" - }, - 3 - ] - } - } - ] - } - }, - { - "name": "TickArray", - "type": { - "kind": "struct", - "fields": [ - { - "name": "startTickIndex", - "type": "i32" - }, - { - "name": "ticks", - "type": { - "array": [ - { - "defined": "Tick" - }, - 88 - ] - } - }, - { - "name": "whirlpool", - "type": "publicKey" - } - ] - } - }, - { - "name": "Whirlpool", - "type": { - "kind": "struct", - "fields": [ - { - "name": "whirlpoolsConfig", - "type": "publicKey" - }, - { - "name": "whirlpoolBump", - "type": { - "array": [ - "u8", - 1 - ] - } - }, - { - "name": "tickSpacing", - "type": "u16" - }, - { - "name": "tickSpacingSeed", - "type": { - "array": [ - "u8", - 2 - ] - } - }, - { - "name": "feeRate", - "type": "u16" - }, - { - "name": "protocolFeeRate", - "type": "u16" - }, - { - "name": "liquidity", - "type": "u128" - }, - { - "name": "sqrtPrice", - "type": "u128" - }, - { - "name": "tickCurrentIndex", - "type": "i32" - }, - { - "name": "protocolFeeOwedA", - "type": "u64" - }, - { - "name": "protocolFeeOwedB", - "type": "u64" - }, - { - "name": "tokenMintA", - "type": "publicKey" - }, - { - "name": "tokenVaultA", - "type": "publicKey" - }, - { - "name": "feeGrowthGlobalA", - "type": "u128" - }, - { - "name": "tokenMintB", - "type": "publicKey" - }, - { - "name": "tokenVaultB", - "type": "publicKey" - }, - { - "name": "feeGrowthGlobalB", - "type": "u128" - }, - { - "name": "rewardLastUpdatedTimestamp", - "type": "u64" - }, - { - "name": "rewardInfos", - "type": { - "array": [ - { - "defined": "WhirlpoolRewardInfo" - }, - 3 - ] - } - } - ] - } - } - ], - "types": [ - { - "name": "OpenPositionBumps", - "type": { - "kind": "struct", - "fields": [ - { - "name": "positionBump", - "type": "u8" - } - ] - } - }, - { - "name": "OpenPositionWithMetadataBumps", - "type": { - "kind": "struct", - "fields": [ - { - "name": "positionBump", - "type": "u8" - }, - { - "name": "metadataBump", - "type": "u8" - } - ] - } - }, - { - "name": "PositionRewardInfo", - "type": { - "kind": "struct", - "fields": [ - { - "name": "growthInsideCheckpoint", - "type": "u128" - }, - { - "name": "amountOwed", - "type": "u64" - } - ] - } - }, - { - "name": "Tick", - "type": { - "kind": "struct", - "fields": [ - { - "name": "initialized", - "type": "bool" - }, - { - "name": "liquidityNet", - "type": "i128" - }, - { - "name": "liquidityGross", - "type": "u128" - }, - { - "name": "feeGrowthOutsideA", - "type": "u128" - }, - { - "name": "feeGrowthOutsideB", - "type": "u128" - }, - { - "name": "rewardGrowthsOutside", - "type": { - "array": [ - "u128", - 3 - ] - } - } - ] - } - }, - { - "name": "WhirlpoolRewardInfo", - "docs": [ - "Stores the state relevant for tracking liquidity mining rewards at the `Whirlpool` level.", - "These values are used in conjunction with `PositionRewardInfo`, `Tick.reward_growths_outside`,", - "and `Whirlpool.reward_last_updated_timestamp` to determine how many rewards are earned by open", - "positions." - ], - "type": { - "kind": "struct", - "fields": [ - { - "name": "mint", - "docs": [ - "Reward token mint." - ], - "type": "publicKey" - }, - { - "name": "vault", - "docs": [ - "Reward vault token account." - ], - "type": "publicKey" - }, - { - "name": "authority", - "docs": [ - "Authority account that has permission to initialize the reward and set emissions." - ], - "type": "publicKey" - }, - { - "name": "emissionsPerSecondX64", - "docs": [ - "Q64.64 number that indicates how many tokens per second are earned per unit of liquidity." - ], - "type": "u128" - }, - { - "name": "growthGlobalX64", - "docs": [ - "Q64.64 number that tracks the total tokens earned per unit of liquidity since the reward", - "emissions were turned on." - ], - "type": "u128" - } - ] - } - }, - { - "name": "WhirlpoolBumps", - "type": { - "kind": "struct", - "fields": [ - { - "name": "whirlpoolBump", - "type": "u8" - } - ] - } - }, - { - "name": "CurrIndex", - "type": { - "kind": "enum", - "variants": [ - { - "name": "Below" - }, - { - "name": "Inside" - }, - { - "name": "Above" - } - ] - } - }, - { - "name": "TickLabel", - "type": { - "kind": "enum", - "variants": [ - { - "name": "Upper" - }, - { - "name": "Lower" - } - ] - } - }, - { - "name": "Direction", - "type": { - "kind": "enum", - "variants": [ - { - "name": "Left" - }, - { - "name": "Right" - } - ] - } - } - ], - "errors": [ - { - "code": 6000, - "name": "InvalidEnum", - "msg": "Enum value could not be converted" - }, - { - "code": 6001, - "name": "InvalidStartTick", - "msg": "Invalid start tick index provided." - }, - { - "code": 6002, - "name": "TickArrayExistInPool", - "msg": "Tick-array already exists in this whirlpool" - }, - { - "code": 6003, - "name": "TickArrayIndexOutofBounds", - "msg": "Attempt to search for a tick-array failed" - }, - { - "code": 6004, - "name": "InvalidTickSpacing", - "msg": "Tick-spacing is not supported" - }, - { - "code": 6005, - "name": "ClosePositionNotEmpty", - "msg": "Position is not empty It cannot be closed" - }, - { - "code": 6006, - "name": "DivideByZero", - "msg": "Unable to divide by zero" - }, - { - "code": 6007, - "name": "NumberCastError", - "msg": "Unable to cast number into BigInt" - }, - { - "code": 6008, - "name": "NumberDownCastError", - "msg": "Unable to down cast number" - }, - { - "code": 6009, - "name": "TickNotFound", - "msg": "Tick not found within tick array" - }, - { - "code": 6010, - "name": "InvalidTickIndex", - "msg": "Provided tick index is either out of bounds or uninitializable" - }, - { - "code": 6011, - "name": "SqrtPriceOutOfBounds", - "msg": "Provided sqrt price out of bounds" - }, - { - "code": 6012, - "name": "LiquidityZero", - "msg": "Liquidity amount must be greater than zero" - }, - { - "code": 6013, - "name": "LiquidityTooHigh", - "msg": "Liquidity amount must be less than i64::MAX" - }, - { - "code": 6014, - "name": "LiquidityOverflow", - "msg": "Liquidity overflow" - }, - { - "code": 6015, - "name": "LiquidityUnderflow", - "msg": "Liquidity underflow" - }, - { - "code": 6016, - "name": "LiquidityNetError", - "msg": "Tick liquidity net underflowed or overflowed" - }, - { - "code": 6017, - "name": "TokenMaxExceeded", - "msg": "Exceeded token max" - }, - { - "code": 6018, - "name": "TokenMinSubceeded", - "msg": "Did not meet token min" - }, - { - "code": 6019, - "name": "MissingOrInvalidDelegate", - "msg": "Position token account has a missing or invalid delegate" - }, - { - "code": 6020, - "name": "InvalidPositionTokenAmount", - "msg": "Position token amount must be 1" - }, - { - "code": 6021, - "name": "InvalidTimestampConversion", - "msg": "Timestamp should be convertible from i64 to u64" - }, - { - "code": 6022, - "name": "InvalidTimestamp", - "msg": "Timestamp should be greater than the last updated timestamp" - }, - { - "code": 6023, - "name": "InvalidTickArraySequence", - "msg": "Invalid tick array sequence provided for instruction." - }, - { - "code": 6024, - "name": "InvalidTokenMintOrder", - "msg": "Token Mint in wrong order" - }, - { - "code": 6025, - "name": "RewardNotInitialized", - "msg": "Reward not initialized" - }, - { - "code": 6026, - "name": "InvalidRewardIndex", - "msg": "Invalid reward index" - }, - { - "code": 6027, - "name": "RewardVaultAmountInsufficient", - "msg": "Reward vault requires amount to support emissions for at least one day" - }, - { - "code": 6028, - "name": "FeeRateMaxExceeded", - "msg": "Exceeded max fee rate" - }, - { - "code": 6029, - "name": "ProtocolFeeRateMaxExceeded", - "msg": "Exceeded max protocol fee rate" - }, - { - "code": 6030, - "name": "MultiplicationShiftRightOverflow", - "msg": "Multiplication with shift right overflow" - }, - { - "code": 6031, - "name": "MulDivOverflow", - "msg": "Muldiv overflow" - }, - { - "code": 6032, - "name": "MulDivInvalidInput", - "msg": "Invalid div_u256 input" - }, - { - "code": 6033, - "name": "MultiplicationOverflow", - "msg": "Multiplication overflow" - }, - { - "code": 6034, - "name": "InvalidSqrtPriceLimitDirection", - "msg": "Provided SqrtPriceLimit not in the same direction as the swap." - }, - { - "code": 6035, - "name": "ZeroTradableAmount", - "msg": "There are no tradable amount to swap." - }, - { - "code": 6036, - "name": "AmountOutBelowMinimum", - "msg": "Amount out below minimum threshold" - }, - { - "code": 6037, - "name": "AmountInAboveMaximum", - "msg": "Amount in above maximum threshold" - }, - { - "code": 6038, - "name": "TickArraySequenceInvalidIndex", - "msg": "Invalid index for tick array sequence" - }, - { - "code": 6039, - "name": "AmountCalcOverflow", - "msg": "Amount calculated overflows" - }, - { - "code": 6040, - "name": "AmountRemainingOverflow", - "msg": "Amount remaining overflows" - }, - { - "code": 6041, - "name": "InvalidIntermediaryMint", - "msg": "Invalid intermediary mint" - }, - { - "code": 6042, - "name": "DuplicateTwoHopPool", - "msg": "Duplicate two hop pool" - }, - { - "code": 6043, - "name": "InvalidBundleIndex", - "msg": "Bundle index is out of bounds" - }, - { - "code": 6044, - "name": "BundledPositionAlreadyOpened", - "msg": "Position has already been opened" - }, - { - "code": 6045, - "name": "BundledPositionAlreadyClosed", - "msg": "Position has already been closed" - }, - { - "code": 6046, - "name": "PositionBundleNotDeletable", - "msg": "Unable to delete PositionBundle with open positions" - } - ] -} \ No newline at end of file diff --git a/sdk/src/artifacts/whirlpool.ts b/sdk/src/artifacts/whirlpool.ts deleted file mode 100644 index 23d8a17..0000000 --- a/sdk/src/artifacts/whirlpool.ts +++ /dev/null @@ -1,5051 +0,0 @@ -export type Whirlpool = { - "version": "0.2.0", - "name": "whirlpool", - "instructions": [ - { - "name": "initializeConfig", - "docs": [ - "Initializes a WhirlpoolsConfig account that hosts info & authorities", - "required to govern a set of Whirlpools.", - "", - "### Parameters", - "- `fee_authority` - Authority authorized to initialize fee-tiers and set customs fees.", - "- `collect_protocol_fees_authority` - Authority authorized to collect protocol fees.", - "- `reward_emissions_super_authority` - Authority authorized to set reward authorities in pools." - ], - "accounts": [ - { - "name": "config", - "isMut": true, - "isSigner": true - }, - { - "name": "funder", - "isMut": true, - "isSigner": true - }, - { - "name": "systemProgram", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "feeAuthority", - "type": "publicKey" - }, - { - "name": "collectProtocolFeesAuthority", - "type": "publicKey" - }, - { - "name": "rewardEmissionsSuperAuthority", - "type": "publicKey" - }, - { - "name": "defaultProtocolFeeRate", - "type": "u16" - } - ] - }, - { - "name": "initializePool", - "docs": [ - "Initializes a Whirlpool account.", - "Fee rate is set to the default values on the config and supplied fee_tier.", - "", - "### Parameters", - "- `bumps` - The bump value when deriving the PDA of the Whirlpool address.", - "- `tick_spacing` - The desired tick spacing for this pool.", - "- `initial_sqrt_price` - The desired initial sqrt-price for this pool", - "", - "#### Special Errors", - "`InvalidTokenMintOrder` - The order of mints have to be ordered by", - "`SqrtPriceOutOfBounds` - provided initial_sqrt_price is not between 2^-64 to 2^64", - "" - ], - "accounts": [ - { - "name": "whirlpoolsConfig", - "isMut": false, - "isSigner": false - }, - { - "name": "tokenMintA", - "isMut": false, - "isSigner": false - }, - { - "name": "tokenMintB", - "isMut": false, - "isSigner": false - }, - { - "name": "funder", - "isMut": true, - "isSigner": true - }, - { - "name": "whirlpool", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenVaultA", - "isMut": true, - "isSigner": true - }, - { - "name": "tokenVaultB", - "isMut": true, - "isSigner": true - }, - { - "name": "feeTier", - "isMut": false, - "isSigner": false - }, - { - "name": "tokenProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "systemProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "rent", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "bumps", - "type": { - "defined": "WhirlpoolBumps" - } - }, - { - "name": "tickSpacing", - "type": "u16" - }, - { - "name": "initialSqrtPrice", - "type": "u128" - } - ] - }, - { - "name": "initializeTickArray", - "docs": [ - "Initializes a tick_array account to represent a tick-range in a Whirlpool.", - "", - "### Parameters", - "- `start_tick_index` - The starting tick index for this tick-array.", - "Has to be a multiple of TickArray size & the tick spacing of this pool.", - "", - "#### Special Errors", - "- `InvalidStartTick` - if the provided start tick is out of bounds or is not a multiple of", - "TICK_ARRAY_SIZE * tick spacing." - ], - "accounts": [ - { - "name": "whirlpool", - "isMut": false, - "isSigner": false - }, - { - "name": "funder", - "isMut": true, - "isSigner": true - }, - { - "name": "tickArray", - "isMut": true, - "isSigner": false - }, - { - "name": "systemProgram", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "startTickIndex", - "type": "i32" - } - ] - }, - { - "name": "initializeFeeTier", - "docs": [ - "Initializes a fee_tier account usable by Whirlpools in a WhirlpoolConfig space.", - "", - "### Authority", - "- \"fee_authority\" - Set authority in the WhirlpoolConfig", - "", - "### Parameters", - "- `tick_spacing` - The tick-spacing that this fee-tier suggests the default_fee_rate for.", - "- `default_fee_rate` - The default fee rate that a pool will use if the pool uses this", - "fee tier during initialization.", - "", - "#### Special Errors", - "- `FeeRateMaxExceeded` - If the provided default_fee_rate exceeds MAX_FEE_RATE." - ], - "accounts": [ - { - "name": "config", - "isMut": false, - "isSigner": false - }, - { - "name": "feeTier", - "isMut": true, - "isSigner": false - }, - { - "name": "funder", - "isMut": true, - "isSigner": true - }, - { - "name": "feeAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "systemProgram", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "tickSpacing", - "type": "u16" - }, - { - "name": "defaultFeeRate", - "type": "u16" - } - ] - }, - { - "name": "initializeReward", - "docs": [ - "Initialize reward for a Whirlpool. A pool can only support up to a set number of rewards.", - "", - "### Authority", - "- \"reward_authority\" - assigned authority by the reward_super_authority for the specified", - "reward-index in this Whirlpool", - "", - "### Parameters", - "- `reward_index` - The reward index that we'd like to initialize. (0 <= index <= NUM_REWARDS)", - "", - "#### Special Errors", - "- `InvalidRewardIndex` - If the provided reward index doesn't match the lowest uninitialized", - "index in this pool, or exceeds NUM_REWARDS, or", - "all reward slots for this pool has been initialized." - ], - "accounts": [ - { - "name": "rewardAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "funder", - "isMut": true, - "isSigner": true - }, - { - "name": "whirlpool", - "isMut": true, - "isSigner": false - }, - { - "name": "rewardMint", - "isMut": false, - "isSigner": false - }, - { - "name": "rewardVault", - "isMut": true, - "isSigner": true - }, - { - "name": "tokenProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "systemProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "rent", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "rewardIndex", - "type": "u8" - } - ] - }, - { - "name": "setRewardEmissions", - "docs": [ - "Set the reward emissions for a reward in a Whirlpool.", - "", - "### Authority", - "- \"reward_authority\" - assigned authority by the reward_super_authority for the specified", - "reward-index in this Whirlpool", - "", - "### Parameters", - "- `reward_index` - The reward index (0 <= index <= NUM_REWARDS) that we'd like to modify.", - "- `emissions_per_second_x64` - The amount of rewards emitted in this pool.", - "", - "#### Special Errors", - "- `RewardVaultAmountInsufficient` - The amount of rewards in the reward vault cannot emit", - "more than a day of desired emissions.", - "- `InvalidTimestamp` - Provided timestamp is not in order with the previous timestamp.", - "- `InvalidRewardIndex` - If the provided reward index doesn't match the lowest uninitialized", - "index in this pool, or exceeds NUM_REWARDS, or", - "all reward slots for this pool has been initialized." - ], - "accounts": [ - { - "name": "whirlpool", - "isMut": true, - "isSigner": false - }, - { - "name": "rewardAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "rewardVault", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "rewardIndex", - "type": "u8" - }, - { - "name": "emissionsPerSecondX64", - "type": "u128" - } - ] - }, - { - "name": "openPosition", - "docs": [ - "Open a position in a Whirlpool. A unique token will be minted to represent the position", - "in the users wallet. The position will start off with 0 liquidity.", - "", - "### Parameters", - "- `tick_lower_index` - The tick specifying the lower end of the position range.", - "- `tick_upper_index` - The tick specifying the upper end of the position range.", - "", - "#### Special Errors", - "- `InvalidTickIndex` - If a provided tick is out of bounds, out of order or not a multiple of", - "the tick-spacing in this pool." - ], - "accounts": [ - { - "name": "funder", - "isMut": true, - "isSigner": true - }, - { - "name": "owner", - "isMut": false, - "isSigner": false - }, - { - "name": "position", - "isMut": true, - "isSigner": false - }, - { - "name": "positionMint", - "isMut": true, - "isSigner": true - }, - { - "name": "positionTokenAccount", - "isMut": true, - "isSigner": false - }, - { - "name": "whirlpool", - "isMut": false, - "isSigner": false - }, - { - "name": "tokenProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "systemProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "rent", - "isMut": false, - "isSigner": false - }, - { - "name": "associatedTokenProgram", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "bumps", - "type": { - "defined": "OpenPositionBumps" - } - }, - { - "name": "tickLowerIndex", - "type": "i32" - }, - { - "name": "tickUpperIndex", - "type": "i32" - } - ] - }, - { - "name": "openPositionWithMetadata", - "docs": [ - "Open a position in a Whirlpool. A unique token will be minted to represent the position", - "in the users wallet. Additional Metaplex metadata is appended to identify the token.", - "The position will start off with 0 liquidity.", - "", - "### Parameters", - "- `tick_lower_index` - The tick specifying the lower end of the position range.", - "- `tick_upper_index` - The tick specifying the upper end of the position range.", - "", - "#### Special Errors", - "- `InvalidTickIndex` - If a provided tick is out of bounds, out of order or not a multiple of", - "the tick-spacing in this pool." - ], - "accounts": [ - { - "name": "funder", - "isMut": true, - "isSigner": true - }, - { - "name": "owner", - "isMut": false, - "isSigner": false - }, - { - "name": "position", - "isMut": true, - "isSigner": false - }, - { - "name": "positionMint", - "isMut": true, - "isSigner": true - }, - { - "name": "positionMetadataAccount", - "isMut": true, - "isSigner": false, - "docs": [ - "https://github.com/metaplex-foundation/metaplex-program-library/blob/master/token-metadata/program/src/utils.rs#L873" - ] - }, - { - "name": "positionTokenAccount", - "isMut": true, - "isSigner": false - }, - { - "name": "whirlpool", - "isMut": false, - "isSigner": false - }, - { - "name": "tokenProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "systemProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "rent", - "isMut": false, - "isSigner": false - }, - { - "name": "associatedTokenProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "metadataProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "metadataUpdateAuth", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "bumps", - "type": { - "defined": "OpenPositionWithMetadataBumps" - } - }, - { - "name": "tickLowerIndex", - "type": "i32" - }, - { - "name": "tickUpperIndex", - "type": "i32" - } - ] - }, - { - "name": "increaseLiquidity", - "docs": [ - "Add liquidity to a position in the Whirlpool. This call also updates the position's accrued fees and rewards.", - "", - "### Authority", - "- `position_authority` - authority that owns the token corresponding to this desired position.", - "", - "### Parameters", - "- `liquidity_amount` - The total amount of Liquidity the user is willing to deposit.", - "- `token_max_a` - The maximum amount of tokenA the user is willing to deposit.", - "- `token_max_b` - The maximum amount of tokenB the user is willing to deposit.", - "", - "#### Special Errors", - "- `LiquidityZero` - Provided liquidity amount is zero.", - "- `LiquidityTooHigh` - Provided liquidity exceeds u128::max.", - "- `TokenMaxExceeded` - The required token to perform this operation exceeds the user defined amount." - ], - "accounts": [ - { - "name": "whirlpool", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "positionAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "position", - "isMut": true, - "isSigner": false - }, - { - "name": "positionTokenAccount", - "isMut": false, - "isSigner": false - }, - { - "name": "tokenOwnerAccountA", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenOwnerAccountB", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenVaultA", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenVaultB", - "isMut": true, - "isSigner": false - }, - { - "name": "tickArrayLower", - "isMut": true, - "isSigner": false - }, - { - "name": "tickArrayUpper", - "isMut": true, - "isSigner": false - } - ], - "args": [ - { - "name": "liquidityAmount", - "type": "u128" - }, - { - "name": "tokenMaxA", - "type": "u64" - }, - { - "name": "tokenMaxB", - "type": "u64" - } - ] - }, - { - "name": "decreaseLiquidity", - "docs": [ - "Withdraw liquidity from a position in the Whirlpool. This call also updates the position's accrued fees and rewards.", - "", - "### Authority", - "- `position_authority` - authority that owns the token corresponding to this desired position.", - "", - "### Parameters", - "- `liquidity_amount` - The total amount of Liquidity the user desires to withdraw.", - "- `token_min_a` - The minimum amount of tokenA the user is willing to withdraw.", - "- `token_min_b` - The minimum amount of tokenB the user is willing to withdraw.", - "", - "#### Special Errors", - "- `LiquidityZero` - Provided liquidity amount is zero.", - "- `LiquidityTooHigh` - Provided liquidity exceeds u128::max.", - "- `TokenMinSubceeded` - The required token to perform this operation subceeds the user defined amount." - ], - "accounts": [ - { - "name": "whirlpool", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "positionAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "position", - "isMut": true, - "isSigner": false - }, - { - "name": "positionTokenAccount", - "isMut": false, - "isSigner": false - }, - { - "name": "tokenOwnerAccountA", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenOwnerAccountB", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenVaultA", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenVaultB", - "isMut": true, - "isSigner": false - }, - { - "name": "tickArrayLower", - "isMut": true, - "isSigner": false - }, - { - "name": "tickArrayUpper", - "isMut": true, - "isSigner": false - } - ], - "args": [ - { - "name": "liquidityAmount", - "type": "u128" - }, - { - "name": "tokenMinA", - "type": "u64" - }, - { - "name": "tokenMinB", - "type": "u64" - } - ] - }, - { - "name": "updateFeesAndRewards", - "docs": [ - "Update the accrued fees and rewards for a position.", - "", - "#### Special Errors", - "- `TickNotFound` - Provided tick array account does not contain the tick for this position.", - "- `LiquidityZero` - Position has zero liquidity and therefore already has the most updated fees and reward values." - ], - "accounts": [ - { - "name": "whirlpool", - "isMut": true, - "isSigner": false - }, - { - "name": "position", - "isMut": true, - "isSigner": false - }, - { - "name": "tickArrayLower", - "isMut": false, - "isSigner": false - }, - { - "name": "tickArrayUpper", - "isMut": false, - "isSigner": false - } - ], - "args": [] - }, - { - "name": "collectFees", - "docs": [ - "Collect fees accrued for this position.", - "", - "### Authority", - "- `position_authority` - authority that owns the token corresponding to this desired position." - ], - "accounts": [ - { - "name": "whirlpool", - "isMut": false, - "isSigner": false - }, - { - "name": "positionAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "position", - "isMut": true, - "isSigner": false - }, - { - "name": "positionTokenAccount", - "isMut": false, - "isSigner": false - }, - { - "name": "tokenOwnerAccountA", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenVaultA", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenOwnerAccountB", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenVaultB", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenProgram", - "isMut": false, - "isSigner": false - } - ], - "args": [] - }, - { - "name": "collectReward", - "docs": [ - "Collect rewards accrued for this position.", - "", - "### Authority", - "- `position_authority` - authority that owns the token corresponding to this desired position." - ], - "accounts": [ - { - "name": "whirlpool", - "isMut": false, - "isSigner": false - }, - { - "name": "positionAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "position", - "isMut": true, - "isSigner": false - }, - { - "name": "positionTokenAccount", - "isMut": false, - "isSigner": false - }, - { - "name": "rewardOwnerAccount", - "isMut": true, - "isSigner": false - }, - { - "name": "rewardVault", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenProgram", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "rewardIndex", - "type": "u8" - } - ] - }, - { - "name": "collectProtocolFees", - "docs": [ - "Collect the protocol fees accrued in this Whirlpool", - "", - "### Authority", - "- `collect_protocol_fees_authority` - assigned authority in the WhirlpoolConfig that can collect protocol fees" - ], - "accounts": [ - { - "name": "whirlpoolsConfig", - "isMut": false, - "isSigner": false - }, - { - "name": "whirlpool", - "isMut": true, - "isSigner": false - }, - { - "name": "collectProtocolFeesAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "tokenVaultA", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenVaultB", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenDestinationA", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenDestinationB", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenProgram", - "isMut": false, - "isSigner": false - } - ], - "args": [] - }, - { - "name": "swap", - "docs": [ - "Perform a swap in this Whirlpool", - "", - "### Authority", - "- \"token_authority\" - The authority to withdraw tokens from the input token account.", - "", - "### Parameters", - "- `amount` - The amount of input or output token to swap from (depending on amount_specified_is_input).", - "- `other_amount_threshold` - The maximum/minimum of input/output token to swap into (depending on amount_specified_is_input).", - "- `sqrt_price_limit` - The maximum/minimum price the swap will swap to.", - "- `amount_specified_is_input` - Specifies the token the parameter `amount`represents. If true, the amount represents the input token of the swap.", - "- `a_to_b` - The direction of the swap. True if swapping from A to B. False if swapping from B to A.", - "", - "#### Special Errors", - "- `ZeroTradableAmount` - User provided parameter `amount` is 0.", - "- `InvalidSqrtPriceLimitDirection` - User provided parameter `sqrt_price_limit` does not match the direction of the trade.", - "- `SqrtPriceOutOfBounds` - User provided parameter `sqrt_price_limit` is over Whirlppool's max/min bounds for sqrt-price.", - "- `InvalidTickArraySequence` - User provided tick-arrays are not in sequential order required to proceed in this trade direction.", - "- `TickArraySequenceInvalidIndex` - The swap loop attempted to access an invalid array index during the query of the next initialized tick.", - "- `TickArrayIndexOutofBounds` - The swap loop attempted to access an invalid array index during tick crossing.", - "- `LiquidityOverflow` - Liquidity value overflowed 128bits during tick crossing.", - "- `InvalidTickSpacing` - The swap pool was initialized with tick-spacing of 0." - ], - "accounts": [ - { - "name": "tokenProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "tokenAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "whirlpool", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenOwnerAccountA", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenVaultA", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenOwnerAccountB", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenVaultB", - "isMut": true, - "isSigner": false - }, - { - "name": "tickArray0", - "isMut": true, - "isSigner": false - }, - { - "name": "tickArray1", - "isMut": true, - "isSigner": false - }, - { - "name": "tickArray2", - "isMut": true, - "isSigner": false - }, - { - "name": "oracle", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "amount", - "type": "u64" - }, - { - "name": "otherAmountThreshold", - "type": "u64" - }, - { - "name": "sqrtPriceLimit", - "type": "u128" - }, - { - "name": "amountSpecifiedIsInput", - "type": "bool" - }, - { - "name": "aToB", - "type": "bool" - } - ] - }, - { - "name": "closePosition", - "docs": [ - "Close a position in a Whirlpool. Burns the position token in the owner's wallet.", - "", - "### Authority", - "- \"position_authority\" - The authority that owns the position token.", - "", - "#### Special Errors", - "- `ClosePositionNotEmpty` - The provided position account is not empty." - ], - "accounts": [ - { - "name": "positionAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "receiver", - "isMut": true, - "isSigner": false - }, - { - "name": "position", - "isMut": true, - "isSigner": false - }, - { - "name": "positionMint", - "isMut": true, - "isSigner": false - }, - { - "name": "positionTokenAccount", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenProgram", - "isMut": false, - "isSigner": false - } - ], - "args": [] - }, - { - "name": "setDefaultFeeRate", - "docs": [ - "Set the default_fee_rate for a FeeTier", - "Only the current fee authority has permission to invoke this instruction.", - "", - "### Authority", - "- \"fee_authority\" - Set authority in the WhirlpoolConfig", - "", - "### Parameters", - "- `default_fee_rate` - The default fee rate that a pool will use if the pool uses this", - "fee tier during initialization.", - "", - "#### Special Errors", - "- `FeeRateMaxExceeded` - If the provided default_fee_rate exceeds MAX_FEE_RATE." - ], - "accounts": [ - { - "name": "whirlpoolsConfig", - "isMut": false, - "isSigner": false - }, - { - "name": "feeTier", - "isMut": true, - "isSigner": false - }, - { - "name": "feeAuthority", - "isMut": false, - "isSigner": true - } - ], - "args": [ - { - "name": "defaultFeeRate", - "type": "u16" - } - ] - }, - { - "name": "setDefaultProtocolFeeRate", - "docs": [ - "Sets the default protocol fee rate for a WhirlpoolConfig", - "Protocol fee rate is represented as a basis point.", - "Only the current fee authority has permission to invoke this instruction.", - "", - "### Authority", - "- \"fee_authority\" - Set authority that can modify pool fees in the WhirlpoolConfig", - "", - "### Parameters", - "- `default_protocol_fee_rate` - Rate that is referenced during the initialization of a Whirlpool using this config.", - "", - "#### Special Errors", - "- `ProtocolFeeRateMaxExceeded` - If the provided default_protocol_fee_rate exceeds MAX_PROTOCOL_FEE_RATE." - ], - "accounts": [ - { - "name": "whirlpoolsConfig", - "isMut": true, - "isSigner": false - }, - { - "name": "feeAuthority", - "isMut": false, - "isSigner": true - } - ], - "args": [ - { - "name": "defaultProtocolFeeRate", - "type": "u16" - } - ] - }, - { - "name": "setFeeRate", - "docs": [ - "Sets the fee rate for a Whirlpool.", - "Fee rate is represented as hundredths of a basis point.", - "Only the current fee authority has permission to invoke this instruction.", - "", - "### Authority", - "- \"fee_authority\" - Set authority that can modify pool fees in the WhirlpoolConfig", - "", - "### Parameters", - "- `fee_rate` - The rate that the pool will use to calculate fees going onwards.", - "", - "#### Special Errors", - "- `FeeRateMaxExceeded` - If the provided fee_rate exceeds MAX_FEE_RATE." - ], - "accounts": [ - { - "name": "whirlpoolsConfig", - "isMut": false, - "isSigner": false - }, - { - "name": "whirlpool", - "isMut": true, - "isSigner": false - }, - { - "name": "feeAuthority", - "isMut": false, - "isSigner": true - } - ], - "args": [ - { - "name": "feeRate", - "type": "u16" - } - ] - }, - { - "name": "setProtocolFeeRate", - "docs": [ - "Sets the protocol fee rate for a Whirlpool.", - "Protocol fee rate is represented as a basis point.", - "Only the current fee authority has permission to invoke this instruction.", - "", - "### Authority", - "- \"fee_authority\" - Set authority that can modify pool fees in the WhirlpoolConfig", - "", - "### Parameters", - "- `protocol_fee_rate` - The rate that the pool will use to calculate protocol fees going onwards.", - "", - "#### Special Errors", - "- `ProtocolFeeRateMaxExceeded` - If the provided default_protocol_fee_rate exceeds MAX_PROTOCOL_FEE_RATE." - ], - "accounts": [ - { - "name": "whirlpoolsConfig", - "isMut": false, - "isSigner": false - }, - { - "name": "whirlpool", - "isMut": true, - "isSigner": false - }, - { - "name": "feeAuthority", - "isMut": false, - "isSigner": true - } - ], - "args": [ - { - "name": "protocolFeeRate", - "type": "u16" - } - ] - }, - { - "name": "setFeeAuthority", - "docs": [ - "Sets the fee authority for a WhirlpoolConfig.", - "The fee authority can set the fee & protocol fee rate for individual pools or", - "set the default fee rate for newly minted pools.", - "Only the current fee authority has permission to invoke this instruction.", - "", - "### Authority", - "- \"fee_authority\" - Set authority that can modify pool fees in the WhirlpoolConfig" - ], - "accounts": [ - { - "name": "whirlpoolsConfig", - "isMut": true, - "isSigner": false - }, - { - "name": "feeAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "newFeeAuthority", - "isMut": false, - "isSigner": false - } - ], - "args": [] - }, - { - "name": "setCollectProtocolFeesAuthority", - "docs": [ - "Sets the fee authority to collect protocol fees for a WhirlpoolConfig.", - "Only the current collect protocol fee authority has permission to invoke this instruction.", - "", - "### Authority", - "- \"fee_authority\" - Set authority that can collect protocol fees in the WhirlpoolConfig" - ], - "accounts": [ - { - "name": "whirlpoolsConfig", - "isMut": true, - "isSigner": false - }, - { - "name": "collectProtocolFeesAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "newCollectProtocolFeesAuthority", - "isMut": false, - "isSigner": false - } - ], - "args": [] - }, - { - "name": "setRewardAuthority", - "docs": [ - "Set the whirlpool reward authority at the provided `reward_index`.", - "Only the current reward authority for this reward index has permission to invoke this instruction.", - "", - "### Authority", - "- \"reward_authority\" - Set authority that can control reward emission for this particular reward.", - "", - "#### Special Errors", - "- `InvalidRewardIndex` - If the provided reward index doesn't match the lowest uninitialized", - "index in this pool, or exceeds NUM_REWARDS, or", - "all reward slots for this pool has been initialized." - ], - "accounts": [ - { - "name": "whirlpool", - "isMut": true, - "isSigner": false - }, - { - "name": "rewardAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "newRewardAuthority", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "rewardIndex", - "type": "u8" - } - ] - }, - { - "name": "setRewardAuthorityBySuperAuthority", - "docs": [ - "Set the whirlpool reward authority at the provided `reward_index`.", - "Only the current reward super authority has permission to invoke this instruction.", - "", - "### Authority", - "- \"reward_authority\" - Set authority that can control reward emission for this particular reward.", - "", - "#### Special Errors", - "- `InvalidRewardIndex` - If the provided reward index doesn't match the lowest uninitialized", - "index in this pool, or exceeds NUM_REWARDS, or", - "all reward slots for this pool has been initialized." - ], - "accounts": [ - { - "name": "whirlpoolsConfig", - "isMut": false, - "isSigner": false - }, - { - "name": "whirlpool", - "isMut": true, - "isSigner": false - }, - { - "name": "rewardEmissionsSuperAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "newRewardAuthority", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "rewardIndex", - "type": "u8" - } - ] - }, - { - "name": "setRewardEmissionsSuperAuthority", - "docs": [ - "Set the whirlpool reward super authority for a WhirlpoolConfig", - "Only the current reward super authority has permission to invoke this instruction.", - "This instruction will not change the authority on any `WhirlpoolRewardInfo` whirlpool rewards.", - "", - "### Authority", - "- \"reward_emissions_super_authority\" - Set authority that can control reward authorities for all pools in this config space." - ], - "accounts": [ - { - "name": "whirlpoolsConfig", - "isMut": true, - "isSigner": false - }, - { - "name": "rewardEmissionsSuperAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "newRewardEmissionsSuperAuthority", - "isMut": false, - "isSigner": false - } - ], - "args": [] - }, - { - "name": "twoHopSwap", - "docs": [ - "Perform a two-hop swap in this Whirlpool", - "", - "### Authority", - "- \"token_authority\" - The authority to withdraw tokens from the input token account.", - "", - "### Parameters", - "- `amount` - The amount of input or output token to swap from (depending on amount_specified_is_input).", - "- `other_amount_threshold` - The maximum/minimum of input/output token to swap into (depending on amount_specified_is_input).", - "- `amount_specified_is_input` - Specifies the token the parameter `amount`represents. If true, the amount represents the input token of the swap.", - "- `a_to_b_one` - The direction of the swap of hop one. True if swapping from A to B. False if swapping from B to A.", - "- `a_to_b_two` - The direction of the swap of hop two. True if swapping from A to B. False if swapping from B to A.", - "- `sqrt_price_limit_one` - The maximum/minimum price the swap will swap to in the first hop.", - "- `sqrt_price_limit_two` - The maximum/minimum price the swap will swap to in the second hop.", - "", - "#### Special Errors", - "- `ZeroTradableAmount` - User provided parameter `amount` is 0.", - "- `InvalidSqrtPriceLimitDirection` - User provided parameter `sqrt_price_limit` does not match the direction of the trade.", - "- `SqrtPriceOutOfBounds` - User provided parameter `sqrt_price_limit` is over Whirlppool's max/min bounds for sqrt-price.", - "- `InvalidTickArraySequence` - User provided tick-arrays are not in sequential order required to proceed in this trade direction.", - "- `TickArraySequenceInvalidIndex` - The swap loop attempted to access an invalid array index during the query of the next initialized tick.", - "- `TickArrayIndexOutofBounds` - The swap loop attempted to access an invalid array index during tick crossing.", - "- `LiquidityOverflow` - Liquidity value overflowed 128bits during tick crossing.", - "- `InvalidTickSpacing` - The swap pool was initialized with tick-spacing of 0.", - "- `InvalidIntermediaryMint` - Error if the intermediary mint between hop one and two do not equal.", - "- `DuplicateTwoHopPool` - Error if whirlpool one & two are the same pool." - ], - "accounts": [ - { - "name": "tokenProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "tokenAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "whirlpoolOne", - "isMut": true, - "isSigner": false - }, - { - "name": "whirlpoolTwo", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenOwnerAccountOneA", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenVaultOneA", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenOwnerAccountOneB", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenVaultOneB", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenOwnerAccountTwoA", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenVaultTwoA", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenOwnerAccountTwoB", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenVaultTwoB", - "isMut": true, - "isSigner": false - }, - { - "name": "tickArrayOne0", - "isMut": true, - "isSigner": false - }, - { - "name": "tickArrayOne1", - "isMut": true, - "isSigner": false - }, - { - "name": "tickArrayOne2", - "isMut": true, - "isSigner": false - }, - { - "name": "tickArrayTwo0", - "isMut": true, - "isSigner": false - }, - { - "name": "tickArrayTwo1", - "isMut": true, - "isSigner": false - }, - { - "name": "tickArrayTwo2", - "isMut": true, - "isSigner": false - }, - { - "name": "oracleOne", - "isMut": false, - "isSigner": false - }, - { - "name": "oracleTwo", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "amount", - "type": "u64" - }, - { - "name": "otherAmountThreshold", - "type": "u64" - }, - { - "name": "amountSpecifiedIsInput", - "type": "bool" - }, - { - "name": "aToBOne", - "type": "bool" - }, - { - "name": "aToBTwo", - "type": "bool" - }, - { - "name": "sqrtPriceLimitOne", - "type": "u128" - }, - { - "name": "sqrtPriceLimitTwo", - "type": "u128" - } - ] - }, - { - "name": "initializePositionBundle", - "docs": [ - "Initializes a PositionBundle account that bundles several positions.", - "A unique token will be minted to represent the position bundle in the users wallet." - ], - "accounts": [ - { - "name": "positionBundle", - "isMut": true, - "isSigner": false - }, - { - "name": "positionBundleMint", - "isMut": true, - "isSigner": true - }, - { - "name": "positionBundleTokenAccount", - "isMut": true, - "isSigner": false - }, - { - "name": "positionBundleOwner", - "isMut": false, - "isSigner": false - }, - { - "name": "funder", - "isMut": true, - "isSigner": true - }, - { - "name": "tokenProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "systemProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "rent", - "isMut": false, - "isSigner": false - }, - { - "name": "associatedTokenProgram", - "isMut": false, - "isSigner": false - } - ], - "args": [] - }, - { - "name": "initializePositionBundleWithMetadata", - "docs": [ - "Initializes a PositionBundle account that bundles several positions.", - "A unique token will be minted to represent the position bundle in the users wallet.", - "Additional Metaplex metadata is appended to identify the token." - ], - "accounts": [ - { - "name": "positionBundle", - "isMut": true, - "isSigner": false - }, - { - "name": "positionBundleMint", - "isMut": true, - "isSigner": true - }, - { - "name": "positionBundleMetadata", - "isMut": true, - "isSigner": false, - "docs": [ - "https://github.com/metaplex-foundation/metaplex-program-library/blob/773a574c4b34e5b9f248a81306ec24db064e255f/token-metadata/program/src/utils/metadata.rs#L100" - ] - }, - { - "name": "positionBundleTokenAccount", - "isMut": true, - "isSigner": false - }, - { - "name": "positionBundleOwner", - "isMut": false, - "isSigner": false - }, - { - "name": "funder", - "isMut": true, - "isSigner": true - }, - { - "name": "metadataUpdateAuth", - "isMut": false, - "isSigner": false - }, - { - "name": "tokenProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "systemProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "rent", - "isMut": false, - "isSigner": false - }, - { - "name": "associatedTokenProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "metadataProgram", - "isMut": false, - "isSigner": false - } - ], - "args": [] - }, - { - "name": "deletePositionBundle", - "docs": [ - "Delete a PositionBundle account. Burns the position bundle token in the owner's wallet.", - "", - "### Authority", - "- `position_bundle_owner` - The owner that owns the position bundle token.", - "", - "### Special Errors", - "- `PositionBundleNotDeletable` - The provided position bundle has open positions." - ], - "accounts": [ - { - "name": "positionBundle", - "isMut": true, - "isSigner": false - }, - { - "name": "positionBundleMint", - "isMut": true, - "isSigner": false - }, - { - "name": "positionBundleTokenAccount", - "isMut": true, - "isSigner": false - }, - { - "name": "positionBundleOwner", - "isMut": false, - "isSigner": true - }, - { - "name": "receiver", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenProgram", - "isMut": false, - "isSigner": false - } - ], - "args": [] - }, - { - "name": "openBundledPosition", - "docs": [ - "Open a bundled position in a Whirlpool. No new tokens are issued", - "because the owner of the position bundle becomes the owner of the position.", - "The position will start off with 0 liquidity.", - "", - "### Authority", - "- `position_bundle_authority` - authority that owns the token corresponding to this desired position bundle.", - "", - "### Parameters", - "- `bundle_index` - The bundle index that we'd like to open.", - "- `tick_lower_index` - The tick specifying the lower end of the position range.", - "- `tick_upper_index` - The tick specifying the upper end of the position range.", - "", - "#### Special Errors", - "- `InvalidBundleIndex` - If the provided bundle index is out of bounds.", - "- `InvalidTickIndex` - If a provided tick is out of bounds, out of order or not a multiple of", - "the tick-spacing in this pool." - ], - "accounts": [ - { - "name": "bundledPosition", - "isMut": true, - "isSigner": false - }, - { - "name": "positionBundle", - "isMut": true, - "isSigner": false - }, - { - "name": "positionBundleTokenAccount", - "isMut": false, - "isSigner": false - }, - { - "name": "positionBundleAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "whirlpool", - "isMut": false, - "isSigner": false - }, - { - "name": "funder", - "isMut": true, - "isSigner": true - }, - { - "name": "systemProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "rent", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "bundleIndex", - "type": "u16" - }, - { - "name": "tickLowerIndex", - "type": "i32" - }, - { - "name": "tickUpperIndex", - "type": "i32" - } - ] - }, - { - "name": "closeBundledPosition", - "docs": [ - "Close a bundled position in a Whirlpool.", - "", - "### Authority", - "- `position_bundle_authority` - authority that owns the token corresponding to this desired position bundle.", - "", - "### Parameters", - "- `bundle_index` - The bundle index that we'd like to close.", - "", - "#### Special Errors", - "- `InvalidBundleIndex` - If the provided bundle index is out of bounds.", - "- `ClosePositionNotEmpty` - The provided position account is not empty." - ], - "accounts": [ - { - "name": "bundledPosition", - "isMut": true, - "isSigner": false - }, - { - "name": "positionBundle", - "isMut": true, - "isSigner": false - }, - { - "name": "positionBundleTokenAccount", - "isMut": false, - "isSigner": false - }, - { - "name": "positionBundleAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "receiver", - "isMut": true, - "isSigner": false - } - ], - "args": [ - { - "name": "bundleIndex", - "type": "u16" - } - ] - } - ], - "accounts": [ - { - "name": "whirlpoolsConfig", - "type": { - "kind": "struct", - "fields": [ - { - "name": "feeAuthority", - "type": "publicKey" - }, - { - "name": "collectProtocolFeesAuthority", - "type": "publicKey" - }, - { - "name": "rewardEmissionsSuperAuthority", - "type": "publicKey" - }, - { - "name": "defaultProtocolFeeRate", - "type": "u16" - } - ] - } - }, - { - "name": "feeTier", - "type": { - "kind": "struct", - "fields": [ - { - "name": "whirlpoolsConfig", - "type": "publicKey" - }, - { - "name": "tickSpacing", - "type": "u16" - }, - { - "name": "defaultFeeRate", - "type": "u16" - } - ] - } - }, - { - "name": "positionBundle", - "type": { - "kind": "struct", - "fields": [ - { - "name": "positionBundleMint", - "type": "publicKey" - }, - { - "name": "positionBitmap", - "type": { - "array": [ - "u8", - 32 - ] - } - } - ] - } - }, - { - "name": "position", - "type": { - "kind": "struct", - "fields": [ - { - "name": "whirlpool", - "type": "publicKey" - }, - { - "name": "positionMint", - "type": "publicKey" - }, - { - "name": "liquidity", - "type": "u128" - }, - { - "name": "tickLowerIndex", - "type": "i32" - }, - { - "name": "tickUpperIndex", - "type": "i32" - }, - { - "name": "feeGrowthCheckpointA", - "type": "u128" - }, - { - "name": "feeOwedA", - "type": "u64" - }, - { - "name": "feeGrowthCheckpointB", - "type": "u128" - }, - { - "name": "feeOwedB", - "type": "u64" - }, - { - "name": "rewardInfos", - "type": { - "array": [ - { - "defined": "PositionRewardInfo" - }, - 3 - ] - } - } - ] - } - }, - { - "name": "tickArray", - "type": { - "kind": "struct", - "fields": [ - { - "name": "startTickIndex", - "type": "i32" - }, - { - "name": "ticks", - "type": { - "array": [ - { - "defined": "Tick" - }, - 88 - ] - } - }, - { - "name": "whirlpool", - "type": "publicKey" - } - ] - } - }, - { - "name": "whirlpool", - "type": { - "kind": "struct", - "fields": [ - { - "name": "whirlpoolsConfig", - "type": "publicKey" - }, - { - "name": "whirlpoolBump", - "type": { - "array": [ - "u8", - 1 - ] - } - }, - { - "name": "tickSpacing", - "type": "u16" - }, - { - "name": "tickSpacingSeed", - "type": { - "array": [ - "u8", - 2 - ] - } - }, - { - "name": "feeRate", - "type": "u16" - }, - { - "name": "protocolFeeRate", - "type": "u16" - }, - { - "name": "liquidity", - "type": "u128" - }, - { - "name": "sqrtPrice", - "type": "u128" - }, - { - "name": "tickCurrentIndex", - "type": "i32" - }, - { - "name": "protocolFeeOwedA", - "type": "u64" - }, - { - "name": "protocolFeeOwedB", - "type": "u64" - }, - { - "name": "tokenMintA", - "type": "publicKey" - }, - { - "name": "tokenVaultA", - "type": "publicKey" - }, - { - "name": "feeGrowthGlobalA", - "type": "u128" - }, - { - "name": "tokenMintB", - "type": "publicKey" - }, - { - "name": "tokenVaultB", - "type": "publicKey" - }, - { - "name": "feeGrowthGlobalB", - "type": "u128" - }, - { - "name": "rewardLastUpdatedTimestamp", - "type": "u64" - }, - { - "name": "rewardInfos", - "type": { - "array": [ - { - "defined": "WhirlpoolRewardInfo" - }, - 3 - ] - } - } - ] - } - } - ], - "types": [ - { - "name": "OpenPositionBumps", - "type": { - "kind": "struct", - "fields": [ - { - "name": "positionBump", - "type": "u8" - } - ] - } - }, - { - "name": "OpenPositionWithMetadataBumps", - "type": { - "kind": "struct", - "fields": [ - { - "name": "positionBump", - "type": "u8" - }, - { - "name": "metadataBump", - "type": "u8" - } - ] - } - }, - { - "name": "PositionRewardInfo", - "type": { - "kind": "struct", - "fields": [ - { - "name": "growthInsideCheckpoint", - "type": "u128" - }, - { - "name": "amountOwed", - "type": "u64" - } - ] - } - }, - { - "name": "Tick", - "type": { - "kind": "struct", - "fields": [ - { - "name": "initialized", - "type": "bool" - }, - { - "name": "liquidityNet", - "type": "i128" - }, - { - "name": "liquidityGross", - "type": "u128" - }, - { - "name": "feeGrowthOutsideA", - "type": "u128" - }, - { - "name": "feeGrowthOutsideB", - "type": "u128" - }, - { - "name": "rewardGrowthsOutside", - "type": { - "array": [ - "u128", - 3 - ] - } - } - ] - } - }, - { - "name": "WhirlpoolRewardInfo", - "docs": [ - "Stores the state relevant for tracking liquidity mining rewards at the `Whirlpool` level.", - "These values are used in conjunction with `PositionRewardInfo`, `Tick.reward_growths_outside`,", - "and `Whirlpool.reward_last_updated_timestamp` to determine how many rewards are earned by open", - "positions." - ], - "type": { - "kind": "struct", - "fields": [ - { - "name": "mint", - "docs": [ - "Reward token mint." - ], - "type": "publicKey" - }, - { - "name": "vault", - "docs": [ - "Reward vault token account." - ], - "type": "publicKey" - }, - { - "name": "authority", - "docs": [ - "Authority account that has permission to initialize the reward and set emissions." - ], - "type": "publicKey" - }, - { - "name": "emissionsPerSecondX64", - "docs": [ - "Q64.64 number that indicates how many tokens per second are earned per unit of liquidity." - ], - "type": "u128" - }, - { - "name": "growthGlobalX64", - "docs": [ - "Q64.64 number that tracks the total tokens earned per unit of liquidity since the reward", - "emissions were turned on." - ], - "type": "u128" - } - ] - } - }, - { - "name": "WhirlpoolBumps", - "type": { - "kind": "struct", - "fields": [ - { - "name": "whirlpoolBump", - "type": "u8" - } - ] - } - }, - { - "name": "CurrIndex", - "type": { - "kind": "enum", - "variants": [ - { - "name": "Below" - }, - { - "name": "Inside" - }, - { - "name": "Above" - } - ] - } - }, - { - "name": "TickLabel", - "type": { - "kind": "enum", - "variants": [ - { - "name": "Upper" - }, - { - "name": "Lower" - } - ] - } - }, - { - "name": "Direction", - "type": { - "kind": "enum", - "variants": [ - { - "name": "Left" - }, - { - "name": "Right" - } - ] - } - } - ], - "errors": [ - { - "code": 6000, - "name": "InvalidEnum", - "msg": "Enum value could not be converted" - }, - { - "code": 6001, - "name": "InvalidStartTick", - "msg": "Invalid start tick index provided." - }, - { - "code": 6002, - "name": "TickArrayExistInPool", - "msg": "Tick-array already exists in this whirlpool" - }, - { - "code": 6003, - "name": "TickArrayIndexOutofBounds", - "msg": "Attempt to search for a tick-array failed" - }, - { - "code": 6004, - "name": "InvalidTickSpacing", - "msg": "Tick-spacing is not supported" - }, - { - "code": 6005, - "name": "ClosePositionNotEmpty", - "msg": "Position is not empty It cannot be closed" - }, - { - "code": 6006, - "name": "DivideByZero", - "msg": "Unable to divide by zero" - }, - { - "code": 6007, - "name": "NumberCastError", - "msg": "Unable to cast number into BigInt" - }, - { - "code": 6008, - "name": "NumberDownCastError", - "msg": "Unable to down cast number" - }, - { - "code": 6009, - "name": "TickNotFound", - "msg": "Tick not found within tick array" - }, - { - "code": 6010, - "name": "InvalidTickIndex", - "msg": "Provided tick index is either out of bounds or uninitializable" - }, - { - "code": 6011, - "name": "SqrtPriceOutOfBounds", - "msg": "Provided sqrt price out of bounds" - }, - { - "code": 6012, - "name": "LiquidityZero", - "msg": "Liquidity amount must be greater than zero" - }, - { - "code": 6013, - "name": "LiquidityTooHigh", - "msg": "Liquidity amount must be less than i64::MAX" - }, - { - "code": 6014, - "name": "LiquidityOverflow", - "msg": "Liquidity overflow" - }, - { - "code": 6015, - "name": "LiquidityUnderflow", - "msg": "Liquidity underflow" - }, - { - "code": 6016, - "name": "LiquidityNetError", - "msg": "Tick liquidity net underflowed or overflowed" - }, - { - "code": 6017, - "name": "TokenMaxExceeded", - "msg": "Exceeded token max" - }, - { - "code": 6018, - "name": "TokenMinSubceeded", - "msg": "Did not meet token min" - }, - { - "code": 6019, - "name": "MissingOrInvalidDelegate", - "msg": "Position token account has a missing or invalid delegate" - }, - { - "code": 6020, - "name": "InvalidPositionTokenAmount", - "msg": "Position token amount must be 1" - }, - { - "code": 6021, - "name": "InvalidTimestampConversion", - "msg": "Timestamp should be convertible from i64 to u64" - }, - { - "code": 6022, - "name": "InvalidTimestamp", - "msg": "Timestamp should be greater than the last updated timestamp" - }, - { - "code": 6023, - "name": "InvalidTickArraySequence", - "msg": "Invalid tick array sequence provided for instruction." - }, - { - "code": 6024, - "name": "InvalidTokenMintOrder", - "msg": "Token Mint in wrong order" - }, - { - "code": 6025, - "name": "RewardNotInitialized", - "msg": "Reward not initialized" - }, - { - "code": 6026, - "name": "InvalidRewardIndex", - "msg": "Invalid reward index" - }, - { - "code": 6027, - "name": "RewardVaultAmountInsufficient", - "msg": "Reward vault requires amount to support emissions for at least one day" - }, - { - "code": 6028, - "name": "FeeRateMaxExceeded", - "msg": "Exceeded max fee rate" - }, - { - "code": 6029, - "name": "ProtocolFeeRateMaxExceeded", - "msg": "Exceeded max protocol fee rate" - }, - { - "code": 6030, - "name": "MultiplicationShiftRightOverflow", - "msg": "Multiplication with shift right overflow" - }, - { - "code": 6031, - "name": "MulDivOverflow", - "msg": "Muldiv overflow" - }, - { - "code": 6032, - "name": "MulDivInvalidInput", - "msg": "Invalid div_u256 input" - }, - { - "code": 6033, - "name": "MultiplicationOverflow", - "msg": "Multiplication overflow" - }, - { - "code": 6034, - "name": "InvalidSqrtPriceLimitDirection", - "msg": "Provided SqrtPriceLimit not in the same direction as the swap." - }, - { - "code": 6035, - "name": "ZeroTradableAmount", - "msg": "There are no tradable amount to swap." - }, - { - "code": 6036, - "name": "AmountOutBelowMinimum", - "msg": "Amount out below minimum threshold" - }, - { - "code": 6037, - "name": "AmountInAboveMaximum", - "msg": "Amount in above maximum threshold" - }, - { - "code": 6038, - "name": "TickArraySequenceInvalidIndex", - "msg": "Invalid index for tick array sequence" - }, - { - "code": 6039, - "name": "AmountCalcOverflow", - "msg": "Amount calculated overflows" - }, - { - "code": 6040, - "name": "AmountRemainingOverflow", - "msg": "Amount remaining overflows" - }, - { - "code": 6041, - "name": "InvalidIntermediaryMint", - "msg": "Invalid intermediary mint" - }, - { - "code": 6042, - "name": "DuplicateTwoHopPool", - "msg": "Duplicate two hop pool" - }, - { - "code": 6043, - "name": "InvalidBundleIndex", - "msg": "Bundle index is out of bounds" - }, - { - "code": 6044, - "name": "BundledPositionAlreadyOpened", - "msg": "Position has already been opened" - }, - { - "code": 6045, - "name": "BundledPositionAlreadyClosed", - "msg": "Position has already been closed" - }, - { - "code": 6046, - "name": "PositionBundleNotDeletable", - "msg": "Unable to delete PositionBundle with open positions" - } - ] -}; - -export const IDL: Whirlpool = { - "version": "0.2.0", - "name": "whirlpool", - "instructions": [ - { - "name": "initializeConfig", - "docs": [ - "Initializes a WhirlpoolsConfig account that hosts info & authorities", - "required to govern a set of Whirlpools.", - "", - "### Parameters", - "- `fee_authority` - Authority authorized to initialize fee-tiers and set customs fees.", - "- `collect_protocol_fees_authority` - Authority authorized to collect protocol fees.", - "- `reward_emissions_super_authority` - Authority authorized to set reward authorities in pools." - ], - "accounts": [ - { - "name": "config", - "isMut": true, - "isSigner": true - }, - { - "name": "funder", - "isMut": true, - "isSigner": true - }, - { - "name": "systemProgram", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "feeAuthority", - "type": "publicKey" - }, - { - "name": "collectProtocolFeesAuthority", - "type": "publicKey" - }, - { - "name": "rewardEmissionsSuperAuthority", - "type": "publicKey" - }, - { - "name": "defaultProtocolFeeRate", - "type": "u16" - } - ] - }, - { - "name": "initializePool", - "docs": [ - "Initializes a Whirlpool account.", - "Fee rate is set to the default values on the config and supplied fee_tier.", - "", - "### Parameters", - "- `bumps` - The bump value when deriving the PDA of the Whirlpool address.", - "- `tick_spacing` - The desired tick spacing for this pool.", - "- `initial_sqrt_price` - The desired initial sqrt-price for this pool", - "", - "#### Special Errors", - "`InvalidTokenMintOrder` - The order of mints have to be ordered by", - "`SqrtPriceOutOfBounds` - provided initial_sqrt_price is not between 2^-64 to 2^64", - "" - ], - "accounts": [ - { - "name": "whirlpoolsConfig", - "isMut": false, - "isSigner": false - }, - { - "name": "tokenMintA", - "isMut": false, - "isSigner": false - }, - { - "name": "tokenMintB", - "isMut": false, - "isSigner": false - }, - { - "name": "funder", - "isMut": true, - "isSigner": true - }, - { - "name": "whirlpool", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenVaultA", - "isMut": true, - "isSigner": true - }, - { - "name": "tokenVaultB", - "isMut": true, - "isSigner": true - }, - { - "name": "feeTier", - "isMut": false, - "isSigner": false - }, - { - "name": "tokenProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "systemProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "rent", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "bumps", - "type": { - "defined": "WhirlpoolBumps" - } - }, - { - "name": "tickSpacing", - "type": "u16" - }, - { - "name": "initialSqrtPrice", - "type": "u128" - } - ] - }, - { - "name": "initializeTickArray", - "docs": [ - "Initializes a tick_array account to represent a tick-range in a Whirlpool.", - "", - "### Parameters", - "- `start_tick_index` - The starting tick index for this tick-array.", - "Has to be a multiple of TickArray size & the tick spacing of this pool.", - "", - "#### Special Errors", - "- `InvalidStartTick` - if the provided start tick is out of bounds or is not a multiple of", - "TICK_ARRAY_SIZE * tick spacing." - ], - "accounts": [ - { - "name": "whirlpool", - "isMut": false, - "isSigner": false - }, - { - "name": "funder", - "isMut": true, - "isSigner": true - }, - { - "name": "tickArray", - "isMut": true, - "isSigner": false - }, - { - "name": "systemProgram", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "startTickIndex", - "type": "i32" - } - ] - }, - { - "name": "initializeFeeTier", - "docs": [ - "Initializes a fee_tier account usable by Whirlpools in a WhirlpoolConfig space.", - "", - "### Authority", - "- \"fee_authority\" - Set authority in the WhirlpoolConfig", - "", - "### Parameters", - "- `tick_spacing` - The tick-spacing that this fee-tier suggests the default_fee_rate for.", - "- `default_fee_rate` - The default fee rate that a pool will use if the pool uses this", - "fee tier during initialization.", - "", - "#### Special Errors", - "- `FeeRateMaxExceeded` - If the provided default_fee_rate exceeds MAX_FEE_RATE." - ], - "accounts": [ - { - "name": "config", - "isMut": false, - "isSigner": false - }, - { - "name": "feeTier", - "isMut": true, - "isSigner": false - }, - { - "name": "funder", - "isMut": true, - "isSigner": true - }, - { - "name": "feeAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "systemProgram", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "tickSpacing", - "type": "u16" - }, - { - "name": "defaultFeeRate", - "type": "u16" - } - ] - }, - { - "name": "initializeReward", - "docs": [ - "Initialize reward for a Whirlpool. A pool can only support up to a set number of rewards.", - "", - "### Authority", - "- \"reward_authority\" - assigned authority by the reward_super_authority for the specified", - "reward-index in this Whirlpool", - "", - "### Parameters", - "- `reward_index` - The reward index that we'd like to initialize. (0 <= index <= NUM_REWARDS)", - "", - "#### Special Errors", - "- `InvalidRewardIndex` - If the provided reward index doesn't match the lowest uninitialized", - "index in this pool, or exceeds NUM_REWARDS, or", - "all reward slots for this pool has been initialized." - ], - "accounts": [ - { - "name": "rewardAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "funder", - "isMut": true, - "isSigner": true - }, - { - "name": "whirlpool", - "isMut": true, - "isSigner": false - }, - { - "name": "rewardMint", - "isMut": false, - "isSigner": false - }, - { - "name": "rewardVault", - "isMut": true, - "isSigner": true - }, - { - "name": "tokenProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "systemProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "rent", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "rewardIndex", - "type": "u8" - } - ] - }, - { - "name": "setRewardEmissions", - "docs": [ - "Set the reward emissions for a reward in a Whirlpool.", - "", - "### Authority", - "- \"reward_authority\" - assigned authority by the reward_super_authority for the specified", - "reward-index in this Whirlpool", - "", - "### Parameters", - "- `reward_index` - The reward index (0 <= index <= NUM_REWARDS) that we'd like to modify.", - "- `emissions_per_second_x64` - The amount of rewards emitted in this pool.", - "", - "#### Special Errors", - "- `RewardVaultAmountInsufficient` - The amount of rewards in the reward vault cannot emit", - "more than a day of desired emissions.", - "- `InvalidTimestamp` - Provided timestamp is not in order with the previous timestamp.", - "- `InvalidRewardIndex` - If the provided reward index doesn't match the lowest uninitialized", - "index in this pool, or exceeds NUM_REWARDS, or", - "all reward slots for this pool has been initialized." - ], - "accounts": [ - { - "name": "whirlpool", - "isMut": true, - "isSigner": false - }, - { - "name": "rewardAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "rewardVault", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "rewardIndex", - "type": "u8" - }, - { - "name": "emissionsPerSecondX64", - "type": "u128" - } - ] - }, - { - "name": "openPosition", - "docs": [ - "Open a position in a Whirlpool. A unique token will be minted to represent the position", - "in the users wallet. The position will start off with 0 liquidity.", - "", - "### Parameters", - "- `tick_lower_index` - The tick specifying the lower end of the position range.", - "- `tick_upper_index` - The tick specifying the upper end of the position range.", - "", - "#### Special Errors", - "- `InvalidTickIndex` - If a provided tick is out of bounds, out of order or not a multiple of", - "the tick-spacing in this pool." - ], - "accounts": [ - { - "name": "funder", - "isMut": true, - "isSigner": true - }, - { - "name": "owner", - "isMut": false, - "isSigner": false - }, - { - "name": "position", - "isMut": true, - "isSigner": false - }, - { - "name": "positionMint", - "isMut": true, - "isSigner": true - }, - { - "name": "positionTokenAccount", - "isMut": true, - "isSigner": false - }, - { - "name": "whirlpool", - "isMut": false, - "isSigner": false - }, - { - "name": "tokenProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "systemProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "rent", - "isMut": false, - "isSigner": false - }, - { - "name": "associatedTokenProgram", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "bumps", - "type": { - "defined": "OpenPositionBumps" - } - }, - { - "name": "tickLowerIndex", - "type": "i32" - }, - { - "name": "tickUpperIndex", - "type": "i32" - } - ] - }, - { - "name": "openPositionWithMetadata", - "docs": [ - "Open a position in a Whirlpool. A unique token will be minted to represent the position", - "in the users wallet. Additional Metaplex metadata is appended to identify the token.", - "The position will start off with 0 liquidity.", - "", - "### Parameters", - "- `tick_lower_index` - The tick specifying the lower end of the position range.", - "- `tick_upper_index` - The tick specifying the upper end of the position range.", - "", - "#### Special Errors", - "- `InvalidTickIndex` - If a provided tick is out of bounds, out of order or not a multiple of", - "the tick-spacing in this pool." - ], - "accounts": [ - { - "name": "funder", - "isMut": true, - "isSigner": true - }, - { - "name": "owner", - "isMut": false, - "isSigner": false - }, - { - "name": "position", - "isMut": true, - "isSigner": false - }, - { - "name": "positionMint", - "isMut": true, - "isSigner": true - }, - { - "name": "positionMetadataAccount", - "isMut": true, - "isSigner": false, - "docs": [ - "https://github.com/metaplex-foundation/metaplex-program-library/blob/master/token-metadata/program/src/utils.rs#L873" - ] - }, - { - "name": "positionTokenAccount", - "isMut": true, - "isSigner": false - }, - { - "name": "whirlpool", - "isMut": false, - "isSigner": false - }, - { - "name": "tokenProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "systemProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "rent", - "isMut": false, - "isSigner": false - }, - { - "name": "associatedTokenProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "metadataProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "metadataUpdateAuth", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "bumps", - "type": { - "defined": "OpenPositionWithMetadataBumps" - } - }, - { - "name": "tickLowerIndex", - "type": "i32" - }, - { - "name": "tickUpperIndex", - "type": "i32" - } - ] - }, - { - "name": "increaseLiquidity", - "docs": [ - "Add liquidity to a position in the Whirlpool. This call also updates the position's accrued fees and rewards.", - "", - "### Authority", - "- `position_authority` - authority that owns the token corresponding to this desired position.", - "", - "### Parameters", - "- `liquidity_amount` - The total amount of Liquidity the user is willing to deposit.", - "- `token_max_a` - The maximum amount of tokenA the user is willing to deposit.", - "- `token_max_b` - The maximum amount of tokenB the user is willing to deposit.", - "", - "#### Special Errors", - "- `LiquidityZero` - Provided liquidity amount is zero.", - "- `LiquidityTooHigh` - Provided liquidity exceeds u128::max.", - "- `TokenMaxExceeded` - The required token to perform this operation exceeds the user defined amount." - ], - "accounts": [ - { - "name": "whirlpool", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "positionAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "position", - "isMut": true, - "isSigner": false - }, - { - "name": "positionTokenAccount", - "isMut": false, - "isSigner": false - }, - { - "name": "tokenOwnerAccountA", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenOwnerAccountB", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenVaultA", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenVaultB", - "isMut": true, - "isSigner": false - }, - { - "name": "tickArrayLower", - "isMut": true, - "isSigner": false - }, - { - "name": "tickArrayUpper", - "isMut": true, - "isSigner": false - } - ], - "args": [ - { - "name": "liquidityAmount", - "type": "u128" - }, - { - "name": "tokenMaxA", - "type": "u64" - }, - { - "name": "tokenMaxB", - "type": "u64" - } - ] - }, - { - "name": "decreaseLiquidity", - "docs": [ - "Withdraw liquidity from a position in the Whirlpool. This call also updates the position's accrued fees and rewards.", - "", - "### Authority", - "- `position_authority` - authority that owns the token corresponding to this desired position.", - "", - "### Parameters", - "- `liquidity_amount` - The total amount of Liquidity the user desires to withdraw.", - "- `token_min_a` - The minimum amount of tokenA the user is willing to withdraw.", - "- `token_min_b` - The minimum amount of tokenB the user is willing to withdraw.", - "", - "#### Special Errors", - "- `LiquidityZero` - Provided liquidity amount is zero.", - "- `LiquidityTooHigh` - Provided liquidity exceeds u128::max.", - "- `TokenMinSubceeded` - The required token to perform this operation subceeds the user defined amount." - ], - "accounts": [ - { - "name": "whirlpool", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "positionAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "position", - "isMut": true, - "isSigner": false - }, - { - "name": "positionTokenAccount", - "isMut": false, - "isSigner": false - }, - { - "name": "tokenOwnerAccountA", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenOwnerAccountB", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenVaultA", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenVaultB", - "isMut": true, - "isSigner": false - }, - { - "name": "tickArrayLower", - "isMut": true, - "isSigner": false - }, - { - "name": "tickArrayUpper", - "isMut": true, - "isSigner": false - } - ], - "args": [ - { - "name": "liquidityAmount", - "type": "u128" - }, - { - "name": "tokenMinA", - "type": "u64" - }, - { - "name": "tokenMinB", - "type": "u64" - } - ] - }, - { - "name": "updateFeesAndRewards", - "docs": [ - "Update the accrued fees and rewards for a position.", - "", - "#### Special Errors", - "- `TickNotFound` - Provided tick array account does not contain the tick for this position.", - "- `LiquidityZero` - Position has zero liquidity and therefore already has the most updated fees and reward values." - ], - "accounts": [ - { - "name": "whirlpool", - "isMut": true, - "isSigner": false - }, - { - "name": "position", - "isMut": true, - "isSigner": false - }, - { - "name": "tickArrayLower", - "isMut": false, - "isSigner": false - }, - { - "name": "tickArrayUpper", - "isMut": false, - "isSigner": false - } - ], - "args": [] - }, - { - "name": "collectFees", - "docs": [ - "Collect fees accrued for this position.", - "", - "### Authority", - "- `position_authority` - authority that owns the token corresponding to this desired position." - ], - "accounts": [ - { - "name": "whirlpool", - "isMut": false, - "isSigner": false - }, - { - "name": "positionAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "position", - "isMut": true, - "isSigner": false - }, - { - "name": "positionTokenAccount", - "isMut": false, - "isSigner": false - }, - { - "name": "tokenOwnerAccountA", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenVaultA", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenOwnerAccountB", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenVaultB", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenProgram", - "isMut": false, - "isSigner": false - } - ], - "args": [] - }, - { - "name": "collectReward", - "docs": [ - "Collect rewards accrued for this position.", - "", - "### Authority", - "- `position_authority` - authority that owns the token corresponding to this desired position." - ], - "accounts": [ - { - "name": "whirlpool", - "isMut": false, - "isSigner": false - }, - { - "name": "positionAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "position", - "isMut": true, - "isSigner": false - }, - { - "name": "positionTokenAccount", - "isMut": false, - "isSigner": false - }, - { - "name": "rewardOwnerAccount", - "isMut": true, - "isSigner": false - }, - { - "name": "rewardVault", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenProgram", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "rewardIndex", - "type": "u8" - } - ] - }, - { - "name": "collectProtocolFees", - "docs": [ - "Collect the protocol fees accrued in this Whirlpool", - "", - "### Authority", - "- `collect_protocol_fees_authority` - assigned authority in the WhirlpoolConfig that can collect protocol fees" - ], - "accounts": [ - { - "name": "whirlpoolsConfig", - "isMut": false, - "isSigner": false - }, - { - "name": "whirlpool", - "isMut": true, - "isSigner": false - }, - { - "name": "collectProtocolFeesAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "tokenVaultA", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenVaultB", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenDestinationA", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenDestinationB", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenProgram", - "isMut": false, - "isSigner": false - } - ], - "args": [] - }, - { - "name": "swap", - "docs": [ - "Perform a swap in this Whirlpool", - "", - "### Authority", - "- \"token_authority\" - The authority to withdraw tokens from the input token account.", - "", - "### Parameters", - "- `amount` - The amount of input or output token to swap from (depending on amount_specified_is_input).", - "- `other_amount_threshold` - The maximum/minimum of input/output token to swap into (depending on amount_specified_is_input).", - "- `sqrt_price_limit` - The maximum/minimum price the swap will swap to.", - "- `amount_specified_is_input` - Specifies the token the parameter `amount`represents. If true, the amount represents the input token of the swap.", - "- `a_to_b` - The direction of the swap. True if swapping from A to B. False if swapping from B to A.", - "", - "#### Special Errors", - "- `ZeroTradableAmount` - User provided parameter `amount` is 0.", - "- `InvalidSqrtPriceLimitDirection` - User provided parameter `sqrt_price_limit` does not match the direction of the trade.", - "- `SqrtPriceOutOfBounds` - User provided parameter `sqrt_price_limit` is over Whirlppool's max/min bounds for sqrt-price.", - "- `InvalidTickArraySequence` - User provided tick-arrays are not in sequential order required to proceed in this trade direction.", - "- `TickArraySequenceInvalidIndex` - The swap loop attempted to access an invalid array index during the query of the next initialized tick.", - "- `TickArrayIndexOutofBounds` - The swap loop attempted to access an invalid array index during tick crossing.", - "- `LiquidityOverflow` - Liquidity value overflowed 128bits during tick crossing.", - "- `InvalidTickSpacing` - The swap pool was initialized with tick-spacing of 0." - ], - "accounts": [ - { - "name": "tokenProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "tokenAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "whirlpool", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenOwnerAccountA", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenVaultA", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenOwnerAccountB", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenVaultB", - "isMut": true, - "isSigner": false - }, - { - "name": "tickArray0", - "isMut": true, - "isSigner": false - }, - { - "name": "tickArray1", - "isMut": true, - "isSigner": false - }, - { - "name": "tickArray2", - "isMut": true, - "isSigner": false - }, - { - "name": "oracle", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "amount", - "type": "u64" - }, - { - "name": "otherAmountThreshold", - "type": "u64" - }, - { - "name": "sqrtPriceLimit", - "type": "u128" - }, - { - "name": "amountSpecifiedIsInput", - "type": "bool" - }, - { - "name": "aToB", - "type": "bool" - } - ] - }, - { - "name": "closePosition", - "docs": [ - "Close a position in a Whirlpool. Burns the position token in the owner's wallet.", - "", - "### Authority", - "- \"position_authority\" - The authority that owns the position token.", - "", - "#### Special Errors", - "- `ClosePositionNotEmpty` - The provided position account is not empty." - ], - "accounts": [ - { - "name": "positionAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "receiver", - "isMut": true, - "isSigner": false - }, - { - "name": "position", - "isMut": true, - "isSigner": false - }, - { - "name": "positionMint", - "isMut": true, - "isSigner": false - }, - { - "name": "positionTokenAccount", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenProgram", - "isMut": false, - "isSigner": false - } - ], - "args": [] - }, - { - "name": "setDefaultFeeRate", - "docs": [ - "Set the default_fee_rate for a FeeTier", - "Only the current fee authority has permission to invoke this instruction.", - "", - "### Authority", - "- \"fee_authority\" - Set authority in the WhirlpoolConfig", - "", - "### Parameters", - "- `default_fee_rate` - The default fee rate that a pool will use if the pool uses this", - "fee tier during initialization.", - "", - "#### Special Errors", - "- `FeeRateMaxExceeded` - If the provided default_fee_rate exceeds MAX_FEE_RATE." - ], - "accounts": [ - { - "name": "whirlpoolsConfig", - "isMut": false, - "isSigner": false - }, - { - "name": "feeTier", - "isMut": true, - "isSigner": false - }, - { - "name": "feeAuthority", - "isMut": false, - "isSigner": true - } - ], - "args": [ - { - "name": "defaultFeeRate", - "type": "u16" - } - ] - }, - { - "name": "setDefaultProtocolFeeRate", - "docs": [ - "Sets the default protocol fee rate for a WhirlpoolConfig", - "Protocol fee rate is represented as a basis point.", - "Only the current fee authority has permission to invoke this instruction.", - "", - "### Authority", - "- \"fee_authority\" - Set authority that can modify pool fees in the WhirlpoolConfig", - "", - "### Parameters", - "- `default_protocol_fee_rate` - Rate that is referenced during the initialization of a Whirlpool using this config.", - "", - "#### Special Errors", - "- `ProtocolFeeRateMaxExceeded` - If the provided default_protocol_fee_rate exceeds MAX_PROTOCOL_FEE_RATE." - ], - "accounts": [ - { - "name": "whirlpoolsConfig", - "isMut": true, - "isSigner": false - }, - { - "name": "feeAuthority", - "isMut": false, - "isSigner": true - } - ], - "args": [ - { - "name": "defaultProtocolFeeRate", - "type": "u16" - } - ] - }, - { - "name": "setFeeRate", - "docs": [ - "Sets the fee rate for a Whirlpool.", - "Fee rate is represented as hundredths of a basis point.", - "Only the current fee authority has permission to invoke this instruction.", - "", - "### Authority", - "- \"fee_authority\" - Set authority that can modify pool fees in the WhirlpoolConfig", - "", - "### Parameters", - "- `fee_rate` - The rate that the pool will use to calculate fees going onwards.", - "", - "#### Special Errors", - "- `FeeRateMaxExceeded` - If the provided fee_rate exceeds MAX_FEE_RATE." - ], - "accounts": [ - { - "name": "whirlpoolsConfig", - "isMut": false, - "isSigner": false - }, - { - "name": "whirlpool", - "isMut": true, - "isSigner": false - }, - { - "name": "feeAuthority", - "isMut": false, - "isSigner": true - } - ], - "args": [ - { - "name": "feeRate", - "type": "u16" - } - ] - }, - { - "name": "setProtocolFeeRate", - "docs": [ - "Sets the protocol fee rate for a Whirlpool.", - "Protocol fee rate is represented as a basis point.", - "Only the current fee authority has permission to invoke this instruction.", - "", - "### Authority", - "- \"fee_authority\" - Set authority that can modify pool fees in the WhirlpoolConfig", - "", - "### Parameters", - "- `protocol_fee_rate` - The rate that the pool will use to calculate protocol fees going onwards.", - "", - "#### Special Errors", - "- `ProtocolFeeRateMaxExceeded` - If the provided default_protocol_fee_rate exceeds MAX_PROTOCOL_FEE_RATE." - ], - "accounts": [ - { - "name": "whirlpoolsConfig", - "isMut": false, - "isSigner": false - }, - { - "name": "whirlpool", - "isMut": true, - "isSigner": false - }, - { - "name": "feeAuthority", - "isMut": false, - "isSigner": true - } - ], - "args": [ - { - "name": "protocolFeeRate", - "type": "u16" - } - ] - }, - { - "name": "setFeeAuthority", - "docs": [ - "Sets the fee authority for a WhirlpoolConfig.", - "The fee authority can set the fee & protocol fee rate for individual pools or", - "set the default fee rate for newly minted pools.", - "Only the current fee authority has permission to invoke this instruction.", - "", - "### Authority", - "- \"fee_authority\" - Set authority that can modify pool fees in the WhirlpoolConfig" - ], - "accounts": [ - { - "name": "whirlpoolsConfig", - "isMut": true, - "isSigner": false - }, - { - "name": "feeAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "newFeeAuthority", - "isMut": false, - "isSigner": false - } - ], - "args": [] - }, - { - "name": "setCollectProtocolFeesAuthority", - "docs": [ - "Sets the fee authority to collect protocol fees for a WhirlpoolConfig.", - "Only the current collect protocol fee authority has permission to invoke this instruction.", - "", - "### Authority", - "- \"fee_authority\" - Set authority that can collect protocol fees in the WhirlpoolConfig" - ], - "accounts": [ - { - "name": "whirlpoolsConfig", - "isMut": true, - "isSigner": false - }, - { - "name": "collectProtocolFeesAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "newCollectProtocolFeesAuthority", - "isMut": false, - "isSigner": false - } - ], - "args": [] - }, - { - "name": "setRewardAuthority", - "docs": [ - "Set the whirlpool reward authority at the provided `reward_index`.", - "Only the current reward authority for this reward index has permission to invoke this instruction.", - "", - "### Authority", - "- \"reward_authority\" - Set authority that can control reward emission for this particular reward.", - "", - "#### Special Errors", - "- `InvalidRewardIndex` - If the provided reward index doesn't match the lowest uninitialized", - "index in this pool, or exceeds NUM_REWARDS, or", - "all reward slots for this pool has been initialized." - ], - "accounts": [ - { - "name": "whirlpool", - "isMut": true, - "isSigner": false - }, - { - "name": "rewardAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "newRewardAuthority", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "rewardIndex", - "type": "u8" - } - ] - }, - { - "name": "setRewardAuthorityBySuperAuthority", - "docs": [ - "Set the whirlpool reward authority at the provided `reward_index`.", - "Only the current reward super authority has permission to invoke this instruction.", - "", - "### Authority", - "- \"reward_authority\" - Set authority that can control reward emission for this particular reward.", - "", - "#### Special Errors", - "- `InvalidRewardIndex` - If the provided reward index doesn't match the lowest uninitialized", - "index in this pool, or exceeds NUM_REWARDS, or", - "all reward slots for this pool has been initialized." - ], - "accounts": [ - { - "name": "whirlpoolsConfig", - "isMut": false, - "isSigner": false - }, - { - "name": "whirlpool", - "isMut": true, - "isSigner": false - }, - { - "name": "rewardEmissionsSuperAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "newRewardAuthority", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "rewardIndex", - "type": "u8" - } - ] - }, - { - "name": "setRewardEmissionsSuperAuthority", - "docs": [ - "Set the whirlpool reward super authority for a WhirlpoolConfig", - "Only the current reward super authority has permission to invoke this instruction.", - "This instruction will not change the authority on any `WhirlpoolRewardInfo` whirlpool rewards.", - "", - "### Authority", - "- \"reward_emissions_super_authority\" - Set authority that can control reward authorities for all pools in this config space." - ], - "accounts": [ - { - "name": "whirlpoolsConfig", - "isMut": true, - "isSigner": false - }, - { - "name": "rewardEmissionsSuperAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "newRewardEmissionsSuperAuthority", - "isMut": false, - "isSigner": false - } - ], - "args": [] - }, - { - "name": "twoHopSwap", - "docs": [ - "Perform a two-hop swap in this Whirlpool", - "", - "### Authority", - "- \"token_authority\" - The authority to withdraw tokens from the input token account.", - "", - "### Parameters", - "- `amount` - The amount of input or output token to swap from (depending on amount_specified_is_input).", - "- `other_amount_threshold` - The maximum/minimum of input/output token to swap into (depending on amount_specified_is_input).", - "- `amount_specified_is_input` - Specifies the token the parameter `amount`represents. If true, the amount represents the input token of the swap.", - "- `a_to_b_one` - The direction of the swap of hop one. True if swapping from A to B. False if swapping from B to A.", - "- `a_to_b_two` - The direction of the swap of hop two. True if swapping from A to B. False if swapping from B to A.", - "- `sqrt_price_limit_one` - The maximum/minimum price the swap will swap to in the first hop.", - "- `sqrt_price_limit_two` - The maximum/minimum price the swap will swap to in the second hop.", - "", - "#### Special Errors", - "- `ZeroTradableAmount` - User provided parameter `amount` is 0.", - "- `InvalidSqrtPriceLimitDirection` - User provided parameter `sqrt_price_limit` does not match the direction of the trade.", - "- `SqrtPriceOutOfBounds` - User provided parameter `sqrt_price_limit` is over Whirlppool's max/min bounds for sqrt-price.", - "- `InvalidTickArraySequence` - User provided tick-arrays are not in sequential order required to proceed in this trade direction.", - "- `TickArraySequenceInvalidIndex` - The swap loop attempted to access an invalid array index during the query of the next initialized tick.", - "- `TickArrayIndexOutofBounds` - The swap loop attempted to access an invalid array index during tick crossing.", - "- `LiquidityOverflow` - Liquidity value overflowed 128bits during tick crossing.", - "- `InvalidTickSpacing` - The swap pool was initialized with tick-spacing of 0.", - "- `InvalidIntermediaryMint` - Error if the intermediary mint between hop one and two do not equal.", - "- `DuplicateTwoHopPool` - Error if whirlpool one & two are the same pool." - ], - "accounts": [ - { - "name": "tokenProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "tokenAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "whirlpoolOne", - "isMut": true, - "isSigner": false - }, - { - "name": "whirlpoolTwo", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenOwnerAccountOneA", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenVaultOneA", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenOwnerAccountOneB", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenVaultOneB", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenOwnerAccountTwoA", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenVaultTwoA", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenOwnerAccountTwoB", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenVaultTwoB", - "isMut": true, - "isSigner": false - }, - { - "name": "tickArrayOne0", - "isMut": true, - "isSigner": false - }, - { - "name": "tickArrayOne1", - "isMut": true, - "isSigner": false - }, - { - "name": "tickArrayOne2", - "isMut": true, - "isSigner": false - }, - { - "name": "tickArrayTwo0", - "isMut": true, - "isSigner": false - }, - { - "name": "tickArrayTwo1", - "isMut": true, - "isSigner": false - }, - { - "name": "tickArrayTwo2", - "isMut": true, - "isSigner": false - }, - { - "name": "oracleOne", - "isMut": false, - "isSigner": false - }, - { - "name": "oracleTwo", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "amount", - "type": "u64" - }, - { - "name": "otherAmountThreshold", - "type": "u64" - }, - { - "name": "amountSpecifiedIsInput", - "type": "bool" - }, - { - "name": "aToBOne", - "type": "bool" - }, - { - "name": "aToBTwo", - "type": "bool" - }, - { - "name": "sqrtPriceLimitOne", - "type": "u128" - }, - { - "name": "sqrtPriceLimitTwo", - "type": "u128" - } - ] - }, - { - "name": "initializePositionBundle", - "docs": [ - "Initializes a PositionBundle account that bundles several positions.", - "A unique token will be minted to represent the position bundle in the users wallet." - ], - "accounts": [ - { - "name": "positionBundle", - "isMut": true, - "isSigner": false - }, - { - "name": "positionBundleMint", - "isMut": true, - "isSigner": true - }, - { - "name": "positionBundleTokenAccount", - "isMut": true, - "isSigner": false - }, - { - "name": "positionBundleOwner", - "isMut": false, - "isSigner": false - }, - { - "name": "funder", - "isMut": true, - "isSigner": true - }, - { - "name": "tokenProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "systemProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "rent", - "isMut": false, - "isSigner": false - }, - { - "name": "associatedTokenProgram", - "isMut": false, - "isSigner": false - } - ], - "args": [] - }, - { - "name": "initializePositionBundleWithMetadata", - "docs": [ - "Initializes a PositionBundle account that bundles several positions.", - "A unique token will be minted to represent the position bundle in the users wallet.", - "Additional Metaplex metadata is appended to identify the token." - ], - "accounts": [ - { - "name": "positionBundle", - "isMut": true, - "isSigner": false - }, - { - "name": "positionBundleMint", - "isMut": true, - "isSigner": true - }, - { - "name": "positionBundleMetadata", - "isMut": true, - "isSigner": false, - "docs": [ - "https://github.com/metaplex-foundation/metaplex-program-library/blob/773a574c4b34e5b9f248a81306ec24db064e255f/token-metadata/program/src/utils/metadata.rs#L100" - ] - }, - { - "name": "positionBundleTokenAccount", - "isMut": true, - "isSigner": false - }, - { - "name": "positionBundleOwner", - "isMut": false, - "isSigner": false - }, - { - "name": "funder", - "isMut": true, - "isSigner": true - }, - { - "name": "metadataUpdateAuth", - "isMut": false, - "isSigner": false - }, - { - "name": "tokenProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "systemProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "rent", - "isMut": false, - "isSigner": false - }, - { - "name": "associatedTokenProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "metadataProgram", - "isMut": false, - "isSigner": false - } - ], - "args": [] - }, - { - "name": "deletePositionBundle", - "docs": [ - "Delete a PositionBundle account. Burns the position bundle token in the owner's wallet.", - "", - "### Authority", - "- `position_bundle_owner` - The owner that owns the position bundle token.", - "", - "### Special Errors", - "- `PositionBundleNotDeletable` - The provided position bundle has open positions." - ], - "accounts": [ - { - "name": "positionBundle", - "isMut": true, - "isSigner": false - }, - { - "name": "positionBundleMint", - "isMut": true, - "isSigner": false - }, - { - "name": "positionBundleTokenAccount", - "isMut": true, - "isSigner": false - }, - { - "name": "positionBundleOwner", - "isMut": false, - "isSigner": true - }, - { - "name": "receiver", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenProgram", - "isMut": false, - "isSigner": false - } - ], - "args": [] - }, - { - "name": "openBundledPosition", - "docs": [ - "Open a bundled position in a Whirlpool. No new tokens are issued", - "because the owner of the position bundle becomes the owner of the position.", - "The position will start off with 0 liquidity.", - "", - "### Authority", - "- `position_bundle_authority` - authority that owns the token corresponding to this desired position bundle.", - "", - "### Parameters", - "- `bundle_index` - The bundle index that we'd like to open.", - "- `tick_lower_index` - The tick specifying the lower end of the position range.", - "- `tick_upper_index` - The tick specifying the upper end of the position range.", - "", - "#### Special Errors", - "- `InvalidBundleIndex` - If the provided bundle index is out of bounds.", - "- `InvalidTickIndex` - If a provided tick is out of bounds, out of order or not a multiple of", - "the tick-spacing in this pool." - ], - "accounts": [ - { - "name": "bundledPosition", - "isMut": true, - "isSigner": false - }, - { - "name": "positionBundle", - "isMut": true, - "isSigner": false - }, - { - "name": "positionBundleTokenAccount", - "isMut": false, - "isSigner": false - }, - { - "name": "positionBundleAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "whirlpool", - "isMut": false, - "isSigner": false - }, - { - "name": "funder", - "isMut": true, - "isSigner": true - }, - { - "name": "systemProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "rent", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "bundleIndex", - "type": "u16" - }, - { - "name": "tickLowerIndex", - "type": "i32" - }, - { - "name": "tickUpperIndex", - "type": "i32" - } - ] - }, - { - "name": "closeBundledPosition", - "docs": [ - "Close a bundled position in a Whirlpool.", - "", - "### Authority", - "- `position_bundle_authority` - authority that owns the token corresponding to this desired position bundle.", - "", - "### Parameters", - "- `bundle_index` - The bundle index that we'd like to close.", - "", - "#### Special Errors", - "- `InvalidBundleIndex` - If the provided bundle index is out of bounds.", - "- `ClosePositionNotEmpty` - The provided position account is not empty." - ], - "accounts": [ - { - "name": "bundledPosition", - "isMut": true, - "isSigner": false - }, - { - "name": "positionBundle", - "isMut": true, - "isSigner": false - }, - { - "name": "positionBundleTokenAccount", - "isMut": false, - "isSigner": false - }, - { - "name": "positionBundleAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "receiver", - "isMut": true, - "isSigner": false - } - ], - "args": [ - { - "name": "bundleIndex", - "type": "u16" - } - ] - } - ], - "accounts": [ - { - "name": "whirlpoolsConfig", - "type": { - "kind": "struct", - "fields": [ - { - "name": "feeAuthority", - "type": "publicKey" - }, - { - "name": "collectProtocolFeesAuthority", - "type": "publicKey" - }, - { - "name": "rewardEmissionsSuperAuthority", - "type": "publicKey" - }, - { - "name": "defaultProtocolFeeRate", - "type": "u16" - } - ] - } - }, - { - "name": "feeTier", - "type": { - "kind": "struct", - "fields": [ - { - "name": "whirlpoolsConfig", - "type": "publicKey" - }, - { - "name": "tickSpacing", - "type": "u16" - }, - { - "name": "defaultFeeRate", - "type": "u16" - } - ] - } - }, - { - "name": "positionBundle", - "type": { - "kind": "struct", - "fields": [ - { - "name": "positionBundleMint", - "type": "publicKey" - }, - { - "name": "positionBitmap", - "type": { - "array": [ - "u8", - 32 - ] - } - } - ] - } - }, - { - "name": "position", - "type": { - "kind": "struct", - "fields": [ - { - "name": "whirlpool", - "type": "publicKey" - }, - { - "name": "positionMint", - "type": "publicKey" - }, - { - "name": "liquidity", - "type": "u128" - }, - { - "name": "tickLowerIndex", - "type": "i32" - }, - { - "name": "tickUpperIndex", - "type": "i32" - }, - { - "name": "feeGrowthCheckpointA", - "type": "u128" - }, - { - "name": "feeOwedA", - "type": "u64" - }, - { - "name": "feeGrowthCheckpointB", - "type": "u128" - }, - { - "name": "feeOwedB", - "type": "u64" - }, - { - "name": "rewardInfos", - "type": { - "array": [ - { - "defined": "PositionRewardInfo" - }, - 3 - ] - } - } - ] - } - }, - { - "name": "tickArray", - "type": { - "kind": "struct", - "fields": [ - { - "name": "startTickIndex", - "type": "i32" - }, - { - "name": "ticks", - "type": { - "array": [ - { - "defined": "Tick" - }, - 88 - ] - } - }, - { - "name": "whirlpool", - "type": "publicKey" - } - ] - } - }, - { - "name": "whirlpool", - "type": { - "kind": "struct", - "fields": [ - { - "name": "whirlpoolsConfig", - "type": "publicKey" - }, - { - "name": "whirlpoolBump", - "type": { - "array": [ - "u8", - 1 - ] - } - }, - { - "name": "tickSpacing", - "type": "u16" - }, - { - "name": "tickSpacingSeed", - "type": { - "array": [ - "u8", - 2 - ] - } - }, - { - "name": "feeRate", - "type": "u16" - }, - { - "name": "protocolFeeRate", - "type": "u16" - }, - { - "name": "liquidity", - "type": "u128" - }, - { - "name": "sqrtPrice", - "type": "u128" - }, - { - "name": "tickCurrentIndex", - "type": "i32" - }, - { - "name": "protocolFeeOwedA", - "type": "u64" - }, - { - "name": "protocolFeeOwedB", - "type": "u64" - }, - { - "name": "tokenMintA", - "type": "publicKey" - }, - { - "name": "tokenVaultA", - "type": "publicKey" - }, - { - "name": "feeGrowthGlobalA", - "type": "u128" - }, - { - "name": "tokenMintB", - "type": "publicKey" - }, - { - "name": "tokenVaultB", - "type": "publicKey" - }, - { - "name": "feeGrowthGlobalB", - "type": "u128" - }, - { - "name": "rewardLastUpdatedTimestamp", - "type": "u64" - }, - { - "name": "rewardInfos", - "type": { - "array": [ - { - "defined": "WhirlpoolRewardInfo" - }, - 3 - ] - } - } - ] - } - } - ], - "types": [ - { - "name": "OpenPositionBumps", - "type": { - "kind": "struct", - "fields": [ - { - "name": "positionBump", - "type": "u8" - } - ] - } - }, - { - "name": "OpenPositionWithMetadataBumps", - "type": { - "kind": "struct", - "fields": [ - { - "name": "positionBump", - "type": "u8" - }, - { - "name": "metadataBump", - "type": "u8" - } - ] - } - }, - { - "name": "PositionRewardInfo", - "type": { - "kind": "struct", - "fields": [ - { - "name": "growthInsideCheckpoint", - "type": "u128" - }, - { - "name": "amountOwed", - "type": "u64" - } - ] - } - }, - { - "name": "Tick", - "type": { - "kind": "struct", - "fields": [ - { - "name": "initialized", - "type": "bool" - }, - { - "name": "liquidityNet", - "type": "i128" - }, - { - "name": "liquidityGross", - "type": "u128" - }, - { - "name": "feeGrowthOutsideA", - "type": "u128" - }, - { - "name": "feeGrowthOutsideB", - "type": "u128" - }, - { - "name": "rewardGrowthsOutside", - "type": { - "array": [ - "u128", - 3 - ] - } - } - ] - } - }, - { - "name": "WhirlpoolRewardInfo", - "docs": [ - "Stores the state relevant for tracking liquidity mining rewards at the `Whirlpool` level.", - "These values are used in conjunction with `PositionRewardInfo`, `Tick.reward_growths_outside`,", - "and `Whirlpool.reward_last_updated_timestamp` to determine how many rewards are earned by open", - "positions." - ], - "type": { - "kind": "struct", - "fields": [ - { - "name": "mint", - "docs": [ - "Reward token mint." - ], - "type": "publicKey" - }, - { - "name": "vault", - "docs": [ - "Reward vault token account." - ], - "type": "publicKey" - }, - { - "name": "authority", - "docs": [ - "Authority account that has permission to initialize the reward and set emissions." - ], - "type": "publicKey" - }, - { - "name": "emissionsPerSecondX64", - "docs": [ - "Q64.64 number that indicates how many tokens per second are earned per unit of liquidity." - ], - "type": "u128" - }, - { - "name": "growthGlobalX64", - "docs": [ - "Q64.64 number that tracks the total tokens earned per unit of liquidity since the reward", - "emissions were turned on." - ], - "type": "u128" - } - ] - } - }, - { - "name": "WhirlpoolBumps", - "type": { - "kind": "struct", - "fields": [ - { - "name": "whirlpoolBump", - "type": "u8" - } - ] - } - }, - { - "name": "CurrIndex", - "type": { - "kind": "enum", - "variants": [ - { - "name": "Below" - }, - { - "name": "Inside" - }, - { - "name": "Above" - } - ] - } - }, - { - "name": "TickLabel", - "type": { - "kind": "enum", - "variants": [ - { - "name": "Upper" - }, - { - "name": "Lower" - } - ] - } - }, - { - "name": "Direction", - "type": { - "kind": "enum", - "variants": [ - { - "name": "Left" - }, - { - "name": "Right" - } - ] - } - } - ], - "errors": [ - { - "code": 6000, - "name": "InvalidEnum", - "msg": "Enum value could not be converted" - }, - { - "code": 6001, - "name": "InvalidStartTick", - "msg": "Invalid start tick index provided." - }, - { - "code": 6002, - "name": "TickArrayExistInPool", - "msg": "Tick-array already exists in this whirlpool" - }, - { - "code": 6003, - "name": "TickArrayIndexOutofBounds", - "msg": "Attempt to search for a tick-array failed" - }, - { - "code": 6004, - "name": "InvalidTickSpacing", - "msg": "Tick-spacing is not supported" - }, - { - "code": 6005, - "name": "ClosePositionNotEmpty", - "msg": "Position is not empty It cannot be closed" - }, - { - "code": 6006, - "name": "DivideByZero", - "msg": "Unable to divide by zero" - }, - { - "code": 6007, - "name": "NumberCastError", - "msg": "Unable to cast number into BigInt" - }, - { - "code": 6008, - "name": "NumberDownCastError", - "msg": "Unable to down cast number" - }, - { - "code": 6009, - "name": "TickNotFound", - "msg": "Tick not found within tick array" - }, - { - "code": 6010, - "name": "InvalidTickIndex", - "msg": "Provided tick index is either out of bounds or uninitializable" - }, - { - "code": 6011, - "name": "SqrtPriceOutOfBounds", - "msg": "Provided sqrt price out of bounds" - }, - { - "code": 6012, - "name": "LiquidityZero", - "msg": "Liquidity amount must be greater than zero" - }, - { - "code": 6013, - "name": "LiquidityTooHigh", - "msg": "Liquidity amount must be less than i64::MAX" - }, - { - "code": 6014, - "name": "LiquidityOverflow", - "msg": "Liquidity overflow" - }, - { - "code": 6015, - "name": "LiquidityUnderflow", - "msg": "Liquidity underflow" - }, - { - "code": 6016, - "name": "LiquidityNetError", - "msg": "Tick liquidity net underflowed or overflowed" - }, - { - "code": 6017, - "name": "TokenMaxExceeded", - "msg": "Exceeded token max" - }, - { - "code": 6018, - "name": "TokenMinSubceeded", - "msg": "Did not meet token min" - }, - { - "code": 6019, - "name": "MissingOrInvalidDelegate", - "msg": "Position token account has a missing or invalid delegate" - }, - { - "code": 6020, - "name": "InvalidPositionTokenAmount", - "msg": "Position token amount must be 1" - }, - { - "code": 6021, - "name": "InvalidTimestampConversion", - "msg": "Timestamp should be convertible from i64 to u64" - }, - { - "code": 6022, - "name": "InvalidTimestamp", - "msg": "Timestamp should be greater than the last updated timestamp" - }, - { - "code": 6023, - "name": "InvalidTickArraySequence", - "msg": "Invalid tick array sequence provided for instruction." - }, - { - "code": 6024, - "name": "InvalidTokenMintOrder", - "msg": "Token Mint in wrong order" - }, - { - "code": 6025, - "name": "RewardNotInitialized", - "msg": "Reward not initialized" - }, - { - "code": 6026, - "name": "InvalidRewardIndex", - "msg": "Invalid reward index" - }, - { - "code": 6027, - "name": "RewardVaultAmountInsufficient", - "msg": "Reward vault requires amount to support emissions for at least one day" - }, - { - "code": 6028, - "name": "FeeRateMaxExceeded", - "msg": "Exceeded max fee rate" - }, - { - "code": 6029, - "name": "ProtocolFeeRateMaxExceeded", - "msg": "Exceeded max protocol fee rate" - }, - { - "code": 6030, - "name": "MultiplicationShiftRightOverflow", - "msg": "Multiplication with shift right overflow" - }, - { - "code": 6031, - "name": "MulDivOverflow", - "msg": "Muldiv overflow" - }, - { - "code": 6032, - "name": "MulDivInvalidInput", - "msg": "Invalid div_u256 input" - }, - { - "code": 6033, - "name": "MultiplicationOverflow", - "msg": "Multiplication overflow" - }, - { - "code": 6034, - "name": "InvalidSqrtPriceLimitDirection", - "msg": "Provided SqrtPriceLimit not in the same direction as the swap." - }, - { - "code": 6035, - "name": "ZeroTradableAmount", - "msg": "There are no tradable amount to swap." - }, - { - "code": 6036, - "name": "AmountOutBelowMinimum", - "msg": "Amount out below minimum threshold" - }, - { - "code": 6037, - "name": "AmountInAboveMaximum", - "msg": "Amount in above maximum threshold" - }, - { - "code": 6038, - "name": "TickArraySequenceInvalidIndex", - "msg": "Invalid index for tick array sequence" - }, - { - "code": 6039, - "name": "AmountCalcOverflow", - "msg": "Amount calculated overflows" - }, - { - "code": 6040, - "name": "AmountRemainingOverflow", - "msg": "Amount remaining overflows" - }, - { - "code": 6041, - "name": "InvalidIntermediaryMint", - "msg": "Invalid intermediary mint" - }, - { - "code": 6042, - "name": "DuplicateTwoHopPool", - "msg": "Duplicate two hop pool" - }, - { - "code": 6043, - "name": "InvalidBundleIndex", - "msg": "Bundle index is out of bounds" - }, - { - "code": 6044, - "name": "BundledPositionAlreadyOpened", - "msg": "Position has already been opened" - }, - { - "code": 6045, - "name": "BundledPositionAlreadyClosed", - "msg": "Position has already been closed" - }, - { - "code": 6046, - "name": "PositionBundleNotDeletable", - "msg": "Unable to delete PositionBundle with open positions" - } - ] -}; diff --git a/sdk/src/context.ts b/sdk/src/context.ts deleted file mode 100644 index 01313a5..0000000 --- a/sdk/src/context.ts +++ /dev/null @@ -1,134 +0,0 @@ -import { AnchorProvider, Idl, Program } from "@coral-xyz/anchor"; -import { - BuildOptions, - LookupTableFetcher, - TransactionBuilderOptions, - Wallet, - WrappedSolAccountCreateMethod, -} from "@orca-so/common-sdk"; -import { Commitment, Connection, PublicKey, SendOptions } from "@solana/web3.js"; -import { Whirlpool } from "./artifacts/whirlpool"; -import WhirlpoolIDL from "./artifacts/whirlpool.json"; -import { WhirlpoolAccountFetcherInterface, buildDefaultAccountFetcher } from "./network/public/"; -import { contextOptionsToBuilderOptions } from "./utils/txn-utils"; - -/** - * Default settings used when interacting with transactions. - * @category Core - */ -export type WhirlpoolContextOpts = { - userDefaultBuildOptions?: Partial; - userDefaultSendOptions?: Partial; - userDefaultConfirmCommitment?: Commitment; - accountResolverOptions?: AccountResolverOptions; -}; - -/** - * Default settings used when resolving token accounts. - * @category Core - */ -export type AccountResolverOptions = { - createWrappedSolAccountMethod: WrappedSolAccountCreateMethod; - allowPDAOwnerAddress: boolean; -}; - -const DEFAULT_ACCOUNT_RESOLVER_OPTS: AccountResolverOptions = { - createWrappedSolAccountMethod: "keypair", - allowPDAOwnerAddress: false, -}; - -/** - * Context for storing environment classes and objects for usage throughout the SDK - * @category Core - */ -export class WhirlpoolContext { - readonly connection: Connection; - readonly wallet: Wallet; - readonly program: Program; - readonly provider: AnchorProvider; - readonly fetcher: WhirlpoolAccountFetcherInterface; - readonly lookupTableFetcher: LookupTableFetcher | undefined; - readonly opts: WhirlpoolContextOpts; - readonly txBuilderOpts: TransactionBuilderOptions | undefined; - readonly accountResolverOpts: AccountResolverOptions; - - public static from( - connection: Connection, - wallet: Wallet, - programId: PublicKey, - fetcher: WhirlpoolAccountFetcherInterface = buildDefaultAccountFetcher(connection), - lookupTableFetcher?: LookupTableFetcher, - opts: WhirlpoolContextOpts = {} - ): WhirlpoolContext { - const anchorProvider = new AnchorProvider(connection, wallet, { - commitment: opts.userDefaultConfirmCommitment || "confirmed", - preflightCommitment: opts.userDefaultConfirmCommitment || "confirmed", - }); - const program = new Program(WhirlpoolIDL as Idl, programId, anchorProvider); - return new WhirlpoolContext( - anchorProvider, - anchorProvider.wallet, - program, - fetcher, - lookupTableFetcher, - opts - ); - } - - public static fromWorkspace( - provider: AnchorProvider, - program: Program, - fetcher: WhirlpoolAccountFetcherInterface = buildDefaultAccountFetcher(provider.connection), - lookupTableFetcher?: LookupTableFetcher, - opts: WhirlpoolContextOpts = {} - ) { - return new WhirlpoolContext( - provider, - provider.wallet, - program, - fetcher, - lookupTableFetcher, - opts - ); - } - - public static withProvider( - provider: AnchorProvider, - programId: PublicKey, - fetcher: WhirlpoolAccountFetcherInterface = buildDefaultAccountFetcher(provider.connection), - lookupTableFetcher?: LookupTableFetcher, - opts: WhirlpoolContextOpts = {} - ): WhirlpoolContext { - const program = new Program(WhirlpoolIDL as Idl, programId, provider); - return new WhirlpoolContext( - provider, - provider.wallet, - program, - fetcher, - lookupTableFetcher, - opts - ); - } - - public constructor( - provider: AnchorProvider, - wallet: Wallet, - program: Program, - fetcher: WhirlpoolAccountFetcherInterface, - lookupTableFetcher?: LookupTableFetcher, - opts: WhirlpoolContextOpts = {} - ) { - this.connection = provider.connection; - this.wallet = wallet; - // It's a hack but it works on Anchor workspace *shrug* - this.program = program as unknown as Program; - this.provider = provider; - this.fetcher = fetcher; - this.lookupTableFetcher = lookupTableFetcher; - this.opts = opts; - this.txBuilderOpts = contextOptionsToBuilderOptions(this.opts); - this.accountResolverOpts = opts.accountResolverOptions ?? DEFAULT_ACCOUNT_RESOLVER_OPTS; - } - - // TODO: Add another factory method to build from on-chain IDL -} diff --git a/sdk/src/errors/errors.ts b/sdk/src/errors/errors.ts deleted file mode 100644 index 9fe5365..0000000 --- a/sdk/src/errors/errors.ts +++ /dev/null @@ -1,51 +0,0 @@ -export enum MathErrorCode { - MultiplicationOverflow = `MultiplicationOverflow`, - MulDivOverflow = `MulDivOverflow`, - MultiplicationShiftRightOverflow = `MultiplicationShiftRightOverflow`, - DivideByZero = `DivideByZero`, -} - -export enum TokenErrorCode { - TokenMaxExceeded = `TokenMaxExceeded`, - TokenMinSubceeded = `TokenMinSubceeded`, -} - -export enum SwapErrorCode { - InvalidDevFeePercentage = `InvalidDevFeePercentage`, - InvalidSqrtPriceLimitDirection = `InvalidSqrtPriceLimitDirection`, - SqrtPriceOutOfBounds = `SqrtPriceOutOfBounds`, - ZeroTradableAmount = `ZeroTradableAmount`, - AmountOutBelowMinimum = `AmountOutBelowMinimum`, - AmountInAboveMaximum = `AmountInAboveMaximum`, - TickArrayCrossingAboveMax = `TickArrayCrossingAboveMax`, - TickArrayIndexNotInitialized = `TickArrayIndexNotInitialized`, - TickArraySequenceInvalid = `TickArraySequenceInvalid`, -} - -export enum RouteQueryErrorCode { - RouteDoesNotExist = "RouteDoesNotExist", - TradeAmountTooHigh = "TradeAmountTooHigh", - ZeroInputAmount = "ZeroInputAmount", - General = "General", -} - -export type WhirlpoolsErrorCode = - | TokenErrorCode - | SwapErrorCode - | MathErrorCode - | RouteQueryErrorCode; - -export class WhirlpoolsError extends Error { - message: string; - errorCode?: WhirlpoolsErrorCode; - constructor(message: string, errorCode?: WhirlpoolsErrorCode, stack?: string) { - super(message); - this.message = message; - this.errorCode = errorCode; - this.stack = stack; - } - - public static isWhirlpoolsErrorCode(e: any, code: WhirlpoolsErrorCode): boolean { - return e instanceof WhirlpoolsError && e.errorCode === code; - } -} diff --git a/sdk/src/impl/position-impl.ts b/sdk/src/impl/position-impl.ts deleted file mode 100644 index 2f4a345..0000000 --- a/sdk/src/impl/position-impl.ts +++ /dev/null @@ -1,530 +0,0 @@ -import { Address } from "@coral-xyz/anchor"; -import { - AddressUtil, - Instruction, - TokenUtil, - TransactionBuilder, - ZERO, - resolveOrCreateATAs, -} from "@orca-so/common-sdk"; -import { NATIVE_MINT, getAssociatedTokenAddressSync } from "@solana/spl-token"; -import { PublicKey } from "@solana/web3.js"; -import invariant from "tiny-invariant"; -import { WhirlpoolContext } from "../context"; -import { - DecreaseLiquidityInput, - IncreaseLiquidityInput, - collectFeesIx, - collectRewardIx, - decreaseLiquidityIx, - increaseLiquidityIx, - updateFeesAndRewardsIx, -} from "../instructions"; -import { - IGNORE_CACHE, - PREFER_CACHE, - WhirlpoolAccountFetchOptions, -} from "../network/public/fetcher"; -import { PositionData, TickArrayData, TickData, WhirlpoolData } from "../types/public"; -import { getTickArrayDataForPosition } from "../utils/builder/position-builder-util"; -import { PDAUtil, PoolUtil, TickArrayUtil, TickUtil } from "../utils/public"; -import { - TokenMintTypes, - getTokenMintsFromWhirlpools, - resolveAtaForMints, -} from "../utils/whirlpool-ata-utils"; -import { Position } from "../whirlpool-client"; - -export class PositionImpl implements Position { - private data: PositionData; - private whirlpoolData: WhirlpoolData; - private lowerTickArrayData: TickArrayData; - private upperTickArrayData: TickArrayData; - constructor( - readonly ctx: WhirlpoolContext, - readonly address: PublicKey, - data: PositionData, - whirlpoolData: WhirlpoolData, - lowerTickArrayData: TickArrayData, - upperTickArrayData: TickArrayData - ) { - this.data = data; - this.whirlpoolData = whirlpoolData; - this.lowerTickArrayData = lowerTickArrayData; - this.upperTickArrayData = upperTickArrayData; - } - - getAddress(): PublicKey { - return this.address; - } - - getData(): PositionData { - return this.data; - } - - getWhirlpoolData(): WhirlpoolData { - return this.whirlpoolData; - } - - getLowerTickData(): TickData { - return TickArrayUtil.getTickFromArray( - this.lowerTickArrayData, - this.data.tickLowerIndex, - this.whirlpoolData.tickSpacing - ); - } - - getUpperTickData(): TickData { - return TickArrayUtil.getTickFromArray( - this.upperTickArrayData, - this.data.tickUpperIndex, - this.whirlpoolData.tickSpacing - ); - } - - async refreshData() { - await this.refresh(); - return this.data; - } - - async increaseLiquidity( - liquidityInput: IncreaseLiquidityInput, - resolveATA = true, - sourceWallet?: Address, - positionWallet?: Address, - ataPayer?: Address - ) { - const sourceWalletKey = sourceWallet - ? AddressUtil.toPubKey(sourceWallet) - : this.ctx.wallet.publicKey; - const positionWalletKey = positionWallet - ? AddressUtil.toPubKey(positionWallet) - : this.ctx.wallet.publicKey; - const ataPayerKey = ataPayer ? AddressUtil.toPubKey(ataPayer) : this.ctx.wallet.publicKey; - - const whirlpool = await this.ctx.fetcher.getPool(this.data.whirlpool, IGNORE_CACHE); - if (!whirlpool) { - throw new Error("Unable to fetch whirlpool for this position."); - } - - const txBuilder = new TransactionBuilder( - this.ctx.provider.connection, - this.ctx.provider.wallet, - this.ctx.txBuilderOpts - ); - - let tokenOwnerAccountA: PublicKey; - let tokenOwnerAccountB: PublicKey; - - if (resolveATA) { - const [ataA, ataB] = await resolveOrCreateATAs( - this.ctx.connection, - sourceWalletKey, - [ - { tokenMint: whirlpool.tokenMintA, wrappedSolAmountIn: liquidityInput.tokenMaxA }, - { tokenMint: whirlpool.tokenMintB, wrappedSolAmountIn: liquidityInput.tokenMaxB }, - ], - () => this.ctx.fetcher.getAccountRentExempt(), - ataPayerKey, - undefined, // use default - this.ctx.accountResolverOpts.allowPDAOwnerAddress, - this.ctx.accountResolverOpts.createWrappedSolAccountMethod - ); - const { address: ataAddrA, ...tokenOwnerAccountAIx } = ataA!; - const { address: ataAddrB, ...tokenOwnerAccountBIx } = ataB!; - tokenOwnerAccountA = ataAddrA; - tokenOwnerAccountB = ataAddrB; - txBuilder.addInstruction(tokenOwnerAccountAIx); - txBuilder.addInstruction(tokenOwnerAccountBIx); - } else { - tokenOwnerAccountA = getAssociatedTokenAddressSync( - whirlpool.tokenMintA, - sourceWalletKey, - this.ctx.accountResolverOpts.allowPDAOwnerAddress - ); - tokenOwnerAccountB = getAssociatedTokenAddressSync( - whirlpool.tokenMintB, - sourceWalletKey, - this.ctx.accountResolverOpts.allowPDAOwnerAddress - ); - } - const positionTokenAccount = getAssociatedTokenAddressSync( - this.data.positionMint, - positionWalletKey, - this.ctx.accountResolverOpts.allowPDAOwnerAddress - ); - - const increaseIx = increaseLiquidityIx(this.ctx.program, { - ...liquidityInput, - whirlpool: this.data.whirlpool, - position: this.address, - positionTokenAccount, - tokenOwnerAccountA, - tokenOwnerAccountB, - tokenVaultA: whirlpool.tokenVaultA, - tokenVaultB: whirlpool.tokenVaultB, - tickArrayLower: PDAUtil.getTickArray( - this.ctx.program.programId, - this.data.whirlpool, - TickUtil.getStartTickIndex(this.data.tickLowerIndex, whirlpool.tickSpacing) - ).publicKey, - tickArrayUpper: PDAUtil.getTickArray( - this.ctx.program.programId, - this.data.whirlpool, - TickUtil.getStartTickIndex(this.data.tickUpperIndex, whirlpool.tickSpacing) - ).publicKey, - positionAuthority: positionWalletKey, - }); - txBuilder.addInstruction(increaseIx); - return txBuilder; - } - - async decreaseLiquidity( - liquidityInput: DecreaseLiquidityInput, - resolveATA = true, - sourceWallet?: Address, - positionWallet?: Address, - ataPayer?: Address - ) { - const sourceWalletKey = sourceWallet - ? AddressUtil.toPubKey(sourceWallet) - : this.ctx.wallet.publicKey; - const positionWalletKey = positionWallet - ? AddressUtil.toPubKey(positionWallet) - : this.ctx.wallet.publicKey; - const ataPayerKey = ataPayer ? AddressUtil.toPubKey(ataPayer) : this.ctx.wallet.publicKey; - const whirlpool = await this.ctx.fetcher.getPool(this.data.whirlpool, IGNORE_CACHE); - - if (!whirlpool) { - throw new Error("Unable to fetch whirlpool for this position."); - } - - const txBuilder = new TransactionBuilder( - this.ctx.provider.connection, - this.ctx.provider.wallet, - this.ctx.txBuilderOpts - ); - let tokenOwnerAccountA: PublicKey; - let tokenOwnerAccountB: PublicKey; - - if (resolveATA) { - const [ataA, ataB] = await resolveOrCreateATAs( - this.ctx.connection, - sourceWalletKey, - [{ tokenMint: whirlpool.tokenMintA }, { tokenMint: whirlpool.tokenMintB }], - () => this.ctx.fetcher.getAccountRentExempt(), - ataPayerKey, - undefined, // use default - this.ctx.accountResolverOpts.allowPDAOwnerAddress, - this.ctx.accountResolverOpts.createWrappedSolAccountMethod - ); - const { address: ataAddrA, ...tokenOwnerAccountAIx } = ataA!; - const { address: ataAddrB, ...tokenOwnerAccountBIx } = ataB!; - tokenOwnerAccountA = ataAddrA; - tokenOwnerAccountB = ataAddrB; - txBuilder.addInstruction(tokenOwnerAccountAIx); - txBuilder.addInstruction(tokenOwnerAccountBIx); - } else { - tokenOwnerAccountA = getAssociatedTokenAddressSync( - whirlpool.tokenMintA, - sourceWalletKey, - this.ctx.accountResolverOpts.allowPDAOwnerAddress - ); - tokenOwnerAccountB = getAssociatedTokenAddressSync( - whirlpool.tokenMintB, - sourceWalletKey, - this.ctx.accountResolverOpts.allowPDAOwnerAddress - ); - } - - const decreaseIx = decreaseLiquidityIx(this.ctx.program, { - ...liquidityInput, - whirlpool: this.data.whirlpool, - position: this.address, - positionTokenAccount: getAssociatedTokenAddressSync( - this.data.positionMint, - positionWalletKey, - this.ctx.accountResolverOpts.allowPDAOwnerAddress - ), - tokenOwnerAccountA, - tokenOwnerAccountB, - tokenVaultA: whirlpool.tokenVaultA, - tokenVaultB: whirlpool.tokenVaultB, - tickArrayLower: PDAUtil.getTickArray( - this.ctx.program.programId, - this.data.whirlpool, - TickUtil.getStartTickIndex(this.data.tickLowerIndex, whirlpool.tickSpacing) - ).publicKey, - tickArrayUpper: PDAUtil.getTickArray( - this.ctx.program.programId, - this.data.whirlpool, - TickUtil.getStartTickIndex(this.data.tickUpperIndex, whirlpool.tickSpacing) - ).publicKey, - positionAuthority: positionWalletKey, - }); - txBuilder.addInstruction(decreaseIx); - return txBuilder; - } - - async collectFees( - updateFeesAndRewards: boolean = true, - ownerTokenAccountMap?: Partial>, - destinationWallet?: Address, - positionWallet?: Address, - ataPayer?: Address, - opts: WhirlpoolAccountFetchOptions = PREFER_CACHE - ): Promise { - const [destinationWalletKey, positionWalletKey, ataPayerKey] = AddressUtil.toPubKeys([ - destinationWallet ?? this.ctx.wallet.publicKey, - positionWallet ?? this.ctx.wallet.publicKey, - ataPayer ?? this.ctx.wallet.publicKey, - ]); - - const whirlpool = await this.ctx.fetcher.getPool(this.data.whirlpool, opts); - if (!whirlpool) { - throw new Error( - `Unable to fetch whirlpool (${this.data.whirlpool}) for this position (${this.address}).` - ); - } - - let txBuilder = new TransactionBuilder( - this.ctx.provider.connection, - this.ctx.provider.wallet, - this.ctx.txBuilderOpts - ); - - const accountExemption = await this.ctx.fetcher.getAccountRentExempt(); - - let ataMap = { ...ownerTokenAccountMap }; - - if (!ownerTokenAccountMap) { - const affliatedMints = getTokenMintsFromWhirlpools([whirlpool], TokenMintTypes.POOL_ONLY); - const { ataTokenAddresses: affliatedTokenAtaMap, resolveAtaIxs } = await resolveAtaForMints( - this.ctx, - { - mints: affliatedMints.mintMap, - accountExemption, - receiver: destinationWalletKey, - payer: ataPayerKey, - } - ); - - txBuilder.addInstructions(resolveAtaIxs); - - if (affliatedMints.hasNativeMint) { - let { address: wSOLAta, ...resolveWSolIx } = - TokenUtil.createWrappedNativeAccountInstruction( - destinationWalletKey, - ZERO, - accountExemption, - ataPayerKey, - destinationWalletKey, - this.ctx.accountResolverOpts.createWrappedSolAccountMethod - ); - affliatedTokenAtaMap[NATIVE_MINT.toBase58()] = wSOLAta; - txBuilder.addInstruction(resolveWSolIx); - } - - ataMap = { ...affliatedTokenAtaMap }; - } - - const tokenOwnerAccountA = ataMap[whirlpool.tokenMintA.toBase58()]; - invariant( - !!tokenOwnerAccountA, - `No owner token account provided for wallet ${destinationWalletKey.toBase58()} for token A ${whirlpool.tokenMintA.toBase58()} ` - ); - const tokenOwnerAccountB = ataMap[whirlpool.tokenMintB.toBase58()]; - invariant( - !!tokenOwnerAccountB, - `No owner token account provided for wallet ${destinationWalletKey.toBase58()} for token B ${whirlpool.tokenMintB.toBase58()} ` - ); - - const positionTokenAccount = getAssociatedTokenAddressSync( - this.data.positionMint, - positionWalletKey, - this.ctx.accountResolverOpts.allowPDAOwnerAddress - ); - - if (updateFeesAndRewards && !this.data.liquidity.isZero()) { - const updateIx = await this.updateFeesAndRewards(); - txBuilder.addInstruction(updateIx); - } - - const ix = collectFeesIx(this.ctx.program, { - whirlpool: this.data.whirlpool, - position: this.address, - positionTokenAccount, - tokenOwnerAccountA: AddressUtil.toPubKey(tokenOwnerAccountA), - tokenOwnerAccountB: AddressUtil.toPubKey(tokenOwnerAccountB), - tokenVaultA: whirlpool.tokenVaultA, - tokenVaultB: whirlpool.tokenVaultB, - positionAuthority: positionWalletKey, - }); - - txBuilder.addInstruction(ix); - - return txBuilder; - } - - async collectRewards( - rewardsToCollect?: Address[], - updateFeesAndRewards: boolean = true, - ownerTokenAccountMap?: Partial>, - destinationWallet?: Address, - positionWallet?: Address, - ataPayer?: Address, - opts: WhirlpoolAccountFetchOptions = IGNORE_CACHE - ): Promise { - const [destinationWalletKey, positionWalletKey, ataPayerKey] = AddressUtil.toPubKeys([ - destinationWallet ?? this.ctx.wallet.publicKey, - positionWallet ?? this.ctx.wallet.publicKey, - ataPayer ?? this.ctx.wallet.publicKey, - ]); - - const whirlpool = await this.ctx.fetcher.getPool(this.data.whirlpool, opts); - if (!whirlpool) { - throw new Error( - `Unable to fetch whirlpool(${this.data.whirlpool}) for this position(${this.address}).` - ); - } - - const initializedRewards = whirlpool.rewardInfos.filter((info) => - PoolUtil.isRewardInitialized(info) - ); - - const txBuilder = new TransactionBuilder( - this.ctx.provider.connection, - this.ctx.provider.wallet, - this.ctx.txBuilderOpts - ); - - const accountExemption = await this.ctx.fetcher.getAccountRentExempt(); - - let ataMap = { ...ownerTokenAccountMap }; - if (!ownerTokenAccountMap) { - const rewardMints = getTokenMintsFromWhirlpools([whirlpool], TokenMintTypes.REWARD_ONLY); - const { ataTokenAddresses: affliatedTokenAtaMap, resolveAtaIxs } = await resolveAtaForMints( - this.ctx, - { - mints: rewardMints.mintMap, - accountExemption, - receiver: destinationWalletKey, - payer: ataPayerKey, - } - ); - - if (rewardMints.hasNativeMint) { - let { address: wSOLAta, ...resolveWSolIx } = - TokenUtil.createWrappedNativeAccountInstruction( - destinationWalletKey, - ZERO, - accountExemption, - ataPayerKey, - destinationWalletKey, - this.ctx.accountResolverOpts.createWrappedSolAccountMethod - ); - affliatedTokenAtaMap[NATIVE_MINT.toBase58()] = wSOLAta; - txBuilder.addInstruction(resolveWSolIx); - } - - txBuilder.addInstructions(resolveAtaIxs); - - ataMap = { ...affliatedTokenAtaMap }; - } - - const positionTokenAccount = getAssociatedTokenAddressSync( - this.data.positionMint, - positionWalletKey, - this.ctx.accountResolverOpts.allowPDAOwnerAddress - ); - if (updateFeesAndRewards && !this.data.liquidity.isZero()) { - const updateIx = await this.updateFeesAndRewards(); - txBuilder.addInstruction(updateIx); - } - - initializedRewards.forEach((info, index) => { - if ( - rewardsToCollect && - !rewardsToCollect.some((r) => r.toString() === info.mint.toBase58()) - ) { - // If rewardsToCollect is specified and this reward is not in it, - // don't include collectIX for that in TX - return; - } - - const rewardOwnerAccount = ataMap[info.mint.toBase58()]; - invariant( - !!rewardOwnerAccount, - `No owner token account provided for wallet ${destinationWalletKey.toBase58()} for reward ${index} token ${info.mint.toBase58()} ` - ); - - const ix = collectRewardIx(this.ctx.program, { - whirlpool: this.data.whirlpool, - position: this.address, - positionTokenAccount, - rewardIndex: index, - rewardOwnerAccount: AddressUtil.toPubKey(rewardOwnerAccount), - rewardVault: info.vault, - positionAuthority: positionWalletKey, - }); - - txBuilder.addInstruction(ix); - }); - - return txBuilder; - } - - private async refresh() { - const positionAccount = await this.ctx.fetcher.getPosition(this.address, IGNORE_CACHE); - if (!!positionAccount) { - this.data = positionAccount; - } - const whirlpoolAccount = await this.ctx.fetcher.getPool(this.data.whirlpool, IGNORE_CACHE); - if (!!whirlpoolAccount) { - this.whirlpoolData = whirlpoolAccount; - } - - const [lowerTickArray, upperTickArray] = await getTickArrayDataForPosition( - this.ctx, - this.data, - this.whirlpoolData, - IGNORE_CACHE - ); - if (lowerTickArray) { - this.lowerTickArrayData = lowerTickArray; - } - if (upperTickArray) { - this.upperTickArrayData = upperTickArray; - } - } - - private async updateFeesAndRewards(): Promise { - const whirlpool = await this.ctx.fetcher.getPool(this.data.whirlpool); - if (!whirlpool) { - throw new Error( - `Unable to fetch whirlpool(${this.data.whirlpool}) for this position(${this.address}).` - ); - } - - const [tickArrayLowerPda, tickArrayUpperPda] = [ - this.data.tickLowerIndex, - this.data.tickUpperIndex, - ].map((tickIndex) => - PDAUtil.getTickArrayFromTickIndex( - tickIndex, - whirlpool.tickSpacing, - this.data.whirlpool, - this.ctx.program.programId - ) - ); - - const updateIx = updateFeesAndRewardsIx(this.ctx.program, { - whirlpool: this.data.whirlpool, - position: this.address, - tickArrayLower: tickArrayLowerPda.publicKey, - tickArrayUpper: tickArrayUpperPda.publicKey, - }); - - return updateIx; - } -} diff --git a/sdk/src/impl/util.ts b/sdk/src/impl/util.ts deleted file mode 100644 index 081896b..0000000 --- a/sdk/src/impl/util.ts +++ /dev/null @@ -1,80 +0,0 @@ -import BN from "bn.js"; -import { PoolUtil, TokenInfo } from ".."; -import { - WhirlpoolAccountFetchOptions, - WhirlpoolAccountFetcherInterface, -} from "../network/public/fetcher"; -import { - TokenAccountInfo, - WhirlpoolData, - WhirlpoolRewardInfo, - WhirlpoolRewardInfoData, -} from "../types/public"; - -export async function getTokenMintInfos( - fetcher: WhirlpoolAccountFetcherInterface, - data: WhirlpoolData, - opts?: WhirlpoolAccountFetchOptions -): Promise { - const mintA = data.tokenMintA; - const infoA = await fetcher.getMintInfo(mintA, opts); - if (!infoA) { - throw new Error(`Unable to fetch MintInfo for mint - ${mintA}`); - } - const mintB = data.tokenMintB; - const infoB = await fetcher.getMintInfo(mintB, opts); - if (!infoB) { - throw new Error(`Unable to fetch MintInfo for mint - ${mintB}`); - } - return [ - { mint: mintA, ...infoA }, - { mint: mintB, ...infoB }, - ]; -} - -export async function getRewardInfos( - fetcher: WhirlpoolAccountFetcherInterface, - data: WhirlpoolData, - opts?: WhirlpoolAccountFetchOptions -): Promise { - const rewardInfos: WhirlpoolRewardInfo[] = []; - for (const rewardInfo of data.rewardInfos) { - rewardInfos.push(await getRewardInfo(fetcher, rewardInfo, opts)); - } - return rewardInfos; -} - -async function getRewardInfo( - fetcher: WhirlpoolAccountFetcherInterface, - data: WhirlpoolRewardInfoData, - opts?: WhirlpoolAccountFetchOptions -): Promise { - const rewardInfo = { ...data, initialized: false, vaultAmount: new BN(0) }; - if (PoolUtil.isRewardInitialized(data)) { - const vaultInfo = await fetcher.getTokenInfo(data.vault, opts); - if (!vaultInfo) { - throw new Error(`Unable to fetch TokenAccountInfo for vault - ${data.vault}`); - } - rewardInfo.initialized = true; - rewardInfo.vaultAmount = new BN(vaultInfo.amount.toString()); - } - return rewardInfo; -} - -export async function getTokenVaultAccountInfos( - fetcher: WhirlpoolAccountFetcherInterface, - data: WhirlpoolData, - opts?: WhirlpoolAccountFetchOptions -): Promise { - const vaultA = data.tokenVaultA; - const vaultInfoA = await fetcher.getTokenInfo(vaultA, opts); - if (!vaultInfoA) { - throw new Error(`Unable to fetch TokenAccountInfo for vault - ${vaultA}`); - } - const vaultB = data.tokenVaultB; - const vaultInfoB = await fetcher.getTokenInfo(vaultB, opts); - if (!vaultInfoB) { - throw new Error(`Unable to fetch TokenAccountInfo for vault - ${vaultB}`); - } - return [vaultInfoA, vaultInfoB]; -} diff --git a/sdk/src/impl/whirlpool-client-impl.ts b/sdk/src/impl/whirlpool-client-impl.ts deleted file mode 100644 index 866abda..0000000 --- a/sdk/src/impl/whirlpool-client-impl.ts +++ /dev/null @@ -1,299 +0,0 @@ -import { Address } from "@coral-xyz/anchor"; -import { AddressUtil, TransactionBuilder } from "@orca-so/common-sdk"; -import { Keypair, PublicKey } from "@solana/web3.js"; -import invariant from "tiny-invariant"; -import { WhirlpoolContext } from "../context"; -import { initTickArrayIx } from "../instructions"; -import { - collectAllForPositionAddressesTxns, - collectProtocolFees, -} from "../instructions/composites"; -import { WhirlpoolIx } from "../ix"; -import { - IGNORE_CACHE, - PREFER_CACHE, - WhirlpoolAccountFetchOptions, - WhirlpoolAccountFetcherInterface, -} from "../network/public/fetcher"; -import { WhirlpoolRouter, WhirlpoolRouterBuilder } from "../router/public"; -import { WhirlpoolData } from "../types/public"; -import { getTickArrayDataForPosition } from "../utils/builder/position-builder-util"; -import { PDAUtil, PoolUtil, PriceMath, TickUtil } from "../utils/public"; -import { Position, Whirlpool, WhirlpoolClient } from "../whirlpool-client"; -import { PositionImpl } from "./position-impl"; -import { getRewardInfos, getTokenMintInfos, getTokenVaultAccountInfos } from "./util"; -import { WhirlpoolImpl } from "./whirlpool-impl"; - -export class WhirlpoolClientImpl implements WhirlpoolClient { - constructor(readonly ctx: WhirlpoolContext) {} - - public getContext(): WhirlpoolContext { - return this.ctx; - } - - public getFetcher(): WhirlpoolAccountFetcherInterface { - return this.ctx.fetcher; - } - - public getRouter(poolAddresses: Address[]): Promise { - return WhirlpoolRouterBuilder.buildWithPools(this.ctx, poolAddresses); - } - - public async getPool(poolAddress: Address, opts = PREFER_CACHE): Promise { - const account = await this.ctx.fetcher.getPool(poolAddress, opts); - if (!account) { - throw new Error(`Unable to fetch Whirlpool at address at ${poolAddress}`); - } - const tokenInfos = await getTokenMintInfos(this.ctx.fetcher, account, opts); - const vaultInfos = await getTokenVaultAccountInfos(this.ctx.fetcher, account, opts); - const rewardInfos = await getRewardInfos(this.ctx.fetcher, account, opts); - return new WhirlpoolImpl( - this.ctx, - AddressUtil.toPubKey(poolAddress), - tokenInfos[0], - tokenInfos[1], - vaultInfos[0], - vaultInfos[1], - rewardInfos, - account - ); - } - - public async getPools(poolAddresses: Address[], opts = PREFER_CACHE): Promise { - const accounts = Array.from( - (await this.ctx.fetcher.getPools(poolAddresses, opts)).values() - ).filter((account): account is WhirlpoolData => !!account); - if (accounts.length !== poolAddresses.length) { - throw new Error(`Unable to fetch all Whirlpools at addresses ${poolAddresses}`); - } - const tokenMints = new Set(); - const tokenAccounts = new Set(); - accounts.forEach((account) => { - tokenMints.add(account.tokenMintA.toBase58()); - tokenMints.add(account.tokenMintB.toBase58()); - tokenAccounts.add(account.tokenVaultA.toBase58()); - tokenAccounts.add(account.tokenVaultB.toBase58()); - account.rewardInfos.forEach((rewardInfo) => { - if (PoolUtil.isRewardInitialized(rewardInfo)) { - tokenAccounts.add(rewardInfo.vault.toBase58()); - } - }); - }); - await this.ctx.fetcher.getMintInfos(Array.from(tokenMints), opts); - await this.ctx.fetcher.getTokenInfos(Array.from(tokenAccounts), opts); - - const whirlpools: Whirlpool[] = []; - for (let i = 0; i < accounts.length; i++) { - const account = accounts[i]; - const poolAddress = poolAddresses[i]; - const tokenInfos = await getTokenMintInfos(this.ctx.fetcher, account, PREFER_CACHE); - const vaultInfos = await getTokenVaultAccountInfos(this.ctx.fetcher, account, PREFER_CACHE); - const rewardInfos = await getRewardInfos(this.ctx.fetcher, account, PREFER_CACHE); - whirlpools.push( - new WhirlpoolImpl( - this.ctx, - AddressUtil.toPubKey(poolAddress), - tokenInfos[0], - tokenInfos[1], - vaultInfos[0], - vaultInfos[1], - rewardInfos, - account - ) - ); - } - return whirlpools; - } - - public async getPosition(positionAddress: Address, opts = PREFER_CACHE): Promise { - const account = await this.ctx.fetcher.getPosition(positionAddress, opts); - if (!account) { - throw new Error(`Unable to fetch Position at address at ${positionAddress}`); - } - const whirlAccount = await this.ctx.fetcher.getPool(account.whirlpool, opts); - if (!whirlAccount) { - throw new Error(`Unable to fetch Whirlpool for Position at address at ${positionAddress}`); - } - - const [lowerTickArray, upperTickArray] = await getTickArrayDataForPosition( - this.ctx, - account, - whirlAccount, - opts - ); - if (!lowerTickArray || !upperTickArray) { - throw new Error(`Unable to fetch TickArrays for Position at address at ${positionAddress}`); - } - return new PositionImpl( - this.ctx, - AddressUtil.toPubKey(positionAddress), - account, - whirlAccount, - lowerTickArray, - upperTickArray - ); - } - - public async getPositions( - positionAddresses: Address[], - opts = PREFER_CACHE - ): Promise> { - // TODO: Prefetch and use fetcher as a cache - Think of a cleaner way to prefetch - const positions = Array.from( - (await this.ctx.fetcher.getPositions(positionAddresses, opts)).values() - ); - const whirlpoolAddrs = positions - .map((position) => position?.whirlpool.toBase58()) - .flatMap((x) => (!!x ? x : [])); - await this.ctx.fetcher.getPools(whirlpoolAddrs, opts); - const tickArrayAddresses: Set = new Set(); - await Promise.all( - positions.map(async (pos) => { - if (pos) { - const pool = await this.ctx.fetcher.getPool(pos.whirlpool, PREFER_CACHE); - if (pool) { - const lowerTickArrayPda = PDAUtil.getTickArrayFromTickIndex( - pos.tickLowerIndex, - pool.tickSpacing, - pos.whirlpool, - this.ctx.program.programId - ).publicKey; - const upperTickArrayPda = PDAUtil.getTickArrayFromTickIndex( - pos.tickUpperIndex, - pool.tickSpacing, - pos.whirlpool, - this.ctx.program.programId - ).publicKey; - tickArrayAddresses.add(lowerTickArrayPda.toBase58()); - tickArrayAddresses.add(upperTickArrayPda.toBase58()); - } - } - }) - ); - await this.ctx.fetcher.getTickArrays(Array.from(tickArrayAddresses), IGNORE_CACHE); - - // Use getPosition and the prefetched values to generate the Positions - const results = await Promise.all( - positionAddresses.map(async (pos) => { - try { - const position = await this.getPosition(pos, PREFER_CACHE); - return [pos, position]; - } catch { - return [pos, null]; - } - }) - ); - return Object.fromEntries(results); - } - - public async createPool( - whirlpoolsConfig: Address, - tokenMintA: Address, - tokenMintB: Address, - tickSpacing: number, - initialTick: number, - funder: Address, - opts = PREFER_CACHE - ): Promise<{ poolKey: PublicKey; tx: TransactionBuilder }> { - invariant(TickUtil.checkTickInBounds(initialTick), "initialTick is out of bounds."); - invariant( - TickUtil.isTickInitializable(initialTick, tickSpacing), - `initial tick ${initialTick} is not an initializable tick for tick-spacing ${tickSpacing}` - ); - - const correctTokenOrder = PoolUtil.orderMints(tokenMintA, tokenMintB).map((addr) => - addr.toString() - ); - - invariant( - correctTokenOrder[0] === tokenMintA.toString(), - "Token order needs to be flipped to match the canonical ordering (i.e. sorted on the byte repr. of the mint pubkeys)" - ); - - whirlpoolsConfig = AddressUtil.toPubKey(whirlpoolsConfig); - - const feeTierKey = PDAUtil.getFeeTier( - this.ctx.program.programId, - whirlpoolsConfig, - tickSpacing - ).publicKey; - - const initSqrtPrice = PriceMath.tickIndexToSqrtPriceX64(initialTick); - const tokenVaultAKeypair = Keypair.generate(); - const tokenVaultBKeypair = Keypair.generate(); - - const whirlpoolPda = PDAUtil.getWhirlpool( - this.ctx.program.programId, - whirlpoolsConfig, - new PublicKey(tokenMintA), - new PublicKey(tokenMintB), - tickSpacing - ); - - const feeTier = await this.ctx.fetcher.getFeeTier(feeTierKey, opts); - invariant(!!feeTier, `Fee tier for ${tickSpacing} doesn't exist`); - - const txBuilder = new TransactionBuilder( - this.ctx.provider.connection, - this.ctx.provider.wallet, - this.ctx.txBuilderOpts - ); - - const initPoolIx = WhirlpoolIx.initializePoolIx(this.ctx.program, { - initSqrtPrice, - whirlpoolsConfig, - whirlpoolPda, - tokenMintA: new PublicKey(tokenMintA), - tokenMintB: new PublicKey(tokenMintB), - tokenVaultAKeypair, - tokenVaultBKeypair, - feeTierKey, - tickSpacing, - funder: new PublicKey(funder), - }); - - const initialTickArrayStartTick = TickUtil.getStartTickIndex(initialTick, tickSpacing); - const initialTickArrayPda = PDAUtil.getTickArray( - this.ctx.program.programId, - whirlpoolPda.publicKey, - initialTickArrayStartTick - ); - - txBuilder.addInstruction(initPoolIx); - txBuilder.addInstruction( - initTickArrayIx(this.ctx.program, { - startTick: initialTickArrayStartTick, - tickArrayPda: initialTickArrayPda, - whirlpool: whirlpoolPda.publicKey, - funder: AddressUtil.toPubKey(funder), - }) - ); - - return { - poolKey: whirlpoolPda.publicKey, - tx: txBuilder, - }; - } - - public async collectFeesAndRewardsForPositions( - positionAddresses: Address[], - opts?: WhirlpoolAccountFetchOptions - ): Promise { - const walletKey = this.ctx.wallet.publicKey; - return collectAllForPositionAddressesTxns( - this.ctx, - { - positions: positionAddresses, - receiver: walletKey, - positionAuthority: walletKey, - positionOwner: walletKey, - payer: walletKey, - }, - opts - ); - } - - public async collectProtocolFeesForPools(poolAddresses: Address[]): Promise { - return collectProtocolFees(this.ctx, poolAddresses); - } -} diff --git a/sdk/src/impl/whirlpool-impl.ts b/sdk/src/impl/whirlpool-impl.ts deleted file mode 100644 index 6a1c9d0..0000000 --- a/sdk/src/impl/whirlpool-impl.ts +++ /dev/null @@ -1,624 +0,0 @@ -import { Address, BN, translateAddress } from "@coral-xyz/anchor"; -import { - AddressUtil, - MEASUREMENT_BLOCKHASH, - Percentage, - TokenUtil, - TransactionBuilder, - ZERO, - resolveOrCreateATAs, -} from "@orca-so/common-sdk"; -import { NATIVE_MINT, getAssociatedTokenAddressSync } from "@solana/spl-token"; -import { Keypair, PublicKey } from "@solana/web3.js"; -import invariant from "tiny-invariant"; -import { WhirlpoolContext } from "../context"; -import { - DevFeeSwapInput, - IncreaseLiquidityInput, - SwapInput, - closePositionIx, - decreaseLiquidityIx, - increaseLiquidityIx, - initTickArrayIx, - openPositionIx, - openPositionWithMetadataIx, - swapAsync, -} from "../instructions"; -import { IGNORE_CACHE, PREFER_CACHE } from "../network/public/fetcher"; -import { - collectFeesQuote, - collectRewardsQuote, - decreaseLiquidityQuoteByLiquidityWithParams, -} from "../quotes/public"; -import { TokenAccountInfo, TokenInfo, WhirlpoolData, WhirlpoolRewardInfo } from "../types/public"; -import { getTickArrayDataForPosition } from "../utils/builder/position-builder-util"; -import { PDAUtil, TickArrayUtil, TickUtil } from "../utils/public"; -import { - TokenMintTypes, - getTokenMintsFromWhirlpools, - resolveAtaForMints, -} from "../utils/whirlpool-ata-utils"; -import { Whirlpool } from "../whirlpool-client"; -import { PositionImpl } from "./position-impl"; -import { getRewardInfos, getTokenVaultAccountInfos } from "./util"; -import { checkMergedTransactionSizeIsValid } from "../utils/txn-utils"; - -export class WhirlpoolImpl implements Whirlpool { - private data: WhirlpoolData; - constructor( - readonly ctx: WhirlpoolContext, - readonly address: PublicKey, - readonly tokenAInfo: TokenInfo, - readonly tokenBInfo: TokenInfo, - private tokenVaultAInfo: TokenAccountInfo, - private tokenVaultBInfo: TokenAccountInfo, - private rewardInfos: WhirlpoolRewardInfo[], - data: WhirlpoolData - ) { - this.data = data; - } - - getAddress(): PublicKey { - return this.address; - } - - getData(): WhirlpoolData { - return this.data; - } - - getTokenAInfo(): TokenInfo { - return this.tokenAInfo; - } - - getTokenBInfo(): TokenInfo { - return this.tokenBInfo; - } - - getTokenVaultAInfo(): TokenAccountInfo { - return this.tokenVaultAInfo; - } - - getTokenVaultBInfo(): TokenAccountInfo { - return this.tokenVaultBInfo; - } - - getRewardInfos(): WhirlpoolRewardInfo[] { - return this.rewardInfos; - } - - async refreshData() { - await this.refresh(); - return this.data; - } - - async openPosition( - tickLower: number, - tickUpper: number, - liquidityInput: IncreaseLiquidityInput, - wallet?: Address, - funder?: Address, - positionMint?: PublicKey - ) { - await this.refresh(); - return this.getOpenPositionWithOptMetadataTx( - tickLower, - tickUpper, - liquidityInput, - !!wallet ? AddressUtil.toPubKey(wallet) : this.ctx.wallet.publicKey, - !!funder ? AddressUtil.toPubKey(funder) : this.ctx.wallet.publicKey, - false, - positionMint - ); - } - - async openPositionWithMetadata( - tickLower: number, - tickUpper: number, - liquidityInput: IncreaseLiquidityInput, - sourceWallet?: Address, - funder?: Address, - positionMint?: PublicKey - ) { - await this.refresh(); - return this.getOpenPositionWithOptMetadataTx( - tickLower, - tickUpper, - liquidityInput, - !!sourceWallet ? AddressUtil.toPubKey(sourceWallet) : this.ctx.wallet.publicKey, - !!funder ? AddressUtil.toPubKey(funder) : this.ctx.wallet.publicKey, - true, - positionMint - ); - } - - async initTickArrayForTicks(ticks: number[], funder?: Address, opts = IGNORE_CACHE) { - const initTickArrayStartPdas = await TickArrayUtil.getUninitializedArraysPDAs( - ticks, - this.ctx.program.programId, - this.address, - this.data.tickSpacing, - this.ctx.fetcher, - opts - ); - - if (!initTickArrayStartPdas.length) { - return null; - } - - const txBuilder = new TransactionBuilder( - this.ctx.provider.connection, - this.ctx.provider.wallet, - this.ctx.txBuilderOpts - ); - initTickArrayStartPdas.forEach((initTickArrayInfo) => { - txBuilder.addInstruction( - initTickArrayIx(this.ctx.program, { - startTick: initTickArrayInfo.startIndex, - tickArrayPda: initTickArrayInfo.pda, - whirlpool: this.address, - funder: !!funder ? AddressUtil.toPubKey(funder) : this.ctx.provider.wallet.publicKey, - }) - ); - }); - return txBuilder; - } - - async closePosition( - positionAddress: Address, - slippageTolerance: Percentage, - destinationWallet?: Address, - positionWallet?: Address, - payer?: Address - ) { - await this.refresh(); - const positionWalletKey = positionWallet - ? AddressUtil.toPubKey(positionWallet) - : this.ctx.wallet.publicKey; - const destinationWalletKey = destinationWallet - ? AddressUtil.toPubKey(destinationWallet) - : this.ctx.wallet.publicKey; - const payerKey = payer ? AddressUtil.toPubKey(payer) : this.ctx.wallet.publicKey; - return this.getClosePositionIx( - AddressUtil.toPubKey(positionAddress), - slippageTolerance, - destinationWalletKey, - positionWalletKey, - payerKey - ); - } - - async swap(quote: SwapInput, sourceWallet?: Address): Promise { - const sourceWalletKey = sourceWallet - ? AddressUtil.toPubKey(sourceWallet) - : this.ctx.wallet.publicKey; - return swapAsync( - this.ctx, - { - swapInput: quote, - whirlpool: this, - wallet: sourceWalletKey, - }, - IGNORE_CACHE - ); - } - - async swapWithDevFees( - quote: DevFeeSwapInput, - devFeeWallet: PublicKey, - wallet?: PublicKey | undefined, - payer?: PublicKey | undefined - ): Promise { - const sourceWalletKey = wallet ? AddressUtil.toPubKey(wallet) : this.ctx.wallet.publicKey; - const payerKey = payer ? AddressUtil.toPubKey(payer) : this.ctx.wallet.publicKey; - const txBuilder = new TransactionBuilder( - this.ctx.provider.connection, - this.ctx.provider.wallet, - this.ctx.txBuilderOpts - ); - - if (!quote.devFeeAmount.eq(ZERO)) { - const inputToken = - quote.aToB === quote.amountSpecifiedIsInput ? this.getTokenAInfo() : this.getTokenBInfo(); - - txBuilder.addInstruction( - await TokenUtil.createSendTokensToWalletInstruction( - this.ctx.connection, - sourceWalletKey, - devFeeWallet, - inputToken.mint, - inputToken.decimals, - quote.devFeeAmount, - () => this.ctx.fetcher.getAccountRentExempt(), - payerKey, - this.ctx.accountResolverOpts.allowPDAOwnerAddress - ) - ); - } - - const swapTxBuilder = await swapAsync( - this.ctx, - { - swapInput: quote, - whirlpool: this, - wallet: sourceWalletKey, - }, - IGNORE_CACHE - ); - - txBuilder.addInstruction(swapTxBuilder.compressIx(true)); - - return txBuilder; - } - - /** - * Construct a transaction for opening an new position with optional metadata - */ - async getOpenPositionWithOptMetadataTx( - tickLower: number, - tickUpper: number, - liquidityInput: IncreaseLiquidityInput, - wallet: PublicKey, - funder: PublicKey, - withMetadata: boolean = false, - positionMint?: PublicKey - ): Promise<{ positionMint: PublicKey; tx: TransactionBuilder }> { - invariant(TickUtil.checkTickInBounds(tickLower), "tickLower is out of bounds."); - invariant(TickUtil.checkTickInBounds(tickUpper), "tickUpper is out of bounds."); - - const { liquidityAmount: liquidity, tokenMaxA, tokenMaxB } = liquidityInput; - - invariant(liquidity.gt(new BN(0)), "liquidity must be greater than zero"); - - const whirlpool = await this.ctx.fetcher.getPool(this.address, PREFER_CACHE); - if (!whirlpool) { - throw new Error(`Whirlpool not found: ${translateAddress(this.address).toBase58()}`); - } - - invariant( - TickUtil.isTickInitializable(tickLower, whirlpool.tickSpacing), - `lower tick ${tickLower} is not an initializable tick for tick-spacing ${whirlpool.tickSpacing}` - ); - invariant( - TickUtil.isTickInitializable(tickUpper, whirlpool.tickSpacing), - `upper tick ${tickUpper} is not an initializable tick for tick-spacing ${whirlpool.tickSpacing}` - ); - - const positionMintKeypair = Keypair.generate(); - const positionMintPubkey = positionMint ?? positionMintKeypair.publicKey; - const positionPda = PDAUtil.getPosition( - this.ctx.program.programId, - positionMintPubkey - ); - const metadataPda = PDAUtil.getPositionMetadata(positionMintPubkey); - const positionTokenAccountAddress = getAssociatedTokenAddressSync( - positionMintPubkey, - wallet, - this.ctx.accountResolverOpts.allowPDAOwnerAddress - ); - - const txBuilder = new TransactionBuilder( - this.ctx.provider.connection, - this.ctx.provider.wallet, - this.ctx.txBuilderOpts - ); - - const positionIx = (withMetadata ? openPositionWithMetadataIx : openPositionIx)( - this.ctx.program, - { - funder, - owner: wallet, - positionPda, - metadataPda, - positionMintAddress: positionMintPubkey, - positionTokenAccount: positionTokenAccountAddress, - whirlpool: this.address, - tickLowerIndex: tickLower, - tickUpperIndex: tickUpper, - } - ); - txBuilder.addInstruction(positionIx); - if(positionMint === undefined) { - txBuilder.addSigner(positionMintKeypair); - } - - const [ataA, ataB] = await resolveOrCreateATAs( - this.ctx.connection, - wallet, - [ - { tokenMint: whirlpool.tokenMintA, wrappedSolAmountIn: tokenMaxA }, - { tokenMint: whirlpool.tokenMintB, wrappedSolAmountIn: tokenMaxB }, - ], - () => this.ctx.fetcher.getAccountRentExempt(), - funder, - undefined, // use default - this.ctx.accountResolverOpts.allowPDAOwnerAddress, - this.ctx.accountResolverOpts.createWrappedSolAccountMethod - ); - const { address: tokenOwnerAccountA, ...tokenOwnerAccountAIx } = ataA; - const { address: tokenOwnerAccountB, ...tokenOwnerAccountBIx } = ataB; - - txBuilder.addInstruction(tokenOwnerAccountAIx); - txBuilder.addInstruction(tokenOwnerAccountBIx); - - const tickArrayLowerPda = PDAUtil.getTickArrayFromTickIndex( - tickLower, - this.data.tickSpacing, - this.address, - this.ctx.program.programId - ); - const tickArrayUpperPda = PDAUtil.getTickArrayFromTickIndex( - tickUpper, - this.data.tickSpacing, - this.address, - this.ctx.program.programId - ); - - const liquidityIx = increaseLiquidityIx(this.ctx.program, { - liquidityAmount: liquidity, - tokenMaxA, - tokenMaxB, - whirlpool: this.address, - positionAuthority: wallet, - position: positionPda.publicKey, - positionTokenAccount: positionTokenAccountAddress, - tokenOwnerAccountA, - tokenOwnerAccountB, - tokenVaultA: whirlpool.tokenVaultA, - tokenVaultB: whirlpool.tokenVaultB, - tickArrayLower: tickArrayLowerPda.publicKey, - tickArrayUpper: tickArrayUpperPda.publicKey, - }); - txBuilder.addInstruction(liquidityIx); - - return { - positionMint: positionMintPubkey, - tx: txBuilder, - }; - } - - async getClosePositionIx( - positionAddress: PublicKey, - slippageTolerance: Percentage, - destinationWallet: PublicKey, - positionWallet: PublicKey, - payerKey: PublicKey - ): Promise { - const positionData = await this.ctx.fetcher.getPosition(positionAddress, IGNORE_CACHE); - if (!positionData) { - throw new Error(`Position not found: ${positionAddress.toBase58()}`); - } - - const whirlpool = this.data; - - invariant( - positionData.whirlpool.equals(this.address), - `Position ${positionAddress.toBase58()} is not a position for Whirlpool ${this.address.toBase58()}` - ); - - const positionTokenAccount = getAssociatedTokenAddressSync( - positionData.positionMint, - positionWallet, - this.ctx.accountResolverOpts.allowPDAOwnerAddress - ); - - const tokenAccountsTxBuilder = new TransactionBuilder( - this.ctx.provider.connection, - this.ctx.provider.wallet, - this.ctx.txBuilderOpts - ); - - const accountExemption = await this.ctx.fetcher.getAccountRentExempt(); - - const txBuilder = new TransactionBuilder( - this.ctx.provider.connection, - this.ctx.provider.wallet, - this.ctx.txBuilderOpts - ); - - const tickArrayLower = PDAUtil.getTickArrayFromTickIndex( - positionData.tickLowerIndex, - whirlpool.tickSpacing, - positionData.whirlpool, - this.ctx.program.programId - ).publicKey; - - const tickArrayUpper = PDAUtil.getTickArrayFromTickIndex( - positionData.tickUpperIndex, - whirlpool.tickSpacing, - positionData.whirlpool, - this.ctx.program.programId - ).publicKey; - - const [tickArrayLowerData, tickArrayUpperData] = await getTickArrayDataForPosition( - this.ctx, - positionData, - whirlpool, - IGNORE_CACHE - ); - - invariant( - !!tickArrayLowerData, - `Tick array ${tickArrayLower} expected to be initialized for whirlpool ${this.address}` - ); - - invariant( - !!tickArrayUpperData, - `Tick array ${tickArrayUpper} expected to be initialized for whirlpool ${this.address}` - ); - - const position = new PositionImpl( - this.ctx, - positionAddress, - positionData, - whirlpool, - tickArrayLowerData, - tickArrayUpperData - ); - - const tickLower = position.getLowerTickData(); - const tickUpper = position.getUpperTickData(); - - const feesQuote = collectFeesQuote({ - position: positionData, - whirlpool, - tickLower, - tickUpper, - }); - - const rewardsQuote = collectRewardsQuote({ - position: positionData, - whirlpool, - tickLower, - tickUpper, - }); - - const shouldCollectFees = feesQuote.feeOwedA.gtn(0) || feesQuote.feeOwedB.gtn(0); - invariant( - this.data.rewardInfos.length === rewardsQuote.length, - "Rewards quote does not match reward infos length" - ); - - const shouldDecreaseLiquidity = positionData.liquidity.gtn(0); - - const rewardsToCollect = this.data.rewardInfos - .filter((_, i) => (rewardsQuote[i] ?? ZERO).gtn(0)) - .map((info) => info.mint); - - const shouldCollectRewards = rewardsToCollect.length > 0; - - let mintType = TokenMintTypes.ALL; - if ((shouldDecreaseLiquidity || shouldCollectFees) && !shouldCollectRewards) { - mintType = TokenMintTypes.POOL_ONLY; - } else if (!(shouldDecreaseLiquidity || shouldCollectFees) && shouldCollectRewards) { - mintType = TokenMintTypes.REWARD_ONLY; - } - - const affiliatedMints = getTokenMintsFromWhirlpools([whirlpool], mintType); - const { ataTokenAddresses: walletTokenAccountsByMint, resolveAtaIxs } = - await resolveAtaForMints(this.ctx, { - mints: affiliatedMints.mintMap, - accountExemption, - receiver: destinationWallet, - payer: payerKey, - }); - - tokenAccountsTxBuilder.addInstructions(resolveAtaIxs); - - // Handle native mint - if (affiliatedMints.hasNativeMint) { - let { address: wSOLAta, ...resolveWSolIx } = TokenUtil.createWrappedNativeAccountInstruction( - destinationWallet, - ZERO, - accountExemption, - payerKey, - destinationWallet, - this.ctx.accountResolverOpts.createWrappedSolAccountMethod - ); - walletTokenAccountsByMint[NATIVE_MINT.toBase58()] = wSOLAta; - txBuilder.addInstruction(resolveWSolIx); - } - - if (shouldDecreaseLiquidity) { - /* Remove all liquidity remaining in the position */ - const tokenOwnerAccountA = walletTokenAccountsByMint[whirlpool.tokenMintA.toBase58()]; - const tokenOwnerAccountB = walletTokenAccountsByMint[whirlpool.tokenMintB.toBase58()]; - - const decreaseLiqQuote = decreaseLiquidityQuoteByLiquidityWithParams({ - liquidity: positionData.liquidity, - slippageTolerance, - sqrtPrice: whirlpool.sqrtPrice, - tickCurrentIndex: whirlpool.tickCurrentIndex, - tickLowerIndex: positionData.tickLowerIndex, - tickUpperIndex: positionData.tickUpperIndex, - }); - - const liquidityIx = decreaseLiquidityIx(this.ctx.program, { - ...decreaseLiqQuote, - whirlpool: positionData.whirlpool, - positionAuthority: positionWallet, - position: positionAddress, - positionTokenAccount, - tokenOwnerAccountA, - tokenOwnerAccountB, - tokenVaultA: whirlpool.tokenVaultA, - tokenVaultB: whirlpool.tokenVaultB, - tickArrayLower, - tickArrayUpper, - }); - - txBuilder.addInstruction(liquidityIx); - } - - if (shouldCollectFees) { - const collectFeexTx = await position.collectFees( - false, - walletTokenAccountsByMint, - destinationWallet, - positionWallet, - payerKey, - IGNORE_CACHE - ); - - txBuilder.addInstruction(collectFeexTx.compressIx(false)); - } - - if (shouldCollectRewards) { - const collectRewardsTx = await position.collectRewards( - rewardsToCollect, - false, - walletTokenAccountsByMint, - destinationWallet, - positionWallet, - payerKey - ); - - txBuilder.addInstruction(collectRewardsTx.compressIx(false)); - } - - /* Close position */ - const positionIx = closePositionIx(this.ctx.program, { - positionAuthority: positionWallet, - receiver: destinationWallet, - positionTokenAccount, - position: positionAddress, - positionMint: positionData.positionMint, - }); - - txBuilder.addInstruction(positionIx); - - if (tokenAccountsTxBuilder.isEmpty()) { - return [txBuilder] - } - - // This handles an edge case where the instructions are too - // large to fit in a single transaction and we need to split the - // instructions into two transactions. - const canFitInOneTransaction = await checkMergedTransactionSizeIsValid( - this.ctx, - [tokenAccountsTxBuilder, txBuilder], - MEASUREMENT_BLOCKHASH - ) - if (!canFitInOneTransaction) { - return [tokenAccountsTxBuilder, txBuilder] - } - - tokenAccountsTxBuilder.addInstruction(txBuilder.compressIx(false)); - return [tokenAccountsTxBuilder] - } - - private async refresh() { - const account = await this.ctx.fetcher.getPool(this.address, IGNORE_CACHE); - if (!!account) { - const rewardInfos = await getRewardInfos(this.ctx.fetcher, account, IGNORE_CACHE); - const [tokenVaultAInfo, tokenVaultBInfo] = await getTokenVaultAccountInfos( - this.ctx.fetcher, - account, - IGNORE_CACHE - ); - this.data = account; - this.tokenVaultAInfo = tokenVaultAInfo; - this.tokenVaultBInfo = tokenVaultBInfo; - this.rewardInfos = rewardInfos; - } - } -} diff --git a/sdk/src/index.ts b/sdk/src/index.ts deleted file mode 100644 index dc22b83..0000000 --- a/sdk/src/index.ts +++ /dev/null @@ -1,19 +0,0 @@ -import Decimal from "decimal.js"; - -export * from "./context"; -export * from "./impl/position-impl"; -export * from "./ix"; -export * from "./network/public"; -export * from "./prices"; -export * from "./quotes/public"; -export * from "./router/public"; -export * from "./types/public"; -export * from "./types/public/anchor-types"; -export * from "./utils/public"; -export * from "./whirlpool-client"; - -// Global rules for Decimals -// - 40 digits of precision for the largest number -// - 20 digits of precision for the smallest number -// - Always round towards 0 to mirror smart contract rules -Decimal.set({ precision: 40, toExpPos: 40, toExpNeg: -20, rounding: 1 }); diff --git a/sdk/src/instructions/close-bundled-position-ix.ts b/sdk/src/instructions/close-bundled-position-ix.ts deleted file mode 100644 index 5b75c79..0000000 --- a/sdk/src/instructions/close-bundled-position-ix.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { Program } from "@coral-xyz/anchor"; -import { Instruction } from "@orca-so/common-sdk"; -import { PublicKey } from "@solana/web3.js"; -import { Whirlpool } from "../artifacts/whirlpool"; - -/** - * Parameters to close a bundled position in a Whirlpool. - * - * @category Instruction Types - * @param bundledPosition - PublicKey for the bundled position. - * @param positionBundle - PublicKey for the position bundle. - * @param positionBundleTokenAccount - The associated token address for the position bundle token in the owners wallet. - * @param positionBundleAuthority - authority that owns the token corresponding to this desired bundled position. - * @param bundleIndex - The bundle index that holds the bundled position. - * @param receiver - PublicKey for the wallet that will receive the rented lamports. - */ -export type CloseBundledPositionParams = { - bundledPosition: PublicKey; - positionBundle: PublicKey; - positionBundleTokenAccount: PublicKey; - positionBundleAuthority: PublicKey; - bundleIndex: number; - receiver: PublicKey; -}; - -/** - * Close a bundled position in a Whirlpool. - * - * #### Special Errors - * `InvalidBundleIndex` - If the provided bundle index is out of bounds. - * `ClosePositionNotEmpty` - The provided position account is not empty. - * - * @category Instructions - * @param program - program object containing services required to generate the instruction - * @param params - CloseBundledPositionParams object - * @returns - Instruction to perform the action. - */ -export function closeBundledPositionIx( - program: Program, - params: CloseBundledPositionParams -): Instruction { - const { - bundledPosition, - positionBundle, - positionBundleTokenAccount, - positionBundleAuthority, - bundleIndex, - receiver, - } = params; - - const ix = program.instruction.closeBundledPosition(bundleIndex, { - accounts: { - bundledPosition, - positionBundle, - positionBundleTokenAccount, - positionBundleAuthority, - receiver, - }, - }); - - return { - instructions: [ix], - cleanupInstructions: [], - signers: [], - }; -} diff --git a/sdk/src/instructions/close-position-ix.ts b/sdk/src/instructions/close-position-ix.ts deleted file mode 100644 index 67d95b0..0000000 --- a/sdk/src/instructions/close-position-ix.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { Program } from "@coral-xyz/anchor"; -import { Instruction } from "@orca-so/common-sdk"; -import { TOKEN_PROGRAM_ID } from "@solana/spl-token"; -import { PublicKey } from "@solana/web3.js"; -import { Whirlpool } from "../artifacts/whirlpool"; - -/** - * Parameters to close a position in a Whirlpool. - * - * @category Instruction Types - * @param receiver - PublicKey for the wallet that will receive the rented lamports. - * @param position - PublicKey for the position. - * @param positionMint - PublicKey for the mint token for the Position token. - * @param positionTokenAccount - The associated token address for the position token in the owners wallet. - * @param positionAuthority - Authority that owns the position token. - */ -export type ClosePositionParams = { - receiver: PublicKey; - position: PublicKey; - positionMint: PublicKey; - positionTokenAccount: PublicKey; - positionAuthority: PublicKey; -}; - -/** - * Close a position in a Whirlpool. Burns the position token in the owner's wallet. - * - * @category Instructions - * @param context - Context object containing services required to generate the instruction - * @param params - ClosePositionParams object - * @returns - Instruction to perform the action. - */ -export function closePositionIx( - program: Program, - params: ClosePositionParams -): Instruction { - const { - positionAuthority, - receiver: receiver, - position: position, - positionMint: positionMint, - positionTokenAccount, - } = params; - - const ix = program.instruction.closePosition({ - accounts: { - positionAuthority, - receiver, - position, - positionMint, - positionTokenAccount, - tokenProgram: TOKEN_PROGRAM_ID, - }, - }); - - return { - instructions: [ix], - cleanupInstructions: [], - signers: [], - }; -} diff --git a/sdk/src/instructions/collect-fees-ix.ts b/sdk/src/instructions/collect-fees-ix.ts deleted file mode 100644 index f3ad1be..0000000 --- a/sdk/src/instructions/collect-fees-ix.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { Program } from "@coral-xyz/anchor"; -import { TOKEN_PROGRAM_ID } from "@solana/spl-token"; -import { PublicKey } from "@solana/web3.js"; -import { Whirlpool } from "../artifacts/whirlpool"; - -import { Instruction } from "@orca-so/common-sdk"; - -/** - * Parameters to collect fees from a position. - * - * @category Instruction Types - * @param whirlpool - PublicKey for the whirlpool that the position will be opened for. - * @param position - PublicKey for the position will be opened for. - * @param positionTokenAccount - PublicKey for the position token's associated token address. - * @param tokenOwnerAccountA - PublicKey for the token A account that will be withdrawed from. - * @param tokenOwnerAccountB - PublicKey for the token B account that will be withdrawed from. - * @param tokenVaultA - PublicKey for the tokenA vault for this whirlpool. - * @param tokenVaultB - PublicKey for the tokenB vault for this whirlpool. - * @param positionAuthority - authority that owns the token corresponding to this desired position. - */ -export type CollectFeesParams = { - whirlpool: PublicKey; - position: PublicKey; - positionTokenAccount: PublicKey; - tokenOwnerAccountA: PublicKey; - tokenOwnerAccountB: PublicKey; - tokenVaultA: PublicKey; - tokenVaultB: PublicKey; - positionAuthority: PublicKey; -}; - -/** - * Collect fees accrued for this position. - * Call updateFeesAndRewards before this to update the position to the newest accrued values. - * - * @category Instructions - * @param context - Context object containing services required to generate the instruction - * @param params - CollectFeesParams object - * @returns - Instruction to perform the action. - */ -export function collectFeesIx(program: Program, params: CollectFeesParams): Instruction { - const { - whirlpool, - positionAuthority, - position, - positionTokenAccount, - tokenOwnerAccountA, - tokenOwnerAccountB, - tokenVaultA, - tokenVaultB, - } = params; - - const ix = program.instruction.collectFees({ - accounts: { - whirlpool, - positionAuthority, - position, - positionTokenAccount, - tokenOwnerAccountA, - tokenOwnerAccountB, - tokenVaultA, - tokenVaultB, - tokenProgram: TOKEN_PROGRAM_ID, - }, - }); - - return { - instructions: [ix], - cleanupInstructions: [], - signers: [], - }; -} diff --git a/sdk/src/instructions/collect-protocol-fees-ix.ts b/sdk/src/instructions/collect-protocol-fees-ix.ts deleted file mode 100644 index 2b37562..0000000 --- a/sdk/src/instructions/collect-protocol-fees-ix.ts +++ /dev/null @@ -1,69 +0,0 @@ -import { Program } from "@coral-xyz/anchor"; -import { Instruction } from "@orca-so/common-sdk"; -import { TOKEN_PROGRAM_ID } from "@solana/spl-token"; -import { PublicKey } from "@solana/web3.js"; -import { Whirlpool } from "../artifacts/whirlpool"; - -/** - * Parameters to collect protocol fees for a Whirlpool - * - * @category Instruction Types - * @param whirlpoolsConfig - The public key for the WhirlpoolsConfig this pool is initialized in - * @param whirlpool - PublicKey for the whirlpool that the position will be opened for. - * @param tokenVaultA - PublicKey for the tokenA vault for this whirlpool. - * @param tokenVaultB - PublicKey for the tokenB vault for this whirlpool. - * @param tokenOwnerAccountA - PublicKey for the associated token account for tokenA in the collection wallet - * @param tokenOwnerAccountB - PublicKey for the associated token account for tokenA in the collection wallet - * @param collectProtocolFeesAuthority - assigned authority in the WhirlpoolsConfig that can collect protocol fees - */ -export type CollectProtocolFeesParams = { - whirlpoolsConfig: PublicKey; - whirlpool: PublicKey; - tokenVaultA: PublicKey; - tokenVaultB: PublicKey; - tokenOwnerAccountA: PublicKey; - tokenOwnerAccountB: PublicKey; - collectProtocolFeesAuthority: PublicKey; -}; - -/** - * Collect protocol fees accrued in this Whirlpool. - * - * @category Instructions - * @param context - Context object containing services required to generate the instruction - * @param params - CollectProtocolFeesParams object - * @returns - Instruction to perform the action. - */ -export function collectProtocolFeesIx( - program: Program, - params: CollectProtocolFeesParams -): Instruction { - const { - whirlpoolsConfig, - whirlpool, - collectProtocolFeesAuthority, - tokenVaultA, - tokenVaultB, - tokenOwnerAccountA: tokenDestinationA, - tokenOwnerAccountB: tokenDestinationB, - } = params; - - const ix = program.instruction.collectProtocolFees({ - accounts: { - whirlpoolsConfig, - whirlpool, - collectProtocolFeesAuthority, - tokenVaultA, - tokenVaultB, - tokenDestinationA, - tokenDestinationB, - tokenProgram: TOKEN_PROGRAM_ID, - }, - }); - - return { - instructions: [ix], - cleanupInstructions: [], - signers: [], - }; -} diff --git a/sdk/src/instructions/collect-reward-ix.ts b/sdk/src/instructions/collect-reward-ix.ts deleted file mode 100644 index 612131e..0000000 --- a/sdk/src/instructions/collect-reward-ix.ts +++ /dev/null @@ -1,69 +0,0 @@ -import { Program } from "@coral-xyz/anchor"; -import { Instruction } from "@orca-so/common-sdk"; -import { TOKEN_PROGRAM_ID } from "@solana/spl-token"; -import { PublicKey } from "@solana/web3.js"; -import { Whirlpool } from "../artifacts/whirlpool"; - -/** - * Parameters to collect rewards from a reward index in a position. - * - * @category Instruction Types - * @param whirlpool - PublicKey for the whirlpool that the position will be opened for. - * @param position - PublicKey for the position will be opened for. - * @param positionTokenAccount - PublicKey for the position token's associated token address. - * @param rewardIndex - The reward index that we'd like to initialize. (0 <= index <= NUM_REWARDS). - * @param rewardOwnerAccount - PublicKey for the reward token account that the reward will deposit into. - * @param rewardVault - PublicKey of the vault account that reward will be withdrawn from. - * @param positionAuthority - authority that owns the token corresponding to this desired position. - */ -export type CollectRewardParams = { - whirlpool: PublicKey; - position: PublicKey; - positionTokenAccount: PublicKey; - rewardIndex: number; - rewardOwnerAccount: PublicKey; - rewardVault: PublicKey; - positionAuthority: PublicKey; -}; - -/** - * Collect rewards accrued for this reward index in a position. - * Call updateFeesAndRewards before this to update the position to the newest accrued values. - * - * @category Instructions - * @param context - Context object containing services required to generate the instruction - * @param params - CollectRewardParams object - * @returns - Instruction to perform the action. - */ -export function collectRewardIx( - program: Program, - params: CollectRewardParams -): Instruction { - const { - whirlpool, - positionAuthority, - position, - positionTokenAccount, - rewardOwnerAccount, - rewardVault, - rewardIndex, - } = params; - - const ix = program.instruction.collectReward(rewardIndex, { - accounts: { - whirlpool, - positionAuthority, - position, - positionTokenAccount, - rewardOwnerAccount, - rewardVault, - tokenProgram: TOKEN_PROGRAM_ID, - }, - }); - - return { - instructions: [ix], - cleanupInstructions: [], - signers: [], - }; -} diff --git a/sdk/src/instructions/composites/collect-all-txn.ts b/sdk/src/instructions/composites/collect-all-txn.ts deleted file mode 100644 index bee6b0a..0000000 --- a/sdk/src/instructions/composites/collect-all-txn.ts +++ /dev/null @@ -1,310 +0,0 @@ -import { Address } from "@coral-xyz/anchor"; -import { - Instruction, - ResolvedTokenAddressInstruction, - TokenUtil, - TransactionBuilder, - ZERO, - resolveOrCreateATAs, -} from "@orca-so/common-sdk"; -import { NATIVE_MINT, getAssociatedTokenAddressSync } from "@solana/spl-token"; -import { PublicKey } from "@solana/web3.js"; -import { PositionData, WhirlpoolContext } from "../.."; -import { WhirlpoolIx } from "../../ix"; -import { PREFER_CACHE, WhirlpoolAccountFetchOptions } from "../../network/public/fetcher"; -import { WhirlpoolData } from "../../types/public"; -import { PDAUtil, PoolUtil, TickUtil } from "../../utils/public"; -import { checkMergedTransactionSizeIsValid, convertListToMap } from "../../utils/txn-utils"; -import { getTokenMintsFromWhirlpools } from "../../utils/whirlpool-ata-utils"; -import { updateFeesAndRewardsIx } from "../update-fees-and-rewards-ix"; - -/** - * Parameters to collect all fees and rewards from a list of positions. - * - * @category Instruction Types - * @param positionAddrs - An array of Whirlpool position addresses. - * @param receiver - The destination wallet that collected fees & reward will be sent to. Defaults to ctx.wallet key. - * @param positionOwner - The wallet key that contains the position token. Defaults to ctx.wallet key. - * @param positionAuthority - The authority key that can authorize operation on the position. Defaults to ctx.wallet key. - * @param payer - The key that will pay for the initialization of ATA token accounts. Defaults to ctx.wallet key. - */ -export type CollectAllPositionAddressParams = { - positions: Address[]; -} & CollectAllParams; - -/** - * Parameters to collect all fees and rewards from a list of positions. - * - * @category Instruction Types - * @param positions - An array of Whirlpool positions. - * @param receiver - The destination wallet that collected fees & reward will be sent to. Defaults to ctx.wallet key. - * @param positionOwner - The wallet key that contains the position token. Defaults to ctx.wallet key. - * @param positionAuthority - The authority key that can authorize operation on the position. Defaults to ctx.wallet key. - * @param payer - The key that will pay for the initialization of ATA token accounts. Defaults to ctx.wallet key. - */ -export type CollectAllPositionParams = { - positions: Record; -} & CollectAllParams; - -/** - * Common parameters between {@link CollectAllPositionParams} & {@link CollectAllPositionAddressParams} - * - * @category Instruction Types - * @param receiver - The destination wallet that collected fees & reward will be sent to. Defaults to ctx.wallet key. - * @param positionOwner - The wallet key that contains the position token. Defaults to ctx.wallet key. - * @param positionAuthority - The authority key that can authorize operation on the position. Defaults to ctx.wallet key. - * @param payer - The key that will pay for the initialization of ATA token accounts. Defaults to ctx.wallet key. - */ -export type CollectAllParams = { - receiver?: PublicKey; - positionOwner?: PublicKey; - positionAuthority?: PublicKey; - payer?: PublicKey; -}; - -/** - * Build a set of transactions to collect fees and rewards for a set of Whirlpool Positions. - * - * @category Instructions - * @experimental - * @param ctx - WhirlpoolContext object for the current environment. - * @param params - CollectAllPositionAddressParams object - * @param opts an {@link WhirlpoolAccountFetchOptions} object to define fetch and cache options when accessing on-chain accounts - * @returns A set of transaction-builders to resolve ATA for affliated tokens, collect fee & rewards for all positions. - */ -export async function collectAllForPositionAddressesTxns( - ctx: WhirlpoolContext, - params: CollectAllPositionAddressParams, - opts: WhirlpoolAccountFetchOptions = PREFER_CACHE -): Promise { - const { positions, ...rest } = params; - const fetchedPositions = await ctx.fetcher.getPositions(positions, opts); - - const positionMap: Record = {}; - fetchedPositions.forEach((pos, addr) => { - if (pos) { - positionMap[addr] = pos; - } - }); - - return collectAllForPositionsTxns(ctx, { positions: positionMap, ...rest }); -} - -/** - * Build a set of transactions to collect fees and rewards for a set of Whirlpool Positions. - * - * @experimental - * @param ctx - WhirlpoolContext object for the current environment. - * @param params - CollectAllPositionParams object - * @returns A set of transaction-builders to resolve ATA for affliated tokens, collect fee & rewards for all positions. - */ -export async function collectAllForPositionsTxns( - ctx: WhirlpoolContext, - params: CollectAllPositionParams -): Promise { - const { positions, receiver, positionAuthority, positionOwner, payer } = params; - const receiverKey = receiver ?? ctx.wallet.publicKey; - const positionAuthorityKey = positionAuthority ?? ctx.wallet.publicKey; - const positionOwnerKey = positionOwner ?? ctx.wallet.publicKey; - const payerKey = payer ?? ctx.wallet.publicKey; - const positionList = Object.entries(positions); - - if (positionList.length === 0) { - return []; - } - - const whirlpoolAddrs = positionList.map(([, pos]) => pos.whirlpool.toBase58()); - const whirlpools = await ctx.fetcher.getPools(whirlpoolAddrs, PREFER_CACHE); - - const allMints = getTokenMintsFromWhirlpools(Array.from(whirlpools.values())); - const accountExemption = await ctx.fetcher.getAccountRentExempt(); - - // resolvedAtas[mint] => Instruction & { address } - // if already ATA exists, Instruction will be EMPTY_INSTRUCTION - const resolvedAtas = convertListToMap( - await resolveOrCreateATAs( - ctx.connection, - receiverKey, - allMints.mintMap.map((tokenMint) => ({ tokenMint })), - async () => accountExemption, - payerKey, - true, // CreateIdempotent - ctx.accountResolverOpts.allowPDAOwnerAddress, - ctx.accountResolverOpts.createWrappedSolAccountMethod - ), - allMints.mintMap.map((mint) => mint.toBase58()) - ); - - const latestBlockhash = await ctx.connection.getLatestBlockhash(); - const txBuilders: TransactionBuilder[] = []; - - let posIndex = 0; - let pendingTxBuilder = null; - let touchedMints = null; - let reattempt = false; - while (posIndex < positionList.length) { - if (!pendingTxBuilder || !touchedMints) { - pendingTxBuilder = new TransactionBuilder(ctx.connection, ctx.wallet, ctx.txBuilderOpts); - touchedMints = new Set(); - resolvedAtas[NATIVE_MINT.toBase58()] = TokenUtil.createWrappedNativeAccountInstruction( - receiverKey, - ZERO, - accountExemption, - undefined, // use default - undefined, // use default - ctx.accountResolverOpts.createWrappedSolAccountMethod - ); - } - - // Build collect instructions - const [positionAddr, position] = positionList[posIndex]; - const collectIxForPosition = constructCollectIxForPosition( - ctx, - new PublicKey(positionAddr), - position, - whirlpools, - positionOwnerKey, - positionAuthorityKey, - resolvedAtas, - touchedMints - ); - const positionTxBuilder = new TransactionBuilder(ctx.connection, ctx.wallet, ctx.txBuilderOpts); - positionTxBuilder.addInstructions(collectIxForPosition); - - // Attempt to push the new instructions into the pending builder - // Iterate to the next position if possible - // Create a builder and reattempt if the current one is full. - const mergeable = await checkMergedTransactionSizeIsValid( - ctx, - [pendingTxBuilder, positionTxBuilder], - latestBlockhash - ); - if (mergeable) { - pendingTxBuilder.addInstruction(positionTxBuilder.compressIx(false)); - posIndex += 1; - reattempt = false; - } else { - if (reattempt) { - throw new Error( - `Unable to fit collection ix for ${position.positionMint.toBase58()} in a Transaction.` - ); - } - - txBuilders.push(pendingTxBuilder); - pendingTxBuilder = null; - touchedMints = null; - reattempt = true; - } - } - - if (pendingTxBuilder) { - txBuilders.push(pendingTxBuilder); - } - return txBuilders; -} - -// TODO: Once individual collect ix for positions is implemented, maybe migrate over if it can take custom ATA? -const constructCollectIxForPosition = ( - ctx: WhirlpoolContext, - positionKey: PublicKey, - position: PositionData, - whirlpools: ReadonlyMap, - positionOwner: PublicKey, - positionAuthority: PublicKey, - resolvedAtas: Record, - touchedMints: Set -) => { - const ixForPosition: Instruction[] = []; - const { - whirlpool: whirlpoolKey, - liquidity, - tickLowerIndex, - tickUpperIndex, - positionMint, - rewardInfos: positionRewardInfos, - } = position; - - const whirlpool = whirlpools.get(whirlpoolKey.toBase58()); - if (!whirlpool) { - throw new Error( - `Unable to process positionMint ${positionMint} - unable to derive whirlpool ${whirlpoolKey.toBase58()}` - ); - } - const { tickSpacing } = whirlpool; - const mintA = whirlpool.tokenMintA.toBase58(); - const mintB = whirlpool.tokenMintB.toBase58(); - - const positionTokenAccount = getAssociatedTokenAddressSync( - positionMint, - positionOwner, - ctx.accountResolverOpts.allowPDAOwnerAddress - ); - - // Update fee and reward values if necessary - if (!liquidity.eq(ZERO)) { - ixForPosition.push( - updateFeesAndRewardsIx(ctx.program, { - position: positionKey, - whirlpool: whirlpoolKey, - tickArrayLower: PDAUtil.getTickArray( - ctx.program.programId, - whirlpoolKey, - TickUtil.getStartTickIndex(tickLowerIndex, tickSpacing) - ).publicKey, - tickArrayUpper: PDAUtil.getTickArray( - ctx.program.programId, - whirlpoolKey, - TickUtil.getStartTickIndex(tickUpperIndex, tickSpacing) - ).publicKey, - }) - ); - } - - // Collect Fee - if (!touchedMints.has(mintA)) { - ixForPosition.push(resolvedAtas[mintA]); - touchedMints.add(mintA); - } - if (!touchedMints.has(mintB)) { - ixForPosition.push(resolvedAtas[mintB]); - touchedMints.add(mintB); - } - ixForPosition.push( - WhirlpoolIx.collectFeesIx(ctx.program, { - whirlpool: whirlpoolKey, - position: positionKey, - positionAuthority, - positionTokenAccount, - tokenOwnerAccountA: resolvedAtas[mintA].address, - tokenOwnerAccountB: resolvedAtas[mintB].address, - tokenVaultA: whirlpool.tokenVaultA, - tokenVaultB: whirlpool.tokenVaultB, - }) - ); - - // Collect Rewards - // TODO: handle empty vault values? - positionRewardInfos.forEach((_, index) => { - const rewardInfo = whirlpool.rewardInfos[index]; - if (PoolUtil.isRewardInitialized(rewardInfo)) { - const mintReward = rewardInfo.mint.toBase58(); - if (!touchedMints.has(mintReward)) { - ixForPosition.push(resolvedAtas[mintReward]); - touchedMints.add(mintReward); - } - ixForPosition.push( - WhirlpoolIx.collectRewardIx(ctx.program, { - whirlpool: whirlpoolKey, - position: positionKey, - positionAuthority, - positionTokenAccount, - rewardIndex: index, - rewardOwnerAccount: resolvedAtas[mintReward].address, - rewardVault: rewardInfo.vault, - }) - ); - } - }); - - return ixForPosition; -}; diff --git a/sdk/src/instructions/composites/collect-protocol-fees.ts b/sdk/src/instructions/composites/collect-protocol-fees.ts deleted file mode 100644 index 6a7aa52..0000000 --- a/sdk/src/instructions/composites/collect-protocol-fees.ts +++ /dev/null @@ -1,93 +0,0 @@ -import { Address } from "@coral-xyz/anchor"; -import { AddressUtil, Instruction, TokenUtil, TransactionBuilder } from "@orca-so/common-sdk"; -import { NATIVE_MINT } from "@solana/spl-token"; -import { PACKET_DATA_SIZE } from "@solana/web3.js"; -import { WhirlpoolContext } from "../.."; -import { PREFER_CACHE } from "../../network/public/fetcher"; -import { - TokenMintTypes, - addNativeMintHandlingIx, - getTokenMintsFromWhirlpools, - resolveAtaForMints, -} from "../../utils/whirlpool-ata-utils"; -import { collectProtocolFeesIx } from "../collect-protocol-fees-ix"; - -export async function collectProtocolFees( - ctx: WhirlpoolContext, - poolAddresses: Address[] -): Promise { - const receiverKey = ctx.wallet.publicKey; - const payerKey = ctx.wallet.publicKey; - - const whirlpoolDatas = Array.from( - (await ctx.fetcher.getPools(poolAddresses, PREFER_CACHE)).values() - ); - - const accountExemption = await ctx.fetcher.getAccountRentExempt(); - const { ataTokenAddresses, resolveAtaIxs } = await resolveAtaForMints(ctx, { - mints: getTokenMintsFromWhirlpools(whirlpoolDatas, TokenMintTypes.POOL_ONLY).mintMap, - accountExemption, - receiver: receiverKey, - payer: payerKey, - }); - - const latestBlockhash = await ctx.connection.getLatestBlockhash(); - let txBuilder = new TransactionBuilder( - ctx.connection, - ctx.wallet, - ctx.txBuilderOpts - ).addInstructions(resolveAtaIxs); - - const instructions: Instruction[] = []; - - for (const poolAddress of poolAddresses) { - const pool = await ctx.fetcher.getPool(poolAddress); - if (!pool) { - throw new Error(`Pool not found: ${poolAddress}`); - } - - const poolConfig = await ctx.fetcher.getConfig(pool.whirlpoolsConfig); - if (!poolConfig) { - throw new Error(`Config not found: ${pool.whirlpoolsConfig}`); - } - - if (poolConfig.collectProtocolFeesAuthority.toBase58() !== ctx.wallet.publicKey.toBase58()) { - throw new Error(`Wallet is not the collectProtocolFeesAuthority`); - } - - const poolHandlesNativeMint = - TokenUtil.isNativeMint(pool.tokenMintA) || TokenUtil.isNativeMint(pool.tokenMintB); - const txBuilderHasNativeMint = !!ataTokenAddresses[NATIVE_MINT.toBase58()]; - - if (poolHandlesNativeMint && !txBuilderHasNativeMint) { - addNativeMintHandlingIx( - txBuilder, - ataTokenAddresses, - receiverKey, - accountExemption, - ctx.accountResolverOpts.createWrappedSolAccountMethod - ); - } - - // add collect ixn - instructions.push( - collectProtocolFeesIx(ctx.program, { - whirlpoolsConfig: pool.whirlpoolsConfig, - whirlpool: AddressUtil.toPubKey(poolAddress), - tokenVaultA: pool.tokenVaultA, - tokenVaultB: pool.tokenVaultB, - tokenOwnerAccountA: ataTokenAddresses[pool.tokenMintA.toBase58()], - tokenOwnerAccountB: ataTokenAddresses[pool.tokenMintB.toBase58()], - collectProtocolFeesAuthority: poolConfig.collectProtocolFeesAuthority, - }) - ); - } - - txBuilder.addInstructions(instructions); - const txSize = await txBuilder.txnSize({ latestBlockhash }); - if (txSize > PACKET_DATA_SIZE) { - throw new Error(`Transaction size is too large: ${txSize}`); - } - - return txBuilder; -} diff --git a/sdk/src/instructions/composites/index.ts b/sdk/src/instructions/composites/index.ts deleted file mode 100644 index 0d0c5e0..0000000 --- a/sdk/src/instructions/composites/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from "./collect-all-txn"; -export * from "./collect-protocol-fees"; -export * from "./swap-async"; diff --git a/sdk/src/instructions/composites/swap-async.ts b/sdk/src/instructions/composites/swap-async.ts deleted file mode 100644 index 1938565..0000000 --- a/sdk/src/instructions/composites/swap-async.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { resolveOrCreateATAs, TransactionBuilder, ZERO } from "@orca-so/common-sdk"; -import { PublicKey } from "@solana/web3.js"; -import { SwapUtils, TickArrayUtil, Whirlpool, WhirlpoolContext } from "../.."; -import { WhirlpoolAccountFetchOptions } from "../../network/public/fetcher"; -import { SwapInput, swapIx } from "../swap-ix"; - -export type SwapAsyncParams = { - swapInput: SwapInput; - whirlpool: Whirlpool; - wallet: PublicKey; -}; - -/** - * Swap instruction builder method with resolveATA & additional checks. - * @param ctx - WhirlpoolContext object for the current environment. - * @param params - {@link SwapAsyncParams} - * @param opts - {@link WhirlpoolAccountFetchOptions} to use for account fetching. - * @returns - */ -export async function swapAsync( - ctx: WhirlpoolContext, - params: SwapAsyncParams, - opts: WhirlpoolAccountFetchOptions -): Promise { - const { wallet, whirlpool, swapInput } = params; - const { aToB, amount } = swapInput; - const txBuilder = new TransactionBuilder(ctx.connection, ctx.wallet, ctx.txBuilderOpts); - const tickArrayAddresses = [swapInput.tickArray0, swapInput.tickArray1, swapInput.tickArray2]; - - let uninitializedArrays = await TickArrayUtil.getUninitializedArraysString( - tickArrayAddresses, - ctx.fetcher, - opts - ); - if (uninitializedArrays) { - throw new Error(`TickArray addresses - [${uninitializedArrays}] need to be initialized.`); - } - - const data = whirlpool.getData(); - const [resolvedAtaA, resolvedAtaB] = await resolveOrCreateATAs( - ctx.connection, - wallet, - [ - { tokenMint: data.tokenMintA, wrappedSolAmountIn: aToB ? amount : ZERO }, - { tokenMint: data.tokenMintB, wrappedSolAmountIn: !aToB ? amount : ZERO }, - ], - () => ctx.fetcher.getAccountRentExempt(), - undefined, // use default - true, // use idempotent to allow multiple simultaneous calls - ctx.accountResolverOpts.allowPDAOwnerAddress, - ctx.accountResolverOpts.createWrappedSolAccountMethod - ); - const { address: ataAKey, ...tokenOwnerAccountAIx } = resolvedAtaA; - const { address: ataBKey, ...tokenOwnerAccountBIx } = resolvedAtaB; - txBuilder.addInstructions([tokenOwnerAccountAIx, tokenOwnerAccountBIx]); - const inputTokenAccount = aToB ? ataAKey : ataBKey; - const outputTokenAccount = aToB ? ataBKey : ataAKey; - - return txBuilder.addInstruction( - swapIx( - ctx.program, - SwapUtils.getSwapParamsFromQuote( - swapInput, - ctx, - whirlpool, - inputTokenAccount, - outputTokenAccount, - wallet - ) - ) - ); -} diff --git a/sdk/src/instructions/composites/swap-with-route.ts b/sdk/src/instructions/composites/swap-with-route.ts deleted file mode 100644 index 53118bb..0000000 --- a/sdk/src/instructions/composites/swap-with-route.ts +++ /dev/null @@ -1,384 +0,0 @@ -import { - AddressUtil, - EMPTY_INSTRUCTION, - Percentage, - ResolvedTokenAddressInstruction, - TokenUtil, - TransactionBuilder, - ZERO, -} from "@orca-so/common-sdk"; -import { - Account, - NATIVE_MINT, - createAssociatedTokenAccountInstruction, - createCloseAccountInstruction, - getAssociatedTokenAddressSync, -} from "@solana/spl-token"; -import { PublicKey, TransactionInstruction } from "@solana/web3.js"; -import BN from "bn.js"; -import { - AtaAccountInfo, - PDAUtil, - SubTradeRoute, - SwapUtils, - TickArrayUtil, - TradeRoute, - WhirlpoolContext, - twoHopSwapQuoteFromSwapQuotes, -} from "../.."; -import { PREFER_CACHE, WhirlpoolAccountFetchOptions } from "../../network/public/fetcher"; -import { adjustForSlippage } from "../../utils/position-util"; -import { contextOptionsToBuilderOptions } from "../../utils/txn-utils"; -import { swapIx } from "../swap-ix"; -import { twoHopSwapIx } from "../two-hop-swap-ix"; - -export type SwapFromRouteParams = { - route: TradeRoute; - slippage: Percentage; - wallet: PublicKey; - resolvedAtaAccounts: AtaAccountInfo[] | null; -}; - -export async function getSwapFromRoute( - ctx: WhirlpoolContext, - params: SwapFromRouteParams, - opts: WhirlpoolAccountFetchOptions = PREFER_CACHE, - txBuilder: TransactionBuilder = new TransactionBuilder( - ctx.connection, - ctx.wallet, - contextOptionsToBuilderOptions(ctx.opts) - ) -) { - const { route, wallet, resolvedAtaAccounts, slippage } = params; - const requiredAtas = new Set(); - const requiredIntermediateAtas = new Set(); - const requiredTickArrays = []; - let hasNativeMint = false; - let nativeMintAmount = new BN(0); - - function addOrNative(mint: string, amount: BN) { - if (mint === NATIVE_MINT.toBase58()) { - hasNativeMint = true; - nativeMintAmount = nativeMintAmount.add(amount); - } else { - requiredAtas.add(mint); - } - } - for (let i = 0; i < route.subRoutes.length; i++) { - const routeFragment = route.subRoutes[i]; - const slippageAdjustedRoute = adjustQuoteForSlippage(routeFragment, slippage); - if (slippageAdjustedRoute.hopQuotes.length == 1) { - const { quote, mintA, mintB } = slippageAdjustedRoute.hopQuotes[0]; - - requiredTickArrays.push(...[quote.tickArray0, quote.tickArray1, quote.tickArray2]); - - const inputAmount = quote.amountSpecifiedIsInput ? quote.amount : quote.otherAmountThreshold; - addOrNative(mintA.toString(), quote.aToB ? inputAmount : ZERO); - addOrNative(mintB.toString(), !quote.aToB ? inputAmount : ZERO); - } else if (slippageAdjustedRoute.hopQuotes.length == 2) { - const { - quote: quoteOne, - mintA: mintOneA, - mintB: mintOneB, - } = slippageAdjustedRoute.hopQuotes[0]; - const { - quote: quoteTwo, - mintA: mintTwoA, - mintB: mintTwoB, - } = slippageAdjustedRoute.hopQuotes[1]; - const twoHopQuote = twoHopSwapQuoteFromSwapQuotes(quoteOne, quoteTwo); - - requiredTickArrays.push( - ...[ - twoHopQuote.tickArrayOne0, - twoHopQuote.tickArrayOne1, - twoHopQuote.tickArrayOne2, - twoHopQuote.tickArrayTwo0, - twoHopQuote.tickArrayTwo1, - twoHopQuote.tickArrayTwo2, - ] - ); - - const inputAmount = quoteOne.amountSpecifiedIsInput - ? quoteOne.estimatedAmountIn - : quoteOne.otherAmountThreshold; - addOrNative(mintOneA.toString(), quoteOne.aToB ? inputAmount : ZERO); - addOrNative(mintOneB.toString(), !quoteOne.aToB ? inputAmount : ZERO); - addOrNative(mintTwoA.toString(), ZERO); - addOrNative(mintTwoB.toString(), ZERO); - requiredIntermediateAtas.add(quoteOne.aToB ? mintOneB.toString() : mintOneA.toString()); - } - } - - let uninitializedArrays = await TickArrayUtil.getUninitializedArraysString( - requiredTickArrays, - ctx.fetcher, - opts - ); - if (uninitializedArrays) { - throw new Error(`TickArray addresses - [${uninitializedArrays}] need to be initialized.`); - } - - // Handle non-native mints only first - requiredAtas.delete(NATIVE_MINT.toBase58()); - - const ataInstructionMap = await cachedResolveOrCreateNonNativeATAs( - wallet, - requiredAtas, - requiredIntermediateAtas, - (keys) => { - // TODO: if atas are not up to date, there might be failures, not sure if there's - // any good way, other than to re-fetch each time? - if (resolvedAtaAccounts != null) { - return Promise.resolve( - keys.map((key) => - resolvedAtaAccounts.find((ata) => ata.address?.toBase58() === key.toBase58()) - ) as Account[] - ); - } else { - return ctx.fetcher.getTokenInfos(keys, opts).then((result) => Array.from(result.values())); - } - }, - undefined, // use default - ctx.accountResolverOpts.allowPDAOwnerAddress - ); - - const ataIxes = Object.values(ataInstructionMap); - - if (hasNativeMint) { - const solIx = TokenUtil.createWrappedNativeAccountInstruction( - wallet, - nativeMintAmount, - await ctx.fetcher.getAccountRentExempt(), - undefined, // use default - undefined, // use default - ctx.accountResolverOpts.createWrappedSolAccountMethod - ); - txBuilder.addInstruction(solIx); - ataInstructionMap[NATIVE_MINT.toBase58()] = solIx; - } - - txBuilder.addInstructions(ataIxes); - - // Slippage adjustment - const slippageAdjustedQuotes = route.subRoutes.map((quote) => - adjustQuoteForSlippage(quote, slippage) - ); - - for (let i = 0; i < slippageAdjustedQuotes.length; i++) { - const routeFragment = slippageAdjustedQuotes[i]; - if (routeFragment.hopQuotes.length == 1) { - const { quote, whirlpool, mintA, mintB, vaultA, vaultB } = routeFragment.hopQuotes[0]; - const [wp, tokenVaultA, tokenVaultB] = AddressUtil.toPubKeys([whirlpool, vaultA, vaultB]); - const accA = ataInstructionMap[mintA.toString()].address; - const accB = ataInstructionMap[mintB.toString()].address; - const oraclePda = PDAUtil.getOracle(ctx.program.programId, wp); - txBuilder.addInstruction( - swapIx(ctx.program, { - whirlpool: wp, - tokenOwnerAccountA: accA, - tokenOwnerAccountB: accB, - tokenVaultA, - tokenVaultB, - oracle: oraclePda.publicKey, - tokenAuthority: wallet, - ...quote, - }) - ); - } else if (routeFragment.hopQuotes.length == 2) { - const { - quote: quoteOne, - whirlpool: whirlpoolOne, - mintA: mintOneA, - mintB: mintOneB, - vaultA: vaultOneA, - vaultB: vaultOneB, - } = routeFragment.hopQuotes[0]; - const { - quote: quoteTwo, - whirlpool: whirlpoolTwo, - mintA: mintTwoA, - mintB: mintTwoB, - vaultA: vaultTwoA, - vaultB: vaultTwoB, - } = routeFragment.hopQuotes[1]; - - const [wpOne, wpTwo, tokenVaultOneA, tokenVaultOneB, tokenVaultTwoA, tokenVaultTwoB] = - AddressUtil.toPubKeys([ - whirlpoolOne, - whirlpoolTwo, - vaultOneA, - vaultOneB, - vaultTwoA, - vaultTwoB, - ]); - const twoHopQuote = twoHopSwapQuoteFromSwapQuotes(quoteOne, quoteTwo); - - const oracleOne = PDAUtil.getOracle(ctx.program.programId, wpOne).publicKey; - const oracleTwo = PDAUtil.getOracle(ctx.program.programId, wpTwo).publicKey; - - const tokenOwnerAccountOneA = ataInstructionMap[mintOneA.toString()].address; - const tokenOwnerAccountOneB = ataInstructionMap[mintOneB.toString()].address; - const tokenOwnerAccountTwoA = ataInstructionMap[mintTwoA.toString()].address; - const tokenOwnerAccountTwoB = ataInstructionMap[mintTwoB.toString()].address; - txBuilder.addInstruction( - twoHopSwapIx(ctx.program, { - ...twoHopQuote, - whirlpoolOne: wpOne, - whirlpoolTwo: wpTwo, - tokenOwnerAccountOneA, - tokenOwnerAccountOneB, - tokenOwnerAccountTwoA, - tokenOwnerAccountTwoB, - tokenVaultOneA, - tokenVaultOneB, - tokenVaultTwoA, - tokenVaultTwoB, - oracleOne, - oracleTwo, - tokenAuthority: wallet, - }) - ); - } - } - return txBuilder; -} - -function adjustQuoteForSlippage(quote: SubTradeRoute, slippage: Percentage): SubTradeRoute { - const { hopQuotes } = quote; - if (hopQuotes.length === 1) { - return { - ...quote, - hopQuotes: [ - { - ...hopQuotes[0], - quote: { - ...hopQuotes[0].quote, - ...SwapUtils.calculateSwapAmountsFromQuote( - hopQuotes[0].quote.amount, - hopQuotes[0].quote.estimatedAmountIn, - hopQuotes[0].quote.estimatedAmountOut, - slippage, - hopQuotes[0].quote.amountSpecifiedIsInput - ), - }, - }, - ], - }; - } else if (quote.hopQuotes.length === 2) { - const swapQuoteOne = quote.hopQuotes[0]; - const swapQuoteTwo = quote.hopQuotes[1]; - const amountSpecifiedIsInput = swapQuoteOne.quote.amountSpecifiedIsInput; - - let updatedQuote = { - ...quote, - }; - - if (amountSpecifiedIsInput) { - updatedQuote.hopQuotes = [ - updatedQuote.hopQuotes[0], - { - ...swapQuoteTwo, - quote: { - ...swapQuoteTwo.quote, - otherAmountThreshold: adjustForSlippage( - swapQuoteTwo.quote.estimatedAmountOut, - slippage, - false - ), - }, - }, - ]; - } else { - updatedQuote.hopQuotes = [ - { - ...swapQuoteOne, - quote: { - ...swapQuoteOne.quote, - otherAmountThreshold: adjustForSlippage( - swapQuoteOne.quote.estimatedAmountIn, - slippage, - true - ), - }, - }, - updatedQuote.hopQuotes[1], - ]; - } - return updatedQuote; - } - - return quote; -} - -/** - * Internal duplicate of resolveOrCreateAta - * This could be ported over to common-sdk? - * - * IMPORTANT: wrappedSolAmountIn should only be used for input/source token that - * could be SOL. This is because when SOL is the output, it is the end - * destination, and thus does not need to be wrapped with an amount. - * - * @param ownerAddress The user's public key - * @param tokenMint Token mint address - * @param intermediateTokenMints Any mints from the tokenMint set that are intermediates in a two-hop swap - * @param getTokenAccounts Function to get token accounts - * @param payer Payer that would pay the rent for the creation of the ATAs - * @param allowPDAOwnerAddress Optional. Allow PDA to be used as the ATA owner address - * @returns - */ -async function cachedResolveOrCreateNonNativeATAs( - ownerAddress: PublicKey, - tokenMints: Set, - intermediateTokenMints: Set, - getTokenAccounts: (keys: PublicKey[]) => Promise>, - payer = ownerAddress, - allowPDAOwnerAddress: boolean = false -): Promise<{ [tokenMint: string]: ResolvedTokenAddressInstruction }> { - const instructionMap: { [tokenMint: string]: ResolvedTokenAddressInstruction } = {}; - const tokenMintArray = Array.from(tokenMints).map((tm) => new PublicKey(tm)); - const tokenAtas = tokenMintArray.map((tm) => - getAssociatedTokenAddressSync(tm, ownerAddress, allowPDAOwnerAddress) - ); - const tokenAccounts = await getTokenAccounts(tokenAtas); - tokenAccounts.forEach((tokenAccount, index) => { - const ataAddress = tokenAtas[index]!; - let resolvedInstruction; - if (tokenAccount) { - // ATA whose owner has been changed is abnormal entity. - // To prevent to send swap/withdraw/collect output to the ATA, an error should be thrown. - if (!tokenAccount.owner.equals(ownerAddress)) { - throw new Error(`ATA with change of ownership detected: ${ataAddress.toBase58()}`); - } - - resolvedInstruction = { address: ataAddress, ...EMPTY_INSTRUCTION }; - } else { - const tokenMint = tokenMintArray[index]; - const createAtaInstructions = [createAssociatedTokenAccountInstruction( - payer, - ataAddress, - ownerAddress, - tokenMint - )]; - - let cleanupInstructions: TransactionInstruction[] = []; - if (intermediateTokenMints.has(tokenMint.toBase58())) { - cleanupInstructions = [createCloseAccountInstruction( - ataAddress, - ownerAddress, - ownerAddress - )]; - } - - resolvedInstruction = { - address: ataAddress, - instructions: createAtaInstructions, - cleanupInstructions: cleanupInstructions, - signers: [], - }; - } - instructionMap[tokenMintArray[index].toBase58()] = resolvedInstruction; - }); - - return instructionMap; -} diff --git a/sdk/src/instructions/decrease-liquidity-ix.ts b/sdk/src/instructions/decrease-liquidity-ix.ts deleted file mode 100644 index 38d6e2e..0000000 --- a/sdk/src/instructions/decrease-liquidity-ix.ts +++ /dev/null @@ -1,101 +0,0 @@ -import { BN, Program } from "@coral-xyz/anchor"; -import { Instruction } from "@orca-so/common-sdk"; -import { TOKEN_PROGRAM_ID } from "@solana/spl-token"; -import { PublicKey } from "@solana/web3.js"; -import { Whirlpool } from "../artifacts/whirlpool"; - -/** - * Parameters to remove liquidity from a position. - * - * @category Instruction Types - * @param liquidityAmount - The total amount of Liquidity the user is withdrawing - * @param tokenMinA - The minimum amount of token A to remove from the position. - * @param tokenMinB - The minimum amount of token B to remove from the position. - * @param whirlpool - PublicKey for the whirlpool that the position will be opened for. - * @param position - PublicKey for the position will be opened for. - * @param positionTokenAccount - PublicKey for the position token's associated token address. - * @param tokenOwnerAccountA - PublicKey for the token A account that will be withdrawed from. - * @param tokenOwnerAccountB - PublicKey for the token B account that will be withdrawed from. - * @param tokenVaultA - PublicKey for the tokenA vault for this whirlpool. - * @param tokenVaultB - PublicKey for the tokenB vault for this whirlpool. - * @param tickArrayLower - PublicKey for the tick-array account that hosts the tick at the lower tick index. - * @param tickArrayUpper - PublicKey for the tick-array account that hosts the tick at the upper tick index. - * @param positionAuthority - authority that owns the token corresponding to this desired position. - */ -export type DecreaseLiquidityParams = { - whirlpool: PublicKey; - position: PublicKey; - positionTokenAccount: PublicKey; - tokenOwnerAccountA: PublicKey; - tokenOwnerAccountB: PublicKey; - tokenVaultA: PublicKey; - tokenVaultB: PublicKey; - tickArrayLower: PublicKey; - tickArrayUpper: PublicKey; - positionAuthority: PublicKey; -} & DecreaseLiquidityInput; - -/** - * @category Instruction Types - */ -export type DecreaseLiquidityInput = { - tokenMinA: BN; - tokenMinB: BN; - liquidityAmount: BN; -}; - -/** - * Remove liquidity to a position in the Whirlpool. - * - * #### Special Errors - * - `LiquidityZero` - Provided liquidity amount is zero. - * - `LiquidityTooHigh` - Provided liquidity exceeds u128::max. - * - `TokenMinSubceeded` - The required token to perform this operation subceeds the user defined amount. - * - * @category Instructions - * @param context - Context object containing services required to generate the instruction - * @param params - DecreaseLiquidityParams object - * @returns - Instruction to perform the action. - */ -export function decreaseLiquidityIx( - program: Program, - params: DecreaseLiquidityParams -): Instruction { - const { - liquidityAmount, - tokenMinA, - tokenMinB, - whirlpool, - positionAuthority, - position, - positionTokenAccount, - tokenOwnerAccountA, - tokenOwnerAccountB, - tokenVaultA, - tokenVaultB, - tickArrayLower, - tickArrayUpper, - } = params; - - const ix = program.instruction.decreaseLiquidity(liquidityAmount, tokenMinA, tokenMinB, { - accounts: { - whirlpool, - tokenProgram: TOKEN_PROGRAM_ID, - positionAuthority, - position, - positionTokenAccount, - tokenOwnerAccountA, - tokenOwnerAccountB, - tokenVaultA, - tokenVaultB, - tickArrayLower, - tickArrayUpper, - }, - }); - - return { - instructions: [ix], - cleanupInstructions: [], - signers: [], - }; -} diff --git a/sdk/src/instructions/delete-position-bundle-ix.ts b/sdk/src/instructions/delete-position-bundle-ix.ts deleted file mode 100644 index b79f57d..0000000 --- a/sdk/src/instructions/delete-position-bundle-ix.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { Program } from "@coral-xyz/anchor"; -import { Instruction } from "@orca-so/common-sdk"; -import { TOKEN_PROGRAM_ID } from "@solana/spl-token"; -import { PublicKey } from "@solana/web3.js"; -import { Whirlpool } from "../artifacts/whirlpool"; - -/** - * Parameters to delete a PositionBundle account. - * - * @category Instruction Types - * @param owner - PublicKey for the wallet that owns the position bundle token. - * @param positionBundle - PublicKey for the position bundle. - * @param positionBundleMint - PublicKey for the mint for the position bundle token. - * @param positionBundleTokenAccount - The associated token address for the position bundle token in the owners wallet. - * @param receiver - PublicKey for the wallet that will receive the rented lamports. - */ -export type DeletePositionBundleParams = { - owner: PublicKey; - positionBundle: PublicKey; - positionBundleMint: PublicKey; - positionBundleTokenAccount: PublicKey; - receiver: PublicKey; -}; - -/** - * Deletes a PositionBundle account. - * - * #### Special Errors - * `PositionBundleNotDeletable` - The provided position bundle has open positions. - * - * @category Instructions - * @param program - program object containing services required to generate the instruction - * @param params - DeletePositionBundleParams object - * @returns - Instruction to perform the action. - */ -export function deletePositionBundleIx( - program: Program, - params: DeletePositionBundleParams -): Instruction { - const { owner, positionBundle, positionBundleMint, positionBundleTokenAccount, receiver } = - params; - - const ix = program.instruction.deletePositionBundle({ - accounts: { - positionBundle: positionBundle, - positionBundleMint: positionBundleMint, - positionBundleTokenAccount, - positionBundleOwner: owner, - receiver, - tokenProgram: TOKEN_PROGRAM_ID, - }, - }); - - return { - instructions: [ix], - cleanupInstructions: [], - signers: [], - }; -} diff --git a/sdk/src/instructions/increase-liquidity-ix.ts b/sdk/src/instructions/increase-liquidity-ix.ts deleted file mode 100644 index 45301cf..0000000 --- a/sdk/src/instructions/increase-liquidity-ix.ts +++ /dev/null @@ -1,111 +0,0 @@ -import { Program } from "@coral-xyz/anchor"; -import { TOKEN_PROGRAM_ID } from "@solana/spl-token"; -import { PublicKey } from "@solana/web3.js"; -import BN from "bn.js"; -import { Whirlpool } from "../artifacts/whirlpool"; - -import { Instruction } from "@orca-so/common-sdk"; - -/** - * Parameters to increase liquidity for a position. - * - * @category Instruction Types - * @param liquidityAmount - The total amount of Liquidity the user is willing to deposit. - * @param tokenMaxA - The maximum amount of token A to add to the position. - * @param tokenMaxB - The maximum amount of token B to add to the position. - * @param whirlpool - PublicKey for the whirlpool that the position will be opened for. - * @param position - PublicKey for the position will be opened for. - * @param positionTokenAccount - PublicKey for the position token's associated token address. - * @param tokenOwnerAccountA - PublicKey for the token A account that will be withdrawed from. - * @param tokenOwnerAccountB - PublicKey for the token B account that will be withdrawed from. - * @param tokenVaultA - PublicKey for the tokenA vault for this whirlpool. - * @param tokenVaultB - PublicKey for the tokenB vault for this whirlpool. - * @param tickArrayLower - PublicKey for the tick-array account that hosts the tick at the lower tick index. - * @param tickArrayUpper - PublicKey for the tick-array account that hosts the tick at the upper tick index. - * @param positionAuthority - authority that owns the token corresponding to this desired position. - */ -export type IncreaseLiquidityParams = { - whirlpool: PublicKey; - position: PublicKey; - positionTokenAccount: PublicKey; - tokenOwnerAccountA: PublicKey; - tokenOwnerAccountB: PublicKey; - tokenVaultA: PublicKey; - tokenVaultB: PublicKey; - tickArrayLower: PublicKey; - tickArrayUpper: PublicKey; - positionAuthority: PublicKey; -} & IncreaseLiquidityInput; - -/** - * Input parameters to deposit liquidity into a position. - * - * This type is usually generated by a quote class to estimate the amount of tokens required to - * deposit a certain amount of liquidity into a position. - * - * @category Instruction Types - * @param tokenMaxA - the maximum amount of tokenA allowed to withdraw from the source wallet. - * @param tokenMaxB - the maximum amount of tokenB allowed to withdraw from the source wallet. - * @param liquidityAmount - the desired amount of liquidity to deposit into the position/ - */ -export type IncreaseLiquidityInput = { - tokenMaxA: BN; - tokenMaxB: BN; - liquidityAmount: BN; -}; - -/** - * Add liquidity to a position in the Whirlpool. - * - * #### Special Errors - * `LiquidityZero` - Provided liquidity amount is zero. - * `LiquidityTooHigh` - Provided liquidity exceeds u128::max. - * `TokenMaxExceeded` - The required token to perform this operation exceeds the user defined amount. - * - * @category Instructions - * @param context - Context object containing services required to generate the instruction - * @param params - IncreaseLiquidityParams object - * @returns - Instruction to perform the action. - */ -export function increaseLiquidityIx( - program: Program, - params: IncreaseLiquidityParams -): Instruction { - const { - liquidityAmount, - tokenMaxA, - tokenMaxB, - whirlpool, - positionAuthority, - position, - positionTokenAccount, - tokenOwnerAccountA, - tokenOwnerAccountB, - tokenVaultA, - tokenVaultB, - tickArrayLower, - tickArrayUpper, - } = params; - - const ix = program.instruction.increaseLiquidity(liquidityAmount, tokenMaxA, tokenMaxB, { - accounts: { - whirlpool, - tokenProgram: TOKEN_PROGRAM_ID, - positionAuthority, - position, - positionTokenAccount, - tokenOwnerAccountA, - tokenOwnerAccountB, - tokenVaultA, - tokenVaultB, - tickArrayLower, - tickArrayUpper, - }, - }); - - return { - instructions: [ix], - cleanupInstructions: [], - signers: [], - }; -} diff --git a/sdk/src/instructions/index.ts b/sdk/src/instructions/index.ts deleted file mode 100644 index b22aee1..0000000 --- a/sdk/src/instructions/index.ts +++ /dev/null @@ -1,30 +0,0 @@ -export * from "./close-bundled-position-ix"; -export * from "./close-position-ix"; -export * from "./collect-fees-ix"; -export * from "./collect-protocol-fees-ix"; -export * from "./collect-reward-ix"; -export * from "./composites"; -export * from "./decrease-liquidity-ix"; -export * from "./delete-position-bundle-ix"; -export * from "./increase-liquidity-ix"; -export * from "./initialize-config-ix"; -export * from "./initialize-fee-tier-ix"; -export * from "./initialize-pool-ix"; -export * from "./initialize-position-bundle-ix"; -export * from "./initialize-reward-ix"; -export * from "./initialize-tick-array-ix"; -export * from "./open-bundled-position-ix"; -export * from "./open-position-ix"; -export * from "./set-collect-protocol-fees-authority-ix"; -export * from "./set-default-fee-rate-ix"; -export * from "./set-default-protocol-fee-rate-ix"; -export * from "./set-fee-authority-ix"; -export * from "./set-fee-rate-ix"; -export * from "./set-protocol-fee-rate-ix"; -export * from "./set-reward-authority-by-super-authority-ix"; -export * from "./set-reward-authority-ix"; -export * from "./set-reward-emissions-ix"; -export * from "./set-reward-emissions-super-authority-ix"; -export * from "./swap-ix"; -export * from "./two-hop-swap-ix"; -export * from "./update-fees-and-rewards-ix"; diff --git a/sdk/src/instructions/initialize-config-ix.ts b/sdk/src/instructions/initialize-config-ix.ts deleted file mode 100644 index 69dc27b..0000000 --- a/sdk/src/instructions/initialize-config-ix.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { Program } from "@coral-xyz/anchor"; -import { Keypair, PublicKey, SystemProgram } from "@solana/web3.js"; -import { Whirlpool } from "../artifacts/whirlpool"; - -import { Instruction } from "@orca-so/common-sdk"; - -/** - * Parameters to initialize a WhirlpoolsConfig account. - * - * @category Instruction Types - * @param whirlpoolsConfigKeypair - Generated keypair for the WhirlpoolsConfig. - * @param feeAuthority - Authority authorized to initialize fee-tiers and set customs fees. - * @param collect_protocol_fees_authority - Authority authorized to collect protocol fees. - * @param rewardEmissionsSuperAuthority - Authority authorized to set reward authorities in pools. - * @param defaultProtocolFeeRate - The default protocol fee rate. Stored as a basis point of the total fees collected by feeRate. - * @param funder - The account that would fund the creation of this account - */ -export type InitConfigParams = { - whirlpoolsConfigKeypair: Keypair; - feeAuthority: PublicKey; - collectProtocolFeesAuthority: PublicKey; - rewardEmissionsSuperAuthority: PublicKey; - defaultProtocolFeeRate: number; - funder: PublicKey; -}; - -/** - * Initializes a WhirlpoolsConfig account that hosts info & authorities - * required to govern a set of Whirlpools. - * - * @category Instructions - * @param context - Context object containing services required to generate the instruction - * @param params - InitConfigParams object - * @returns - Instruction to perform the action. - */ -export function initializeConfigIx( - program: Program, - params: InitConfigParams -): Instruction { - const { - feeAuthority, - collectProtocolFeesAuthority, - rewardEmissionsSuperAuthority, - defaultProtocolFeeRate, - funder, - } = params; - - const ix = program.instruction.initializeConfig( - feeAuthority, - collectProtocolFeesAuthority, - rewardEmissionsSuperAuthority, - defaultProtocolFeeRate, - { - accounts: { - config: params.whirlpoolsConfigKeypair.publicKey, - funder, - systemProgram: SystemProgram.programId, - }, - } - ); - - return { - instructions: [ix], - cleanupInstructions: [], - signers: [params.whirlpoolsConfigKeypair], - }; -} diff --git a/sdk/src/instructions/initialize-fee-tier-ix.ts b/sdk/src/instructions/initialize-fee-tier-ix.ts deleted file mode 100644 index 48653a7..0000000 --- a/sdk/src/instructions/initialize-fee-tier-ix.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { Program } from "@coral-xyz/anchor"; -import { PDA } from "@orca-so/common-sdk"; -import { PublicKey, SystemProgram } from "@solana/web3.js"; -import { Whirlpool } from "../artifacts/whirlpool"; - -import { Instruction } from "@orca-so/common-sdk"; - -/** - * Parameters to initialize a FeeTier account. - * - * @category Instruction Types - * @param whirlpoolsConfig - PublicKey for the whirlpool config space that the fee-tier will be initialized for. - * @param feeTierPda - PDA for the fee-tier account that will be initialized - * @param tickSpacing - The tick spacing this fee tier recommends its default fee rate for. - * @param defaultFeeRate - The default fee rate for this fee-tier. Stored as a hundredths of a basis point. - * @param feeAuthority - Authority authorized to initialize fee-tiers and set customs fees. - * @param funder - The account that would fund the creation of this account - */ -export type InitFeeTierParams = { - whirlpoolsConfig: PublicKey; - feeTierPda: PDA; - tickSpacing: number; - defaultFeeRate: number; - feeAuthority: PublicKey; - funder: PublicKey; -}; - -/** - * Initializes a fee tier account usable by Whirlpools in this WhirlpoolsConfig space. - * - * Special Errors - * `FeeRateMaxExceeded` - If the provided default_fee_rate exceeds MAX_FEE_RATE. - * - * @category Instructions - * @param context - Context object containing services required to generate the instruction - * @param params - InitFeeTierParams object - * @returns - Instruction to perform the action. - */ -export function initializeFeeTierIx( - program: Program, - params: InitFeeTierParams -): Instruction { - const { feeTierPda, whirlpoolsConfig, tickSpacing, feeAuthority, defaultFeeRate, funder } = - params; - - const ix = program.instruction.initializeFeeTier(tickSpacing, defaultFeeRate, { - accounts: { - config: whirlpoolsConfig, - feeTier: feeTierPda.publicKey, - feeAuthority, - funder, - systemProgram: SystemProgram.programId, - }, - }); - - return { - instructions: [ix], - cleanupInstructions: [], - signers: [], - }; -} diff --git a/sdk/src/instructions/initialize-pool-ix.ts b/sdk/src/instructions/initialize-pool-ix.ts deleted file mode 100644 index e72541e..0000000 --- a/sdk/src/instructions/initialize-pool-ix.ts +++ /dev/null @@ -1,87 +0,0 @@ -import { BN, Program } from "@coral-xyz/anchor"; -import { Instruction, PDA } from "@orca-so/common-sdk"; -import { TOKEN_PROGRAM_ID } from "@solana/spl-token"; -import { Keypair, PublicKey, SystemProgram, SYSVAR_RENT_PUBKEY } from "@solana/web3.js"; -import { Whirlpool } from "../artifacts/whirlpool"; -import { WhirlpoolBumpsData } from "../types/public/anchor-types"; - -/** - * Parameters to initialize a Whirlpool account. - * - * @category Instruction Types - * @param initSqrtPrice - The desired initial sqrt-price for this pool - * @param whirlpoolsConfig - The public key for the WhirlpoolsConfig this pool is initialized in - * @param whirlpoolPda - PDA for the whirlpool account that would be initialized - * @param tokenMintA - Mint public key for token A - * @param tokenMintB - Mint public key for token B - * @param tokenVaultAKeypair - Keypair of the token A vault for this pool - * @param tokenVaultBKeypair - Keypair of the token B vault for this pool - * @param feeTierKey - PublicKey of the fee-tier account that this pool would use for the fee-rate - * @param tickSpacing - The desired tick spacing for this pool. - * @param funder - The account that would fund the creation of this account - */ -export type InitPoolParams = { - initSqrtPrice: BN; - whirlpoolsConfig: PublicKey; - whirlpoolPda: PDA; - tokenMintA: PublicKey; - tokenMintB: PublicKey; - tokenVaultAKeypair: Keypair; - tokenVaultBKeypair: Keypair; - feeTierKey: PublicKey; - tickSpacing: number; - funder: PublicKey; -}; - -/** - * Initializes a tick_array account to represent a tick-range in a Whirlpool. - * - * Special Errors - * `InvalidTokenMintOrder` - The order of mints have to be ordered by - * `SqrtPriceOutOfBounds` - provided initial_sqrt_price is not between 2^-64 to 2^64 - * - * @category Instructions - * @param context - Context object containing services required to generate the instruction - * @param params - InitPoolParams object - * @returns - Instruction to perform the action. - */ -export function initializePoolIx(program: Program, params: InitPoolParams): Instruction { - const { - initSqrtPrice, - tokenMintA, - tokenMintB, - whirlpoolsConfig, - whirlpoolPda, - feeTierKey, - tokenVaultAKeypair, - tokenVaultBKeypair, - tickSpacing, - funder, - } = params; - - const whirlpoolBumps: WhirlpoolBumpsData = { - whirlpoolBump: whirlpoolPda.bump, - }; - - const ix = program.instruction.initializePool(whirlpoolBumps, tickSpacing, initSqrtPrice, { - accounts: { - whirlpoolsConfig, - tokenMintA, - tokenMintB, - funder, - whirlpool: whirlpoolPda.publicKey, - tokenVaultA: tokenVaultAKeypair.publicKey, - tokenVaultB: tokenVaultBKeypair.publicKey, - feeTier: feeTierKey, - tokenProgram: TOKEN_PROGRAM_ID, - systemProgram: SystemProgram.programId, - rent: SYSVAR_RENT_PUBKEY, - }, - }); - - return { - instructions: [ix], - cleanupInstructions: [], - signers: [tokenVaultAKeypair, tokenVaultBKeypair], - }; -} diff --git a/sdk/src/instructions/initialize-position-bundle-ix.ts b/sdk/src/instructions/initialize-position-bundle-ix.ts deleted file mode 100644 index 3aaf7da..0000000 --- a/sdk/src/instructions/initialize-position-bundle-ix.ts +++ /dev/null @@ -1,112 +0,0 @@ -import * as anchor from "@coral-xyz/anchor"; -import { Program } from "@coral-xyz/anchor"; -import { Instruction, PDA } from "@orca-so/common-sdk"; -import { ASSOCIATED_TOKEN_PROGRAM_ID, TOKEN_PROGRAM_ID } from "@solana/spl-token"; -import { Keypair, PublicKey, SystemProgram } from "@solana/web3.js"; -import { METADATA_PROGRAM_ADDRESS, WHIRLPOOL_NFT_UPDATE_AUTH } from ".."; -import { Whirlpool } from "../artifacts/whirlpool"; - -/** - * Parameters to initialize a PositionBundle account. - * - * @category Instruction Types - * @param owner - PublicKey for the wallet that will host the minted position bundle token. - * @param positionBundlePda - PDA for the derived position bundle address. - * @param positionBundleMintKeypair - Keypair for the mint for the position bundle token. - * @param positionBundleTokenAccount - The associated token address for the position bundle token in the owners wallet. - * @param funder - The account that would fund the creation of this account - */ -export type InitializePositionBundleParams = { - owner: PublicKey; - positionBundlePda: PDA; - positionBundleMintKeypair: Keypair; - positionBundleTokenAccount: PublicKey; - funder: PublicKey; -}; - -/** - * Initializes a PositionBundle account. - * - * @category Instructions - * @param program - program object containing services required to generate the instruction - * @param params - InitializePositionBundleParams object - * @returns - Instruction to perform the action. - */ -export function initializePositionBundleIx( - program: Program, - params: InitializePositionBundleParams -): Instruction { - const { - owner, - positionBundlePda, - positionBundleMintKeypair, - positionBundleTokenAccount, - funder, - } = params; - - const ix = program.instruction.initializePositionBundle({ - accounts: { - positionBundle: positionBundlePda.publicKey, - positionBundleMint: positionBundleMintKeypair.publicKey, - positionBundleTokenAccount, - positionBundleOwner: owner, - funder, - associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID, - tokenProgram: TOKEN_PROGRAM_ID, - systemProgram: SystemProgram.programId, - rent: anchor.web3.SYSVAR_RENT_PUBKEY, - }, - }); - - return { - instructions: [ix], - cleanupInstructions: [], - signers: [positionBundleMintKeypair], - }; -} - -/** - * Initializes a PositionBundle account. - * Additional Metaplex metadata is appended to identify the token. - * - * @category Instructions - * @param program - program object containing services required to generate the instruction - * @param params - InitializePositionBundleParams object - * @returns - Instruction to perform the action. - */ -export function initializePositionBundleWithMetadataIx( - program: Program, - params: InitializePositionBundleParams & { positionBundleMetadataPda: PDA } -): Instruction { - const { - owner, - positionBundlePda, - positionBundleMintKeypair, - positionBundleTokenAccount, - positionBundleMetadataPda, - funder, - } = params; - - const ix = program.instruction.initializePositionBundleWithMetadata({ - accounts: { - positionBundle: positionBundlePda.publicKey, - positionBundleMint: positionBundleMintKeypair.publicKey, - positionBundleMetadata: positionBundleMetadataPda.publicKey, - positionBundleTokenAccount, - positionBundleOwner: owner, - funder, - associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID, - tokenProgram: TOKEN_PROGRAM_ID, - systemProgram: SystemProgram.programId, - rent: anchor.web3.SYSVAR_RENT_PUBKEY, - metadataProgram: METADATA_PROGRAM_ADDRESS, - metadataUpdateAuth: WHIRLPOOL_NFT_UPDATE_AUTH, - }, - }); - - return { - instructions: [ix], - cleanupInstructions: [], - signers: [positionBundleMintKeypair], - }; -} diff --git a/sdk/src/instructions/initialize-reward-ix.ts b/sdk/src/instructions/initialize-reward-ix.ts deleted file mode 100644 index 4be6998..0000000 --- a/sdk/src/instructions/initialize-reward-ix.ts +++ /dev/null @@ -1,67 +0,0 @@ -import * as anchor from "@coral-xyz/anchor"; -import { Program } from "@coral-xyz/anchor"; -import { TOKEN_PROGRAM_ID } from "@solana/spl-token"; -import { Keypair, PublicKey, SystemProgram } from "@solana/web3.js"; -import { Whirlpool } from "../artifacts/whirlpool"; - -import { Instruction } from "@orca-so/common-sdk"; - -/** - * Parameters to initialize a rewards for a Whirlpool - * - * @category Instruction Types - * @param whirlpool - PublicKey for the whirlpool config space that the fee-tier will be initialized for. - * @param rewardIndex - The reward index that we'd like to initialize. (0 <= index <= NUM_REWARDS). - * @param rewardMint - PublicKey for the reward mint that we'd use for the reward index. - * @param rewardVaultKeypair - Keypair of the vault for this reward index. - * @param rewardAuthority - Assigned authority by the reward_super_authority for the specified reward-index in this Whirlpool - * @param funder - The account that would fund the creation of this account - */ -export type InitializeRewardParams = { - whirlpool: PublicKey; - rewardIndex: number; - rewardMint: PublicKey; - rewardVaultKeypair: Keypair; - rewardAuthority: PublicKey; - funder: PublicKey; -}; - -/** - * Initialize reward for a Whirlpool. A pool can only support up to a set number of rewards. - * The initial emissionsPerSecond is set to 0. - * - * #### Special Errors - * - `InvalidRewardIndex` - If the provided reward index doesn't match the lowest uninitialized index in this pool, - * or exceeds NUM_REWARDS, or all reward slots for this pool has been initialized. - * - * @category Instructions - * @param context - Context object containing services required to generate the instruction - * @param params - InitializeRewardParams object - * @returns - Instruction to perform the action. - */ -export function initializeRewardIx( - program: Program, - params: InitializeRewardParams -): Instruction { - const { rewardAuthority, funder, whirlpool, rewardMint, rewardVaultKeypair, rewardIndex } = - params; - - const ix = program.instruction.initializeReward(rewardIndex, { - accounts: { - rewardAuthority, - funder, - whirlpool, - rewardMint, - rewardVault: rewardVaultKeypair.publicKey, - tokenProgram: TOKEN_PROGRAM_ID, - systemProgram: SystemProgram.programId, - rent: anchor.web3.SYSVAR_RENT_PUBKEY, - }, - }); - - return { - instructions: [ix], - cleanupInstructions: [], - signers: [rewardVaultKeypair], - }; -} diff --git a/sdk/src/instructions/initialize-tick-array-ix.ts b/sdk/src/instructions/initialize-tick-array-ix.ts deleted file mode 100644 index f50eaa8..0000000 --- a/sdk/src/instructions/initialize-tick-array-ix.ts +++ /dev/null @@ -1,54 +0,0 @@ -import * as anchor from "@coral-xyz/anchor"; -import { Program } from "@coral-xyz/anchor"; -import { Instruction, PDA } from "@orca-so/common-sdk"; -import { PublicKey } from "@solana/web3.js"; -import { Whirlpool } from "../artifacts/whirlpool"; - -/** - * Parameters to initialize a TickArray account. - * - * @category Instruction Types - * @param whirlpool - PublicKey for the whirlpool that the initialized tick-array will host ticks for. - * @param tickArrayPda - PDA for the tick array account that will be initialized - * @param startTick - The starting tick index for this tick-array. Has to be a multiple of TickArray size & the tick spacing of this pool. - * @param funder - The account that would fund the creation of this account - */ -export type InitTickArrayParams = { - whirlpool: PublicKey; - tickArrayPda: PDA; - startTick: number; - funder: PublicKey; -}; - -/** - * Initializes a TickArray account. - * - * #### Special Errors - * `InvalidStartTick` - if the provided start tick is out of bounds or is not a multiple of TICK_ARRAY_SIZE * tick spacing. - * - * @category Instructions - * @param context - Context object containing services required to generate the instruction - * @param params - InitTickArrayParams object - * @returns - Instruction to perform the action. - */ -export function initTickArrayIx( - program: Program, - params: InitTickArrayParams -): Instruction { - const { whirlpool, funder, tickArrayPda } = params; - - const ix = program.instruction.initializeTickArray(params.startTick, { - accounts: { - whirlpool, - funder, - tickArray: tickArrayPda.publicKey, - systemProgram: anchor.web3.SystemProgram.programId, - }, - }); - - return { - instructions: [ix], - cleanupInstructions: [], - signers: [], - }; -} diff --git a/sdk/src/instructions/open-bundled-position-ix.ts b/sdk/src/instructions/open-bundled-position-ix.ts deleted file mode 100644 index 0360cf1..0000000 --- a/sdk/src/instructions/open-bundled-position-ix.ts +++ /dev/null @@ -1,81 +0,0 @@ -import * as anchor from "@coral-xyz/anchor"; -import { Program } from "@coral-xyz/anchor"; -import { Instruction, PDA } from "@orca-so/common-sdk"; -import { PublicKey, SystemProgram } from "@solana/web3.js"; -import { Whirlpool } from "../artifacts/whirlpool"; - -/** - * Parameters to open a bundled position in a Whirlpool. - * - * @category Instruction Types - * @param whirlpool - PublicKey for the whirlpool that the bundled position will be opened for. - * @param bundledPositionPda - PDA for the derived bundled position address. - * @param positionBundle - PublicKey for the position bundle. - * @param positionBundleTokenAccount - The associated token address for the position bundle token in the owners wallet. - * @param positionBundleAuthority - authority that owns the token corresponding to this desired bundled position. - * @param bundleIndex - The bundle index that holds the bundled position. - * @param tickLowerIndex - The tick specifying the lower end of the bundled position range. - * @param tickUpperIndex - The tick specifying the upper end of the bundled position range. - * @param funder - The account that would fund the creation of this account - */ -export type OpenBundledPositionParams = { - whirlpool: PublicKey; - bundledPositionPda: PDA; - positionBundle: PublicKey; - positionBundleTokenAccount: PublicKey; - positionBundleAuthority: PublicKey; - bundleIndex: number; - tickLowerIndex: number; - tickUpperIndex: number; - funder: PublicKey; -}; - -/** - * Open a bundled position in a Whirlpool. - * No new tokens are issued because the owner of the position bundle becomes the owner of the position. - * The position will start off with 0 liquidity. - * - * #### Special Errors - * `InvalidBundleIndex` - If the provided bundle index is out of bounds. - * `InvalidTickIndex` - If a provided tick is out of bounds, out of order or not a multiple of the tick-spacing in this pool. - * - * @category Instructions - * @param program - program object containing services required to generate the instruction - * @param params - OpenBundledPositionParams object - * @returns - Instruction to perform the action. - */ -export function openBundledPositionIx( - program: Program, - params: OpenBundledPositionParams -): Instruction { - const { - whirlpool, - bundledPositionPda, - positionBundle, - positionBundleTokenAccount, - positionBundleAuthority, - bundleIndex, - tickLowerIndex, - tickUpperIndex, - funder, - } = params; - - const ix = program.instruction.openBundledPosition(bundleIndex, tickLowerIndex, tickUpperIndex, { - accounts: { - bundledPosition: bundledPositionPda.publicKey, - positionBundle, - positionBundleTokenAccount, - positionBundleAuthority, - whirlpool, - funder, - systemProgram: SystemProgram.programId, - rent: anchor.web3.SYSVAR_RENT_PUBKEY, - }, - }); - - return { - instructions: [ix], - cleanupInstructions: [], - signers: [], - }; -} diff --git a/sdk/src/instructions/open-position-ix.ts b/sdk/src/instructions/open-position-ix.ts deleted file mode 100644 index 798977a..0000000 --- a/sdk/src/instructions/open-position-ix.ts +++ /dev/null @@ -1,109 +0,0 @@ -import { Program } from "@coral-xyz/anchor"; -import { Instruction, PDA } from "@orca-so/common-sdk"; -import { PublicKey } from "@solana/web3.js"; -import { METADATA_PROGRAM_ADDRESS, WHIRLPOOL_NFT_UPDATE_AUTH } from ".."; -import { Whirlpool } from ".././artifacts/whirlpool"; -import { - OpenPositionBumpsData, - OpenPositionWithMetadataBumpsData, -} from "../types/public/anchor-types"; -import { openPositionAccounts } from "../utils/instructions-util"; - -/** - * Parameters to open a position in a Whirlpool. - * - * @category Instruction Types - * @param whirlpool - PublicKey for the whirlpool that the position will be opened for. - * @param ownerKey - PublicKey for the wallet that will host the minted position token. - * @param positionPda - PDA for the derived position address. - * @param positionMintAddress - PublicKey for the mint token for the Position token. - * @param positionTokenAccount - The associated token address for the position token in the owners wallet. - * @param tickLowerIndex - The tick specifying the lower end of the position range. - * @param tickUpperIndex - The tick specifying the upper end of the position range. - * @param funder - The account that would fund the creation of this account - */ -export type OpenPositionParams = { - whirlpool: PublicKey; - owner: PublicKey; - positionPda: PDA; - positionMintAddress: PublicKey; - positionTokenAccount: PublicKey; - tickLowerIndex: number; - tickUpperIndex: number; - funder: PublicKey; -}; - -/** - * Open a position in a Whirlpool. A unique token will be minted to represent the position in the users wallet. - * The position will start off with 0 liquidity. - * - * #### Special Errors - * `InvalidTickIndex` - If a provided tick is out of bounds, out of order or not a multiple of the tick-spacing in this pool. - * - * @category Instructions - * @param context - Context object containing services required to generate the instruction - * @param params - OpenPositionParams object - * @returns - Instruction to perform the action. - */ -export function openPositionIx( - program: Program, - params: OpenPositionParams -): Instruction { - const { positionPda, tickLowerIndex, tickUpperIndex } = params; - - const bumps: OpenPositionBumpsData = { - positionBump: positionPda.bump, - }; - - const ix = program.instruction.openPosition(bumps, tickLowerIndex, tickUpperIndex, { - accounts: openPositionAccounts(params), - }); - - // TODO: Require Keypair and auto sign this ix - return { - instructions: [ix], - cleanupInstructions: [], - signers: [], - }; -} - -/** - * Open a position in a Whirlpool. A unique token will be minted to represent the position - * in the users wallet. Additional Metaplex metadata is appended to identify the token. - * The position will start off with 0 liquidity. - * - * #### Special Errors - * `InvalidTickIndex` - If a provided tick is out of bounds, out of order or not a multiple of the tick-spacing in this pool. - * - * @category Instructions - * @param context - Context object containing services required to generate the instruction - * @param params - OpenPositionParams object and a derived PDA that hosts the position's metadata. - * @returns - Instruction to perform the action. - */ -export function openPositionWithMetadataIx( - program: Program, - params: OpenPositionParams & { metadataPda: PDA } -): Instruction { - const { positionPda, metadataPda, tickLowerIndex, tickUpperIndex } = params; - - const bumps: OpenPositionWithMetadataBumpsData = { - positionBump: positionPda.bump, - metadataBump: metadataPda.bump, - }; - - const ix = program.instruction.openPositionWithMetadata(bumps, tickLowerIndex, tickUpperIndex, { - accounts: { - ...openPositionAccounts(params), - positionMetadataAccount: metadataPda.publicKey, - metadataProgram: METADATA_PROGRAM_ADDRESS, - metadataUpdateAuth: WHIRLPOOL_NFT_UPDATE_AUTH, - }, - }); - - // TODO: Require Keypair and auto sign this ix - return { - instructions: [ix], - cleanupInstructions: [], - signers: [], - }; -} diff --git a/sdk/src/instructions/set-collect-protocol-fees-authority-ix.ts b/sdk/src/instructions/set-collect-protocol-fees-authority-ix.ts deleted file mode 100644 index f2daafe..0000000 --- a/sdk/src/instructions/set-collect-protocol-fees-authority-ix.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { Program } from "@coral-xyz/anchor"; -import { Instruction } from "@orca-so/common-sdk"; -import { PublicKey } from "@solana/web3.js"; -import { Whirlpool } from "../artifacts/whirlpool"; - -/** - * Parameters to set the collect fee authority in a WhirlpoolsConfig - * - * @category Instruction Types - * @param whirlpoolsConfig - The public key for the WhirlpoolsConfig this pool is initialized in - * @param collectProtocolFeesAuthority - The current collectProtocolFeesAuthority in the WhirlpoolsConfig - * @param newCollectProtocolFeesAuthority - The new collectProtocolFeesAuthority in the WhirlpoolsConfig - */ -export type SetCollectProtocolFeesAuthorityParams = { - whirlpoolsConfig: PublicKey; - collectProtocolFeesAuthority: PublicKey; - newCollectProtocolFeesAuthority: PublicKey; -}; - -/** - * Sets the fee authority to collect protocol fees for a WhirlpoolsConfig. - * Only the current collect protocol fee authority has permission to invoke this instruction. - * - * @category Instructions - * @param context - Context object containing services required to generate the instruction - * @param params - SetCollectProtocolFeesAuthorityParams object - * @returns - Instruction to perform the action. - */ -export function setCollectProtocolFeesAuthorityIx( - program: Program, - params: SetCollectProtocolFeesAuthorityParams -): Instruction { - const { whirlpoolsConfig, collectProtocolFeesAuthority, newCollectProtocolFeesAuthority } = - params; - - const ix = program.instruction.setCollectProtocolFeesAuthority({ - accounts: { - whirlpoolsConfig, - collectProtocolFeesAuthority, - newCollectProtocolFeesAuthority, - }, - }); - - return { - instructions: [ix], - cleanupInstructions: [], - signers: [], - }; -} diff --git a/sdk/src/instructions/set-default-fee-rate-ix.ts b/sdk/src/instructions/set-default-fee-rate-ix.ts deleted file mode 100644 index 60c6042..0000000 --- a/sdk/src/instructions/set-default-fee-rate-ix.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { Program } from "@coral-xyz/anchor"; -import { Instruction } from "@orca-so/common-sdk"; -import { PublicKey } from "@solana/web3.js"; -import { Whirlpool } from "../artifacts/whirlpool"; - -import { PDAUtil } from "../utils/public"; - -/** - * Parameters to set the default fee rate for a FeeTier. - * - * @category Instruction Types - * @param whirlpoolsConfig - The public key for the WhirlpoolsConfig this fee-tier is initialized in - * @param feeAuthority - Authority authorized in the WhirlpoolsConfig to set default fee rates. - * @param tickSpacing - The tick spacing of the fee-tier that we would like to update. - * @param defaultFeeRate - The new default fee rate for this fee-tier. Stored as a hundredths of a basis point. - */ -export type SetDefaultFeeRateParams = { - whirlpoolsConfig: PublicKey; - feeAuthority: PublicKey; - tickSpacing: number; - defaultFeeRate: number; -}; - -/** - * Updates a fee tier account with a new default fee rate. The new rate will not retroactively update - * initialized pools. - * - * #### Special Errors - * - `FeeRateMaxExceeded` - If the provided default_fee_rate exceeds MAX_FEE_RATE. - * - * @category Instructions - * @param context - Context object containing services required to generate the instruction - * @param params - SetDefaultFeeRateParams object - * @returns - Instruction to perform the action. - */ -export function setDefaultFeeRateIx( - program: Program, - params: SetDefaultFeeRateParams -): Instruction { - const { whirlpoolsConfig, feeAuthority, tickSpacing, defaultFeeRate } = params; - - const feeTierPda = PDAUtil.getFeeTier(program.programId, whirlpoolsConfig, tickSpacing); - - const ix = program.instruction.setDefaultFeeRate(defaultFeeRate, { - accounts: { - whirlpoolsConfig, - feeTier: feeTierPda.publicKey, - feeAuthority, - }, - }); - - return { - instructions: [ix], - cleanupInstructions: [], - signers: [], - }; -} diff --git a/sdk/src/instructions/set-default-protocol-fee-rate-ix.ts b/sdk/src/instructions/set-default-protocol-fee-rate-ix.ts deleted file mode 100644 index 272ed19..0000000 --- a/sdk/src/instructions/set-default-protocol-fee-rate-ix.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { Program } from "@coral-xyz/anchor"; -import { Instruction } from "@orca-so/common-sdk"; -import { PublicKey } from "@solana/web3.js"; -import { Whirlpool } from "../artifacts/whirlpool"; - -/** - * Parameters to set the default fee rate for a FeeTier. - * - * @category Instruction Types - * @param whirlpoolsConfig - The public key for the WhirlpoolsConfig this pool is initialized in - * @param feeAuthority - Authority authorized in the WhirlpoolsConfig to set default fee rates. - * @param defaultProtocolFeeRate - The new default protocol fee rate for this config. Stored as a basis point of the total fees collected by feeRate. - */ -export type SetDefaultProtocolFeeRateParams = { - whirlpoolsConfig: PublicKey; - feeAuthority: PublicKey; - defaultProtocolFeeRate: number; -}; - -/** - * Updates a WhirlpoolsConfig with a new default protocol fee rate. The new rate will not retroactively update - * initialized pools. - * - * #### Special Errors - * - `ProtocolFeeRateMaxExceeded` - If the provided default_protocol_fee_rate exceeds MAX_PROTOCOL_FEE_RATE. - * - * @category Instructions - * @param context - Context object containing services required to generate the instruction - * @param params - SetDefaultFeeRateParams object - * @returns - Instruction to perform the action. - */ -export function setDefaultProtocolFeeRateIx( - program: Program, - params: SetDefaultProtocolFeeRateParams -): Instruction { - const { whirlpoolsConfig, feeAuthority, defaultProtocolFeeRate } = params; - - const ix = program.instruction.setDefaultProtocolFeeRate(defaultProtocolFeeRate, { - accounts: { - whirlpoolsConfig, - feeAuthority, - }, - }); - - return { - instructions: [ix], - cleanupInstructions: [], - signers: [], - }; -} diff --git a/sdk/src/instructions/set-fee-authority-ix.ts b/sdk/src/instructions/set-fee-authority-ix.ts deleted file mode 100644 index 2311305..0000000 --- a/sdk/src/instructions/set-fee-authority-ix.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { Program } from "@coral-xyz/anchor"; -import { Instruction } from "@orca-so/common-sdk"; -import { PublicKey } from "@solana/web3.js"; -import { Whirlpool } from "../artifacts/whirlpool"; - -/** - * Parameters to set the fee authority in a WhirlpoolsConfig - * - * @category Instruction Types - * @param whirlpoolsConfig - The public key for the WhirlpoolsConfig this pool is initialized in - * @param feeAuthority - The current feeAuthority in the WhirlpoolsConfig - * @param newFeeAuthority - The new feeAuthority in the WhirlpoolsConfig - */ -export type SetFeeAuthorityParams = { - whirlpoolsConfig: PublicKey; - feeAuthority: PublicKey; - newFeeAuthority: PublicKey; -}; - -/** - * Sets the fee authority for a WhirlpoolsConfig. - * The fee authority can set the fee & protocol fee rate for individual pools or set the default fee rate for newly minted pools. - * Only the current fee authority has permission to invoke this instruction. - * - * @category Instructions - * @param context - Context object containing services required to generate the instruction - * @param params - SetFeeAuthorityParams object - * @returns - Instruction to perform the action. - */ -export function setFeeAuthorityIx( - program: Program, - params: SetFeeAuthorityParams -): Instruction { - const { whirlpoolsConfig, feeAuthority, newFeeAuthority } = params; - - const ix = program.instruction.setFeeAuthority({ - accounts: { - whirlpoolsConfig, - feeAuthority, - newFeeAuthority, - }, - }); - - return { - instructions: [ix], - cleanupInstructions: [], - signers: [], - }; -} diff --git a/sdk/src/instructions/set-fee-rate-ix.ts b/sdk/src/instructions/set-fee-rate-ix.ts deleted file mode 100644 index e7194ea..0000000 --- a/sdk/src/instructions/set-fee-rate-ix.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { Program } from "@coral-xyz/anchor"; -import { Instruction } from "@orca-so/common-sdk"; -import { PublicKey } from "@solana/web3.js"; -import { Whirlpool } from "../artifacts/whirlpool"; - -/** - * Parameters to set fee rate for a Whirlpool. - * - * @category Instruction Types - * @param whirlpool - PublicKey for the whirlpool to update. This whirlpool has to be part of the provided WhirlpoolsConfig space. - * @param whirlpoolsConfig - The public key for the WhirlpoolsConfig this pool is initialized in - * @param feeAuthority - Authority authorized in the WhirlpoolsConfig to set default fee rates. - * @param feeRate - The new fee rate for this fee-tier. Stored as a hundredths of a basis point. - */ -export type SetFeeRateParams = { - whirlpool: PublicKey; - whirlpoolsConfig: PublicKey; - feeAuthority: PublicKey; - feeRate: number; -}; - -/** - * Sets the fee rate for a Whirlpool. - * Only the current fee authority has permission to invoke this instruction. - * - * #### Special Errors - * - `FeeRateMaxExceeded` - If the provided fee_rate exceeds MAX_FEE_RATE. - * - * @category Instructions - * @param context - Context object containing services required to generate the instruction - * @param params - SetFeeRateParams object - * @returns - Instruction to perform the action. - */ -export function setFeeRateIx(program: Program, params: SetFeeRateParams): Instruction { - const { whirlpoolsConfig, whirlpool, feeAuthority, feeRate } = params; - - const ix = program.instruction.setFeeRate(feeRate, { - accounts: { - whirlpoolsConfig, - whirlpool, - feeAuthority, - }, - }); - - return { - instructions: [ix], - cleanupInstructions: [], - signers: [], - }; -} diff --git a/sdk/src/instructions/set-protocol-fee-rate-ix.ts b/sdk/src/instructions/set-protocol-fee-rate-ix.ts deleted file mode 100644 index 13147ae..0000000 --- a/sdk/src/instructions/set-protocol-fee-rate-ix.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { Program } from "@coral-xyz/anchor"; -import { Instruction } from "@orca-so/common-sdk"; -import { PublicKey } from "@solana/web3.js"; -import { Whirlpool } from "../artifacts/whirlpool"; - -/** - * Parameters to set fee rate for a Whirlpool. - * - * @category Instruction Types - * @param whirlpool - PublicKey for the whirlpool to update. This whirlpool has to be part of the provided WhirlpoolsConfig space. - * @param whirlpoolsConfig - The public key for the WhirlpoolsConfig this pool is initialized in - * @param feeAuthority - Authority authorized in the WhirlpoolsConfig to set default fee rates. - * @param protocolFeeRate - The new default protocol fee rate for this pool. Stored as a basis point of the total fees collected by feeRate. - */ -export type SetProtocolFeeRateParams = { - whirlpool: PublicKey; - whirlpoolsConfig: PublicKey; - feeAuthority: PublicKey; - protocolFeeRate: number; -}; - -/** - * Sets the protocol fee rate for a Whirlpool. - * Only the current fee authority has permission to invoke this instruction. - * - * #### Special Errors - * - `ProtocolFeeRateMaxExceeded` - If the provided default_protocol_fee_rate exceeds MAX_PROTOCOL_FEE_RATE. - * - * @category Instructions - * @param context - Context object containing services required to generate the instruction - * @param params - SetFeeRateParams object - * @returns - Instruction to perform the action. - */ -export function setProtocolFeeRateIx( - program: Program, - params: SetProtocolFeeRateParams -): Instruction { - const { whirlpoolsConfig, whirlpool, feeAuthority, protocolFeeRate } = params; - - const ix = program.instruction.setProtocolFeeRate(protocolFeeRate, { - accounts: { - whirlpoolsConfig, - whirlpool, - feeAuthority, - }, - }); - - return { - instructions: [ix], - cleanupInstructions: [], - signers: [], - }; -} diff --git a/sdk/src/instructions/set-reward-authority-by-super-authority-ix.ts b/sdk/src/instructions/set-reward-authority-by-super-authority-ix.ts deleted file mode 100644 index 77869ee..0000000 --- a/sdk/src/instructions/set-reward-authority-by-super-authority-ix.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { Program } from "@coral-xyz/anchor"; -import { Instruction } from "@orca-so/common-sdk"; -import { PublicKey } from "@solana/web3.js"; -import { Whirlpool } from "../artifacts/whirlpool"; - -/** - * Parameters to update the reward authority at a particular rewardIndex on a Whirlpool. - * - * @category Instruction Types - * @param whirlpool - PublicKey for the whirlpool to update. This whirlpool has to be part of the provided WhirlpoolsConfig space. - * @param whirlpoolsConfig - The public key for the WhirlpoolsConfig this pool is initialized in - * @param rewardIndex - The reward index that we'd like to update. (0 <= index <= NUM_REWARDS). - * @param rewardEmissionsSuperAuthority - The current rewardEmissionsSuperAuthority in the WhirlpoolsConfig - * @param newRewardAuthority - The new rewardAuthority in the Whirlpool at the rewardIndex - */ -export type SetRewardAuthorityBySuperAuthorityParams = { - whirlpool: PublicKey; - whirlpoolsConfig: PublicKey; - rewardIndex: number; - rewardEmissionsSuperAuthority: PublicKey; - newRewardAuthority: PublicKey; -}; - -/** - * Set the whirlpool reward authority at the provided `reward_index`. - * Only the current reward super authority has permission to invoke this instruction. - * - * #### Special Errors - * - `InvalidRewardIndex` - If the provided reward index doesn't match the lowest uninitialized index in this pool, - * or exceeds NUM_REWARDS. - * - * @category Instructions - * @param context - Context object containing services required to generate the instruction - * @param params - SetRewardAuthorityParams object - * @returns - Instruction to perform the action. - */ -export function setRewardAuthorityBySuperAuthorityIx( - program: Program, - params: SetRewardAuthorityBySuperAuthorityParams -): Instruction { - const { - whirlpoolsConfig, - whirlpool, - rewardEmissionsSuperAuthority, - newRewardAuthority, - rewardIndex, - } = params; - - const ix = program.instruction.setRewardAuthorityBySuperAuthority(rewardIndex, { - accounts: { - whirlpoolsConfig, - whirlpool, - rewardEmissionsSuperAuthority, - newRewardAuthority, - }, - }); - - return { - instructions: [ix], - cleanupInstructions: [], - signers: [], - }; -} diff --git a/sdk/src/instructions/set-reward-authority-ix.ts b/sdk/src/instructions/set-reward-authority-ix.ts deleted file mode 100644 index c4d1713..0000000 --- a/sdk/src/instructions/set-reward-authority-ix.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { Program } from "@coral-xyz/anchor"; -import { Instruction } from "@orca-so/common-sdk"; -import { PublicKey } from "@solana/web3.js"; -import { Whirlpool } from "../artifacts/whirlpool"; - -/** - * Parameters to update the reward authority at a particular rewardIndex on a Whirlpool. - * - * @category Instruction Types - * @param whirlpool - PublicKey for the whirlpool to update. - * @param rewardIndex - The reward index that we'd like to update. (0 <= index <= NUM_REWARDS). - * @param rewardAuthority - The current rewardAuthority in the Whirlpool at the rewardIndex - * @param newRewardAuthority - The new rewardAuthority in the Whirlpool at the rewardIndex - */ -export type SetRewardAuthorityParams = { - whirlpool: PublicKey; - rewardIndex: number; - rewardAuthority: PublicKey; - newRewardAuthority: PublicKey; -}; - -/** - * Set the whirlpool reward authority at the provided `reward_index`. - * Only the current reward authority for this reward index has permission to invoke this instruction. - * - * #### Special Errors - * - `InvalidRewardIndex` - If the provided reward index doesn't match the lowest uninitialized index in this pool, - * or exceeds NUM_REWARDS. - * - * @category Instructions - * @param context - Context object containing services required to generate the instruction - * @param params - SetRewardAuthorityParams object - * @returns - Instruction to perform the action. - */ -export function setRewardAuthorityIx( - program: Program, - params: SetRewardAuthorityParams -): Instruction { - const { whirlpool, rewardAuthority, newRewardAuthority, rewardIndex } = params; - const ix = program.instruction.setRewardAuthority(rewardIndex, { - accounts: { - whirlpool, - rewardAuthority, - newRewardAuthority, - }, - }); - - return { - instructions: [ix], - cleanupInstructions: [], - signers: [], - }; -} diff --git a/sdk/src/instructions/set-reward-emissions-ix.ts b/sdk/src/instructions/set-reward-emissions-ix.ts deleted file mode 100644 index 0c453cc..0000000 --- a/sdk/src/instructions/set-reward-emissions-ix.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { BN, Program } from "@coral-xyz/anchor"; -import { Instruction } from "@orca-so/common-sdk"; -import { PublicKey } from "@solana/web3.js"; -import { Whirlpool } from "../artifacts/whirlpool"; - -/** - * Parameters to set rewards emissions for a reward in a Whirlpool - * - * @category Instruction Types - * @param whirlpool - PublicKey for the whirlpool which the reward resides in. - * @param rewardIndex - The reward index that we'd like to initialize. (0 <= index <= NUM_REWARDS). - * @param rewardVaultKey - PublicKey of the vault for this reward index. - * @param rewardAuthority - Assigned authority by the reward_super_authority for the specified reward-index in this Whirlpool - * @param emissionsPerSecondX64 - The new emissions per second to set for this reward. - */ -export type SetRewardEmissionsParams = { - whirlpool: PublicKey; - rewardIndex: number; - rewardVaultKey: PublicKey; - rewardAuthority: PublicKey; - emissionsPerSecondX64: BN; -}; - -/** - * Set the reward emissions for a reward in a Whirlpool. - * - * #### Special Errors - * - `RewardVaultAmountInsufficient` - The amount of rewards in the reward vault cannot emit more than a day of desired emissions. - * - `InvalidTimestamp` - Provided timestamp is not in order with the previous timestamp. - * - `InvalidRewardIndex` - If the provided reward index doesn't match the lowest uninitialized index in this pool, - * or exceeds NUM_REWARDS. - * - * @category Instructions - * @param context - Context object containing services required to generate the instruction - * @param params - SetRewardEmissionsParams object - * @returns - Instruction to perform the action. - */ -export function setRewardEmissionsIx( - program: Program, - params: SetRewardEmissionsParams -): Instruction { - const { - rewardAuthority, - whirlpool, - rewardIndex, - rewardVaultKey: rewardVault, - emissionsPerSecondX64, - } = params; - - const ix = program.instruction.setRewardEmissions(rewardIndex, emissionsPerSecondX64, { - accounts: { - rewardAuthority, - whirlpool, - rewardVault, - }, - }); - - return { - instructions: [ix], - cleanupInstructions: [], - signers: [], - }; -} diff --git a/sdk/src/instructions/set-reward-emissions-super-authority-ix.ts b/sdk/src/instructions/set-reward-emissions-super-authority-ix.ts deleted file mode 100644 index 23c563f..0000000 --- a/sdk/src/instructions/set-reward-emissions-super-authority-ix.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { Program } from "@coral-xyz/anchor"; -import { Instruction } from "@orca-so/common-sdk"; -import { PublicKey } from "@solana/web3.js"; -import { Whirlpool } from "../artifacts/whirlpool"; - -/** - * Parameters to set rewards emissions for a reward in a Whirlpool - * - * @category Instruction Types - * @param whirlpoolsConfig - PublicKey for the WhirlpoolsConfig that we want to update. - * @param rewardEmissionsSuperAuthority - Current reward emission super authority in this WhirlpoolsConfig - * @param newRewardEmissionsSuperAuthority - New reward emission super authority for this WhirlpoolsConfig - */ -export type SetRewardEmissionsSuperAuthorityParams = { - whirlpoolsConfig: PublicKey; - rewardEmissionsSuperAuthority: PublicKey; - newRewardEmissionsSuperAuthority: PublicKey; -}; - -/** - * Set the whirlpool reward super authority for a WhirlpoolsConfig - * Only the current reward super authority has permission to invoke this instruction. - * This instruction will not change the authority on any `WhirlpoolRewardInfo` whirlpool rewards. - * - * @category Instructions - * @param context - Context object containing services required to generate the instruction - * @param params - SetRewardEmissionsSuperAuthorityParams object - * @returns - Instruction to perform the action. - */ -export function setRewardEmissionsSuperAuthorityIx( - program: Program, - params: SetRewardEmissionsSuperAuthorityParams -): Instruction { - const { whirlpoolsConfig, rewardEmissionsSuperAuthority, newRewardEmissionsSuperAuthority } = - params; - - const ix = program.instruction.setRewardEmissionsSuperAuthority({ - accounts: { - whirlpoolsConfig, - rewardEmissionsSuperAuthority: rewardEmissionsSuperAuthority, - newRewardEmissionsSuperAuthority, - }, - }); - - return { - instructions: [ix], - cleanupInstructions: [], - signers: [], - }; -} diff --git a/sdk/src/instructions/swap-ix.ts b/sdk/src/instructions/swap-ix.ts deleted file mode 100644 index b943f64..0000000 --- a/sdk/src/instructions/swap-ix.ts +++ /dev/null @@ -1,133 +0,0 @@ -import { Program } from "@coral-xyz/anchor"; -import { Instruction } from "@orca-so/common-sdk"; -import { TOKEN_PROGRAM_ID } from "@solana/spl-token"; -import { PublicKey } from "@solana/web3.js"; -import BN from "bn.js"; -import { Whirlpool } from "../artifacts/whirlpool"; - -/** - * Raw parameters and accounts to swap on a Whirlpool - * - * @category Instruction Types - * @param swapInput - Parameters in {@link SwapInput} - * @param whirlpool - PublicKey for the whirlpool that the swap will occur on - * @param tokenOwnerAccountA - PublicKey for the associated token account for tokenA in the collection wallet - * @param tokenOwnerAccountB - PublicKey for the associated token account for tokenB in the collection wallet - * @param tokenVaultA - PublicKey for the tokenA vault for this whirlpool. - * @param tokenVaultB - PublicKey for the tokenB vault for this whirlpool. - * @param oracle - PublicKey for the oracle account for this Whirlpool. - * @param tokenAuthority - authority to withdraw tokens from the input token account - */ -export type SwapParams = SwapInput & { - whirlpool: PublicKey; - tokenOwnerAccountA: PublicKey; - tokenOwnerAccountB: PublicKey; - tokenVaultA: PublicKey; - tokenVaultB: PublicKey; - oracle: PublicKey; - tokenAuthority: PublicKey; -}; - -/** - * Parameters that describe the nature of a swap on a Whirlpool. - * - * @category Instruction Types - * @param aToB - The direction of the swap. True if swapping from A to B. False if swapping from B to A. - * @param amountSpecifiedIsInput - Specifies the token the parameter `amount`represents. If true, the amount represents - * the input token of the swap. - * @param amount - The amount of input or output token to swap from (depending on amountSpecifiedIsInput). - * @param otherAmountThreshold - The maximum/minimum of input/output token to swap into (depending on amountSpecifiedIsInput). - * @param sqrtPriceLimit - The maximum/minimum price the swap will swap to. - * @param tickArray0 - PublicKey of the tick-array where the Whirlpool's currentTickIndex resides in - * @param tickArray1 - The next tick-array in the swap direction. If the swap will not reach the next tick-aray, input the same array as tickArray0. - * @param tickArray2 - The next tick-array in the swap direction after tickArray2. If the swap will not reach the next tick-aray, input the same array as tickArray1. - */ -export type SwapInput = { - amount: BN; - otherAmountThreshold: BN; - sqrtPriceLimit: BN; - amountSpecifiedIsInput: boolean; - aToB: boolean; - tickArray0: PublicKey; - tickArray1: PublicKey; - tickArray2: PublicKey; -}; - -/** - * Parameters to swap on a Whirlpool with developer fees - * - * @category Instruction Types - * @param swapInput - Parameters in {@link SwapInput} - * @param devFeeAmount - FeeAmount (developer fees) charged on this swap - */ -export type DevFeeSwapInput = SwapInput & { - devFeeAmount: BN; -}; - -/** - * Perform a swap in this Whirlpool - * - * #### Special Errors - * - `ZeroTradableAmount` - User provided parameter `amount` is 0. - * - `InvalidSqrtPriceLimitDirection` - User provided parameter `sqrt_price_limit` does not match the direction of the trade. - * - `SqrtPriceOutOfBounds` - User provided parameter `sqrt_price_limit` is over Whirlppool's max/min bounds for sqrt-price. - * - `InvalidTickArraySequence` - User provided tick-arrays are not in sequential order required to proceed in this trade direction. - * - `TickArraySequenceInvalidIndex` - The swap loop attempted to access an invalid array index during the query of the next initialized tick. - * - `TickArrayIndexOutofBounds` - The swap loop attempted to access an invalid array index during tick crossing. - * - `LiquidityOverflow` - Liquidity value overflowed 128bits during tick crossing. - * - `InvalidTickSpacing` - The swap pool was initialized with tick-spacing of 0. - * - * ### Parameters - * @category Instructions - * @param context - Context object containing services required to generate the instruction - * @param params - {@link SwapParams} - * @returns - Instruction to perform the action. - */ -export function swapIx(program: Program, params: SwapParams): Instruction { - const { - amount, - otherAmountThreshold, - sqrtPriceLimit, - amountSpecifiedIsInput, - aToB, - whirlpool, - tokenAuthority, - tokenOwnerAccountA, - tokenVaultA, - tokenOwnerAccountB, - tokenVaultB, - tickArray0, - tickArray1, - tickArray2, - oracle, - } = params; - - const ix = program.instruction.swap( - amount, - otherAmountThreshold, - sqrtPriceLimit, - amountSpecifiedIsInput, - aToB, - { - accounts: { - tokenProgram: TOKEN_PROGRAM_ID, - tokenAuthority: tokenAuthority, - whirlpool, - tokenOwnerAccountA, - tokenVaultA, - tokenOwnerAccountB, - tokenVaultB, - tickArray0, - tickArray1, - tickArray2, - oracle, - }, - } - ); - - return { - instructions: [ix], - cleanupInstructions: [], - signers: [], - }; -} diff --git a/sdk/src/instructions/two-hop-swap-ix.ts b/sdk/src/instructions/two-hop-swap-ix.ts deleted file mode 100644 index ded7e37..0000000 --- a/sdk/src/instructions/two-hop-swap-ix.ts +++ /dev/null @@ -1,168 +0,0 @@ -import { Program } from "@coral-xyz/anchor"; -import { Instruction } from "@orca-so/common-sdk"; -import { TOKEN_PROGRAM_ID } from "@solana/spl-token"; -import { PublicKey } from "@solana/web3.js"; -import BN from "bn.js"; -import { Whirlpool } from "../artifacts/whirlpool"; - -/** - * Parameters to execute a two-hop swap on a Whirlpool. - * - * @category Instruction Types - * @param whirlpoolOne - PublicKey for the whirlpool that the swap-one will occur on - * @param whirlpoolTwo - PublicKey for the whirlpool that the swap-two will occur on - * @param tokenOwnerAccountOneA - PublicKey for the associated token account for tokenA in whirlpoolOne in the collection wallet - * @param tokenOwnerAccountOneB - PublicKey for the associated token account for tokenB in whirlpoolOne in the collection wallet - * @param tokenOwnerAccountTwoA - PublicKey for the associated token account for tokenA in whirlpoolTwo in the collection wallet - * @param tokenOwnerAccountTwoB - PublicKey for the associated token account for tokenB in whirlpoolTwo in the collection wallet - * @param tokenVaultOneA - PublicKey for the tokenA vault for whirlpoolOne. - * @param tokenVaultOneB - PublicKey for the tokenB vault for whirlpoolOne. - * @param tokenVaultTwoA - PublicKey for the tokenA vault for whirlpoolTwo. - * @param tokenVaultTwoB - PublicKey for the tokenB vault for whirlpoolTwo. - * @param oracleOne - PublicKey for the oracle account for this whirlpoolOne. - * @param oracleTwo - PublicKey for the oracle account for this whirlpoolTwo. - * @param tokenAuthority - authority to withdraw tokens from the input token account - * @param swapInput - Parameters in {@link TwoHopSwapInput} - */ -export type TwoHopSwapParams = TwoHopSwapInput & { - whirlpoolOne: PublicKey; - whirlpoolTwo: PublicKey; - tokenOwnerAccountOneA: PublicKey; - tokenOwnerAccountOneB: PublicKey; - tokenOwnerAccountTwoA: PublicKey; - tokenOwnerAccountTwoB: PublicKey; - tokenVaultOneA: PublicKey; - tokenVaultOneB: PublicKey; - tokenVaultTwoA: PublicKey; - tokenVaultTwoB: PublicKey; - oracleOne: PublicKey; - oracleTwo: PublicKey; - tokenAuthority: PublicKey; -}; - -/** - * Parameters that define a two-hop swap on a Whirlpool. - * - * @category Instruction Types - * @param amount - The amount of input or output token to swap from (depending on amountSpecifiedIsInput). - * @param otherAmountThreshold - The maximum/minimum of input/output token to swap into (depending on amountSpecifiedIsInput). - * @param amountSpecifiedIsInput - Specifies the token the paramneter `amount`represets. If true, the amount represents - * the input token of the swap. - * @param aToBOne - The direction of the swap-one. True if swapping from A to B. False if swapping from B to A. - * @param aToBTwo - The direction of the swap-two. True if swapping from A to B. False if swapping from B to A. - * @param sqrtPriceLimitOne - The maximum/minimum price that swap-one will swap to. - * @param sqrtPriceLimitTwo - The maximum/minimum price that swap-two will swap to. - * @param tickArrayOne0 - PublicKey of the tick-array of swap-One where the Whirlpool's currentTickIndex resides in - * @param tickArrayOne1 - The next tick-array in the swap direction of swap-One. If the swap will not reach the next tick-aray, input the same array as tickArray0. - * @param tickArrayOne2 - The next tick-array in the swap direction after tickArray2 of swap-One. If the swap will not reach the next tick-aray, input the same array as tickArray1. - * @param tickArrayTwo0 - PublicKey of the tick-array of swap-Two where the Whirlpool's currentTickIndex resides in - * @param tickArrayTwo1 - The next tick-array in the swap direction of swap-Two. If the swap will not reach the next tick-aray, input the same array as tickArray0. - * @param tickArrayTwo2 - The next tick-array in the swap direction after tickArray2 of swap-Two. If the swap will not reach the next tick-aray, input the same array as tickArray1. - */ -export type TwoHopSwapInput = { - amount: BN; - otherAmountThreshold: BN; - amountSpecifiedIsInput: boolean; - aToBOne: boolean; - aToBTwo: boolean; - sqrtPriceLimitOne: BN; - sqrtPriceLimitTwo: BN; - tickArrayOne0: PublicKey; - tickArrayOne1: PublicKey; - tickArrayOne2: PublicKey; - tickArrayTwo0: PublicKey; - tickArrayTwo1: PublicKey; - tickArrayTwo2: PublicKey; -}; - -/** - * Perform a two-hop swap in this Whirlpool - * - * #### Special Errors - * - `ZeroTradableAmount` - User provided parameter `amount` is 0. - * - `InvalidSqrtPriceLimitDirection` - User provided parameter `sqrt_price_limit` does not match the direction of the trade. - * - `SqrtPriceOutOfBounds` - User provided parameter `sqrt_price_limit` is over Whirlppool's max/min bounds for sqrt-price. - * - `InvalidTickArraySequence` - User provided tick-arrays are not in sequential order required to proceed in this trade direction. - * - `TickArraySequenceInvalidIndex` - The swap loop attempted to access an invalid array index during the query of the next initialized tick. - * - `TickArrayIndexOutofBounds` - The swap loop attempted to access an invalid array index during tick crossing. - * - `LiquidityOverflow` - Liquidity value overflowed 128bits during tick crossing. - * - `InvalidTickSpacing` - The swap pool was initialized with tick-spacing of 0. - * - `InvalidIntermediaryMint` - Error if the intermediary mint between hop one and two do not equal. - * - `DuplicateTwoHopPool` - Error if whirlpool one & two are the same pool. - * - * ### Parameters - * @category Instructions - * @param context - Context object containing services required to generate the instruction - * @param params - {@link TwoHopSwapParams} object - * @returns - Instruction to perform the action. - */ -export function twoHopSwapIx(program: Program, params: TwoHopSwapParams): Instruction { - const { - amount, - otherAmountThreshold, - amountSpecifiedIsInput, - aToBOne, - aToBTwo, - sqrtPriceLimitOne, - sqrtPriceLimitTwo, - whirlpoolOne, - whirlpoolTwo, - tokenAuthority, - tokenOwnerAccountOneA, - tokenVaultOneA, - tokenOwnerAccountOneB, - tokenVaultOneB, - tokenOwnerAccountTwoA, - tokenVaultTwoA, - tokenOwnerAccountTwoB, - tokenVaultTwoB, - tickArrayOne0, - tickArrayOne1, - tickArrayOne2, - tickArrayTwo0, - tickArrayTwo1, - tickArrayTwo2, - oracleOne, - oracleTwo, - } = params; - - const ix = program.instruction.twoHopSwap( - amount, - otherAmountThreshold, - amountSpecifiedIsInput, - aToBOne, - aToBTwo, - sqrtPriceLimitOne, - sqrtPriceLimitTwo, - { - accounts: { - tokenProgram: TOKEN_PROGRAM_ID, - tokenAuthority, - whirlpoolOne, - whirlpoolTwo, - tokenOwnerAccountOneA, - tokenVaultOneA, - tokenOwnerAccountOneB, - tokenVaultOneB, - tokenOwnerAccountTwoA, - tokenVaultTwoA, - tokenOwnerAccountTwoB, - tokenVaultTwoB, - tickArrayOne0, - tickArrayOne1, - tickArrayOne2, - tickArrayTwo0, - tickArrayTwo1, - tickArrayTwo2, - oracleOne, - oracleTwo, - }, - } - ); - - return { - instructions: [ix], - cleanupInstructions: [], - signers: [], - }; -} diff --git a/sdk/src/instructions/update-fees-and-rewards-ix.ts b/sdk/src/instructions/update-fees-and-rewards-ix.ts deleted file mode 100644 index d889a4c..0000000 --- a/sdk/src/instructions/update-fees-and-rewards-ix.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { Program } from "@coral-xyz/anchor"; -import { PublicKey } from "@solana/web3.js"; -import { Whirlpool } from "../artifacts/whirlpool"; - -import { Instruction } from "@orca-so/common-sdk"; - -/** - * Parameters to update fees and reward values for a position. - * - * @category Instruction Types - * @param whirlpool - PublicKey for the whirlpool that the position will be opened for. - * @param position - PublicKey for the position will be opened for. - * @param tickArrayLower - PublicKey for the tick-array account that hosts the tick at the lower tick index. - * @param tickArrayUpper - PublicKey for the tick-array account that hosts the tick at the upper tick index. - */ -export type UpdateFeesAndRewardsParams = { - whirlpool: PublicKey; - position: PublicKey; - tickArrayLower: PublicKey; - tickArrayUpper: PublicKey; -}; - -/** - * Update the accrued fees and rewards for a position. - * - * #### Special Errors - * `TickNotFound` - Provided tick array account does not contain the tick for this position. - * `LiquidityZero` - Position has zero liquidity and therefore already has the most updated fees and reward values. - * - * @category Instructions - * @param context - Context object containing services required to generate the instruction - * @param params - UpdateFeesAndRewardsParams object - * @returns - Instruction to perform the action. - */ -export function updateFeesAndRewardsIx( - program: Program, - params: UpdateFeesAndRewardsParams -): Instruction { - const { whirlpool, position, tickArrayLower, tickArrayUpper } = params; - - const ix = program.instruction.updateFeesAndRewards({ - accounts: { - whirlpool, - position, - tickArrayLower, - tickArrayUpper, - }, - }); - - return { - instructions: [ix], - cleanupInstructions: [], - signers: [], - }; -} diff --git a/sdk/src/ix.ts b/sdk/src/ix.ts deleted file mode 100644 index 1cb5ed7..0000000 --- a/sdk/src/ix.ts +++ /dev/null @@ -1,522 +0,0 @@ -import { Program } from "@coral-xyz/anchor"; -import { PDA } from "@orca-so/common-sdk"; -import { Whirlpool } from "./artifacts/whirlpool"; -import * as ix from "./instructions"; - -/** - * Instruction builders for the Whirlpools program. - * - * @category Core - */ -export class WhirlpoolIx { - /** - * Initializes a WhirlpoolsConfig account that hosts info & authorities - * required to govern a set of Whirlpools. - * - * @param program - program object containing services required to generate the instruction - * @param params - InitConfigParams object - * @returns - Instruction to perform the action. - */ - public static initializeConfigIx(program: Program, params: ix.InitConfigParams) { - return ix.initializeConfigIx(program, params); - } - - /** - * Initializes a fee tier account usable by Whirlpools in this WhirlpoolsConfig space. - * - * Special Errors - * `FeeRateMaxExceeded` - If the provided default_fee_rate exceeds MAX_FEE_RATE. - * - * @param program - program object containing services required to generate the instruction - * @param params - InitFeeTierParams object - * @returns - Instruction to perform the action. - */ - public static initializeFeeTierIx(program: Program, params: ix.InitFeeTierParams) { - return ix.initializeFeeTierIx(program, params); - } - - /** - * Initializes a tick_array account to represent a tick-range in a Whirlpool. - * - * Special Errors - * `InvalidTokenMintOrder` - The order of mints have to be ordered by - * `SqrtPriceOutOfBounds` - provided initial_sqrt_price is not between 2^-64 to 2^64 - * - * @param program - program object containing services required to generate the instruction - * @param params - InitPoolParams object - * @returns - Instruction to perform the action. - */ - public static initializePoolIx(program: Program, params: ix.InitPoolParams) { - return ix.initializePoolIx(program, params); - } - - /** - * Initialize reward for a Whirlpool. A pool can only support up to a set number of rewards. - * The initial emissionsPerSecond is set to 0. - * - * #### Special Errors - * - `InvalidRewardIndex` - If the provided reward index doesn't match the lowest uninitialized index in this pool, - * or exceeds NUM_REWARDS, or all reward slots for this pool has been initialized. - * - * @param program - program object containing services required to generate the instruction - * @param params - InitializeRewardParams object - * @returns - Instruction to perform the action. - */ - public static initializeRewardIx(program: Program, params: ix.InitializeRewardParams) { - return ix.initializeRewardIx(program, params); - } - - /** - * Initializes a TickArray account. - * - * #### Special Errors - * `InvalidStartTick` - if the provided start tick is out of bounds or is not a multiple of TICK_ARRAY_SIZE * tick spacing. - * - * @param program - program object containing services required to generate the instruction - * @param params - InitTickArrayParams object - * @returns - Instruction to perform the action. - */ - public static initTickArrayIx(program: Program, params: ix.InitTickArrayParams) { - return ix.initTickArrayIx(program, params); - } - - /** - * Open a position in a Whirlpool. A unique token will be minted to represent the position in the users wallet. - * The position will start off with 0 liquidity. - * - * #### Special Errors - * `InvalidTickIndex` - If a provided tick is out of bounds, out of order or not a multiple of the tick-spacing in this pool. - * - * @param program - program object containing services required to generate the instruction - * @param params - OpenPositionParams object - * @returns - Instruction to perform the action. - */ - public static openPositionIx(program: Program, params: ix.OpenPositionParams) { - return ix.openPositionIx(program, params); - } - - /** - * Open a position in a Whirlpool. A unique token will be minted to represent the position - * in the users wallet. Additional Metaplex metadata is appended to identify the token. - * The position will start off with 0 liquidity. - * - * #### Special Errors - * `InvalidTickIndex` - If a provided tick is out of bounds, out of order or not a multiple of the tick-spacing in this pool. - * - * @param program - program object containing services required to generate the instruction - * @param params - OpenPositionParams object and a derived PDA that hosts the position's metadata. - * @returns - Instruction to perform the action. - */ - public static openPositionWithMetadataIx( - program: Program, - params: ix.OpenPositionParams & { metadataPda: PDA } - ) { - return ix.openPositionWithMetadataIx(program, params); - } - - /** - * Add liquidity to a position in the Whirlpool. This call also updates the position's accrued fees and rewards. - * - * #### Special Errors - * `LiquidityZero` - Provided liquidity amount is zero. - * `LiquidityTooHigh` - Provided liquidity exceeds u128::max. - * `TokenMaxExceeded` - The required token to perform this operation exceeds the user defined amount. - * - * @param program - program object containing services required to generate the instruction - * @param params - IncreaseLiquidityParams object - * @returns - Instruction to perform the action. - */ - public static increaseLiquidityIx( - program: Program, - params: ix.IncreaseLiquidityParams - ) { - return ix.increaseLiquidityIx(program, params); - } - - /** - * Remove liquidity to a position in the Whirlpool. This call also updates the position's accrued fees and rewards. - * - * #### Special Errors - * - `LiquidityZero` - Provided liquidity amount is zero. - * - `LiquidityTooHigh` - Provided liquidity exceeds u128::max. - * - `TokenMinSubceeded` - The required token to perform this operation subceeds the user defined amount. - * - * @param program - program object containing services required to generate the instruction - * @param params - DecreaseLiquidityParams object - * @returns - Instruction to perform the action. - */ - public static decreaseLiquidityIx( - program: Program, - params: ix.DecreaseLiquidityParams - ) { - return ix.decreaseLiquidityIx(program, params); - } - - /** - * Close a position in a Whirlpool. Burns the position token in the owner's wallet. - * - * @param program - program object containing services required to generate the instruction - * @param params - ClosePositionParams object - * @returns - Instruction to perform the action. - */ - public static closePositionIx(program: Program, params: ix.ClosePositionParams) { - return ix.closePositionIx(program, params); - } - - /** - * Perform a swap in this Whirlpool - * - * #### Special Errors - * - `ZeroTradableAmount` - User provided parameter `amount` is 0. - * - `InvalidSqrtPriceLimitDirection` - User provided parameter `sqrt_price_limit` does not match the direction of the trade. - * - `SqrtPriceOutOfBounds` - User provided parameter `sqrt_price_limit` is over Whirlppool's max/min bounds for sqrt-price. - * - `InvalidTickArraySequence` - User provided tick-arrays are not in sequential order required to proceed in this trade direction. - * - `TickArraySequenceInvalidIndex` - The swap loop attempted to access an invalid array index during the query of the next initialized tick. - * - `TickArrayIndexOutofBounds` - The swap loop attempted to access an invalid array index during tick crossing. - * - `LiquidityOverflow` - Liquidity value overflowed 128bits during tick crossing. - * - `InvalidTickSpacing` - The swap pool was initialized with tick-spacing of 0. - * - * ### Parameters - * @param program - program object containing services required to generate the instruction - * @param params - {@link SwapParams} - * @returns - Instruction to perform the action. - */ - public static swapIx(program: Program, params: ix.SwapParams) { - return ix.swapIx(program, params); - } - - /** - * Perform a two-hop-swap in this Whirlpool - * - * #### Special Errors - * - `ZeroTradableAmount` - User provided parameter `amount` is 0. - * - `InvalidSqrtPriceLimitDirection` - User provided parameter `sqrt_price_limit` does not match the direction of the trade. - * - `SqrtPriceOutOfBounds` - User provided parameter `sqrt_price_limit` is over Whirlppool's max/min bounds for sqrt-price. - * - `InvalidTickArraySequence` - User provided tick-arrays are not in sequential order required to proceed in this trade direction. - * - `TickArraySequenceInvalidIndex` - The swap loop attempted to access an invalid array index during the query of the next initialized tick. - * - `TickArrayIndexOutofBounds` - The swap loop attempted to access an invalid array index during tick crossing. - * - `LiquidityOverflow` - Liquidity value overflowed 128bits during tick crossing. - * - `InvalidTickSpacing` - The swap pool was initialized with tick-spacing of 0. - * - `DuplicateTwoHopPool` - Swaps on the same pool are not allowed. - * - `InvalidIntermediaryMint` - The first and second leg of the hops do not share a common token. - * - * ### Parameters - * @param program - program object containing services required to generate the instruction - * @param params - TwoHopSwapParams object - * @returns - Instruction to perform the action. - */ - public static twoHopSwapIx(program: Program, params: ix.TwoHopSwapParams) { - return ix.twoHopSwapIx(program, params); - } - - /** - * Update the accrued fees and rewards for a position. - * - * #### Special Errors - * `TickNotFound` - Provided tick array account does not contain the tick for this position. - * `LiquidityZero` - Position has zero liquidity and therefore already has the most updated fees and reward values. - * - * @param program - program object containing services required to generate the instruction - * @param params - UpdateFeesAndRewardsParams object - * @returns - Instruction to perform the action. - */ - public static updateFeesAndRewardsIx( - program: Program, - params: ix.UpdateFeesAndRewardsParams - ) { - return ix.updateFeesAndRewardsIx(program, params); - } - - /** - * Collect fees accrued for this position. - * Call updateFeesAndRewards before this to update the position to the newest accrued values. - * - * @param program - program object containing services required to generate the instruction - * @param params - CollectFeesParams object - * @returns - Instruction to perform the action. - */ - public static collectFeesIx(program: Program, params: ix.CollectFeesParams) { - return ix.collectFeesIx(program, params); - } - - /** - * Collect protocol fees accrued in this Whirlpool. - * - * @param program - program object containing services required to generate the instruction - * @param params - CollectProtocolFeesParams object - * @returns - Instruction to perform the action. - */ - public static collectProtocolFeesIx( - program: Program, - params: ix.CollectProtocolFeesParams - ) { - return ix.collectProtocolFeesIx(program, params); - } - - /** - * Collect rewards accrued for this reward index in a position. - * Call updateFeesAndRewards before this to update the position to the newest accrued values. - * - * @param program - program object containing services required to generate the instruction - * @param params - CollectRewardParams object - * @returns - Instruction to perform the action. - */ - public static collectRewardIx(program: Program, params: ix.CollectRewardParams) { - return ix.collectRewardIx(program, params); - } - - /** - * Sets the fee authority to collect protocol fees for a WhirlpoolsConfig. - * Only the current collect protocol fee authority has permission to invoke this instruction. - * - * @param program - program object containing services required to generate the instruction - * @param params - SetCollectProtocolFeesAuthorityParams object - * @returns - Instruction to perform the action. - */ - public static setCollectProtocolFeesAuthorityIx( - program: Program, - params: ix.SetCollectProtocolFeesAuthorityParams - ) { - return ix.setCollectProtocolFeesAuthorityIx(program, params); - } - - /** - * Updates a fee tier account with a new default fee rate. The new rate will not retroactively update - * initialized pools. - * - * #### Special Errors - * - `FeeRateMaxExceeded` - If the provided default_fee_rate exceeds MAX_FEE_RATE. - * - * @param program - program object containing services required to generate the instruction - * @param params - SetDefaultFeeRateParams object - * @returns - Instruction to perform the action. - */ - public static setDefaultFeeRateIx( - program: Program, - params: ix.SetDefaultFeeRateParams - ) { - return ix.setDefaultFeeRateIx(program, params); - } - - /** - * Updates a WhirlpoolsConfig with a new default protocol fee rate. The new rate will not retroactively update - * initialized pools. - * - * #### Special Errors - * - `ProtocolFeeRateMaxExceeded` - If the provided default_protocol_fee_rate exceeds MAX_PROTOCOL_FEE_RATE. - * - * @param program - program object containing services required to generate the instruction - * @param params - SetDefaultFeeRateParams object - * @returns - Instruction to perform the action. - */ - public static setDefaultProtocolFeeRateIx( - program: Program, - params: ix.SetDefaultProtocolFeeRateParams - ) { - return ix.setDefaultProtocolFeeRateIx(program, params); - } - - /** - * Sets the fee authority for a WhirlpoolsConfig. - * The fee authority can set the fee & protocol fee rate for individual pools or set the default fee rate for newly minted pools. - * Only the current fee authority has permission to invoke this instruction. - * - * @param program - program object containing services required to generate the instruction - * @param params - SetFeeAuthorityParams object - * @returns - Instruction to perform the action. - */ - public static setFeeAuthorityIx(program: Program, params: ix.SetFeeAuthorityParams) { - return ix.setFeeAuthorityIx(program, params); - } - - /** - * Sets the fee rate for a Whirlpool. - * Only the current fee authority has permission to invoke this instruction. - * - * #### Special Errors - * - `FeeRateMaxExceeded` - If the provided fee_rate exceeds MAX_FEE_RATE. - * - * @param program - program object containing services required to generate the instruction - * @param params - SetFeeRateParams object - * @returns - Instruction to perform the action. - */ - public static setFeeRateIx(program: Program, params: ix.SetFeeRateParams) { - return ix.setFeeRateIx(program, params); - } - - /** - * Sets the protocol fee rate for a Whirlpool. - * Only the current fee authority has permission to invoke this instruction. - * - * #### Special Errors - * - `ProtocolFeeRateMaxExceeded` - If the provided default_protocol_fee_rate exceeds MAX_PROTOCOL_FEE_RATE. - * - * @param program - program object containing services required to generate the instruction - * @param params - SetFeeRateParams object - * @returns - Instruction to perform the action. - */ - public static setProtocolFeeRateIx( - program: Program, - params: ix.SetProtocolFeeRateParams - ) { - return ix.setProtocolFeeRateIx(program, params); - } - - /** - * Set the whirlpool reward authority at the provided `reward_index`. - * Only the current reward super authority has permission to invoke this instruction. - * - * #### Special Errors - * - `InvalidRewardIndex` - If the provided reward index doesn't match the lowest uninitialized index in this pool, - * or exceeds NUM_REWARDS. - * - * @param program - program object containing services required to generate the instruction - * @param params - SetRewardAuthorityParams object - * @returns - Instruction to perform the action. - */ - public static setRewardAuthorityBySuperAuthorityIx( - program: Program, - params: ix.SetRewardAuthorityBySuperAuthorityParams - ) { - return ix.setRewardAuthorityBySuperAuthorityIx(program, params); - } - - /** - * Set the whirlpool reward authority at the provided `reward_index`. - * Only the current reward authority for this reward index has permission to invoke this instruction. - * - * #### Special Errors - * - `InvalidRewardIndex` - If the provided reward index doesn't match the lowest uninitialized index in this pool, - * or exceeds NUM_REWARDS. - * - * @param program - program object containing services required to generate the instruction - * @param params - SetRewardAuthorityParams object - * @returns - Instruction to perform the action. - */ - public static setRewardAuthorityIx( - program: Program, - params: ix.SetRewardAuthorityParams - ) { - return ix.setRewardAuthorityIx(program, params); - } - - /** - * Set the reward emissions for a reward in a Whirlpool. - * - * #### Special Errors - * - `RewardVaultAmountInsufficient` - The amount of rewards in the reward vault cannot emit more than a day of desired emissions. - * - `InvalidTimestamp` - Provided timestamp is not in order with the previous timestamp. - * - `InvalidRewardIndex` - If the provided reward index doesn't match the lowest uninitialized index in this pool, - * or exceeds NUM_REWARDS. - * - * @param program - program object containing services required to generate the instruction - * @param params - SetRewardEmissionsParams object - * @returns - Instruction to perform the action. - */ - public static setRewardEmissionsIx( - program: Program, - params: ix.SetRewardEmissionsParams - ) { - return ix.setRewardEmissionsIx(program, params); - } - - /** - * Set the whirlpool reward super authority for a WhirlpoolsConfig - * Only the current reward super authority has permission to invoke this instruction. - * This instruction will not change the authority on any `WhirlpoolRewardInfo` whirlpool rewards. - * - * @param program - program object containing services required to generate the instruction - * @param params - SetRewardEmissionsSuperAuthorityParams object - * @returns - Instruction to perform the action. - */ - public static setRewardEmissionsSuperAuthorityIx( - program: Program, - params: ix.SetRewardEmissionsSuperAuthorityParams - ) { - return ix.setRewardEmissionsSuperAuthorityIx(program, params); - } - - /** - * Initializes a PositionBundle account. - * - * @param program - program object containing services required to generate the instruction - * @param params - InitializePositionBundleParams object - * @returns - Instruction to perform the action. - */ - public static initializePositionBundleIx( - program: Program, - params: ix.InitializePositionBundleParams - ) { - return ix.initializePositionBundleIx(program, params); - } - - /** - * Initializes a PositionBundle account. - * Additional Metaplex metadata is appended to identify the token. - * - * @param program - program object containing services required to generate the instruction - * @param params - InitializePositionBundleParams object - * @returns - Instruction to perform the action. - */ - public static initializePositionBundleWithMetadataIx( - program: Program, - params: ix.InitializePositionBundleParams & { positionBundleMetadataPda: PDA } - ) { - return ix.initializePositionBundleWithMetadataIx(program, params); - } - - /** - * Deletes a PositionBundle account. - * - * #### Special Errors - * `PositionBundleNotDeletable` - The provided position bundle has open positions. - * - * @param program - program object containing services required to generate the instruction - * @param params - DeletePositionBundleParams object - * @returns - Instruction to perform the action. - */ - public static deletePositionBundleIx( - program: Program, - params: ix.DeletePositionBundleParams - ) { - return ix.deletePositionBundleIx(program, params); - } - - /** - * Open a bundled position in a Whirlpool. - * No new tokens are issued because the owner of the position bundle becomes the owner of the position. - * The position will start off with 0 liquidity. - * - * #### Special Errors - * `InvalidBundleIndex` - If the provided bundle index is out of bounds. - * `InvalidTickIndex` - If a provided tick is out of bounds, out of order or not a multiple of the tick-spacing in this pool. - * - * @param program - program object containing services required to generate the instruction - * @param params - OpenBundledPositionParams object - * @returns - Instruction to perform the action. - */ - public static openBundledPositionIx( - program: Program, - params: ix.OpenBundledPositionParams - ) { - return ix.openBundledPositionIx(program, params); - } - - /** - * Close a bundled position in a Whirlpool. - * - * #### Special Errors - * `InvalidBundleIndex` - If the provided bundle index is out of bounds. - * `ClosePositionNotEmpty` - The provided position account is not empty. - * - * @param program - program object containing services required to generate the instruction - * @param params - CloseBundledPositionParams object - * @returns - Instruction to perform the action. - */ - public static closeBundledPositionIx( - program: Program, - params: ix.CloseBundledPositionParams - ) { - return ix.closeBundledPositionIx(program, params); - } -} diff --git a/sdk/src/network/public/fetcher/fetcher-impl.ts b/sdk/src/network/public/fetcher/fetcher-impl.ts deleted file mode 100644 index 29bfe7a..0000000 --- a/sdk/src/network/public/fetcher/fetcher-impl.ts +++ /dev/null @@ -1,162 +0,0 @@ -import { Address } from "@coral-xyz/anchor"; -import { - AccountFetcher, - ParsableEntity, - ParsableMintInfo, - ParsableTokenAccountInfo, - SimpleAccountFetcher, -} from "@orca-so/common-sdk"; -import { AccountLayout, Mint, Account as TokenAccount } from "@solana/spl-token"; -import { Connection } from "@solana/web3.js"; -import { - DEFAULT_WHIRLPOOL_RETENTION_POLICY, - WhirlpoolAccountFetchOptions, - WhirlpoolAccountFetcherInterface, - WhirlpoolSupportedTypes, -} from ".."; -import { - FeeTierData, - PositionBundleData, - PositionData, - TickArrayData, - WhirlpoolData, - WhirlpoolsConfigData, -} from "../../../types/public"; -import { - ParsableFeeTier, - ParsablePosition, - ParsablePositionBundle, - ParsableTickArray, - ParsableWhirlpool, - ParsableWhirlpoolsConfig, -} from "../parsing"; - -/** - * Build a default instance of {@link WhirlpoolAccountFetcherInterface} with the default {@link AccountFetcher} implementation - * @param connection An instance of {@link Connection} to use for fetching accounts - * @returns An instance of {@link WhirlpoolAccountFetcherInterface} - * @category Network - */ -export const buildDefaultAccountFetcher = (connection: Connection) => { - return new WhirlpoolAccountFetcher( - connection, - new SimpleAccountFetcher(connection, DEFAULT_WHIRLPOOL_RETENTION_POLICY) - ); -}; - -/** - * Fetcher and cache layer for fetching {@link WhirlpoolSupportedTypes} from the network - * Default implementation for {@link WhirlpoolAccountFetcherInterface} - * @category Network - */ -export class WhirlpoolAccountFetcher implements WhirlpoolAccountFetcherInterface { - private _accountRentExempt: number | undefined; - - constructor( - readonly connection: Connection, - readonly fetcher: AccountFetcher - ) {} - - async getAccountRentExempt(refresh: boolean = false): Promise { - // This value should be relatively static or at least not break according to spec - // https://docs.solana.com/developing/programming-model/accounts#rent-exemption - if (!this._accountRentExempt || refresh) { - this._accountRentExempt = await this.connection.getMinimumBalanceForRentExemption( - AccountLayout.span - ); - } - return this._accountRentExempt; - } - - getPool(address: Address, opts?: WhirlpoolAccountFetchOptions): Promise { - return this.fetcher.getAccount(address, ParsableWhirlpool, opts); - } - getPools( - addresses: Address[], - opts?: WhirlpoolAccountFetchOptions - ): Promise> { - return this.fetcher.getAccounts(addresses, ParsableWhirlpool, opts); - } - getPosition(address: Address, opts?: WhirlpoolAccountFetchOptions): Promise { - return this.fetcher.getAccount(address, ParsablePosition, opts); - } - getPositions( - addresses: Address[], - opts?: WhirlpoolAccountFetchOptions - ): Promise> { - return this.fetcher.getAccounts(addresses, ParsablePosition, opts); - } - getTickArray( - address: Address, - opts?: WhirlpoolAccountFetchOptions - ): Promise { - return this.fetcher.getAccount(address, ParsableTickArray, opts); - } - getTickArrays( - addresses: Address[], - opts?: WhirlpoolAccountFetchOptions - ): Promise> { - return this.fetcher.getAccountsAsArray(addresses, ParsableTickArray, opts); - } - getFeeTier(address: Address, opts?: WhirlpoolAccountFetchOptions): Promise { - return this.fetcher.getAccount(address, ParsableFeeTier, opts); - } - getFeeTiers( - addresses: Address[], - opts?: WhirlpoolAccountFetchOptions - ): Promise> { - return this.fetcher.getAccounts(addresses, ParsableFeeTier, opts); - } - getTokenInfo( - address: Address, - opts?: WhirlpoolAccountFetchOptions - ): Promise { - return this.fetcher.getAccount(address, ParsableTokenAccountInfo, opts); - } - getTokenInfos( - addresses: Address[], - opts?: WhirlpoolAccountFetchOptions - ): Promise> { - return this.fetcher.getAccounts(addresses, ParsableTokenAccountInfo, opts); - } - getMintInfo(address: Address, opts?: WhirlpoolAccountFetchOptions): Promise { - return this.fetcher.getAccount(address, ParsableMintInfo, opts); - } - getMintInfos( - addresses: Address[], - opts?: WhirlpoolAccountFetchOptions - ): Promise> { - return this.fetcher.getAccounts(addresses, ParsableMintInfo, opts); - } - getConfig( - address: Address, - opts?: WhirlpoolAccountFetchOptions - ): Promise { - return this.fetcher.getAccount(address, ParsableWhirlpoolsConfig, opts); - } - getConfigs( - addresses: Address[], - opts?: WhirlpoolAccountFetchOptions - ): Promise> { - return this.fetcher.getAccounts(addresses, ParsableWhirlpoolsConfig, opts); - } - getPositionBundle( - address: Address, - opts?: WhirlpoolAccountFetchOptions - ): Promise { - return this.fetcher.getAccount(address, ParsablePositionBundle, opts); - } - getPositionBundles( - addresses: Address[], - opts?: WhirlpoolAccountFetchOptions - ): Promise> { - return this.fetcher.getAccounts(addresses, ParsablePositionBundle, opts); - } - populateCache( - accounts: ReadonlyMap, - parser: ParsableEntity, - now = Date.now() - ): void { - this.fetcher.populateAccounts(accounts, parser, now); - } -} diff --git a/sdk/src/network/public/fetcher/fetcher-types.ts b/sdk/src/network/public/fetcher/fetcher-types.ts deleted file mode 100644 index a79df36..0000000 --- a/sdk/src/network/public/fetcher/fetcher-types.ts +++ /dev/null @@ -1,224 +0,0 @@ -import { Address } from "@coral-xyz/anchor"; -import { - BasicSupportedTypes, - ParsableEntity, - SimpleAccountFetchOptions, -} from "@orca-so/common-sdk"; -import { Mint, Account as TokenAccount } from "@solana/spl-token"; -import { - FeeTierData, - PositionBundleData, - PositionData, - TickArrayData, - WhirlpoolData, - WhirlpoolsConfigData, -} from "../../../types/public"; - -/** - * Union type of all the {@link ParsableEntity} types that can be cached in the {@link WhirlpoolAccountFetcherInterface} - * @category Network - */ -export type WhirlpoolSupportedTypes = - | WhirlpoolsConfigData - | WhirlpoolData - | PositionData - | TickArrayData - | FeeTierData - | PositionBundleData - | BasicSupportedTypes; - -/** - * The default retention periods for each {@link ParsableEntity} type in the {@link WhirlpoolAccountFetcherInterface} - * @category Network - */ -export const DEFAULT_WHIRLPOOL_RETENTION_POLICY: ReadonlyMap< - ParsableEntity, - number -> = new Map, number>([]); - -/** - * Type to define fetch options for the {@link WhirlpoolAccountFetcherInterface} - * @category Network - */ -export type WhirlpoolAccountFetchOptions = SimpleAccountFetchOptions; - -/** - * Default fetch option for always fetching when making an account request to the {@link WhirlpoolAccountFetcherInterface} - * @category Network - */ -export const IGNORE_CACHE: WhirlpoolAccountFetchOptions = { maxAge: 0 }; - -/** - * Default fetch option for always using the cached value for an account request to the {@link WhirlpoolAccountFetcherInterface} - * @category Network - */ -export const PREFER_CACHE: WhirlpoolAccountFetchOptions = { maxAge: Number.POSITIVE_INFINITY }; - -/** - * Fetcher interface for fetching {@link WhirlpoolSupportedTypes} from the network - * @category Network - */ -export interface WhirlpoolAccountFetcherInterface { - /** - * Fetch and cache the rent exempt value - * @param refresh If true, will always fetch from the network - */ - getAccountRentExempt(refresh?: boolean): Promise; - - /** - * Fetch and cache the account for a given Whirlpool addresses - * @param address The mint address - * @param opts {@link WhirlpoolAccountFetchOptions} instance to dictate fetch behavior - */ - getPool(address: Address, opts?: WhirlpoolAccountFetchOptions): Promise; - - /** - * Fetch and cache the accounts for a given array of Whirlpool addresses - * @param addresses The array of mint addresses - * @param opts {@link WhirlpoolAccountFetchOptions} instance to dictate fetch behavior - */ - getPools( - addresses: Address[], - opts?: WhirlpoolAccountFetchOptions - ): Promise>; - - /** - * Fetch and cache the account for a given Position address - * @param address The address of the position account - * @param opts {@link WhirlpoolAccountFetchOptions} instance to dictate fetch behavior - */ - getPosition(address: Address, opts?: WhirlpoolAccountFetchOptions): Promise; - - /** - * Fetch and cache the accounts for a given array of Position addresses - * @param addresses The array of position account addresses - * @param opts {@link WhirlpoolAccountFetchOptions} instance to dictate fetch behavior - */ - getPositions( - addresses: Address[], - opts?: WhirlpoolAccountFetchOptions - ): Promise>; - - /** - * Fetch and cache the account for a given TickArray address. - * @param address The address of the tick array account - * @param opts {@link WhirlpoolAccountFetchOptions} instance to dictate fetch behavior - */ - getTickArray( - address: Address, - opts?: WhirlpoolAccountFetchOptions - ): Promise; - - /** - * Fetch and cache the accounts for a given array of TickArray addresses - * @param addresses The array of tick array account addresses - * @param opts {@link WhirlpoolAccountFetchOptions} instance to dictate fetch behavior - */ - getTickArrays( - addresses: Address[], - opts?: WhirlpoolAccountFetchOptions - ): Promise>; - - /** - * Fetch and cache the account for a given FeeTier address - * @param address The address of the fee tier account - * @param opts {@link WhirlpoolAccountFetchOptions} instance to dictate fetch behavior - */ - getFeeTier(address: Address, opts?: WhirlpoolAccountFetchOptions): Promise; - - /** - * Fetch and cache the accounts for a given array of FeeTier addresses - * @param addresses The array of fee tier account addresses - * @param opts {@link WhirlpoolAccountFetchOptions} instance to dictate fetch behavior - */ - getFeeTiers( - addresses: Address[], - opts?: WhirlpoolAccountFetchOptions - ): Promise>; - - /** - * Fetch and cache the account for a given TokenAccount address - * @param address The address of the token account - * @param opts {@link WhirlpoolAccountFetchOptions} instance to dictate fetch behavior - */ - getTokenInfo(address: Address, opts?: WhirlpoolAccountFetchOptions): Promise; - - /** - * Fetch and cache the accounts for a given array of TokenAccount addresses - * @param addresses The array of token account addresses - * @param opts {@link WhirlpoolAccountFetchOptions} instance to dictate fetch behavior - */ - getTokenInfos( - addresses: Address[], - opts?: WhirlpoolAccountFetchOptions - ): Promise>; - - /** - * Fetch and cache the account for a given Mint address - * @param address The address of the mint account - * @param opts {@link WhirlpoolAccountFetchOptions} instance to dictate fetch behavior - */ - getMintInfo(address: Address, opts?: WhirlpoolAccountFetchOptions): Promise; - - /** - * Fetch and cache the accounts for a given array of Mint addresses - * @param addresses The array of mint account addresses - * @param opts {@link WhirlpoolAccountFetchOptions} instance to dictate fetch behavior - */ - getMintInfos( - addresses: Address[], - opts?: WhirlpoolAccountFetchOptions - ): Promise>; - - /** - * Fetch and cache the account for a given WhirlpoolConfig address - * @param address The address of the WhirlpoolConfig account - * @param opts {@link WhirlpoolAccountFetchOptions} instance to dictate fetch behavior - */ - getConfig( - address: Address, - opts?: WhirlpoolAccountFetchOptions - ): Promise; - - /** - * Fetch and cache the accounts for a given array of WhirlpoolConfig addresses - * @param addresses The array of WhirlpoolConfig account addresses - * @param opts {@link WhirlpoolAccountFetchOptions} instance to dictate fetch behavior - */ - getConfigs( - addresses: Address[], - opts?: WhirlpoolAccountFetchOptions - ): Promise>; - - /** - * Fetch and cache the account for a given PositionBundle address - * @param address The address of the position bundle account - * @param opts {@link WhirlpoolAccountFetchOptions} instance to dictate fetch behavior - */ - getPositionBundle( - address: Address, - opts?: WhirlpoolAccountFetchOptions - ): Promise; - - /** - * Fetch and cache the accounts for a given array of PositionBundle addresses - * @param addresses The array of position bundle account addresses - * @param opts {@link WhirlpoolAccountFetchOptions} instance to dictate fetch behavior - */ - getPositionBundles( - addresses: Address[], - opts?: WhirlpoolAccountFetchOptions - ): Promise>; - - /** - * Populate the fetcher's cache with the given {@link WhirlpoolsData} accounts - * @param accounts The map of addresses to on-chain account data - * @param parser The {@link ParsableEntity} instance to parse the accounts - * @param now The current timestamp to use for the cache - */ - populateCache( - accounts: ReadonlyMap, - parser: ParsableEntity, - now: number - ): void; -} diff --git a/sdk/src/network/public/fetcher/fetcher-utils.ts b/sdk/src/network/public/fetcher/fetcher-utils.ts deleted file mode 100644 index 13137b3..0000000 --- a/sdk/src/network/public/fetcher/fetcher-utils.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { Address, AddressUtil } from "@orca-so/common-sdk"; -import { Connection } from "@solana/web3.js"; -import invariant from "tiny-invariant"; -import { AccountName, WHIRLPOOL_CODER, WhirlpoolData, getAccountSize } from "../../../types/public"; -import { ParsableWhirlpool } from "../parsing"; - -/** - * Retrieve a list of whirlpool addresses and accounts filtered by the given params using - * getProgramAccounts. - * @category Network - * - * @param connection The connection to use to fetch accounts - * @param programId The Whirlpool program to search Whirlpool accounts for - * @param configId The {@link WhirlpoolConfig} account program address to filter by - * @returns tuple of whirlpool addresses and accounts - */ -export async function getAllWhirlpoolAccountsForConfig({ - connection, - programId, - configId, -}: { - connection: Connection; - programId: Address; - configId: Address; -}): Promise> { - const filters = [ - { dataSize: getAccountSize(AccountName.Whirlpool) }, - { - memcmp: WHIRLPOOL_CODER.memcmp( - AccountName.Whirlpool, - AddressUtil.toPubKey(configId).toBuffer() - ), - }, - ]; - - const accounts = await connection.getProgramAccounts(AddressUtil.toPubKey(programId), { - filters, - }); - - const parsedAccounts: [string, WhirlpoolData][] = []; - accounts.forEach(({ pubkey, account }) => { - const parsedAccount = ParsableWhirlpool.parse(pubkey, account); - invariant(!!parsedAccount, `could not parse whirlpool: ${pubkey.toBase58()}`); - parsedAccounts.push([AddressUtil.toString(pubkey), parsedAccount]); - }); - - return new Map(parsedAccounts.map(([address, pool]) => [AddressUtil.toString(address), pool])); -} diff --git a/sdk/src/network/public/fetcher/index.ts b/sdk/src/network/public/fetcher/index.ts deleted file mode 100644 index 8087334..0000000 --- a/sdk/src/network/public/fetcher/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from "./fetcher-impl"; -export * from "./fetcher-types"; -export * from "./fetcher-utils"; diff --git a/sdk/src/network/public/index.ts b/sdk/src/network/public/index.ts deleted file mode 100644 index b9a3660..0000000 --- a/sdk/src/network/public/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from "./fetcher/"; -export * from "./parsing"; diff --git a/sdk/src/network/public/parsing.ts b/sdk/src/network/public/parsing.ts deleted file mode 100644 index 1bfd946..0000000 --- a/sdk/src/network/public/parsing.ts +++ /dev/null @@ -1,175 +0,0 @@ -import { BorshAccountsCoder, Idl } from "@coral-xyz/anchor"; -import { ParsableEntity, staticImplements } from "@orca-so/common-sdk"; -import { AccountInfo, PublicKey } from "@solana/web3.js"; -import * as WhirlpoolIDL from "../../artifacts/whirlpool.json"; -import { - AccountName, - FeeTierData, - PositionBundleData, - PositionData, - TickArrayData, - WhirlpoolData, - WhirlpoolsConfigData, -} from "../../types/public"; - -/** - * @category Network - */ -@staticImplements>() -export class ParsableWhirlpoolsConfig { - private constructor() {} - - public static parse( - address: PublicKey, - accountData: AccountInfo | undefined | null - ): WhirlpoolsConfigData | null { - if (!accountData?.data) { - return null; - } - - try { - return parseAnchorAccount(AccountName.WhirlpoolsConfig, accountData); - } catch (e) { - console.error(`error while parsing WhirlpoolsConfig: ${e}`); - return null; - } - } -} - -/** - * @category Network - */ -@staticImplements>() -export class ParsableWhirlpool { - private constructor() {} - - public static parse( - address: PublicKey, - accountData: AccountInfo | undefined | null - ): WhirlpoolData | null { - if (!accountData?.data) { - return null; - } - - try { - return parseAnchorAccount(AccountName.Whirlpool, accountData); - } catch (e) { - console.error(`error while parsing Whirlpool: ${e}`); - return null; - } - } -} - -/** - * @category Network - */ -@staticImplements>() -export class ParsablePosition { - private constructor() {} - - public static parse( - address: PublicKey, - accountData: AccountInfo | undefined | null - ): PositionData | null { - if (!accountData?.data) { - return null; - } - - try { - return parseAnchorAccount(AccountName.Position, accountData); - } catch (e) { - console.error(`error while parsing Position: ${e}`); - return null; - } - } -} - -/** - * @category Network - */ -@staticImplements>() -export class ParsableTickArray { - private constructor() {} - - public static parse( - address: PublicKey, - accountData: AccountInfo | undefined | null - ): TickArrayData | null { - if (!accountData?.data) { - return null; - } - - try { - return parseAnchorAccount(AccountName.TickArray, accountData); - } catch (e) { - console.error(`error while parsing TickArray: ${e}`); - return null; - } - } -} - -/** - * @category Network - */ -@staticImplements>() -export class ParsableFeeTier { - private constructor() {} - - public static parse( - address: PublicKey, - accountData: AccountInfo | undefined | null - ): FeeTierData | null { - if (!accountData?.data) { - return null; - } - - try { - return parseAnchorAccount(AccountName.FeeTier, accountData); - } catch (e) { - console.error(`error while parsing FeeTier: ${e}`); - return null; - } - } -} - -/** - * @category Network - */ -@staticImplements>() -export class ParsablePositionBundle { - private constructor() {} - - public static parse( - address: PublicKey, - accountData: AccountInfo | undefined | null - ): PositionBundleData | null { - if (!accountData?.data) { - return null; - } - - try { - return parseAnchorAccount(AccountName.PositionBundle, accountData); - } catch (e) { - console.error(`error while parsing PositionBundle: ${e}`); - return null; - } - } -} - -const WhirlpoolCoder = new BorshAccountsCoder(WhirlpoolIDL as Idl); - -function parseAnchorAccount(accountName: AccountName, accountData: AccountInfo) { - const data = accountData.data; - const discriminator = BorshAccountsCoder.accountDiscriminator(accountName); - if (discriminator.compare(data.slice(0, 8))) { - console.error("incorrect account name during parsing"); - return null; - } - - try { - return WhirlpoolCoder.decode(accountName, data); - } catch (_e) { - console.error("unknown account name during parsing"); - return null; - } -} diff --git a/sdk/src/prices/calculate-pool-prices.ts b/sdk/src/prices/calculate-pool-prices.ts deleted file mode 100644 index fca1e73..0000000 --- a/sdk/src/prices/calculate-pool-prices.ts +++ /dev/null @@ -1,193 +0,0 @@ -import { Address } from "@coral-xyz/anchor"; -import { AddressUtil, DecimalUtil, Percentage } from "@orca-so/common-sdk"; -import { PublicKey } from "@solana/web3.js"; -import BN from "bn.js"; -import Decimal from "decimal.js"; -import { - DecimalsMap, - GetPricesConfig, - GetPricesThresholdConfig, - PoolMap, - PriceMap, - TickArrayMap, - defaultGetPricesConfig, -} from "."; -import { swapQuoteWithParams } from "../quotes/public/swap-quote"; -import { TickArray, WhirlpoolData } from "../types/public"; -import { PoolUtil, PriceMath, SwapUtils } from "../utils/public"; - -function checkLiquidity( - pool: WhirlpoolData, - tickArrays: TickArray[], - aToB: boolean, - thresholdConfig: GetPricesThresholdConfig, - decimalsMap: DecimalsMap -): boolean { - const { amountOut, priceImpactThreshold } = thresholdConfig; - - let estimatedAmountIn; - - try { - ({ estimatedAmountIn } = swapQuoteWithParams( - { - whirlpoolData: pool, - aToB, - amountSpecifiedIsInput: false, - tokenAmount: amountOut, - otherAmountThreshold: SwapUtils.getDefaultOtherAmountThreshold(false), - sqrtPriceLimit: SwapUtils.getDefaultSqrtPriceLimit(aToB), - tickArrays, - }, - Percentage.fromDecimal(new Decimal(0)) - )); - } catch (e) { - // If a quote could not be generated, assume there is insufficient liquidity - return false; - } - - // Calculate the maximum amount in that is allowed against the desired output - let price, inputDecimals, outputDecimals; - if (aToB) { - price = getPrice(pool, decimalsMap); - inputDecimals = decimalsMap[pool.tokenMintA.toBase58()]; - outputDecimals = decimalsMap[pool.tokenMintB.toBase58()]; - } else { - price = getPrice(pool, decimalsMap).pow(-1); - inputDecimals = decimalsMap[pool.tokenMintB.toBase58()]; - outputDecimals = decimalsMap[pool.tokenMintA.toBase58()]; - } - - const amountOutDecimals = DecimalUtil.fromBN(amountOut, outputDecimals); - - const estimatedAmountInDecimals = DecimalUtil.fromBN(estimatedAmountIn, inputDecimals); - - const maxAmountInDecimals = amountOutDecimals - .div(price) - .mul(priceImpactThreshold) - .toDecimalPlaces(inputDecimals); - - return estimatedAmountInDecimals.lte(maxAmountInDecimals); -} - -type PoolObject = { pool: WhirlpoolData; address: PublicKey }; -function getMostLiquidPools( - quoteTokenMint: PublicKey, - poolMap: PoolMap -): Record { - const mostLiquidPools = new Map(); - Object.entries(poolMap).forEach(([address, pool]) => { - const mintA = pool.tokenMintA.toBase58(); - const mintB = pool.tokenMintB.toBase58(); - - if (pool.liquidity.isZero()) { - return; - } - if (!pool.tokenMintA.equals(quoteTokenMint) && !pool.tokenMintB.equals(quoteTokenMint)) { - return; - } - - const baseTokenMint = pool.tokenMintA.equals(quoteTokenMint) ? mintB : mintA; - - const existingPool = mostLiquidPools.get(baseTokenMint); - if (!existingPool || pool.liquidity.gt(existingPool.pool.liquidity)) { - mostLiquidPools.set(baseTokenMint, { address: AddressUtil.toPubKey(address), pool }); - } - }); - - return Object.fromEntries(mostLiquidPools); -} - -export function calculatePricesForQuoteToken( - mints: Address[], - quoteTokenMint: PublicKey, - poolMap: PoolMap, - tickArrayMap: TickArrayMap, - decimalsMap: DecimalsMap, - config: GetPricesConfig, - thresholdConfig: GetPricesThresholdConfig -): PriceMap { - const mostLiquidPools = getMostLiquidPools(quoteTokenMint, poolMap); - - return Object.fromEntries( - mints.map((mintAddr) => { - const mint = AddressUtil.toPubKey(mintAddr); - if (mint.equals(quoteTokenMint)) { - return [mint.toBase58(), new Decimal(1)]; - } - - const [mintA, mintB] = PoolUtil.orderMints(mint, quoteTokenMint); - - // The quote token is the output token. - // Therefore, if the quote token is mintB, then we are swapping from mintA to mintB. - const aToB = AddressUtil.toPubKey(mintB).equals(quoteTokenMint); - - const baseTokenMint = aToB ? mintA : mintB; - const poolCandidate = mostLiquidPools[AddressUtil.toString(baseTokenMint)]; - if (poolCandidate === undefined) { - return [mint.toBase58(), null]; - } - - const { pool, address } = poolCandidate; - - const tickArrays = getTickArrays(pool, address, aToB, tickArrayMap, config); - - const isPoolLiquid = checkLiquidity(pool, tickArrays, aToB, thresholdConfig, decimalsMap); - - if (!isPoolLiquid) { - return [mint.toBase58(), null]; - } - - const price = getPrice(pool, decimalsMap); - const quotePrice = aToB ? price : price.pow(-1); - return [mint.toBase58(), quotePrice]; - }) - ); -} - -function getTickArrays( - pool: WhirlpoolData, - address: PublicKey, - aToB: boolean, - tickArrayMap: TickArrayMap, - config = defaultGetPricesConfig -): TickArray[] { - const { programId } = config; - const tickArrayPublicKeys = SwapUtils.getTickArrayPublicKeys( - pool.tickCurrentIndex, - pool.tickSpacing, - aToB, - programId, - address - ); - - return tickArrayPublicKeys.map((tickArrayPublicKey) => { - return { address: tickArrayPublicKey, data: tickArrayMap[tickArrayPublicKey.toBase58()] }; - }); -} - -function getPrice(pool: WhirlpoolData, decimalsMap: DecimalsMap) { - const tokenAAddress = pool.tokenMintA.toBase58(); - const tokenBAddress = pool.tokenMintB.toBase58(); - if (!(tokenAAddress in decimalsMap) || !(tokenBAddress in decimalsMap)) { - throw new Error("Missing token decimals"); - } - - return PriceMath.sqrtPriceX64ToPrice( - pool.sqrtPrice, - decimalsMap[tokenAAddress], - decimalsMap[tokenBAddress] - ); -} - -export function isSubset(listA: string[], listB: string[]): boolean { - return listA.every((itemA) => listB.includes(itemA)); -} - -export function convertAmount( - amount: BN, - price: Decimal, - amountDecimal: number, - resultDecimal: number -): BN { - return DecimalUtil.toBN(DecimalUtil.fromBN(amount, amountDecimal).div(price), resultDecimal); -} diff --git a/sdk/src/prices/index.ts b/sdk/src/prices/index.ts deleted file mode 100644 index bee3cd4..0000000 --- a/sdk/src/prices/index.ts +++ /dev/null @@ -1,115 +0,0 @@ -import { PublicKey } from "@solana/web3.js"; -import BN from "bn.js"; -import Decimal from "decimal.js"; -import { - ORCA_SUPPORTED_TICK_SPACINGS, - ORCA_WHIRLPOOLS_CONFIG, - ORCA_WHIRLPOOL_PROGRAM_ID, - TickArrayData, - WhirlpoolData, -} from "../types/public"; -import { TOKEN_MINTS } from "../utils/constants"; - -export * from "./price-module"; - -/** - * A config object for the {@link PriceModule} functions. - * - * @category PriceModule - * @param quoteTokens The group of quote tokens that you want to search Whirlpools for. - * The first token must be the token that is being priced against the other tokens. - * The subsequent tokens are alternative tokens that can be used to price the first token. - * @param tickSpacings The group of tick spacings that you want to search Whirlpools for. - * @param programId The public key of the Whirlpool Program account that you want to search Whirlpools for. - * @param whirlpoolsConfig The public key of the {@link WhirlpoolsConfig} account that you want to search Whirlpools for. - */ -export type GetPricesConfig = { - quoteTokens: PublicKey[]; - tickSpacings: number[]; - programId: PublicKey; - whirlpoolsConfig: PublicKey; -}; - -/** - * A config object for the {@link PriceModule} functions to define thresholds for price calculations. - * Whirlpools that do not fit the criteria set by the parameters below will be excluded in the price calculation. - * - * @category PriceModule - * @param amountOut The token amount in terms of the first quote token amount to evaluate a Whirlpool's liquidity against. - * @param priceImpactThreshold Using amountOut to perform a swap quote on a pool, this value is the maximum price impact - * that a Whirlpool can have to be included in the price calculation. - */ -export type GetPricesThresholdConfig = { - amountOut: BN; - priceImpactThreshold: number; -}; - -/** - * A set of fetched accounts that are used for price calculations in {@link PriceModule} functions. - * - * @category PriceModule - * @param poolMap A map of {@link WhirlpoolData} accounts that are used for price calculations. - * @param tickArrayMap A map of {@link TickArrayData} accounts that are used for price calculations. - * @param decimalsMap A map of token decimals that are used for price calculations. - */ -export type PriceCalculationData = { - poolMap: PoolMap; - tickArrayMap: TickArrayMap; - decimalsMap: DecimalsMap; -}; - -/** - * A map of whirlpool addresses against {@link WhirlpoolData} accounts - * @category PriceModule - */ -export type PoolMap = Record; - -/** - * A map of tick-array addresses against {@link TickArrayData} accounts - * @category PriceModule - */ -export type TickArrayMap = Record; - -/** - * A map of token mint addresses against price values. If a price is not available, the value will be null. - * @category PriceModule - */ -export type PriceMap = Record; - -/** - * A map of token mint addresses against token decimals. - * @category PriceModule - */ -export type DecimalsMap = Record; - -/** - * The default quote tokens used for Orca's mainnet deployment. - * Supply your own if you are using a different deployment. - * @category PriceModule - */ -export const defaultQuoteTokens: PublicKey[] = [ - TOKEN_MINTS["USDC"], - TOKEN_MINTS["SOL"], - TOKEN_MINTS["mSOL"], - TOKEN_MINTS["stSOL"], -].map((mint) => new PublicKey(mint)); - -/** - * The default {@link GetPricesConfig} config for Orca's mainnet deployment. - * @category PriceModule - */ -export const defaultGetPricesConfig: GetPricesConfig = { - quoteTokens: defaultQuoteTokens, - tickSpacings: ORCA_SUPPORTED_TICK_SPACINGS, - programId: ORCA_WHIRLPOOL_PROGRAM_ID, - whirlpoolsConfig: ORCA_WHIRLPOOLS_CONFIG, -}; - -/** - * The default {@link GetPricesThresholdConfig} config for Orca's mainnet deployment. - * @category PriceModule - */ -export const defaultGetPricesThresholdConfig: GetPricesThresholdConfig = { - amountOut: new BN(1_000_000_000), - priceImpactThreshold: 1.05, -}; diff --git a/sdk/src/prices/price-module.ts b/sdk/src/prices/price-module.ts deleted file mode 100644 index 4bf1bf1..0000000 --- a/sdk/src/prices/price-module.ts +++ /dev/null @@ -1,353 +0,0 @@ -import { Address } from "@coral-xyz/anchor"; -import { AddressUtil } from "@orca-so/common-sdk"; -import { PublicKey } from "@solana/web3.js"; -import { - DecimalsMap, - PoolMap, - PriceCalculationData, - PriceMap, - TickArrayMap, - defaultGetPricesConfig, - defaultGetPricesThresholdConfig, -} from "."; -import { - IGNORE_CACHE, - PREFER_CACHE, - WhirlpoolAccountFetchOptions, - WhirlpoolAccountFetcherInterface, -} from "../network/public/fetcher"; -import { PDAUtil, PoolUtil, SwapUtils } from "../utils/public"; -import { convertListToMap, filterNullObjects } from "../utils/txn-utils"; -import { calculatePricesForQuoteToken, convertAmount, isSubset } from "./calculate-pool-prices"; - -/** - * PriceModule is a static class that provides functions for fetching and calculating - * token prices for a set of pools or mints. - * - * @category PriceModule - */ -export class PriceModule { - /** - * Fetches and calculates the prices for a set of tokens. - * This method will derive the pools that need to be queried from the mints and is not performant. - * - * @param fetcher {@link WhirlpoolAccountFetcherInterface} - * @param mints The mints to fetch prices for. - * @param config The configuration for the price calculation. - * @param thresholdConfig - The threshold configuration for the price calculation. - * @param opts an {@link WhirlpoolAccountFetchOptions} object to define fetch and cache options when accessing on-chain accounts - * @param availableData - Data that is already available to avoid redundant fetches. - * @returns A map of token addresses to prices. - */ - static async fetchTokenPricesByMints( - fetcher: WhirlpoolAccountFetcherInterface, - mints: Address[], - config = defaultGetPricesConfig, - thresholdConfig = defaultGetPricesThresholdConfig, - opts = IGNORE_CACHE, - availableData: Partial = {} - ): Promise { - const poolMap = availableData?.poolMap - ? availableData?.poolMap - : await PriceModuleUtils.fetchPoolDataFromMints(fetcher, mints, config, opts); - const tickArrayMap = availableData?.tickArrayMap - ? availableData.tickArrayMap - : await PriceModuleUtils.fetchTickArraysForPools(fetcher, poolMap, config, opts); - const decimalsMap = availableData?.decimalsMap - ? availableData.decimalsMap - : await PriceModuleUtils.fetchDecimalsForMints(fetcher, mints, PREFER_CACHE); - - return PriceModule.calculateTokenPrices( - mints, - { - poolMap, - tickArrayMap, - decimalsMap, - }, - config, - thresholdConfig - ); - } - - /** - * Fetches and calculates the token prices from a set of pools. - * - * @param fetcher {@link WhirlpoolAccountFetcherInterface} - * @param pools The pools to fetch prices for. - * @param config The configuration for the price calculation. - * @param thresholdConfig The threshold configuration for the price calculation. - * @param opts an {@link WhirlpoolAccountFetchOptions} object to define fetch and cache options when accessing on-chain accounts - * @returns A map of token addresses to prices - */ - static async fetchTokenPricesByPools( - fetcher: WhirlpoolAccountFetcherInterface, - pools: Address[], - config = defaultGetPricesConfig, - thresholdConfig = defaultGetPricesThresholdConfig, - opts: WhirlpoolAccountFetchOptions = IGNORE_CACHE - ): Promise { - const poolDatas = Array.from((await fetcher.getPools(pools, opts)).values()); - const [filteredPoolDatas, filteredPoolAddresses] = filterNullObjects(poolDatas, pools); - const poolMap = convertListToMap( - filteredPoolDatas, - AddressUtil.toStrings(filteredPoolAddresses) - ); - - const tickArrayMap = await PriceModuleUtils.fetchTickArraysForPools( - fetcher, - poolMap, - config, - opts - ); - const mints = Array.from( - Object.values(poolMap).reduce((acc, pool) => { - acc.add(pool.tokenMintA.toBase58()); - acc.add(pool.tokenMintB.toBase58()); - return acc; - }, new Set()) - ); - const decimalsMap = await PriceModuleUtils.fetchDecimalsForMints(fetcher, mints, PREFER_CACHE); - - return PriceModule.calculateTokenPrices( - mints, - { - poolMap, - tickArrayMap, - decimalsMap, - }, - config, - thresholdConfig - ); - } - - /** - * Calculate the price of each token in the mints array. - * - * Each token will be priced against the first quote token in the config.quoteTokens array - * with sufficient liquidity. If a token does not have sufficient liquidity against the - * first quote token, then it will be priced against the next quote token in the array. - * If a token does not have sufficient liquidity against any quote token, - * then the price will be set to null. - * - * @category PriceModule - * @param mints The mints to calculate prices for. - * @param priceCalcData The data required to calculate prices. - * @param config The configuration for the price calculation. - * @param thresholdConfig The threshold configuration for the price calculation. - * @returns A map of token addresses to prices. - */ - static calculateTokenPrices( - mints: Address[], - priceCalcData: PriceCalculationData, - config = defaultGetPricesConfig, - thresholdConfig = defaultGetPricesThresholdConfig - ): PriceMap { - const { poolMap, decimalsMap, tickArrayMap } = priceCalcData; - const mintStrings = AddressUtil.toStrings(mints); - // Ensure that quote tokens are in the mints array - if ( - !isSubset( - config.quoteTokens.map((mint) => AddressUtil.toString(mint)), - mintStrings.map((mint) => mint) - ) - ) { - throw new Error("Quote tokens must be in mints array"); - } - - const results: PriceMap = Object.fromEntries(mintStrings.map((mint) => [mint, null])); - - const remainingQuoteTokens = config.quoteTokens.slice(); - let remainingMints = mints.slice(); - - while (remainingQuoteTokens.length > 0 && remainingMints.length > 0) { - // Get prices for mints using the next token in remainingQuoteTokens as the quote token - const quoteToken = remainingQuoteTokens.shift(); - if (!quoteToken) { - throw new Error("Unreachable: remainingQuoteTokens is an empty array"); - } - - // Convert the threshold amount out from the first quote token to the current quote token - let amountOutThresholdAgainstFirstQuoteToken; - - // If the quote token is the first quote token, then the amount out is the threshold amount - if (quoteToken.equals(config.quoteTokens[0])) { - amountOutThresholdAgainstFirstQuoteToken = thresholdConfig.amountOut; - } else { - const quoteTokenStr = quoteToken.toBase58(); - const quoteTokenPrice = results[quoteTokenStr]; - if (!quoteTokenPrice) { - throw new Error( - `Quote token - ${quoteTokenStr} must have a price against the first quote token` - ); - } - - amountOutThresholdAgainstFirstQuoteToken = convertAmount( - thresholdConfig.amountOut, - quoteTokenPrice, - decimalsMap[config.quoteTokens[0].toBase58()], - decimalsMap[quoteTokenStr] - ); - } - - const prices = calculatePricesForQuoteToken( - remainingMints, - quoteToken, - poolMap, - tickArrayMap, - decimalsMap, - config, - { - amountOut: amountOutThresholdAgainstFirstQuoteToken, - priceImpactThreshold: thresholdConfig.priceImpactThreshold, - } - ); - - const quoteTokenPrice = results[quoteToken.toBase58()] || prices[quoteToken.toBase58()]; - - // Populate the results map with the calculated prices. - // Ensure that the price is quoted against the first quote token and not the current quote token. - remainingMints.forEach((mintAddr) => { - const mint = AddressUtil.toString(mintAddr); - const mintPrice = prices[mint]; - if (mintPrice != null && quoteTokenPrice != null) { - results[mint] = mintPrice.mul(quoteTokenPrice); - } - }); - - // Filter out any mints that do not have a price - remainingMints = remainingMints.filter((mint) => results[AddressUtil.toString(mint)] == null); - } - - return results; - } -} - -/** - * A list of utility functions for the price module. - * @category PriceModule - */ -export class PriceModuleUtils { - /** - * Fetch pool data for the given mints by deriving the PDA from all combinations of mints & tick-arrays. - * Note that this method can be slow. - * - * @param fetcher {@link WhirlpoolAccountFetcherInterface} - * @param mints The mints to fetch pool data for. - * @param config The configuration for the price calculation. - * @param opts an {@link WhirlpoolAccountFetchOptions} object to define fetch and cache options when accessing on-chain accounts - * @returns A {@link PoolMap} of pool addresses to pool data. - */ - static async fetchPoolDataFromMints( - fetcher: WhirlpoolAccountFetcherInterface, - mints: Address[], - config = defaultGetPricesConfig, - opts = IGNORE_CACHE - ): Promise { - const { quoteTokens, tickSpacings, programId, whirlpoolsConfig } = config; - const poolAddresses: string[] = mints - .map((mint): string[] => - tickSpacings - .map((tickSpacing): string[] => { - return quoteTokens.map((quoteToken): string => { - const [mintA, mintB] = PoolUtil.orderMints(mint, quoteToken); - return PDAUtil.getWhirlpool( - programId, - whirlpoolsConfig, - AddressUtil.toPubKey(mintA), - AddressUtil.toPubKey(mintB), - tickSpacing - ).publicKey.toBase58(); - }); - }) - .flat() - ) - .flat(); - - const poolDatas = Array.from((await fetcher.getPools(poolAddresses, opts)).values()); - - const [filteredPoolDatas, filteredPoolAddresses] = filterNullObjects(poolDatas, poolAddresses); - return convertListToMap(filteredPoolDatas, filteredPoolAddresses); - } - - /** - * Fetch tick-array data for the given pools - * - * @param fetcher {@link WhirlpoolAccountFetcherInterface} - * @param pools The pools to fetch tick-array data for. - * @param config The configuration for the price calculation. - * @param opts an {@link WhirlpoolAccountFetchOptions} object to define fetch and cache options when accessing on-chain accounts - * @returns A {@link TickArrayMap} of tick-array addresses to tick-array data. - */ - static async fetchTickArraysForPools( - fetcher: WhirlpoolAccountFetcherInterface, - pools: PoolMap, - config = defaultGetPricesConfig, - opts: WhirlpoolAccountFetchOptions = IGNORE_CACHE - ): Promise { - const { programId } = config; - - const getQuoteTokenOrder = (mint: PublicKey) => { - const index = config.quoteTokens.findIndex((quoteToken) => quoteToken.equals(mint)); - return index === -1 ? config.quoteTokens.length : index; - }; - - // select tick arrays based on the direction of swapQuote - // TickArray is a large account, which affects decoding time. - // Fetching can be performed in parallel, but it is preferable to fetch the minimum number of accounts necessary. - const tickArrayAddressSet = new Set(); - Object.entries(pools).forEach(([address, pool]) => { - const orderA = getQuoteTokenOrder(pool.tokenMintA); - const orderB = getQuoteTokenOrder(pool.tokenMintB); - - if (orderA === orderB) { - // neither tokenMintA nor tokenMintB is a quote token - return; - } - - const aToB = orderA > orderB; - - const tickArrayPubkeys = SwapUtils.getTickArrayPublicKeys( - pool.tickCurrentIndex, - pool.tickSpacing, - aToB, - programId, - new PublicKey(address) - ); - tickArrayPubkeys.forEach((p) => tickArrayAddressSet.add(p.toBase58())); - }); - const tickArrayAddresses = Array.from(tickArrayAddressSet); - - const tickArrays = await fetcher.getTickArrays(tickArrayAddresses, opts); - - const [filteredTickArrays, filteredTickArrayAddresses] = filterNullObjects( - tickArrays, - tickArrayAddresses - ); - return convertListToMap(filteredTickArrays, filteredTickArrayAddresses); - } - - /** - * Fetch the decimals to token mapping for the given mints. - * @param fetcher {@link WhirlpoolAccountFetcherInterface} - * @param mints The mints to fetch decimals for. - * @param opts an {@link WhirlpoolAccountFetchOptions} object to define fetch and cache options when accessing on-chain accounts - * @returns A {@link DecimalsMap} of mint addresses to decimals. - */ - static async fetchDecimalsForMints( - fetcher: WhirlpoolAccountFetcherInterface, - mints: Address[], - opts = IGNORE_CACHE - ): Promise { - const mintInfos = Array.from((await fetcher.getMintInfos(mints, opts)).values()); - - return mintInfos.reduce((acc, mintInfo, index) => { - const mint = AddressUtil.toString(mints[index]); - if (!mintInfo) { - throw new Error(`Mint account does not exist: ${mint}`); - } - - acc[mint] = mintInfo.decimals; - return acc; - }, {} as DecimalsMap); - } -} diff --git a/sdk/src/quotes/public/collect-fees-quote.ts b/sdk/src/quotes/public/collect-fees-quote.ts deleted file mode 100644 index d5ddeb8..0000000 --- a/sdk/src/quotes/public/collect-fees-quote.ts +++ /dev/null @@ -1,116 +0,0 @@ -import { BN } from "@coral-xyz/anchor"; -import { MathUtil } from "@orca-so/common-sdk"; -import { PositionData, TickData, WhirlpoolData } from "../../types/public"; - -/** - * @category Quotes - */ -export type CollectFeesQuoteParam = { - whirlpool: WhirlpoolData; - position: PositionData; - tickLower: TickData; - tickUpper: TickData; -}; - -/** - * @category Quotes - */ -export type CollectFeesQuote = { - feeOwedA: BN; - feeOwedB: BN; -}; - -/** - * Get a quote on the outstanding fees owed to a position. - * - * @category Quotes - * @param param A collection of fetched Whirlpool accounts to faciliate the quote. - * @returns A quote object containing the fees owed for each token in the pool. - */ -export function collectFeesQuote(param: CollectFeesQuoteParam): CollectFeesQuote { - const { whirlpool, position, tickLower, tickUpper } = param; - - const { - tickCurrentIndex, - feeGrowthGlobalA: feeGrowthGlobalAX64, - feeGrowthGlobalB: feeGrowthGlobalBX64, - } = whirlpool; - const { - tickLowerIndex, - tickUpperIndex, - liquidity, - feeOwedA, - feeOwedB, - feeGrowthCheckpointA: feeGrowthCheckpointAX64, - feeGrowthCheckpointB: feeGrowthCheckpointBX64, - } = position; - const { - feeGrowthOutsideA: tickLowerFeeGrowthOutsideAX64, - feeGrowthOutsideB: tickLowerFeeGrowthOutsideBX64, - } = tickLower; - const { - feeGrowthOutsideA: tickUpperFeeGrowthOutsideAX64, - feeGrowthOutsideB: tickUpperFeeGrowthOutsideBX64, - } = tickUpper; - - // Calculate the fee growths inside the position - - let feeGrowthBelowAX64: BN | null = null; - let feeGrowthBelowBX64: BN | null = null; - - if (tickCurrentIndex < tickLowerIndex) { - feeGrowthBelowAX64 = MathUtil.subUnderflowU128( - feeGrowthGlobalAX64, - tickLowerFeeGrowthOutsideAX64 - ); - feeGrowthBelowBX64 = MathUtil.subUnderflowU128( - feeGrowthGlobalBX64, - tickLowerFeeGrowthOutsideBX64 - ); - } else { - feeGrowthBelowAX64 = tickLowerFeeGrowthOutsideAX64; - feeGrowthBelowBX64 = tickLowerFeeGrowthOutsideBX64; - } - - let feeGrowthAboveAX64: BN | null = null; - let feeGrowthAboveBX64: BN | null = null; - - if (tickCurrentIndex < tickUpperIndex) { - feeGrowthAboveAX64 = tickUpperFeeGrowthOutsideAX64; - feeGrowthAboveBX64 = tickUpperFeeGrowthOutsideBX64; - } else { - feeGrowthAboveAX64 = MathUtil.subUnderflowU128( - feeGrowthGlobalAX64, - tickUpperFeeGrowthOutsideAX64 - ); - feeGrowthAboveBX64 = MathUtil.subUnderflowU128( - feeGrowthGlobalBX64, - tickUpperFeeGrowthOutsideBX64 - ); - } - - const feeGrowthInsideAX64 = MathUtil.subUnderflowU128( - MathUtil.subUnderflowU128(feeGrowthGlobalAX64, feeGrowthBelowAX64), - feeGrowthAboveAX64 - ); - const feeGrowthInsideBX64 = MathUtil.subUnderflowU128( - MathUtil.subUnderflowU128(feeGrowthGlobalBX64, feeGrowthBelowBX64), - feeGrowthAboveBX64 - ); - - // Calculate the updated fees owed - const feeOwedADelta = MathUtil.subUnderflowU128(feeGrowthInsideAX64, feeGrowthCheckpointAX64) - .mul(liquidity) - .shrn(64); - const feeOwedBDelta = MathUtil.subUnderflowU128(feeGrowthInsideBX64, feeGrowthCheckpointBX64) - .mul(liquidity) - .shrn(64); - - const updatedFeeOwedA = feeOwedA.add(feeOwedADelta); - const updatedFeeOwedB = feeOwedB.add(feeOwedBDelta); - - return { - feeOwedA: updatedFeeOwedA, - feeOwedB: updatedFeeOwedB, - }; -} diff --git a/sdk/src/quotes/public/collect-rewards-quote.ts b/sdk/src/quotes/public/collect-rewards-quote.ts deleted file mode 100644 index 2ea3331..0000000 --- a/sdk/src/quotes/public/collect-rewards-quote.ts +++ /dev/null @@ -1,119 +0,0 @@ -import { BN } from "@coral-xyz/anchor"; -import { MathUtil } from "@orca-so/common-sdk"; -import invariant from "tiny-invariant"; -import { NUM_REWARDS, PositionData, TickData, WhirlpoolData } from "../../types/public"; -import { BitMath } from "../../utils/math/bit-math"; -import { PoolUtil } from "../../utils/public/pool-utils"; - -/** - * Parameters needed to generate a quote on collectible rewards on a position. - * @category Quotes - * @param whirlpool - the account data for the whirlpool this position belongs to - * @param position - the account data for the position - * @param tickLower - the TickData account for the lower bound of this position - * @param tickUpper - the TickData account for the upper bound of this position - * @param timeStampInSeconds - optional parameter to generate this quote to a unix time stamp. - */ -export type CollectRewardsQuoteParam = { - whirlpool: WhirlpoolData; - position: PositionData; - tickLower: TickData; - tickUpper: TickData; - timeStampInSeconds?: BN; -}; - -/** - * An array of reward amounts that is collectible on a position. - * @category Quotes - */ -export type CollectRewardsQuote = [BN | undefined, BN | undefined, BN | undefined]; - -/** - * Get a quote on the outstanding rewards owed to a position. - * - * @category Quotes - * @param param A collection of fetched Whirlpool accounts to faciliate the quote. - * @returns A quote object containing the rewards owed for each reward in the pool. - */ -export function collectRewardsQuote(param: CollectRewardsQuoteParam): CollectRewardsQuote { - const { whirlpool, position, tickLower, tickUpper, timeStampInSeconds } = param; - - const { - tickCurrentIndex, - rewardInfos: whirlpoolRewardsInfos, - rewardLastUpdatedTimestamp, - } = whirlpool; - const { tickLowerIndex, tickUpperIndex, liquidity, rewardInfos: positionRewardInfos } = position; - - const currTimestampInSeconds = timeStampInSeconds ?? new BN(Date.now()).div(new BN(1000)); - const timestampDelta = currTimestampInSeconds.sub(new BN(rewardLastUpdatedTimestamp)); - const rewardOwed: CollectRewardsQuote = [undefined, undefined, undefined]; - - for (let i = 0; i < NUM_REWARDS; i++) { - // Calculate the reward growth on the outside of the position (growth_above, growth_below) - const rewardInfo = whirlpoolRewardsInfos[i]; - const positionRewardInfo = positionRewardInfos[i]; - invariant(!!rewardInfo, "whirlpoolRewardsInfos cannot be undefined"); - - const isRewardInitialized = PoolUtil.isRewardInitialized(rewardInfo); - if (!isRewardInitialized) { - continue; - } - - // Increment the global reward growth tracker based on time elasped since the last whirlpool update. - let adjustedRewardGrowthGlobalX64 = rewardInfo.growthGlobalX64; - if (!whirlpool.liquidity.isZero()) { - const rewardGrowthDelta = BitMath.mulDiv( - timestampDelta, - rewardInfo.emissionsPerSecondX64, - whirlpool.liquidity, - 128 - ); - adjustedRewardGrowthGlobalX64 = rewardInfo.growthGlobalX64.add(rewardGrowthDelta); - } - - // Calculate the reward growth outside of the position - const tickLowerRewardGrowthsOutsideX64 = tickLower.rewardGrowthsOutside[i]; - const tickUpperRewardGrowthsOutsideX64 = tickUpper.rewardGrowthsOutside[i]; - - let rewardGrowthsBelowX64: BN = adjustedRewardGrowthGlobalX64; - if (tickLower.initialized) { - rewardGrowthsBelowX64 = - tickCurrentIndex < tickLowerIndex - ? MathUtil.subUnderflowU128( - adjustedRewardGrowthGlobalX64, - tickLowerRewardGrowthsOutsideX64 - ) - : tickLowerRewardGrowthsOutsideX64; - } - - let rewardGrowthsAboveX64: BN = new BN(0); - if (tickUpper.initialized) { - rewardGrowthsAboveX64 = - tickCurrentIndex < tickUpperIndex - ? tickUpperRewardGrowthsOutsideX64 - : MathUtil.subUnderflowU128( - adjustedRewardGrowthGlobalX64, - tickUpperRewardGrowthsOutsideX64 - ); - } - - const rewardGrowthInsideX64 = MathUtil.subUnderflowU128( - MathUtil.subUnderflowU128(adjustedRewardGrowthGlobalX64, rewardGrowthsBelowX64), - rewardGrowthsAboveX64 - ); - - // Knowing the growth of the reward checkpoint for the position, calculate and increment the amount owed for each reward. - const amountOwedX64 = positionRewardInfo.amountOwed.shln(64); - rewardOwed[i] = amountOwedX64 - .add( - MathUtil.subUnderflowU128( - rewardGrowthInsideX64, - positionRewardInfo.growthInsideCheckpoint - ).mul(liquidity) - ) - .shrn(64); - } - - return rewardOwed; -} diff --git a/sdk/src/quotes/public/decrease-liquidity-quote.ts b/sdk/src/quotes/public/decrease-liquidity-quote.ts deleted file mode 100644 index acd1a80..0000000 --- a/sdk/src/quotes/public/decrease-liquidity-quote.ts +++ /dev/null @@ -1,163 +0,0 @@ -import { BN } from "@coral-xyz/anchor"; -import { Percentage, ZERO } from "@orca-so/common-sdk"; -import invariant from "tiny-invariant"; -import { DecreaseLiquidityInput } from "../../instructions"; -import { - adjustForSlippage, - getTokenAFromLiquidity, - getTokenBFromLiquidity, - PositionStatus, - PositionUtil, -} from "../../utils/position-util"; -import { PriceMath, TickUtil } from "../../utils/public"; -import { Position, Whirlpool } from "../../whirlpool-client"; - -/** - * @category Quotes - * @param liquidity - The desired liquidity to withdraw from the Whirlpool - * @param tickCurrentIndex - The Whirlpool's current tickIndex - * @param sqrtPrice - The Whirlpool's current sqrtPrice - * @param tickLowerIndex - The lower index of the position that we are withdrawing from. - * @param tickUpperIndex - The upper index of the position that we are withdrawing from. - * @param slippageTolerance - The maximum slippage allowed when calculating the minimum tokens received. - */ -export type DecreaseLiquidityQuoteParam = { - liquidity: BN; - tickCurrentIndex: number; - sqrtPrice: BN; - tickLowerIndex: number; - tickUpperIndex: number; - slippageTolerance: Percentage; -}; - -/** - * Return object from decrease liquidity quote functions. - * @category Quotes - */ -export type DecreaseLiquidityQuote = DecreaseLiquidityInput & { tokenEstA: BN; tokenEstB: BN }; - -/** - * Get an estimated quote on the minimum tokens receivable based on the desired withdraw liquidity value. - * - * @category Quotes - * @param liquidity - The desired liquidity to withdraw from the Whirlpool - * @param slippageTolerance - The maximum slippage allowed when calculating the minimum tokens received. - * @param position - A Position helper class to help interact with the Position account. - * @param whirlpool - A Whirlpool helper class to help interact with the Whirlpool account. - * @returns An DecreaseLiquidityQuote object detailing the tokenMin & liquidity values to use when calling decrease-liquidity-ix. - */ -export function decreaseLiquidityQuoteByLiquidity( - liquidity: BN, - slippageTolerance: Percentage, - position: Position, - whirlpool: Whirlpool -) { - const positionData = position.getData(); - const whirlpoolData = whirlpool.getData(); - - invariant( - liquidity.lte(positionData.liquidity), - "Quote liquidity is more than the position liquidity." - ); - - return decreaseLiquidityQuoteByLiquidityWithParams({ - liquidity, - slippageTolerance, - tickLowerIndex: positionData.tickLowerIndex, - tickUpperIndex: positionData.tickUpperIndex, - sqrtPrice: whirlpoolData.sqrtPrice, - tickCurrentIndex: whirlpoolData.tickCurrentIndex, - }); -} - -/** - * Get an estimated quote on the minimum tokens receivable based on the desired withdraw liquidity value. - * - * @category Quotes - * @param param DecreaseLiquidityQuoteParam - * @returns An DecreaseLiquidityInput object detailing the tokenMin & liquidity values to use when calling decrease-liquidity-ix. - */ -export function decreaseLiquidityQuoteByLiquidityWithParams( - param: DecreaseLiquidityQuoteParam -): DecreaseLiquidityQuote { - invariant(TickUtil.checkTickInBounds(param.tickLowerIndex), "tickLowerIndex is out of bounds."); - invariant(TickUtil.checkTickInBounds(param.tickUpperIndex), "tickUpperIndex is out of bounds."); - invariant( - TickUtil.checkTickInBounds(param.tickCurrentIndex), - "tickCurrentIndex is out of bounds." - ); - - const positionStatus = PositionUtil.getStrictPositionStatus( - param.sqrtPrice, - param.tickLowerIndex, - param.tickUpperIndex - ); - - switch (positionStatus) { - case PositionStatus.BelowRange: - return quotePositionBelowRange(param); - case PositionStatus.InRange: - return quotePositionInRange(param); - case PositionStatus.AboveRange: - return quotePositionAboveRange(param); - default: - throw new Error(`type ${positionStatus} is an unknown PositionStatus`); - } -} - -function quotePositionBelowRange(param: DecreaseLiquidityQuoteParam): DecreaseLiquidityQuote { - const { tickLowerIndex, tickUpperIndex, liquidity, slippageTolerance } = param; - - const sqrtPriceLowerX64 = PriceMath.tickIndexToSqrtPriceX64(tickLowerIndex); - const sqrtPriceUpperX64 = PriceMath.tickIndexToSqrtPriceX64(tickUpperIndex); - - const tokenEstA = getTokenAFromLiquidity(liquidity, sqrtPriceLowerX64, sqrtPriceUpperX64, false); - const tokenMinA = adjustForSlippage(tokenEstA, slippageTolerance, false); - - return { - tokenMinA, - tokenMinB: ZERO, - tokenEstA, - tokenEstB: ZERO, - liquidityAmount: liquidity, - }; -} - -function quotePositionInRange(param: DecreaseLiquidityQuoteParam): DecreaseLiquidityQuote { - const { sqrtPrice, tickLowerIndex, tickUpperIndex, liquidity, slippageTolerance } = param; - - const sqrtPriceX64 = sqrtPrice; - const sqrtPriceLowerX64 = PriceMath.tickIndexToSqrtPriceX64(tickLowerIndex); - const sqrtPriceUpperX64 = PriceMath.tickIndexToSqrtPriceX64(tickUpperIndex); - - const tokenEstA = getTokenAFromLiquidity(liquidity, sqrtPriceX64, sqrtPriceUpperX64, false); - const tokenMinA = adjustForSlippage(tokenEstA, slippageTolerance, false); - const tokenEstB = getTokenBFromLiquidity(liquidity, sqrtPriceLowerX64, sqrtPriceX64, false); - const tokenMinB = adjustForSlippage(tokenEstB, slippageTolerance, false); - - return { - tokenMinA, - tokenMinB, - tokenEstA, - tokenEstB, - liquidityAmount: liquidity, - }; -} - -function quotePositionAboveRange(param: DecreaseLiquidityQuoteParam): DecreaseLiquidityQuote { - const { tickLowerIndex, tickUpperIndex, liquidity, slippageTolerance: slippageTolerance } = param; - - const sqrtPriceLowerX64 = PriceMath.tickIndexToSqrtPriceX64(tickLowerIndex); - const sqrtPriceUpperX64 = PriceMath.tickIndexToSqrtPriceX64(tickUpperIndex); - - const tokenEstB = getTokenBFromLiquidity(liquidity, sqrtPriceLowerX64, sqrtPriceUpperX64, false); - const tokenMinB = adjustForSlippage(tokenEstB, slippageTolerance, false); - - return { - tokenMinA: ZERO, - tokenMinB, - tokenEstA: ZERO, - tokenEstB, - liquidityAmount: liquidity, - }; -} diff --git a/sdk/src/quotes/public/dev-fee-swap-quote.ts b/sdk/src/quotes/public/dev-fee-swap-quote.ts deleted file mode 100644 index 9f65fdd..0000000 --- a/sdk/src/quotes/public/dev-fee-swap-quote.ts +++ /dev/null @@ -1,88 +0,0 @@ -import { Address } from "@coral-xyz/anchor"; -import { Percentage } from "@orca-so/common-sdk"; -import BN from "bn.js"; -import { SwapErrorCode, WhirlpoolsError } from "../../errors/errors"; -import { - WhirlpoolAccountFetchOptions, - WhirlpoolAccountFetcherInterface, -} from "../../network/public/fetcher"; -import { Whirlpool } from "../../whirlpool-client"; -import { NormalSwapQuote, swapQuoteByInputToken } from "./swap-quote"; - -/** - * A collection of estimated values from quoting a swap that collects a developer-fee. - * @category Quotes - * @param estimatedAmountIn - Approximate number of input token swapped in the swap - * @param estimatedAmountOut - Approximate number of output token swapped in the swap - * @param estimatedEndTickIndex - Approximate tick-index the Whirlpool will land on after this swap - * @param estimatedEndSqrtPrice - Approximate sqrtPrice the Whirlpool will land on after this swap - * @param estimatedFeeAmount - Approximate feeAmount (all fees) charged on this swap - * @param estimatedSwapFeeAmount - Approximate feeAmount (LP + protocol fees) charged on this swap - * @param devFeeAmount - FeeAmount (developer fees) charged on this swap - */ -export type DevFeeSwapQuote = NormalSwapQuote & { - // NOTE: DevFeeSwaps supports input-token based swaps only as it is difficult - // to collect an exact % amount of dev-fees for output-token based swaps due to slippage. - // If there are third party requests in the future for this functionality, we can launch it - // but with the caveat that the % collected is only an estimate. - amountSpecifiedIsInput: true; - estimatedSwapFeeAmount: BN; - devFeeAmount: BN; -}; - -/** - * Get an estimated swap quote using input token amount while collecting dev fees. - * - * @category Quotes - * @param whirlpool - Whirlpool to perform the swap on - * @param inputTokenMint - PublicKey for the input token mint to swap with - * @param tokenAmount - The amount of input token to swap from - * @param slippageTolerance - The amount of slippage to account for in this quote - * @param programId - PublicKey for the Whirlpool ProgramId - * @param cache - WhirlpoolAccountCacheInterface instance to fetch solana accounts - * @param opts an {@link WhirlpoolAccountFetchOptions} object to define fetch and cache options when accessing on-chain accounts - * @param devFeePercentage - The percentage amount to send to developer wallet prior to the swap. Percentage num/dem values has to match token decimal. - * @returns a SwapQuote object with slippage adjusted SwapInput parameters & estimates on token amounts, fee & end whirlpool states. - */ -export async function swapQuoteByInputTokenWithDevFees( - whirlpool: Whirlpool, - inputTokenMint: Address, - tokenAmount: BN, - slippageTolerance: Percentage, - programId: Address, - fetcher: WhirlpoolAccountFetcherInterface, - devFeePercentage: Percentage, - opts?: WhirlpoolAccountFetchOptions -): Promise { - if (devFeePercentage.toDecimal().greaterThanOrEqualTo(1)) { - throw new WhirlpoolsError( - "Provided devFeePercentage must be less than 100%", - SwapErrorCode.InvalidDevFeePercentage - ); - } - - const devFeeAmount = tokenAmount - .mul(devFeePercentage.numerator) - .div(devFeePercentage.denominator); - - const slippageAdjustedQuote = await swapQuoteByInputToken( - whirlpool, - inputTokenMint, - tokenAmount.sub(devFeeAmount), - slippageTolerance, - programId, - fetcher, - opts - ); - - const devFeeAdjustedQuote: DevFeeSwapQuote = { - ...slippageAdjustedQuote, - amountSpecifiedIsInput: true, - estimatedAmountIn: slippageAdjustedQuote.estimatedAmountIn.add(devFeeAmount), - estimatedFeeAmount: slippageAdjustedQuote.estimatedFeeAmount.add(devFeeAmount), - estimatedSwapFeeAmount: slippageAdjustedQuote.estimatedFeeAmount, - devFeeAmount, - }; - - return devFeeAdjustedQuote; -} diff --git a/sdk/src/quotes/public/increase-liquidity-quote.ts b/sdk/src/quotes/public/increase-liquidity-quote.ts deleted file mode 100644 index fee80f7..0000000 --- a/sdk/src/quotes/public/increase-liquidity-quote.ts +++ /dev/null @@ -1,473 +0,0 @@ -import { Address } from "@coral-xyz/anchor"; -import { AddressUtil, DecimalUtil, Percentage, ZERO } from "@orca-so/common-sdk"; -import { PublicKey } from "@solana/web3.js"; -import BN from "bn.js"; -import Decimal from "decimal.js"; -import invariant from "tiny-invariant"; -import { IncreaseLiquidityInput } from "../../instructions"; -import { - PositionStatus, - PositionUtil, - adjustForSlippage, - getLiquidityFromTokenA, - getLiquidityFromTokenB, - getTokenAFromLiquidity, - getTokenBFromLiquidity, -} from "../../utils/position-util"; -import { PriceMath, TickUtil } from "../../utils/public"; -import { Whirlpool } from "../../whirlpool-client"; - - -/*** --------- Quote by Input Token --------- ***/ - -/** - * @category Quotes - * @param inputTokenAmount - The amount of input tokens to deposit. - * @param inputTokenMint - The mint of the input token the user would like to deposit. - * @param tokenMintA - The mint of tokenA in the Whirlpool the user is depositing into. - * @param tokenMintB -The mint of tokenB in the Whirlpool the user is depositing into. - * @param tickCurrentIndex - The Whirlpool's current tickIndex - * @param sqrtPrice - The Whirlpool's current sqrtPrice - * @param tickLowerIndex - The lower index of the position that we are withdrawing from. - * @param tickUpperIndex - The upper index of the position that we are withdrawing from. - * @param slippageTolerance - The maximum slippage allowed when calculating the minimum tokens received. - */ -export type IncreaseLiquidityQuoteParam = { - inputTokenAmount: BN; - inputTokenMint: PublicKey; - tokenMintA: PublicKey; - tokenMintB: PublicKey; - tickCurrentIndex: number; - sqrtPrice: BN; - tickLowerIndex: number; - tickUpperIndex: number; - slippageTolerance: Percentage; -}; - -/** - * Return object from increase liquidity quote functions. - * @category Quotes - */ -export type IncreaseLiquidityQuote = IncreaseLiquidityInput & IncreaseLiquidityEstimate; -type IncreaseLiquidityEstimate = { liquidityAmount: BN; tokenEstA: BN; tokenEstB: BN }; - -/** - * Get an estimated quote on the maximum tokens required to deposit based on a specified input token amount. - * This new version calculates slippage based on price percentage movement, rather than setting the percentage threshold based on token estimates. - * - * @category Quotes - * @param inputTokenAmount - The amount of input tokens to deposit. - * @param inputTokenMint - The mint of the input token the user would like to deposit. - * @param tickLower - The lower index of the position that we are depositing into. - * @param tickUpper - The upper index of the position that we are depositing into. - * @param slippageTolerance - The maximum slippage allowed when calculating the minimum tokens received. - * @param whirlpool - A Whirlpool helper class to help interact with the Whirlpool account. - * @returns An IncreaseLiquidityInput object detailing the required token amounts & liquidity values to use when calling increase-liquidity-ix. - */ -export function increaseLiquidityQuoteByInputTokenUsingPriceSlippage( - inputTokenMint: Address, - inputTokenAmount: Decimal, - tickLower: number, - tickUpper: number, - slippageTolerance: Percentage, - whirlpool: Whirlpool -) { - const data = whirlpool.getData(); - const tokenAInfo = whirlpool.getTokenAInfo(); - const tokenBInfo = whirlpool.getTokenBInfo(); - - const inputMint = AddressUtil.toPubKey(inputTokenMint); - const inputTokenInfo = inputMint.equals(tokenAInfo.mint) ? tokenAInfo : tokenBInfo; - - return increaseLiquidityQuoteByInputTokenWithParamsUsingPriceSlippage({ - inputTokenMint: inputMint, - inputTokenAmount: DecimalUtil.toBN(inputTokenAmount, inputTokenInfo.decimals), - tickLowerIndex: TickUtil.getInitializableTickIndex(tickLower, data.tickSpacing), - tickUpperIndex: TickUtil.getInitializableTickIndex(tickUpper, data.tickSpacing), - slippageTolerance, - ...data, - }); -} - -/** - * Get an estimated quote on the maximum tokens required to deposit based on a specified input token amount. - * This new version calculates slippage based on price percentage movement, rather than setting the percentage threshold based on token estimates. - * - * @category Quotes - * @param param IncreaseLiquidityQuoteParam - * @returns An IncreaseLiquidityInput object detailing the required token amounts & liquidity values to use when calling increase-liquidity-ix. - */ -export function increaseLiquidityQuoteByInputTokenWithParamsUsingPriceSlippage( - param: IncreaseLiquidityQuoteParam -): IncreaseLiquidityQuote { - invariant(TickUtil.checkTickInBounds(param.tickLowerIndex), "tickLowerIndex is out of bounds."); - invariant(TickUtil.checkTickInBounds(param.tickUpperIndex), "tickUpperIndex is out of bounds."); - invariant( - param.inputTokenMint.equals(param.tokenMintA) || param.inputTokenMint.equals(param.tokenMintB), - `input token mint ${param.inputTokenMint.toBase58()} does not match any tokens in the provided pool.` - ); - - const liquidity = getLiquidityFromInputToken(param); - - if (liquidity.eq(ZERO)) { - return { - tokenMaxA: ZERO, - tokenMaxB: ZERO, - liquidityAmount: ZERO, - tokenEstA: ZERO, - tokenEstB: ZERO, - }; - } - - return increaseLiquidityQuoteByLiquidityWithParams({ - liquidity, - tickCurrentIndex: param.tickCurrentIndex, - sqrtPrice: param.sqrtPrice, - tickLowerIndex: param.tickLowerIndex, - tickUpperIndex: param.tickUpperIndex, - slippageTolerance: param.slippageTolerance, - }); -} - -function getLiquidityFromInputToken(params: IncreaseLiquidityQuoteParam) { - const { inputTokenMint, inputTokenAmount, tickLowerIndex, tickUpperIndex, tickCurrentIndex, sqrtPrice } = params; - invariant(tickLowerIndex < tickUpperIndex, `tickLowerIndex(${tickLowerIndex}) must be less than tickUpperIndex(${tickUpperIndex})`); - - if (inputTokenAmount.eq(ZERO)) { - return ZERO; - } - - const isTokenA = params.tokenMintA.equals(inputTokenMint); - const sqrtPriceLowerX64 = PriceMath.tickIndexToSqrtPriceX64(tickLowerIndex); - const sqrtPriceUpperX64 = PriceMath.tickIndexToSqrtPriceX64(tickUpperIndex); - - const positionStatus = PositionUtil.getStrictPositionStatus(sqrtPrice, tickLowerIndex, tickUpperIndex); - - if (positionStatus === PositionStatus.BelowRange) { - return isTokenA ? getLiquidityFromTokenA(inputTokenAmount, sqrtPriceLowerX64, sqrtPriceUpperX64, false) : ZERO; - } - - if (positionStatus === PositionStatus.AboveRange) { - return isTokenA ? ZERO : getLiquidityFromTokenB(inputTokenAmount, sqrtPriceLowerX64, sqrtPriceUpperX64, false); - } - - return isTokenA - ? getLiquidityFromTokenA(inputTokenAmount, sqrtPrice, sqrtPriceUpperX64, false) - : getLiquidityFromTokenB(inputTokenAmount, sqrtPriceLowerX64, sqrtPrice, false); -} - -/*** --------- Quote by Liquidity --------- ***/ - -/** - * @category Quotes - * @param liquidity - The amount of liquidity value to deposit into the Whirlpool. - * @param tokenMintA - The mint of tokenA in the Whirlpool the user is depositing into. - * @param tokenMintB -The mint of tokenB in the Whirlpool the user is depositing into. - * @param tickCurrentIndex - The Whirlpool's current tickIndex - * @param sqrtPrice - The Whirlpool's current sqrtPrice - * @param tickLowerIndex - The lower index of the position that we are withdrawing from. - * @param tickUpperIndex - The upper index of the position that we are withdrawing from. - * @param slippageTolerance - The maximum slippage allowed when calculating the minimum tokens received. - */ -export type IncreaseLiquidityQuoteByLiquidityParam = { - liquidity: BN; - tickCurrentIndex: number; - sqrtPrice: BN; - tickLowerIndex: number; - tickUpperIndex: number; - slippageTolerance: Percentage; -}; - -export function increaseLiquidityQuoteByLiquidityWithParams(params: IncreaseLiquidityQuoteByLiquidityParam): IncreaseLiquidityQuote { - if (params.liquidity.eq(ZERO)) { - return { - tokenMaxA: ZERO, - tokenMaxB: ZERO, - liquidityAmount: ZERO, - tokenEstA: ZERO, - tokenEstB: ZERO, - }; - } - const { tokenEstA, tokenEstB } = getTokenEstimatesFromLiquidity(params); - - const { - lowerBound: [sLowerSqrtPrice, sLowerIndex], - upperBound: [sUpperSqrtPrice, sUpperIndex], - } = PriceMath.getSlippageBoundForSqrtPrice(params.sqrtPrice, params.slippageTolerance); - - const { tokenEstA: tokenEstALower, tokenEstB: tokenEstBLower } = getTokenEstimatesFromLiquidity({ - ...params, - sqrtPrice: sLowerSqrtPrice, - tickCurrentIndex: sLowerIndex, - }); - - const { tokenEstA: tokenEstAUpper, tokenEstB: tokenEstBUpper } = getTokenEstimatesFromLiquidity({ - ...params, - sqrtPrice: sUpperSqrtPrice, - tickCurrentIndex: sUpperIndex, - }); - - const tokenMaxA = BN.max(BN.max(tokenEstA, tokenEstALower), tokenEstAUpper); - const tokenMaxB = BN.max(BN.max(tokenEstB, tokenEstBLower), tokenEstBUpper); - - return { - tokenMaxA, - tokenMaxB, - tokenEstA, - tokenEstB, - liquidityAmount: params.liquidity, - }; -} - -function getTokenEstimatesFromLiquidity(params: IncreaseLiquidityQuoteByLiquidityParam) { - const { - liquidity, - sqrtPrice, - tickLowerIndex, - tickUpperIndex - } = params; - if (liquidity.eq(ZERO)) { - throw new Error("liquidity must be greater than 0"); - } - let tokenEstA = ZERO; - let tokenEstB = ZERO; - - const lowerSqrtPrice = PriceMath.tickIndexToSqrtPriceX64(tickLowerIndex); - const upperSqrtPrice = PriceMath.tickIndexToSqrtPriceX64(tickUpperIndex); - - const positionStatus = PositionUtil.getStrictPositionStatus(sqrtPrice, tickLowerIndex, tickUpperIndex); - - if (positionStatus === PositionStatus.BelowRange) { - tokenEstA = getTokenAFromLiquidity(liquidity, lowerSqrtPrice, upperSqrtPrice, true); - } else if (positionStatus === PositionStatus.InRange) { - tokenEstA = getTokenAFromLiquidity(liquidity, sqrtPrice, upperSqrtPrice, true); - tokenEstB = getTokenBFromLiquidity(liquidity, lowerSqrtPrice, sqrtPrice, true); - } else { - tokenEstB = getTokenBFromLiquidity(liquidity, lowerSqrtPrice, upperSqrtPrice, true); - } - - return { tokenEstA, tokenEstB }; -} - -/*** --------- Deprecated --------- ***/ - -/** - * Get an estimated quote on the maximum tokens required to deposit based on a specified input token amount. - * - * @category Quotes - * @param inputTokenAmount - The amount of input tokens to deposit. - * @param inputTokenMint - The mint of the input token the user would like to deposit. - * @param tickLower - The lower index of the position that we are withdrawing from. - * @param tickUpper - The upper index of the position that we are withdrawing from. - * @param slippageTolerance - The maximum slippage allowed when calculating the minimum tokens received. - * @param whirlpool - A Whirlpool helper class to help interact with the Whirlpool account. - * @returns An IncreaseLiquidityInput object detailing the required token amounts & liquidity values to use when calling increase-liquidity-ix. - * @deprecated Use increaseLiquidityQuoteByInputTokenUsingPriceSlippage instead. - */ -export function increaseLiquidityQuoteByInputToken( - inputTokenMint: Address, - inputTokenAmount: Decimal, - tickLower: number, - tickUpper: number, - slippageTolerance: Percentage, - whirlpool: Whirlpool -) { - const data = whirlpool.getData(); - const tokenAInfo = whirlpool.getTokenAInfo(); - const tokenBInfo = whirlpool.getTokenBInfo(); - - const inputMint = AddressUtil.toPubKey(inputTokenMint); - const inputTokenInfo = inputMint.equals(tokenAInfo.mint) ? tokenAInfo : tokenBInfo; - - return increaseLiquidityQuoteByInputTokenWithParams({ - inputTokenMint: inputMint, - inputTokenAmount: DecimalUtil.toBN(inputTokenAmount, inputTokenInfo.decimals), - tickLowerIndex: TickUtil.getInitializableTickIndex(tickLower, data.tickSpacing), - tickUpperIndex: TickUtil.getInitializableTickIndex(tickUpper, data.tickSpacing), - slippageTolerance: slippageTolerance, - ...data, - }); -} - -/** - * Get an estimated quote on the maximum tokens required to deposit based on a specified input token amount. - * - * @category Quotes - * @param param IncreaseLiquidityQuoteParam - * @returns An IncreaseLiquidityInput object detailing the required token amounts & liquidity values to use when calling increase-liquidity-ix. - * @deprecated Use increaseLiquidityQuoteByInputTokenWithParams_PriceSlippage instead. - */ -export function increaseLiquidityQuoteByInputTokenWithParams( - param: IncreaseLiquidityQuoteParam -): IncreaseLiquidityQuote { - invariant(TickUtil.checkTickInBounds(param.tickLowerIndex), "tickLowerIndex is out of bounds."); - invariant(TickUtil.checkTickInBounds(param.tickUpperIndex), "tickUpperIndex is out of bounds."); - invariant( - param.inputTokenMint.equals(param.tokenMintA) || param.inputTokenMint.equals(param.tokenMintB), - `input token mint ${param.inputTokenMint.toBase58()} does not match any tokens in the provided pool.` - ); - - const positionStatus = PositionUtil.getStrictPositionStatus( - param.sqrtPrice, - param.tickLowerIndex, - param.tickUpperIndex - ); - - switch (positionStatus) { - case PositionStatus.BelowRange: - return quotePositionBelowRange(param); - case PositionStatus.InRange: - return quotePositionInRange(param); - case PositionStatus.AboveRange: - return quotePositionAboveRange(param); - default: - throw new Error(`type ${positionStatus} is an unknown PositionStatus`); - } -} - -/** - * @deprecated - */ -function quotePositionBelowRange(param: IncreaseLiquidityQuoteParam): IncreaseLiquidityQuote { - const { - tokenMintA, - inputTokenMint, - inputTokenAmount, - tickLowerIndex, - tickUpperIndex, - slippageTolerance, - } = param; - - if (!tokenMintA.equals(inputTokenMint)) { - return { - tokenMaxA: ZERO, - tokenMaxB: ZERO, - tokenEstA: ZERO, - tokenEstB: ZERO, - liquidityAmount: ZERO, - }; - } - - const sqrtPriceLowerX64 = PriceMath.tickIndexToSqrtPriceX64(tickLowerIndex); - const sqrtPriceUpperX64 = PriceMath.tickIndexToSqrtPriceX64(tickUpperIndex); - - const liquidityAmount = getLiquidityFromTokenA( - inputTokenAmount, - sqrtPriceLowerX64, - sqrtPriceUpperX64, - false - ); - - const tokenEstA = getTokenAFromLiquidity( - liquidityAmount, - sqrtPriceLowerX64, - sqrtPriceUpperX64, - true - ); - const tokenMaxA = adjustForSlippage(tokenEstA, slippageTolerance, true); - - return { - tokenMaxA, - tokenMaxB: ZERO, - tokenEstA, - tokenEstB: ZERO, - liquidityAmount, - }; -} - -/** - * @deprecated - */ -function quotePositionInRange(param: IncreaseLiquidityQuoteParam): IncreaseLiquidityQuote { - const { - tokenMintA, - sqrtPrice, - inputTokenMint, - inputTokenAmount, - tickLowerIndex, - tickUpperIndex, - slippageTolerance, - } = param; - - const sqrtPriceX64 = sqrtPrice; - const sqrtPriceLowerX64 = PriceMath.tickIndexToSqrtPriceX64(tickLowerIndex); - const sqrtPriceUpperX64 = PriceMath.tickIndexToSqrtPriceX64(tickUpperIndex); - - let [tokenEstA, tokenEstB] = tokenMintA.equals(inputTokenMint) - ? [inputTokenAmount, undefined] - : [undefined, inputTokenAmount]; - - let liquidityAmount: BN; - - if (tokenEstA) { - liquidityAmount = getLiquidityFromTokenA(tokenEstA, sqrtPriceX64, sqrtPriceUpperX64, false); - tokenEstA = getTokenAFromLiquidity(liquidityAmount, sqrtPriceX64, sqrtPriceUpperX64, true); - tokenEstB = getTokenBFromLiquidity(liquidityAmount, sqrtPriceLowerX64, sqrtPriceX64, true); - } else if (tokenEstB) { - liquidityAmount = getLiquidityFromTokenB(tokenEstB, sqrtPriceLowerX64, sqrtPriceX64, false); - tokenEstA = getTokenAFromLiquidity(liquidityAmount, sqrtPriceX64, sqrtPriceUpperX64, true); - tokenEstB = getTokenBFromLiquidity(liquidityAmount, sqrtPriceLowerX64, sqrtPriceX64, true); - } else { - throw new Error("invariant violation"); - } - - const tokenMaxA = adjustForSlippage(tokenEstA, slippageTolerance, true); - const tokenMaxB = adjustForSlippage(tokenEstB, slippageTolerance, true); - - return { - tokenMaxA, - tokenMaxB, - tokenEstA: tokenEstA!, - tokenEstB: tokenEstB!, - liquidityAmount, - }; -} - -/** - * @deprecated - */ -function quotePositionAboveRange(param: IncreaseLiquidityQuoteParam): IncreaseLiquidityQuote { - const { - tokenMintB, - inputTokenMint, - inputTokenAmount, - tickLowerIndex, - tickUpperIndex, - slippageTolerance, - } = param; - - if (!tokenMintB.equals(inputTokenMint)) { - return { - tokenMaxA: ZERO, - tokenMaxB: ZERO, - tokenEstA: ZERO, - tokenEstB: ZERO, - liquidityAmount: ZERO, - }; - } - - const sqrtPriceLowerX64 = PriceMath.tickIndexToSqrtPriceX64(tickLowerIndex); - const sqrtPriceUpperX64 = PriceMath.tickIndexToSqrtPriceX64(tickUpperIndex); - const liquidityAmount = getLiquidityFromTokenB( - inputTokenAmount, - sqrtPriceLowerX64, - sqrtPriceUpperX64, - false - ); - - const tokenEstB = getTokenBFromLiquidity( - liquidityAmount, - sqrtPriceLowerX64, - sqrtPriceUpperX64, - true - ); - const tokenMaxB = adjustForSlippage(tokenEstB, slippageTolerance, true); - - return { - tokenMaxA: ZERO, - tokenMaxB, - tokenEstA: ZERO, - tokenEstB, - liquidityAmount, - }; -} \ No newline at end of file diff --git a/sdk/src/quotes/public/index.ts b/sdk/src/quotes/public/index.ts deleted file mode 100644 index 75a8acb..0000000 --- a/sdk/src/quotes/public/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -export * from "./increase-liquidity-quote"; -export * from "./decrease-liquidity-quote"; -export * from "./collect-fees-quote"; -export * from "./collect-rewards-quote"; -export * from "./swap-quote"; -export * from "./dev-fee-swap-quote"; -export * from "./two-hop-swap-quote"; diff --git a/sdk/src/quotes/public/swap-quote.ts b/sdk/src/quotes/public/swap-quote.ts deleted file mode 100644 index 1f799de..0000000 --- a/sdk/src/quotes/public/swap-quote.ts +++ /dev/null @@ -1,205 +0,0 @@ -import { Address } from "@coral-xyz/anchor"; -import { AddressUtil, Percentage } from "@orca-so/common-sdk"; -import BN from "bn.js"; -import invariant from "tiny-invariant"; -import { SwapInput } from "../../instructions"; -import { - WhirlpoolAccountFetchOptions, - WhirlpoolAccountFetcherInterface, -} from "../../network/public/fetcher"; -import { TickArray, WhirlpoolData } from "../../types/public"; -import { PoolUtil, SwapDirection } from "../../utils/public"; -import { SwapUtils } from "../../utils/public/swap-utils"; -import { Whirlpool } from "../../whirlpool-client"; -import { simulateSwap } from "../swap/swap-quote-impl"; -import { DevFeeSwapQuote } from "./dev-fee-swap-quote"; - -/** - * @category Quotes - * - * @param tokenAmount - The amount of input or output token to swap from (depending on amountSpecifiedIsInput). - * @param otherAmountThreshold - The maximum/minimum of input/output token to swap into (depending on amountSpecifiedIsInput). - * @param sqrtPriceLimit - The maximum/minimum price the swap will swap to. - * @param aToB - The direction of the swap. True if swapping from A to B. False if swapping from B to A. - * @param amountSpecifiedIsInput - Specifies the token the parameter `amount`represents. If true, the amount represents - * the input token of the swap. - * @param tickArrays - An sequential array of tick-array objects in the direction of the trade to swap on - */ -export type SwapQuoteParam = { - whirlpoolData: WhirlpoolData; - tokenAmount: BN; - otherAmountThreshold: BN; - sqrtPriceLimit: BN; - aToB: boolean; - amountSpecifiedIsInput: boolean; - tickArrays: TickArray[]; -}; - -/** - * A collection of estimated values from quoting a swap. - * @category Quotes - * @link {BaseSwapQuote} - * @link {DevFeeSwapQuote} - */ -export type SwapQuote = NormalSwapQuote | DevFeeSwapQuote; - -/** - * A collection of estimated values from quoting a swap. - * @category Quotes - * @param estimatedAmountIn - Approximate number of input token swapped in the swap - * @param estimatedAmountOut - Approximate number of output token swapped in the swap - * @param estimatedEndTickIndex - Approximate tick-index the Whirlpool will land on after this swap - * @param estimatedEndSqrtPrice - Approximate sqrtPrice the Whirlpool will land on after this swap - * @param estimatedFeeAmount - Approximate feeAmount (all fees) charged on this swap - */ -export type SwapEstimates = { - estimatedAmountIn: BN; - estimatedAmountOut: BN; - estimatedEndTickIndex: number; - estimatedEndSqrtPrice: BN; - estimatedFeeAmount: BN; -}; - -/** - * A collection of estimated values from quoting a swap. Object can be directly used in a swap transaction. - * @category Quotes - */ -export type NormalSwapQuote = SwapInput & SwapEstimates; - -/** - * Get an estimated swap quote using input token amount. - * - * @category Quotes - * @param whirlpool - Whirlpool to perform the swap on - * @param inputTokenMint - PublicKey for the input token mint to swap with - * @param tokenAmount - The amount of input token to swap from - * @param slippageTolerance - The amount of slippage to account for in this quote - * @param programId - PublicKey for the Whirlpool ProgramId - * @param cache - WhirlpoolAccountCacheInterface instance object to fetch solana accounts - * @param opts an {@link WhirlpoolAccountFetchOptions} object to define fetch and cache options when accessing on-chain accounts - * @returns a SwapQuote object with slippage adjusted SwapInput parameters & estimates on token amounts, fee & end whirlpool states. - */ -export async function swapQuoteByInputToken( - whirlpool: Whirlpool, - inputTokenMint: Address, - tokenAmount: BN, - slippageTolerance: Percentage, - programId: Address, - fetcher: WhirlpoolAccountFetcherInterface, - opts?: WhirlpoolAccountFetchOptions -): Promise { - const params = await swapQuoteByToken( - whirlpool, - inputTokenMint, - tokenAmount, - true, - programId, - fetcher, - opts - ); - return swapQuoteWithParams(params, slippageTolerance); -} - -/** - * Get an estimated swap quote using an output token amount. - * - * Use this quote to get an estimated amount of input token needed to receive - * the defined output token amount. - * - * @category Quotes - * @param whirlpool - Whirlpool to perform the swap on - * @param outputTokenMint - PublicKey for the output token mint to swap into - * @param tokenAmount - The maximum amount of output token to receive in this swap. - * @param slippageTolerance - The amount of slippage to account for in this quote - * @param programId - PublicKey for the Whirlpool ProgramId - * @param cache - WhirlpoolAccountCacheInterface instance to fetch solana accounts - * @param opts an {@link WhirlpoolAccountFetchOptions} object to define fetch and cache options when accessing on-chain accounts - * @returns a SwapQuote object with slippage adjusted SwapInput parameters & estimates on token amounts, fee & end whirlpool states. - */ -export async function swapQuoteByOutputToken( - whirlpool: Whirlpool, - outputTokenMint: Address, - tokenAmount: BN, - slippageTolerance: Percentage, - programId: Address, - fetcher: WhirlpoolAccountFetcherInterface, - opts?: WhirlpoolAccountFetchOptions -): Promise { - const params = await swapQuoteByToken( - whirlpool, - outputTokenMint, - tokenAmount, - false, - programId, - fetcher, - opts - ); - return swapQuoteWithParams(params, slippageTolerance); -} - -/** - * Perform a sync swap quote based on the basic swap instruction parameters. - * - * @category Quotes - * @param params - SwapQuote parameters - * @param slippageTolerance - The amount of slippage to account for when generating the final quote. - * @returns a SwapQuote object with slippage adjusted SwapInput parameters & estimates on token amounts, fee & end whirlpool states. - */ -export function swapQuoteWithParams( - params: SwapQuoteParam, - slippageTolerance: Percentage -): SwapQuote { - const quote = simulateSwap(params); - - const slippageAdjustedQuote: SwapQuote = { - ...quote, - ...SwapUtils.calculateSwapAmountsFromQuote( - quote.amount, - quote.estimatedAmountIn, - quote.estimatedAmountOut, - slippageTolerance, - quote.amountSpecifiedIsInput - ), - }; - - return slippageAdjustedQuote; -} - -async function swapQuoteByToken( - whirlpool: Whirlpool, - inputTokenMint: Address, - tokenAmount: BN, - amountSpecifiedIsInput: boolean, - programId: Address, - fetcher: WhirlpoolAccountFetcherInterface, - opts?: WhirlpoolAccountFetchOptions -): Promise { - const whirlpoolData = whirlpool.getData(); - const swapMintKey = AddressUtil.toPubKey(inputTokenMint); - const swapTokenType = PoolUtil.getTokenType(whirlpoolData, swapMintKey); - invariant(!!swapTokenType, "swapTokenMint does not match any tokens on this pool"); - - const aToB = - SwapUtils.getSwapDirection(whirlpoolData, swapMintKey, amountSpecifiedIsInput) === - SwapDirection.AtoB; - - const tickArrays = await SwapUtils.getTickArrays( - whirlpoolData.tickCurrentIndex, - whirlpoolData.tickSpacing, - aToB, - AddressUtil.toPubKey(programId), - whirlpool.getAddress(), - fetcher, - opts - ); - - return { - whirlpoolData, - tokenAmount, - aToB, - amountSpecifiedIsInput, - sqrtPriceLimit: SwapUtils.getDefaultSqrtPriceLimit(aToB), - otherAmountThreshold: SwapUtils.getDefaultOtherAmountThreshold(amountSpecifiedIsInput), - tickArrays, - }; -} diff --git a/sdk/src/quotes/public/two-hop-swap-quote.ts b/sdk/src/quotes/public/two-hop-swap-quote.ts deleted file mode 100644 index 40e91b1..0000000 --- a/sdk/src/quotes/public/two-hop-swap-quote.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { TwoHopSwapInput } from "../../instructions"; -import { SwapEstimates, SwapQuote } from "../public/swap-quote"; - -/** - * A collection of estimated values from quoting a swap. - * @category Quotes - * @link {NormalTwoHopSwapQuote} - * @experimental Not yet ready for use - */ -export type TwoHopSwapQuote = NormalTwoHopSwapQuote; // TODO dev swap - -/** - * A collection of estimated values from quoting a two-hop-swap. - * @category Quotes - * @param swapOneEstimates - Estimates for the first leg of the two-hop-swap - * @param swapTwoEstimates - Estimates for the second leg of the two-hop-swap - * @experimental Not yet ready for use - */ -export type NormalTwoHopSwapQuote = { - swapOneEstimates: SwapEstimates; - swapTwoEstimates: SwapEstimates; -} & TwoHopSwapInput; - -/** - * Convert two individual swaps into a quote estimate - * @category Quotes - * @experimental Not yet ready for use - */ -export function twoHopSwapQuoteFromSwapQuotes( - swapQuoteOne: SwapQuote, - swapQuoteTwo: SwapQuote -): TwoHopSwapQuote { - const amountSpecifiedIsInput = swapQuoteOne.amountSpecifiedIsInput; - // If amount specified is input, then we care about input of the first swap - // otherwise we care about output of the second swap - let [amount, otherAmountThreshold] = amountSpecifiedIsInput - ? [swapQuoteOne.amount, swapQuoteTwo.otherAmountThreshold] - : [swapQuoteTwo.amount, swapQuoteOne.otherAmountThreshold]; - - return { - amount, - otherAmountThreshold, - amountSpecifiedIsInput, - aToBOne: swapQuoteOne.aToB, - aToBTwo: swapQuoteTwo.aToB, - sqrtPriceLimitOne: swapQuoteOne.sqrtPriceLimit, - sqrtPriceLimitTwo: swapQuoteTwo.sqrtPriceLimit, - tickArrayOne0: swapQuoteOne.tickArray0, - tickArrayOne1: swapQuoteOne.tickArray1, - tickArrayOne2: swapQuoteOne.tickArray2, - tickArrayTwo0: swapQuoteTwo.tickArray0, - tickArrayTwo1: swapQuoteTwo.tickArray1, - tickArrayTwo2: swapQuoteTwo.tickArray2, - swapOneEstimates: { ...swapQuoteOne }, - swapTwoEstimates: { ...swapQuoteTwo }, - }; -} diff --git a/sdk/src/quotes/swap/swap-manager.ts b/sdk/src/quotes/swap/swap-manager.ts deleted file mode 100644 index 0bf1a71..0000000 --- a/sdk/src/quotes/swap/swap-manager.ts +++ /dev/null @@ -1,168 +0,0 @@ -import { ZERO } from "@orca-so/common-sdk"; -import BN from "bn.js"; -import { PROTOCOL_FEE_RATE_MUL_VALUE, WhirlpoolData } from "../../types/public"; -import { computeSwapStep } from "../../utils/math/swap-math"; -import { PriceMath } from "../../utils/public"; -import { TickArraySequence } from "./tick-array-sequence"; - -export type SwapResult = { - amountA: BN; - amountB: BN; - nextTickIndex: number; - nextSqrtPrice: BN; - totalFeeAmount: BN; -}; - -export function computeSwap( - whirlpoolData: WhirlpoolData, - tickSequence: TickArraySequence, - tokenAmount: BN, - sqrtPriceLimit: BN, - amountSpecifiedIsInput: boolean, - aToB: boolean -): SwapResult { - let amountRemaining = tokenAmount; - let amountCalculated = ZERO; - let currSqrtPrice = whirlpoolData.sqrtPrice; - let currLiquidity = whirlpoolData.liquidity; - let currTickIndex = whirlpoolData.tickCurrentIndex; - let totalFeeAmount = ZERO; - const feeRate = whirlpoolData.feeRate; - const protocolFeeRate = whirlpoolData.protocolFeeRate; - let currProtocolFee = new BN(0); - let currFeeGrowthGlobalInput = aToB - ? whirlpoolData.feeGrowthGlobalA - : whirlpoolData.feeGrowthGlobalB; - - while (amountRemaining.gt(ZERO) && !sqrtPriceLimit.eq(currSqrtPrice)) { - let { nextIndex: nextTickIndex } = tickSequence.findNextInitializedTickIndex(currTickIndex); - - let { nextTickPrice, nextSqrtPriceLimit: targetSqrtPrice } = getNextSqrtPrices( - nextTickIndex, - sqrtPriceLimit, - aToB - ); - - const swapComputation = computeSwapStep( - amountRemaining, - feeRate, - currLiquidity, - currSqrtPrice, - targetSqrtPrice, - amountSpecifiedIsInput, - aToB - ); - - totalFeeAmount = totalFeeAmount.add(swapComputation.feeAmount); - - if (amountSpecifiedIsInput) { - amountRemaining = amountRemaining.sub(swapComputation.amountIn); - amountRemaining = amountRemaining.sub(swapComputation.feeAmount); - amountCalculated = amountCalculated.add(swapComputation.amountOut); - } else { - amountRemaining = amountRemaining.sub(swapComputation.amountOut); - amountCalculated = amountCalculated.add(swapComputation.amountIn); - amountCalculated = amountCalculated.add(swapComputation.feeAmount); - } - - let { nextProtocolFee, nextFeeGrowthGlobalInput } = calculateFees( - swapComputation.feeAmount, - protocolFeeRate, - currLiquidity, - currProtocolFee, - currFeeGrowthGlobalInput - ); - currProtocolFee = nextProtocolFee; - currFeeGrowthGlobalInput = nextFeeGrowthGlobalInput; - - if (swapComputation.nextPrice.eq(nextTickPrice)) { - const nextTick = tickSequence.getTick(nextTickIndex); - if (nextTick.initialized) { - currLiquidity = calculateNextLiquidity(nextTick.liquidityNet, currLiquidity, aToB); - } - currTickIndex = aToB ? nextTickIndex - 1 : nextTickIndex; - } else { - currTickIndex = PriceMath.sqrtPriceX64ToTickIndex(swapComputation.nextPrice); - } - - currSqrtPrice = swapComputation.nextPrice; - } - - let { amountA, amountB } = calculateEstTokens( - tokenAmount, - amountRemaining, - amountCalculated, - aToB, - amountSpecifiedIsInput - ); - - return { - amountA, - amountB, - nextTickIndex: currTickIndex, - nextSqrtPrice: currSqrtPrice, - totalFeeAmount, - }; -} - -function getNextSqrtPrices(nextTick: number, sqrtPriceLimit: BN, aToB: boolean) { - const nextTickPrice = PriceMath.tickIndexToSqrtPriceX64(nextTick); - const nextSqrtPriceLimit = aToB - ? BN.max(sqrtPriceLimit, nextTickPrice) - : BN.min(sqrtPriceLimit, nextTickPrice); - return { nextTickPrice, nextSqrtPriceLimit }; -} - -function calculateFees( - feeAmount: BN, - protocolFeeRate: number, - currLiquidity: BN, - currProtocolFee: BN, - currFeeGrowthGlobalInput: BN -) { - let nextProtocolFee = currProtocolFee; - let nextFeeGrowthGlobalInput = currFeeGrowthGlobalInput; - let globalFee = feeAmount; - - if (protocolFeeRate > 0) { - let delta = calculateProtocolFee(globalFee, protocolFeeRate); - globalFee = globalFee.sub(delta); - nextProtocolFee = nextProtocolFee.add(currProtocolFee); - } - - if (currLiquidity.gt(ZERO)) { - const globalFeeIncrement = globalFee.shln(64).div(currLiquidity); - nextFeeGrowthGlobalInput = nextFeeGrowthGlobalInput.add(globalFeeIncrement); - } - - return { - nextProtocolFee, - nextFeeGrowthGlobalInput, - }; -} - -function calculateProtocolFee(globalFee: BN, protocolFeeRate: number) { - return globalFee.mul(new BN(protocolFeeRate).div(PROTOCOL_FEE_RATE_MUL_VALUE)); -} - -function calculateEstTokens( - amount: BN, - amountRemaining: BN, - amountCalculated: BN, - aToB: boolean, - amountSpecifiedIsInput: boolean -) { - return aToB === amountSpecifiedIsInput - ? { - amountA: amount.sub(amountRemaining), - amountB: amountCalculated, - } - : { - amountA: amountCalculated, - amountB: amount.sub(amountRemaining), - }; -} - -function calculateNextLiquidity(tickNetLiquidity: BN, currLiquidity: BN, aToB: boolean) { - return aToB ? currLiquidity.sub(tickNetLiquidity) : currLiquidity.add(tickNetLiquidity); -} diff --git a/sdk/src/quotes/swap/swap-quote-impl.ts b/sdk/src/quotes/swap/swap-quote-impl.ts deleted file mode 100644 index 4c25f86..0000000 --- a/sdk/src/quotes/swap/swap-quote-impl.ts +++ /dev/null @@ -1,128 +0,0 @@ -import { BN } from "@coral-xyz/anchor"; -import { ZERO } from "@orca-so/common-sdk"; -import { SwapErrorCode, WhirlpoolsError } from "../../errors/errors"; -import { MAX_SQRT_PRICE, MAX_SWAP_TICK_ARRAYS, MIN_SQRT_PRICE } from "../../types/public"; -import { SwapQuote, SwapQuoteParam } from "../public"; -import { computeSwap } from "./swap-manager"; -import { TickArraySequence } from "./tick-array-sequence"; - -/** - * Figure out the quote parameters needed to successfully complete this trade on chain - * @param param - * @returns - * @exceptions - */ -export function simulateSwap(params: SwapQuoteParam): SwapQuote { - const { - aToB, - whirlpoolData, - tickArrays, - tokenAmount, - sqrtPriceLimit, - otherAmountThreshold, - amountSpecifiedIsInput, - } = params; - - if (sqrtPriceLimit.gt(new BN(MAX_SQRT_PRICE)) || sqrtPriceLimit.lt(new BN(MIN_SQRT_PRICE))) { - throw new WhirlpoolsError( - "Provided SqrtPriceLimit is out of bounds.", - SwapErrorCode.SqrtPriceOutOfBounds - ); - } - - if ( - (aToB && sqrtPriceLimit.gt(whirlpoolData.sqrtPrice)) || - (!aToB && sqrtPriceLimit.lt(whirlpoolData.sqrtPrice)) - ) { - throw new WhirlpoolsError( - "Provided SqrtPriceLimit is in the opposite direction of the trade.", - SwapErrorCode.InvalidSqrtPriceLimitDirection - ); - } - - if (tokenAmount.eq(ZERO)) { - throw new WhirlpoolsError("Provided tokenAmount is zero.", SwapErrorCode.ZeroTradableAmount); - } - - const tickSequence = new TickArraySequence(tickArrays, whirlpoolData.tickSpacing, aToB); - - // Ensure 1st search-index resides on the 1st array in the sequence to match smart contract expectation. - if (!tickSequence.isValidTickArray0(whirlpoolData.tickCurrentIndex)) { - throw new WhirlpoolsError( - "TickArray at index 0 does not contain the Whirlpool current tick index.", - SwapErrorCode.TickArraySequenceInvalid - ); - } - - const swapResults = computeSwap( - whirlpoolData, - tickSequence, - tokenAmount, - sqrtPriceLimit, - amountSpecifiedIsInput, - aToB - ); - - if (amountSpecifiedIsInput) { - if ( - (aToB && otherAmountThreshold.gt(swapResults.amountB)) || - (!aToB && otherAmountThreshold.gt(swapResults.amountA)) - ) { - throw new WhirlpoolsError( - "Quoted amount for the other token is below the otherAmountThreshold.", - SwapErrorCode.AmountOutBelowMinimum - ); - } - } else { - if ( - (aToB && otherAmountThreshold.lt(swapResults.amountA)) || - (!aToB && otherAmountThreshold.lt(swapResults.amountB)) - ) { - throw new WhirlpoolsError( - "Quoted amount for the other token is above the otherAmountThreshold.", - SwapErrorCode.AmountInAboveMaximum - ); - } - } - - const { estimatedAmountIn, estimatedAmountOut } = remapAndAdjustTokens( - swapResults.amountA, - swapResults.amountB, - aToB - ); - - const numOfTickCrossings = tickSequence.getNumOfTouchedArrays(); - if (numOfTickCrossings > MAX_SWAP_TICK_ARRAYS) { - throw new WhirlpoolsError( - `Input amount causes the quote to traverse more than the allowable amount of tick-arrays ${numOfTickCrossings}`, - SwapErrorCode.TickArrayCrossingAboveMax - ); - } - - const touchedArrays = tickSequence.getTouchedArrays(MAX_SWAP_TICK_ARRAYS); - - return { - estimatedAmountIn, - estimatedAmountOut, - estimatedEndTickIndex: swapResults.nextTickIndex, - estimatedEndSqrtPrice: swapResults.nextSqrtPrice, - estimatedFeeAmount: swapResults.totalFeeAmount, - amount: tokenAmount, - amountSpecifiedIsInput, - aToB, - otherAmountThreshold, - sqrtPriceLimit, - tickArray0: touchedArrays[0], - tickArray1: touchedArrays[1], - tickArray2: touchedArrays[2], - }; -} - -function remapAndAdjustTokens(amountA: BN, amountB: BN, aToB: boolean) { - const estimatedAmountIn = aToB ? amountA : amountB; - const estimatedAmountOut = aToB ? amountB : amountA; - return { - estimatedAmountIn, - estimatedAmountOut, - }; -} diff --git a/sdk/src/quotes/swap/tick-array-index.ts b/sdk/src/quotes/swap/tick-array-index.ts deleted file mode 100644 index 2c09e6a..0000000 --- a/sdk/src/quotes/swap/tick-array-index.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { TICK_ARRAY_SIZE } from "../../types/public"; - -export class TickArrayIndex { - static fromTickIndex(index: number, tickSpacing: number) { - const arrayIndex = Math.floor(Math.floor(index / tickSpacing) / TICK_ARRAY_SIZE); - let offsetIndex = Math.floor((index % (tickSpacing * TICK_ARRAY_SIZE)) / tickSpacing); - if (offsetIndex < 0) { - offsetIndex = TICK_ARRAY_SIZE + offsetIndex; - } - return new TickArrayIndex(arrayIndex, offsetIndex, tickSpacing); - } - - constructor( - readonly arrayIndex: number, - readonly offsetIndex: number, - readonly tickSpacing: number - ) { - if (offsetIndex >= TICK_ARRAY_SIZE) { - throw new Error("Invalid offsetIndex - value has to be smaller than TICK_ARRAY_SIZE"); - } - if (offsetIndex < 0) { - throw new Error("Invalid offsetIndex - value is smaller than 0"); - } - - if (tickSpacing < 0) { - throw new Error("Invalid tickSpacing - value is less than 0"); - } - } - - toTickIndex() { - return ( - this.arrayIndex * TICK_ARRAY_SIZE * this.tickSpacing + this.offsetIndex * this.tickSpacing - ); - } - - toNextInitializableTickIndex() { - return TickArrayIndex.fromTickIndex(this.toTickIndex() + this.tickSpacing, this.tickSpacing); - } - - toPrevInitializableTickIndex() { - return TickArrayIndex.fromTickIndex(this.toTickIndex() - this.tickSpacing, this.tickSpacing); - } -} diff --git a/sdk/src/quotes/swap/tick-array-sequence.ts b/sdk/src/quotes/swap/tick-array-sequence.ts deleted file mode 100644 index 54a1e92..0000000 --- a/sdk/src/quotes/swap/tick-array-sequence.ts +++ /dev/null @@ -1,176 +0,0 @@ -import { SwapErrorCode, WhirlpoolsError } from "../../errors/errors"; -import { - MAX_TICK_INDEX, - MIN_TICK_INDEX, - TickArray, - TickArrayData, - TickData, - TICK_ARRAY_SIZE, -} from "../../types/public"; -import { TickArrayIndex } from "./tick-array-index"; -import { PublicKey } from "@solana/web3.js"; - -type InitializedTickArray = TickArray & { - // override - data: TickArrayData; -}; - -/** - * NOTE: differs from contract method of having the swap manager keep track of array index. - * This is due to the initial requirement to lazy load tick-arrays. This requirement is no longer necessary. - */ -export class TickArraySequence { - private sequence: InitializedTickArray[]; - private touchedArrays: boolean[]; - private startArrayIndex: number; - - constructor( - tickArrays: Readonly, - readonly tickSpacing: number, - readonly aToB: boolean - ) { - if (!tickArrays[0] || !tickArrays[0].data) { - throw new Error("TickArray index 0 must be initialized"); - } - - // If an uninitialized TickArray appears, truncate all TickArrays after it (inclusive). - this.sequence = []; - for (const tickArray of tickArrays) { - if (!tickArray || !tickArray.data) { - break; - } - this.sequence.push({ - address: tickArray.address, - data: tickArray.data, - }); - } - - this.touchedArrays = [...Array(this.sequence.length).fill(false)]; - this.startArrayIndex = TickArrayIndex.fromTickIndex( - this.sequence[0].data.startTickIndex, - this.tickSpacing - ).arrayIndex; - } - - isValidTickArray0(tickCurrentIndex: number) { - const shift = this.aToB ? 0 : this.tickSpacing; - const tickArray = this.sequence[0].data; - return this.checkIfIndexIsInTickArrayRange(tickArray.startTickIndex, tickCurrentIndex + shift); - } - - getNumOfTouchedArrays() { - return this.touchedArrays.filter((val) => !!val).length; - } - - getTouchedArrays(minArraySize: number): PublicKey[] { - let result = this.touchedArrays.reduce((prev, curr, index) => { - if (curr) { - prev.push(this.sequence[index].address); - } - return prev; - }, []); - - // Edge case: nothing was ever touched. - if (result.length === 0) { - return []; - } - - // The quote object should contain the specified amount of tick arrays to be plugged - // directly into the swap instruction. - // If the result does not fit minArraySize, pad the rest with the last touched array - const sizeDiff = minArraySize - result.length; - if (sizeDiff > 0) { - result = result.concat(Array(sizeDiff).fill(result[result.length - 1])); - } - - return result; - } - - getTick(index: number): TickData { - const targetTaIndex = TickArrayIndex.fromTickIndex(index, this.tickSpacing); - - if (!this.isArrayIndexInBounds(targetTaIndex, this.aToB)) { - throw new Error("Provided tick index is out of bounds for this sequence."); - } - - const localArrayIndex = this.getLocalArrayIndex(targetTaIndex.arrayIndex, this.aToB); - const tickArray = this.sequence[localArrayIndex].data; - - this.touchedArrays[localArrayIndex] = true; - - if (!tickArray) { - throw new WhirlpoolsError( - `TickArray at index ${localArrayIndex} is not initialized.`, - SwapErrorCode.TickArrayIndexNotInitialized - ); - } - - if (!this.checkIfIndexIsInTickArrayRange(tickArray.startTickIndex, index)) { - throw new WhirlpoolsError( - `TickArray at index ${localArrayIndex} is unexpected for this sequence.`, - SwapErrorCode.TickArraySequenceInvalid - ); - } - - return tickArray.ticks[targetTaIndex.offsetIndex]; - } - /** - * if a->b, currIndex is included in the search - * if b->a, currIndex is always ignored - * @param currIndex - * @returns - */ - findNextInitializedTickIndex(currIndex: number) { - const searchIndex = this.aToB ? currIndex : currIndex + this.tickSpacing; - let currTaIndex = TickArrayIndex.fromTickIndex(searchIndex, this.tickSpacing); - - // Throw error if the search attempted to search for an index out of bounds - if (!this.isArrayIndexInBounds(currTaIndex, this.aToB)) { - throw new WhirlpoolsError( - `Swap input value traversed too many arrays. Out of bounds at attempt to traverse tick index - ${currTaIndex.toTickIndex()}.`, - SwapErrorCode.TickArraySequenceInvalid - ); - } - - while (this.isArrayIndexInBounds(currTaIndex, this.aToB)) { - const currTickData = this.getTick(currTaIndex.toTickIndex()); - if (currTickData.initialized) { - return { nextIndex: currTaIndex.toTickIndex(), nextTickData: currTickData }; - } - currTaIndex = this.aToB - ? currTaIndex.toPrevInitializableTickIndex() - : currTaIndex.toNextInitializableTickIndex(); - } - - const lastIndexInArray = Math.max( - Math.min( - this.aToB ? currTaIndex.toTickIndex() + this.tickSpacing : currTaIndex.toTickIndex() - 1, - MAX_TICK_INDEX - ), - MIN_TICK_INDEX - ); - - return { nextIndex: lastIndexInArray, nextTickData: null }; - } - - private getLocalArrayIndex(arrayIndex: number, aToB: boolean) { - return aToB ? this.startArrayIndex - arrayIndex : arrayIndex - this.startArrayIndex; - } - - /** - * Check whether the array index potentially exists in this sequence. - * Note: assumes the sequence of tick-arrays are sequential - * @param index - */ - private isArrayIndexInBounds(index: TickArrayIndex, aToB: boolean) { - // a+0...a+n-1 array index is ok - const localArrayIndex = this.getLocalArrayIndex(index.arrayIndex, aToB); - const seqLength = this.sequence.length; - return localArrayIndex >= 0 && localArrayIndex < seqLength; - } - - private checkIfIndexIsInTickArrayRange(startTick: number, tickIndex: number) { - const upperBound = startTick + this.tickSpacing * TICK_ARRAY_SIZE; - return tickIndex >= startTick && tickIndex < upperBound; - } -} diff --git a/sdk/src/router/batch-swap-quote.ts b/sdk/src/router/batch-swap-quote.ts deleted file mode 100644 index 6dc86d7..0000000 --- a/sdk/src/router/batch-swap-quote.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { Address } from "@coral-xyz/anchor"; -import { AddressUtil } from "@orca-so/common-sdk"; -import BN from "bn.js"; -import invariant from "tiny-invariant"; -import { - WhirlpoolAccountFetcherInterface, - WhirlpoolAccountFetchOptions, -} from "../network/public/fetcher"; -import { SwapQuoteParam } from "../quotes/public"; -import { PoolUtil, SwapDirection, SwapUtils } from "../utils/public"; - -export interface SwapQuoteRequest { - whirlpool: Address; - tradeTokenMint: Address; - tokenAmount: BN; - amountSpecifiedIsInput: boolean; -} - -export async function batchBuildSwapQuoteParams( - quoteRequests: SwapQuoteRequest[], - programId: Address, - fetcher: WhirlpoolAccountFetcherInterface, - opts?: WhirlpoolAccountFetchOptions -): Promise { - const whirlpools = await fetcher.getPools( - quoteRequests.map((req) => req.whirlpool), - opts - ); - const program = AddressUtil.toPubKey(programId); - - const tickArrayRequests = quoteRequests.map((quoteReq) => { - const { whirlpool, tokenAmount, tradeTokenMint, amountSpecifiedIsInput } = quoteReq; - const whirlpoolData = whirlpools.get(AddressUtil.toString(whirlpool))!; - const swapMintKey = AddressUtil.toPubKey(tradeTokenMint); - const swapTokenType = PoolUtil.getTokenType(whirlpoolData, swapMintKey); - invariant(!!swapTokenType, "swapTokenMint does not match any tokens on this pool"); - const aToB = - SwapUtils.getSwapDirection(whirlpoolData, swapMintKey, amountSpecifiedIsInput) === - SwapDirection.AtoB; - return { - whirlpoolData, - tokenAmount, - aToB, - tickCurrentIndex: whirlpoolData.tickCurrentIndex, - tickSpacing: whirlpoolData.tickSpacing, - whirlpoolAddress: AddressUtil.toPubKey(whirlpool), - amountSpecifiedIsInput, - }; - }); - - const tickArrays = await SwapUtils.getBatchTickArrays(program, fetcher, tickArrayRequests, opts); - - return tickArrayRequests.map((req, index) => { - const { whirlpoolData, tokenAmount, aToB, amountSpecifiedIsInput } = req; - return { - whirlpoolData, - tokenAmount, - aToB, - amountSpecifiedIsInput, - sqrtPriceLimit: SwapUtils.getDefaultSqrtPriceLimit(aToB), - otherAmountThreshold: SwapUtils.getDefaultOtherAmountThreshold(amountSpecifiedIsInput), - tickArrays: tickArrays[index], - }; - }); -} diff --git a/sdk/src/router/convert-quote-map.ts b/sdk/src/router/convert-quote-map.ts deleted file mode 100644 index 805e4cf..0000000 --- a/sdk/src/router/convert-quote-map.ts +++ /dev/null @@ -1,177 +0,0 @@ -import BN from "bn.js"; -import { kSmallestPartition } from "../utils/math/k-smallest-partition"; -import { RoutingOptions, SubTradeRoute, TradeRoute } from "./public"; -import { PathQuote, SanitizedQuoteMap } from "./quote-map"; - -export function getBestRoutesFromQuoteMap( - quoteMap: SanitizedQuoteMap, - amountSpecifiedIsInput: boolean, - opts: RoutingOptions -): TradeRoute[] { - const { numTopRoutes, maxSplits } = opts; - const sortedRoutes = [ - ...getRankedRoutes(quoteMap, amountSpecifiedIsInput, numTopRoutes, maxSplits), - ...getSingleHopSplit(quoteMap), - ].sort(getRouteCompareFn(amountSpecifiedIsInput)); - - return convertInternalRoutesToTradeRoutes(sortedRoutes); -} - -function convertInternalRoutesToTradeRoutes(internalRoutes: InternalRoute[]): TradeRoute[] { - const tradeRoutes: TradeRoute[] = internalRoutes.map((internalRoute) => { - const { quotes, totalIn, totalOut } = internalRoute; - return { - subRoutes: quotes.map((quote) => convertPathQuoteToSubTradeRoute(quote)), - totalAmountIn: totalIn, - totalAmountOut: totalOut, - }; - }); - return tradeRoutes; -} - -function convertPathQuoteToSubTradeRoute(pathQuote: PathQuote): SubTradeRoute { - const { calculatedEdgeQuotes, path, splitPercent, amountIn, amountOut } = pathQuote; - return { - path, - splitPercent, - amountIn, - amountOut, - hopQuotes: calculatedEdgeQuotes, - }; -} - -type InternalRoute = { - quotes: PathQuote[]; - splitPercent: number; - totalIn: BN; - totalOut: BN; -}; - -function getSingleHopSplit(quoteMap: SanitizedQuoteMap): InternalRoute[] { - const fullFlow = quoteMap[100]; - if (fullFlow) { - return fullFlow - .filter((f) => f.calculatedEdgeQuotes.length == 1) - .map((f) => { - const oneHop = f.calculatedEdgeQuotes[0]; - return { - quotes: [f], - splitPercent: 100, - totalIn: oneHop.amountIn, - totalOut: oneHop.amountOut, - }; - }) - .flatMap((g) => (!!g ? g : [])); - } - return []; -} - -function getRankedRoutes( - percentMap: SanitizedQuoteMap, - amountSpecifiedIsInput: boolean, - topN: number, - maxSplits: number -): InternalRoute[] { - let routes = generateRoutes(percentMap, maxSplits); - - // Run quick select algorithm to partition the topN results, mutating inplace - const routeCompare = getRouteCompareFn(amountSpecifiedIsInput); - - if (routes.length <= topN) { - return routes.sort(routeCompare); - } - - kSmallestPartition(routes, topN, 0, routes.length - 1, routeCompare); - return routes.slice(0, topN).sort(routeCompare); -} - -function generateRoutes(percentMap: SanitizedQuoteMap, maxSplits: number): InternalRoute[] { - let routes: InternalRoute[] = []; - buildRoutes( - percentMap, - maxSplits, - { - quotes: [], - splitPercent: 0, - totalIn: new BN(0), - totalOut: new BN(0), - }, - routes - ); - return routes; -} - -function buildRoutes( - quotePercentMap: SanitizedQuoteMap, - maxSplits: number, - currentRoute: InternalRoute, - routes: InternalRoute[] -) { - const { splitPercent: percent, quotes } = currentRoute; - const percents = Object.keys(quotePercentMap).map((percent) => Number(percent)); - for (let i = percents.length - 1; i >= 0; i--) { - const nextPercent = percents[i]; - const newPercentTotal = percent + nextPercent; - - // Optimization to prevent exceeding 100% flow and excess combinations of flow by only using decreasing - // amounts of flow percentages - const nextPercentIsSmaller = - quotes.length > 0 && nextPercent > quotes[quotes.length - 1].splitPercent; - if (newPercentTotal > 100 || nextPercentIsSmaller) { - continue; - } - - const nextPercentQuotes = quotePercentMap[nextPercent]; - for (let j = 0; j < nextPercentQuotes.length; j++) { - const nextQuote = nextPercentQuotes[j]; - - // Don't use a quote that shares a pool with an existing quote - const hasReusedPools = nextQuote.edgesPoolAddrs.some((r1) => - quotes.some((r2) => r2.edgesPoolAddrs.some((r3) => r3.indexOf(r1) !== -1)) - ); - if (hasReusedPools) { - continue; - } - - // todo: Doesn't take into transaction fees - // double-hops, multi-route penalties, benefits for pairs that can share lookup tables - const nextRoute: InternalRoute = { - quotes: [...quotes, nextQuote], - splitPercent: newPercentTotal, - totalIn: currentRoute.totalIn.add(nextQuote.amountIn), - totalOut: currentRoute.totalOut.add(nextQuote.amountOut), - }; - - // Remove the current and prior routes from consideration - const nextCandidateQuotes = nextPercentQuotes.slice(j + 1); - - if (newPercentTotal === 100) { - // If we have reached 100% flow routed, we add it to the set of valid route sets - routes.push(nextRoute); - } else if (quotes.length + 1 != maxSplits) { - // Otherwise, recursively build route sets - buildRoutes( - { - ...quotePercentMap, - [nextPercent]: nextCandidateQuotes, - }, - maxSplits, - nextRoute, - routes - ); - } - } - } -} - -function getRouteCompareFn(amountSpecifiedIsInput: boolean) { - return amountSpecifiedIsInput ? routesCompareForInputAmount : routesCompareForOutputAmount; -} - -function routesCompareForInputAmount(a: InternalRoute, b: InternalRoute) { - return b.totalOut.cmp(a.totalOut); -} - -function routesCompareForOutputAmount(a: InternalRoute, b: InternalRoute) { - return a.totalIn.cmp(b.totalIn); -} diff --git a/sdk/src/router/public/index.ts b/sdk/src/router/public/index.ts deleted file mode 100644 index 24ac33f..0000000 --- a/sdk/src/router/public/index.ts +++ /dev/null @@ -1,199 +0,0 @@ -import { Address } from "@coral-xyz/anchor"; -import { Percentage, TransactionBuilder } from "@orca-so/common-sdk"; -import { AddressLookupTableAccount } from "@solana/web3.js"; -import BN from "bn.js"; -import { WhirlpoolAccountFetchOptions } from "../../network/public/fetcher"; -import { SwapQuote } from "../../quotes/public"; -import { Path } from "../../utils/public"; -import { AtaAccountInfo, RouteSelectOptions } from "./router-utils"; - -export * from "./router-builder"; -export * from "./router-utils"; - -/** - * A Trade type that represents a trade between two tokens - * - * @category Router - * @param tokenIn The token that is being traded in - * @param tokenOut The token that is being traded out - * @param tradeAmount The amount of token being traded in or out - * @param amountSpecifiedIsInput Whether the trade amount is the amount being traded in or out - */ -export type Trade = { - tokenIn: Address; - tokenOut: Address; - tradeAmount: BN; - amountSpecifiedIsInput: boolean; -}; - -/** - * Options to configure the router. - * - * @category Router - * @param percentIncrement The percent increment to use when splitting a trade into multiple trades. - * @param numTopRoutes The number of top routes to return from the router. - * @param numTopPartialQuotes The number of top partial quotes to return from the router. - * @param maxSplits The maximum number of splits to perform on a trade. - */ -export type RoutingOptions = { - percentIncrement: number; - numTopRoutes: number; - numTopPartialQuotes: number; - maxSplits: number; -}; - -/** - * A trade route that is ready to execute. - * A trade can be broken into multiple sub-trades for potentially better trades. - * - * @category Router - * @param subRoutes - * The sub-routes that make up the trade route. The sum of all splitPercent should equal 100. - * @param totalAmountIn The total amount of token being traded in for this trade. - * @param totalAmountOut The total amount of token being traded out for this trade. - */ -export type TradeRoute = { - subRoutes: SubTradeRoute[]; - totalAmountIn: BN; - totalAmountOut: BN; -}; - -/** - * Represents a fragment of a trade that was splitted into multiple trades for more efficient execution. - * - * @category Router - * @param path The path of pool addresses that make up this sub trade. - * @param splitPercent The percent of the trade that this sub trade represents. - * @param amountIn The amount of token being traded in within this sub-route. - * @param amountOut The amount of token being traded out within this sub-routes. - * @param hopQuotes The quotes for each hop in the path of this trade. - */ -export type SubTradeRoute = { - path: Path; - splitPercent: number; - amountIn: BN; - amountOut: BN; - hopQuotes: TradeHop[]; -}; - -/** - * Represents a quote for a single hop in the path of a {@link SubTradeRoute}. - * - * @category Router - * @param amountIn The amount of token being traded in for this hop. - * @param amountOut The amount of token being traded out for this hop. - * @param whirlpool The address of the whirlpool that this hop is trading through. - * @param inputMint The address of the input token mint. - * @param outputMint The address of the output token mint. - * @param mintA The address of the first mint in the pool. - * @param mintB The address of the second mint in the pool. - * @param vaultA The address of the first vault in the pool. - * @param vaultB The address of the second vault in the pool. - * @param quote The {@link SwapQuote} for this hop. - * @param snapshot A snapshot of the whirlpool condition when this hop was made - */ -export type TradeHop = { - amountIn: BN; - amountOut: BN; - whirlpool: Address; - inputMint: Address; - outputMint: Address; - mintA: Address; - mintB: Address; - vaultA: Address; - vaultB: Address; - quote: SwapQuote; - snapshot: TradeHopSnapshot; -}; - -/** - * A snapshot of the whirlpool condition when a trade hop was made. - * @category Router - */ -export type TradeHopSnapshot = { - aToB: boolean; - sqrtPrice: BN; - feeRate: Percentage; -}; - -/** - * A trade route that is ready to execute. - * Contains the {@link TradeRoute} and a possible set of {@link AddressLookupTableAccount} that - * is needed to successfully execute the trade. - * - * If the lookup table accounts are undefined, then the trade can be executed with a legacy transaction. - * - * @category Router - */ -export type ExecutableRoute = readonly [TradeRoute, AddressLookupTableAccount[] | undefined]; - -/** - * Convienience class to find routes through a set of Whirlpools and execute a swap across them. - * The router only supports up to 2-hop trades between pools and does not support arbitrage trades - * between the same token. - * - * @category Router - */ -export interface WhirlpoolRouter { - /** - * Finds all possible routes for a trade, ordered by the best other token amount you would get from a trade. - * Use {@link RouterUtils.selectFirstExecutableRoute} to find the best executable route. - * - * @param trade - * The trade to find routes for. - * @param opts an {@link WhirlpoolAccountFetchOptions} object to define fetch and cache options when accessing on-chain accounts - * @param opts - * {@link RoutingOptions} to configure the router. Missing options will be filled with default values from - * {@link RouterUtils.getDefaultRoutingOptions}. - * @param fetchOpts - * {@link WhirlpoolAccountFetchOptions} to configure the fetching of on-chain data. - * @return A list of {@link TradeRoute} that can be used to execute a swap, ordered by the best other token amount. - */ - findAllRoutes( - trade: Trade, - opts?: Partial, - fetchOpts?: WhirlpoolAccountFetchOptions - ): Promise; - - /** - * Finds all possible routes for a trade and select the best route that is executable - * under the current execution environment. - * @param trade - * The trade to find routes for. - * @param opts an {@link WhirlpoolAccountFetchOptions} object to define fetch and cache options when accessing on-chain accounts - * @param opts - * {@link RoutingOptions} to configure the router. Missing options will be filled with default values from - * {@link RouterUtils.getDefaultRoutingOptions}. - * @param selectionOpts - * {@link RouteSelectOptions} to configure the selection of the best route. Missing options - * will be filled with default values from {@link RouterUtils.getDefaultRouteSelectOptions}. - * @param fetchOpts - * {@link WhirlpoolAccountFetchOptions} to configure the fetching of on-chain data. - * @returns - * The best {@link ExecutableRoute} that can be used to execute a swap. If no executable route is found, null is returned. - */ - findBestRoute( - trade: Trade, - opts?: Partial, - selectionOpts?: Partial, - fetchOpts?: WhirlpoolAccountFetchOptions - ): Promise; - - /** - * Construct a {@link TransactionBuilder} to help execute a trade route. - * @param trade The trade route to execute. - * @param slippage The slippage tolerance for the trade. - * @param resolvedAtas - * The ATA accounts that the executing wallet owns / needed by the execution. - * If not provided, the router will attempt to resolve them. - * @returns - * A {@link TransactionBuilder}that can be used to execute the trade. - * If provvided from {@link ExecutableRoute}, plug the {@link AddressLookupTableAccount}s - * into builder to lower the transaction size. - */ - swap( - trade: TradeRoute, - slippage: Percentage, - resolvedAtas: AtaAccountInfo[] | null - ): Promise; -} diff --git a/sdk/src/router/public/router-builder.ts b/sdk/src/router/public/router-builder.ts deleted file mode 100644 index 74796a4..0000000 --- a/sdk/src/router/public/router-builder.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { Address } from "@coral-xyz/anchor"; -import { WhirlpoolRouter } from "."; -import { WhirlpoolContext } from "../.."; -import { PoolGraph, PoolGraphBuilder } from "../../utils/public"; -import { WhirlpoolRouterImpl } from "../router-impl"; - -/** - * Builder to build instances of the {@link WhirlpoolRouter} - * @category Router - */ -export class WhirlpoolRouterBuilder { - /** - * Builds a {@link WhirlpoolRouter} with a prebuilt {@link PoolGraph} - * - * @param ctx A {@link WhirlpoolContext} for the current execution environment - * @param graph A {@link PoolGraph} that represents the connections between all pools. - * @returns A {@link WhirlpoolRouter} that can be used to find routes and execute swaps - */ - static buildWithPoolGraph(ctx: WhirlpoolContext, graph: PoolGraph): WhirlpoolRouter { - return new WhirlpoolRouterImpl(ctx, graph); - } - - /** - * Fetch and builds a {@link WhirlpoolRouter} with a list of pool addresses. - * @param ctx A {@link WhirlpoolContext} for the current execution environment - * @param pools A list of {@link Address}es that the router will find routes through. - * @returns A {@link WhirlpoolRouter} that can be used to find routes and execute swaps - */ - static async buildWithPools(ctx: WhirlpoolContext, pools: Address[]): Promise { - const poolGraph = await PoolGraphBuilder.buildPoolGraphWithFetch(pools, ctx.fetcher); - return new WhirlpoolRouterImpl(ctx, poolGraph); - } -} diff --git a/sdk/src/router/public/router-utils.ts b/sdk/src/router/public/router-utils.ts deleted file mode 100644 index 2367523..0000000 --- a/sdk/src/router/public/router-utils.ts +++ /dev/null @@ -1,268 +0,0 @@ -import { - AddressUtil, - LookupTableFetcher, - MEASUREMENT_BLOCKHASH, - Percentage, - TransactionBuilder, - TX_SIZE_LIMIT, -} from "@orca-so/common-sdk"; -import { Account } from "@solana/spl-token"; -import { PublicKey } from "@solana/web3.js"; -import BN from "bn.js"; -import Decimal from "decimal.js"; -import { ExecutableRoute, RoutingOptions, Trade, TradeRoute } from "."; -import { WhirlpoolContext } from "../../context"; -import { getSwapFromRoute } from "../../instructions/composites/swap-with-route"; -import { PREFER_CACHE } from "../../network/public/fetcher"; -import { U64 } from "../../utils/math/constants"; -import { PriceMath } from "../../utils/public"; -import { isWalletConnected } from "../../utils/wallet-utils"; - -/** - * A type representing a Associated Token Account - * @param address The address of the ATA account. - * @param owner The owner address of the ATA. - * @param mint The mint of the token the ATA represents. - */ -export type AtaAccountInfo = Pick; - -/** - * Parameters to configure the selection of the best route. - * @category Router - * @param maxSupportedTransactionVersion The maximum transaction version that the wallet supports. - * @param maxTransactionSize The maximum transaction size that the wallet supports. - * @param availableAtaAccounts A list of ATA accounts that are available in this wallet to use for the swap. - * @param onRouteEvaluation - * A callback that is called right before a route is evaluated. Users have a chance to add additional instructions - * to be added for an accurate txn size measurement. (ex. Adding a priority fee ix to the transaction) - * - */ -export type RouteSelectOptions = { - maxSupportedTransactionVersion: "legacy" | number; - maxTransactionSize: number; - availableAtaAccounts?: AtaAccountInfo[]; - onRouteEvaluation?: (route: Readonly, tx: TransactionBuilder) => void; -}; - -/** - * A selection of utility functions for the {@link WhirlpoolRouter}. - * @category Router - */ -export class RouterUtils { - /** - * Selects the best executable route from a list of routes using the current execution environment. - * The wallet support type, available ATA accounts, existance of lookup tables all effect the transaction size - * and eligibility of a route. - * - * @param ctx The {@link WhirlpoolContext} that represents the current execution environment - * @param orderedRoutes A list of routes to select from, ordered by the best routes (trade amount wise) first. - * @param opts {@link RouteSelectOptions} to configure the selection of the best route. - * @returns - * The best {@link ExecutableRoute} that can be used to execute a swap. If no executable route is found, null is returned. - */ - static async selectFirstExecutableRoute( - ctx: WhirlpoolContext, - orderedRoutes: TradeRoute[], - opts: RouteSelectOptions - ): Promise { - const { wallet } = ctx; - - if (orderedRoutes.length === 0) { - return null; - } - - // Don't measure if there is no wallet - if (!isWalletConnected(wallet)) { - return [orderedRoutes[0], undefined]; - } - - // Preload LookupTableFetcher with lookup tables that are needed for v0 transactions - if (opts.maxSupportedTransactionVersion !== "legacy" && ctx.lookupTableFetcher) { - await loadLookupTablesForRoutes(ctx.lookupTableFetcher, orderedRoutes); - } - - for (let i = 0; i < orderedRoutes.length && i < MEASURE_ROUTE_MAX; i++) { - const route = orderedRoutes[i]; - - const tx = await getSwapFromRoute( - ctx, - { - route, - slippage: Percentage.fromFraction(0, 100), - resolvedAtaAccounts: opts.availableAtaAccounts ?? null, - wallet: wallet.publicKey, - }, - PREFER_CACHE - ); - - if (!!opts.onRouteEvaluation) { - opts.onRouteEvaluation(route, tx); - } - - try { - const legacyTxSize = tx.txnSize({ - latestBlockhash: MEASUREMENT_BLOCKHASH, - maxSupportedTransactionVersion: "legacy", - }); - if (legacyTxSize !== undefined && legacyTxSize <= opts.maxTransactionSize) { - return [route, undefined]; - } - } catch (e) { - // No-op - } - - let v0TxSize; - if (opts.maxSupportedTransactionVersion !== "legacy" && ctx.lookupTableFetcher) { - const addressesToLookup = RouterUtils.getTouchedTickArraysFromRoute(route); - if (addressesToLookup.length > MAX_LOOKUP_TABLE_FETCH_SIZE) { - continue; - } - - const lookupTableAccounts = await ctx.lookupTableFetcher.getLookupTableAccountsForAddresses( - addressesToLookup - ); - try { - v0TxSize = tx.txnSize({ - latestBlockhash: MEASUREMENT_BLOCKHASH, - maxSupportedTransactionVersion: opts.maxSupportedTransactionVersion, - lookupTableAccounts, - }); - - if (v0TxSize !== undefined && v0TxSize <= opts.maxTransactionSize) { - return [route, lookupTableAccounts]; - } - } catch (e) { - // No-op - } - } - } - - return null; - } - - /** - * Calculate the price impact for a route. - * @param trade The trade the user used to derive the route. - * @param route The route to calculate the price impact for. - * @returns A Decimal object representing the percentage value of the price impact (ex. 3.01%) - */ - static getPriceImpactForRoute(trade: Trade, route: TradeRoute): Decimal { - const { amountSpecifiedIsInput } = trade; - - const totalBaseValue = route.subRoutes.reduce((acc, route) => { - const directionalHops = amountSpecifiedIsInput - ? route.hopQuotes - : route.hopQuotes.slice().reverse(); - const baseOutputs = directionalHops.reduce((acc, quote, index) => { - const { snapshot } = quote; - const { aToB, sqrtPrice, feeRate } = snapshot; - // Inverse sqrt price will cause 1bps precision loss since ticks are spaces of 1bps - const directionalSqrtPrice = aToB ? sqrtPrice : PriceMath.invertSqrtPriceX64(sqrtPrice); - - // Convert from in/out -> base_out/in using the directional price & fee rate - let nextBaseValue; - const price = directionalSqrtPrice.mul(directionalSqrtPrice).div(U64); - if (amountSpecifiedIsInput) { - const amountIn = index === 0 ? quote.amountIn : acc[index - 1]; - const feeAdjustedAmount = amountIn - .mul(feeRate.denominator.sub(feeRate.numerator)) - .div(feeRate.denominator); - nextBaseValue = price.mul(feeAdjustedAmount).div(U64); - } else { - const amountOut = index === 0 ? quote.amountOut : acc[index - 1]; - const feeAdjustedAmount = amountOut.mul(U64).div(price); - nextBaseValue = feeAdjustedAmount - .mul(feeRate.denominator) - .div(feeRate.denominator.sub(feeRate.numerator)); - } - - acc.push(nextBaseValue); - return acc; - }, new Array()); - - return acc.add(baseOutputs[baseOutputs.length - 1]); - }, new BN(0)); - - const totalBaseValueDec = new Decimal(totalBaseValue.toString()); - const totalAmountEstimatedDec = new Decimal( - amountSpecifiedIsInput ? route.totalAmountOut.toString() : route.totalAmountIn.toString() - ); - const priceImpact = amountSpecifiedIsInput - ? totalBaseValueDec.sub(totalAmountEstimatedDec).div(totalBaseValueDec) - : totalAmountEstimatedDec.sub(totalBaseValueDec).div(totalAmountEstimatedDec); - - return priceImpact.mul(100); - } - - /** - * Get the tick arrays addresses that are touched by a route. - * @param route The route to get the tick arrays from. - * @returns The tick arrays addresses that are touched by the route. - */ - static getTouchedTickArraysFromRoute(route: TradeRoute): PublicKey[] { - const taAddresses = new Set(); - for (const quote of route.subRoutes) { - for (const hop of quote.hopQuotes) { - // We only need to search for tick arrays, since we should be guaranteed due to the layout - // that all other addresses are included in the LUTs for the tick array - taAddresses.add(hop.quote.tickArray0.toBase58()); - taAddresses.add(hop.quote.tickArray1.toBase58()); - taAddresses.add(hop.quote.tickArray2.toBase58()); - } - } - return AddressUtil.toPubKeys(Array.from(taAddresses)); - } - - /** - * Get the default options for generating trade routes. - * @returns Default options for generating trade routes. - */ - static getDefaultRouteOptions(): RoutingOptions { - return { - percentIncrement: 20, - numTopRoutes: 50, - numTopPartialQuotes: 10, - maxSplits: 3, - }; - } - - /** - * Get the default options for selecting a route from a list of generated routes. - * @returns Default options for selecting a a route from a list of generated routes. - */ - static getDefaultSelectOptions(): RouteSelectOptions { - return { - maxSupportedTransactionVersion: 0, - maxTransactionSize: TX_SIZE_LIMIT, - }; - } -} - -async function loadLookupTablesForRoutes( - lookupTableFetcher: LookupTableFetcher, - routes: TradeRoute[] -) { - const altTicks = new Set(); - for (let i = 0; i < routes.length && i < MEASURE_ROUTE_MAX; i++) { - const route = routes[i]; - RouterUtils.getTouchedTickArraysFromRoute(route).map((ta) => altTicks.add(ta.toBase58())); - } - const altTickArray = Array.from(altTicks); - const altPageSize = 45; - const altRequests = []; - for (let i = 0; i < altTickArray.length; i += altPageSize) { - altRequests.push(altTickArray.slice(i, i + altPageSize)); - } - await Promise.all( - altRequests.map((altPage) => { - const altPageKeys = AddressUtil.toPubKeys(altPage); - lookupTableFetcher.loadLookupTables(altPageKeys); - }) - ); -} - -// The maximum number of routes to measure -const MEASURE_ROUTE_MAX = 100; - -// The maximum number of tick arrays to lookup per network request -const MAX_LOOKUP_TABLE_FETCH_SIZE = 50; diff --git a/sdk/src/router/quote-map.ts b/sdk/src/router/quote-map.ts deleted file mode 100644 index 83e797c..0000000 --- a/sdk/src/router/quote-map.ts +++ /dev/null @@ -1,316 +0,0 @@ -import { Address } from "@coral-xyz/anchor"; -import { AddressUtil, Percentage } from "@orca-so/common-sdk"; -import { PublicKey } from "@solana/web3.js"; -import BN from "bn.js"; -import { SwapErrorCode } from "../errors/errors"; -import { PREFER_CACHE, WhirlpoolAccountFetcherInterface } from "../network/public/fetcher"; -import { SwapQuoteParam, swapQuoteWithParams } from "../quotes/public"; -import { Path, PoolUtil } from "../utils/public"; -import { SwapQuoteRequest, batchBuildSwapQuoteParams } from "./batch-swap-quote"; -import { RoutingOptions, Trade, TradeHop } from "./public"; - -// Key between -export type SanitizedQuoteMap = Record; - -// A trade quote on trading on a path between user input tokenIn -> tokenOut -export type PathQuote = { - path: Path; - edgesPoolAddrs: string[]; - splitPercent: number; - amountIn: BN; - amountOut: BN; - calculatedEdgeQuotes: TradeHopQuoteSuccess[]; -}; - -export async function getQuoteMap( - trade: Trade, - paths: Path[], - amountSpecifiedIsInput: boolean, - programId: PublicKey, - fetcher: WhirlpoolAccountFetcherInterface, - opts: RoutingOptions -) { - const { percentIncrement, numTopPartialQuotes } = opts; - const { tokenIn, tokenOut, tradeAmount } = trade; - - const { percents, amounts } = getSplitPercentageAmts(tradeAmount, percentIncrement); - // The max route length is the number of iterations of quoting that we need to do - const maxRouteLength = Math.max(...paths.map((path) => path.edges.length), 0); - - // For hop 0 of all routes, get swap quotes using [inputAmount, inputTokenMint] - // For hop 1..n of all routes, get swap quotes using [outputAmount, outputTokenMint] of hop n-1 as input - const quoteMap: InternalQuoteMap = {}; - let iteration = Array.from(Array(maxRouteLength).keys()); - if (!amountSpecifiedIsInput) { - iteration = iteration.reverse(); - } - - try { - for (const hop of iteration) { - // Each batch of quotes needs to be iterative - const quoteUpdates = buildQuoteUpdateRequests( - tokenIn, - tokenOut, - paths, - percents, - amounts, - hop, - amountSpecifiedIsInput, - quoteMap - ); - - const quoteParams = await batchBuildSwapQuoteParams( - quoteUpdates.map((update) => update.request), - AddressUtil.toPubKey(programId), - fetcher, - PREFER_CACHE - ); - - populateQuoteMap(quoteUpdates, quoteParams, quoteMap); - } - } catch (e) { - throw e; - } - - return sanitizeQuoteMap(quoteMap, numTopPartialQuotes, amountSpecifiedIsInput); -} - -// Key between -type InternalQuoteMap = Record< - number, - Array< - Pick - > ->; - -type InternalPathQuote = Omit & { - calculatedEdgeQuotes: (TradeHopQuoteResult | undefined)[]; -}; - -type TradeHopQuoteResult = TradeHopQuoteSuccess | TradeHopQuoteError; -type TradeHopQuoteSuccess = TradeHop & { success: true }; -type TradeHopQuoteError = { - success: false; - error: SwapErrorCode; -}; - -function populateQuoteMap( - quoteUpdates: ReturnType, - quoteParams: SwapQuoteParam[], - quoteMap: InternalQuoteMap -) { - for (const { splitPercent, pathIndex, quoteIndex, edgeIndex, request } of quoteUpdates) { - const swapParam = quoteParams[quoteIndex]; - const path = quoteMap[splitPercent][pathIndex]; - try { - const quote = swapQuoteWithParams(swapParam, Percentage.fromFraction(0, 1000)); - const { whirlpoolData, tokenAmount, aToB, amountSpecifiedIsInput } = swapParam; - const [mintA, mintB, vaultA, vaultB] = [ - whirlpoolData.tokenMintA.toBase58(), - whirlpoolData.tokenMintB.toBase58(), - whirlpoolData.tokenVaultA.toBase58(), - whirlpoolData.tokenVaultB.toBase58(), - ]; - const [inputMint, outputMint] = aToB ? [mintA, mintB] : [mintB, mintA]; - path.calculatedEdgeQuotes[edgeIndex] = { - success: true, - amountIn: amountSpecifiedIsInput ? tokenAmount : quote.estimatedAmountIn, - amountOut: amountSpecifiedIsInput ? quote.estimatedAmountOut : tokenAmount, - whirlpool: request.whirlpool, - inputMint, - outputMint, - mintA, - mintB, - vaultA, - vaultB, - quote, - snapshot: { - aToB: swapParam.aToB, - sqrtPrice: whirlpoolData.sqrtPrice, - feeRate: PoolUtil.getFeeRate(whirlpoolData.feeRate), - }, - }; - } catch (e: any) { - const errorCode: SwapErrorCode = e.errorCode; - path.calculatedEdgeQuotes[edgeIndex] = { - success: false, - error: errorCode, - }; - continue; - } - } -} - -/** - * A list of quote requests to be queried in a batch. - * - * @param quoteIndex The index for this quote in the QuoteRequest array - * @param pathIndex The index of the trade paths this request is evaluating - * @param edgeIndex The index of the edge for the evaluated path - * @param splitPercent The percent of the total amount to be swapped - * @param poolAddress The account address of the pool this edge is evaluating - * - */ -type QuoteRequest = { - quoteIndex: number; - pathIndex: number; - edgeIndex: number; - splitPercent: number; - request: SwapQuoteRequest; -}; - -function buildQuoteUpdateRequests( - tokenIn: Address, - tokenOut: Address, - paths: Path[], - percents: number[], - amounts: BN[], - hop: number, - amountSpecifiedIsInput: boolean, - quoteMap: InternalQuoteMap -): QuoteRequest[] { - // Each batch of quotes needs to be iterative - const quoteUpdates: QuoteRequest[] = []; - for (let amountIndex = 0; amountIndex < amounts.length; amountIndex++) { - const percent = percents[amountIndex]; - const tradeAmount = amounts[amountIndex]; - - // Initialize quote map for first hop - if (!quoteMap[percent]) { - quoteMap[percent] = Array(paths.length); - } - - // Iterate over all routes - for (let pathIndex = 0; pathIndex < paths.length; pathIndex++) { - const path = paths[pathIndex]; - const edges = path.edges; - // If the current route is already complete (amountSpecifiedIsInput = true) or if the current hop is beyond - // this route's length (amountSpecifiedIsInput = false), don't do anything - if (amountSpecifiedIsInput ? edges.length <= hop : hop > edges.length - 1) { - continue; - } - - const startingRouteEval = amountSpecifiedIsInput ? hop === 0 : hop === edges.length - 1; - const poolsPath = AddressUtil.toStrings(edges.map((edge) => edge.poolAddress)); - - // If this is the first hop of the route, initialize the quote map - if (startingRouteEval) { - quoteMap[percent][pathIndex] = { - path: path, - splitPercent: percent, - edgesPoolAddrs: poolsPath, - calculatedEdgeQuotes: Array(edges.length), - }; - } - const currentQuote = quoteMap[percent][pathIndex]; - - const poolAddr = poolsPath[hop]; - const lastHop = amountSpecifiedIsInput - ? currentQuote.calculatedEdgeQuotes[hop - 1] - : currentQuote.calculatedEdgeQuotes[hop + 1]; - - // If this is the first hop, use the input mint and amount, otherwise use the output of the last hop - let tokenAmount: BN; - let tradeToken: Address; - if (startingRouteEval) { - tokenAmount = tradeAmount; - tradeToken = amountSpecifiedIsInput ? tokenIn : tokenOut; - } else { - if (!lastHop?.success) { - continue; - } - tokenAmount = amountSpecifiedIsInput ? lastHop.amountOut : lastHop.amountIn; - tradeToken = amountSpecifiedIsInput ? lastHop.outputMint : lastHop.inputMint; - } - - quoteUpdates.push({ - splitPercent: percent, - pathIndex, - edgeIndex: hop, - quoteIndex: quoteUpdates.length, - request: { - whirlpool: poolAddr, - tradeTokenMint: tradeToken, - tokenAmount, - amountSpecifiedIsInput, - }, - }); - } - } - return quoteUpdates; -} - -/** - * Annotate amountIn/amountOut for calculations - * @param tradeAmount - * @param quoteMap - * @returns - */ -function sanitizeQuoteMap( - quoteMap: InternalQuoteMap, - pruneN: number, - amountSpecifiedIsInput: boolean -): readonly [SanitizedQuoteMap, Set] { - const percents = Object.keys(quoteMap).map((percent) => Number(percent)); - const cleanedQuoteMap: SanitizedQuoteMap = {}; - const failureErrors: Set = new Set(); - for (let i = 0; i < percents.length; i++) { - const percent = percents[i]; - const uncleanedQuotes = quoteMap[percent]; - cleanedQuoteMap[percent] = []; - for (const { - edgesPoolAddrs: hopPoolAddrs, - calculatedEdgeQuotes: calculatedHops, - path, - } of uncleanedQuotes) { - // If the route was successful at each step, add it to the clean quote stack - const filteredCalculatedEdges = calculatedHops.flatMap((val) => - !!val && val.success ? val : [] - ); - if (filteredCalculatedEdges.length === hopPoolAddrs.length) { - const [input, output] = [ - filteredCalculatedEdges[0].amountIn, - filteredCalculatedEdges[filteredCalculatedEdges.length - 1].amountOut, - ]; - cleanedQuoteMap[percent].push({ - path, - splitPercent: percent, - edgesPoolAddrs: hopPoolAddrs, - amountIn: input, - amountOut: output, - calculatedEdgeQuotes: filteredCalculatedEdges, - }); - continue; - } - - // If a route failed, there would only be one failure - const quoteFailures = calculatedHops.flatMap((f) => (f && !f?.success ? f : [])); - failureErrors.add(quoteFailures[0].error); - } - } - - // Prune the quote map to only include the top N quotes - const prunedQuoteMap: SanitizedQuoteMap = {}; - const sortFn = amountSpecifiedIsInput - ? (a: PathQuote, b: PathQuote) => b.amountOut.cmp(a.amountOut) - : (a: PathQuote, b: PathQuote) => a.amountIn.cmp(b.amountIn); - for (let i = 0; i < percents.length; i++) { - const sortedQuotes = cleanedQuoteMap[percents[i]].sort(sortFn); - const slicedSorted = sortedQuotes.slice(0, pruneN); - prunedQuoteMap[percents[i]] = slicedSorted; - } - - return [prunedQuoteMap, failureErrors] as const; -} - -function getSplitPercentageAmts(inputAmount: BN, minPercent: number = 5) { - const percents = []; - const amounts = []; - - for (let i = 1; i <= 100 / minPercent; i++) { - percents.push(i * minPercent); - amounts.push(inputAmount.mul(new BN(i * minPercent)).div(new BN(100))); - } - - return { percents, amounts }; -} diff --git a/sdk/src/router/router-impl.ts b/sdk/src/router/router-impl.ts deleted file mode 100644 index 9ea5922..0000000 --- a/sdk/src/router/router-impl.ts +++ /dev/null @@ -1,174 +0,0 @@ -import { Address } from "@coral-xyz/anchor"; -import { AddressUtil, Percentage, TransactionBuilder } from "@orca-so/common-sdk"; -import { Account } from "@solana/spl-token"; -import { WhirlpoolContext } from ".."; -import { RouteQueryErrorCode, SwapErrorCode, WhirlpoolsError } from "../errors/errors"; -import { getSwapFromRoute } from "../instructions/composites/swap-with-route"; -import { - IGNORE_CACHE, - PREFER_CACHE, - WhirlpoolAccountFetchOptions, - WhirlpoolAccountFetcherInterface, -} from "../network/public/fetcher"; -import { Path, PoolGraph, SwapUtils } from "../utils/public"; -import { getBestRoutesFromQuoteMap } from "./convert-quote-map"; -import { - ExecutableRoute, - RouteSelectOptions, - RouterUtils, - RoutingOptions, - Trade, - TradeRoute, - WhirlpoolRouter, -} from "./public"; -import { getQuoteMap } from "./quote-map"; - -export class WhirlpoolRouterImpl implements WhirlpoolRouter { - constructor(readonly ctx: WhirlpoolContext, readonly poolGraph: PoolGraph) {} - - async findAllRoutes( - trade: Trade, - opts?: Partial, - fetchOpts?: WhirlpoolAccountFetchOptions - ): Promise { - const { tokenIn, tokenOut, tradeAmount, amountSpecifiedIsInput } = trade; - const paths = this.poolGraph.getPath(tokenIn, tokenOut); - - if (paths.length === 0) { - return Promise.reject( - new WhirlpoolsError( - `Could not find route for ${tokenIn} -> ${tokenOut}`, - RouteQueryErrorCode.RouteDoesNotExist - ) - ); - } - - if (tradeAmount.isZero()) { - return Promise.reject( - new WhirlpoolsError( - `findBestRoutes error - input amount is zero.`, - RouteQueryErrorCode.ZeroInputAmount - ) - ); - } - - const routingOptions = { ...RouterUtils.getDefaultRouteOptions(), ...opts }; - const { program, fetcher } = this.ctx; - const programId = program.programId; - - await prefetchRoutes(paths, programId, fetcher, fetchOpts); - - try { - const [quoteMap, failures] = await getQuoteMap( - trade, - paths, - amountSpecifiedIsInput, - programId, - fetcher, - routingOptions - ); - const bestRoutes = getBestRoutesFromQuoteMap( - quoteMap, - amountSpecifiedIsInput, - routingOptions - ); - - // TODO: Rudementary implementation to determine error. Find a better solution - if (bestRoutes.length === 0) { - // TODO: TRADE_AMOUNT_TOO_HIGH actually corresponds to TickArrayCrossingAboveMax. Fix swap quote. - if (failures.has(SwapErrorCode.TickArraySequenceInvalid)) { - return Promise.reject( - new WhirlpoolsError( - `All swap quote generation failed on amount too high.`, - RouteQueryErrorCode.TradeAmountTooHigh - ) - ); - } - } - - return bestRoutes; - } catch (e: any) { - return Promise.reject( - new WhirlpoolsError( - `Stack error received on quote generation.`, - RouteQueryErrorCode.General, - e.stack - ) - ); - } - } - - async findBestRoute( - trade: Trade, - routingOpts?: Partial, - selectionOpts?: Partial, - fetchOpts?: WhirlpoolAccountFetchOptions - ): Promise { - const allRoutes = await this.findAllRoutes(trade, routingOpts, fetchOpts); - const selectOpts = { ...RouterUtils.getDefaultSelectOptions(), ...selectionOpts }; - return await RouterUtils.selectFirstExecutableRoute(this.ctx, allRoutes, selectOpts); - } - - async swap( - trade: TradeRoute, - slippage: Percentage, - resolvedAtas: Account[] | null - ): Promise { - const txBuilder = await getSwapFromRoute( - this.ctx, - { - route: trade, - slippage, - resolvedAtaAccounts: resolvedAtas, - wallet: this.ctx.wallet.publicKey, - }, - IGNORE_CACHE - ); - return txBuilder; - } -} - -// Load all pool and tick-array data into the fetcher cache. -async function prefetchRoutes( - paths: Path[], - programId: Address, - fetcher: WhirlpoolAccountFetcherInterface, - opts: WhirlpoolAccountFetchOptions = PREFER_CACHE -): Promise { - const poolSet = new Set(); - for (let i = 0; i < paths.length; i++) { - const path = paths[i]; - for (let j = 0; j < path.edges.length; j++) { - poolSet.add(AddressUtil.toString(path.edges[j].poolAddress)); - } - } - - const ps = Array.from(poolSet); - const allWps = await fetcher.getPools(ps, opts); - - const tickArrayAddresses = []; - for (const [key, wp] of allWps) { - if (wp == null) { - continue; - } - const addr1 = SwapUtils.getTickArrayPublicKeys( - wp.tickCurrentIndex, - wp.tickSpacing, - true, - AddressUtil.toPubKey(programId), - AddressUtil.toPubKey(key) - ); - const addr2 = SwapUtils.getTickArrayPublicKeys( - wp.tickCurrentIndex, - wp.tickSpacing, - false, - AddressUtil.toPubKey(programId), - AddressUtil.toPubKey(key) - ); - const allAddrs = [...addr1, ...addr2].map((k) => k.toBase58()); - const unique = Array.from(new Set(allAddrs)); - tickArrayAddresses.push(...unique); - } - - await fetcher.getTickArrays(tickArrayAddresses, opts); -} diff --git a/sdk/src/tsconfig.json b/sdk/src/tsconfig.json deleted file mode 100644 index efaed5c..0000000 --- a/sdk/src/tsconfig.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "extends": "../tsconfig-base.json", - "compilerOptions": { - "composite": true - }, - "include": ["./**/*", "./artifacts/**/*.json"], - "typedocOptions": { - "entryPoints": ["index.ts"], - "out": "../../docs" - } -} diff --git a/sdk/src/types/public/anchor-types.ts b/sdk/src/types/public/anchor-types.ts deleted file mode 100644 index 43f8f72..0000000 --- a/sdk/src/types/public/anchor-types.ts +++ /dev/null @@ -1,197 +0,0 @@ -import { BN, BorshAccountsCoder, Idl } from "@coral-xyz/anchor"; -import { PublicKey } from "@solana/web3.js"; -import WhirlpoolIDL from "../../artifacts/whirlpool.json"; - -/** - * This file contains the types that has the same structure as the types anchor functions returns. - * These types are hard-casted by the client function. - * - * This file must be manually updated every time the idl updates as accounts will - * be hard-casted to fit the type. - */ - -/** - * Supported parasable account names from the Whirlpool contract. - * @category Network - */ -export enum AccountName { - WhirlpoolsConfig = "WhirlpoolsConfig", - Position = "Position", - TickArray = "TickArray", - Whirlpool = "Whirlpool", - FeeTier = "FeeTier", - PositionBundle = "PositionBundle", -} - -export const WHIRLPOOL_IDL = WhirlpoolIDL as Idl; - -/** - * The Anchor coder for the Whirlpool program. - * @category Solana Accounts - */ -export const WHIRLPOOL_CODER = new BorshAccountsCoder(WHIRLPOOL_IDL); - -/** - * Get the size of an account owned by the Whirlpool program in bytes. - * @param accountName Whirlpool account name - * @returns Size in bytes of the account - */ -export function getAccountSize(accountName: AccountName) { - const size = WHIRLPOOL_CODER.size( - WHIRLPOOL_IDL.accounts!.find((account) => account.name === accountName)! - ); - return size + RESERVED_BYTES[accountName]; -} - -/** - * Reserved bytes for each account used for calculating the account size. - */ -const RESERVED_BYTES: ReservedBytes = { - [AccountName.WhirlpoolsConfig]: 2, - [AccountName.Position]: 0, - [AccountName.TickArray]: 0, - [AccountName.Whirlpool]: 0, - [AccountName.FeeTier]: 0, - [AccountName.PositionBundle]: 64, -}; - -type ReservedBytes = { - [name in AccountName]: number; -}; - -/** - * Size of the Whirlpool account in bytes. - * @deprecated Please use {@link getAccountSize} instead. - * @category Solana Accounts - */ -export const WHIRLPOOL_ACCOUNT_SIZE = getAccountSize(AccountName.Whirlpool); - -/** - * @category Solana Accounts - */ -export type WhirlpoolsConfigData = { - feeAuthority: PublicKey; - collectProtocolFeesAuthority: PublicKey; - rewardEmissionsSuperAuthority: PublicKey; - defaultFeeRate: number; - defaultProtocolFeeRate: number; -}; - -/** - * @category Solana Accounts - */ -export type WhirlpoolRewardInfoData = { - mint: PublicKey; - vault: PublicKey; - authority: PublicKey; - emissionsPerSecondX64: BN; - growthGlobalX64: BN; -}; - -/** - * @category Solana Accounts - */ -export type WhirlpoolBumpsData = { - whirlpoolBump: number; -}; - -/** - * @category Solana Accounts - */ -export type WhirlpoolData = { - whirlpoolsConfig: PublicKey; - whirlpoolBump: number[]; - feeRate: number; - protocolFeeRate: number; - liquidity: BN; - sqrtPrice: BN; - tickCurrentIndex: number; - protocolFeeOwedA: BN; - protocolFeeOwedB: BN; - tokenMintA: PublicKey; - tokenVaultA: PublicKey; - feeGrowthGlobalA: BN; - tokenMintB: PublicKey; - tokenVaultB: PublicKey; - feeGrowthGlobalB: BN; - rewardLastUpdatedTimestamp: BN; - rewardInfos: WhirlpoolRewardInfoData[]; - tickSpacing: number; -}; - -/** - * @category Solana Accounts - */ -export type TickArrayData = { - whirlpool: PublicKey; - startTickIndex: number; - ticks: TickData[]; -}; - -/** - * @category Solana Accounts - */ -export type TickData = { - initialized: boolean; - liquidityNet: BN; - liquidityGross: BN; - feeGrowthOutsideA: BN; - feeGrowthOutsideB: BN; - rewardGrowthsOutside: BN[]; -}; - -/** - * @category Solana Accounts - */ -export type PositionRewardInfoData = { - growthInsideCheckpoint: BN; - amountOwed: BN; -}; - -/** - * @category Solana Accounts - */ -export type OpenPositionBumpsData = { - positionBump: number; -}; - -/** - * @category Solana Accounts - */ -export type OpenPositionWithMetadataBumpsData = { - positionBump: number; - metadataBump: number; -}; - -/** - * @category Solana Accounts - */ -export type PositionData = { - whirlpool: PublicKey; - positionMint: PublicKey; - liquidity: BN; - tickLowerIndex: number; - tickUpperIndex: number; - feeGrowthCheckpointA: BN; - feeOwedA: BN; - feeGrowthCheckpointB: BN; - feeOwedB: BN; - rewardInfos: PositionRewardInfoData[]; -}; - -/** - * @category Solana Accounts - */ -export type FeeTierData = { - whirlpoolsConfig: PublicKey; - tickSpacing: number; - defaultFeeRate: number; -}; - -/** - * @category Solana Accounts - */ -export type PositionBundleData = { - positionBundleMint: PublicKey; - positionBitmap: number[]; -}; diff --git a/sdk/src/types/public/client-types.ts b/sdk/src/types/public/client-types.ts deleted file mode 100644 index ce03471..0000000 --- a/sdk/src/types/public/client-types.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { Account, Mint } from "@solana/spl-token"; -import { PublicKey } from "@solana/web3.js"; -import BN from "bn.js"; -import { TickArrayData, WhirlpoolRewardInfoData } from "./anchor-types"; - -/** - * Extended Mint type to host token info. - * @category WhirlpoolClient - */ -export type TokenInfo = Mint & { mint: PublicKey }; - -/** - * Extended (token) Account type to host account info for a Token. - * @category WhirlpoolClient - */ -export type TokenAccountInfo = Account; - -/** - * Type to represent a reward for a reward index on a Whirlpool. - * @category WhirlpoolClient - */ -export type WhirlpoolRewardInfo = WhirlpoolRewardInfoData & { - initialized: boolean; - vaultAmount: BN; -}; - -/** - * A wrapper class of a TickArray on a Whirlpool - * @category WhirlpoolClient - */ -export type TickArray = { - address: PublicKey; - data: TickArrayData | null; -}; diff --git a/sdk/src/types/public/constants.ts b/sdk/src/types/public/constants.ts deleted file mode 100644 index 00828a1..0000000 --- a/sdk/src/types/public/constants.ts +++ /dev/null @@ -1,109 +0,0 @@ -import { BN } from "@coral-xyz/anchor"; -import { PublicKey } from "@solana/web3.js"; - -/** - * Program ID hosting Orca's Whirlpool program. - * @category Constants - */ -export const ORCA_WHIRLPOOL_PROGRAM_ID = new PublicKey( - "whirLbMiicVdio4qvUfM5KAg6Ct8VwpYzGff3uctyCc" -); - -/** - * Orca's WhirlpoolsConfig PublicKey. - * @category Constants - */ -export const ORCA_WHIRLPOOLS_CONFIG = new PublicKey("2LecshUwdy9xi7meFgHtFJQNSKk4KdTrcpvaB56dP2NQ"); - -/** - * Orca's supported tick spacings. - * @category Constants - */ -export const ORCA_SUPPORTED_TICK_SPACINGS = [1, 2, 4, 8, 16, 64, 128, 256]; - -/** - * The number of rewards supported by this whirlpool. - * @category Constants - */ -export const NUM_REWARDS = 3; - -/** - * The maximum tick index supported by the Whirlpool program. - * @category Constants - */ -export const MAX_TICK_INDEX = 443636; - -/** - * The minimum tick index supported by the Whirlpool program. - * @category Constants - */ -export const MIN_TICK_INDEX = -443636; - -/** - * The maximum sqrt-price supported by the Whirlpool program. - * @category Constants - */ -export const MAX_SQRT_PRICE = "79226673515401279992447579055"; - -/** - * The minimum sqrt-price supported by the Whirlpool program. - * @category Constants - */ -export const MIN_SQRT_PRICE = "4295048016"; - -/** - * The minimum sqrt-price supported by the Whirlpool program. - * @category Constants - */ -export const MIN_SQRT_PRICE_BN = new BN(MIN_SQRT_PRICE); - -/** - * The maximum sqrt-price supported by the Whirlpool program. - * @category Constants - */ -export const MAX_SQRT_PRICE_BN = new BN(MAX_SQRT_PRICE); - -/** - * The number of initialized ticks that a tick-array account can hold. - * @category Constants - */ -export const TICK_ARRAY_SIZE = 88; - -/** - * The number of bundled positions that a position-bundle account can hold. - * @category Constants - */ -export const POSITION_BUNDLE_SIZE = 256; - -/** - * @category Constants - */ -export const METADATA_PROGRAM_ADDRESS = new PublicKey( - "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s" -); - -/** - * The maximum number of tick-arrays that can traversed across in a swap. - * @category Constants - */ -export const MAX_SWAP_TICK_ARRAYS = 3; - -/** - * The denominator which the protocol fee rate is divided on. - * @category Constants - */ -export const PROTOCOL_FEE_RATE_MUL_VALUE = new BN(10_000); - -/** - * The denominator which the fee rate is divided on. - * @category Constants - */ -export const FEE_RATE_MUL_VALUE = new BN(1_000_000); - -/** - * The public key that is allowed to update the metadata of Whirlpool NFTs. - * @category Constants - */ -export const WHIRLPOOL_NFT_UPDATE_AUTH = new PublicKey( - "3axbTs2z5GBy6usVbNVoqEgZMng3vZvMnAoX29BFfwhr" -); diff --git a/sdk/src/types/public/index.ts b/sdk/src/types/public/index.ts deleted file mode 100644 index de60940..0000000 --- a/sdk/src/types/public/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from "./anchor-types"; -export * from "./client-types"; -export * from "./constants"; -export * from "./ix-types"; diff --git a/sdk/src/types/public/ix-types.ts b/sdk/src/types/public/ix-types.ts deleted file mode 100644 index 9b97742..0000000 --- a/sdk/src/types/public/ix-types.ts +++ /dev/null @@ -1,39 +0,0 @@ -export { - ClosePositionParams, - CollectFeesParams, - CollectProtocolFeesParams, - CollectRewardParams, - DecreaseLiquidityInput, - DecreaseLiquidityParams, - DevFeeSwapInput, - IncreaseLiquidityInput, - IncreaseLiquidityParams, - InitConfigParams, - InitFeeTierParams, - InitializeRewardParams, - InitPoolParams, - InitTickArrayParams, - OpenPositionParams, - SetCollectProtocolFeesAuthorityParams, - SetDefaultFeeRateParams, - SetDefaultProtocolFeeRateParams, - SetFeeAuthorityParams, - SetFeeRateParams, - SetProtocolFeeRateParams, - SetRewardAuthorityBySuperAuthorityParams, - SetRewardAuthorityParams, - SetRewardEmissionsParams, - SetRewardEmissionsSuperAuthorityParams, - SwapInput, - SwapParams, - UpdateFeesAndRewardsParams, - InitializePositionBundleParams, - DeletePositionBundleParams, - OpenBundledPositionParams, - CloseBundledPositionParams, -} from "../../instructions/"; -export { - CollectAllParams, - CollectAllPositionAddressParams, - CollectAllPositionParams, -} from "../../instructions/composites"; diff --git a/sdk/src/utils/builder/position-builder-util.ts b/sdk/src/utils/builder/position-builder-util.ts deleted file mode 100644 index 3bc8044..0000000 --- a/sdk/src/utils/builder/position-builder-util.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { WhirlpoolContext } from "../.."; -import { WhirlpoolAccountFetchOptions } from "../../network/public/fetcher"; -import { PositionData, WhirlpoolData } from "../../types/public"; -import { PDAUtil } from "../public"; - -export async function getTickArrayDataForPosition( - ctx: WhirlpoolContext, - position: PositionData, - whirlpool: WhirlpoolData, - opts?: WhirlpoolAccountFetchOptions -) { - const lowerTickArrayKey = PDAUtil.getTickArrayFromTickIndex( - position.tickLowerIndex, - whirlpool.tickSpacing, - position.whirlpool, - ctx.program.programId - ).publicKey; - const upperTickArrayKey = PDAUtil.getTickArrayFromTickIndex( - position.tickUpperIndex, - whirlpool.tickSpacing, - position.whirlpool, - ctx.program.programId - ).publicKey; - - return await ctx.fetcher.getTickArrays([lowerTickArrayKey, upperTickArrayKey], opts); -} diff --git a/sdk/src/utils/constants.ts b/sdk/src/utils/constants.ts deleted file mode 100644 index 01aca6c..0000000 --- a/sdk/src/utils/constants.ts +++ /dev/null @@ -1,8 +0,0 @@ -export const TOKEN_MINTS = { - USDC: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", - SOL: "So11111111111111111111111111111111111111112", - USDT: "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB", - USDH: "USDH1SM1ojwWUga67PGrgFWUHibbjqMvuMaDkRJTgkX", - mSOL: "mSoLzYCxHdYgdzU16g5QSh3i5K3z3KZK7ytfqcJm7So", - stSOL: "7dHbWXmci3dT8UFYWYZweBLXgycu7Y3iL6trKn1Y7ARj", -}; diff --git a/sdk/src/utils/graphs/adjacency-list-pool-graph.ts b/sdk/src/utils/graphs/adjacency-list-pool-graph.ts deleted file mode 100644 index 7883425..0000000 --- a/sdk/src/utils/graphs/adjacency-list-pool-graph.ts +++ /dev/null @@ -1,278 +0,0 @@ -import { Address } from "@coral-xyz/anchor"; -import { AddressUtil } from "@orca-so/common-sdk"; -import { - Edge, - Path, - PathSearchEntries, - PathSearchOptions, - PoolGraph, - PoolTokenPair, -} from "./public/pool-graph"; -import { PoolGraphUtils } from "./public/pool-graph-utils"; - -/** - * A pool graph implementation using an adjacency list. - * - * Whirlpools (Pools (edges) & Tokens (nodes)) are sparse graphs concentrated on popular pairs such as SOL, USDC etc. - * Therefore this implementation is more efficient in memory consumption & building than a matrix. - * - * TODO: This implementation does not support 2-edge paths between identical tokens. - */ -export class AdjacencyListPoolGraph implements PoolGraph { - readonly graph: Readonly; - readonly tokens: Readonly; - - constructor(pools: PoolTokenPair[]) { - const [adjacencyListGraphMap, insertedTokens] = buildPoolGraph(pools); - this.graph = adjacencyListGraphMap; - this.tokens = Array.from(insertedTokens); - } - - getPath(startMint: Address, endMint: Address, options?: PathSearchOptions): Path[] { - const results = this.getPathsForPairs([[startMint, endMint]], options); - return results[0][1]; - } - - getPathsForPairs( - searchTokenPairs: [Address, Address][], - options?: PathSearchOptions - ): PathSearchEntries { - const searchTokenPairsInString = searchTokenPairs.map(([startMint, endMint]) => { - return [AddressUtil.toString(startMint), AddressUtil.toString(endMint)] as const; - }); - - const searchTokenPairsToFind = searchTokenPairsInString.filter(([startMint, endMint]) => { - return startMint !== endMint; - }); - - const walkMap = findWalks( - searchTokenPairsToFind, - this.graph, - options?.intermediateTokens.map((token) => AddressUtil.toString(token)) - ); - - const results = searchTokenPairsInString.map(([startMint, endMint]) => { - const searchRouteId = PoolGraphUtils.getSearchPathId(startMint, endMint); - - const [internalStartMint, internalEndMint] = [startMint, endMint].sort(); - const internalRouteId = getInternalRouteId(internalStartMint, internalEndMint, false); - const reversed = internalStartMint !== startMint; - const pathsForSearchPair = walkMap[internalRouteId]; - - const paths = pathsForSearchPair - ? pathsForSearchPair.map((path) => { - return { - startTokenMint: startMint, - endTokenMint: endMint, - edges: getHopsFromRoute(path, reversed), - }; - }) - : []; - - return [searchRouteId, paths] as const; - }); - return results; - } - - getAllPaths(options?: PathSearchOptions | undefined): PathSearchEntries { - const tokenPairCombinations = combinations2(this.tokens) as [string, string][]; - const searchTokenPairsInString = tokenPairCombinations.map(([startMint, endMint]) => { - return [startMint, endMint] as const; - }); - - const searchTokenPairsToFind = searchTokenPairsInString.filter(([startMint, endMint]) => { - return startMint !== endMint; - }); - - const walkMap = findWalks( - searchTokenPairsToFind, - this.graph, - options?.intermediateTokens.map((token) => AddressUtil.toString(token)) - ); - - // TODO: The token pairs are is in 1 direction only, we have to reverse them to get the other direction. - // this is actually pretty slow.consider removing reversal optimization in findWalks - const results = searchTokenPairsInString.reduce( - (acc, [startMint, endMint]) => { - const searchRouteId = PoolGraphUtils.getSearchPathId(startMint, endMint); - - // We do not support routes that routes between identical tokens - if (startMint === endMint) { - acc.push([searchRouteId, []]); - return acc; - } - - const [internalStartMint, internalEndMint] = [startMint, endMint].sort(); - const internalRouteId = getInternalRouteId(internalStartMint, internalEndMint, false); - const reversed = internalStartMint !== startMint; - const pathsForSearchPair = walkMap[internalRouteId]; - - const paths = pathsForSearchPair - ? pathsForSearchPair.map((path) => { - return { - startTokenMint: startMint, - endTokenMint: endMint, - edges: getHopsFromRoute(path, reversed), - }; - }) - : []; - - acc.push([searchRouteId, paths]); - - const reversedSearchRouteId = PoolGraphUtils.getSearchPathId(endMint, startMint); - const reversedPaths = pathsForSearchPair - ? pathsForSearchPair.map((path) => { - return { - startTokenMint: endMint, - endTokenMint: startMint, - edges: getHopsFromRoute(path, !reversed), - }; - }) - : []; - - acc.push([reversedSearchRouteId, reversedPaths]); - return acc; - }, - [] - ); - - return results; - } -} - -function getHopsFromRoute(path: string[], reversed: boolean): Edge[] { - const finalRoutes = reversed ? path.slice().reverse() : path; - - return finalRoutes.map((hopStr) => { - return { poolAddress: hopStr }; - }); -} - -type AdjacencyPoolGraphMap = Record; - -type PoolGraphEdge = { - address: string; - otherToken: string; -}; - -// A record of path-id (tokenA-tokenB) to a list of edges -type PoolWalks = Record; - -function buildPoolGraph( - pools: PoolTokenPair[] -): readonly [Readonly, Set] { - const insertedPoolCache: Record> = {}; - const insertedTokens = new Set(); - const poolGraphSet = pools.reduce((poolGraph: Record, pool) => { - const { address, tokenMintA, tokenMintB } = pool; - const [addr, mintA, mintB] = AddressUtil.toStrings([address, tokenMintA, tokenMintB]); - - insertedTokens.add(mintA); - insertedTokens.add(mintB); - - if (poolGraph[mintA] === undefined) { - poolGraph[mintA] = []; - insertedPoolCache[mintA] = new Set(); - } - - if (poolGraph[mintB] === undefined) { - poolGraph[mintB] = []; - insertedPoolCache[mintB] = new Set(); - } - - const [insertedPoolsForA, insertedPoolsForB] = [ - insertedPoolCache[mintA], - insertedPoolCache[mintB], - ]; - - if (!insertedPoolsForA.has(addr)) { - poolGraph[mintA].push({ address: addr, otherToken: mintB }); - insertedPoolsForA.add(addr); - } - - if (!insertedPoolsForB.has(addr)) { - poolGraph[mintB].push({ address: addr, otherToken: mintA }); - insertedPoolsForB.add(addr); - } - - return poolGraph; - }, {}); - - return [poolGraphSet, insertedTokens] as const; -} - -// This is currently hardcoded to find walks of max length 2, generalizing to longer walks -// may mean that a adjacency matrix might have better performance -// NOTE: that this function does not support routing between the same token on hop length 2. -function findWalks( - tokenPairs: (readonly [string, string])[], - poolGraph: AdjacencyPoolGraphMap, - intermediateTokens?: string[] -) { - const walks: PoolWalks = {}; - - tokenPairs.forEach(([tokenMintFrom, tokenMintTo]) => { - let paths = []; - - // Adjust walk's from & to token based of of internal path id. - const [internalTokenMintFrom, internalTokenMintTo] = [tokenMintFrom, tokenMintTo].sort(); - const internalPathId = getInternalRouteId(internalTokenMintFrom, internalTokenMintTo, false); - - const poolsForTokenFrom = poolGraph[internalTokenMintFrom] || []; - const poolsForTokenTo = poolGraph[internalTokenMintTo] || []; - - // If the internal path id has already been created, then there is no need to re-search the path. - // Possible that the path was searched in reverse. - if (!!walks[internalPathId]) { - return; - } - - // Find all direct pool paths, i.e. all edges shared between tokenA and tokenB - const singleHop = poolsForTokenFrom - .filter(({ address }) => poolsForTokenTo.some((p) => p.address === address)) - .map((op) => [op.address]); - paths.push(...singleHop); - - // Remove all direct edges from poolA to poolB - const firstHop = poolsForTokenFrom.filter( - ({ address }) => !poolsForTokenTo.some((p) => p.address === address) - ); - - // Find all edges/nodes from neighbors of A that connect to B to create paths of length 2 - // tokenA --> tokenX --> tokenB - firstHop.forEach((firstPool) => { - const intermediateToken = firstPool.otherToken; - if (!intermediateTokens || intermediateTokens.indexOf(intermediateToken) > -1) { - const secondHops = poolsForTokenTo - .filter((secondPool) => secondPool.otherToken === intermediateToken) - .map((secondPool) => [firstPool.address, secondPool.address]); - paths.push(...secondHops); - } - }); - - if (paths.length > 0) { - walks[internalPathId] = paths; - } - }); - - return walks; -} - -function getInternalRouteId(tokenA: Address, tokenB: Address, sort = true): string { - const mints = [AddressUtil.toString(tokenA), AddressUtil.toString(tokenB)]; - const sortedMints = sort ? mints.sort() : mints; - return `${sortedMints[0]}${PoolGraphUtils.PATH_ID_DELIMITER}${sortedMints[1]}`; -} - -// equivalent to lodash.combinations(array, 2) -function combinations2(array: Readonly): [T, T][] { - const result: [T, T][] = []; - - for (let i = 0; i < array.length - 1; i++) { - for (let j = i+1; j < array.length; j++) { - result.push([array[i], array[j]]); - } - } - - return result; -} diff --git a/sdk/src/utils/graphs/public/index.ts b/sdk/src/utils/graphs/public/index.ts deleted file mode 100644 index 2a10b31..0000000 --- a/sdk/src/utils/graphs/public/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from "./pool-graph"; -export * from "./pool-graph-builder"; -export * from "./pool-graph-utils"; diff --git a/sdk/src/utils/graphs/public/pool-graph-builder.ts b/sdk/src/utils/graphs/public/pool-graph-builder.ts deleted file mode 100644 index 4e4e0a4..0000000 --- a/sdk/src/utils/graphs/public/pool-graph-builder.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { Address } from "@coral-xyz/anchor"; -import { PREFER_CACHE, WhirlpoolAccountFetcherInterface } from "../../../network/public/fetcher"; -import { AdjacencyListPoolGraph } from "../adjacency-list-pool-graph"; -import { PoolGraph, PoolTokenPair } from "./pool-graph"; - -/** - * A builder class for creating a {@link PoolGraph} - * - * Note: we use an adjacency list as a representation of our pool graph, - * since we assume that most token pairings don't exist as pools - * @category PoolGraph - */ -export class PoolGraphBuilder { - /** - * Fetch data and build a {@link PoolGraph} from a list of pools addresses - * @param pools - a list of pool addresses to generate this pool graph - * @param cache - {@link WhirlpoolAccountFetcherInterface} to use for fetching pool data - * @returns A {@link PoolGraph} with the provided pools - */ - static async buildPoolGraphWithFetch( - pools: Address[], - fetcher: WhirlpoolAccountFetcherInterface - ): Promise { - const poolAccounts = await fetcher.getPools(pools, PREFER_CACHE); - const poolTokenPairs = Array.from(poolAccounts.entries()) - .map(([addr, pool]) => { - if (pool) { - return { - address: addr, - tokenMintA: pool.tokenMintA, - tokenMintB: pool.tokenMintB, - }; - } - return null; - }) - .flatMap((pool) => (pool ? pool : [])); - - return new AdjacencyListPoolGraph(poolTokenPairs); - } - - /** - * Build a {@link PoolGraph} from a list of pools in the format of {@link PoolTokenPair} - * @param poolTokenPairs - a list of {@link PoolTokenPair} to generate this pool graph - * @returns A {@link PoolGraph} with the provided pools - */ - static buildPoolGraph(poolTokenPairs: PoolTokenPair[]): PoolGraph { - return new AdjacencyListPoolGraph(poolTokenPairs); - } -} diff --git a/sdk/src/utils/graphs/public/pool-graph-utils.ts b/sdk/src/utils/graphs/public/pool-graph-utils.ts deleted file mode 100644 index 2e12fde..0000000 --- a/sdk/src/utils/graphs/public/pool-graph-utils.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { Address } from "@coral-xyz/anchor"; -import { AddressUtil } from "@orca-so/common-sdk"; - -/** - * A utility class for working with pool graphs - * @category PoolGraph - */ -export class PoolGraphUtils { - static readonly PATH_ID_DELIMITER = "-"; - - /** - * Get a search path id from two tokens. The id can be used to identify a path between the two tokens in {@link PathSearchEntries}. - * @param tokenA The first token in the path - * @param tokenB The second token in the path - * @returns A path id that can be used to identify a path between the two tokens in {@link PathSearchEntries}. - */ - static getSearchPathId(tokenA: Address, tokenB: Address): string { - return `${AddressUtil.toString(tokenA)}${ - PoolGraphUtils.PATH_ID_DELIMITER - }${AddressUtil.toString(tokenB)}`; - } - - /** - * Deconstruct a path id into the two tokens it represents - * @param pathId - The path id to deconstruct - * @returns A tuple of the two tokens in the path id. Returns undefined if the provided pathId is invalid. - */ - static deconstructPathId(pathId: string): readonly [string, string] { - const split = pathId.split(PoolGraphUtils.PATH_ID_DELIMITER); - - if (split.length !== 2) { - throw new Error(`Invalid path id: ${pathId}`); - } - - const [tokenA, tokenB] = split; - return [tokenA, tokenB] as const; - } -} diff --git a/sdk/src/utils/graphs/public/pool-graph.ts b/sdk/src/utils/graphs/public/pool-graph.ts deleted file mode 100644 index 21ed457..0000000 --- a/sdk/src/utils/graphs/public/pool-graph.ts +++ /dev/null @@ -1,99 +0,0 @@ -import { Address } from "@coral-xyz/anchor"; - -/** - * An object containing the token pairs of a Whirlpool. - * @category PoolGraph - */ -export interface PoolTokenPair { - address: Address; - tokenMintA: Address; - tokenMintB: Address; -} - -/** - * Results for a series of graph search queries between two tokens. - * The search id for each entry can be obtained from {@link PoolGraphUtils.getSearchRouteId} - * If a path exist between tokens for that search id, it will be an array of paths. - * If paths do not exist, it will be an empty array. - * - * @category PoolGraph - */ -export type PathSearchEntries = (readonly [string, Path[]])[]; - -/** - * A path to trade from start token mint to end token mint. - * - * @category PoolGraph - * @param startMint - The token the path starts with - * @param endMint - The token the path ends with - * @param edges - An ordered list of edges (pool addresses) that make up the path - */ -export type Path = { - startTokenMint: string; - endTokenMint: string; - edges: Edge[]; -}; - -/** - * A type representing a pool graph edge. - * - * @category PoolGraph - */ -export type Edge = { - poolAddress: Address; -}; - -/** - * Options for finding a path between two tokens - * - * @category PoolGraph - * @param intermediateTokens - A list of tokens that can be used as intermediate hops - */ -export type PathSearchOptions = { - intermediateTokens: Address[]; -}; - -/** - * A type representing an undirected graph of pools that can be used to find paths between two tokens. - * In this graph, nodes are token mints, and edges are pools - * - * @category PoolGraph - */ -export type PoolGraph = { - /** - * Get a list of paths between two tokens for this pool graph. - * - * Notes: - * - Only support paths with up to 2 edges - * - Paths searching between two identical token mints are not supported. - * - * @param startMint The token the path starts from - * @param endMint The token the path ends in - * @param options Options for finding a path - * @returns A list of path between the two tokens. If no path are found, it will be an empty array. - */ - getPath: (startMint: Address, endMint: Address, options?: PathSearchOptions) => Path[]; - - /** - * Get a map of paths from a list of token pairs for this pool graph. - * - * Notes: - * - Only support paths with up to 2 edges - * - Paths searching between two identical token mints are not supported. - * - * @param searchTokenPairs A list of token pairs to find paths for. The first token in the pair is the start token, and the second token is the end token. - * @param options Options for finding a path - * @return An array of search result entires in the same order as the searchTokenPairs. - */ - getPathsForPairs( - searchTokenPairs: [Address, Address][], - options?: PathSearchOptions - ): PathSearchEntries; - - /** - * Get a list of all paths for this pool graph. - * @param options Options for finding a path - * @return An array of all permutations of token-pairs to the paths for each pair. - */ - getAllPaths(options?: PathSearchOptions): PathSearchEntries; -}; diff --git a/sdk/src/utils/instructions-util.ts b/sdk/src/utils/instructions-util.ts deleted file mode 100644 index 48ae7c6..0000000 --- a/sdk/src/utils/instructions-util.ts +++ /dev/null @@ -1,27 +0,0 @@ -import * as anchor from "@coral-xyz/anchor"; -import { ASSOCIATED_TOKEN_PROGRAM_ID, TOKEN_PROGRAM_ID } from "@solana/spl-token"; -import { SystemProgram } from "@solana/web3.js"; -import { OpenPositionParams } from "../instructions"; - -export function openPositionAccounts(params: OpenPositionParams) { - const { - funder, - owner, - positionPda, - positionMintAddress, - positionTokenAccount: positionTokenAccountAddress, - whirlpool: whirlpoolKey, - } = params; - return { - funder: funder, - owner, - position: positionPda.publicKey, - positionMint: positionMintAddress, - positionTokenAccount: positionTokenAccountAddress, - whirlpool: whirlpoolKey, - tokenProgram: TOKEN_PROGRAM_ID, - systemProgram: SystemProgram.programId, - rent: anchor.web3.SYSVAR_RENT_PUBKEY, - associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID, - }; -} diff --git a/sdk/src/utils/math/bit-math.ts b/sdk/src/utils/math/bit-math.ts deleted file mode 100644 index 6c6b9bd..0000000 --- a/sdk/src/utils/math/bit-math.ts +++ /dev/null @@ -1,82 +0,0 @@ -import { BN } from "@coral-xyz/anchor"; -import { MathUtil, ONE, TWO, U64_MAX, ZERO } from "@orca-so/common-sdk"; -import { MathErrorCode, WhirlpoolsError } from "../../errors/errors"; - -export class BitMath { - static mul(n0: BN, n1: BN, limit: number): BN { - const result = n0.mul(n1); - if (this.isOverLimit(result, limit)) { - throw new WhirlpoolsError( - `Mul result higher than u${limit}`, - MathErrorCode.MultiplicationOverflow - ); - } - return result; - } - - static mulDiv(n0: BN, n1: BN, d: BN, limit: number): BN { - return this.mulDivRoundUpIf(n0, n1, d, false, limit); - } - - static mulDivRoundUp(n0: BN, n1: BN, d: BN, limit: number): BN { - return this.mulDivRoundUpIf(n0, n1, d, true, limit); - } - - static mulDivRoundUpIf(n0: BN, n1: BN, d: BN, roundUp: boolean, limit: number): BN { - if (d.eq(ZERO)) { - throw new WhirlpoolsError("mulDiv denominator is zero", MathErrorCode.DivideByZero); - } - - const p = this.mul(n0, n1, limit); - const n = p.div(d); - - return roundUp && p.mod(d).gt(ZERO) ? n.add(ONE) : n; - } - - static checked_mul_shift_right(n0: BN, n1: BN, limit: number) { - return this.checked_mul_shift_right_round_up_if(n0, n1, false, limit); - } - - static checked_mul_shift_right_round_up_if(n0: BN, n1: BN, roundUp: boolean, limit: number) { - if (n0.eq(ZERO) || n1.eq(ZERO)) { - return ZERO; - } - - const p = this.mul(n0, n1, limit); - if (this.isOverLimit(p, limit)) { - throw new WhirlpoolsError( - `MulShiftRight overflowed u${limit}.`, - MathErrorCode.MultiplicationShiftRightOverflow - ); - } - const result = MathUtil.fromX64_BN(p); - const shouldRound = roundUp && result.and(U64_MAX).gt(ZERO); - if (shouldRound && result.eq(U64_MAX)) { - throw new WhirlpoolsError( - `MulShiftRight overflowed u${limit}.`, - MathErrorCode.MultiplicationOverflow - ); - } - - return shouldRound ? result.add(ONE) : result; - } - - static isOverLimit(n0: BN, limit: number) { - const limitBN = TWO.pow(new BN(limit)).sub(ONE); - return n0.gt(limitBN); - } - - static divRoundUp(n: BN, d: BN) { - return this.divRoundUpIf(n, d, true); - } - - static divRoundUpIf(n: BN, d: BN, roundUp: boolean) { - if (d.eq(ZERO)) { - throw new WhirlpoolsError("divRoundUpIf - divide by zero", MathErrorCode.DivideByZero); - } - - let q = n.div(d); - - return roundUp && n.mod(d).gt(ZERO) ? q.add(ONE) : q; - } -} diff --git a/sdk/src/utils/math/constants.ts b/sdk/src/utils/math/constants.ts deleted file mode 100644 index 2c75413..0000000 --- a/sdk/src/utils/math/constants.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { ONE, U64_MAX } from "@orca-so/common-sdk"; - -export const U64 = U64_MAX.add(ONE); diff --git a/sdk/src/utils/math/k-smallest-partition.ts b/sdk/src/utils/math/k-smallest-partition.ts deleted file mode 100644 index c7d405b..0000000 --- a/sdk/src/utils/math/k-smallest-partition.ts +++ /dev/null @@ -1,84 +0,0 @@ -const RECURSION_BREAKPOINT = 600; - -/** - * Implementation of Floyd-Rivest selection - * https://en.wikipedia.org/wiki/Floyd%E2%80%93Rivest_algorithm - * - * Performs an in place partition of an array of items, such that - * indices [0, k) contain the k smallest elements and all indices - * [k, array.length) are larger than all elements in [0, k) - * - * @param array - * @param k - * @param left - * @param right - * @param compare - */ -export function kSmallestPartition( - array: T[], - k: number, - left: number = 0, - right: number = array.length - 1, - compare: (a: T, b: T) => number = defaultCompare -) { - while (right > left) { - // Recursive sampling and partition of the set - if (right - left > RECURSION_BREAKPOINT) { - const n = right - left + 1; - const i = k - left + 1; - const z = Math.log(n); - const s = 0.5 * Math.exp((2 * z) / 3); - const sd = 0.5 * Math.sqrt((z * s * (n - s)) / n) * (i - n / 2 < 0 ? -1 : 1); - const newLeft = Math.max(left, Math.floor(k - (i * s) / n + sd)); - const newRight = Math.min(right, Math.floor(k + ((n - i) * s) / n + sd)); - kSmallestPartition(array, k, newLeft, newRight, compare); - } - - // Partition elements around t - const t = array[k]; - let i = left; - let j = right; - - swap(array, left, k); - if (compare(array[right], t) > 0) { - swap(array, left, right); - } - - while (i < j) { - swap(array, i, j); - i++; - j--; - while (compare(array[i], t) < 0) { - i++; - } - while (compare(array[j], t) > 0) { - j--; - } - } - - if (compare(array[left], t) === 0) { - swap(array, left, j); - } else { - j++; - swap(array, j, right); - } - - // Adjust boundaries of partitions - if (j <= k) { - left = j + 1; - } - if (k <= j) { - right = j - 1; - } - } -} - -function swap(arr: T[], i: number, j: number) { - const tmp = arr[i]; - arr[i] = arr[j]; - arr[j] = tmp; -} - -function defaultCompare(a: T, b: T) { - return a < b ? -1 : a > b ? 1 : 0; -} diff --git a/sdk/src/utils/math/swap-math.ts b/sdk/src/utils/math/swap-math.ts deleted file mode 100644 index d773304..0000000 --- a/sdk/src/utils/math/swap-math.ts +++ /dev/null @@ -1,114 +0,0 @@ -import BN from "bn.js"; -import { FEE_RATE_MUL_VALUE } from "../../types/public"; -import { BitMath } from "./bit-math"; -import { getAmountDeltaA, getAmountDeltaB, getNextSqrtPrice } from "./token-math"; - -export type SwapStep = { - amountIn: BN; - amountOut: BN; - nextPrice: BN; - feeAmount: BN; -}; - -export function computeSwapStep( - amountRemaining: BN, - feeRate: number, - currLiquidity: BN, - currSqrtPrice: BN, - targetSqrtPrice: BN, - amountSpecifiedIsInput: boolean, - aToB: boolean -): SwapStep { - let amountFixedDelta = getAmountFixedDelta( - currSqrtPrice, - targetSqrtPrice, - currLiquidity, - amountSpecifiedIsInput, - aToB - ); - - let amountCalc = amountRemaining; - if (amountSpecifiedIsInput) { - const result = BitMath.mulDiv( - amountRemaining, - FEE_RATE_MUL_VALUE.sub(new BN(feeRate)), - FEE_RATE_MUL_VALUE, - 128 - ); - amountCalc = result; - } - - let nextSqrtPrice = amountCalc.gte(amountFixedDelta) - ? targetSqrtPrice - : getNextSqrtPrice(currSqrtPrice, currLiquidity, amountCalc, amountSpecifiedIsInput, aToB); - - let isMaxSwap = nextSqrtPrice.eq(targetSqrtPrice); - - let amountUnfixedDelta = getAmountUnfixedDelta( - currSqrtPrice, - nextSqrtPrice, - currLiquidity, - amountSpecifiedIsInput, - aToB - ); - - if (!isMaxSwap) { - amountFixedDelta = getAmountFixedDelta( - currSqrtPrice, - nextSqrtPrice, - currLiquidity, - amountSpecifiedIsInput, - aToB - ); - } - - let amountIn = amountSpecifiedIsInput ? amountFixedDelta : amountUnfixedDelta; - let amountOut = amountSpecifiedIsInput ? amountUnfixedDelta : amountFixedDelta; - - if (!amountSpecifiedIsInput && amountOut.gt(amountRemaining)) { - amountOut = amountRemaining; - } - - let feeAmount: BN; - if (amountSpecifiedIsInput && !isMaxSwap) { - feeAmount = amountRemaining.sub(amountIn); - } else { - const feeRateBN = new BN(feeRate); - feeAmount = BitMath.mulDivRoundUp(amountIn, feeRateBN, FEE_RATE_MUL_VALUE.sub(feeRateBN), 128); - } - - return { - amountIn, - amountOut, - nextPrice: nextSqrtPrice, - feeAmount, - }; -} - -function getAmountFixedDelta( - currSqrtPrice: BN, - targetSqrtPrice: BN, - currLiquidity: BN, - amountSpecifiedIsInput: boolean, - aToB: boolean -) { - if (aToB === amountSpecifiedIsInput) { - return getAmountDeltaA(currSqrtPrice, targetSqrtPrice, currLiquidity, amountSpecifiedIsInput); - } else { - return getAmountDeltaB(currSqrtPrice, targetSqrtPrice, currLiquidity, amountSpecifiedIsInput); - } -} - -function getAmountUnfixedDelta( - currSqrtPrice: BN, - targetSqrtPrice: BN, - currLiquidity: BN, - amountSpecifiedIsInput: boolean, - aToB: boolean -) { - if (aToB === amountSpecifiedIsInput) { - return getAmountDeltaB(currSqrtPrice, targetSqrtPrice, currLiquidity, !amountSpecifiedIsInput); - } else { - return getAmountDeltaA(currSqrtPrice, targetSqrtPrice, currLiquidity, !amountSpecifiedIsInput); - } -} diff --git a/sdk/src/utils/math/token-math.ts b/sdk/src/utils/math/token-math.ts deleted file mode 100644 index 90ce669..0000000 --- a/sdk/src/utils/math/token-math.ts +++ /dev/null @@ -1,141 +0,0 @@ -import { Percentage, U64_MAX, ZERO } from "@orca-so/common-sdk"; -import BN from "bn.js"; -import { MathErrorCode, TokenErrorCode, WhirlpoolsError } from "../../errors/errors"; -import { MAX_SQRT_PRICE, MIN_SQRT_PRICE } from "../../types/public"; -import { BitMath } from "./bit-math"; - -export function getAmountDeltaA( - currSqrtPrice: BN, - targetSqrtPrice: BN, - currLiquidity: BN, - roundUp: boolean -): BN { - let [sqrtPriceLower, sqrtPriceUpper] = toIncreasingPriceOrder(currSqrtPrice, targetSqrtPrice); - let sqrtPriceDiff = sqrtPriceUpper.sub(sqrtPriceLower); - - let numerator = currLiquidity.mul(sqrtPriceDiff).shln(64); - let denominator = sqrtPriceLower.mul(sqrtPriceUpper); - - let quotient = numerator.div(denominator); - let remainder = numerator.mod(denominator); - - let result = roundUp && !remainder.eq(ZERO) ? quotient.add(new BN(1)) : quotient; - - if (result.gt(U64_MAX)) { - throw new WhirlpoolsError("Results larger than U64", TokenErrorCode.TokenMaxExceeded); - } - - return result; -} - -export function getAmountDeltaB( - currSqrtPrice: BN, - targetSqrtPrice: BN, - currLiquidity: BN, - roundUp: boolean -): BN { - let [sqrtPriceLower, sqrtPriceUpper] = toIncreasingPriceOrder(currSqrtPrice, targetSqrtPrice); - let sqrtPriceDiff = sqrtPriceUpper.sub(sqrtPriceLower); - return BitMath.checked_mul_shift_right_round_up_if(currLiquidity, sqrtPriceDiff, roundUp, 128); -} - -export function getNextSqrtPrice( - sqrtPrice: BN, - currLiquidity: BN, - amount: BN, - amountSpecifiedIsInput: boolean, - aToB: boolean -) { - if (amountSpecifiedIsInput === aToB) { - return getNextSqrtPriceFromARoundUp(sqrtPrice, currLiquidity, amount, amountSpecifiedIsInput); - } else { - return getNextSqrtPriceFromBRoundDown(sqrtPrice, currLiquidity, amount, amountSpecifiedIsInput); - } -} - -export function adjustForSlippage( - n: BN, - { numerator, denominator }: Percentage, - adjustUp: boolean -): BN { - if (adjustUp) { - return n.mul(denominator.add(numerator)).div(denominator); - } else { - return n.mul(denominator).div(denominator.add(numerator)); - } -} - -function toIncreasingPriceOrder(sqrtPrice0: BN, sqrtPrice1: BN) { - if (sqrtPrice0.gt(sqrtPrice1)) { - return [sqrtPrice1, sqrtPrice0]; - } else { - return [sqrtPrice0, sqrtPrice1]; - } -} - -function getNextSqrtPriceFromARoundUp( - sqrtPrice: BN, - currLiquidity: BN, - amount: BN, - amountSpecifiedIsInput: boolean -) { - if (amount.eq(ZERO)) { - return sqrtPrice; - } - - let p = BitMath.mul(sqrtPrice, amount, 256); - let numerator = BitMath.mul(currLiquidity, sqrtPrice, 256).shln(64); - if (BitMath.isOverLimit(numerator, 256)) { - throw new WhirlpoolsError( - "getNextSqrtPriceFromARoundUp - numerator overflow u256", - MathErrorCode.MultiplicationOverflow - ); - } - - let currLiquidityShiftLeft = currLiquidity.shln(64); - if (!amountSpecifiedIsInput && currLiquidityShiftLeft.lte(p)) { - throw new WhirlpoolsError( - "getNextSqrtPriceFromARoundUp - Unable to divide currLiquidityX64 by product", - MathErrorCode.DivideByZero - ); - } - - let denominator = amountSpecifiedIsInput - ? currLiquidityShiftLeft.add(p) - : currLiquidityShiftLeft.sub(p); - - let price = BitMath.divRoundUp(numerator, denominator); - - if (price.lt(new BN(MIN_SQRT_PRICE))) { - throw new WhirlpoolsError( - "getNextSqrtPriceFromARoundUp - price less than min sqrt price", - TokenErrorCode.TokenMinSubceeded - ); - } else if (price.gt(new BN(MAX_SQRT_PRICE))) { - throw new WhirlpoolsError( - "getNextSqrtPriceFromARoundUp - price less than max sqrt price", - TokenErrorCode.TokenMaxExceeded - ); - } - - return price; -} - -function getNextSqrtPriceFromBRoundDown( - sqrtPrice: BN, - currLiquidity: BN, - amount: BN, - amountSpecifiedIsInput: boolean -) { - let amountX64 = amount.shln(64); - - let delta = BitMath.divRoundUpIf(amountX64, currLiquidity, !amountSpecifiedIsInput); - - if (amountSpecifiedIsInput) { - sqrtPrice = sqrtPrice.add(delta); - } else { - sqrtPrice = sqrtPrice.sub(delta); - } - - return sqrtPrice; -} diff --git a/sdk/src/utils/position-util.ts b/sdk/src/utils/position-util.ts deleted file mode 100644 index e93beab..0000000 --- a/sdk/src/utils/position-util.ts +++ /dev/null @@ -1,250 +0,0 @@ -import { BN } from "@coral-xyz/anchor"; -import { MathUtil, Percentage } from "@orca-so/common-sdk"; -import { PriceMath } from "./public"; -import { - getLowerSqrtPriceFromTokenA, - getLowerSqrtPriceFromTokenB, - getUpperSqrtPriceFromTokenA, - getUpperSqrtPriceFromTokenB, -} from "./swap-utils"; - -export enum SwapDirection { - AtoB = "Swap A to B", - BtoA = "Swap B to A", -} - -export enum AmountSpecified { - Input = "Specified input amount", - Output = "Specified output amount", -} - -export enum PositionStatus { - BelowRange, - InRange, - AboveRange, -} - -export class PositionUtil { - private constructor() { } - - /** - * Returns the position status of a given tickCurrentIndex in relation to the tickLowerIndex and tickUpperIndex. - * If the tickCurrentIndex is below the range, it returns PositionStatus.BelowRange. - * If the tickCurrentIndex is above the range, it returns PositionStatus.AboveRange. - * If the tickCurrentIndex is equal to the lower, PositionStatus.InRange is returned. - * On the other hand, if the tickCurrentIndex is equal to the upper, PositionStatus.AboveRange is returned. - * The relation "PriceMath.tickIndexToSqrtPriceX64(tickCurrentIndex) <= pool's sqrtPrice" is the reason. - * - * @param tickCurrentIndex - Whirlpool's current tick index. - * @param tickLowerIndex - The tick specifying the lower end of the position range. - * @param tickUpperIndex - The tick specifying the upper end of the position range. - * @returns Position status in the form of PositionStatus enum. - */ - public static getPositionStatus( - tickCurrentIndex: number, - tickLowerIndex: number, - tickUpperIndex: number - ): PositionStatus { - if (tickCurrentIndex < tickLowerIndex) { - return PositionStatus.BelowRange; - } else if (tickCurrentIndex < tickUpperIndex) { - return PositionStatus.InRange; - } else { - return PositionStatus.AboveRange; - } - } - - /** - * Returns the position status of a given sqrtPriceX64 in relation to the tickLowerIndex and tickUpperIndex. - * If the sqrtPriceX64 is below the range, it returns PositionStatus.BelowRange. - * If the sqrtPriceX64 is above the range, it returns PositionStatus.AboveRange. - * If the sqrtPriceX64 is equal to the lower or upper, PositionStatus.BelowRange or PositionStatus.AboveRange is returned respectively. - * - * @param sqrtPriceX64 - X64 representation of the square root of the price. - * @param tickLowerIndex - The tick specifying the lower end of the position range. - * @param tickUpperIndex - The tick specifying the upper end of the position range. - * @returns Position status in the form of PositionStatus enum. - */ - public static getStrictPositionStatus( - sqrtPriceX64: BN, - tickLowerIndex: number, - tickUpperIndex: number - ): PositionStatus { - const sqrtPriceLowerX64 = PriceMath.tickIndexToSqrtPriceX64(tickLowerIndex); - const sqrtPriceUpperX64 = PriceMath.tickIndexToSqrtPriceX64(tickUpperIndex); - - if (sqrtPriceX64.lte(sqrtPriceLowerX64)) { - return PositionStatus.BelowRange; - } else if (sqrtPriceX64.gte(sqrtPriceUpperX64)) { - return PositionStatus.AboveRange; - } else { - return PositionStatus.InRange; - } - } -} - -export function adjustForSlippage( - n: BN, - { numerator, denominator }: Percentage, - adjustUp: boolean -): BN { - if (adjustUp) { - return n.mul(denominator.add(numerator)).div(denominator); - } else { - return n.mul(denominator).div(denominator.add(numerator)); - } -} - -export function adjustAmountForSlippage( - amountIn: BN, - amountOut: BN, - { numerator, denominator }: Percentage, - amountSpecified: AmountSpecified -): BN { - if (amountSpecified === AmountSpecified.Input) { - return amountOut.mul(denominator).div(denominator.add(numerator)); - } else { - return amountIn.mul(denominator.add(numerator)).div(denominator); - } -} - -export function getLiquidityFromTokenA( - amount: BN, - sqrtPriceLowerX64: BN, - sqrtPriceUpperX64: BN, - roundUp: boolean -) { - const result = amount - .mul(sqrtPriceLowerX64) - .mul(sqrtPriceUpperX64) - .div(sqrtPriceUpperX64.sub(sqrtPriceLowerX64)); - if (roundUp) { - return MathUtil.shiftRightRoundUp(result); - } else { - return result.shrn(64); - } -} - -export function getLiquidityFromTokenB( - amount: BN, - sqrtPriceLowerX64: BN, - sqrtPriceUpperX64: BN, - roundUp: boolean -) { - const numerator = amount.shln(64); - const denominator = sqrtPriceUpperX64.sub(sqrtPriceLowerX64); - if (roundUp) { - return MathUtil.divRoundUp(numerator, denominator); - } else { - return numerator.div(denominator); - } -} - -export function getAmountFixedDelta( - currentSqrtPriceX64: BN, - targetSqrtPriceX64: BN, - liquidity: BN, - amountSpecified: AmountSpecified, - swapDirection: SwapDirection -) { - if ((amountSpecified == AmountSpecified.Input) == (swapDirection == SwapDirection.AtoB)) { - return getTokenAFromLiquidity( - liquidity, - currentSqrtPriceX64, - targetSqrtPriceX64, - amountSpecified == AmountSpecified.Input - ); - } else { - return getTokenBFromLiquidity( - liquidity, - currentSqrtPriceX64, - targetSqrtPriceX64, - amountSpecified == AmountSpecified.Input - ); - } -} - -export function getAmountUnfixedDelta( - currentSqrtPriceX64: BN, - targetSqrtPriceX64: BN, - liquidity: BN, - amountSpecified: AmountSpecified, - swapDirection: SwapDirection -) { - if ((amountSpecified == AmountSpecified.Input) == (swapDirection == SwapDirection.AtoB)) { - return getTokenBFromLiquidity( - liquidity, - currentSqrtPriceX64, - targetSqrtPriceX64, - amountSpecified == AmountSpecified.Output - ); - } else { - return getTokenAFromLiquidity( - liquidity, - currentSqrtPriceX64, - targetSqrtPriceX64, - amountSpecified == AmountSpecified.Output - ); - } -} - -export function getNextSqrtPrice( - sqrtPriceX64: BN, - liquidity: BN, - amount: BN, - amountSpecified: AmountSpecified, - swapDirection: SwapDirection -) { - if (amountSpecified === AmountSpecified.Input && swapDirection === SwapDirection.AtoB) { - return getLowerSqrtPriceFromTokenA(amount, liquidity, sqrtPriceX64); - } else if (amountSpecified === AmountSpecified.Output && swapDirection === SwapDirection.BtoA) { - return getUpperSqrtPriceFromTokenA(amount, liquidity, sqrtPriceX64); - } else if (amountSpecified === AmountSpecified.Input && swapDirection === SwapDirection.BtoA) { - return getUpperSqrtPriceFromTokenB(amount, liquidity, sqrtPriceX64); - } else { - return getLowerSqrtPriceFromTokenB(amount, liquidity, sqrtPriceX64); - } -} - -export function getTokenAFromLiquidity( - liquidity: BN, - sqrtPrice0X64: BN, - sqrtPrice1X64: BN, - roundUp: boolean -) { - const [sqrtPriceLowerX64, sqrtPriceUpperX64] = orderSqrtPrice(sqrtPrice0X64, sqrtPrice1X64); - - const numerator = liquidity.mul(sqrtPriceUpperX64.sub(sqrtPriceLowerX64)).shln(64); - const denominator = sqrtPriceUpperX64.mul(sqrtPriceLowerX64); - if (roundUp) { - return MathUtil.divRoundUp(numerator, denominator); - } else { - return numerator.div(denominator); - } -} - -export function getTokenBFromLiquidity( - liquidity: BN, - sqrtPrice0X64: BN, - sqrtPrice1X64: BN, - roundUp: boolean -) { - const [sqrtPriceLowerX64, sqrtPriceUpperX64] = orderSqrtPrice(sqrtPrice0X64, sqrtPrice1X64); - - const result = liquidity.mul(sqrtPriceUpperX64.sub(sqrtPriceLowerX64)); - if (roundUp) { - return MathUtil.shiftRightRoundUp(result); - } else { - return result.shrn(64); - } -} - -/** Private */ - -function orderSqrtPrice(sqrtPrice0X64: BN, sqrtPrice1X64: BN): [BN, BN] { - if (sqrtPrice0X64.lt(sqrtPrice1X64)) { - return [sqrtPrice0X64, sqrtPrice1X64]; - } else { - return [sqrtPrice1X64, sqrtPrice0X64]; - } -} diff --git a/sdk/src/utils/public/index.ts b/sdk/src/utils/public/index.ts deleted file mode 100644 index 085ae49..0000000 --- a/sdk/src/utils/public/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -export * from "../graphs/public"; -export * from "./ix-utils"; -export * from "./pda-utils"; -export * from "./pool-utils"; -export * from "./position-bundle-util"; -export * from "./price-math"; -export * from "./swap-utils"; -export * from "./tick-utils"; -export * from "./types"; diff --git a/sdk/src/utils/public/ix-utils.ts b/sdk/src/utils/public/ix-utils.ts deleted file mode 100644 index 4941867..0000000 --- a/sdk/src/utils/public/ix-utils.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Instruction, TransactionBuilder } from "@orca-so/common-sdk"; -import { WhirlpoolContext } from "../../context"; - -export function toTx(ctx: WhirlpoolContext, ix: Instruction): TransactionBuilder { - return new TransactionBuilder( - ctx.provider.connection, - ctx.provider.wallet, - ctx.txBuilderOpts - ).addInstruction(ix); -} diff --git a/sdk/src/utils/public/pda-utils.ts b/sdk/src/utils/public/pda-utils.ts deleted file mode 100644 index 2028d32..0000000 --- a/sdk/src/utils/public/pda-utils.ts +++ /dev/null @@ -1,224 +0,0 @@ -import { BN } from "@coral-xyz/anchor"; -import { AddressUtil } from "@orca-so/common-sdk"; -import { PublicKey } from "@solana/web3.js"; -import { METADATA_PROGRAM_ADDRESS } from "../../types/public"; -import { PriceMath } from "./price-math"; -import { TickUtil } from "./tick-utils"; - -const PDA_WHIRLPOOL_SEED = "whirlpool"; -const PDA_POSITION_SEED = "position"; -const PDA_METADATA_SEED = "metadata"; -const PDA_TICK_ARRAY_SEED = "tick_array"; -const PDA_FEE_TIER_SEED = "fee_tier"; -const PDA_ORACLE_SEED = "oracle"; -const PDA_POSITION_BUNDLE_SEED = "position_bundle"; -const PDA_BUNDLED_POSITION_SEED = "bundled_position"; - -/** - * @category Whirlpool Utils - */ -export class PDAUtil { - /** - * - * @param programId - * @param whirlpoolsConfigKey - * @param tokenMintAKey - * @param tokenMintBKey - * @param tickSpacing - * @returns - */ - public static getWhirlpool( - programId: PublicKey, - whirlpoolsConfigKey: PublicKey, - tokenMintAKey: PublicKey, - tokenMintBKey: PublicKey, - tickSpacing: number - ) { - return AddressUtil.findProgramAddress( - [ - Buffer.from(PDA_WHIRLPOOL_SEED), - whirlpoolsConfigKey.toBuffer(), - tokenMintAKey.toBuffer(), - tokenMintBKey.toBuffer(), - new BN(tickSpacing).toArrayLike(Buffer, "le", 2), - ], - programId - ); - } - - /** - * @category Program Derived Addresses - * @param programId - * @param positionMintKey - * @returns - */ - public static getPosition(programId: PublicKey, positionMintKey: PublicKey) { - return AddressUtil.findProgramAddress( - [Buffer.from(PDA_POSITION_SEED), positionMintKey.toBuffer()], - programId - ); - } - - /** - * @category Program Derived Addresses - * @param positionMintKey - * @returns - */ - public static getPositionMetadata(positionMintKey: PublicKey) { - return AddressUtil.findProgramAddress( - [ - Buffer.from(PDA_METADATA_SEED), - METADATA_PROGRAM_ADDRESS.toBuffer(), - positionMintKey.toBuffer(), - ], - METADATA_PROGRAM_ADDRESS - ); - } - - /** - * @category Program Derived Addresses - * @param programId - * @param whirlpoolAddress - * @param startTick - * @returns - */ - public static getTickArray(programId: PublicKey, whirlpoolAddress: PublicKey, startTick: number) { - return AddressUtil.findProgramAddress( - [ - Buffer.from(PDA_TICK_ARRAY_SEED), - whirlpoolAddress.toBuffer(), - Buffer.from(startTick.toString()), - ], - programId - ); - } - - /** - * Get the PDA of the tick array containing tickIndex. - * tickArrayOffset can be used to get neighboring tick arrays. - * - * @param tickIndex - * @param tickSpacing - * @param whirlpool - * @param programId - * @param tickArrayOffset - * @returns - */ - public static getTickArrayFromTickIndex( - tickIndex: number, - tickSpacing: number, - whirlpool: PublicKey, - programId: PublicKey, - tickArrayOffset = 0 - ) { - const startIndex = TickUtil.getStartTickIndex(tickIndex, tickSpacing, tickArrayOffset); - return PDAUtil.getTickArray( - AddressUtil.toPubKey(programId), - AddressUtil.toPubKey(whirlpool), - startIndex - ); - } - - public static getTickArrayFromSqrtPrice( - sqrtPriceX64: BN, - tickSpacing: number, - whirlpool: PublicKey, - programId: PublicKey, - tickArrayOffset = 0 - ) { - const tickIndex = PriceMath.sqrtPriceX64ToTickIndex(sqrtPriceX64); - return PDAUtil.getTickArrayFromTickIndex( - tickIndex, - tickSpacing, - whirlpool, - programId, - tickArrayOffset - ); - } - - /** - * @category Program Derived Addresses - * @param programId - * @param whirlpoolsConfigAddress - * @param tickSpacing - * @returns - */ - public static getFeeTier( - programId: PublicKey, - whirlpoolsConfigAddress: PublicKey, - tickSpacing: number - ) { - return AddressUtil.findProgramAddress( - [ - Buffer.from(PDA_FEE_TIER_SEED), - whirlpoolsConfigAddress.toBuffer(), - new BN(tickSpacing).toArrayLike(Buffer, "le", 2), - ], - programId - ); - } - - /** - * @category Program Derived Addresses - * @param programId - * @param whirlpoolAddress - * @returns - */ - public static getOracle(programId: PublicKey, whirlpoolAddress: PublicKey) { - return AddressUtil.findProgramAddress( - [Buffer.from(PDA_ORACLE_SEED), whirlpoolAddress.toBuffer()], - programId - ); - } - - /** - * @category Program Derived Addresses - * @param programId - * @param positionBundleMintKey - * @param bundleIndex - * @returns - */ - public static getBundledPosition( - programId: PublicKey, - positionBundleMintKey: PublicKey, - bundleIndex: number - ) { - return AddressUtil.findProgramAddress( - [ - Buffer.from(PDA_BUNDLED_POSITION_SEED), - positionBundleMintKey.toBuffer(), - Buffer.from(bundleIndex.toString()), - ], - programId - ); - } - - /** - * @category Program Derived Addresses - * @param programId - * @param positionBundleMintKey - * @returns - */ - public static getPositionBundle(programId: PublicKey, positionBundleMintKey: PublicKey) { - return AddressUtil.findProgramAddress( - [Buffer.from(PDA_POSITION_BUNDLE_SEED), positionBundleMintKey.toBuffer()], - programId - ); - } - - /** - * @category Program Derived Addresses - * @param positionBundleMintKey - * @returns - */ - public static getPositionBundleMetadata(positionBundleMintKey: PublicKey) { - return AddressUtil.findProgramAddress( - [ - Buffer.from(PDA_METADATA_SEED), - METADATA_PROGRAM_ADDRESS.toBuffer(), - positionBundleMintKey.toBuffer(), - ], - METADATA_PROGRAM_ADDRESS - ); - } -} diff --git a/sdk/src/utils/public/pool-utils.ts b/sdk/src/utils/public/pool-utils.ts deleted file mode 100644 index 9c70a1b..0000000 --- a/sdk/src/utils/public/pool-utils.ts +++ /dev/null @@ -1,250 +0,0 @@ -import { Address } from "@coral-xyz/anchor"; -import { AddressUtil, MathUtil, Percentage } from "@orca-so/common-sdk"; -import { PublicKey } from "@solana/web3.js"; -import BN from "bn.js"; -import Decimal from "decimal.js"; -import { WhirlpoolData, WhirlpoolRewardInfoData } from "../../types/public"; -import { TOKEN_MINTS } from "../constants"; -import { PriceMath } from "./price-math"; -import { TokenType } from "./types"; - -/** - * @category Whirlpool Utils - */ -export class PoolUtil { - private constructor() {} - - public static isRewardInitialized(rewardInfo: WhirlpoolRewardInfoData): boolean { - return ( - !PublicKey.default.equals(rewardInfo.mint) && !PublicKey.default.equals(rewardInfo.vault) - ); - } - - /** - * Return the corresponding token type (TokenA/B) for this mint key for a Whirlpool. - * - * @param pool The Whirlpool to evaluate the mint against - * @param mint The token mint PublicKey - * @returns The match result in the form of TokenType enum. undefined if the token mint is not part of the trade pair of the pool. - */ - public static getTokenType(pool: WhirlpoolData, mint: PublicKey): TokenType | undefined { - if (pool.tokenMintA.equals(mint)) { - return TokenType.TokenA; - } else if (pool.tokenMintB.equals(mint)) { - return TokenType.TokenB; - } - return undefined; - } - - public static getFeeRate(feeRate: number): Percentage { - /** - * Smart Contract comment: https://github.com/orca-so/whirlpool/blob/main/programs/whirlpool/src/state/whirlpool.rs#L9-L11 - * // Stored as hundredths of a basis point - * // u16::MAX corresponds to ~6.5% - * pub fee_rate: u16, - */ - return Percentage.fromFraction(feeRate, 1e6); // TODO - } - - public static getProtocolFeeRate(protocolFeeRate: number): Percentage { - /** - * Smart Contract comment: https://github.com/orca-so/whirlpool/blob/main/programs/whirlpool/src/state/whirlpool.rs#L13-L14 - * // Stored as a basis point - * pub protocol_fee_rate: u16, - */ - return Percentage.fromFraction(protocolFeeRate, 1e4); // TODO - } - - public static orderMints(mintX: Address, mintY: Address): [Address, Address] { - return this.compareMints(mintX, mintY) < 0 ? [mintX, mintY] : [mintY, mintX]; - } - - public static compareMints(mintX: Address, mintY: Address): number { - return Buffer.compare( - AddressUtil.toPubKey(mintX).toBuffer(), - AddressUtil.toPubKey(mintY).toBuffer() - ); - } - - /** - * @category Whirlpool Utils - * @param liquidity - * @param currentSqrtPrice - * @param lowerSqrtPrice - * @param upperSqrtPrice - * @param round_up - * @returns - */ - public static getTokenAmountsFromLiquidity( - liquidity: BN, - currentSqrtPrice: BN, - lowerSqrtPrice: BN, - upperSqrtPrice: BN, - round_up: boolean - ): TokenAmounts { - const _liquidity = new Decimal(liquidity.toString()); - const _currentPrice = new Decimal(currentSqrtPrice.toString()); - const _lowerPrice = new Decimal(lowerSqrtPrice.toString()); - const _upperPrice = new Decimal(upperSqrtPrice.toString()); - let tokenA, tokenB; - if (currentSqrtPrice.lt(lowerSqrtPrice)) { - // x = L * (pb - pa) / (pa * pb) - tokenA = MathUtil.toX64_Decimal(_liquidity) - .mul(_upperPrice.sub(_lowerPrice)) - .div(_lowerPrice.mul(_upperPrice)); - tokenB = new Decimal(0); - } else if (currentSqrtPrice.lt(upperSqrtPrice)) { - // x = L * (pb - p) / (p * pb) - // y = L * (p - pa) - tokenA = MathUtil.toX64_Decimal(_liquidity) - .mul(_upperPrice.sub(_currentPrice)) - .div(_currentPrice.mul(_upperPrice)); - tokenB = MathUtil.fromX64_Decimal(_liquidity.mul(_currentPrice.sub(_lowerPrice))); - } else { - // y = L * (pb - pa) - tokenA = new Decimal(0); - tokenB = MathUtil.fromX64_Decimal(_liquidity.mul(_upperPrice.sub(_lowerPrice))); - } - - // TODO: round up - if (round_up) { - return { - tokenA: new BN(tokenA.ceil().toString()), - tokenB: new BN(tokenB.ceil().toString()), - }; - } else { - return { - tokenA: new BN(tokenA.floor().toString()), - tokenB: new BN(tokenB.floor().toString()), - }; - } - } - - /** - * Estimate the liquidity amount required to increase/decrease liquidity. - * - * // TODO: At the top end of the price range, tick calcuation is off therefore the results can be off - * - * @category Whirlpool Utils - * @param currTick - Whirlpool's current tick index (aka price) - * @param lowerTick - Position lower tick index - * @param upperTick - Position upper tick index - * @param tokenAmount - The desired amount of tokens to deposit/withdraw - * @returns An estimated amount of liquidity needed to deposit/withdraw the desired amount of tokens. - */ - public static estimateLiquidityFromTokenAmounts( - currTick: number, - lowerTick: number, - upperTick: number, - tokenAmount: TokenAmounts - ): BN { - if (upperTick < lowerTick) { - throw new Error("upper tick cannot be lower than the lower tick"); - } - - const currSqrtPrice = PriceMath.tickIndexToSqrtPriceX64(currTick); - const lowerSqrtPrice = PriceMath.tickIndexToSqrtPriceX64(lowerTick); - const upperSqrtPrice = PriceMath.tickIndexToSqrtPriceX64(upperTick); - - if (currTick >= upperTick) { - return estLiquidityForTokenB(upperSqrtPrice, lowerSqrtPrice, tokenAmount.tokenB); - } else if (currTick < lowerTick) { - return estLiquidityForTokenA(lowerSqrtPrice, upperSqrtPrice, tokenAmount.tokenA); - } else { - const estLiquidityAmountA = estLiquidityForTokenA( - currSqrtPrice, - upperSqrtPrice, - tokenAmount.tokenA - ); - const estLiquidityAmountB = estLiquidityForTokenB( - currSqrtPrice, - lowerSqrtPrice, - tokenAmount.tokenB - ); - return BN.min(estLiquidityAmountA, estLiquidityAmountB); - } - } - - /** - * Given an arbitrary pair of token mints, this function returns an ordering of the token mints - * in the format [base, quote]. USD based stable coins are prioritized as the quote currency - * followed by variants of SOL. - * - * @category Whirlpool Utils - * @param tokenMintAKey - The mint of token A in the token pair. - * @param tokenMintBKey - The mint of token B in the token pair. - * @returns A two-element array with the tokens sorted in the order of [baseToken, quoteToken]. - */ - public static toBaseQuoteOrder( - tokenMintAKey: PublicKey, - tokenMintBKey: PublicKey - ): [PublicKey, PublicKey] { - const pair: [PublicKey, PublicKey] = [tokenMintAKey, tokenMintBKey]; - return pair.sort(sortByQuotePriority); - } -} - -/** - * @category Whirlpool Utils - */ -export type TokenAmounts = { - tokenA: BN; - tokenB: BN; -}; - -/** - * @category Whirlpool Utils - */ -export function toTokenAmount(a: number, b: number): TokenAmounts { - return { - tokenA: new BN(a.toString()), - tokenB: new BN(b.toString()), - }; -} - -// These are the token mints that will be prioritized as the second token in the pair (quote). -// The number that the mint maps to determines the priority that it will be used as the quote -// currency. -const QUOTE_TOKENS: { [mint: string]: number } = { - [TOKEN_MINTS["USDT"]]: 100, - [TOKEN_MINTS["USDC"]]: 90, // USDC - [TOKEN_MINTS["USDH"]]: 80, // USDH - [TOKEN_MINTS["SOL"]]: 70, // SOL - [TOKEN_MINTS["mSOL"]]: 60, // mSOL - [TOKEN_MINTS["stSOL"]]: 50, // stSOL -}; - -const DEFAULT_QUOTE_PRIORITY = 0; - -function getQuoteTokenPriority(mint: string): number { - const value = QUOTE_TOKENS[mint]; - if (value) { - return value; - } - return DEFAULT_QUOTE_PRIORITY; -} - -function sortByQuotePriority(mintLeft: PublicKey, mintRight: PublicKey): number { - return getQuoteTokenPriority(mintLeft.toString()) - getQuoteTokenPriority(mintRight.toString()); -} - -// Convert this function based on Delta A = Delta L * (1/sqrt(lower) - 1/sqrt(upper)) -function estLiquidityForTokenA(sqrtPrice1: BN, sqrtPrice2: BN, tokenAmount: BN) { - const lowerSqrtPriceX64 = BN.min(sqrtPrice1, sqrtPrice2); - const upperSqrtPriceX64 = BN.max(sqrtPrice1, sqrtPrice2); - - const num = MathUtil.fromX64_BN(tokenAmount.mul(upperSqrtPriceX64).mul(lowerSqrtPriceX64)); - const dem = upperSqrtPriceX64.sub(lowerSqrtPriceX64); - - return num.div(dem); -} - -// Convert this function based on Delta B = Delta L * (sqrt_price(upper) - sqrt_price(lower)) -function estLiquidityForTokenB(sqrtPrice1: BN, sqrtPrice2: BN, tokenAmount: BN) { - const lowerSqrtPriceX64 = BN.min(sqrtPrice1, sqrtPrice2); - const upperSqrtPriceX64 = BN.max(sqrtPrice1, sqrtPrice2); - - const delta = upperSqrtPriceX64.sub(lowerSqrtPriceX64); - - return tokenAmount.shln(64).div(delta); -} diff --git a/sdk/src/utils/public/position-bundle-util.ts b/sdk/src/utils/public/position-bundle-util.ts deleted file mode 100644 index b5c6d5d..0000000 --- a/sdk/src/utils/public/position-bundle-util.ts +++ /dev/null @@ -1,125 +0,0 @@ -import invariant from "tiny-invariant"; -import { PositionBundleData, POSITION_BUNDLE_SIZE } from "../../types/public"; - -/** - * A collection of utility functions when interacting with a PositionBundle. - * @category Whirlpool Utils - */ -export class PositionBundleUtil { - private constructor() {} - - /** - * Check if the bundle index is in the correct range. - * - * @param bundleIndex The bundle index to be checked - * @returns true if bundle index is in the correct range - */ - public static checkBundleIndexInBounds(bundleIndex: number): boolean { - return bundleIndex >= 0 && bundleIndex < POSITION_BUNDLE_SIZE; - } - - /** - * Check if the Bundled Position corresponding to the bundle index has been opened. - * - * @param positionBundle The position bundle to be checked - * @param bundleIndex The bundle index to be checked - * @returns true if Bundled Position has been opened - */ - public static isOccupied(positionBundle: PositionBundleData, bundleIndex: number): boolean { - invariant(PositionBundleUtil.checkBundleIndexInBounds(bundleIndex), "bundleIndex out of range"); - const array = PositionBundleUtil.convertBitmapToArray(positionBundle); - return array[bundleIndex]; - } - - /** - * Check if the Bundled Position corresponding to the bundle index has not been opened. - * - * @param positionBundle The position bundle to be checked - * @param bundleIndex The bundle index to be checked - * @returns true if Bundled Position has not been opened - */ - public static isUnoccupied(positionBundle: PositionBundleData, bundleIndex: number): boolean { - return !PositionBundleUtil.isOccupied(positionBundle, bundleIndex); - } - - /** - * Check if all bundle index is occupied. - * - * @param positionBundle The position bundle to be checked - * @returns true if all bundle index is occupied - */ - public static isFull(positionBundle: PositionBundleData): boolean { - const unoccupied = PositionBundleUtil.getUnoccupiedBundleIndexes(positionBundle); - return unoccupied.length === 0; - } - - /** - * Check if all bundle index is unoccupied. - * - * @param positionBundle The position bundle to be checked - * @returns true if all bundle index is unoccupied - */ - public static isEmpty(positionBundle: PositionBundleData): boolean { - const occupied = PositionBundleUtil.getOccupiedBundleIndexes(positionBundle); - return occupied.length === 0; - } - - /** - * Get all bundle indexes where the corresponding Bundled Position is open. - * - * @param positionBundle The position bundle to be checked - * @returns The array of bundle index where the corresponding Bundled Position is open - */ - public static getOccupiedBundleIndexes(positionBundle: PositionBundleData): number[] { - const result: number[] = []; - PositionBundleUtil.convertBitmapToArray(positionBundle).forEach((occupied, index) => { - if (occupied) { - result.push(index); - } - }); - return result; - } - - /** - * Get all bundle indexes where the corresponding Bundled Position is not open. - * - * @param positionBundle The position bundle to be checked - * @returns The array of bundle index where the corresponding Bundled Position is not open - */ - public static getUnoccupiedBundleIndexes(positionBundle: PositionBundleData): number[] { - const result: number[] = []; - PositionBundleUtil.convertBitmapToArray(positionBundle).forEach((occupied, index) => { - if (!occupied) { - result.push(index); - } - }); - return result; - } - - /** - * Get the first unoccupied bundle index in the position bundle. - * - * @param positionBundle The position bundle to be checked - * @returns The first unoccupied bundle index, null if the position bundle is full - */ - public static findUnoccupiedBundleIndex(positionBundle: PositionBundleData): number | null { - const unoccupied = PositionBundleUtil.getUnoccupiedBundleIndexes(positionBundle); - return unoccupied.length === 0 ? null : unoccupied[0]; - } - - /** - * Convert position bitmap to the array of boolean which represent if Bundled Position is open. - * - * @param positionBundle The position bundle whose bitmap will be converted - * @returns The array of boolean representing if Bundled Position is open - */ - public static convertBitmapToArray(positionBundle: PositionBundleData): boolean[] { - const result: boolean[] = []; - positionBundle.positionBitmap.map((bitmap) => { - for (let offset = 0; offset < 8; offset++) { - result.push((bitmap & (1 << offset)) !== 0); - } - }); - return result; - } -} diff --git a/sdk/src/utils/public/price-math.ts b/sdk/src/utils/public/price-math.ts deleted file mode 100644 index cbcf557..0000000 --- a/sdk/src/utils/public/price-math.ts +++ /dev/null @@ -1,350 +0,0 @@ -import { BN } from "@coral-xyz/anchor"; -import { DecimalUtil, MathUtil, Percentage } from "@orca-so/common-sdk"; -import Decimal from "decimal.js"; -import { - MAX_SQRT_PRICE, - MAX_SQRT_PRICE_BN, - MIN_SQRT_PRICE, - MIN_SQRT_PRICE_BN, -} from "../../types/public"; -import { TickUtil } from "./tick-utils"; - -const BIT_PRECISION = 14; -const LOG_B_2_X32 = "59543866431248"; -const LOG_B_P_ERR_MARGIN_LOWER_X64 = "184467440737095516"; -const LOG_B_P_ERR_MARGIN_UPPER_X64 = "15793534762490258745"; - -/** - * A collection of utility functions to convert between price, tickIndex and sqrtPrice. - * - * @category Whirlpool Utils - */ -export class PriceMath { - public static priceToSqrtPriceX64(price: Decimal, decimalsA: number, decimalsB: number): BN { - return MathUtil.toX64(price.mul(Decimal.pow(10, decimalsB - decimalsA)).sqrt()); - } - - public static sqrtPriceX64ToPrice( - sqrtPriceX64: BN, - decimalsA: number, - decimalsB: number, - ): Decimal { - return MathUtil.fromX64(sqrtPriceX64) - .pow(2) - .mul(Decimal.pow(10, decimalsA - decimalsB)); - } - - /** - * @param tickIndex - * @returns - */ - public static tickIndexToSqrtPriceX64(tickIndex: number): BN { - if (tickIndex > 0) { - return new BN(tickIndexToSqrtPricePositive(tickIndex)); - } else { - return new BN(tickIndexToSqrtPriceNegative(tickIndex)); - } - } - - /** - * - * @param sqrtPriceX64 - * @returns - */ - public static sqrtPriceX64ToTickIndex(sqrtPriceX64: BN): number { - if (sqrtPriceX64.gt(new BN(MAX_SQRT_PRICE)) || sqrtPriceX64.lt(new BN(MIN_SQRT_PRICE))) { - throw new Error("Provided sqrtPrice is not within the supported sqrtPrice range."); - } - - const msb = sqrtPriceX64.bitLength() - 1; - const adjustedMsb = new BN(msb - 64); - const log2pIntegerX32 = signedShiftLeft(adjustedMsb, 32, 128); - - let bit = new BN("8000000000000000", "hex"); - let precision = 0; - let log2pFractionX64 = new BN(0); - - let r = msb >= 64 ? sqrtPriceX64.shrn(msb - 63) : sqrtPriceX64.shln(63 - msb); - - while (bit.gt(new BN(0)) && precision < BIT_PRECISION) { - r = r.mul(r); - let rMoreThanTwo = r.shrn(127); - r = r.shrn(63 + rMoreThanTwo.toNumber()); - log2pFractionX64 = log2pFractionX64.add(bit.mul(rMoreThanTwo)); - bit = bit.shrn(1); - precision += 1; - } - - const log2pFractionX32 = log2pFractionX64.shrn(32); - - const log2pX32 = log2pIntegerX32.add(log2pFractionX32); - const logbpX64 = log2pX32.mul(new BN(LOG_B_2_X32)); - - const tickLow = signedShiftRight( - logbpX64.sub(new BN(LOG_B_P_ERR_MARGIN_LOWER_X64)), - 64, - 128, - ).toNumber(); - const tickHigh = signedShiftRight( - logbpX64.add(new BN(LOG_B_P_ERR_MARGIN_UPPER_X64)), - 64, - 128, - ).toNumber(); - - if (tickLow == tickHigh) { - return tickLow; - } else { - const derivedTickHighSqrtPriceX64 = PriceMath.tickIndexToSqrtPriceX64(tickHigh); - if (derivedTickHighSqrtPriceX64.lte(sqrtPriceX64)) { - return tickHigh; - } else { - return tickLow; - } - } - } - - public static tickIndexToPrice(tickIndex: number, decimalsA: number, decimalsB: number): Decimal { - return PriceMath.sqrtPriceX64ToPrice( - PriceMath.tickIndexToSqrtPriceX64(tickIndex), - decimalsA, - decimalsB, - ); - } - - public static priceToTickIndex(price: Decimal, decimalsA: number, decimalsB: number): number { - return PriceMath.sqrtPriceX64ToTickIndex( - PriceMath.priceToSqrtPriceX64(price, decimalsA, decimalsB), - ); - } - - public static priceToInitializableTickIndex( - price: Decimal, - decimalsA: number, - decimalsB: number, - tickSpacing: number, - ): number { - return TickUtil.getInitializableTickIndex( - PriceMath.priceToTickIndex(price, decimalsA, decimalsB), - tickSpacing, - ); - } - - /** - * Utility to invert the price Pb/Pa to Pa/Pb - * NOTE: precision is lost in this conversion - * - * @param price Pb / Pa - * @param decimalsA Decimals of original token A (i.e. token A in the given Pb / Pa price) - * @param decimalsB Decimals of original token B (i.e. token B in the given Pb / Pa price) - * @returns inverted price, i.e. Pa / Pb - */ - public static invertPrice(price: Decimal, decimalsA: number, decimalsB: number): Decimal { - const tick = PriceMath.priceToTickIndex(price, decimalsA, decimalsB); - const invTick = TickUtil.invertTick(tick); - return PriceMath.tickIndexToPrice(invTick, decimalsB, decimalsA); - } - - /** - * Utility to invert the sqrtPriceX64 from X64 repr. of sqrt(Pb/Pa) to X64 repr. of sqrt(Pa/Pb) - * NOTE: precision is lost in this conversion - * - * @param sqrtPriceX64 X64 representation of sqrt(Pb / Pa) - * @returns inverted sqrtPriceX64, i.e. X64 representation of sqrt(Pa / Pb) - */ - public static invertSqrtPriceX64(sqrtPriceX64: BN): BN { - const tick = PriceMath.sqrtPriceX64ToTickIndex(sqrtPriceX64); - const invTick = TickUtil.invertTick(tick); - return PriceMath.tickIndexToSqrtPriceX64(invTick); - } - - /** - * Calculate the sqrtPriceX64 & tick index slippage price boundary for a given price and slippage. - * Note: This function loses precision - * - * @param sqrtPriceX64 the sqrtPriceX64 to apply the slippage on - * @param slippage the slippage to apply onto the sqrtPriceX64 - * @returns the sqrtPriceX64 & tick index slippage price boundary - */ - public static getSlippageBoundForSqrtPrice( - sqrtPriceX64: BN, - slippage: Percentage, - ): { lowerBound: [BN, number]; upperBound: [BN, number] } { - const sqrtPriceX64Decimal = DecimalUtil.fromBN(sqrtPriceX64); - const slippageNumerator = new Decimal(slippage.numerator.toString()); - const slippageDenominator = new Decimal(slippage.denominator.toString()); - const lowerBoundSqrtPriceDecimal = sqrtPriceX64Decimal - .mul(slippageDenominator.sub(slippageNumerator).sqrt()) - .div(slippageDenominator.sqrt()) - .toDecimalPlaces(0); - const upperBoundSqrtPriceDecimal = sqrtPriceX64Decimal - .mul(slippageDenominator.add(slippageNumerator).sqrt()) - .div(slippageDenominator.sqrt()) - .toDecimalPlaces(0); - - const lowerBoundSqrtPrice = BN.min( - BN.max(new BN(lowerBoundSqrtPriceDecimal.toString()), MIN_SQRT_PRICE_BN), - MAX_SQRT_PRICE_BN, - ); - const upperBoundSqrtPrice = BN.min( - BN.max(new BN(upperBoundSqrtPriceDecimal.toString()), MIN_SQRT_PRICE_BN), - MAX_SQRT_PRICE_BN, - ); - - const lowerTickCurrentIndex = PriceMath.sqrtPriceX64ToTickIndex(lowerBoundSqrtPrice); - const upperTickCurrentIndex = PriceMath.sqrtPriceX64ToTickIndex(upperBoundSqrtPrice); - - return { - lowerBound: [lowerBoundSqrtPrice, lowerTickCurrentIndex], - upperBound: [upperBoundSqrtPrice, upperTickCurrentIndex], - }; - } -} - -// Private Functions - -function tickIndexToSqrtPricePositive(tick: number) { - let ratio: BN; - - if ((tick & 1) != 0) { - ratio = new BN("79232123823359799118286999567"); - } else { - ratio = new BN("79228162514264337593543950336"); - } - - if ((tick & 2) != 0) { - ratio = signedShiftRight(ratio.mul(new BN("79236085330515764027303304731")), 96, 256); - } - if ((tick & 4) != 0) { - ratio = signedShiftRight(ratio.mul(new BN("79244008939048815603706035061")), 96, 256); - } - if ((tick & 8) != 0) { - ratio = signedShiftRight(ratio.mul(new BN("79259858533276714757314932305")), 96, 256); - } - if ((tick & 16) != 0) { - ratio = signedShiftRight(ratio.mul(new BN("79291567232598584799939703904")), 96, 256); - } - if ((tick & 32) != 0) { - ratio = signedShiftRight(ratio.mul(new BN("79355022692464371645785046466")), 96, 256); - } - if ((tick & 64) != 0) { - ratio = signedShiftRight(ratio.mul(new BN("79482085999252804386437311141")), 96, 256); - } - if ((tick & 128) != 0) { - ratio = signedShiftRight(ratio.mul(new BN("79736823300114093921829183326")), 96, 256); - } - if ((tick & 256) != 0) { - ratio = signedShiftRight(ratio.mul(new BN("80248749790819932309965073892")), 96, 256); - } - if ((tick & 512) != 0) { - ratio = signedShiftRight(ratio.mul(new BN("81282483887344747381513967011")), 96, 256); - } - if ((tick & 1024) != 0) { - ratio = signedShiftRight(ratio.mul(new BN("83390072131320151908154831281")), 96, 256); - } - if ((tick & 2048) != 0) { - ratio = signedShiftRight(ratio.mul(new BN("87770609709833776024991924138")), 96, 256); - } - if ((tick & 4096) != 0) { - ratio = signedShiftRight(ratio.mul(new BN("97234110755111693312479820773")), 96, 256); - } - if ((tick & 8192) != 0) { - ratio = signedShiftRight(ratio.mul(new BN("119332217159966728226237229890")), 96, 256); - } - if ((tick & 16384) != 0) { - ratio = signedShiftRight(ratio.mul(new BN("179736315981702064433883588727")), 96, 256); - } - if ((tick & 32768) != 0) { - ratio = signedShiftRight(ratio.mul(new BN("407748233172238350107850275304")), 96, 256); - } - if ((tick & 65536) != 0) { - ratio = signedShiftRight(ratio.mul(new BN("2098478828474011932436660412517")), 96, 256); - } - if ((tick & 131072) != 0) { - ratio = signedShiftRight(ratio.mul(new BN("55581415166113811149459800483533")), 96, 256); - } - if ((tick & 262144) != 0) { - ratio = signedShiftRight(ratio.mul(new BN("38992368544603139932233054999993551")), 96, 256); - } - - return signedShiftRight(ratio, 32, 256); -} - -function tickIndexToSqrtPriceNegative(tickIndex: number) { - let tick = Math.abs(tickIndex); - let ratio: BN; - - if ((tick & 1) != 0) { - ratio = new BN("18445821805675392311"); - } else { - ratio = new BN("18446744073709551616"); - } - - if ((tick & 2) != 0) { - ratio = signedShiftRight(ratio.mul(new BN("18444899583751176498")), 64, 256); - } - if ((tick & 4) != 0) { - ratio = signedShiftRight(ratio.mul(new BN("18443055278223354162")), 64, 256); - } - if ((tick & 8) != 0) { - ratio = signedShiftRight(ratio.mul(new BN("18439367220385604838")), 64, 256); - } - if ((tick & 16) != 0) { - ratio = signedShiftRight(ratio.mul(new BN("18431993317065449817")), 64, 256); - } - if ((tick & 32) != 0) { - ratio = signedShiftRight(ratio.mul(new BN("18417254355718160513")), 64, 256); - } - if ((tick & 64) != 0) { - ratio = signedShiftRight(ratio.mul(new BN("18387811781193591352")), 64, 256); - } - if ((tick & 128) != 0) { - ratio = signedShiftRight(ratio.mul(new BN("18329067761203520168")), 64, 256); - } - if ((tick & 256) != 0) { - ratio = signedShiftRight(ratio.mul(new BN("18212142134806087854")), 64, 256); - } - if ((tick & 512) != 0) { - ratio = signedShiftRight(ratio.mul(new BN("17980523815641551639")), 64, 256); - } - if ((tick & 1024) != 0) { - ratio = signedShiftRight(ratio.mul(new BN("17526086738831147013")), 64, 256); - } - if ((tick & 2048) != 0) { - ratio = signedShiftRight(ratio.mul(new BN("16651378430235024244")), 64, 256); - } - if ((tick & 4096) != 0) { - ratio = signedShiftRight(ratio.mul(new BN("15030750278693429944")), 64, 256); - } - if ((tick & 8192) != 0) { - ratio = signedShiftRight(ratio.mul(new BN("12247334978882834399")), 64, 256); - } - if ((tick & 16384) != 0) { - ratio = signedShiftRight(ratio.mul(new BN("8131365268884726200")), 64, 256); - } - if ((tick & 32768) != 0) { - ratio = signedShiftRight(ratio.mul(new BN("3584323654723342297")), 64, 256); - } - if ((tick & 65536) != 0) { - ratio = signedShiftRight(ratio.mul(new BN("696457651847595233")), 64, 256); - } - if ((tick & 131072) != 0) { - ratio = signedShiftRight(ratio.mul(new BN("26294789957452057")), 64, 256); - } - if ((tick & 262144) != 0) { - ratio = signedShiftRight(ratio.mul(new BN("37481735321082")), 64, 256); - } - - return ratio; -} - -function signedShiftLeft(n0: BN, shiftBy: number, bitWidth: number) { - let twosN0 = n0.toTwos(bitWidth).shln(shiftBy); - twosN0.imaskn(bitWidth + 1); - return twosN0.fromTwos(bitWidth); -} - -function signedShiftRight(n0: BN, shiftBy: number, bitWidth: number) { - let twoN0 = n0.toTwos(bitWidth).shrn(shiftBy); - twoN0.imaskn(bitWidth - shiftBy + 1); - return twoN0.fromTwos(bitWidth - shiftBy); -} diff --git a/sdk/src/utils/public/swap-utils.ts b/sdk/src/utils/public/swap-utils.ts deleted file mode 100644 index 96bc95e..0000000 --- a/sdk/src/utils/public/swap-utils.ts +++ /dev/null @@ -1,287 +0,0 @@ -import { Address } from "@coral-xyz/anchor"; -import { AddressUtil, Percentage, U64_MAX, ZERO } from "@orca-so/common-sdk"; -import { PublicKey } from "@solana/web3.js"; -import BN from "bn.js"; -import { WhirlpoolContext } from "../.."; -import { - WhirlpoolAccountFetchOptions, - WhirlpoolAccountFetcherInterface, -} from "../../network/public/fetcher"; -import { - MAX_SQRT_PRICE, - MAX_SWAP_TICK_ARRAYS, - MIN_SQRT_PRICE, - SwapInput, - SwapParams, - TickArray, - WhirlpoolData, -} from "../../types/public"; -import { Whirlpool } from "../../whirlpool-client"; -import { adjustForSlippage } from "../math/token-math"; -import { PDAUtil } from "./pda-utils"; -import { PoolUtil } from "./pool-utils"; -import { TickUtil } from "./tick-utils"; -import { SwapDirection, TokenType } from "./types"; - -/** - * A request to fetch the tick-arrays that a swap may traverse across. - * @category Whirlpool Utils - */ -export interface TickArrayRequest { - whirlpoolAddress: PublicKey; - aToB: boolean; - tickCurrentIndex: number; - tickSpacing: number; -} - -/** - * @category Whirlpool Utils - */ -export class SwapUtils { - /** - * Get the default values for the sqrtPriceLimit parameter in a swap. - * @param aToB - The direction of a swap - * @returns The default values for the sqrtPriceLimit parameter in a swap. - */ - public static getDefaultSqrtPriceLimit(aToB: boolean) { - return new BN(aToB ? MIN_SQRT_PRICE : MAX_SQRT_PRICE); - } - - /** - * Get the default values for the otherAmountThreshold parameter in a swap. - * @param amountSpecifiedIsInput - The direction of a swap - * @returns The default values for the otherAmountThreshold parameter in a swap. - */ - public static getDefaultOtherAmountThreshold(amountSpecifiedIsInput: boolean) { - return amountSpecifiedIsInput ? ZERO : U64_MAX; - } - - /** - * Given the intended token mint to swap, return the swap direction of a swap for a Whirlpool - * @param pool The Whirlpool to evaluate the mint against - * @param swapTokenMint The token mint PublicKey the user bases their swap against - * @param swapTokenIsInput Whether the swap token is the input token. (similar to amountSpecifiedIsInput from swap Ix) - * @returns The direction of the swap given the swapTokenMint. undefined if the token mint is not part of the trade pair of the pool. - */ - public static getSwapDirection( - pool: WhirlpoolData, - swapTokenMint: PublicKey, - swapTokenIsInput: boolean - ): SwapDirection | undefined { - const tokenType = PoolUtil.getTokenType(pool, swapTokenMint); - if (!tokenType) { - return undefined; - } - - return (tokenType === TokenType.TokenA) === swapTokenIsInput - ? SwapDirection.AtoB - : SwapDirection.BtoA; - } - - /** - * Given the current tick-index, returns the dervied PDA and fetched data - * for the tick-arrays that this swap may traverse across. - * - * @category Whirlpool Utils - * @param tickCurrentIndex - The current tickIndex for the Whirlpool to swap on. - * @param tickSpacing - The tickSpacing for the Whirlpool. - * @param aToB - The direction of the trade. - * @param programId - The Whirlpool programId which the Whirlpool lives on. - * @param whirlpoolAddress - PublicKey of the whirlpool to swap on. - * @returns An array of PublicKey[] for the tickArray accounts that this swap may traverse across. - */ - public static getTickArrayPublicKeys( - tickCurrentIndex: number, - tickSpacing: number, - aToB: boolean, - programId: PublicKey, - whirlpoolAddress: PublicKey - ) { - const shift = aToB ? 0 : tickSpacing; - - let offset = 0; - let tickArrayAddresses: PublicKey[] = []; - for (let i = 0; i < MAX_SWAP_TICK_ARRAYS; i++) { - let startIndex: number; - try { - startIndex = TickUtil.getStartTickIndex(tickCurrentIndex + shift, tickSpacing, offset); - } catch { - return tickArrayAddresses; - } - - const pda = PDAUtil.getTickArray(programId, whirlpoolAddress, startIndex); - tickArrayAddresses.push(pda.publicKey); - offset = aToB ? offset - 1 : offset + 1; - } - - return tickArrayAddresses; - } - - /** - * Given the current tick-index, returns TickArray objects that this swap may traverse across. - * - * @category Whirlpool Utils - * @param tickCurrentIndex - The current tickIndex for the Whirlpool to swap on. - * @param tickSpacing - The tickSpacing for the Whirlpool. - * @param aToB - The direction of the trade. - * @param programId - The Whirlpool programId which the Whirlpool lives on. - * @param whirlpoolAddress - PublicKey of the whirlpool to swap on. - * @param cache - WhirlpoolAccountCacheInterface object to fetch solana accounts - * @param opts an {@link WhirlpoolAccountFetchOptions} object to define fetch and cache options when accessing on-chain accounts - * @returns An array of PublicKey[] for the tickArray accounts that this swap may traverse across. - */ - public static async getTickArrays( - tickCurrentIndex: number, - tickSpacing: number, - aToB: boolean, - programId: PublicKey, - whirlpoolAddress: PublicKey, - fetcher: WhirlpoolAccountFetcherInterface, - opts?: WhirlpoolAccountFetchOptions - ): Promise { - const data = await this.getBatchTickArrays( - programId, - fetcher, - [{ tickCurrentIndex, tickSpacing, aToB, whirlpoolAddress }], - opts - ); - return data[0]; - } - - /** - * Fetch a batch of tick-arrays for a set of TA requests. - * @param programId - The Whirlpool programId which the Whirlpool lives on. - * @param cache - WhirlpoolAccountCacheInterface instance to fetch solana accounts - * @param tickArrayRequests - An array of {@link TickArrayRequest} of tick-arrays to request for. - * @param opts an {@link WhirlpoolAccountFetchOptions} object to define fetch and cache options when accessing on-chain accounts - * @returns A array of request indicies mapped to an array of resulting PublicKeys. - */ - public static async getBatchTickArrays( - programId: PublicKey, - fetcher: WhirlpoolAccountFetcherInterface, - tickArrayRequests: TickArrayRequest[], - opts?: WhirlpoolAccountFetchOptions - ): Promise { - let addresses: PublicKey[] = []; - let requestToIndices = []; - - // Each individual tick array request may correspond to more than one tick array - // so we map each request to a slice of the batch request - for (let i = 0; i < tickArrayRequests.length; i++) { - const { tickCurrentIndex, tickSpacing, aToB, whirlpoolAddress } = tickArrayRequests[i]; - const requestAddresses = SwapUtils.getTickArrayPublicKeys( - tickCurrentIndex, - tickSpacing, - aToB, - programId, - whirlpoolAddress - ); - requestToIndices.push([addresses.length, addresses.length + requestAddresses.length]); - addresses.push(...requestAddresses); - } - const data = await fetcher.getTickArrays(addresses, opts); - - // Re-map from flattened batch data to TickArray[] for request - return requestToIndices.map((indices) => { - const [start, end] = indices; - const addressSlice = addresses.slice(start, end); - const dataSlice = data.slice(start, end); - return addressSlice.map((addr, index) => ({ - address: addr, - data: dataSlice[index], - })); - }); - } - - /** - * Calculate the SwapInput parameters `amount` & `otherAmountThreshold` based on the amountIn & amountOut estimates from a quote. - * @param amount - The amount of tokens the user wanted to swap from. - * @param estAmountIn - The estimated amount of input tokens expected in a `SwapQuote` - * @param estAmountOut - The estimated amount of output tokens expected from a `SwapQuote` - * @param slippageTolerance - The amount of slippage to adjust for. - * @param amountSpecifiedIsInput - Specifies the token the parameter `amount`represents in the swap quote. If true, the amount represents - * the input token of the swap. - * @returns A Partial `SwapInput` object containing the slippage adjusted 'amount' & 'otherAmountThreshold' parameters. - */ - public static calculateSwapAmountsFromQuote( - amount: BN, - estAmountIn: BN, - estAmountOut: BN, - slippageTolerance: Percentage, - amountSpecifiedIsInput: boolean - ): Pick { - if (amountSpecifiedIsInput) { - return { - amount, - otherAmountThreshold: adjustForSlippage(estAmountOut, slippageTolerance, false), - }; - } else { - return { - amount, - otherAmountThreshold: adjustForSlippage(estAmountIn, slippageTolerance, true), - }; - } - } - - /** - * Convert a quote object and WhirlpoolClient's {@link Whirlpool} object into a {@link SwapParams} type - * to be plugged into {@link WhirlpoolIx.swapIx}. - * - * @param quote - A {@link SwapQuote} type generated from {@link swapQuoteWithParams} - * @param ctx - {@link WhirlpoolContext} - * @param whirlpool - A {@link Whirlpool} object from WhirlpoolClient - * @param inputTokenAssociatedAddress - The public key for the ATA of the input token in the swap - * @param outputTokenAssociatedAddress - The public key for the ATA of the input token in the swap - * @param wallet - The token authority for this swap - * @returns A converted {@link SwapParams} generated from the input - */ - public static getSwapParamsFromQuote( - quote: SwapInput, - ctx: WhirlpoolContext, - whirlpool: Whirlpool, - inputTokenAssociatedAddress: Address, - outputTokenAssociatedAddress: Address, - wallet: PublicKey - ) { - const data = whirlpool.getData(); - return this.getSwapParamsFromQuoteKeys( - quote, - ctx, - whirlpool.getAddress(), - data.tokenVaultA, - data.tokenVaultB, - inputTokenAssociatedAddress, - outputTokenAssociatedAddress, - wallet - ); - } - - public static getSwapParamsFromQuoteKeys( - quote: SwapInput, - ctx: WhirlpoolContext, - whirlpool: PublicKey, - tokenVaultA: PublicKey, - tokenVaultB: PublicKey, - inputTokenAssociatedAddress: Address, - outputTokenAssociatedAddress: Address, - wallet: PublicKey - ) { - const aToB = quote.aToB; - const [inputTokenATA, outputTokenATA] = AddressUtil.toPubKeys([ - inputTokenAssociatedAddress, - outputTokenAssociatedAddress, - ]); - const oraclePda = PDAUtil.getOracle(ctx.program.programId, whirlpool); - const params: SwapParams = { - whirlpool, - tokenOwnerAccountA: aToB ? inputTokenATA : outputTokenATA, - tokenOwnerAccountB: aToB ? outputTokenATA : inputTokenATA, - tokenVaultA, - tokenVaultB, - oracle: oraclePda.publicKey, - tokenAuthority: wallet, - ...quote, - }; - return params; - } -} diff --git a/sdk/src/utils/public/tick-utils.ts b/sdk/src/utils/public/tick-utils.ts deleted file mode 100644 index 0fd63a5..0000000 --- a/sdk/src/utils/public/tick-utils.ts +++ /dev/null @@ -1,338 +0,0 @@ -import { Address } from "@coral-xyz/anchor"; -import { AddressUtil, PDA } from "@orca-so/common-sdk"; -import { PublicKey } from "@solana/web3.js"; -import invariant from "tiny-invariant"; -import { - WhirlpoolAccountFetchOptions, - WhirlpoolAccountFetcherInterface, -} from "../../network/public/fetcher"; -import { - MAX_TICK_INDEX, - MIN_TICK_INDEX, - TICK_ARRAY_SIZE, - TickArrayData, - TickData, -} from "../../types/public"; -import { PDAUtil } from "./pda-utils"; - -enum TickSearchDirection { - Left, - Right, -} - -/** - * A collection of utility functions when interacting with Ticks. - * @category Whirlpool Utils - */ -export class TickUtil { - private constructor() {} - - /** - * Get the offset index to access a tick at a given tick-index in a tick-array - * - * @param tickIndex The tick index for the tick that this offset would access - * @param arrayStartIndex The starting tick for the array that this tick-index resides in - * @param tickSpacing The tickSpacing for the Whirlpool that this tickArray belongs to - * @returns The offset index that can access the desired tick at the given tick-array - */ - public static getOffsetIndex(tickIndex: number, arrayStartIndex: number, tickSpacing: number) { - return Math.floor((tickIndex - arrayStartIndex) / tickSpacing); - } - - /** - * Get the startIndex of the tick array containing tickIndex. - * - * @param tickIndex - * @param tickSpacing - * @param offset can be used to get neighboring tick array startIndex. - * @returns - */ - public static getStartTickIndex(tickIndex: number, tickSpacing: number, offset = 0): number { - const realIndex = Math.floor(tickIndex / tickSpacing / TICK_ARRAY_SIZE); - const startTickIndex = (realIndex + offset) * tickSpacing * TICK_ARRAY_SIZE; - - const ticksInArray = TICK_ARRAY_SIZE * tickSpacing; - const minTickIndex = MIN_TICK_INDEX - ((MIN_TICK_INDEX % ticksInArray) + ticksInArray); - invariant(startTickIndex >= minTickIndex, `startTickIndex is too small - - ${startTickIndex}`); - invariant(startTickIndex <= MAX_TICK_INDEX, `startTickIndex is too large - ${startTickIndex}`); - return startTickIndex; - } - - /** - * Get the nearest (rounding down) valid tick index from the tickIndex. - * A valid tick index is a point on the tick spacing grid line. - */ - public static getInitializableTickIndex(tickIndex: number, tickSpacing: number): number { - return tickIndex - (tickIndex % tickSpacing); - } - - public static getNextInitializableTickIndex(tickIndex: number, tickSpacing: number) { - return TickUtil.getInitializableTickIndex(tickIndex, tickSpacing) + tickSpacing; - } - - public static getPrevInitializableTickIndex(tickIndex: number, tickSpacing: number) { - return TickUtil.getInitializableTickIndex(tickIndex, tickSpacing) - tickSpacing; - } - - /** - * Get the previous initialized tick index within the same tick array. - * - * @param account - * @param currentTickIndex - * @param tickSpacing - * @returns - */ - public static findPreviousInitializedTickIndex( - account: TickArrayData, - currentTickIndex: number, - tickSpacing: number - ): number | null { - return TickUtil.findInitializedTick( - account, - currentTickIndex, - tickSpacing, - TickSearchDirection.Left - ); - } - - /** - * Get the next initialized tick index within the same tick array. - * @param account - * @param currentTickIndex - * @param tickSpacing - * @returns - */ - public static findNextInitializedTickIndex( - account: TickArrayData, - currentTickIndex: number, - tickSpacing: number - ): number | null { - return TickUtil.findInitializedTick( - account, - currentTickIndex, - tickSpacing, - TickSearchDirection.Right - ); - } - - private static findInitializedTick( - account: TickArrayData, - currentTickIndex: number, - tickSpacing: number, - searchDirection: TickSearchDirection - ): number | null { - const currentTickArrayIndex = tickIndexToInnerIndex( - account.startTickIndex, - currentTickIndex, - tickSpacing - ); - - const increment = searchDirection === TickSearchDirection.Right ? 1 : -1; - - let stepInitializedTickArrayIndex = - searchDirection === TickSearchDirection.Right - ? currentTickArrayIndex + increment - : currentTickArrayIndex; - while ( - stepInitializedTickArrayIndex >= 0 && - stepInitializedTickArrayIndex < account.ticks.length - ) { - if (account.ticks[stepInitializedTickArrayIndex]?.initialized) { - return innerIndexToTickIndex( - account.startTickIndex, - stepInitializedTickArrayIndex, - tickSpacing - ); - } - - stepInitializedTickArrayIndex += increment; - } - - return null; - } - - public static checkTickInBounds(tick: number) { - return tick <= MAX_TICK_INDEX && tick >= MIN_TICK_INDEX; - } - - public static isTickInitializable(tick: number, tickSpacing: number) { - return tick % tickSpacing === 0; - } - - /** - * - * Returns the tick 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 - * @param tick The tick to invert - * @returns - */ - public static invertTick(tick: number) { - return -tick; - } - - /** - * Get the minimum and maximum tick index that can be initialized. - * - * @param tickSpacing The tickSpacing for the Whirlpool - * @returns An array of numbers where the first element is the minimum tick index and the second element is the maximum tick index. - */ - public static getFullRangeTickIndex(tickSpacing: number): [number, number] { - return [ - Math.ceil(MIN_TICK_INDEX / tickSpacing) * tickSpacing, - Math.floor(MAX_TICK_INDEX / tickSpacing) * tickSpacing, - ]; - } - - /** - * Check if the tick range is the full range of the Whirlpool. - * @param tickSpacing The tickSpacing for the Whirlpool - * @param tickLowerIndex The lower tick index of the range - * @param tickUpperIndex The upper tick index of the range - * @returns true if the range is the full range of the Whirlpool, false otherwise. - */ - public static isFullRange(tickSpacing: number, tickLowerIndex: number, tickUpperIndex: number): boolean { - const [min, max] = TickUtil.getFullRangeTickIndex(tickSpacing); - return tickLowerIndex === min && tickUpperIndex === max; - } -} - -/** - * A collection of utility functions when interacting with a TickArray. - * @category Whirlpool Utils - */ -export class TickArrayUtil { - /** - * Get the tick from tickArray with a global tickIndex. - */ - public static getTickFromArray( - tickArray: TickArrayData, - tickIndex: number, - tickSpacing: number - ): TickData { - const realIndex = tickIndexToInnerIndex(tickArray.startTickIndex, tickIndex, tickSpacing); - const tick = tickArray.ticks[realIndex]; - invariant( - !!tick, - `tick realIndex out of range - start - ${tickArray.startTickIndex} index - ${tickIndex}, realIndex - ${realIndex}` - ); - return tick; - } - - /** - * Return a sequence of tick array pdas based on the sequence start index. - * @param tick - A tick in the first tick-array of your sequence - * @param tickSpacing - Tick spacing for the whirlpool - * @param numOfTickArrays - The number of TickArray PDAs to generate - * @param programId - Program Id of the whirlpool for these tick-arrays - * @param whirlpoolAddress - Address for the Whirlpool for these tick-arrays - * @returns TickArray PDAs for the sequence` - */ - public static getTickArrayPDAs( - tick: number, - tickSpacing: number, - numOfTickArrays: number, - programId: PublicKey, - whirlpoolAddress: PublicKey, - aToB: boolean - ): PDA[] { - let arrayIndexList = [...Array(numOfTickArrays).keys()]; - if (aToB) { - arrayIndexList = arrayIndexList.map((value) => -value); - } - return arrayIndexList.map((value) => { - const startTick = TickUtil.getStartTickIndex(tick, tickSpacing, value); - return PDAUtil.getTickArray(programId, whirlpoolAddress, startTick); - }); - } - - /** - * Return a string containing all of the uninitialized arrays in the provided addresses. - * Useful for creating error messages. - * - * @param tickArrayAddrs - A list of tick-array addresses to verify. - * @param cache - {@link WhirlpoolAccountFetcherInterface} - * @param opts an {@link WhirlpoolAccountFetchOptions} object to define fetch and cache options when accessing on-chain accounts - * @returns A string of all uninitialized tick array addresses, delimited by ",". Falsy value if all arrays are initialized. - */ - public static async getUninitializedArraysString( - tickArrayAddrs: Address[], - fetcher: WhirlpoolAccountFetcherInterface, - opts?: WhirlpoolAccountFetchOptions - ) { - const taAddrs = AddressUtil.toPubKeys(tickArrayAddrs); - const tickArrayData = await fetcher.getTickArrays(taAddrs, opts); - - // Verify tick arrays are initialized if the user provided them. - if (tickArrayData) { - const uninitializedIndices = TickArrayUtil.getUninitializedArrays(tickArrayData); - if (uninitializedIndices.length > 0) { - const uninitializedArrays = uninitializedIndices - .map((index) => taAddrs[index].toBase58()) - .join(", "); - - return uninitializedArrays; - } - } - - return null; - } - - public static async getUninitializedArraysPDAs( - ticks: number[], - programId: PublicKey, - whirlpoolAddress: PublicKey, - tickSpacing: number, - fetcher: WhirlpoolAccountFetcherInterface, - opts: WhirlpoolAccountFetchOptions - ) { - const startTicks = ticks.map((tick) => TickUtil.getStartTickIndex(tick, tickSpacing)); - const removeDupeTicks = [...new Set(startTicks)]; - const tickArrayPDAs = removeDupeTicks.map((tick) => - PDAUtil.getTickArray(programId, whirlpoolAddress, tick) - ); - const fetchedArrays = await fetcher.getTickArrays( - tickArrayPDAs.map((pda) => pda.publicKey), - opts - ); - const uninitializedIndices = TickArrayUtil.getUninitializedArrays(fetchedArrays); - return uninitializedIndices.map((index) => { - return { - startIndex: removeDupeTicks[index], - pda: tickArrayPDAs[index], - }; - }); - } - - /** - * Evaluate a list of tick-array data and return the array of indices which the tick-arrays are not initialized. - * @param tickArrays - a list of TickArrayData or null objects from WhirlpoolAccountCacheInterface.getTickArrays - * @returns an array of array-index for the input tickArrays that requires initialization. - */ - public static getUninitializedArrays(tickArrays: readonly (TickArrayData | null)[]): number[] { - return tickArrays - .map((value, index) => { - if (!value) { - return index; - } - return -1; - }) - .filter((index) => index >= 0); - } -} - -function tickIndexToInnerIndex( - startTickIndex: number, - tickIndex: number, - tickSpacing: number -): number { - return Math.floor((tickIndex - startTickIndex) / tickSpacing); -} - -function innerIndexToTickIndex( - startTickIndex: number, - tickArrayIndex: number, - tickSpacing: number -): number { - return startTickIndex + tickArrayIndex * tickSpacing; -} diff --git a/sdk/src/utils/public/types.ts b/sdk/src/utils/public/types.ts deleted file mode 100644 index a84ec58..0000000 --- a/sdk/src/utils/public/types.ts +++ /dev/null @@ -1,17 +0,0 @@ -/** - * An enum for the direction of a swap. - * @category Whirlpool Utils - */ -export enum SwapDirection { - AtoB = "aToB", - BtoA = "bToA", -} - -/** - * An enum for the token type in a Whirlpool. - * @category Whirlpool Utils - */ -export enum TokenType { - TokenA = 1, - TokenB, -} diff --git a/sdk/src/utils/spl-token-utils.ts b/sdk/src/utils/spl-token-utils.ts deleted file mode 100644 index a311501..0000000 --- a/sdk/src/utils/spl-token-utils.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { NATIVE_MINT } from "@solana/spl-token"; -import { PublicKey } from "@solana/web3.js"; - -export function isNativeMint(mint: PublicKey) { - return mint.equals(NATIVE_MINT); -} diff --git a/sdk/src/utils/swap-utils.ts b/sdk/src/utils/swap-utils.ts deleted file mode 100644 index 3088ed0..0000000 --- a/sdk/src/utils/swap-utils.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { MathUtil } from "@orca-so/common-sdk"; -import BN from "bn.js"; - -export function getLowerSqrtPriceFromTokenA(amount: BN, liquidity: BN, sqrtPriceX64: BN): BN { - const numerator = liquidity.mul(sqrtPriceX64).shln(64); - const denominator = liquidity.shln(64).add(amount.mul(sqrtPriceX64)); - - // always round up - return MathUtil.divRoundUp(numerator, denominator); -} - -export function getUpperSqrtPriceFromTokenA(amount: BN, liquidity: BN, sqrtPriceX64: BN): BN { - const numerator = liquidity.mul(sqrtPriceX64).shln(64); - const denominator = liquidity.shln(64).sub(amount.mul(sqrtPriceX64)); - - // always round up - return MathUtil.divRoundUp(numerator, denominator); -} - -export function getLowerSqrtPriceFromTokenB(amount: BN, liquidity: BN, sqrtPriceX64: BN): BN { - // always round down - return sqrtPriceX64.sub(MathUtil.divRoundUp(amount.shln(64), liquidity)); -} - -export function getUpperSqrtPriceFromTokenB(amount: BN, liquidity: BN, sqrtPriceX64: BN): BN { - // always round down (rounding up a negative number) - return sqrtPriceX64.add(amount.shln(64).div(liquidity)); -} diff --git a/sdk/src/utils/txn-utils.ts b/sdk/src/utils/txn-utils.ts deleted file mode 100644 index d2c5e62..0000000 --- a/sdk/src/utils/txn-utils.ts +++ /dev/null @@ -1,73 +0,0 @@ -import { - TransactionBuilder, - TransactionBuilderOptions, - defaultTransactionBuilderOptions, -} from "@orca-so/common-sdk"; -import { WhirlpoolContext, WhirlpoolContextOpts as WhirlpoolContextOptions } from ".."; - -export function convertListToMap(fetchedData: T[], addresses: string[]): Record { - const result: Record = {}; - fetchedData.forEach((data, index) => { - if (data) { - const addr = addresses[index]; - result[addr] = data; - } - }); - return result; -} - -// Filter out null objects in the first array and remove the corresponding objects in the second array -export function filterNullObjects( - firstArray: ReadonlyArray, - secondArray: ReadonlyArray -): [Array, Array] { - const filteredFirstArray: Array = []; - const filteredSecondArray: Array = []; - - firstArray.forEach((item, idx) => { - if (item !== null) { - filteredFirstArray.push(item); - filteredSecondArray.push(secondArray[idx]); - } - }); - - return [filteredFirstArray, filteredSecondArray]; -} - -export async function checkMergedTransactionSizeIsValid( - ctx: WhirlpoolContext, - builders: TransactionBuilder[], - latestBlockhash: Readonly<{ - blockhash: string; - lastValidBlockHeight: number; - }> -): Promise { - const merged = new TransactionBuilder(ctx.connection, ctx.wallet, ctx.txBuilderOpts); - builders.forEach((builder) => merged.addInstruction(builder.compressIx(true))); - try { - const size = await merged.txnSize({ - latestBlockhash, - }); - return true; - } catch (e) { - return false; - } -} - -export function contextOptionsToBuilderOptions( - opts: WhirlpoolContextOptions -): TransactionBuilderOptions | undefined { - return { - defaultBuildOption: { - ...defaultTransactionBuilderOptions.defaultBuildOption, - ...opts.userDefaultBuildOptions, - }, - defaultSendOption: { - ...defaultTransactionBuilderOptions.defaultSendOption, - ...opts.userDefaultSendOptions, - }, - defaultConfirmationCommitment: - opts.userDefaultConfirmCommitment ?? - defaultTransactionBuilderOptions.defaultConfirmationCommitment, - }; -} diff --git a/sdk/src/utils/wallet-utils.ts b/sdk/src/utils/wallet-utils.ts deleted file mode 100644 index 2148b2f..0000000 --- a/sdk/src/utils/wallet-utils.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Wallet } from "@orca-so/common-sdk"; -import { PublicKey } from "@solana/web3.js"; - -/** - * Checks if a wallet is connected. - * @category Whirlpool Utils - * @param wallet The wallet to check. - * @returns True if the wallet is connected, false otherwise. - */ -export function isWalletConnected(wallet: Wallet | null): boolean { - return wallet !== null && !wallet.publicKey.equals(PublicKey.default); -} diff --git a/sdk/src/utils/whirlpool-ata-utils.ts b/sdk/src/utils/whirlpool-ata-utils.ts deleted file mode 100644 index 440d942..0000000 --- a/sdk/src/utils/whirlpool-ata-utils.ts +++ /dev/null @@ -1,185 +0,0 @@ -import { - Instruction, - TokenUtil, - TransactionBuilder, - ZERO, - resolveOrCreateATAs, - WrappedSolAccountCreateMethod, -} from "@orca-so/common-sdk"; -import { NATIVE_MINT } from "@solana/spl-token"; -import { PublicKey } from "@solana/web3.js"; -import { PoolUtil, WhirlpoolContext } from ".."; -import { WhirlpoolData } from "../types/public"; -import { convertListToMap } from "./txn-utils"; - -export enum TokenMintTypes { - ALL = "ALL", - POOL_ONLY = "POOL_ONLY", - REWARD_ONLY = "REWARDS_ONLY", -} - -export type WhirlpoolsTokenMints = { - mintMap: PublicKey[]; - hasNativeMint: boolean; -}; - -/** - * Fetch a list of affliated tokens from a list of whirlpools - * - * SOL tokens does not use the ATA program and therefore not handled. - * @param whirlpoolDatas An array of whirlpoolData (from fetcher.listPools) - * @param mintTypes The set of mints to collect from these whirlpools - * @returns All the whirlpool, reward token mints in the given set of whirlpools - */ -export function getTokenMintsFromWhirlpools( - whirlpoolDatas: (WhirlpoolData | null)[], - mintTypes = TokenMintTypes.ALL -): WhirlpoolsTokenMints { - let hasNativeMint = false; - const mints = Array.from( - whirlpoolDatas.reduce>((accu, whirlpoolData) => { - if (whirlpoolData) { - if (mintTypes === TokenMintTypes.ALL || mintTypes === TokenMintTypes.POOL_ONLY) { - const { tokenMintA, tokenMintB } = whirlpoolData; - // TODO: Once we move to sync-native for wSOL wrapping, we can simplify and use wSOL ATA instead of a custom token account. - if (!TokenUtil.isNativeMint(tokenMintA)) { - accu.add(tokenMintA.toBase58()); - } else { - hasNativeMint = true; - } - - if (!TokenUtil.isNativeMint(tokenMintB)) { - accu.add(tokenMintB.toBase58()); - } else { - hasNativeMint = true; - } - } - - if (mintTypes === TokenMintTypes.ALL || mintTypes === TokenMintTypes.REWARD_ONLY) { - const rewardInfos = whirlpoolData.rewardInfos; - rewardInfos.forEach((reward) => { - if (TokenUtil.isNativeMint(reward.mint)) { - hasNativeMint = true; - } - if (PoolUtil.isRewardInitialized(reward)) { - accu.add(reward.mint.toBase58()); - } - }); - } - } - return accu; - }, new Set()) - ).map((mint) => new PublicKey(mint)); - - return { - mintMap: mints, - hasNativeMint, - }; -} - -/** - * Parameters to resolve ATAs for affliated tokens in a list of Whirlpools - * - * @category Instruction Types - * @param mints - The list of mints to generate affliated tokens for. - * @param accountExemption - The value from the most recent getMinimumBalanceForRentExemption(). - * @param destinationWallet - the wallet to generate ATAs against - * @param payer - The payer address that would pay for the creation of ATA addresses - */ -export type ResolveAtaInstructionParams = { - mints: PublicKey[]; - accountExemption: number; - receiver?: PublicKey; - payer?: PublicKey; -}; - -/** - * An interface of mapping between tokenMint & ATA & the instruction set to initialize them. - * - * @category Instruction Types - * @param ataTokenAddresses - A record between the token mint & generated ATA addresses - * @param resolveAtaIxs - An array of instructions to initialize all uninitialized ATA token accounts for the list above. - */ -export type ResolvedATAInstructionSet = { - ataTokenAddresses: Record; - resolveAtaIxs: Instruction[]; -}; - -/** - * Build instructions to resolve ATAs (Associated Tokens Addresses) for affliated tokens in a list of Whirlpools. - * Affliated tokens are tokens that are part of the trade pair or reward in a Whirlpool. - * - * @param ctx - WhirlpoolContext object for the current environment. - * @param params - ResolveAtaInstructionParams - * @returns a ResolvedTokenAddressesIxSet containing the derived ATA addresses & ix set to initialize the accounts. - */ -export async function resolveAtaForMints( - ctx: WhirlpoolContext, - params: ResolveAtaInstructionParams -): Promise { - const { mints, receiver, payer, accountExemption } = params; - const receiverKey = receiver ?? ctx.wallet.publicKey; - const payerKey = payer ?? ctx.wallet.publicKey; - - const resolvedAtaResults = await resolveOrCreateATAs( - ctx.connection, - receiverKey, - mints.map((tokenMint) => { - return { tokenMint }; - }), - async () => accountExemption, - payerKey, - undefined, // use default - ctx.accountResolverOpts.allowPDAOwnerAddress, - ctx.accountResolverOpts.createWrappedSolAccountMethod - ); - - // Convert the results back into the specified format - const { resolveAtaIxs, resolvedAtas } = resolvedAtaResults.reduce<{ - resolvedAtas: PublicKey[]; - resolveAtaIxs: Instruction[]; - }>( - (accu, curr) => { - const { address, ...ix } = curr; - accu.resolvedAtas.push(address); - - // TODO: common-sdk needs to have an easier way to check for empty instruction - if (ix.instructions.length) { - accu.resolveAtaIxs.push(ix); - } - return accu; - }, - { resolvedAtas: [], resolveAtaIxs: [] } - ); - - const affliatedTokenAtaMap = convertListToMap( - resolvedAtas, - mints.map((mint) => mint.toBase58()) - ); - return { - ataTokenAddresses: affliatedTokenAtaMap, - resolveAtaIxs, - }; -} - -/** - * Add native WSOL mint handling to a transaction builder. - */ -export function addNativeMintHandlingIx( - txBuilder: TransactionBuilder, - affliatedTokenAtaMap: Record, - destinationWallet: PublicKey, - accountExemption: number, - createAccountMethod: WrappedSolAccountCreateMethod -) { - let { address: wSOLAta, ...resolveWSolIx } = TokenUtil.createWrappedNativeAccountInstruction( - destinationWallet, - ZERO, - accountExemption, - undefined, // use default - undefined, // use default - createAccountMethod - ); - affliatedTokenAtaMap[NATIVE_MINT.toBase58()] = wSOLAta; - txBuilder.prependInstruction(resolveWSolIx); -} diff --git a/sdk/src/whirlpool-client.ts b/sdk/src/whirlpool-client.ts deleted file mode 100644 index d24b11a..0000000 --- a/sdk/src/whirlpool-client.ts +++ /dev/null @@ -1,423 +0,0 @@ -import { Address } from "@coral-xyz/anchor"; -import { Percentage, TransactionBuilder } from "@orca-so/common-sdk"; -import { PublicKey } from "@solana/web3.js"; -import { WhirlpoolContext } from "./context"; -import { WhirlpoolClientImpl } from "./impl/whirlpool-client-impl"; -import { DevFeeSwapInput, SwapInput } from "./instructions"; -import { - WhirlpoolAccountFetchOptions, - WhirlpoolAccountFetcherInterface, -} from "./network/public/fetcher"; -import { WhirlpoolRouter } from "./router/public"; -import { - DecreaseLiquidityInput, - IncreaseLiquidityInput, - PositionData, - TickData, - WhirlpoolData, -} from "./types/public"; -import { TokenAccountInfo, TokenInfo, WhirlpoolRewardInfo } from "./types/public/client-types"; - -/** - * Helper class to help interact with Whirlpool Accounts with a simpler interface. - * - * @category WhirlpoolClient - */ -export interface WhirlpoolClient { - /** - * Get this client's WhirlpoolContext object - * @return a WhirlpoolContext object - */ - getContext: () => WhirlpoolContext; - - /** - * Get an WhirlpoolAccountCacheInterface to fetch and cache Whirlpool accounts - * @return an WhirlpoolAccountCacheInterface instance - */ - getFetcher: () => WhirlpoolAccountFetcherInterface; - - /** - * Get a WhirlpoolRouter to help generate the best prices when transacting across a set of pools. - * @param poolAddresses the addresses of the Whirlpool account addresses to route through - * @returns a {@link WhirlpoolRouter} instance - */ - getRouter: (poolAddresses: Address[]) => Promise; - - /** - * Get a Whirlpool object to interact with the Whirlpool account at the given address. - * @param poolAddress the address of the Whirlpool account - * @param opts an options object to define fetch and cache options when accessing on-chain accounts - * @return a Whirlpool object to interact with - */ - getPool: (poolAddress: Address, opts?: WhirlpoolAccountFetchOptions) => Promise; - - /** - * Get a list of Whirlpool objects matching the provided list of addresses. - * @param poolAddresses the addresses of the Whirlpool accounts - * @param opts an options object to define fetch and cache options when accessing on-chain accounts - * @return a list of Whirlpool objects to interact with - */ - getPools: (poolAddresses: Address[], opts?: WhirlpoolAccountFetchOptions) => Promise; - - /** - * Get a Position object to interact with the Position account at the given address. - * @param positionAddress the address of the Position account - * @param opts an options object to define fetch and cache options when accessing on-chain accounts - * @return a Position object to interact with. - * @throws error when address does not return a Position account. - */ - getPosition: (positionAddress: Address, opts?: WhirlpoolAccountFetchOptions) => Promise; - - /** - * Get a list of Position objects to interact with the Position account at the given addresses. - * @param positionAddress the addresses of the Position accounts - * @param opts an options object to define fetch and cache options when accessing on-chain accounts - * @return a Record object between account address and Position. If an address is not a Position account, it will be null. - */ - getPositions: ( - positionAddresses: Address[], - opts?: WhirlpoolAccountFetchOptions - ) => Promise>; - - /** - * Collect all fees and rewards from a list of positions. - * @experimental - * @param positionAddress the addresses of the Position accounts to collect fee & rewards from. - * @param opts an options object to define fetch and cache options when accessing on-chain accounts - * @returns A set of transaction-builders to resolve ATA for affliated tokens, collect fee & rewards for all positions. - */ - collectFeesAndRewardsForPositions: ( - positionAddresses: Address[], - opts?: WhirlpoolAccountFetchOptions - ) => Promise; - - /** - * Create a Whirlpool account for a group of token A, token B and tick spacing - * @param whirlpoolConfig the address of the whirlpool config - * @param tokenMintA the address of the token A - * @param tokenMintB the address of the token B - * @param tickSpacing the space between two ticks in the tick array - * @param initialTick the initial tick that the pool is set to (derived from initial price) - * @param funder the account to debit SOL from to fund the creation of the account(s) - * @return `poolKey`: The public key of the newly created whirlpool account. `tx`: The transaction containing instructions for the on-chain operations. - * @throws error when the tokens are not in the canonical byte-based ordering. To resolve this, invert the token order and the initialTick (see `TickUtil.invertTick()`, `PriceMath.invertSqrtPriceX64()`, or `PriceMath.invertPrice()`). - */ - createPool: ( - whirlpoolsConfig: Address, - tokenMintA: Address, - tokenMintB: Address, - tickSpacing: number, - initialTick: number, - funder: Address - ) => Promise<{ poolKey: PublicKey; tx: TransactionBuilder }>; - - /** - * Collect protocol fees from a list of pools - * @param poolAddresses the addresses of the Whirlpool accounts to collect protocol fees from - * @returns A transaction builder to resolve ATA for tokenA and tokenB if needed, and collect protocol fees for all pools - */ - collectProtocolFeesForPools: (poolAddresses: Address[]) => Promise; -} - -/** - * Construct a WhirlpoolClient instance to help interact with Whirlpools accounts with. - * - * @category WhirlpoolClient - * @param ctx - WhirlpoolContext object - * @returns a WhirlpoolClient instance to help with interacting with Whirlpools accounts. - */ -export function buildWhirlpoolClient(ctx: WhirlpoolContext): WhirlpoolClient { - return new WhirlpoolClientImpl(ctx); -} - -/** - * Helper class to interact with a Whirlpool account and build complex transactions. - * @category WhirlpoolClient - */ -export interface Whirlpool { - /** - * Return the address for this Whirlpool instance. - * @return the PublicKey for this Whirlpool instance. - */ - getAddress: () => PublicKey; - - /** - * Return the most recently fetched Whirlpool account data. - * @return most recently fetched WhirlpoolData for this address. - */ - getData: () => WhirlpoolData; - - /** - * Fetch and return the most recently fetched Whirlpool account data. - * @return the most up to date WhirlpoolData for this address. - */ - refreshData: () => Promise; - - /** - * Get the TokenInfo for token A of this pool. - * @return TokenInfo for token A - */ - getTokenAInfo: () => TokenInfo; - - /** - * Get the TokenInfo for token B of this pool. - * @return TokenInfo for token B - */ - getTokenBInfo: () => TokenInfo; - - /** - * Get the TokenAccountInfo for token vault A of this pool. - * @return TokenAccountInfo for token vault A - */ - getTokenVaultAInfo: () => TokenAccountInfo; - - /** - * Get the TokenAccountInfo for token vault B of this pool. - * @return TokenAccountInfo for token vault B - */ - getTokenVaultBInfo: () => TokenAccountInfo; - - /** - * Get the WhirlpoolRewardInfos for this pool. - * @return Array of 3 WhirlpoolRewardInfos. However, not all of them may be initialized. Use the initialized field on WhirlpoolRewardInfo to check if the reward is active. - */ - getRewardInfos: () => WhirlpoolRewardInfo[]; - - /** - * Initialize a set of tick-arrays that encompasses the provided ticks. - * - * If `funder` is provided, the funder wallet has to sign this transaction. - * - * @param ticks - A group of ticks that define the desired tick-arrays to initialize. If the tick's array has been initialized, it will be ignored. - * @param funder - the wallet that will fund the cost needed to initialize the position. If null, the WhirlpoolContext wallet is used. - * @param opts an {@link WhirlpoolAccountFetchOptions} object to define fetch and cache options when accessing on-chain accounts - * @return a transaction that will initialize the defined tick-arrays if executed. Return null if all of the tick's arrays are initialized. - */ - initTickArrayForTicks: ( - ticks: number[], - funder?: Address, - opts?: WhirlpoolAccountFetchOptions - ) => Promise; - - /** - * Open and fund a position on this Whirlpool. - * - * User has to ensure the TickArray for tickLower and tickUpper has been initialized prior to calling this function. - * - * If `wallet` or `funder` is provided, those wallets have to sign this transaction. - * - * @param tickLower - the tick index for the lower bound of this position - * @param tickUpper - the tick index for the upper bound of this position - * @param liquidityInput - an InputLiquidityInput type to define the desired liquidity amount to deposit - * @param wallet - the wallet to withdraw tokens to deposit into the position and house the position token. If null, the WhirlpoolContext wallet is used. - * @param funder - the wallet that will fund the cost needed to initialize the position. If null, the WhirlpoolContext wallet is used. - * @param positionMint - the mint address of the position token to be created. If null, a new mint address will be created. - * @return `positionMint` - the position to be created. `tx` - The transaction containing the instructions to perform the operation on chain. - */ - openPosition: ( - tickLower: number, - tickUpper: number, - liquidityInput: IncreaseLiquidityInput, - wallet?: Address, - funder?: Address, - positionMint?: PublicKey - ) => Promise<{ positionMint: PublicKey; tx: TransactionBuilder }>; - - /** - * Open and fund a position with meta-data on this Whirlpool. - * - * User has to ensure the TickArray for tickLower and tickUpper has been initialized prior to calling this function. - * - * If `wallet` or `funder` is provided, the wallet owners have to sign this transaction. - * - * @param tickLower - the tick index for the lower bound of this position - * @param tickUpper - the tick index for the upper bound of this position - * @param liquidityInput - input that defines the desired liquidity amount and maximum tokens willing to be to deposited. - * @param wallet - the wallet to withdraw tokens to deposit into the position and house the position token. If null, the WhirlpoolContext wallet is used. - * @param funder - the wallet that will fund the cost needed to initialize the position. If null, the WhirlpoolContext wallet is used. - * @param positionMint - the mint address of the position token to be created. If null, a new mint address will be created. - * @return `positionMint` - the position to be created. `tx` - The transaction containing the instructions to perform the operation on chain. - */ - openPositionWithMetadata: ( - tickLower: number, - tickUpper: number, - liquidityInput: IncreaseLiquidityInput, - wallet?: Address, - funder?: Address, - positionMint?: PublicKey - ) => Promise<{ positionMint: PublicKey; tx: TransactionBuilder }>; - - /** - * Withdraw all tokens from a position, close the account and burn the position token. - * - * Users have to collect all fees and rewards from this position prior to closing the account. - * - * If `positionWallet`, `payer` is provided, the wallet owner has to sign this transaction. - * - * @param positionAddress - The address of the position account. - * @param slippageTolerance - The amount of slippage the caller is willing to accept when withdrawing liquidity. - * @param destinationWallet - The wallet that the tokens withdrawn and rent lamports will be sent to. If null, the WhirlpoolContext wallet is used. - * @param positionWallet - The wallet that houses the position token that corresponds to this position address. If null, the WhirlpoolContext wallet is used. - * @param payer - the wallet that will fund the cost needed to initialize the token ATA accounts. If null, the WhirlpoolContext wallet is used. - */ - closePosition: ( - positionAddress: Address, - slippageTolerance: Percentage, - destinationWallet?: Address, - positionWallet?: Address, - payer?: Address - ) => Promise; - - /** - * Perform a swap between tokenA and tokenB on this pool. - * - * @param input - A quote on the desired tokenIn and tokenOut for this swap. Use {@link swapQuoteWithParams} or other swap quote functions to generate this object. - * @param wallet - The wallet that tokens will be withdrawn and deposit into. If null, the WhirlpoolContext wallet is used. - * @return a transaction that will perform the swap once executed. - */ - swap: (input: SwapInput, wallet?: PublicKey) => Promise; - - /** - * Collect a developer fee and perform a swap between tokenA and tokenB on this pool. - * - * @param input - A quote on the desired tokenIn and tokenOut for this swap. Use {@link swapQuoteByInputTokenWithDevFees} to generate this object. - * @param devFeeWallet - The wallet that developer fees will be deposited into. - * @param wallet - The wallet that swap tokens will be withdrawn and deposit into. If null, the WhirlpoolContext wallet is used. - * @param payer - The wallet that will fund the cost needed to initialize the dev wallet token ATA accounts. If null, the WhirlpoolContext wallet is used. - * @return a transaction that will perform the swap once executed. - */ - swapWithDevFees: ( - input: DevFeeSwapInput, - devFeeWallet: PublicKey, - wallet?: PublicKey, - payer?: PublicKey - ) => Promise; -} - -/** - * Helper class to interact with a Position account and build complex transactions. - * @category WhirlpoolClient - */ -export interface Position { - /** - * Return the address for this Whirlpool instance. - * @return the PublicKey for this Whirlpool instance. - */ - getAddress: () => PublicKey; - - /** - * Return the most recently fetched Position account data. - * @return most recently fetched PositionData for this address. - */ - getData: () => PositionData; - - /** - * Return the most recently fetched Whirlpool account data for this position. - * @return most recently fetched WhirlpoolData for this position. - */ - getWhirlpoolData: () => WhirlpoolData; - - /** - * Return the most recently fetched TickData account data for this position's lower tick. - * @return most recently fetched TickData for this position's lower tick. - */ - getLowerTickData: () => TickData; - - /** - * Return the most recently fetched TickData account data for this position's upper tick. - * @return most recently fetched TickData for this position's upper tick. - */ - getUpperTickData: () => TickData; - - /** - * Fetch and return the most recently fetched Position account data. - * @return the most up to date PositionData for this address. - */ - refreshData: () => Promise; - - /** - * Deposit additional tokens into this postiion. - * The wallet must contain the position token and the necessary token A & B to complete the deposit. - * If `positionWallet` and `wallet` is provided, the wallet owners have to sign this transaction. - * - * @param liquidityInput - input that defines the desired liquidity amount and maximum tokens willing to be to deposited. - * @param resolveATA - if true, add instructions to create associated token accounts for tokenA,B for the destinationWallet if necessary. (RPC call required) - * @param wallet - to withdraw tokens to deposit into the position. If null, the WhirlpoolContext wallet is used. - * @param positionWallet - the wallet to that houses the position token. If null, the WhirlpoolContext wallet is used. - * @param ataPayer - wallet that will fund the creation of the new associated token accounts - * @return the transaction that will deposit the tokens into the position when executed. - */ - increaseLiquidity: ( - liquidityInput: IncreaseLiquidityInput, - resolveATA?: boolean, - wallet?: Address, - positionWallet?: Address, - ataPayer?: Address - ) => Promise; - - /** - * Withdraw liquidity from this position. - * - * If `positionWallet` is provided, the wallet owners have to sign this transaction. - * - * @param liquidityInput - input that defines the desired liquidity amount and minimum tokens willing to be to withdrawn from the position. - * @param resolveATA - if true, add instructions to create associated token accounts for tokenA,B for the destinationWallet if necessary. (RPC call required) - * @param destinationWallet - the wallet to deposit tokens into when withdrawing from the position. If null, the WhirlpoolContext wallet is used. - * @param positionWallet - the wallet to that houses the position token. If null, the WhirlpoolContext wallet is used. - * @param ataPayer - wallet that will fund the creation of the new associated token accounts - * @return the transaction that will deposit the tokens into the position when executed. - */ - decreaseLiquidity: ( - liquidityInput: DecreaseLiquidityInput, - resolveATA?: boolean, - destinationWallet?: Address, - positionWallet?: Address, - ataPayer?: Address - ) => Promise; - - /** - * Collect fees from this position - * - * If `positionWallet` is provided, the wallet owners have to sign this transaction. - * - * @param updateFeesAndRewards - if true, add instructions to refresh the accumulated fees and rewards data (default to true unless you know that the collect fees quote and on-chain data match for the "feeOwedA" and "feeOwedB" fields in the Position account) - * @param ownerTokenAccountMap - A record that maps a given mint to the owner's token account for that mint (if an entry doesn't exist, it will be automatically resolved) - * @param destinationWallet - the wallet to deposit tokens into when withdrawing from the position. If null, the WhirlpoolContext wallet is used. - * @param positionWallet - the wallet to that houses the position token. If null, the WhirlpoolContext wallet is used. - * @param ataPayer - wallet that will fund the creation of the new associated token accounts - * @param opts an options object to define fetch and cache options when accessing on-chain accounts - * @return the transaction that will collect fees from the position - */ - collectFees: ( - updateFeesAndRewards?: boolean, - ownerTokenAccountMap?: Partial>, - destinationWallet?: Address, - positionWallet?: Address, - ataPayer?: Address, - opts?: WhirlpoolAccountFetchOptions - ) => Promise; - - /** - * Collect rewards from this position - * - * If `positionWallet` is provided, the wallet owners have to sign this transaction. - * - * @param rewardsToCollect - reward mints to collect (omitting this parameter means all rewards will be collected) - * @param updateFeesAndRewards - if true, add instructions to refresh the accumulated fees and rewards data (default to true unless you know that the collect fees quote and on-chain data match for the "feeOwedA" and "feeOwedB" fields in the Position account) - * @param ownerTokenAccountMap - A record that maps a given mint to the owner's token account for that mint (if an entry doesn't exist, it will be automatically resolved) - * @param destinationWallet - the wallet to deposit tokens into when withdrawing from the position. If null, the WhirlpoolContext wallet is used. - * @param positionWallet - the wallet to that houses the position token. If null, the WhirlpoolContext wallet is used. - * @param ataPayer - wallet that will fund the creation of the new associated token accounts - * @param opts an options object to define fetch and cache options when accessing on-chain accounts - * @return the transaction that will collect fees from the position - */ - collectRewards: ( - rewardsToCollect?: Address[], - updateFeesAndRewards?: boolean, - ownerTokenAccountMap?: Partial>, - destinationWallet?: Address, - positionWallet?: Address, - ataPayer?: Address, - opts?: WhirlpoolAccountFetchOptions - ) => Promise; -} diff --git a/sdk/tests/integration/close_bundled_position.test.ts b/sdk/tests/integration/close_bundled_position.test.ts deleted file mode 100644 index c972c2c..0000000 --- a/sdk/tests/integration/close_bundled_position.test.ts +++ /dev/null @@ -1,625 +0,0 @@ -import * as anchor from "@coral-xyz/anchor"; -import { PDA, Percentage } from "@orca-so/common-sdk"; -import * as assert from "assert"; -import BN from "bn.js"; -import { - InitPoolParams, - POSITION_BUNDLE_SIZE, - PositionBundleData, - WhirlpoolContext, - WhirlpoolIx, - buildWhirlpoolClient, - increaseLiquidityQuoteByInputTokenWithParamsUsingPriceSlippage, - toTx -} from "../../src"; -import { IGNORE_CACHE } from "../../src/network/public/fetcher"; -import { - ONE_SOL, - TickSpacing, - approveToken, createAssociatedTokenAccount, - systemTransferTx, - transferToken -} from "../utils"; -import { defaultConfirmOptions } from "../utils/const"; -import { initTestPool, initializePositionBundle, openBundledPosition, openPosition } from "../utils/init-utils"; -import { mintTokensToTestAccount } from "../utils/test-builders"; - -describe("close_bundled_position", () => { - const provider = anchor.AnchorProvider.local(undefined, defaultConfirmOptions); - const program = anchor.workspace.Whirlpool; - const ctx = WhirlpoolContext.fromWorkspace(provider, program); - const client = buildWhirlpoolClient(ctx); - const fetcher = ctx.fetcher; - - const tickLowerIndex = 0; - const tickUpperIndex = 128; - let poolInitInfo: InitPoolParams; - let whirlpoolPda: PDA; - const funderKeypair = anchor.web3.Keypair.generate(); - - before(async () => { - poolInitInfo = (await initTestPool(ctx, TickSpacing.Standard)).poolInitInfo; - whirlpoolPda = poolInitInfo.whirlpoolPda; - await systemTransferTx(provider, funderKeypair.publicKey, ONE_SOL).buildAndExecute(); - - const pool = await client.getPool(whirlpoolPda.publicKey); - await (await pool.initTickArrayForTicks([0]))?.buildAndExecute(); - }); - - function checkBitmapIsOpened(account: PositionBundleData, bundleIndex: number): boolean { - if (bundleIndex < 0 || bundleIndex >= POSITION_BUNDLE_SIZE) throw Error("bundleIndex is out of bounds"); - - const bitmapIndex = Math.floor(bundleIndex / 8); - const bitmapOffset = bundleIndex % 8; - return (account.positionBitmap[bitmapIndex] & (1 << bitmapOffset)) > 0; - } - - function checkBitmapIsClosed(account: PositionBundleData, bundleIndex: number): boolean { - if (bundleIndex < 0 || bundleIndex >= POSITION_BUNDLE_SIZE) throw Error("bundleIndex is out of bounds"); - - const bitmapIndex = Math.floor(bundleIndex / 8); - const bitmapOffset = bundleIndex % 8; - return (account.positionBitmap[bitmapIndex] & (1 << bitmapOffset)) === 0; - } - - function checkBitmap(account: PositionBundleData, openedBundleIndexes: number[]) { - for (let i = 0; i < POSITION_BUNDLE_SIZE; i++) { - if (openedBundleIndexes.includes(i)) { - assert.ok(checkBitmapIsOpened(account, i)); - } - else { - assert.ok(checkBitmapIsClosed(account, i)); - } - } - } - - it("successfully closes an opened bundled position", async () => { - const positionBundleInfo = await initializePositionBundle(ctx, ctx.wallet.publicKey); - - const bundleIndex = 0; - const positionInitInfo = await openBundledPosition( - ctx, - whirlpoolPda.publicKey, - positionBundleInfo.positionBundleMintKeypair.publicKey, - bundleIndex, - tickLowerIndex, - tickUpperIndex - ); - const { bundledPositionPda } = positionInitInfo.params; - - const preAccount = await fetcher.getPosition(bundledPositionPda.publicKey, IGNORE_CACHE); - const prePositionBundle = await fetcher.getPositionBundle(positionBundleInfo.positionBundlePda.publicKey, IGNORE_CACHE); - checkBitmap(prePositionBundle!, [bundleIndex]); - assert.ok(preAccount !== null); - - const receiverKeypair = anchor.web3.Keypair.generate(); - await toTx( - ctx, - WhirlpoolIx.closeBundledPositionIx(ctx.program, { - bundledPosition: bundledPositionPda.publicKey, - bundleIndex, - positionBundle: positionBundleInfo.positionBundlePda.publicKey, - positionBundleAuthority: ctx.wallet.publicKey, - positionBundleTokenAccount: positionBundleInfo.positionBundleTokenAccount, - receiver: receiverKeypair.publicKey, - }) - ).buildAndExecute(); - const postAccount = await fetcher.getPosition(bundledPositionPda.publicKey, IGNORE_CACHE); - const postPositionBundle = await fetcher.getPositionBundle(positionBundleInfo.positionBundlePda.publicKey, IGNORE_CACHE); - checkBitmap(postPositionBundle!, []); - assert.ok(postAccount === null); - - const receiverAccount = await provider.connection.getAccountInfo(receiverKeypair.publicKey); - const lamports = receiverAccount?.lamports; - assert.ok(lamports != undefined && lamports > 0); - }); - - it("should be failed: invalid bundle index", async () => { - const positionBundleInfo = await initializePositionBundle(ctx, ctx.wallet.publicKey); - - const bundleIndex = 0; - const positionInitInfo = await openBundledPosition( - ctx, - whirlpoolPda.publicKey, - positionBundleInfo.positionBundleMintKeypair.publicKey, - bundleIndex, - tickLowerIndex, - tickUpperIndex - ); - const { bundledPositionPda } = positionInitInfo.params; - - const tx = await toTx( - ctx, - WhirlpoolIx.closeBundledPositionIx(ctx.program, { - bundledPosition: bundledPositionPda.publicKey, - bundleIndex: 1, // invalid - positionBundle: positionBundleInfo.positionBundlePda.publicKey, - positionBundleAuthority: ctx.wallet.publicKey, - positionBundleTokenAccount: positionBundleInfo.positionBundleTokenAccount, - receiver: ctx.wallet.publicKey, - }) - ); - await assert.rejects( - tx.buildAndExecute(), - /0x7d6/ // ConstraintSeeds (seed constraint was violated) - ); - }); - - it("should be failed: user closes bundled position already closed", async () => { - const positionBundleInfo = await initializePositionBundle(ctx, ctx.wallet.publicKey); - - const bundleIndex = 0; - const positionInitInfo = await openBundledPosition( - ctx, - whirlpoolPda.publicKey, - positionBundleInfo.positionBundleMintKeypair.publicKey, - bundleIndex, - tickLowerIndex, - tickUpperIndex - ); - const { bundledPositionPda } = positionInitInfo.params; - - const tx = toTx( - ctx, - WhirlpoolIx.closeBundledPositionIx(ctx.program, { - bundledPosition: bundledPositionPda.publicKey, - bundleIndex, - positionBundle: positionBundleInfo.positionBundlePda.publicKey, - positionBundleAuthority: ctx.wallet.publicKey, - positionBundleTokenAccount: positionBundleInfo.positionBundleTokenAccount, - receiver: ctx.wallet.publicKey, - }) - ); - - // close... - await tx.buildAndExecute(); - // re-close... - await assert.rejects( - tx.buildAndExecute(), - /0xbc4/ // AccountNotInitialized - ); - }); - - it("should be failed: bundled position is not empty", async () => { - const positionBundleInfo = await initializePositionBundle(ctx, ctx.wallet.publicKey); - - const bundleIndex = 0; - const positionInitInfo = await openBundledPosition( - ctx, - whirlpoolPda.publicKey, - positionBundleInfo.positionBundleMintKeypair.publicKey, - bundleIndex, - tickLowerIndex, - tickUpperIndex - ); - const { bundledPositionPda } = positionInitInfo.params; - - // deposit - const pool = await client.getPool(poolInitInfo.whirlpoolPda.publicKey, IGNORE_CACHE); - const quote = increaseLiquidityQuoteByInputTokenWithParamsUsingPriceSlippage({ - tokenMintA: poolInitInfo.tokenMintA, - tokenMintB: poolInitInfo.tokenMintB, - sqrtPrice: pool.getData().sqrtPrice, - slippageTolerance: Percentage.fromFraction(0, 100), - tickLowerIndex, - tickUpperIndex, - tickCurrentIndex: pool.getData().tickCurrentIndex, - inputTokenMint: poolInitInfo.tokenMintB, - inputTokenAmount: new BN(1_000_000), - }); - - await mintTokensToTestAccount( - provider, - poolInitInfo.tokenMintA, - quote.tokenMaxA.toNumber(), - poolInitInfo.tokenMintB, - quote.tokenMaxB.toNumber(), - ctx.wallet.publicKey - ); - - const position = await client.getPosition(bundledPositionPda.publicKey, IGNORE_CACHE); - await (await position.increaseLiquidity(quote)).buildAndExecute(); - assert.ok((await position.refreshData()).liquidity.gtn(0)); - - // try to close... - const tx = toTx( - ctx, - WhirlpoolIx.closeBundledPositionIx(ctx.program, { - bundledPosition: bundledPositionPda.publicKey, - bundleIndex, - positionBundle: positionBundleInfo.positionBundlePda.publicKey, - positionBundleAuthority: ctx.wallet.publicKey, - positionBundleTokenAccount: positionBundleInfo.positionBundleTokenAccount, - receiver: ctx.wallet.publicKey, - }) - ); - await assert.rejects( - tx.buildAndExecute(), - /0x1775/ // ClosePositionNotEmpty - ); - }); - - describe("invalid input account", () => { - it("should be failed: invalid bundled position", async () => { - const positionBundleInfo = await initializePositionBundle(ctx, ctx.wallet.publicKey); - - const positionInitInfo0 = await openBundledPosition( - ctx, - whirlpoolPda.publicKey, - positionBundleInfo.positionBundleMintKeypair.publicKey, - 0, - tickLowerIndex, - tickUpperIndex - ); - - const positionInitInfo1 = await openBundledPosition( - ctx, - whirlpoolPda.publicKey, - positionBundleInfo.positionBundleMintKeypair.publicKey, - 1, - tickLowerIndex, - tickUpperIndex - ); - const tx = toTx( - ctx, - WhirlpoolIx.closeBundledPositionIx(ctx.program, { - bundledPosition: positionInitInfo1.params.bundledPositionPda.publicKey, // invalid - bundleIndex: 0, - positionBundle: positionBundleInfo.positionBundlePda.publicKey, - positionBundleAuthority: ctx.wallet.publicKey, - positionBundleTokenAccount: positionBundleInfo.positionBundleTokenAccount, - receiver: ctx.wallet.publicKey, - }) - ); - await assert.rejects( - tx.buildAndExecute(), - /0x7d6/ // ConstraintSeeds (seed constraint was violated) - ); - }); - - it("should be failed: invalid position bundle", async () => { - const positionBundleInfo0 = await initializePositionBundle(ctx, ctx.wallet.publicKey); - const positionBundleInfo1 = await initializePositionBundle(ctx, ctx.wallet.publicKey); - - const bundleIndex = 0; - const positionInitInfo = await openBundledPosition( - ctx, - whirlpoolPda.publicKey, - positionBundleInfo0.positionBundleMintKeypair.publicKey, - bundleIndex, - tickLowerIndex, - tickUpperIndex - ); - const tx = toTx( - ctx, - WhirlpoolIx.closeBundledPositionIx(ctx.program, { - bundledPosition: positionInitInfo.params.bundledPositionPda.publicKey, - bundleIndex, - positionBundle: positionBundleInfo1.positionBundlePda.publicKey, // invalid - positionBundleAuthority: ctx.wallet.publicKey, - positionBundleTokenAccount: positionBundleInfo0.positionBundleTokenAccount, - receiver: ctx.wallet.publicKey, - }) - ); - await assert.rejects( - tx.buildAndExecute(), - /0x7d6/ // ConstraintSeeds (seed constraint was violated) - ); - }); - - it("should be failed: invalid ATA (amount is zero)", async () => { - const positionBundleInfo = await initializePositionBundle(ctx); - - const bundleIndex = 0; - const positionInitInfo = await openBundledPosition( - ctx, - whirlpoolPda.publicKey, - positionBundleInfo.positionBundleMintKeypair.publicKey, - bundleIndex, - tickLowerIndex, - tickUpperIndex - ); - - const ata = await createAssociatedTokenAccount( - provider, - positionBundleInfo.positionBundleMintKeypair.publicKey, - funderKeypair.publicKey, - ctx.wallet.publicKey, - ); - const tx = toTx( - ctx, - WhirlpoolIx.closeBundledPositionIx(ctx.program, { - bundledPosition: positionInitInfo.params.bundledPositionPda.publicKey, - bundleIndex, - positionBundle: positionBundleInfo.positionBundlePda.publicKey, - positionBundleAuthority: ctx.wallet.publicKey, - positionBundleTokenAccount: ata, // invalid - receiver: ctx.wallet.publicKey, - }) - ); - - await assert.rejects( - tx.buildAndExecute(), - /0x7d3/ // ConstraintRaw (amount == 1) - ); - }); - - it("should be failed: invalid ATA (invalid mint)", async () => { - const positionBundleInfo0 = await initializePositionBundle(ctx, ctx.wallet.publicKey); - const positionBundleInfo1 = await initializePositionBundle(ctx, ctx.wallet.publicKey); - - const bundleIndex = 0; - const positionInitInfo = await openBundledPosition( - ctx, - whirlpoolPda.publicKey, - positionBundleInfo0.positionBundleMintKeypair.publicKey, - bundleIndex, - tickLowerIndex, - tickUpperIndex - ); - const tx = toTx( - ctx, - WhirlpoolIx.closeBundledPositionIx(ctx.program, { - bundledPosition: positionInitInfo.params.bundledPositionPda.publicKey, - bundleIndex, - positionBundle: positionBundleInfo0.positionBundlePda.publicKey, - positionBundleAuthority: ctx.wallet.publicKey, - positionBundleTokenAccount: positionBundleInfo1.positionBundleTokenAccount, // invalid - receiver: ctx.wallet.publicKey, - }) - ); - - await assert.rejects( - tx.buildAndExecute(), - /0x7d3/ // ConstraintRaw (mint == position_bundle.position_bundle_mint) - ); - }); - - it("should be failed: invalid position bundle authority", async () => { - const positionBundleInfo = await initializePositionBundle(ctx); - - const bundleIndex = 0; - const positionInitInfo = await openBundledPosition( - ctx, - whirlpoolPda.publicKey, - positionBundleInfo.positionBundleMintKeypair.publicKey, - bundleIndex, - tickLowerIndex, - tickUpperIndex - ); - const tx = toTx( - ctx, - WhirlpoolIx.closeBundledPositionIx(ctx.program, { - bundledPosition: positionInitInfo.params.bundledPositionPda.publicKey, - bundleIndex, - positionBundle: positionBundleInfo.positionBundlePda.publicKey, - positionBundleAuthority: funderKeypair.publicKey, // invalid - positionBundleTokenAccount: positionBundleInfo.positionBundleTokenAccount, - receiver: ctx.wallet.publicKey, - }) - ); - tx.addSigner(funderKeypair); - - await assert.rejects( - tx.buildAndExecute(), - /0x1783/ // MissingOrInvalidDelegate - ); - }); - }); - - describe("authority delegation", () => { - it("successfully closes bundled position with delegated authority", async () => { - const positionBundleInfo = await initializePositionBundle(ctx); - - const bundleIndex = 0; - const positionInitInfo = await openBundledPosition( - ctx, - whirlpoolPda.publicKey, - positionBundleInfo.positionBundleMintKeypair.publicKey, - bundleIndex, - tickLowerIndex, - tickUpperIndex - ); - - const tx = toTx( - ctx, - WhirlpoolIx.closeBundledPositionIx(ctx.program, { - bundledPosition: positionInitInfo.params.bundledPositionPda.publicKey, - bundleIndex, - positionBundle: positionBundleInfo.positionBundlePda.publicKey, - positionBundleAuthority: funderKeypair.publicKey, // should be delegated - positionBundleTokenAccount: positionBundleInfo.positionBundleTokenAccount, - receiver: ctx.wallet.publicKey, - }) - ); - tx.addSigner(funderKeypair); - - await assert.rejects( - tx.buildAndExecute(), - /0x1783/ // MissingOrInvalidDelegate - ); - - // delegate 1 token from ctx.wallet to funder - await approveToken( - provider, - positionBundleInfo.positionBundleTokenAccount, - funderKeypair.publicKey, - 1, - ); - await tx.buildAndExecute(); - const positionBundle = await fetcher.getPositionBundle(positionBundleInfo.positionBundlePda.publicKey, IGNORE_CACHE); - checkBitmapIsClosed(positionBundle!, 0); - }); - - it("successfully closes bundled position even if delegation exists", async () => { - const positionBundleInfo = await initializePositionBundle(ctx); - - const bundleIndex = 0; - const positionInitInfo = await openBundledPosition( - ctx, - whirlpoolPda.publicKey, - positionBundleInfo.positionBundleMintKeypair.publicKey, - bundleIndex, - tickLowerIndex, - tickUpperIndex - ); - - const tx = toTx( - ctx, - WhirlpoolIx.closeBundledPositionIx(ctx.program, { - bundledPosition: positionInitInfo.params.bundledPositionPda.publicKey, - bundleIndex, - positionBundle: positionBundleInfo.positionBundlePda.publicKey, - positionBundleAuthority: ctx.wallet.publicKey, - positionBundleTokenAccount: positionBundleInfo.positionBundleTokenAccount, - receiver: ctx.wallet.publicKey, - }) - ); - - // delegate 1 token from ctx.wallet to funder - await approveToken( - provider, - positionBundleInfo.positionBundleTokenAccount, - funderKeypair.publicKey, - 1, - ); - - // owner can close even if delegation exists - await tx.buildAndExecute(); - const positionBundle = await fetcher.getPositionBundle(positionBundleInfo.positionBundlePda.publicKey, IGNORE_CACHE); - checkBitmapIsClosed(positionBundle!, 0); - }); - - it("should be faild: delegated amount is zero", async () => { - const positionBundleInfo = await initializePositionBundle(ctx); - - const bundleIndex = 0; - const positionInitInfo = await openBundledPosition( - ctx, - whirlpoolPda.publicKey, - positionBundleInfo.positionBundleMintKeypair.publicKey, - bundleIndex, - tickLowerIndex, - tickUpperIndex - ); - - const tx = toTx( - ctx, - WhirlpoolIx.closeBundledPositionIx(ctx.program, { - bundledPosition: positionInitInfo.params.bundledPositionPda.publicKey, - bundleIndex, - positionBundle: positionBundleInfo.positionBundlePda.publicKey, - positionBundleAuthority: funderKeypair.publicKey, // should be delegated - positionBundleTokenAccount: positionBundleInfo.positionBundleTokenAccount, - receiver: ctx.wallet.publicKey, - }) - ); - tx.addSigner(funderKeypair); - - await assert.rejects( - tx.buildAndExecute(), - /0x1783/ // MissingOrInvalidDelegate - ); - - // delegate ZERO token from ctx.wallet to funder - await approveToken( - provider, - positionBundleInfo.positionBundleTokenAccount, - funderKeypair.publicKey, - 0, - ); - await assert.rejects( - tx.buildAndExecute(), - /0x1784/ // InvalidPositionTokenAmount - ); - }); - }); - - describe("transfer position bundle", () => { - it("successfully closes bundled position after position bundle token transfer", async () => { - const positionBundleInfo = await initializePositionBundle(ctx); - - const bundleIndex = 0; - const positionInitInfo = await openBundledPosition( - ctx, - whirlpoolPda.publicKey, - positionBundleInfo.positionBundleMintKeypair.publicKey, - bundleIndex, - tickLowerIndex, - tickUpperIndex - ); - - const funderATA = await createAssociatedTokenAccount( - provider, - positionBundleInfo.positionBundleMintKeypair.publicKey, - funderKeypair.publicKey, - ctx.wallet.publicKey, - ); - - await transferToken( - provider, - positionBundleInfo.positionBundleTokenAccount, - funderATA, - 1 - ); - - const tokenInfo = await fetcher.getTokenInfo(funderATA, IGNORE_CACHE); - assert.ok(tokenInfo?.amount === 1n); - - const tx = toTx( - ctx, - WhirlpoolIx.closeBundledPositionIx(ctx.program, { - bundledPosition: positionInitInfo.params.bundledPositionPda.publicKey, - bundleIndex, - positionBundle: positionBundleInfo.positionBundlePda.publicKey, - positionBundleAuthority: funderKeypair.publicKey, // new owner - positionBundleTokenAccount: funderATA, - receiver: funderKeypair.publicKey - }) - ); - tx.addSigner(funderKeypair); - - await tx.buildAndExecute(); - const positionBundle = await fetcher.getPositionBundle(positionBundleInfo.positionBundlePda.publicKey, IGNORE_CACHE); - checkBitmapIsClosed(positionBundle!, 0); - }); - }); - - describe("non-bundled position", () => { - it("should be failed: try to close NON-bundled position", async () => { - const positionBundleInfo = await initializePositionBundle(ctx); - - const bundleIndex = 0; - - const positionInitInfo = await openBundledPosition( - ctx, - whirlpoolPda.publicKey, - positionBundleInfo.positionBundleMintKeypair.publicKey, - bundleIndex, - tickLowerIndex, - tickUpperIndex - ); - - // open NON-bundled position - const { params } = await openPosition(ctx, poolInitInfo.whirlpoolPda.publicKey, 0, 128); - - const tx = toTx( - ctx, - WhirlpoolIx.closeBundledPositionIx(ctx.program, { - bundledPosition: params.positionPda.publicKey, // NON-bundled position - bundleIndex, - positionBundle: positionBundleInfo.positionBundlePda.publicKey, - positionBundleAuthority: ctx.wallet.publicKey, - positionBundleTokenAccount: positionBundleInfo.positionBundleTokenAccount, - receiver: ctx.wallet.publicKey, - }) - ); - - await assert.rejects( - tx.buildAndExecute(), - /0x7d6/ // ConstraintSeeds (seed constraint was violated) - ); - }); - }); - -}); diff --git a/sdk/tests/integration/close_position.test.ts b/sdk/tests/integration/close_position.test.ts deleted file mode 100644 index a50db8b..0000000 --- a/sdk/tests/integration/close_position.test.ts +++ /dev/null @@ -1,466 +0,0 @@ -import * as anchor from "@coral-xyz/anchor"; -import { AuthorityType } from "@solana/spl-token"; -import * as assert from "assert"; -import { toTx, WhirlpoolIx } from "../../src"; -import { WhirlpoolContext } from "../../src/context"; -import { - approveToken, - createAndMintToTokenAccount, - createTokenAccount, - setAuthority, - TickSpacing, - transferToken, - ZERO_BN -} from "../utils"; -import { defaultConfirmOptions } from "../utils/const"; -import { WhirlpoolTestFixture } from "../utils/fixture"; -import { initializePositionBundle, initTestPool, initTestPoolWithLiquidity, openBundledPosition, openPosition } from "../utils/init-utils"; - -describe("close_position", () => { - const provider = anchor.AnchorProvider.local(undefined, defaultConfirmOptions); - const program = anchor.workspace.Whirlpool; - const ctx = WhirlpoolContext.fromWorkspace(provider, program); - - it("successfully closes an open position", async () => { - const { poolInitInfo } = await initTestPool(ctx, TickSpacing.Standard); - - const { params } = await openPosition(ctx, poolInitInfo.whirlpoolPda.publicKey, 0, 128); - const receiverKeypair = anchor.web3.Keypair.generate(); - - await toTx( - ctx, - WhirlpoolIx.closePositionIx(ctx.program, { - positionAuthority: provider.wallet.publicKey, - receiver: receiverKeypair.publicKey, - position: params.positionPda.publicKey, - positionMint: params.positionMintAddress, - positionTokenAccount: params.positionTokenAccount, - }) - ).buildAndExecute(); - - const supplyResponse = await provider.connection.getTokenSupply(params.positionMintAddress); - assert.equal(supplyResponse.value.uiAmount, 0); - - assert.equal(await provider.connection.getAccountInfo(params.positionPda.publicKey), undefined); - assert.equal(await provider.connection.getAccountInfo(params.positionTokenAccount), undefined); - - const receiverAccount = await provider.connection.getAccountInfo(receiverKeypair.publicKey); - const lamports = receiverAccount?.lamports; - assert.ok(lamports != undefined && lamports > 0); - }); - - it("succeeds if the position is delegated", async () => { - const { poolInitInfo } = await initTestPool(ctx, TickSpacing.Standard); - - const owner = anchor.web3.Keypair.generate(); - const delegate = anchor.web3.Keypair.generate(); - - const { params } = await openPosition( - ctx, - poolInitInfo.whirlpoolPda.publicKey, - 0, - 128, - owner.publicKey - ); - - await approveToken(ctx.provider, params.positionTokenAccount, delegate.publicKey, 1, owner); - await setAuthority( - ctx.provider, - params.positionTokenAccount, - delegate.publicKey, - AuthorityType.CloseAccount, - owner - ); - - await toTx( - ctx, - WhirlpoolIx.closePositionIx(ctx.program, { - positionAuthority: delegate.publicKey, - receiver: owner.publicKey, - position: params.positionPda.publicKey, - positionMint: params.positionMintAddress, - positionTokenAccount: params.positionTokenAccount, - }) - ) - .addSigner(delegate) - .buildAndExecute(); - }); - - it("succeeds with the owner's signature even if the token is delegated", async () => { - const { poolInitInfo } = await initTestPool(ctx, TickSpacing.Standard); - - const owner = anchor.web3.Keypair.generate(); - const delegate = anchor.web3.Keypair.generate(); - - const { params } = await openPosition( - ctx, - poolInitInfo.whirlpoolPda.publicKey, - 0, - 128, - owner.publicKey - ); - - await approveToken(ctx.provider, params.positionTokenAccount, delegate.publicKey, 1, owner); - - await toTx( - ctx, - WhirlpoolIx.closePositionIx(ctx.program, { - positionAuthority: owner.publicKey, - receiver: owner.publicKey, - position: params.positionPda.publicKey, - positionMint: params.positionMintAddress, - positionTokenAccount: params.positionTokenAccount, - }) - ) - .addSigner(owner) - .buildAndExecute(); - }); - - it("succeeds with position token that was transferred to new owner", async () => { - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing: TickSpacing.Standard, - positions: [{ tickLowerIndex: 0, tickUpperIndex: 128, liquidityAmount: ZERO_BN }], - }); - const position = fixture.getInfos().positions[0]; - - const newOwner = anchor.web3.Keypair.generate(); - const newOwnerPositionTokenAccount = await createTokenAccount( - provider, - position.mintKeypair.publicKey, - newOwner.publicKey - ); - - await transferToken(provider, position.tokenAccount, newOwnerPositionTokenAccount, 1); - - await toTx( - ctx, - WhirlpoolIx.closePositionIx(ctx.program, { - positionAuthority: newOwner.publicKey, - receiver: newOwner.publicKey, - position: position.publicKey, - positionMint: position.mintKeypair.publicKey, - positionTokenAccount: newOwnerPositionTokenAccount, - }) - ) - .addSigner(newOwner) - .buildAndExecute(); - }); - - it("fails to close a position with liquidity", async () => { - const { positionInfo } = await initTestPoolWithLiquidity(ctx); - - const receiverKeypair = anchor.web3.Keypair.generate(); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.closePositionIx(ctx.program, { - positionAuthority: provider.wallet.publicKey, - receiver: receiverKeypair.publicKey, - position: positionInfo.positionPda.publicKey, - positionMint: positionInfo.positionMintAddress, - positionTokenAccount: positionInfo.positionTokenAccount, - }) - ).buildAndExecute(), - /0x1775/ // ClosePositionNotEmpty - ); - }); - - it("fails if owner is not signer", async () => { - const { poolInitInfo } = await initTestPool(ctx, TickSpacing.Standard); - - const owner = anchor.web3.Keypair.generate(); - - const { params } = await openPosition( - ctx, - poolInitInfo.whirlpoolPda.publicKey, - 0, - 128, - owner.publicKey - ); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.closePositionIx(ctx.program, { - positionAuthority: owner.publicKey, - receiver: owner.publicKey, - position: params.positionPda.publicKey, - positionMint: params.positionMintAddress, - positionTokenAccount: params.positionTokenAccount, - }) - ).buildAndExecute(), - /.*signature verification fail.*/i - ); - }); - - it("fails if delegate is not signer", async () => { - const { poolInitInfo } = await initTestPool(ctx, TickSpacing.Standard); - - const owner = anchor.web3.Keypair.generate(); - const delegate = anchor.web3.Keypair.generate(); - - const { params } = await openPosition( - ctx, - poolInitInfo.whirlpoolPda.publicKey, - 0, - 128, - owner.publicKey - ); - - await approveToken(ctx.provider, params.positionTokenAccount, delegate.publicKey, 1, owner); - await setAuthority( - ctx.provider, - params.positionTokenAccount, - delegate.publicKey, - AuthorityType.CloseAccount, - owner - ); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.closePositionIx(ctx.program, { - positionAuthority: delegate.publicKey, - receiver: owner.publicKey, - position: params.positionPda.publicKey, - positionMint: params.positionMintAddress, - positionTokenAccount: params.positionTokenAccount, - }) - ).buildAndExecute(), - /.*signature verification fail.*/i - ); - }); - - it("fails if the authority does not match", async () => { - const { poolInitInfo } = await initTestPool(ctx, TickSpacing.Standard); - - const owner = anchor.web3.Keypair.generate(); - const fakeOwner = anchor.web3.Keypair.generate(); - - const { params } = await openPosition( - ctx, - poolInitInfo.whirlpoolPda.publicKey, - 0, - 128, - owner.publicKey - ); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.closePositionIx(ctx.program, { - positionAuthority: fakeOwner.publicKey, - receiver: owner.publicKey, - position: params.positionPda.publicKey, - positionMint: params.positionMintAddress, - positionTokenAccount: params.positionTokenAccount, - }) - ) - .addSigner(fakeOwner) - .buildAndExecute(), - /0x1783/ // MissingOrInvalidDelegate - ); - }); - - it("fails if position token account does not contain exactly one token", async () => { - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing: TickSpacing.Standard, - positions: [{ tickLowerIndex: 0, tickUpperIndex: 128, liquidityAmount: ZERO_BN }], - }); - const position = fixture.getInfos().positions[0]; - - const fakePositionTokenAccount = await createTokenAccount( - provider, - position.mintKeypair.publicKey, - provider.wallet.publicKey - ); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.closePositionIx(ctx.program, { - positionAuthority: provider.wallet.publicKey, - receiver: provider.wallet.publicKey, - position: position.publicKey, - positionMint: position.mintKeypair.publicKey, - positionTokenAccount: fakePositionTokenAccount, - }) - ).buildAndExecute(), - /0x7d3/ // ConstraintRaw - ); - }); - - it("fails if delegated amount is 0", async () => { - const { poolInitInfo } = await initTestPool(ctx, TickSpacing.Standard); - - const owner = anchor.web3.Keypair.generate(); - const delegate = anchor.web3.Keypair.generate(); - - const { params } = await openPosition( - ctx, - poolInitInfo.whirlpoolPda.publicKey, - 0, - 128, - owner.publicKey - ); - - await approveToken(ctx.provider, params.positionTokenAccount, delegate.publicKey, 0, owner); - await setAuthority( - ctx.provider, - params.positionTokenAccount, - delegate.publicKey, - AuthorityType.CloseAccount, - owner - ); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.closePositionIx(ctx.program, { - positionAuthority: delegate.publicKey, - receiver: owner.publicKey, - position: params.positionPda.publicKey, - positionMint: params.positionMintAddress, - positionTokenAccount: params.positionTokenAccount, - }) - ) - .addSigner(delegate) - .buildAndExecute(), - /0x1784/ // InvalidPositionTokenAmount - ); - }); - - it("fails if positionAuthority does not match delegate", async () => { - const { poolInitInfo } = await initTestPool(ctx, TickSpacing.Standard); - - const owner = anchor.web3.Keypair.generate(); - const delegate = anchor.web3.Keypair.generate(); - const fakeDelegate = anchor.web3.Keypair.generate(); - - const { params } = await openPosition( - ctx, - poolInitInfo.whirlpoolPda.publicKey, - 0, - 128, - owner.publicKey - ); - - await approveToken(ctx.provider, params.positionTokenAccount, delegate.publicKey, 1, owner); - await setAuthority( - ctx.provider, - params.positionTokenAccount, - delegate.publicKey, - AuthorityType.CloseAccount, - owner - ); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.closePositionIx(ctx.program, { - positionAuthority: fakeDelegate.publicKey, - receiver: owner.publicKey, - position: params.positionPda.publicKey, - positionMint: params.positionMintAddress, - positionTokenAccount: params.positionTokenAccount, - }) - ) - .addSigner(fakeDelegate) - .buildAndExecute(), - /0x1783/ // MissingOrInvalidDelegate - ); - }); - - it("fails if position token account mint does not match position mint", async () => { - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing: TickSpacing.Standard, - positions: [{ tickLowerIndex: 0, tickUpperIndex: 128, liquidityAmount: ZERO_BN }], - }); - const { - poolInitInfo: { tokenMintA }, - positions, - } = fixture.getInfos(); - const position = positions[0]; - - const fakePositionTokenAccount = await createAndMintToTokenAccount(provider, tokenMintA, 1); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.closePositionIx(ctx.program, { - positionAuthority: provider.wallet.publicKey, - receiver: provider.wallet.publicKey, - position: position.publicKey, - positionMint: position.mintKeypair.publicKey, - positionTokenAccount: fakePositionTokenAccount, - }) - ).buildAndExecute(), - /0x7d3/ // ConstraintRaw - ); - }); - - it("fails if position_mint does not match position's position_mint field", async () => { - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing: TickSpacing.Standard, - positions: [{ tickLowerIndex: 0, tickUpperIndex: 128, liquidityAmount: ZERO_BN }], - }); - const { - poolInitInfo: { tokenMintA }, - positions, - } = fixture.getInfos(); - const position = positions[0]; - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.closePositionIx(ctx.program, { - positionAuthority: provider.wallet.publicKey, - receiver: provider.wallet.publicKey, - position: position.publicKey, - positionMint: tokenMintA, - positionTokenAccount: position.tokenAccount, - }) - ).buildAndExecute(), - // Seeds constraint added by adding PositionBundle, so ConstraintSeeds will be violated first - /0x7d6/ // ConstraintSeeds (seed constraint was violated) - ); - }); - - describe("bundled position", () => { - it("fails if position is BUNDLED position", async () => { - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing: TickSpacing.Standard, - positions: [], - }); - const { poolInitInfo } = fixture.getInfos(); - - // open bundled position - const positionBundleInfo = await initializePositionBundle(ctx); - const bundleIndex = 0; - const positionInitInfo = await openBundledPosition( - ctx, - poolInitInfo.whirlpoolPda.publicKey, - positionBundleInfo.positionBundleMintKeypair.publicKey, - bundleIndex, - 0, - 128, - ); - - // try to close bundled position - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.closePositionIx(ctx.program, { - positionAuthority: provider.wallet.publicKey, - receiver: provider.wallet.publicKey, - position: positionInitInfo.params.bundledPositionPda.publicKey, - positionMint: positionBundleInfo.positionBundleMintKeypair.publicKey, - positionTokenAccount: positionBundleInfo.positionBundleTokenAccount, - }) - ).buildAndExecute(), - /0x7d6/ // ConstraintSeeds (seed constraint was violated) - ); - }); - }); -}); diff --git a/sdk/tests/integration/collect_fees.test.ts b/sdk/tests/integration/collect_fees.test.ts deleted file mode 100644 index feb9031..0000000 --- a/sdk/tests/integration/collect_fees.test.ts +++ /dev/null @@ -1,673 +0,0 @@ -import * as anchor from "@coral-xyz/anchor"; -import { BN } from "@coral-xyz/anchor"; -import { MathUtil } from "@orca-so/common-sdk"; -import * as assert from "assert"; -import Decimal from "decimal.js"; -import { - collectFeesQuote, - PDAUtil, - PositionData, - TickArrayData, - TickArrayUtil, - toTx, - WhirlpoolContext, - WhirlpoolData, - WhirlpoolIx -} from "../../src"; -import { IGNORE_CACHE } from "../../src/network/public/fetcher"; -import { - approveToken, - createTokenAccount, - getTokenBalance, - TickSpacing, - transferToken, - ZERO_BN -} from "../utils"; -import { defaultConfirmOptions } from "../utils/const"; -import { WhirlpoolTestFixture } from "../utils/fixture"; -import { initTestPool } from "../utils/init-utils"; - -describe("collect_fees", () => { - const provider = anchor.AnchorProvider.local(undefined, defaultConfirmOptions); - const program = anchor.workspace.Whirlpool; - const ctx = WhirlpoolContext.fromWorkspace(provider, program); - const fetcher = ctx.fetcher; - - it("successfully collect fees", async () => { - // In same tick array - start index 22528 - const tickLowerIndex = 29440; - const tickUpperIndex = 33536; - - const tickSpacing = TickSpacing.Standard; - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing, - positions: [ - { tickLowerIndex, tickUpperIndex, liquidityAmount: new anchor.BN(10_000_000) }, // In range position - { tickLowerIndex: 0, tickUpperIndex: 128, liquidityAmount: new anchor.BN(1_000_000) }, // Out of range position - ], - }); - const { - poolInitInfo: { - whirlpoolPda, - tokenVaultAKeypair, - tokenVaultBKeypair, - tokenMintA, - tokenMintB, - }, - tokenAccountA, - tokenAccountB, - positions, - } = fixture.getInfos(); - - const tickArrayPda = PDAUtil.getTickArray(ctx.program.programId, whirlpoolPda.publicKey, 22528); - const positionBeforeSwap = (await fetcher.getPosition(positions[0].publicKey)) as PositionData; - assert.ok(positionBeforeSwap.feeOwedA.eq(ZERO_BN)); - assert.ok(positionBeforeSwap.feeOwedB.eq(ZERO_BN)); - - const oraclePda = PDAUtil.getOracle(ctx.program.programId, whirlpoolPda.publicKey); - - // Accrue fees in token A - await toTx( - ctx, - WhirlpoolIx.swapIx(ctx.program, { - amount: new BN(200_000), - otherAmountThreshold: ZERO_BN, - sqrtPriceLimit: MathUtil.toX64(new Decimal(4)), - amountSpecifiedIsInput: true, - aToB: true, - whirlpool: whirlpoolPda.publicKey, - tokenAuthority: ctx.wallet.publicKey, - tokenOwnerAccountA: tokenAccountA, - tokenVaultA: tokenVaultAKeypair.publicKey, - tokenOwnerAccountB: tokenAccountB, - tokenVaultB: tokenVaultBKeypair.publicKey, - tickArray0: tickArrayPda.publicKey, - tickArray1: tickArrayPda.publicKey, - tickArray2: tickArrayPda.publicKey, - oracle: oraclePda.publicKey, - }) - ).buildAndExecute(); - - // Accrue fees in token B - await toTx( - ctx, - WhirlpoolIx.swapIx(ctx.program, { - amount: new BN(200_000), - otherAmountThreshold: ZERO_BN, - sqrtPriceLimit: MathUtil.toX64(new Decimal(5)), - amountSpecifiedIsInput: true, - aToB: false, - whirlpool: whirlpoolPda.publicKey, - tokenAuthority: ctx.wallet.publicKey, - tokenOwnerAccountA: tokenAccountA, - tokenVaultA: tokenVaultAKeypair.publicKey, - tokenOwnerAccountB: tokenAccountB, - tokenVaultB: tokenVaultBKeypair.publicKey, - tickArray0: tickArrayPda.publicKey, - tickArray1: tickArrayPda.publicKey, - tickArray2: tickArrayPda.publicKey, - oracle: oraclePda.publicKey, - }) - ).buildAndExecute(); - - await toTx( - ctx, - WhirlpoolIx.updateFeesAndRewardsIx(ctx.program, { - whirlpool: whirlpoolPda.publicKey, - position: positions[0].publicKey, - tickArrayLower: tickArrayPda.publicKey, - tickArrayUpper: tickArrayPda.publicKey, - }) - ).buildAndExecute(); - - const positionBeforeCollect = (await fetcher.getPosition( - positions[0].publicKey, - IGNORE_CACHE - )) as PositionData; - assert.ok(positionBeforeCollect.feeOwedA.eq(new BN(581))); - assert.ok(positionBeforeCollect.feeOwedB.eq(new BN(581))); - - const feeAccountA = await createTokenAccount(provider, tokenMintA, provider.wallet.publicKey); - const feeAccountB = await createTokenAccount(provider, tokenMintB, provider.wallet.publicKey); - - // Generate collect fees expectation - const whirlpoolData = (await fetcher.getPool(whirlpoolPda.publicKey)) as WhirlpoolData; - const tickArrayData = (await fetcher.getTickArray(tickArrayPda.publicKey)) as TickArrayData; - const lowerTick = TickArrayUtil.getTickFromArray(tickArrayData, tickLowerIndex, tickSpacing); - const upperTick = TickArrayUtil.getTickFromArray(tickArrayData, tickUpperIndex, tickSpacing); - const expectation = collectFeesQuote({ - whirlpool: whirlpoolData, - position: positionBeforeCollect, - tickLower: lowerTick, - tickUpper: upperTick, - }); - - // Perform collect fees tx - await toTx( - ctx, - WhirlpoolIx.collectFeesIx(ctx.program, { - whirlpool: whirlpoolPda.publicKey, - positionAuthority: provider.wallet.publicKey, - position: positions[0].publicKey, - positionTokenAccount: positions[0].tokenAccount, - tokenOwnerAccountA: feeAccountA, - tokenOwnerAccountB: feeAccountB, - tokenVaultA: tokenVaultAKeypair.publicKey, - tokenVaultB: tokenVaultBKeypair.publicKey, - }) - ).buildAndExecute(); - const positionAfter = (await fetcher.getPosition(positions[0].publicKey, IGNORE_CACHE)) as PositionData; - const feeBalanceA = await getTokenBalance(provider, feeAccountA); - const feeBalanceB = await getTokenBalance(provider, feeAccountB); - - assert.equal(feeBalanceA, expectation.feeOwedA); - assert.equal(feeBalanceB, expectation.feeOwedB); - assert.ok(positionAfter.feeOwedA.eq(ZERO_BN)); - assert.ok(positionAfter.feeOwedB.eq(ZERO_BN)); - - // Assert out of range position values - await toTx( - ctx, - WhirlpoolIx.updateFeesAndRewardsIx(ctx.program, { - whirlpool: whirlpoolPda.publicKey, - position: positions[1].publicKey, - tickArrayLower: positions[1].tickArrayLower, - tickArrayUpper: positions[1].tickArrayUpper, - }) - ).buildAndExecute(); - const outOfRangePosition = await fetcher.getPosition(positions[1].publicKey, IGNORE_CACHE); - assert.ok(outOfRangePosition?.feeOwedA.eq(ZERO_BN)); - assert.ok(outOfRangePosition?.feeOwedB.eq(ZERO_BN)); - }); - - it("successfully collect fees with approved delegate", async () => { - const tickSpacing = TickSpacing.Standard; - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing, - positions: [ - { tickLowerIndex: 0, tickUpperIndex: 128, liquidityAmount: new anchor.BN(10_000_000) }, // In range position - ], - }); - const { - poolInitInfo: { whirlpoolPda, tokenVaultAKeypair, tokenVaultBKeypair }, - positions, - tokenAccountA, - tokenAccountB, - } = fixture.getInfos(); - const position = positions[0]; - - const delegate = anchor.web3.Keypair.generate(); - await approveToken(provider, position.tokenAccount, delegate.publicKey, 1); - - await toTx( - ctx, - WhirlpoolIx.collectFeesIx(ctx.program, { - whirlpool: whirlpoolPda.publicKey, - positionAuthority: delegate.publicKey, - position: position.publicKey, - positionTokenAccount: position.tokenAccount, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: tokenAccountB, - tokenVaultA: tokenVaultAKeypair.publicKey, - tokenVaultB: tokenVaultBKeypair.publicKey, - }) - ) - .addSigner(delegate) - .buildAndExecute(); - }); - - it("successfully collect fees with owner even if there is approved delegate", async () => { - const tickSpacing = TickSpacing.Standard; - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing, - positions: [ - { tickLowerIndex: 0, tickUpperIndex: 128, liquidityAmount: new anchor.BN(10_000_000) }, // In range position - ], - }); - const { - poolInitInfo: { whirlpoolPda, tokenVaultAKeypair, tokenVaultBKeypair }, - positions, - tokenAccountA, - tokenAccountB, - } = fixture.getInfos(); - const position = positions[0]; - - const delegate = anchor.web3.Keypair.generate(); - await approveToken(provider, position.tokenAccount, delegate.publicKey, 1); - - await toTx( - ctx, - WhirlpoolIx.collectFeesIx(ctx.program, { - whirlpool: whirlpoolPda.publicKey, - positionAuthority: provider.wallet.publicKey, - position: position.publicKey, - positionTokenAccount: position.tokenAccount, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: tokenAccountB, - tokenVaultA: tokenVaultAKeypair.publicKey, - tokenVaultB: tokenVaultBKeypair.publicKey, - }) - ).buildAndExecute(); - }); - - it("successfully collect fees with transferred position token", async () => { - const tickSpacing = TickSpacing.Standard; - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing, - positions: [ - { tickLowerIndex: 0, tickUpperIndex: 128, liquidityAmount: new anchor.BN(10_000_000) }, // In range position - ], - }); - const { - poolInitInfo: { whirlpoolPda, tokenVaultAKeypair, tokenVaultBKeypair }, - positions, - tokenAccountA, - tokenAccountB, - } = fixture.getInfos(); - const position = positions[0]; - - const newOwner = anchor.web3.Keypair.generate(); - const newOwnerPositionTokenAccount = await createTokenAccount( - provider, - position.mintKeypair.publicKey, - newOwner.publicKey - ); - - await transferToken(provider, position.tokenAccount, newOwnerPositionTokenAccount, 1); - - await toTx( - ctx, - WhirlpoolIx.collectFeesIx(ctx.program, { - whirlpool: whirlpoolPda.publicKey, - positionAuthority: newOwner.publicKey, - position: position.publicKey, - positionTokenAccount: newOwnerPositionTokenAccount, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: tokenAccountB, - tokenVaultA: tokenVaultAKeypair.publicKey, - tokenVaultB: tokenVaultBKeypair.publicKey, - }) - ) - .addSigner(newOwner) - .buildAndExecute(); - }); - - it("fails when position does not match whirlpool", async () => { - // In same tick array - start index 22528 - const tickLowerIndex = 29440; - const tickUpperIndex = 33536; - const tickSpacing = TickSpacing.Standard; - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing, - positions: [{ tickLowerIndex, tickUpperIndex, liquidityAmount: new anchor.BN(10_000_000) }], - }); - const { - poolInitInfo: { tokenVaultAKeypair, tokenVaultBKeypair }, - tokenAccountA, - tokenAccountB, - positions, - } = fixture.getInfos(); - - const { - poolInitInfo: { whirlpoolPda: whirlpoolPda2 }, - } = await initTestPool(ctx, tickSpacing); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.collectFeesIx(ctx.program, { - whirlpool: whirlpoolPda2.publicKey, - positionAuthority: provider.wallet.publicKey, - position: positions[0].publicKey, - positionTokenAccount: positions[0].tokenAccount, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: tokenAccountB, - tokenVaultA: tokenVaultAKeypair.publicKey, - tokenVaultB: tokenVaultBKeypair.publicKey, - }) - ).buildAndExecute(), - /0x7d1/ // ConstraintHasOne - ); - }); - - it("fails when position token account does not contain exactly one token", async () => { - // In same tick array - start index 22528 - const tickLowerIndex = 29440; - const tickUpperIndex = 33536; - const tickSpacing = TickSpacing.Standard; - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing, - positions: [{ tickLowerIndex, tickUpperIndex, liquidityAmount: new anchor.BN(10_000_000) }], - }); - const { - poolInitInfo: { whirlpoolPda, tokenVaultAKeypair, tokenVaultBKeypair }, - tokenAccountA, - tokenAccountB, - positions, - } = fixture.getInfos(); - - const positionTokenAccount2 = await createTokenAccount( - provider, - positions[0].mintKeypair.publicKey, - provider.wallet.publicKey - ); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.collectFeesIx(ctx.program, { - whirlpool: whirlpoolPda.publicKey, - positionAuthority: provider.wallet.publicKey, - position: positions[0].publicKey, - positionTokenAccount: positionTokenAccount2, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: tokenAccountB, - tokenVaultA: tokenVaultAKeypair.publicKey, - tokenVaultB: tokenVaultBKeypair.publicKey, - }) - ).buildAndExecute(), - /0x7d3/ // ConstraintRaw - ); - - await transferToken(provider, positions[0].tokenAccount, positionTokenAccount2, 1); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.collectFeesIx(ctx.program, { - whirlpool: whirlpoolPda.publicKey, - positionAuthority: provider.wallet.publicKey, - position: positions[0].publicKey, - positionTokenAccount: positions[0].tokenAccount, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: tokenAccountB, - tokenVaultA: tokenVaultAKeypair.publicKey, - tokenVaultB: tokenVaultBKeypair.publicKey, - }) - ).buildAndExecute(), - /0x7d3/ // ConstraintRaw - ); - }); - - it("fails when position authority is not approved delegate for position token account", async () => { - // In same tick array - start index 22528 - const tickLowerIndex = 29440; - const tickUpperIndex = 33536; - const tickSpacing = TickSpacing.Standard; - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing, - positions: [{ tickLowerIndex, tickUpperIndex, liquidityAmount: new anchor.BN(10_000_000) }], - }); - const { - poolInitInfo: { whirlpoolPda, tokenVaultAKeypair, tokenVaultBKeypair }, - tokenAccountA, - tokenAccountB, - positions, - } = fixture.getInfos(); - - const delegate = anchor.web3.Keypair.generate(); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.collectFeesIx(ctx.program, { - whirlpool: whirlpoolPda.publicKey, - positionAuthority: delegate.publicKey, - position: positions[0].publicKey, - positionTokenAccount: positions[0].tokenAccount, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: tokenAccountB, - tokenVaultA: tokenVaultAKeypair.publicKey, - tokenVaultB: tokenVaultBKeypair.publicKey, - }) - ) - .addSigner(delegate) - .buildAndExecute(), - /0x1783/ // MissingOrInvalidDelegate - ); - }); - - it("fails when position authority is not authorized to transfer exactly one token", async () => { - // In same tick array - start index 22528 - const tickLowerIndex = 29440; - const tickUpperIndex = 33536; - const tickSpacing = TickSpacing.Standard; - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing, - positions: [{ tickLowerIndex, tickUpperIndex, liquidityAmount: new anchor.BN(10_000_000) }], - }); - const { - poolInitInfo: { whirlpoolPda, tokenVaultAKeypair, tokenVaultBKeypair }, - tokenAccountA, - tokenAccountB, - positions, - } = fixture.getInfos(); - - const delegate = anchor.web3.Keypair.generate(); - await approveToken(provider, positions[0].tokenAccount, delegate.publicKey, 2); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.collectFeesIx(ctx.program, { - whirlpool: whirlpoolPda.publicKey, - positionAuthority: delegate.publicKey, - position: positions[0].publicKey, - positionTokenAccount: positions[0].tokenAccount, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: tokenAccountB, - tokenVaultA: tokenVaultAKeypair.publicKey, - tokenVaultB: tokenVaultBKeypair.publicKey, - }) - ) - .addSigner(delegate) - .buildAndExecute(), - /0x1784/ // InvalidPositionTokenAmount - ); - }); - - it("fails when position authority is not a signer", async () => { - // In same tick array - start index 22528 - const tickLowerIndex = 29440; - const tickUpperIndex = 33536; - const tickSpacing = TickSpacing.Standard; - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing, - positions: [{ tickLowerIndex, tickUpperIndex, liquidityAmount: new anchor.BN(10_000_000) }], - }); - const { - poolInitInfo: { whirlpoolPda, tokenVaultAKeypair, tokenVaultBKeypair }, - tokenAccountA, - tokenAccountB, - positions, - } = fixture.getInfos(); - - const delegate = anchor.web3.Keypair.generate(); - await approveToken(provider, positions[0].tokenAccount, delegate.publicKey, 1); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.collectFeesIx(ctx.program, { - whirlpool: whirlpoolPda.publicKey, - positionAuthority: delegate.publicKey, - position: positions[0].publicKey, - positionTokenAccount: positions[0].tokenAccount, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: tokenAccountB, - tokenVaultA: tokenVaultAKeypair.publicKey, - tokenVaultB: tokenVaultBKeypair.publicKey, - }) - ).buildAndExecute(), - /.*signature verification fail.*/i - ); - }); - - it("fails when position token account mint does not equal position mint", async () => { - // In same tick array - start index 22528 - const tickLowerIndex = 29440; - const tickUpperIndex = 33536; - const tickSpacing = TickSpacing.Standard; - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing, - positions: [{ tickLowerIndex, tickUpperIndex, liquidityAmount: new anchor.BN(10_000_000) }], - }); - const { - poolInitInfo: { whirlpoolPda, tokenVaultAKeypair, tokenVaultBKeypair, tokenMintA }, - tokenAccountA, - tokenAccountB, - positions, - } = fixture.getInfos(); - - const fakePositionTokenAccount = await createTokenAccount( - provider, - tokenMintA, - provider.wallet.publicKey - ); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.collectFeesIx(ctx.program, { - whirlpool: whirlpoolPda.publicKey, - positionAuthority: provider.wallet.publicKey, - position: positions[0].publicKey, - positionTokenAccount: fakePositionTokenAccount, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: tokenAccountB, - tokenVaultA: tokenVaultAKeypair.publicKey, - tokenVaultB: tokenVaultBKeypair.publicKey, - }) - ).buildAndExecute(), - /0x7d3/ // ConstraintRaw - ); - }); - - it("fails when token vault does not match whirlpool token vault", async () => { - // In same tick array - start index 22528 - const tickLowerIndex = 29440; - const tickUpperIndex = 33536; - const tickSpacing = TickSpacing.Standard; - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing, - positions: [{ tickLowerIndex, tickUpperIndex, liquidityAmount: new anchor.BN(10_000_000) }], - }); - const { - poolInitInfo: { - whirlpoolPda, - tokenVaultAKeypair, - tokenVaultBKeypair, - tokenMintA, - tokenMintB, - }, - tokenAccountA, - tokenAccountB, - positions, - } = fixture.getInfos(); - - const fakeVaultA = await createTokenAccount(provider, tokenMintA, provider.wallet.publicKey); - const fakeVaultB = await createTokenAccount(provider, tokenMintB, provider.wallet.publicKey); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.collectFeesIx(ctx.program, { - whirlpool: whirlpoolPda.publicKey, - positionAuthority: provider.wallet.publicKey, - position: positions[0].publicKey, - positionTokenAccount: positions[0].tokenAccount, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: tokenAccountB, - tokenVaultA: fakeVaultA, - tokenVaultB: tokenVaultBKeypair.publicKey, - }) - ).buildAndExecute(), - /0x7dc/ // ConstraintAddress - ); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.collectFeesIx(ctx.program, { - whirlpool: whirlpoolPda.publicKey, - positionAuthority: provider.wallet.publicKey, - position: positions[0].publicKey, - positionTokenAccount: positions[0].tokenAccount, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: tokenAccountB, - tokenVaultA: tokenVaultAKeypair.publicKey, - tokenVaultB: fakeVaultB, - }) - ).buildAndExecute(), - /0x7dc/ // ConstraintAddress - ); - }); - - it("fails when owner token account mint does not match whirlpool token mint", async () => { - // In same tick array - start index 22528 - const tickLowerIndex = 29440; - const tickUpperIndex = 33536; - const tickSpacing = TickSpacing.Standard; - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing, - positions: [{ tickLowerIndex, tickUpperIndex, liquidityAmount: new anchor.BN(10_000_000) }], - }); - const { - poolInitInfo: { - whirlpoolPda, - tokenVaultAKeypair, - tokenVaultBKeypair, - tokenMintA, - tokenMintB, - }, - tokenAccountA, - tokenAccountB, - positions, - } = fixture.getInfos(); - - const invalidOwnerAccountA = await createTokenAccount( - provider, - tokenMintB, - provider.wallet.publicKey - ); - const invalidOwnerAccountB = await createTokenAccount( - provider, - tokenMintA, - provider.wallet.publicKey - ); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.collectFeesIx(ctx.program, { - whirlpool: whirlpoolPda.publicKey, - positionAuthority: provider.wallet.publicKey, - position: positions[0].publicKey, - positionTokenAccount: positions[0].tokenAccount, - tokenOwnerAccountA: invalidOwnerAccountA, - tokenOwnerAccountB: tokenAccountB, - tokenVaultA: tokenVaultAKeypair.publicKey, - tokenVaultB: tokenVaultBKeypair.publicKey, - }) - ).buildAndExecute(), - /0x7d3/ // ConstraintRaw - ); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.collectFeesIx(ctx.program, { - whirlpool: whirlpoolPda.publicKey, - positionAuthority: provider.wallet.publicKey, - position: positions[0].publicKey, - positionTokenAccount: positions[0].tokenAccount, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: invalidOwnerAccountB, - tokenVaultA: tokenVaultAKeypair.publicKey, - tokenVaultB: tokenVaultBKeypair.publicKey, - }) - ).buildAndExecute(), - /0x7d3/ // ConstraintRaw - ); - }); -}); diff --git a/sdk/tests/integration/collect_protocol_fees.test.ts b/sdk/tests/integration/collect_protocol_fees.test.ts deleted file mode 100644 index f01d9a4..0000000 --- a/sdk/tests/integration/collect_protocol_fees.test.ts +++ /dev/null @@ -1,368 +0,0 @@ -import * as anchor from "@coral-xyz/anchor"; -import { BN } from "@coral-xyz/anchor"; -import { MathUtil } from "@orca-so/common-sdk"; -import * as assert from "assert"; -import Decimal from "decimal.js"; -import { PDAUtil, toTx, WhirlpoolContext, WhirlpoolData, WhirlpoolIx } from "../../src"; -import { IGNORE_CACHE } from "../../src/network/public/fetcher"; -import { createTokenAccount, getTokenBalance, TickSpacing, ZERO_BN } from "../utils"; -import { defaultConfirmOptions } from "../utils/const"; -import { WhirlpoolTestFixture } from "../utils/fixture"; -import { initTestPool } from "../utils/init-utils"; - -describe("collect_protocol_fees", () => { - const provider = anchor.AnchorProvider.local(undefined, defaultConfirmOptions); - - const program = anchor.workspace.Whirlpool; - const ctx = WhirlpoolContext.fromWorkspace(provider, program); - const fetcher = ctx.fetcher; - - it("successfully collects fees", async () => { - // In same tick array - start index 22528 - const tickLowerIndex = 29440; - const tickUpperIndex = 33536; - - const tickSpacing = TickSpacing.Standard; - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing, - positions: [{ tickLowerIndex, tickUpperIndex, liquidityAmount: new anchor.BN(10_000_000) }], - }); - const { - poolInitInfo: { - whirlpoolPda, - tokenVaultAKeypair, - tokenVaultBKeypair, - tokenMintA, - tokenMintB, - }, - configKeypairs: { feeAuthorityKeypair, collectProtocolFeesAuthorityKeypair }, - configInitInfo: { whirlpoolsConfigKeypair: whirlpoolsConfigKeypair }, - tokenAccountA, - tokenAccountB, - positions, - } = fixture.getInfos(); - - await toTx( - ctx, - WhirlpoolIx.setProtocolFeeRateIx(ctx.program, { - whirlpool: whirlpoolPda.publicKey, - whirlpoolsConfig: whirlpoolsConfigKeypair.publicKey, - feeAuthority: feeAuthorityKeypair.publicKey, - protocolFeeRate: 2500, - }) - ) - .addSigner(feeAuthorityKeypair) - .buildAndExecute(); - - const poolBefore = (await fetcher.getPool(whirlpoolPda.publicKey, IGNORE_CACHE)) as WhirlpoolData; - assert.ok(poolBefore?.protocolFeeOwedA.eq(ZERO_BN)); - assert.ok(poolBefore?.protocolFeeOwedB.eq(ZERO_BN)); - - const tickArrayPda = positions[0].tickArrayLower; - - const oraclePda = PDAUtil.getOracle(ctx.program.programId, whirlpoolPda.publicKey); - - // Accrue fees in token A - await toTx( - ctx, - WhirlpoolIx.swapIx(ctx.program, { - amount: new BN(200_000), - otherAmountThreshold: ZERO_BN, - sqrtPriceLimit: MathUtil.toX64(new Decimal(4)), - amountSpecifiedIsInput: true, - aToB: true, - whirlpool: whirlpoolPda.publicKey, - tokenAuthority: ctx.wallet.publicKey, - tokenOwnerAccountA: tokenAccountA, - tokenVaultA: tokenVaultAKeypair.publicKey, - tokenOwnerAccountB: tokenAccountB, - tokenVaultB: tokenVaultBKeypair.publicKey, - tickArray0: tickArrayPda, - tickArray1: tickArrayPda, - tickArray2: tickArrayPda, - oracle: oraclePda.publicKey, - }) - ).buildAndExecute(); - - // Accrue fees in token B - await toTx( - ctx, - WhirlpoolIx.swapIx(ctx.program, { - amount: new BN(200_000), - otherAmountThreshold: ZERO_BN, - sqrtPriceLimit: MathUtil.toX64(new Decimal(5)), - amountSpecifiedIsInput: true, - aToB: false, - whirlpool: whirlpoolPda.publicKey, - tokenAuthority: ctx.wallet.publicKey, - tokenOwnerAccountA: tokenAccountA, - tokenVaultA: tokenVaultAKeypair.publicKey, - tokenOwnerAccountB: tokenAccountB, - tokenVaultB: tokenVaultBKeypair.publicKey, - tickArray0: tickArrayPda, - tickArray1: tickArrayPda, - tickArray2: tickArrayPda, - oracle: oraclePda.publicKey, - }) - ).buildAndExecute(); - - const poolAfter = (await fetcher.getPool(whirlpoolPda.publicKey, IGNORE_CACHE)) as WhirlpoolData; - assert.ok(poolAfter?.protocolFeeOwedA.eq(new BN(150))); - assert.ok(poolAfter?.protocolFeeOwedB.eq(new BN(150))); - - const destA = await createTokenAccount(provider, tokenMintA, provider.wallet.publicKey); - const destB = await createTokenAccount(provider, tokenMintB, provider.wallet.publicKey); - - await toTx( - ctx, - WhirlpoolIx.collectProtocolFeesIx(ctx.program, { - whirlpoolsConfig: whirlpoolsConfigKeypair.publicKey, - whirlpool: whirlpoolPda.publicKey, - collectProtocolFeesAuthority: collectProtocolFeesAuthorityKeypair.publicKey, - tokenVaultA: tokenVaultAKeypair.publicKey, - tokenVaultB: tokenVaultBKeypair.publicKey, - tokenOwnerAccountA: destA, - tokenOwnerAccountB: destB, - }) - ) - .addSigner(collectProtocolFeesAuthorityKeypair) - .buildAndExecute(); - - const balanceDestA = await getTokenBalance(provider, destA); - const balanceDestB = await getTokenBalance(provider, destB); - assert.equal(balanceDestA, "150"); - assert.equal(balanceDestB, "150"); - assert.ok(poolBefore?.protocolFeeOwedA.eq(ZERO_BN)); - assert.ok(poolBefore?.protocolFeeOwedB.eq(ZERO_BN)); - }); - - it("fails to collect fees without the authority's signature", async () => { - const tickSpacing = TickSpacing.Standard; - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing, - positions: [ - { tickLowerIndex: 29440, tickUpperIndex: 33536, liquidityAmount: new anchor.BN(10_000_000) }, - ], - }); - const { - poolInitInfo: { whirlpoolPda, tokenVaultAKeypair, tokenVaultBKeypair }, - configKeypairs: { collectProtocolFeesAuthorityKeypair }, - configInitInfo: { whirlpoolsConfigKeypair }, - tokenAccountA, - tokenAccountB, - } = fixture.getInfos(); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.collectProtocolFeesIx(ctx.program, { - whirlpoolsConfig: whirlpoolsConfigKeypair.publicKey, - whirlpool: whirlpoolPda.publicKey, - collectProtocolFeesAuthority: collectProtocolFeesAuthorityKeypair.publicKey, - tokenVaultA: tokenVaultAKeypair.publicKey, - tokenVaultB: tokenVaultBKeypair.publicKey, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: tokenAccountB, - }) - ).buildAndExecute(), - /.*signature verification fail.*/i - ); - }); - - it("fails when collect_protocol_fees_authority is invalid", async () => { - const tickSpacing = TickSpacing.Standard; - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing, - positions: [ - { tickLowerIndex: 29440, tickUpperIndex: 33536, liquidityAmount: new anchor.BN(10_000_000) }, - ], - }); - const { - poolInitInfo: { whirlpoolPda, tokenVaultAKeypair, tokenVaultBKeypair }, - configKeypairs: { rewardEmissionsSuperAuthorityKeypair }, - configInitInfo: { whirlpoolsConfigKeypair }, - tokenAccountA, - tokenAccountB, - } = fixture.getInfos(); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.collectProtocolFeesIx(ctx.program, { - whirlpoolsConfig: whirlpoolsConfigKeypair.publicKey, - whirlpool: whirlpoolPda.publicKey, - collectProtocolFeesAuthority: rewardEmissionsSuperAuthorityKeypair.publicKey, - tokenVaultA: tokenVaultAKeypair.publicKey, - tokenVaultB: tokenVaultBKeypair.publicKey, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: tokenAccountB, - }) - ) - .addSigner(rewardEmissionsSuperAuthorityKeypair) - .buildAndExecute(), - /0x7dc/ // ConstraintAddress - ); - }); - - it("fails when whirlpool does not match config", async () => { - const tickSpacing = TickSpacing.Standard; - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing, - positions: [ - { tickLowerIndex: 29440, tickUpperIndex: 33536, liquidityAmount: new anchor.BN(10_000_000) }, - ], - }); - const { - poolInitInfo: { tokenVaultAKeypair, tokenVaultBKeypair }, - configKeypairs: { collectProtocolFeesAuthorityKeypair }, - configInitInfo: { whirlpoolsConfigKeypair }, - tokenAccountA, - tokenAccountB, - } = fixture.getInfos(); - const { - poolInitInfo: { whirlpoolPda: whirlpoolPda2 }, - } = await initTestPool(ctx, tickSpacing); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.collectProtocolFeesIx(ctx.program, { - whirlpoolsConfig: whirlpoolsConfigKeypair.publicKey, - whirlpool: whirlpoolPda2.publicKey, - collectProtocolFeesAuthority: collectProtocolFeesAuthorityKeypair.publicKey, - tokenVaultA: tokenVaultAKeypair.publicKey, - tokenVaultB: tokenVaultBKeypair.publicKey, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: tokenAccountB, - }) - ) - .addSigner(collectProtocolFeesAuthorityKeypair) - .buildAndExecute(), - /0x7d1/ // ConstraintHasOne - ); - }); - - it("fails when vaults do not match whirlpool vaults", async () => { - const tickSpacing = TickSpacing.Standard; - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing, - positions: [ - { tickLowerIndex: 29440, tickUpperIndex: 33536, liquidityAmount: new anchor.BN(10_000_000) }, - ], - }); - const { - poolInitInfo: { - whirlpoolPda, - tokenVaultAKeypair, - tokenVaultBKeypair, - tokenMintA, - tokenMintB, - }, - configKeypairs: { collectProtocolFeesAuthorityKeypair }, - configInitInfo: { whirlpoolsConfigKeypair: whirlpoolsConfigKeypair }, - tokenAccountA, - tokenAccountB, - } = fixture.getInfos(); - - const fakeVaultA = await createTokenAccount(provider, tokenMintA, provider.wallet.publicKey); - const fakeVaultB = await createTokenAccount(provider, tokenMintB, provider.wallet.publicKey); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.collectProtocolFeesIx(ctx.program, { - whirlpoolsConfig: whirlpoolsConfigKeypair.publicKey, - whirlpool: whirlpoolPda.publicKey, - collectProtocolFeesAuthority: collectProtocolFeesAuthorityKeypair.publicKey, - tokenVaultA: fakeVaultA, - tokenVaultB: tokenVaultBKeypair.publicKey, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: tokenAccountB, - }) - ) - .addSigner(collectProtocolFeesAuthorityKeypair) - .buildAndExecute(), - /0x7dc/ // ConstraintAddress - ); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.collectProtocolFeesIx(ctx.program, { - whirlpoolsConfig: whirlpoolsConfigKeypair.publicKey, - whirlpool: whirlpoolPda.publicKey, - collectProtocolFeesAuthority: collectProtocolFeesAuthorityKeypair.publicKey, - tokenVaultA: tokenVaultAKeypair.publicKey, - tokenVaultB: fakeVaultB, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: tokenAccountB, - }) - ) - .addSigner(collectProtocolFeesAuthorityKeypair) - .buildAndExecute(), - /0x7dc/ // ConstraintAddress - ); - }); - - it("fails when destination mints do not match whirlpool mints", async () => { - const tickSpacing = TickSpacing.Standard; - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing, - positions: [ - { tickLowerIndex: 29440, tickUpperIndex: 33536, liquidityAmount: new anchor.BN(10_000_000) }, - ], - }); - const { - poolInitInfo: { - whirlpoolPda, - tokenVaultAKeypair, - tokenVaultBKeypair, - tokenMintA, - tokenMintB, - }, - configKeypairs: { collectProtocolFeesAuthorityKeypair }, - configInitInfo: { whirlpoolsConfigKeypair: whirlpoolsConfigKepair }, - tokenAccountA, - tokenAccountB, - } = fixture.getInfos(); - - const invalidDestA = await createTokenAccount(provider, tokenMintB, provider.wallet.publicKey); - const invalidDestB = await createTokenAccount(provider, tokenMintA, provider.wallet.publicKey); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.collectProtocolFeesIx(ctx.program, { - whirlpoolsConfig: whirlpoolsConfigKepair.publicKey, - whirlpool: whirlpoolPda.publicKey, - collectProtocolFeesAuthority: collectProtocolFeesAuthorityKeypair.publicKey, - tokenVaultA: tokenVaultAKeypair.publicKey, - tokenVaultB: tokenVaultBKeypair.publicKey, - tokenOwnerAccountA: invalidDestA, - tokenOwnerAccountB: tokenAccountB, - }) - ) - .addSigner(collectProtocolFeesAuthorityKeypair) - .buildAndExecute(), - /0x7d3/ // ConstraintRaw - ); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.collectProtocolFeesIx(ctx.program, { - whirlpoolsConfig: whirlpoolsConfigKepair.publicKey, - whirlpool: whirlpoolPda.publicKey, - collectProtocolFeesAuthority: collectProtocolFeesAuthorityKeypair.publicKey, - tokenVaultA: tokenVaultAKeypair.publicKey, - tokenVaultB: tokenVaultBKeypair.publicKey, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: invalidDestB, - }) - ) - .addSigner(collectProtocolFeesAuthorityKeypair) - .buildAndExecute(), - /0x7d3/ // ConstraintRaw - ); - }); -}); diff --git a/sdk/tests/integration/collect_reward.test.ts b/sdk/tests/integration/collect_reward.test.ts deleted file mode 100644 index a39f11b..0000000 --- a/sdk/tests/integration/collect_reward.test.ts +++ /dev/null @@ -1,749 +0,0 @@ -import * as anchor from "@coral-xyz/anchor"; -import { BN } from "@coral-xyz/anchor"; -import { MathUtil } from "@orca-so/common-sdk"; -import * as assert from "assert"; -import Decimal from "decimal.js"; -import { - buildWhirlpoolClient, - collectRewardsQuote, - NUM_REWARDS, toTx, - WhirlpoolContext, WhirlpoolIx -} from "../../src"; -import { IGNORE_CACHE } from "../../src/network/public/fetcher"; -import { - approveToken, - createAndMintToTokenAccount, - createMint, - createTokenAccount, - getTokenBalance, - sleep, - TickSpacing, - transferToken, - ZERO_BN -} from "../utils"; -import { defaultConfirmOptions } from "../utils/const"; -import { WhirlpoolTestFixture } from "../utils/fixture"; -import { initTestPool } from "../utils/init-utils"; - -describe("collect_reward", () => { - const provider = anchor.AnchorProvider.local(undefined, defaultConfirmOptions); - - const program = anchor.workspace.Whirlpool; - const ctx = WhirlpoolContext.fromWorkspace(provider, program); - const fetcher = ctx.fetcher; - const client = buildWhirlpoolClient(ctx); - - it("successfully collect rewards", async () => { - const vaultStartBalance = 1_000_000; - const lowerTickIndex = -1280, - upperTickIndex = 1280, - tickSpacing = TickSpacing.Standard; - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing: tickSpacing, - initialSqrtPrice: MathUtil.toX64(new Decimal(1)), - positions: [ - { - tickLowerIndex: lowerTickIndex, - tickUpperIndex: upperTickIndex, - liquidityAmount: new anchor.BN(1_000_000), - }, - ], - rewards: [ - { - emissionsPerSecondX64: MathUtil.toX64(new Decimal(10)), - vaultAmount: new BN(vaultStartBalance), - }, - { - emissionsPerSecondX64: MathUtil.toX64(new Decimal(10)), - vaultAmount: new BN(vaultStartBalance), - }, - { - emissionsPerSecondX64: MathUtil.toX64(new Decimal(10)), - vaultAmount: new BN(vaultStartBalance), - }, - ], - }); - const { - poolInitInfo: { whirlpoolPda }, - positions, - rewards, - } = fixture.getInfos(); - - // accrue rewards - await sleep(1200); - - await toTx( - ctx, - WhirlpoolIx.updateFeesAndRewardsIx(ctx.program, { - whirlpool: whirlpoolPda.publicKey, - position: positions[0].publicKey, - tickArrayLower: positions[0].tickArrayLower, - tickArrayUpper: positions[0].tickArrayUpper, - }) - ).buildAndExecute(); - - // Generate collect reward expectation - const pool = await client.getPool(whirlpoolPda.publicKey, IGNORE_CACHE); - const positionPreCollect = await client.getPosition(positions[0].publicKey, IGNORE_CACHE); - - // Lock the collectRewards quote to the last time we called updateFeesAndRewards - const expectation = collectRewardsQuote({ - whirlpool: pool.getData(), - position: positionPreCollect.getData(), - tickLower: positionPreCollect.getLowerTickData(), - tickUpper: positionPreCollect.getUpperTickData(), - timeStampInSeconds: pool.getData().rewardLastUpdatedTimestamp - }); - - // Check that the expectation is not zero - for (let i = 0; i < NUM_REWARDS; i++) { - assert.ok(!expectation[i]!.isZero()); - } - - // Perform collect rewards tx - for (let i = 0; i < NUM_REWARDS; i++) { - const rewardOwnerAccount = await createTokenAccount( - provider, - rewards[i].rewardMint, - provider.wallet.publicKey - ); - - await toTx( - ctx, - WhirlpoolIx.collectRewardIx(ctx.program, { - whirlpool: whirlpoolPda.publicKey, - positionAuthority: provider.wallet.publicKey, - position: positions[0].publicKey, - positionTokenAccount: positions[0].tokenAccount, - rewardOwnerAccount: rewardOwnerAccount, - rewardVault: rewards[i].rewardVaultKeypair.publicKey, - rewardIndex: i, - }) - ).buildAndExecute(); - - const collectedBalance = parseInt(await getTokenBalance(provider, rewardOwnerAccount)); - assert.equal(collectedBalance, expectation[i]?.toNumber()); - const vaultBalance = parseInt( - await getTokenBalance(provider, rewards[i].rewardVaultKeypair.publicKey) - ); - assert.equal(vaultStartBalance - collectedBalance, vaultBalance); - const position = await fetcher.getPosition(positions[0].publicKey, IGNORE_CACHE); - assert.equal(position?.rewardInfos[i].amountOwed, 0); - assert.ok(position?.rewardInfos[i].growthInsideCheckpoint.gte(ZERO_BN)); - } - }); - - it("successfully collect reward with a position authority delegate", async () => { - const vaultStartBalance = 1_000_000; - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing: TickSpacing.Standard, - initialSqrtPrice: MathUtil.toX64(new Decimal(1)), - positions: [ - { tickLowerIndex: -1280, tickUpperIndex: 1280, liquidityAmount: new anchor.BN(1_000_000) }, - ], - rewards: [ - { - emissionsPerSecondX64: MathUtil.toX64(new Decimal(2)), - vaultAmount: new BN(vaultStartBalance), - }, - ], - }); - const { - poolInitInfo: { whirlpoolPda }, - positions, - rewards, - } = fixture.getInfos(); - - // accrue rewards - await sleep(1200); - - const rewardOwnerAccount = await createTokenAccount( - provider, - rewards[0].rewardMint, - provider.wallet.publicKey - ); - - await toTx( - ctx, - WhirlpoolIx.updateFeesAndRewardsIx(ctx.program, { - whirlpool: whirlpoolPda.publicKey, - position: positions[0].publicKey, - tickArrayLower: positions[0].tickArrayLower, - tickArrayUpper: positions[0].tickArrayUpper, - }) - ).buildAndExecute(); - - const delegate = anchor.web3.Keypair.generate(); - await approveToken(provider, positions[0].tokenAccount, delegate.publicKey, 1); - - await toTx( - ctx, - WhirlpoolIx.collectRewardIx(ctx.program, { - whirlpool: whirlpoolPda.publicKey, - positionAuthority: delegate.publicKey, - position: positions[0].publicKey, - positionTokenAccount: positions[0].tokenAccount, - rewardOwnerAccount, - rewardVault: rewards[0].rewardVaultKeypair.publicKey, - rewardIndex: 0, - }) - ) - .addSigner(delegate) - .buildAndExecute(); - }); - - it("successfully collect reward with transferred position token", async () => { - const vaultStartBalance = 1_000_000; - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing: TickSpacing.Standard, - initialSqrtPrice: MathUtil.toX64(new Decimal(1)), - positions: [ - { tickLowerIndex: -1280, tickUpperIndex: 1280, liquidityAmount: new anchor.BN(1_000_000) }, - ], - rewards: [ - { - emissionsPerSecondX64: MathUtil.toX64(new Decimal(2)), - vaultAmount: new BN(vaultStartBalance), - }, - ], - }); - const { - poolInitInfo: { whirlpoolPda }, - positions, - rewards, - } = fixture.getInfos(); - - // accrue rewards - await sleep(1200); - - const rewardOwnerAccount = await createTokenAccount( - provider, - rewards[0].rewardMint, - provider.wallet.publicKey - ); - - const delegate = anchor.web3.Keypair.generate(); - const delegatePositionAccount = await createTokenAccount( - provider, - positions[0].mintKeypair.publicKey, - delegate.publicKey - ); - await transferToken(provider, positions[0].tokenAccount, delegatePositionAccount, 1); - - await toTx( - ctx, - WhirlpoolIx.updateFeesAndRewardsIx(ctx.program, { - whirlpool: whirlpoolPda.publicKey, - position: positions[0].publicKey, - tickArrayLower: positions[0].tickArrayLower, - tickArrayUpper: positions[0].tickArrayUpper, - }) - ).buildAndExecute(); - - await toTx( - ctx, - WhirlpoolIx.collectRewardIx(ctx.program, { - whirlpool: whirlpoolPda.publicKey, - positionAuthority: delegate.publicKey, - position: positions[0].publicKey, - positionTokenAccount: delegatePositionAccount, - rewardOwnerAccount, - rewardVault: rewards[0].rewardVaultKeypair.publicKey, - rewardIndex: 0, - }) - ) - .addSigner(delegate) - .buildAndExecute(); - }); - - it("successfully collect reward with owner even when there is a delegate", async () => { - const vaultStartBalance = 1_000_000; - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing: TickSpacing.Standard, - initialSqrtPrice: MathUtil.toX64(new Decimal(1)), - positions: [ - { tickLowerIndex: -1280, tickUpperIndex: 1280, liquidityAmount: new anchor.BN(1_000_000) }, - ], - rewards: [ - { - emissionsPerSecondX64: MathUtil.toX64(new Decimal(2)), - vaultAmount: new BN(vaultStartBalance), - }, - ], - }); - const { - poolInitInfo: { whirlpoolPda }, - positions, - rewards, - } = fixture.getInfos(); - - // accrue rewards - await sleep(1200); - - const rewardOwnerAccount = await createTokenAccount( - provider, - rewards[0].rewardMint, - provider.wallet.publicKey - ); - - await toTx( - ctx, - WhirlpoolIx.updateFeesAndRewardsIx(ctx.program, { - whirlpool: whirlpoolPda.publicKey, - position: positions[0].publicKey, - tickArrayLower: positions[0].tickArrayLower, - tickArrayUpper: positions[0].tickArrayUpper, - }) - ).buildAndExecute(); - - const delegate = anchor.web3.Keypair.generate(); - await approveToken(provider, positions[0].tokenAccount, delegate.publicKey, 1); - - await toTx( - ctx, - WhirlpoolIx.collectRewardIx(ctx.program, { - whirlpool: whirlpoolPda.publicKey, - positionAuthority: provider.wallet.publicKey, - position: positions[0].publicKey, - positionTokenAccount: positions[0].tokenAccount, - rewardOwnerAccount, - rewardVault: rewards[0].rewardVaultKeypair.publicKey, - rewardIndex: 0, - }) - ).buildAndExecute(); - }); - - it("fails when reward index references an uninitialized reward", async () => { - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing: TickSpacing.Standard, - initialSqrtPrice: MathUtil.toX64(new Decimal(1)), - positions: [ - { tickLowerIndex: -1280, tickUpperIndex: 1280, liquidityAmount: new anchor.BN(1_000_000) }, - ], - }); - const { - poolInitInfo: { whirlpoolPda }, - positions, - } = fixture.getInfos(); - - // accrue rewards - await sleep(1200); - - const fakeRewardMint = await createMint(provider); - const rewardOwnerAccount = await createTokenAccount( - provider, - fakeRewardMint, - provider.wallet.publicKey - ); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.collectRewardIx(ctx.program, { - whirlpool: whirlpoolPda.publicKey, - positionAuthority: provider.wallet.publicKey, - position: positions[0].publicKey, - positionTokenAccount: positions[0].tokenAccount, - rewardOwnerAccount, - rewardVault: anchor.web3.PublicKey.default, - rewardIndex: 0, - }) - ).buildAndExecute(), - /0xbbf/ // AccountNotInitialized - ); - }); - - it("fails when position does not match whirlpool", async () => { - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing: TickSpacing.Standard, - initialSqrtPrice: MathUtil.toX64(new Decimal(1)), - positions: [ - { tickLowerIndex: -1280, tickUpperIndex: 1280, liquidityAmount: new anchor.BN(1_000_000) }, - ], - rewards: [ - { emissionsPerSecondX64: MathUtil.toX64(new Decimal(2)), vaultAmount: new BN(1_000_000) }, - ], - }); - const { positions, rewards } = fixture.getInfos(); - - // accrue rewards - await sleep(1200); - - const { - poolInitInfo: { whirlpoolPda }, - } = await initTestPool(ctx, TickSpacing.Standard); - const rewardOwnerAccount = await createTokenAccount( - provider, - rewards[0].rewardMint, - provider.wallet.publicKey - ); - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.collectRewardIx(ctx.program, { - whirlpool: whirlpoolPda.publicKey, - positionAuthority: provider.wallet.publicKey, - position: positions[0].publicKey, - positionTokenAccount: positions[0].tokenAccount, - rewardOwnerAccount, - rewardVault: rewards[0].rewardVaultKeypair.publicKey, - rewardIndex: 0, - }) - ).buildAndExecute(), - /0x7d1/ // ConstraintHasOne - ); - }); - - it("fails when position token account does not have exactly one token", async () => { - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing: TickSpacing.Standard, - initialSqrtPrice: MathUtil.toX64(new Decimal(1)), - positions: [ - { tickLowerIndex: -1280, tickUpperIndex: 1280, liquidityAmount: new anchor.BN(1_000_000) }, - ], - rewards: [ - { emissionsPerSecondX64: MathUtil.toX64(new Decimal(2)), vaultAmount: new BN(1_000_000) }, - ], - }); - const { - poolInitInfo: { whirlpoolPda }, - positions, - rewards, - } = fixture.getInfos(); - - // accrue rewards - await sleep(1200); - - const rewardOwnerAccount = await createTokenAccount( - provider, - rewards[0].rewardMint, - provider.wallet.publicKey - ); - const otherPositionAcount = await createTokenAccount( - provider, - positions[0].mintKeypair.publicKey, - provider.wallet.publicKey - ); - await transferToken(provider, positions[0].tokenAccount, otherPositionAcount, 1); - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.collectRewardIx(ctx.program, { - whirlpool: whirlpoolPda.publicKey, - positionAuthority: provider.wallet.publicKey, - position: positions[0].publicKey, - positionTokenAccount: positions[0].tokenAccount, - rewardOwnerAccount, - rewardVault: rewards[0].rewardVaultKeypair.publicKey, - rewardIndex: 0, - }) - ).buildAndExecute(), - /0x7d3/ // ConstraintRaw - ); - }); - - it("fails when position token account mint does not match position mint", async () => { - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing: TickSpacing.Standard, - initialSqrtPrice: MathUtil.toX64(new Decimal(1)), - positions: [ - { tickLowerIndex: -1280, tickUpperIndex: 1280, liquidityAmount: new anchor.BN(1_000_000) }, - ], - rewards: [ - { emissionsPerSecondX64: MathUtil.toX64(new Decimal(2)), vaultAmount: new BN(1_000_000) }, - ], - }); - const { - poolInitInfo: { whirlpoolPda, tokenMintA }, - positions, - rewards, - } = fixture.getInfos(); - - // accrue rewards - await sleep(1200); - - const rewardOwnerAccount = await createTokenAccount( - provider, - rewards[0].rewardMint, - provider.wallet.publicKey - ); - - const fakePositionTokenAccount = await createAndMintToTokenAccount(provider, tokenMintA, 1); - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.collectRewardIx(ctx.program, { - whirlpool: whirlpoolPda.publicKey, - positionAuthority: provider.wallet.publicKey, - position: positions[0].publicKey, - positionTokenAccount: fakePositionTokenAccount, - rewardOwnerAccount, - rewardVault: rewards[0].rewardVaultKeypair.publicKey, - rewardIndex: 0, - }) - ).buildAndExecute(), - /0x7d3/ // ConstraintRaw - ); - }); - - it("fails when position authority is not approved delegate for position token account", async () => { - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing: TickSpacing.Standard, - initialSqrtPrice: MathUtil.toX64(new Decimal(1)), - positions: [ - { tickLowerIndex: -1280, tickUpperIndex: 1280, liquidityAmount: new anchor.BN(1_000_000) }, - ], - rewards: [ - { emissionsPerSecondX64: MathUtil.toX64(new Decimal(2)), vaultAmount: new BN(1_000_000) }, - ], - }); - const { - poolInitInfo: { whirlpoolPda }, - positions, - rewards, - } = fixture.getInfos(); - - // accrue rewards - await sleep(1200); - - const rewardOwnerAccount = await createTokenAccount( - provider, - rewards[0].rewardMint, - provider.wallet.publicKey - ); - const delegate = anchor.web3.Keypair.generate(); - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.collectRewardIx(ctx.program, { - whirlpool: whirlpoolPda.publicKey, - positionAuthority: delegate.publicKey, - position: positions[0].publicKey, - positionTokenAccount: positions[0].tokenAccount, - rewardOwnerAccount, - rewardVault: rewards[0].rewardVaultKeypair.publicKey, - rewardIndex: 0, - }) - ) - .addSigner(delegate) - .buildAndExecute(), - /0x1783/ // MissingOrInvalidDelegate - ); - }); - - it("fails when position authority is not authorized for exactly one token", async () => { - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing: TickSpacing.Standard, - initialSqrtPrice: MathUtil.toX64(new Decimal(1)), - positions: [ - { tickLowerIndex: -1280, tickUpperIndex: 1280, liquidityAmount: new anchor.BN(1_000_000) }, - ], - rewards: [ - { emissionsPerSecondX64: MathUtil.toX64(new Decimal(2)), vaultAmount: new BN(1_000_000) }, - ], - }); - const { - poolInitInfo: { whirlpoolPda }, - positions, - rewards, - } = fixture.getInfos(); - - // accrue rewards - await sleep(1200); - - const rewardOwnerAccount = await createTokenAccount( - provider, - rewards[0].rewardMint, - provider.wallet.publicKey - ); - const delegate = anchor.web3.Keypair.generate(); - await approveToken(provider, positions[0].tokenAccount, delegate.publicKey, 2); - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.collectRewardIx(ctx.program, { - whirlpool: whirlpoolPda.publicKey, - positionAuthority: delegate.publicKey, - position: positions[0].publicKey, - positionTokenAccount: positions[0].tokenAccount, - rewardOwnerAccount, - rewardVault: rewards[0].rewardVaultKeypair.publicKey, - rewardIndex: 0, - }) - ) - .addSigner(delegate) - .buildAndExecute(), - /0x1784/ // InvalidPositionTokenAmount - ); - }); - - it("fails when position authority was not a signer", async () => { - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing: TickSpacing.Standard, - initialSqrtPrice: MathUtil.toX64(new Decimal(1)), - positions: [ - { tickLowerIndex: -1280, tickUpperIndex: 1280, liquidityAmount: new anchor.BN(1_000_000) }, - ], - rewards: [ - { emissionsPerSecondX64: MathUtil.toX64(new Decimal(2)), vaultAmount: new BN(1_000_000) }, - ], - }); - const { - poolInitInfo: { whirlpoolPda }, - positions, - rewards, - } = fixture.getInfos(); - - // accrue rewards - await sleep(1200); - - const rewardOwnerAccount = await createTokenAccount( - provider, - rewards[0].rewardMint, - provider.wallet.publicKey - ); - const delegate = anchor.web3.Keypair.generate(); - await approveToken(provider, positions[0].tokenAccount, delegate.publicKey, 1); - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.collectRewardIx(ctx.program, { - whirlpool: whirlpoolPda.publicKey, - positionAuthority: delegate.publicKey, - position: positions[0].publicKey, - positionTokenAccount: positions[0].tokenAccount, - rewardOwnerAccount, - rewardVault: rewards[0].rewardVaultKeypair.publicKey, - rewardIndex: 0, - }) - ).buildAndExecute(), - /.*signature verification fail.*/i - ); - }); - - it("fails when reward vault does not match whirlpool reward vault", async () => { - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing: TickSpacing.Standard, - initialSqrtPrice: MathUtil.toX64(new Decimal(1)), - positions: [ - { tickLowerIndex: -1280, tickUpperIndex: 1280, liquidityAmount: new anchor.BN(1_000_000) }, - ], - rewards: [ - { emissionsPerSecondX64: MathUtil.toX64(new Decimal(2)), vaultAmount: new BN(1_000_000) }, - ], - }); - const { - poolInitInfo: { whirlpoolPda }, - positions, - rewards, - } = fixture.getInfos(); - - // accrue rewards - await sleep(1200); - - const rewardOwnerAccount = await createTokenAccount( - provider, - rewards[0].rewardMint, - provider.wallet.publicKey - ); - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.collectRewardIx(ctx.program, { - whirlpool: whirlpoolPda.publicKey, - positionAuthority: provider.wallet.publicKey, - position: positions[0].publicKey, - positionTokenAccount: positions[0].tokenAccount, - rewardOwnerAccount, - rewardVault: rewardOwnerAccount, - rewardIndex: 0, - }) - ).buildAndExecute(), - /0x7dc/ // ConstraintAddress - ); - }); - - it("fails when reward owner account mint does not match whirlpool reward mint", async () => { - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing: TickSpacing.Standard, - initialSqrtPrice: MathUtil.toX64(new Decimal(1)), - positions: [ - { tickLowerIndex: -1280, tickUpperIndex: 1280, liquidityAmount: new anchor.BN(1_000_000) }, - ], - rewards: [ - { emissionsPerSecondX64: MathUtil.toX64(new Decimal(2)), vaultAmount: new BN(1_000_000) }, - ], - }); - const { - poolInitInfo: { whirlpoolPda, tokenMintA }, - positions, - rewards, - } = fixture.getInfos(); - - // accrue rewards - await sleep(1200); - - const rewardOwnerAccount = await createTokenAccount( - provider, - tokenMintA, - provider.wallet.publicKey - ); - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.collectRewardIx(ctx.program, { - whirlpool: whirlpoolPda.publicKey, - positionAuthority: provider.wallet.publicKey, - position: positions[0].publicKey, - positionTokenAccount: positions[0].tokenAccount, - rewardOwnerAccount, - rewardVault: rewards[0].rewardVaultKeypair.publicKey, - rewardIndex: 0, - }) - ).buildAndExecute(), - /0x7d3/ // ConstraintRaw - ); - }); - - it("fails when reward index is out of bounds", async () => { - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing: TickSpacing.Standard, - initialSqrtPrice: MathUtil.toX64(new Decimal(1)), - positions: [ - { tickLowerIndex: -1280, tickUpperIndex: 1280, liquidityAmount: new anchor.BN(1_000_000) }, - ], - rewards: [ - { emissionsPerSecondX64: MathUtil.toX64(new Decimal(2)), vaultAmount: new BN(1_000_000) }, - ], - }); - const { - poolInitInfo: { whirlpoolPda, tokenMintA }, - positions, - rewards, - } = fixture.getInfos(); - - // accrue rewards - await sleep(1200); - - const rewardOwnerAccount = await createTokenAccount( - provider, - tokenMintA, - provider.wallet.publicKey - ); - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.collectRewardIx(ctx.program, { - whirlpool: whirlpoolPda.publicKey, - positionAuthority: provider.wallet.publicKey, - position: positions[0].publicKey, - positionTokenAccount: positions[0].tokenAccount, - rewardOwnerAccount, - rewardVault: rewards[0].rewardVaultKeypair.publicKey, - rewardIndex: 4, - }) - ).buildAndExecute(), - /Program failed to complete/ // index out of bounds - ); - }); -}); diff --git a/sdk/tests/integration/decrease_liquidity.test.ts b/sdk/tests/integration/decrease_liquidity.test.ts deleted file mode 100644 index 47b05ab..0000000 --- a/sdk/tests/integration/decrease_liquidity.test.ts +++ /dev/null @@ -1,876 +0,0 @@ -import * as anchor from "@coral-xyz/anchor"; -import { MathUtil, Percentage } from "@orca-so/common-sdk"; -import * as assert from "assert"; -import { BN } from "bn.js"; -import Decimal from "decimal.js"; -import { - PositionData, - TickArrayData, - WhirlpoolContext, - WhirlpoolData, - WhirlpoolIx, - toTx -} from "../../src"; -import { IGNORE_CACHE } from "../../src/network/public/fetcher"; -import { decreaseLiquidityQuoteByLiquidityWithParams } from "../../src/quotes/public/decrease-liquidity-quote"; -import { - TickSpacing, - ZERO_BN, - approveToken, - assertTick, - createAndMintToTokenAccount, - createMint, - createTokenAccount, - sleep, - transferToken -} from "../utils"; -import { defaultConfirmOptions } from "../utils/const"; -import { WhirlpoolTestFixture } from "../utils/fixture"; -import { initTestPool, initTickArray, openPosition } from "../utils/init-utils"; - -describe("decrease_liquidity", () => { - const provider = anchor.AnchorProvider.local(undefined, defaultConfirmOptions); - - const program = anchor.workspace.Whirlpool; - const ctx = WhirlpoolContext.fromWorkspace(provider, program); - const fetcher = ctx.fetcher; - - it("successfully decrease liquidity from position in one tick array", async () => { - const liquidityAmount = new anchor.BN(1_250_000); - const tickLower = 7168, - tickUpper = 8960; - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing: TickSpacing.Standard, - initialSqrtPrice: MathUtil.toX64(new Decimal(1.48)), - positions: [{ tickLowerIndex: tickLower, tickUpperIndex: tickUpper, liquidityAmount }], - }); - const { poolInitInfo, tokenAccountA, tokenAccountB, positions } = fixture.getInfos(); - const { whirlpoolPda, tokenVaultAKeypair, tokenVaultBKeypair } = poolInitInfo; - const poolBefore = (await fetcher.getPool(whirlpoolPda.publicKey, IGNORE_CACHE)) as WhirlpoolData; - - // To check if rewardLastUpdatedTimestamp is updated - await sleep(1200); - - const removalQuote = decreaseLiquidityQuoteByLiquidityWithParams({ - liquidity: new anchor.BN(1_000_000), - sqrtPrice: poolBefore.sqrtPrice, - slippageTolerance: Percentage.fromFraction(1, 100), - tickCurrentIndex: poolBefore.tickCurrentIndex, - tickLowerIndex: tickLower, - tickUpperIndex: tickUpper, - }); - - await toTx( - ctx, - WhirlpoolIx.decreaseLiquidityIx(ctx.program, { - ...removalQuote, - whirlpool: whirlpoolPda.publicKey, - positionAuthority: provider.wallet.publicKey, - position: positions[0].publicKey, - positionTokenAccount: positions[0].tokenAccount, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: tokenAccountB, - tokenVaultA: tokenVaultAKeypair.publicKey, - tokenVaultB: tokenVaultBKeypair.publicKey, - tickArrayLower: positions[0].tickArrayLower, - tickArrayUpper: positions[0].tickArrayUpper, - }) - ).buildAndExecute(); - - const remainingLiquidity = liquidityAmount.sub(removalQuote.liquidityAmount); - const poolAfter = (await fetcher.getPool(whirlpoolPda.publicKey, IGNORE_CACHE)) as WhirlpoolData; - assert.ok(poolAfter.rewardLastUpdatedTimestamp.gt(poolBefore.rewardLastUpdatedTimestamp)); - assert.ok(poolAfter.liquidity.eq(remainingLiquidity)); - - const position = await fetcher.getPosition(positions[0].publicKey, IGNORE_CACHE); - assert.ok(position?.liquidity.eq(remainingLiquidity)); - - const tickArray = (await fetcher.getTickArray( - positions[0].tickArrayLower, - IGNORE_CACHE - )) as TickArrayData; - assertTick(tickArray.ticks[56], true, remainingLiquidity, remainingLiquidity); - assertTick(tickArray.ticks[70], true, remainingLiquidity, remainingLiquidity.neg()); - }); - - it("successfully decrease liquidity from position in two tick arrays", async () => { - const liquidityAmount = new anchor.BN(1_250_000); - const tickLower = -1280, - tickUpper = 1280; - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing: TickSpacing.Standard, - initialSqrtPrice: MathUtil.toX64(new Decimal(1)), - positions: [{ tickLowerIndex: -1280, tickUpperIndex: 1280, liquidityAmount }], - }); - const { poolInitInfo, positions, tokenAccountA, tokenAccountB } = fixture.getInfos(); - const { whirlpoolPda, tokenVaultAKeypair, tokenVaultBKeypair } = poolInitInfo; - const position = positions[0]; - const poolBefore = (await fetcher.getPool(whirlpoolPda.publicKey, IGNORE_CACHE)) as WhirlpoolData; - - const removalQuote = decreaseLiquidityQuoteByLiquidityWithParams({ - liquidity: new anchor.BN(1_000_000), - sqrtPrice: poolBefore.sqrtPrice, - slippageTolerance: Percentage.fromFraction(1, 100), - tickCurrentIndex: poolBefore.tickCurrentIndex, - tickLowerIndex: tickLower, - tickUpperIndex: tickUpper, - }); - - await toTx( - ctx, - WhirlpoolIx.decreaseLiquidityIx(ctx.program, { - ...removalQuote, - whirlpool: whirlpoolPda.publicKey, - positionAuthority: provider.wallet.publicKey, - position: position.publicKey, - positionTokenAccount: position.tokenAccount, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: tokenAccountB, - tokenVaultA: tokenVaultAKeypair.publicKey, - tokenVaultB: tokenVaultBKeypair.publicKey, - tickArrayLower: position.tickArrayLower, - tickArrayUpper: position.tickArrayUpper, - }) - ).buildAndExecute(); - - const remainingLiquidity = liquidityAmount.sub(removalQuote.liquidityAmount); - const poolAfter = (await fetcher.getPool(whirlpoolPda.publicKey, IGNORE_CACHE)) as WhirlpoolData; - - assert.ok(poolAfter.rewardLastUpdatedTimestamp.gte(poolBefore.rewardLastUpdatedTimestamp)); - assert.ok(poolAfter.liquidity.eq(remainingLiquidity)); - - const positionAfter = (await fetcher.getPosition(position.publicKey, IGNORE_CACHE)) as PositionData; - assert.ok(positionAfter.liquidity.eq(remainingLiquidity)); - - const tickArrayLower = (await fetcher.getTickArray( - position.tickArrayLower, - IGNORE_CACHE - )) as TickArrayData; - assertTick(tickArrayLower.ticks[78], true, remainingLiquidity, remainingLiquidity); - const tickArrayUpper = (await fetcher.getTickArray( - position.tickArrayUpper, - IGNORE_CACHE - )) as TickArrayData; - assertTick(tickArrayUpper.ticks[10], true, remainingLiquidity, remainingLiquidity.neg()); - }); - - it("successfully decrease liquidity with approved delegate", async () => { - const liquidityAmount = new anchor.BN(1_250_000); - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing: TickSpacing.Standard, - initialSqrtPrice: MathUtil.toX64(new Decimal(1)), - positions: [{ tickLowerIndex: -1280, tickUpperIndex: 1280, liquidityAmount }], - }); - const { poolInitInfo, positions, tokenAccountA, tokenAccountB } = fixture.getInfos(); - const { whirlpoolPda } = poolInitInfo; - const position = positions[0]; - - const delegate = anchor.web3.Keypair.generate(); - - await approveToken(provider, positions[0].tokenAccount, delegate.publicKey, 1); - await approveToken(provider, tokenAccountA, delegate.publicKey, 1_000_000); - await approveToken(provider, tokenAccountB, delegate.publicKey, 1_000_000); - - const removeAmount = new anchor.BN(1_000_000); - - await toTx( - ctx, - WhirlpoolIx.decreaseLiquidityIx(ctx.program, { - liquidityAmount: removeAmount, - tokenMinA: new BN(0), - tokenMinB: new BN(0), - whirlpool: whirlpoolPda.publicKey, - positionAuthority: delegate.publicKey, - position: position.publicKey, - positionTokenAccount: position.tokenAccount, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: tokenAccountB, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArrayLower: position.tickArrayLower, - tickArrayUpper: position.tickArrayUpper, - }) - ) - .addSigner(delegate) - .buildAndExecute(); - }); - - it("successfully decrease liquidity with owner even if there is approved delegate", async () => { - const liquidityAmount = new anchor.BN(1_250_000); - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing: TickSpacing.Standard, - initialSqrtPrice: MathUtil.toX64(new Decimal(1.48)), - positions: [{ tickLowerIndex: 7168, tickUpperIndex: 8960, liquidityAmount }], - }); - const { poolInitInfo, positions, tokenAccountA, tokenAccountB } = fixture.getInfos(); - const { whirlpoolPda } = poolInitInfo; - const position = positions[0]; - - const delegate = anchor.web3.Keypair.generate(); - - await approveToken(provider, positions[0].tokenAccount, delegate.publicKey, 1); - await approveToken(provider, tokenAccountA, delegate.publicKey, 1_000_000); - await approveToken(provider, tokenAccountB, delegate.publicKey, 1_000_000); - - const removeAmount = new anchor.BN(1_000_000); - - await toTx( - ctx, - WhirlpoolIx.decreaseLiquidityIx(ctx.program, { - liquidityAmount: removeAmount, - tokenMinA: new BN(0), - tokenMinB: new BN(0), - whirlpool: whirlpoolPda.publicKey, - positionAuthority: provider.wallet.publicKey, - position: position.publicKey, - positionTokenAccount: position.tokenAccount, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: tokenAccountB, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArrayLower: position.tickArrayLower, - tickArrayUpper: position.tickArrayUpper, - }) - ).buildAndExecute(); - }); - - it("successfully decrease liquidity with transferred position token", async () => { - const liquidityAmount = new anchor.BN(1_250_000); - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing: TickSpacing.Standard, - initialSqrtPrice: MathUtil.toX64(new Decimal(1.48)), - positions: [{ tickLowerIndex: 7168, tickUpperIndex: 8960, liquidityAmount }], - }); - const { poolInitInfo, positions, tokenAccountA, tokenAccountB } = fixture.getInfos(); - const { whirlpoolPda } = poolInitInfo; - const position = positions[0]; - - const removeAmount = new anchor.BN(1_000_000); - const newOwner = anchor.web3.Keypair.generate(); - const newOwnerPositionTokenAccount = await createTokenAccount( - provider, - position.mintKeypair.publicKey, - newOwner.publicKey - ); - await transferToken(provider, position.tokenAccount, newOwnerPositionTokenAccount, 1); - - await toTx( - ctx, - WhirlpoolIx.decreaseLiquidityIx(ctx.program, { - liquidityAmount: removeAmount, - tokenMinA: new BN(0), - tokenMinB: new BN(0), - whirlpool: whirlpoolPda.publicKey, - positionAuthority: newOwner.publicKey, - position: position.publicKey, - positionTokenAccount: newOwnerPositionTokenAccount, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: tokenAccountB, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArrayLower: position.tickArrayLower, - tickArrayUpper: position.tickArrayUpper, - }) - ) - .addSigner(newOwner) - .buildAndExecute(); - }); - - it("fails when liquidity amount is zero", async () => { - const liquidityAmount = new anchor.BN(1_250_000); - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing: TickSpacing.Standard, - initialSqrtPrice: MathUtil.toX64(new Decimal(1)), - positions: [{ tickLowerIndex: -1280, tickUpperIndex: 1280, liquidityAmount }], - }); - const { poolInitInfo, positions, tokenAccountA, tokenAccountB } = fixture.getInfos(); - const { whirlpoolPda, tokenVaultAKeypair, tokenVaultBKeypair } = poolInitInfo; - const position = positions[0]; - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.decreaseLiquidityIx(ctx.program, { - liquidityAmount: new anchor.BN(0), - tokenMinA: new BN(0), - tokenMinB: new BN(0), - whirlpool: whirlpoolPda.publicKey, - positionAuthority: provider.wallet.publicKey, - position: position.publicKey, - positionTokenAccount: position.tokenAccount, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: tokenAccountB, - tokenVaultA: tokenVaultAKeypair.publicKey, - tokenVaultB: tokenVaultBKeypair.publicKey, - tickArrayLower: position.tickArrayLower, - tickArrayUpper: position.tickArrayUpper, - }) - ).buildAndExecute(), - /0x177c/ // LiquidityZero - ); - }); - - it("fails when position has insufficient liquidity for the withdraw amount", async () => { - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing: TickSpacing.Standard, - initialSqrtPrice: MathUtil.toX64(new Decimal(1)), - positions: [{ tickLowerIndex: -1280, tickUpperIndex: 1280, liquidityAmount: ZERO_BN }], - }); - const { poolInitInfo, positions, tokenAccountA, tokenAccountB } = fixture.getInfos(); - const { whirlpoolPda, tokenVaultAKeypair, tokenVaultBKeypair } = poolInitInfo; - const position = positions[0]; - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.decreaseLiquidityIx(ctx.program, { - liquidityAmount: new anchor.BN(1_000), - tokenMinA: new BN(0), - tokenMinB: new BN(0), - whirlpool: whirlpoolPda.publicKey, - positionAuthority: provider.wallet.publicKey, - position: position.publicKey, - positionTokenAccount: position.tokenAccount, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: tokenAccountB, - tokenVaultA: tokenVaultAKeypair.publicKey, - tokenVaultB: tokenVaultBKeypair.publicKey, - tickArrayLower: position.tickArrayLower, - tickArrayUpper: position.tickArrayUpper, - }) - ).buildAndExecute(), - /0x177f/ // LiquidityUnderflow - ); - }); - - it("fails when token min a subceeded", async () => { - const liquidityAmount = new anchor.BN(1_250_000); - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing: TickSpacing.Standard, - initialSqrtPrice: MathUtil.toX64(new Decimal(0.005)), - positions: [{ tickLowerIndex: -1280, tickUpperIndex: 1280, liquidityAmount }], - }); - const { poolInitInfo, positions, tokenAccountA, tokenAccountB } = fixture.getInfos(); - const { whirlpoolPda, tokenVaultAKeypair, tokenVaultBKeypair } = poolInitInfo; - const position = positions[0]; - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.decreaseLiquidityIx(ctx.program, { - liquidityAmount, - tokenMinA: new BN(1_000_000), - tokenMinB: new BN(0), - whirlpool: whirlpoolPda.publicKey, - positionAuthority: provider.wallet.publicKey, - position: position.publicKey, - positionTokenAccount: position.tokenAccount, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: tokenAccountB, - tokenVaultA: tokenVaultAKeypair.publicKey, - tokenVaultB: tokenVaultBKeypair.publicKey, - tickArrayLower: position.tickArrayLower, - tickArrayUpper: position.tickArrayUpper, - }) - ).buildAndExecute(), - /0x1782/ // TokenMinSubceeded - ); - }); - - it("fails when token min b subceeded", async () => { - const liquidityAmount = new anchor.BN(1_250_000); - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing: TickSpacing.Standard, - initialSqrtPrice: MathUtil.toX64(new Decimal(5)), - positions: [{ tickLowerIndex: -1280, tickUpperIndex: 1280, liquidityAmount }], - }); - const { poolInitInfo, positions, tokenAccountA, tokenAccountB } = fixture.getInfos(); - const { whirlpoolPda, tokenVaultAKeypair, tokenVaultBKeypair } = poolInitInfo; - const position = positions[0]; - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.decreaseLiquidityIx(ctx.program, { - liquidityAmount, - tokenMinA: new BN(0), - tokenMinB: new BN(1_000_000), - whirlpool: whirlpoolPda.publicKey, - positionAuthority: provider.wallet.publicKey, - position: position.publicKey, - positionTokenAccount: position.tokenAccount, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: tokenAccountB, - tokenVaultA: tokenVaultAKeypair.publicKey, - tokenVaultB: tokenVaultBKeypair.publicKey, - tickArrayLower: position.tickArrayLower, - tickArrayUpper: position.tickArrayUpper, - }) - ).buildAndExecute(), - /0x1782/ // TokenMinSubceeded - ); - }); - - it("fails when position account does not have exactly 1 token", async () => { - const liquidityAmount = new anchor.BN(1_250_000); - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing: TickSpacing.Standard, - initialSqrtPrice: MathUtil.toX64(new Decimal(2.2)), - positions: [{ tickLowerIndex: 7168, tickUpperIndex: 8960, liquidityAmount }], - }); - const { poolInitInfo, positions, tokenAccountA, tokenAccountB } = fixture.getInfos(); - const { whirlpoolPda } = poolInitInfo; - const position = positions[0]; - - // Create a position token account that contains 0 tokens - const newPositionTokenAccount = await createTokenAccount( - provider, - positions[0].mintKeypair.publicKey, - provider.wallet.publicKey - ); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.decreaseLiquidityIx(ctx.program, { - liquidityAmount, - tokenMinA: new BN(0), - tokenMinB: new BN(0), - whirlpool: whirlpoolPda.publicKey, - positionAuthority: provider.wallet.publicKey, - position: position.publicKey, - positionTokenAccount: newPositionTokenAccount, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: tokenAccountB, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArrayLower: position.tickArrayLower, - tickArrayUpper: position.tickArrayUpper, - }) - ).buildAndExecute(), - /0x7d3/ // ConstraintRaw - ); - - // Send position token to other position token account - await transferToken(provider, position.tokenAccount, newPositionTokenAccount, 1); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.decreaseLiquidityIx(ctx.program, { - liquidityAmount, - tokenMinA: new BN(0), - tokenMinB: new BN(0), - whirlpool: whirlpoolPda.publicKey, - positionAuthority: provider.wallet.publicKey, - position: position.publicKey, - positionTokenAccount: position.tokenAccount, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: tokenAccountB, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArrayLower: position.tickArrayLower, - tickArrayUpper: position.tickArrayUpper, - }) - ).buildAndExecute(), - /0x7d3/ // ConstraintRaw - ); - }); - - it("fails when position token account mint does not match position mint", async () => { - const liquidityAmount = new anchor.BN(6_500_000); - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing: TickSpacing.Standard, - initialSqrtPrice: MathUtil.toX64(new Decimal(2.2)), - positions: [{ tickLowerIndex: 7168, tickUpperIndex: 8960, liquidityAmount }], - }); - const { poolInitInfo, positions, tokenAccountA, tokenAccountB } = fixture.getInfos(); - const { whirlpoolPda, tokenMintA } = poolInitInfo; - const position = positions[0]; - - const invalidPositionTokenAccount = await createAndMintToTokenAccount(provider, tokenMintA, 1); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.decreaseLiquidityIx(ctx.program, { - liquidityAmount, - tokenMinA: new BN(0), - tokenMinB: new BN(0), - whirlpool: whirlpoolPda.publicKey, - positionAuthority: provider.wallet.publicKey, - position: position.publicKey, - positionTokenAccount: invalidPositionTokenAccount, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: tokenAccountB, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArrayLower: position.tickArrayLower, - tickArrayUpper: position.tickArrayUpper, - }) - ).buildAndExecute(), - /0x7d3/ // A raw constraint was violated - ); - }); - - it("fails when position does not match whirlpool", async () => { - const liquidityAmount = new anchor.BN(6_500_000); - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing: TickSpacing.Standard, - initialSqrtPrice: MathUtil.toX64(new Decimal(2.2)), - positions: [{ tickLowerIndex: 7168, tickUpperIndex: 8960, liquidityAmount }], - }); - const { poolInitInfo, positions, tokenAccountA, tokenAccountB } = fixture.getInfos(); - const { whirlpoolPda } = poolInitInfo; - const tickArray = positions[0].tickArrayLower; - - const { poolInitInfo: poolInitInfo2 } = await initTestPool(ctx, TickSpacing.Standard); - const { - params: { positionPda, positionTokenAccount: positionTokenAccountAddress }, - } = await openPosition(ctx, poolInitInfo2.whirlpoolPda.publicKey, 7168, 8960); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.decreaseLiquidityIx(ctx.program, { - liquidityAmount, - tokenMinA: new BN(0), - tokenMinB: new BN(0), - whirlpool: whirlpoolPda.publicKey, - positionAuthority: provider.wallet.publicKey, - position: positionPda.publicKey, - positionTokenAccount: positionTokenAccountAddress, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: tokenAccountB, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArrayLower: tickArray, - tickArrayUpper: tickArray, - }) - ).buildAndExecute(), - /0x7d1/ // A has_one constraint was violated - ); - }); - - it("fails when token vaults do not match whirlpool vaults", async () => { - const liquidityAmount = new anchor.BN(6_500_000); - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing: TickSpacing.Standard, - initialSqrtPrice: MathUtil.toX64(new Decimal(2.2)), - positions: [{ tickLowerIndex: 7168, tickUpperIndex: 8960, liquidityAmount }], - }); - const { poolInitInfo, positions, tokenAccountA, tokenAccountB } = fixture.getInfos(); - const { whirlpoolPda, tokenMintA, tokenMintB } = poolInitInfo; - const position = positions[0]; - - const fakeVaultA = await createAndMintToTokenAccount(provider, tokenMintA, 1_000); - const fakeVaultB = await createAndMintToTokenAccount(provider, tokenMintB, 1_000); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.decreaseLiquidityIx(ctx.program, { - liquidityAmount, - tokenMinA: new BN(0), - tokenMinB: new BN(0), - whirlpool: whirlpoolPda.publicKey, - positionAuthority: provider.wallet.publicKey, - position: position.publicKey, - positionTokenAccount: position.tokenAccount, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: tokenAccountB, - tokenVaultA: fakeVaultA, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArrayLower: position.tickArrayLower, - tickArrayUpper: position.tickArrayUpper, - }) - ).buildAndExecute(), - /0x7d3/ // ConstraintRaw - ); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.decreaseLiquidityIx(ctx.program, { - liquidityAmount, - tokenMinA: new BN(0), - tokenMinB: new BN(0), - whirlpool: whirlpoolPda.publicKey, - positionAuthority: provider.wallet.publicKey, - position: position.publicKey, - positionTokenAccount: position.tokenAccount, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: tokenAccountB, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenVaultB: fakeVaultB, - tickArrayLower: position.tickArrayLower, - tickArrayUpper: position.tickArrayUpper, - }) - ).buildAndExecute(), - /0x7d3/ // ConstraintRaw - ); - }); - - it("fails when owner token account mint does not match whirlpool token mint", async () => { - const liquidityAmount = new anchor.BN(6_500_000); - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing: TickSpacing.Standard, - initialSqrtPrice: MathUtil.toX64(new Decimal(2.2)), - positions: [{ tickLowerIndex: 7168, tickUpperIndex: 8960, liquidityAmount }], - }); - const { poolInitInfo, positions, tokenAccountA, tokenAccountB } = fixture.getInfos(); - const { whirlpoolPda } = poolInitInfo; - const invalidMint = await createMint(provider); - const invalidTokenAccount = await createAndMintToTokenAccount(provider, invalidMint, 1_000_000); - const position = positions[0]; - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.decreaseLiquidityIx(ctx.program, { - liquidityAmount, - tokenMinA: new BN(0), - tokenMinB: new BN(0), - whirlpool: whirlpoolPda.publicKey, - positionAuthority: provider.wallet.publicKey, - position: position.publicKey, - positionTokenAccount: position.tokenAccount, - tokenOwnerAccountA: invalidTokenAccount, - tokenOwnerAccountB: tokenAccountB, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArrayLower: position.tickArrayLower, - tickArrayUpper: position.tickArrayUpper, - }) - ).buildAndExecute(), - /0x7d3/ // ConstraintRaw - ); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.decreaseLiquidityIx(ctx.program, { - liquidityAmount, - tokenMinA: new BN(0), - tokenMinB: new BN(0), - whirlpool: whirlpoolPda.publicKey, - positionAuthority: provider.wallet.publicKey, - position: position.publicKey, - positionTokenAccount: position.tokenAccount, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: invalidTokenAccount, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArrayLower: position.tickArrayLower, - tickArrayUpper: position.tickArrayUpper, - }) - ).buildAndExecute(), - /0x7d3/ // ConstraintRaw - ); - }); - - it("fails when position authority is not approved delegate for position token account", async () => { - const liquidityAmount = new anchor.BN(6_500_000); - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing: TickSpacing.Standard, - initialSqrtPrice: MathUtil.toX64(new Decimal(2.2)), - positions: [{ tickLowerIndex: 7168, tickUpperIndex: 8960, liquidityAmount }], - }); - const { poolInitInfo, positions, tokenAccountA, tokenAccountB } = fixture.getInfos(); - const { whirlpoolPda } = poolInitInfo; - const position = positions[0]; - const delegate = anchor.web3.Keypair.generate(); - - await approveToken(provider, tokenAccountA, delegate.publicKey, 1_000_000); - await approveToken(provider, tokenAccountB, delegate.publicKey, 1_000_000); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.decreaseLiquidityIx(ctx.program, { - liquidityAmount, - tokenMinA: new BN(0), - tokenMinB: new BN(0), - whirlpool: whirlpoolPda.publicKey, - positionAuthority: delegate.publicKey, - position: position.publicKey, - positionTokenAccount: position.tokenAccount, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: tokenAccountB, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArrayLower: position.tickArrayLower, - tickArrayUpper: position.tickArrayUpper, - }) - ) - .addSigner(delegate) - .buildAndExecute(), - /0x1783/ // MissingOrInvalidDelegate - ); - }); - - it("fails when position authority is not authorized for exactly 1 token", async () => { - const liquidityAmount = new anchor.BN(6_500_000); - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing: TickSpacing.Standard, - initialSqrtPrice: MathUtil.toX64(new Decimal(2.2)), - positions: [{ tickLowerIndex: 7168, tickUpperIndex: 8960, liquidityAmount }], - }); - const { poolInitInfo, positions, tokenAccountA, tokenAccountB } = fixture.getInfos(); - const { whirlpoolPda } = poolInitInfo; - const position = positions[0]; - const delegate = anchor.web3.Keypair.generate(); - - await approveToken(provider, position.tokenAccount, delegate.publicKey, 0); - await approveToken(provider, tokenAccountA, delegate.publicKey, 1_000_000); - await approveToken(provider, tokenAccountB, delegate.publicKey, 1_000_000); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.decreaseLiquidityIx(ctx.program, { - liquidityAmount, - tokenMinA: new BN(0), - tokenMinB: new BN(0), - whirlpool: whirlpoolPda.publicKey, - positionAuthority: delegate.publicKey, - position: position.publicKey, - positionTokenAccount: position.tokenAccount, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: tokenAccountB, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArrayLower: position.tickArrayLower, - tickArrayUpper: position.tickArrayUpper, - }) - ) - .addSigner(delegate) - .buildAndExecute(), - /0x1784/ // InvalidPositionTokenAmount - ); - }); - - it("fails when position authority was not a signer", async () => { - const liquidityAmount = new anchor.BN(6_500_000); - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing: TickSpacing.Standard, - initialSqrtPrice: MathUtil.toX64(new Decimal(2.2)), - positions: [{ tickLowerIndex: 7168, tickUpperIndex: 8960, liquidityAmount }], - }); - const { poolInitInfo, positions, tokenAccountA, tokenAccountB } = fixture.getInfos(); - const { whirlpoolPda } = poolInitInfo; - const position = positions[0]; - const delegate = anchor.web3.Keypair.generate(); - - await approveToken(provider, position.tokenAccount, delegate.publicKey, 1); - await approveToken(provider, tokenAccountA, delegate.publicKey, 1_000_000); - await approveToken(provider, tokenAccountB, delegate.publicKey, 1_000_000); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.decreaseLiquidityIx(ctx.program, { - liquidityAmount, - tokenMinA: new BN(0), - tokenMinB: new BN(167_000), - whirlpool: whirlpoolPda.publicKey, - positionAuthority: delegate.publicKey, - position: position.publicKey, - positionTokenAccount: position.tokenAccount, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: tokenAccountB, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArrayLower: position.tickArrayLower, - tickArrayUpper: position.tickArrayUpper, - }) - ).buildAndExecute(), - /.*signature verification fail.*/i - ); - }); - - it("fails when tick arrays do not match the position", async () => { - const liquidityAmount = new anchor.BN(6_500_000); - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing: TickSpacing.Standard, - initialSqrtPrice: MathUtil.toX64(new Decimal(2.2)), - positions: [{ tickLowerIndex: 7168, tickUpperIndex: 8960, liquidityAmount }], - }); - const { poolInitInfo, positions, tokenAccountA, tokenAccountB } = fixture.getInfos(); - const { whirlpoolPda } = poolInitInfo; - const position = positions[0]; - - const { - params: { tickArrayPda: tickArrayLowerPda }, - } = await initTickArray(ctx, whirlpoolPda.publicKey, 11264); - - const { - params: { tickArrayPda: tickArrayUpperPda }, - } = await initTickArray(ctx, whirlpoolPda.publicKey, 22528); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.decreaseLiquidityIx(ctx.program, { - liquidityAmount, - tokenMinA: new BN(0), - tokenMinB: new BN(0), - whirlpool: whirlpoolPda.publicKey, - positionAuthority: provider.wallet.publicKey, - position: position.publicKey, - positionTokenAccount: position.tokenAccount, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: tokenAccountB, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArrayLower: tickArrayLowerPda.publicKey, - tickArrayUpper: tickArrayUpperPda.publicKey, - }) - ).buildAndExecute(), - /0x1779/ // TicKNotFound - ); - }); - - it("fails when the tick arrays are for a different whirlpool", async () => { - const liquidityAmount = new anchor.BN(6_500_000); - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing: TickSpacing.Standard, - initialSqrtPrice: MathUtil.toX64(new Decimal(2.2)), - positions: [{ tickLowerIndex: 7168, tickUpperIndex: 8960, liquidityAmount }], - }); - const { poolInitInfo, positions, tokenAccountA, tokenAccountB } = fixture.getInfos(); - const { whirlpoolPda } = poolInitInfo; - const position = positions[0]; - - const { poolInitInfo: poolInitInfo2 } = await initTestPool(ctx, TickSpacing.Standard); - - const { - params: { tickArrayPda: tickArrayLowerPda }, - } = await initTickArray(ctx, poolInitInfo2.whirlpoolPda.publicKey, -11264); - - const { - params: { tickArrayPda: tickArrayUpperPda }, - } = await initTickArray(ctx, poolInitInfo2.whirlpoolPda.publicKey, 0); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.decreaseLiquidityIx(ctx.program, { - liquidityAmount, - tokenMinA: new BN(0), - tokenMinB: new BN(0), - whirlpool: whirlpoolPda.publicKey, - positionAuthority: provider.wallet.publicKey, - position: position.publicKey, - positionTokenAccount: position.tokenAccount, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: tokenAccountB, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArrayLower: tickArrayLowerPda.publicKey, - tickArrayUpper: tickArrayUpperPda.publicKey, - }) - ).buildAndExecute(), - /0x7d1/ // A has one constraint was violated - ); - }); -}); diff --git a/sdk/tests/integration/delete_position_bundle.test.ts b/sdk/tests/integration/delete_position_bundle.test.ts deleted file mode 100644 index e433151..0000000 --- a/sdk/tests/integration/delete_position_bundle.test.ts +++ /dev/null @@ -1,547 +0,0 @@ -import * as anchor from "@coral-xyz/anchor"; -import { PDA } from "@orca-so/common-sdk"; -import { ASSOCIATED_TOKEN_PROGRAM_ID } from "@solana/spl-token"; -import { Keypair } from "@solana/web3.js"; -import * as assert from "assert"; -import { InitPoolParams, POSITION_BUNDLE_SIZE, PositionBundleData, WhirlpoolIx, toTx } from "../../src"; -import { WhirlpoolContext } from "../../src/context"; -import { IGNORE_CACHE } from "../../src/network/public/fetcher"; -import { - ONE_SOL, - TickSpacing, - approveToken, - burnToken, - createAssociatedTokenAccount, - systemTransferTx, - transferToken -} from "../utils"; -import { defaultConfirmOptions } from "../utils/const"; -import { initTestPool, initializePositionBundle, initializePositionBundleWithMetadata, openBundledPosition } from "../utils/init-utils"; - -describe("delete_position_bundle", () => { - const provider = anchor.AnchorProvider.local(undefined, defaultConfirmOptions); - - - const program = anchor.workspace.Whirlpool; - const ctx = WhirlpoolContext.fromWorkspace(provider, program); - const fetcher = ctx.fetcher; - - const tickLowerIndex = 0; - const tickUpperIndex = 128; - let poolInitInfo: InitPoolParams; - let whirlpoolPda: PDA; - const funderKeypair = anchor.web3.Keypair.generate(); - - before(async () => { - poolInitInfo = (await initTestPool(ctx, TickSpacing.Standard)).poolInitInfo; - whirlpoolPda = poolInitInfo.whirlpoolPda; - await systemTransferTx(provider, funderKeypair.publicKey, ONE_SOL).buildAndExecute(); - }); - - function checkBitmapIsOpened(account: PositionBundleData, bundleIndex: number): boolean { - if (bundleIndex < 0 || bundleIndex >= POSITION_BUNDLE_SIZE) throw Error("bundleIndex is out of bounds"); - - const bitmapIndex = Math.floor(bundleIndex / 8); - const bitmapOffset = bundleIndex % 8; - return (account.positionBitmap[bitmapIndex] & (1 << bitmapOffset)) > 0; - } - - it("successfully closes an position bundle, with metadata", async () => { - // with local-validator, ctx.wallet may have large lamports and it overflows number data type... - const owner = funderKeypair; - - const positionBundleInfo = await initializePositionBundleWithMetadata( - ctx, - owner.publicKey, - owner - ); - - // PositionBundle account exists - const prePositionBundle = await fetcher.getPositionBundle(positionBundleInfo.positionBundlePda.publicKey, IGNORE_CACHE); - assert.ok(prePositionBundle !== null); - - // NFT supply should be 1 - const preSupplyResponse = await provider.connection.getTokenSupply(positionBundleInfo.positionBundleMintKeypair.publicKey); - assert.equal(preSupplyResponse.value.uiAmount, 1); - - // ATA account exists - assert.notEqual(await provider.connection.getAccountInfo(positionBundleInfo.positionBundleTokenAccount), undefined); - - // Metadata account exists - assert.notEqual(await provider.connection.getAccountInfo(positionBundleInfo.positionBundleMetadataPda.publicKey), undefined); - - const preBalance = await provider.connection.getBalance(owner.publicKey, "confirmed"); - - const rentPositionBundle = await provider.connection.getBalance(positionBundleInfo.positionBundlePda.publicKey, "confirmed"); - const rentTokenAccount = await provider.connection.getBalance(positionBundleInfo.positionBundleTokenAccount, "confirmed"); - - await toTx( - ctx, - WhirlpoolIx.deletePositionBundleIx(ctx.program, { - positionBundle: positionBundleInfo.positionBundlePda.publicKey, - positionBundleMint: positionBundleInfo.positionBundleMintKeypair.publicKey, - positionBundleTokenAccount: positionBundleInfo.positionBundleTokenAccount, - owner: owner.publicKey, - receiver: owner.publicKey - }) - ).addSigner(owner).buildAndExecute(); - - const postBalance = await provider.connection.getBalance(owner.publicKey, "confirmed"); - - // PositionBundle account should be closed - const postPositionBundle = await fetcher.getPositionBundle(positionBundleInfo.positionBundlePda.publicKey, IGNORE_CACHE); - assert.ok(postPositionBundle === null); - - // NFT should be burned and its supply should be 0 - const supplyResponse = await provider.connection.getTokenSupply(positionBundleInfo.positionBundleMintKeypair.publicKey); - assert.equal(supplyResponse.value.uiAmount, 0); - - // ATA account should be closed - assert.equal(await provider.connection.getAccountInfo(positionBundleInfo.positionBundleTokenAccount), undefined); - - // Metadata account should NOT be closed - assert.notEqual(await provider.connection.getAccountInfo(positionBundleInfo.positionBundleMetadataPda.publicKey), undefined); - - // check if rent are refunded - const diffBalance = postBalance - preBalance; - const rentTotal = rentPositionBundle + rentTokenAccount; - assert.equal(diffBalance, rentTotal); - }); - - it("successfully closes an position bundle, without metadata", async () => { - // with local-validator, ctx.wallet may have large lamports and it overflows number data type... - const owner = funderKeypair; - - const positionBundleInfo = await initializePositionBundle( - ctx, - owner.publicKey, - owner - ); - - // PositionBundle account exists - const prePositionBundle = await fetcher.getPositionBundle(positionBundleInfo.positionBundlePda.publicKey, IGNORE_CACHE); - assert.ok(prePositionBundle !== null); - - // NFT supply should be 1 - const preSupplyResponse = await provider.connection.getTokenSupply(positionBundleInfo.positionBundleMintKeypair.publicKey); - assert.equal(preSupplyResponse.value.uiAmount, 1); - - // ATA account exists - assert.notEqual(await provider.connection.getAccountInfo(positionBundleInfo.positionBundleTokenAccount), undefined); - - const preBalance = await provider.connection.getBalance(owner.publicKey, "confirmed"); - - const rentPositionBundle = await provider.connection.getBalance(positionBundleInfo.positionBundlePda.publicKey, "confirmed"); - const rentTokenAccount = await provider.connection.getBalance(positionBundleInfo.positionBundleTokenAccount, "confirmed"); - - await toTx( - ctx, - WhirlpoolIx.deletePositionBundleIx(ctx.program, { - positionBundle: positionBundleInfo.positionBundlePda.publicKey, - positionBundleMint: positionBundleInfo.positionBundleMintKeypair.publicKey, - positionBundleTokenAccount: positionBundleInfo.positionBundleTokenAccount, - owner: owner.publicKey, - receiver: owner.publicKey - }) - ).addSigner(owner).buildAndExecute(); - - const postBalance = await provider.connection.getBalance(owner.publicKey, "confirmed"); - - // PositionBundle account should be closed - const postPositionBundle = await fetcher.getPositionBundle(positionBundleInfo.positionBundlePda.publicKey, IGNORE_CACHE); - assert.ok(postPositionBundle === null); - - // NFT should be burned and its supply should be 0 - const supplyResponse = await provider.connection.getTokenSupply(positionBundleInfo.positionBundleMintKeypair.publicKey); - assert.equal(supplyResponse.value.uiAmount, 0); - - // ATA account should be closed - assert.equal(await provider.connection.getAccountInfo(positionBundleInfo.positionBundleTokenAccount), undefined); - - // check if rent are refunded - const diffBalance = postBalance - preBalance; - const rentTotal = rentPositionBundle + rentTokenAccount; - assert.equal(diffBalance, rentTotal); - }); - - it("successfully closes an position bundle, receiver != owner", async () => { - const receiver = funderKeypair; - - const positionBundleInfo = await initializePositionBundle( - ctx, - ctx.wallet.publicKey, - ); - - const preBalance = await provider.connection.getBalance(receiver.publicKey, "confirmed"); - - const rentPositionBundle = await provider.connection.getBalance(positionBundleInfo.positionBundlePda.publicKey, "confirmed"); - const rentTokenAccount = await provider.connection.getBalance(positionBundleInfo.positionBundleTokenAccount, "confirmed"); - - await toTx( - ctx, - WhirlpoolIx.deletePositionBundleIx(ctx.program, { - positionBundle: positionBundleInfo.positionBundlePda.publicKey, - positionBundleMint: positionBundleInfo.positionBundleMintKeypair.publicKey, - positionBundleTokenAccount: positionBundleInfo.positionBundleTokenAccount, - owner: ctx.wallet.publicKey, - receiver: receiver.publicKey - }) - ).buildAndExecute(); - - const postBalance = await provider.connection.getBalance(receiver.publicKey, "confirmed"); - - // check if rent are refunded to receiver - const diffBalance = postBalance - preBalance; - const rentTotal = rentPositionBundle + rentTokenAccount; - assert.equal(diffBalance, rentTotal); - }); - - it("should be failed: position bundle has opened bundled position (bundleIndex = 0)", async () => { - const positionBundleInfo = await initializePositionBundle( - ctx, - ctx.wallet.publicKey, - ); - - const bundleIndex = 0; - const positionInitInfo = await openBundledPosition( - ctx, - whirlpoolPda.publicKey, - positionBundleInfo.positionBundleMintKeypair.publicKey, - bundleIndex, - tickLowerIndex, - tickUpperIndex - ); - const { bundledPositionPda } = positionInitInfo.params; - - const position = await fetcher.getPosition(positionInitInfo.params.bundledPositionPda.publicKey, IGNORE_CACHE); - assert.equal(position!.tickLowerIndex, tickLowerIndex); - assert.equal(position!.tickUpperIndex, tickUpperIndex); - - const positionBundle = await fetcher.getPositionBundle(positionBundleInfo.positionBundlePda.publicKey, IGNORE_CACHE); - checkBitmapIsOpened(positionBundle!, bundleIndex); - - const tx = toTx( - ctx, - WhirlpoolIx.deletePositionBundleIx(ctx.program, { - positionBundle: positionBundleInfo.positionBundlePda.publicKey, - positionBundleMint: positionBundleInfo.positionBundleMintKeypair.publicKey, - positionBundleTokenAccount: positionBundleInfo.positionBundleTokenAccount, - owner: ctx.wallet.publicKey, - receiver: ctx.wallet.publicKey, - }) - ); - - // should be failed - await assert.rejects( - tx.buildAndExecute(), - /0x179e/ // PositionBundleNotDeletable - ); - - // close bundled position - await toTx( - ctx, - WhirlpoolIx.closeBundledPositionIx(ctx.program, { - bundledPosition: bundledPositionPda.publicKey, - bundleIndex, - positionBundle: positionBundleInfo.positionBundlePda.publicKey, - positionBundleAuthority: ctx.wallet.publicKey, - positionBundleTokenAccount: positionBundleInfo.positionBundleTokenAccount, - receiver: ctx.wallet.publicKey, - }) - ).buildAndExecute(); - - // should be ok - await tx.buildAndExecute(); - const deleted = await fetcher.getPositionBundle(positionBundleInfo.positionBundlePda.publicKey, IGNORE_CACHE); - assert.ok(deleted === null); - }); - - it("should be failed: position bundle has opened bundled position (bundleIndex = POSITION_BUNDLE_SIZE - 1)", async () => { - const positionBundleInfo = await initializePositionBundle( - ctx, - ctx.wallet.publicKey, - ); - - const bundleIndex = POSITION_BUNDLE_SIZE - 1; - const positionInitInfo = await openBundledPosition( - ctx, - whirlpoolPda.publicKey, - positionBundleInfo.positionBundleMintKeypair.publicKey, - bundleIndex, - tickLowerIndex, - tickUpperIndex - ); - const { bundledPositionPda } = positionInitInfo.params; - - const position = await fetcher.getPosition(positionInitInfo.params.bundledPositionPda.publicKey, IGNORE_CACHE); - assert.equal(position!.tickLowerIndex, tickLowerIndex); - assert.equal(position!.tickUpperIndex, tickUpperIndex); - - const positionBundle = await fetcher.getPositionBundle(positionBundleInfo.positionBundlePda.publicKey, IGNORE_CACHE); - checkBitmapIsOpened(positionBundle!, bundleIndex); - - const tx = toTx( - ctx, - WhirlpoolIx.deletePositionBundleIx(ctx.program, { - positionBundle: positionBundleInfo.positionBundlePda.publicKey, - positionBundleMint: positionBundleInfo.positionBundleMintKeypair.publicKey, - positionBundleTokenAccount: positionBundleInfo.positionBundleTokenAccount, - owner: ctx.wallet.publicKey, - receiver: ctx.wallet.publicKey, - }) - ); - - // should be failed - await assert.rejects( - tx.buildAndExecute(), - /0x179e/ // PositionBundleNotDeletable - ); - - // close bundled position - await toTx( - ctx, - WhirlpoolIx.closeBundledPositionIx(ctx.program, { - bundledPosition: bundledPositionPda.publicKey, - bundleIndex, - positionBundle: positionBundleInfo.positionBundlePda.publicKey, - positionBundleAuthority: ctx.wallet.publicKey, - positionBundleTokenAccount: positionBundleInfo.positionBundleTokenAccount, - receiver: ctx.wallet.publicKey, - }) - ).buildAndExecute(); - - // should be ok - await tx.buildAndExecute(); - const deleted = await fetcher.getPositionBundle(positionBundleInfo.positionBundlePda.publicKey, IGNORE_CACHE); - assert.ok(deleted === null); - }); - - it("should be failed: only owner can delete position bundle, delegated user cannot", async () => { - const positionBundleInfo = await initializePositionBundle( - ctx, - ctx.wallet.publicKey, - ); - - const delegate = Keypair.generate(); - await approveToken( - provider, - positionBundleInfo.positionBundleTokenAccount, - delegate.publicKey, - 1 - ); - - const tx = toTx( - ctx, - WhirlpoolIx.deletePositionBundleIx(ctx.program, { - positionBundle: positionBundleInfo.positionBundlePda.publicKey, - positionBundleMint: positionBundleInfo.positionBundleMintKeypair.publicKey, - positionBundleTokenAccount: positionBundleInfo.positionBundleTokenAccount, - owner: delegate.publicKey, // not owner - receiver: ctx.wallet.publicKey, - }) - ).addSigner(delegate); - - // should be failed - await assert.rejects( - tx.buildAndExecute(), - /0x7d3/ // ConstraintRaw - ); - - // ownership transfer to delegate - const delegateTokenAccount = await createAssociatedTokenAccount( - provider, - positionBundleInfo.positionBundleMintKeypair.publicKey, - delegate.publicKey, - ctx.wallet.publicKey - ); - await transferToken( - provider, - positionBundleInfo.positionBundleTokenAccount, - delegateTokenAccount, - 1 - ); - - const txAfterTransfer = toTx( - ctx, - WhirlpoolIx.deletePositionBundleIx(ctx.program, { - positionBundle: positionBundleInfo.positionBundlePda.publicKey, - positionBundleMint: positionBundleInfo.positionBundleMintKeypair.publicKey, - positionBundleTokenAccount: delegateTokenAccount, - owner: delegate.publicKey, // now, delegate is owner - receiver: ctx.wallet.publicKey, - }) - ).addSigner(delegate); - - await txAfterTransfer.buildAndExecute(); - const deleted = await fetcher.getPositionBundle(positionBundleInfo.positionBundlePda.publicKey, IGNORE_CACHE); - assert.ok(deleted === null); - }); - - describe("invalid input account", () => { - it("should be failed: invalid position bundle", async () => { - const positionBundleInfo1 = await initializePositionBundle( - ctx, - ctx.wallet.publicKey, - ); - const positionBundleInfo2 = await initializePositionBundle( - ctx, - ctx.wallet.publicKey, - ); - - const tx = toTx( - ctx, - WhirlpoolIx.deletePositionBundleIx(ctx.program, { - positionBundle: positionBundleInfo2.positionBundlePda.publicKey, // invalid - positionBundleMint: positionBundleInfo1.positionBundleMintKeypair.publicKey, - positionBundleTokenAccount: positionBundleInfo1.positionBundleTokenAccount, - owner: ctx.wallet.publicKey, - receiver: ctx.wallet.publicKey, - }) - ); - - await assert.rejects( - tx.buildAndExecute(), - /0x7dc/ // ConstraintAddress - ); - }); - - it("should be failed: invalid position bundle mint", async () => { - const positionBundleInfo1 = await initializePositionBundle( - ctx, - ctx.wallet.publicKey, - ); - const positionBundleInfo2 = await initializePositionBundle( - ctx, - ctx.wallet.publicKey, - ); - - const tx = toTx( - ctx, - WhirlpoolIx.deletePositionBundleIx(ctx.program, { - positionBundle: positionBundleInfo1.positionBundlePda.publicKey, - positionBundleMint: positionBundleInfo2.positionBundleMintKeypair.publicKey, // invalid - positionBundleTokenAccount: positionBundleInfo1.positionBundleTokenAccount, - owner: ctx.wallet.publicKey, - receiver: ctx.wallet.publicKey, - }) - ); - - await assert.rejects( - tx.buildAndExecute(), - /0x7dc/ // ConstraintAddress - ); - }); - - it("should be failed: invalid ATA (amount is zero)", async () => { - const positionBundleInfo = await initializePositionBundle( - ctx, - ctx.wallet.publicKey, - ); - - await burnToken(ctx.provider, positionBundleInfo.positionBundleTokenAccount, positionBundleInfo.positionBundleMintKeypair.publicKey, 1); - - const tokenAccount = await fetcher.getTokenInfo(positionBundleInfo.positionBundleTokenAccount); - assert.equal(tokenAccount!.amount.toString(), "0"); - - const tx = toTx( - ctx, - WhirlpoolIx.deletePositionBundleIx(ctx.program, { - positionBundle: positionBundleInfo.positionBundlePda.publicKey, - positionBundleMint: positionBundleInfo.positionBundleMintKeypair.publicKey, - positionBundleTokenAccount: positionBundleInfo.positionBundleTokenAccount, // amount = 0 - owner: ctx.wallet.publicKey, - receiver: ctx.wallet.publicKey, - }) - ); - - await assert.rejects( - tx.buildAndExecute(), - /0x7d3/ // ConstraintRaw - ); - }); - - it("should be failed: invalid ATA (invalid mint)", async () => { - const positionBundleInfo1 = await initializePositionBundle( - ctx, - ctx.wallet.publicKey, - ); - const positionBundleInfo2 = await initializePositionBundle( - ctx, - ctx.wallet.publicKey, - ); - - const tx = toTx( - ctx, - WhirlpoolIx.deletePositionBundleIx(ctx.program, { - positionBundle: positionBundleInfo1.positionBundlePda.publicKey, - positionBundleMint: positionBundleInfo1.positionBundleMintKeypair.publicKey, - positionBundleTokenAccount: positionBundleInfo2.positionBundleTokenAccount, // invalid, - owner: ctx.wallet.publicKey, - receiver: ctx.wallet.publicKey, - }) - ); - - await assert.rejects( - tx.buildAndExecute(), - /0x7d3/ // ConstraintRaw - ); - }); - - it("should be failed: invalid ATA (invalid owner), invalid owner", async () => { - const positionBundleInfo = await initializePositionBundle( - ctx, - ctx.wallet.publicKey, - ); - - const otherWallet = Keypair.generate(); - const tx = toTx( - ctx, - WhirlpoolIx.deletePositionBundleIx(ctx.program, { - positionBundle: positionBundleInfo.positionBundlePda.publicKey, - positionBundleMint: positionBundleInfo.positionBundleMintKeypair.publicKey, - positionBundleTokenAccount: positionBundleInfo.positionBundleTokenAccount, // ata.owner != owner - owner: otherWallet.publicKey, - receiver: ctx.wallet.publicKey, - }) - ).addSigner(otherWallet); - - await assert.rejects( - tx.buildAndExecute(), - /0x7d3/ // ConstraintRaw - ); - }); - - it("should be failed: invalid token program", async () => { - const positionBundleInfo = await initializePositionBundle( - ctx, - ctx.wallet.publicKey, - ); - - const ix = program.instruction.deletePositionBundle({ - accounts: { - positionBundle: positionBundleInfo.positionBundlePda.publicKey, - positionBundleMint: positionBundleInfo.positionBundleMintKeypair.publicKey, - positionBundleTokenAccount: positionBundleInfo.positionBundleTokenAccount, - positionBundleOwner: ctx.wallet.publicKey, - tokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID, // invalid - receiver: ctx.wallet.publicKey, - } - }); - - const tx = toTx( - ctx, - { - instructions: [ix], - cleanupInstructions: [], - signers: [], - } - ); - - await assert.rejects( - tx.buildAndExecute(), - /0xbc0/ // InvalidProgramId - ); - }); - }); - -}); diff --git a/sdk/tests/integration/get_pool_prices.test.ts b/sdk/tests/integration/get_pool_prices.test.ts deleted file mode 100644 index c488516..0000000 --- a/sdk/tests/integration/get_pool_prices.test.ts +++ /dev/null @@ -1,277 +0,0 @@ -import * as anchor from "@coral-xyz/anchor"; -import { MathUtil } from "@orca-so/common-sdk"; -import { PublicKey } from "@solana/web3.js"; -import * as assert from "assert"; -import { BN } from "bn.js"; -import Decimal from "decimal.js"; -import { - GetPricesConfig, GetPricesThresholdConfig, PriceModule, - PriceModuleUtils, WhirlpoolContext -} from "../../src"; -import { TickSpacing } from "../utils"; -import { defaultConfirmOptions } from "../utils/const"; -import { - FundedPositionParams, - buildTestAquariums, - getDefaultAquarium, - initTestPoolWithLiquidity -} from "../utils/init-utils"; - -// TODO: Move these tests to use mock data instead of relying on solana localnet. It's very slow. -describe("get_pool_prices", () => { - const provider = anchor.AnchorProvider.local(undefined, defaultConfirmOptions); - const program = anchor.workspace.Whirlpool; - const context = WhirlpoolContext.fromWorkspace(provider, program); - - async function fetchMaps(context: WhirlpoolContext, mints: PublicKey[], config: GetPricesConfig) { - const poolMap = await PriceModuleUtils.fetchPoolDataFromMints(context.fetcher, mints, config); - const tickArrayMap = await PriceModuleUtils.fetchTickArraysForPools(context.fetcher, poolMap, config); - const decimalsMap = await PriceModuleUtils.fetchDecimalsForMints(context.fetcher, mints); - - return { poolMap, tickArrayMap, decimalsMap }; - } - - async function fetchAndCalculate( - context: WhirlpoolContext, - mints: PublicKey[], - config: GetPricesConfig, - thresholdConfig: GetPricesThresholdConfig - ) { - const { poolMap, tickArrayMap, decimalsMap } = await fetchMaps(context, mints, config); - - const priceMap = PriceModule.calculateTokenPrices( - mints, - { - poolMap, - tickArrayMap, - decimalsMap, - }, - config, - thresholdConfig - ); - - return { - poolMap, - tickArrayMap, - decimalsMap, - priceMap, - }; - } - - function getDefaultThresholdConfig(): GetPricesThresholdConfig { - return { - amountOut: new BN(1_000_000), - priceImpactThreshold: 1.05, - }; - } - - it("successfully calculates the price for one token with a single pool", async () => { - const { poolInitInfo, configInitInfo } = await initTestPoolWithLiquidity(context); - - const config: GetPricesConfig = { - quoteTokens: [poolInitInfo.tokenMintB], - tickSpacings: [TickSpacing.Standard], - programId: program.programId, - whirlpoolsConfig: configInitInfo.whirlpoolsConfigKeypair.publicKey, - }; - - const thresholdConfig = getDefaultThresholdConfig(); - - const mints = [poolInitInfo.tokenMintA, poolInitInfo.tokenMintB]; - - const { poolMap, tickArrayMap, priceMap } = await fetchAndCalculate( - context, - mints, - config, - thresholdConfig - ); - - assert.equal(Object.keys(poolMap).length, 1); - assert.equal(Object.keys(tickArrayMap).length, 1); // mintA to mintB direction - - assert.equal(Object.keys(priceMap).length, 2); - }); - - it("successfully calculates the price for two tokens against a third quote token", async () => { - const aqConfig = getDefaultAquarium(); - // Add a third token and account and a second pool - aqConfig.initMintParams.push({}); - aqConfig.initTokenAccParams.push({ mintIndex: 2 }); - aqConfig.initPoolParams.push({ mintIndices: [1, 2], tickSpacing: TickSpacing.Standard }); - - // Add tick arrays and positions - const aToB = false; - aqConfig.initTickArrayRangeParams.push({ - poolIndex: 0, - startTickIndex: 22528, - arrayCount: 3, - aToB, - }); - aqConfig.initTickArrayRangeParams.push({ - poolIndex: 1, - startTickIndex: 22528, - arrayCount: 3, - aToB, - }); - const fundParams: FundedPositionParams[] = [ - { - liquidityAmount: new anchor.BN(10_000_000), - tickLowerIndex: 29440, - tickUpperIndex: 33536, - }, - ]; - aqConfig.initPositionParams.push({ poolIndex: 0, fundParams }); - aqConfig.initPositionParams.push({ poolIndex: 1, fundParams }); - - const aquarium = (await buildTestAquariums(context, [aqConfig]))[0]; - const { mintKeys, configParams } = aquarium; - - const config: GetPricesConfig = { - quoteTokens: [mintKeys[1]], - tickSpacings: [TickSpacing.Standard], - programId: program.programId, - whirlpoolsConfig: configParams.configInitInfo.whirlpoolsConfigKeypair.publicKey, - }; - - const thresholdConfig = getDefaultThresholdConfig(); - - const mints = [mintKeys[0], mintKeys[1], mintKeys[2]]; - - const { poolMap, tickArrayMap, priceMap } = await fetchAndCalculate( - context, - mints, - config, - thresholdConfig - ); - - // mints are sorted (mintKeys[0] < mintKeys[1] < mintKeys[2]) - const fetchedTickArrayForPool0 = 1; // A to B direction (mintKeys[0] to mintKeys[1]) - const fetchedTickArrayForPool1 = 3; // B to A direction (mintKeys[2] to mintKeys[1]) - - assert.equal(Object.keys(poolMap).length, 2); - assert.equal(Object.keys(tickArrayMap).length, fetchedTickArrayForPool0 + fetchedTickArrayForPool1); - assert.equal(Object.keys(priceMap).length, 3); - }); - - it("successfully calculates the price for one token with multiple pools against a quote token", async () => { - const aqConfig = getDefaultAquarium(); - // Add a third token and account and a second pool - aqConfig.initPoolParams.push({ - mintIndices: [0, 1], - tickSpacing: TickSpacing.SixtyFour, - initSqrtPrice: MathUtil.toX64(new Decimal(5.2)), - }); - - // Add tick arrays and positions - const aToB = false; - - aqConfig.initTickArrayRangeParams.push({ - poolIndex: 0, - startTickIndex: 22528, - arrayCount: 3, - aToB, - }); - aqConfig.initTickArrayRangeParams.push({ - poolIndex: 1, - startTickIndex: 22528, - arrayCount: 3, - aToB, - }); - const fundParams0: FundedPositionParams[] = [ - { - liquidityAmount: new anchor.BN(10_000_000), - tickLowerIndex: 29440, - tickUpperIndex: 33536, - }, - ]; - const fundParams1: FundedPositionParams[] = [ - { - liquidityAmount: new anchor.BN(50_000_000), - tickLowerIndex: 29440, - tickUpperIndex: 33536, - }, - ]; - aqConfig.initPositionParams.push({ poolIndex: 0, fundParams: fundParams0 }); - aqConfig.initPositionParams.push({ poolIndex: 1, fundParams: fundParams1 }); - - const aquarium = (await buildTestAquariums(context, [aqConfig]))[0]; - const { mintKeys, configParams } = aquarium; - - const config: GetPricesConfig = { - quoteTokens: [mintKeys[1]], - tickSpacings: [TickSpacing.Standard, TickSpacing.SixtyFour], - programId: program.programId, - whirlpoolsConfig: configParams.configInitInfo.whirlpoolsConfigKeypair.publicKey, - }; - - const thresholdConfig = getDefaultThresholdConfig(); - - const mints = [mintKeys[0], mintKeys[1]]; - - const { poolMap, priceMap } = await fetchAndCalculate(context, mints, config, thresholdConfig); - - assert.equal(Object.keys(poolMap).length, 2); - assert.equal(Object.keys(priceMap).length, 2); - }); - - it("successfully calculates the price for one token which requires an indirect pool to calculate price", async () => { - const aqConfig = getDefaultAquarium(); - // Add a third token and account and a second pool - aqConfig.initMintParams.push({}); - aqConfig.initTokenAccParams.push({ mintIndex: 2 }); - aqConfig.initPoolParams.push({ mintIndices: [1, 2], tickSpacing: TickSpacing.Standard }); - - // Add tick arrays and positions - const aToB = false; - aqConfig.initTickArrayRangeParams.push({ - poolIndex: 0, - startTickIndex: 22528, - arrayCount: 3, - aToB, - }); - aqConfig.initTickArrayRangeParams.push({ - poolIndex: 1, - startTickIndex: 22528, - arrayCount: 3, - aToB, - }); - const fundParams: FundedPositionParams[] = [ - { - liquidityAmount: new anchor.BN(10_000_000_000), - tickLowerIndex: 29440, - tickUpperIndex: 33536, - }, - ]; - aqConfig.initPositionParams.push({ poolIndex: 0, fundParams }); - aqConfig.initPositionParams.push({ poolIndex: 1, fundParams }); - - const aquarium = (await buildTestAquariums(context, [aqConfig]))[0]; - const { mintKeys, configParams } = aquarium; - - const config: GetPricesConfig = { - quoteTokens: [mintKeys[2], mintKeys[1]], - tickSpacings: [TickSpacing.Standard], - programId: program.programId, - whirlpoolsConfig: configParams.configInitInfo.whirlpoolsConfigKeypair.publicKey, - }; - - const thresholdConfig = getDefaultThresholdConfig(); - - const mints = [mintKeys[0], mintKeys[1], mintKeys[2]]; - - const { poolMap, tickArrayMap, priceMap } = await fetchAndCalculate( - context, - mints, - config, - thresholdConfig - ); - - // mints are sorted (mintKeys[0] < mintKeys[1] < mintKeys[2]) - const fetchedTickArrayForPool0 = 1; // A to B direction (mintKeys[0] to mintKeys[1]) - const fetchedTickArrayForPool1 = 1; // A to B direction (mintKeys[1] to mintKeys[2]) - - assert.equal(Object.keys(poolMap).length, 2); - assert.equal(Object.keys(tickArrayMap).length, fetchedTickArrayForPool0 + fetchedTickArrayForPool1); - assert.equal(Object.keys(priceMap).length, 3); - }); -}); diff --git a/sdk/tests/integration/increase_liquidity.test.ts b/sdk/tests/integration/increase_liquidity.test.ts deleted file mode 100644 index f8f3ee4..0000000 --- a/sdk/tests/integration/increase_liquidity.test.ts +++ /dev/null @@ -1,1108 +0,0 @@ -import * as anchor from "@coral-xyz/anchor"; -import { MathUtil, TransactionBuilder } from "@orca-so/common-sdk"; -import * as assert from "assert"; -import { BN } from "bn.js"; -import Decimal from "decimal.js"; -import { - PDAUtil, - PositionData, - PriceMath, - TickArrayData, - TickUtil, - WhirlpoolContext, - WhirlpoolData, - WhirlpoolIx, - toTx -} from "../../src"; -import { IGNORE_CACHE } from "../../src/network/public/fetcher"; -import { PoolUtil, toTokenAmount } from "../../src/utils/public/pool-utils"; -import { - MAX_U64, - TickSpacing, - ZERO_BN, - approveToken, - assertTick, - createAndMintToTokenAccount, - createMint, - createTokenAccount, - getTokenBalance, - sleep, - transferToken -} from "../utils"; -import { defaultConfirmOptions } from "../utils/const"; -import { WhirlpoolTestFixture } from "../utils/fixture"; -import { initTestPool, initTickArray, openPosition } from "../utils/init-utils"; -import { - generateDefaultInitTickArrayParams, - generateDefaultOpenPositionParams -} from "../utils/test-builders"; - -describe("increase_liquidity", () => { - const provider = anchor.AnchorProvider.local(undefined, defaultConfirmOptions); - - const program = anchor.workspace.Whirlpool; - const ctx = WhirlpoolContext.fromWorkspace(provider, program); - const fetcher = ctx.fetcher; - - it("increase liquidity of a position spanning two tick arrays", async () => { - const currTick = 0; - const tickLowerIndex = -1280, - tickUpperIndex = 1280; - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing: TickSpacing.Standard, - positions: [{ tickLowerIndex, tickUpperIndex, liquidityAmount: ZERO_BN }], - initialSqrtPrice: PriceMath.tickIndexToSqrtPriceX64(currTick), - }); - const { poolInitInfo, positions, tokenAccountA, tokenAccountB } = fixture.getInfos(); - const { whirlpoolPda } = poolInitInfo; - const positionInitInfo = positions[0]; - - const poolBefore = (await fetcher.getPool(whirlpoolPda.publicKey, IGNORE_CACHE)) as WhirlpoolData; - const tokenAmount = toTokenAmount(167_000, 167_000); - const liquidityAmount = PoolUtil.estimateLiquidityFromTokenAmounts( - currTick, - tickLowerIndex, - tickUpperIndex, - tokenAmount - ); - - // To check if rewardLastUpdatedTimestamp is updated - await sleep(1200); - - await toTx( - ctx, - WhirlpoolIx.increaseLiquidityIx(ctx.program, { - liquidityAmount, - tokenMaxA: tokenAmount.tokenA, - tokenMaxB: tokenAmount.tokenB, - whirlpool: whirlpoolPda.publicKey, - positionAuthority: provider.wallet.publicKey, - position: positionInitInfo.publicKey, - positionTokenAccount: positionInitInfo.tokenAccount, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: tokenAccountB, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArrayLower: positionInitInfo.tickArrayLower, - tickArrayUpper: positionInitInfo.tickArrayUpper, - }) - ).buildAndExecute(); - - const position = (await fetcher.getPosition(positionInitInfo.publicKey, IGNORE_CACHE)) as PositionData; - assert.ok(position.liquidity.eq(liquidityAmount)); - - const poolAfter = (await fetcher.getPool(whirlpoolPda.publicKey, IGNORE_CACHE)) as WhirlpoolData; - assert.ok(poolAfter.rewardLastUpdatedTimestamp.gt(poolBefore.rewardLastUpdatedTimestamp)); - assert.equal( - await getTokenBalance(provider, poolInitInfo.tokenVaultAKeypair.publicKey), - tokenAmount.tokenA.toString() - ); - assert.equal( - await getTokenBalance(provider, poolInitInfo.tokenVaultBKeypair.publicKey), - tokenAmount.tokenB.toString() - ); - assert.ok(poolAfter.liquidity.eq(new anchor.BN(liquidityAmount))); - - const tickArrayLower = (await fetcher.getTickArray( - positionInitInfo.tickArrayLower, - IGNORE_CACHE - )) as TickArrayData; - assertTick(tickArrayLower.ticks[78], true, liquidityAmount, liquidityAmount); - const tickArrayUpper = (await fetcher.getTickArray( - positionInitInfo.tickArrayUpper, - IGNORE_CACHE - )) as TickArrayData; - assertTick(tickArrayUpper.ticks[10], true, liquidityAmount, liquidityAmount.neg()); - }); - - it("increase liquidity of a position contained in one tick array", async () => { - const currTick = 500; - const tickLowerIndex = 7168; - const tickUpperIndex = 8960; - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing: TickSpacing.Standard, - positions: [{ tickLowerIndex, tickUpperIndex, liquidityAmount: ZERO_BN }], - initialSqrtPrice: PriceMath.tickIndexToSqrtPriceX64(currTick), - }); - const { poolInitInfo, positions, tokenAccountA, tokenAccountB } = fixture.getInfos(); - const { whirlpoolPda } = poolInitInfo; - const positionInitInfo = positions[0]; - const poolBefore = (await fetcher.getPool(whirlpoolPda.publicKey, IGNORE_CACHE)) as WhirlpoolData; - - const tokenAmount = toTokenAmount(1_000_000, 0); - const liquidityAmount = PoolUtil.estimateLiquidityFromTokenAmounts( - currTick, - tickLowerIndex, - tickUpperIndex, - tokenAmount - ); - - await toTx( - ctx, - WhirlpoolIx.increaseLiquidityIx(ctx.program, { - liquidityAmount, - tokenMaxA: tokenAmount.tokenA, - tokenMaxB: tokenAmount.tokenB, - whirlpool: whirlpoolPda.publicKey, - positionAuthority: provider.wallet.publicKey, - position: positionInitInfo.publicKey, - positionTokenAccount: positionInitInfo.tokenAccount, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: tokenAccountB, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArrayLower: positionInitInfo.tickArrayLower, - tickArrayUpper: positionInitInfo.tickArrayUpper, - }) - ).buildAndExecute(); - - assert.equal( - await getTokenBalance(provider, poolInitInfo.tokenVaultAKeypair.publicKey), - tokenAmount.tokenA.toString() - ); - - assert.equal( - await getTokenBalance(provider, poolInitInfo.tokenVaultBKeypair.publicKey), - tokenAmount.tokenB.toString() - ); - - const expectedLiquidity = new anchor.BN(liquidityAmount); - const position = (await fetcher.getPosition(positionInitInfo.publicKey, IGNORE_CACHE)) as PositionData; - assert.ok(position.liquidity.eq(expectedLiquidity)); - - const tickArray = (await fetcher.getTickArray( - positionInitInfo.tickArrayLower, - IGNORE_CACHE - )) as TickArrayData; - - assertTick(tickArray.ticks[56], true, expectedLiquidity, expectedLiquidity); - assertTick(tickArray.ticks[70], true, expectedLiquidity, expectedLiquidity.neg()); - - const poolAfter = (await fetcher.getPool(whirlpoolPda.publicKey, IGNORE_CACHE)) as WhirlpoolData; - assert.ok(poolAfter.rewardLastUpdatedTimestamp.gte(poolBefore.rewardLastUpdatedTimestamp)); - assert.equal(poolAfter.liquidity, 0); - }); - - it("initialize and increase liquidity of a position in a single transaction", async () => { - const currTick = 500; - const tickLowerIndex = 7168; - const tickUpperIndex = 8960; - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing: TickSpacing.Standard, - initialSqrtPrice: PriceMath.tickIndexToSqrtPriceX64(currTick), - }); - const { poolInitInfo, tokenAccountA, tokenAccountB } = fixture.getInfos(); - const { whirlpoolPda, tickSpacing } = poolInitInfo; - const poolBefore = (await fetcher.getPool(whirlpoolPda.publicKey, IGNORE_CACHE)) as WhirlpoolData; - - const tokenAmount = toTokenAmount(1_000_000, 0); - const liquidityAmount = PoolUtil.estimateLiquidityFromTokenAmounts( - currTick, - tickLowerIndex, - tickUpperIndex, - tokenAmount - ); - - const { params, mint } = await generateDefaultOpenPositionParams( - ctx, - whirlpoolPda.publicKey, - tickLowerIndex, - tickUpperIndex, - ctx.wallet.publicKey - ); - - const tickArrayLower = PDAUtil.getTickArray( - ctx.program.programId, - whirlpoolPda.publicKey, - TickUtil.getStartTickIndex(tickLowerIndex, tickSpacing) - ).publicKey; - - const tickArrayUpper = PDAUtil.getTickArray( - ctx.program.programId, - whirlpoolPda.publicKey, - TickUtil.getStartTickIndex(tickUpperIndex, tickSpacing) - ).publicKey; - - await new TransactionBuilder(ctx.provider.connection, ctx.provider.wallet, ctx.txBuilderOpts) - // TODO: create a ComputeBudgetInstruction to request more compute - .addInstruction( - WhirlpoolIx.initTickArrayIx( - ctx.program, - generateDefaultInitTickArrayParams( - ctx, - whirlpoolPda.publicKey, - TickUtil.getStartTickIndex(tickLowerIndex, tickSpacing) - ) - ) - ) - // .addInstruction( - // buildtoTx(ctx, WhirlpoolIx.initTickArrayIx(generateDefaultInitTickArrayParams( - // ctx, - // whirlpoolPda.publicKey, - // getStartTickIndex(pos[0].tickLowerIndex + TICK_ARRAY_SIZE * tickSpacing, tickSpacing), - // )) - // ) - .addInstruction(WhirlpoolIx.openPositionIx(ctx.program, params)) - // .addInstruction( - // buildWhirlpoolIx.openPositionWithMetadataIx(ctx.program, params) - // ) - .addSigner(mint) - .addInstruction( - WhirlpoolIx.increaseLiquidityIx(ctx.program, { - liquidityAmount, - tokenMaxA: tokenAmount.tokenA, - tokenMaxB: tokenAmount.tokenB, - whirlpool: whirlpoolPda.publicKey, - positionAuthority: provider.wallet.publicKey, - position: params.positionPda.publicKey, - positionTokenAccount: params.positionTokenAccount, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: tokenAccountB, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArrayLower: tickArrayLower, - tickArrayUpper: tickArrayUpper, - }) - ) - .buildAndExecute(); - - assert.equal( - await getTokenBalance(provider, poolInitInfo.tokenVaultAKeypair.publicKey), - tokenAmount.tokenA.toString() - ); - - assert.equal( - await getTokenBalance(provider, poolInitInfo.tokenVaultBKeypair.publicKey), - tokenAmount.tokenB.toString() - ); - - const expectedLiquidity = new anchor.BN(liquidityAmount); - const position = (await fetcher.getPosition( - params.positionPda.publicKey, - IGNORE_CACHE - )) as PositionData; - assert.ok(position.liquidity.eq(expectedLiquidity)); - - const tickArray = (await fetcher.getTickArray(tickArrayLower, IGNORE_CACHE)) as TickArrayData; - - assertTick(tickArray.ticks[56], true, expectedLiquidity, expectedLiquidity); - assertTick(tickArray.ticks[70], true, expectedLiquidity, expectedLiquidity.neg()); - - const poolAfter = (await fetcher.getPool(whirlpoolPda.publicKey, IGNORE_CACHE)) as WhirlpoolData; - assert.ok(poolAfter.rewardLastUpdatedTimestamp.gte(poolBefore.rewardLastUpdatedTimestamp)); - assert.equal(poolAfter.liquidity, 0); - }); - - it("increase liquidity of a position with an approved position authority delegate", async () => { - const currTick = 1300; - const tickLowerIndex = -1280, - tickUpperIndex = 1280; - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing: TickSpacing.Standard, - positions: [{ tickLowerIndex, tickUpperIndex, liquidityAmount: ZERO_BN }], - initialSqrtPrice: PriceMath.tickIndexToSqrtPriceX64(currTick), - }); - const { poolInitInfo, positions, tokenAccountA, tokenAccountB } = fixture.getInfos(); - const { whirlpoolPda } = poolInitInfo; - const positionInitInfo = positions[0]; - - const poolBefore = (await fetcher.getPool(whirlpoolPda.publicKey, IGNORE_CACHE)) as WhirlpoolData; - const tokenAmount = toTokenAmount(0, 167_000); - const liquidityAmount = PoolUtil.estimateLiquidityFromTokenAmounts( - currTick, - tickLowerIndex, - tickUpperIndex, - tokenAmount - ); - - const delegate = anchor.web3.Keypair.generate(); - await approveToken(provider, positionInitInfo.tokenAccount, delegate.publicKey, 1); - await approveToken(provider, tokenAccountA, delegate.publicKey, 1_000_000); - await approveToken(provider, tokenAccountB, delegate.publicKey, 1_000_000); - - await toTx( - ctx, - WhirlpoolIx.increaseLiquidityIx(ctx.program, { - liquidityAmount, - tokenMaxA: tokenAmount.tokenA, - tokenMaxB: tokenAmount.tokenB, - whirlpool: whirlpoolPda.publicKey, - positionAuthority: delegate.publicKey, - position: positionInitInfo.publicKey, - positionTokenAccount: positionInitInfo.tokenAccount, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: tokenAccountB, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArrayLower: positionInitInfo.tickArrayLower, - tickArrayUpper: positionInitInfo.tickArrayUpper, - }) - ) - .addSigner(delegate) - .buildAndExecute(); - - const position = (await fetcher.getPosition(positionInitInfo.publicKey, IGNORE_CACHE)) as PositionData; - assert.ok(position.liquidity.eq(liquidityAmount)); - - const poolAfter = (await fetcher.getPool(whirlpoolPda.publicKey, IGNORE_CACHE)) as WhirlpoolData; - assert.ok(poolAfter.rewardLastUpdatedTimestamp.gte(poolBefore.rewardLastUpdatedTimestamp)); - assert.equal( - await getTokenBalance(provider, poolInitInfo.tokenVaultAKeypair.publicKey), - tokenAmount.tokenA.toString() - ); - assert.equal( - await getTokenBalance(provider, poolInitInfo.tokenVaultBKeypair.publicKey), - tokenAmount.tokenB.toString() - ); - assert.equal(poolAfter.liquidity, 0); - - const tickArrayLower = (await fetcher.getTickArray( - positionInitInfo.tickArrayLower, - IGNORE_CACHE - )) as TickArrayData; - assertTick(tickArrayLower.ticks[78], true, liquidityAmount, liquidityAmount); - const tickArrayUpper = (await fetcher.getTickArray( - positionInitInfo.tickArrayUpper, - IGNORE_CACHE - )) as TickArrayData; - assertTick(tickArrayUpper.ticks[10], true, liquidityAmount, liquidityAmount.neg()); - }); - - it("add maximum amount of liquidity near minimum price", async () => { - const currTick = -443621; - const { poolInitInfo } = await initTestPool( - ctx, - TickSpacing.Stable, - PriceMath.tickIndexToSqrtPriceX64(currTick) - ); - - const { tokenMintA, tokenMintB, whirlpoolPda } = poolInitInfo; - const tokenAccountA = await createAndMintToTokenAccount(provider, tokenMintA, MAX_U64); - const tokenAccountB = await createAndMintToTokenAccount(provider, tokenMintB, MAX_U64); - - const { - params: { tickArrayPda }, - } = await initTickArray(ctx, whirlpoolPda.publicKey, -444224); - - const tickLowerIndex = -443632; - const tickUpperIndex = -443624; - const positionInfo = await openPosition( - ctx, - whirlpoolPda.publicKey, - tickLowerIndex, - tickUpperIndex - ); - const { positionPda, positionTokenAccount: positionTokenAccountAddress } = positionInfo.params; - - const tokenAmount = { - tokenA: new BN(0), - tokenB: MAX_U64, - }; - const estLiquidityAmount = PoolUtil.estimateLiquidityFromTokenAmounts( - currTick, - tickLowerIndex, - tickUpperIndex, - tokenAmount - ); - - await toTx( - ctx, - WhirlpoolIx.increaseLiquidityIx(ctx.program, { - liquidityAmount: estLiquidityAmount, - tokenMaxA: tokenAmount.tokenA, - tokenMaxB: tokenAmount.tokenB, - whirlpool: whirlpoolPda.publicKey, - positionAuthority: provider.wallet.publicKey, - position: positionPda.publicKey, - positionTokenAccount: positionTokenAccountAddress, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: tokenAccountB, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArrayLower: tickArrayPda.publicKey, - tickArrayUpper: tickArrayPda.publicKey, - }) - ).buildAndExecute(); - - const position = (await fetcher.getPosition(positionPda.publicKey, IGNORE_CACHE)) as PositionData; - assert.ok(position.liquidity.eq(estLiquidityAmount)); - }); - - it("add maximum amount of liquidity near maximum price", async () => { - const currTick = 443635; - const { poolInitInfo } = await initTestPool( - ctx, - TickSpacing.Stable, - PriceMath.tickIndexToSqrtPriceX64(currTick) - ); - - const { tokenMintA, tokenMintB, whirlpoolPda } = poolInitInfo; - const tokenAccountA = await createAndMintToTokenAccount(provider, tokenMintA, MAX_U64); - const tokenAccountB = await createAndMintToTokenAccount(provider, tokenMintB, MAX_U64); - - const { - params: { tickArrayPda }, - } = await initTickArray(ctx, whirlpoolPda.publicKey, 436480); - - const tickLowerIndex = 436488; - const tickUpperIndex = 436496; - const positionInfo = await openPosition( - ctx, - whirlpoolPda.publicKey, - tickLowerIndex, - tickUpperIndex - ); - const { positionPda, positionTokenAccount: positionTokenAccountAddress } = positionInfo.params; - - const tokenAmount = { - tokenA: new BN(0), - tokenB: MAX_U64, - }; - const estLiquidityAmount = PoolUtil.estimateLiquidityFromTokenAmounts( - currTick, - tickLowerIndex, - tickUpperIndex, - tokenAmount - ); - - await toTx( - ctx, - WhirlpoolIx.increaseLiquidityIx(ctx.program, { - liquidityAmount: estLiquidityAmount, - tokenMaxA: tokenAmount.tokenA, - tokenMaxB: tokenAmount.tokenB, - whirlpool: whirlpoolPda.publicKey, - positionAuthority: provider.wallet.publicKey, - position: positionPda.publicKey, - positionTokenAccount: positionTokenAccountAddress, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: tokenAccountB, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArrayLower: tickArrayPda.publicKey, - tickArrayUpper: tickArrayPda.publicKey, - }) - ).buildAndExecute(); - - const position = (await fetcher.getPosition(positionPda.publicKey, IGNORE_CACHE)) as PositionData; - assert.ok(position.liquidity.eq(estLiquidityAmount)); - }); - - it("fails with zero liquidity amount", async () => { - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing: TickSpacing.Standard, - positions: [{ tickLowerIndex: 7168, tickUpperIndex: 8960, liquidityAmount: ZERO_BN }], - }); - const { poolInitInfo, positions, tokenAccountA, tokenAccountB } = fixture.getInfos(); - const { whirlpoolPda } = poolInitInfo; - const positionInitInfo = positions[0]; - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.increaseLiquidityIx(ctx.program, { - liquidityAmount: ZERO_BN, - tokenMaxA: new BN(0), - tokenMaxB: new BN(1_000_000), - whirlpool: whirlpoolPda.publicKey, - positionAuthority: provider.wallet.publicKey, - position: positionInitInfo.publicKey, - positionTokenAccount: positionInitInfo.tokenAccount, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: tokenAccountB, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArrayLower: positionInitInfo.tickArrayLower, - tickArrayUpper: positionInitInfo.tickArrayUpper, - }) - ).buildAndExecute(), - /0x177c/ // LiquidityZero - ); - }); - - it("fails when token max a exceeded", async () => { - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing: TickSpacing.Standard, - initialSqrtPrice: MathUtil.toX64(new Decimal(1)), - positions: [{ tickLowerIndex: 7168, tickUpperIndex: 8960, liquidityAmount: ZERO_BN }], - }); - const { poolInitInfo, positions, tokenAccountA, tokenAccountB } = fixture.getInfos(); - const { whirlpoolPda } = poolInitInfo; - const positionInitInfo = positions[0]; - - const liquidityAmount = new anchor.BN(6_500_000); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.increaseLiquidityIx(ctx.program, { - liquidityAmount, - tokenMaxA: new BN(0), - tokenMaxB: new BN(999_999_999), - whirlpool: whirlpoolPda.publicKey, - positionAuthority: provider.wallet.publicKey, - position: positionInitInfo.publicKey, - positionTokenAccount: positionInitInfo.tokenAccount, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: tokenAccountB, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArrayLower: positionInitInfo.tickArrayLower, - tickArrayUpper: positionInitInfo.tickArrayUpper, - }) - ).buildAndExecute(), - /0x1781/ // TokenMaxExceeded - ); - }); - - it("fails when token max b exceeded", async () => { - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing: TickSpacing.Standard, - positions: [{ tickLowerIndex: 7168, tickUpperIndex: 8960, liquidityAmount: ZERO_BN }], - }); - const { poolInitInfo, positions, tokenAccountA, tokenAccountB } = fixture.getInfos(); - const { whirlpoolPda } = poolInitInfo; - const positionInitInfo = positions[0]; - - const liquidityAmount = new anchor.BN(6_500_000); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.increaseLiquidityIx(ctx.program, { - liquidityAmount, - tokenMaxA: new BN(999_999_999), - tokenMaxB: new BN(0), - whirlpool: whirlpoolPda.publicKey, - positionAuthority: provider.wallet.publicKey, - position: positionInitInfo.publicKey, - positionTokenAccount: positionInitInfo.tokenAccount, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: tokenAccountB, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArrayLower: positionInitInfo.tickArrayLower, - tickArrayUpper: positionInitInfo.tickArrayUpper, - }) - ).buildAndExecute(), - /0x1781/ // TokenMaxExceeded - ); - }); - - it("fails when position account does not have exactly 1 token", async () => { - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing: TickSpacing.Standard, - positions: [{ tickLowerIndex: 7168, tickUpperIndex: 8960, liquidityAmount: ZERO_BN }], - }); - const { poolInitInfo, positions, tokenAccountA, tokenAccountB } = fixture.getInfos(); - const { whirlpoolPda } = poolInitInfo; - const positionInitInfo = positions[0]; - - // Create a position token account that contains 0 tokens - const newPositionTokenAccount = await createTokenAccount( - provider, - positionInitInfo.mintKeypair.publicKey, - provider.wallet.publicKey - ); - - const liquidityAmount = new anchor.BN(6_500_000); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.increaseLiquidityIx(ctx.program, { - liquidityAmount, - tokenMaxA: new BN(0), - tokenMaxB: new BN(1_000_000), - whirlpool: whirlpoolPda.publicKey, - positionAuthority: provider.wallet.publicKey, - position: positionInitInfo.publicKey, - positionTokenAccount: newPositionTokenAccount, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: tokenAccountB, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArrayLower: positionInitInfo.tickArrayLower, - tickArrayUpper: positionInitInfo.tickArrayUpper, - }) - ).buildAndExecute(), - /0x7d3/ // ConstraintRaw - ); - - // Send position token to other position token account - await transferToken(provider, positionInitInfo.tokenAccount, newPositionTokenAccount, 1); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.increaseLiquidityIx(ctx.program, { - liquidityAmount, - tokenMaxA: new BN(0), - tokenMaxB: new BN(1_000_000), - whirlpool: whirlpoolPda.publicKey, - positionAuthority: provider.wallet.publicKey, - position: positionInitInfo.publicKey, - positionTokenAccount: positionInitInfo.tokenAccount, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: tokenAccountB, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArrayLower: positionInitInfo.tickArrayLower, - tickArrayUpper: positionInitInfo.tickArrayUpper, - }) - ).buildAndExecute(), - /0x7d3/ // ConstraintRaw - ); - }); - - it("fails when position token account mint does not match position mint", async () => { - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing: TickSpacing.Standard, - positions: [{ tickLowerIndex: 7168, tickUpperIndex: 8960, liquidityAmount: ZERO_BN }], - }); - const { poolInitInfo, positions, tokenAccountA, tokenAccountB } = fixture.getInfos(); - const { whirlpoolPda, tokenMintA } = poolInitInfo; - const positionInitInfo = positions[0]; - - // Create a position token account that contains 0 tokens - const invalidPositionTokenAccount = await createAndMintToTokenAccount(provider, tokenMintA, 1); - - const liquidityAmount = new anchor.BN(6_500_000); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.increaseLiquidityIx(ctx.program, { - liquidityAmount, - tokenMaxA: new BN(0), - tokenMaxB: new BN(1_000_000), - whirlpool: whirlpoolPda.publicKey, - positionAuthority: provider.wallet.publicKey, - position: positionInitInfo.publicKey, - positionTokenAccount: invalidPositionTokenAccount, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: tokenAccountB, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArrayLower: positionInitInfo.tickArrayLower, - tickArrayUpper: positionInitInfo.tickArrayUpper, - }) - ).buildAndExecute(), - /0x7d3/ // A raw constraint was violated - ); - }); - - it("fails when position does not match whirlpool", async () => { - const tickLowerIndex = 7168; - const tickUpperIndex = 8960; - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing: TickSpacing.Standard, - positions: [{ tickLowerIndex, tickUpperIndex, liquidityAmount: ZERO_BN }], - }); - const { poolInitInfo, tokenAccountA, tokenAccountB } = fixture.getInfos(); - const { whirlpoolPda } = poolInitInfo; - - const { poolInitInfo: poolInitInfo2 } = await initTestPool(ctx, TickSpacing.Standard); - const positionInitInfo = await openPosition( - ctx, - poolInitInfo2.whirlpoolPda.publicKey, - tickLowerIndex, - tickUpperIndex - ); - const { positionPda, positionTokenAccount: positionTokenAccountAddress } = - positionInitInfo.params; - - const { - params: { tickArrayPda }, - } = await initTickArray(ctx, poolInitInfo2.whirlpoolPda.publicKey, 0); - - const liquidityAmount = new anchor.BN(6_500_000); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.increaseLiquidityIx(ctx.program, { - liquidityAmount, - tokenMaxA: new BN(0), - tokenMaxB: new BN(1_000_000), - whirlpool: whirlpoolPda.publicKey, - positionAuthority: provider.wallet.publicKey, - position: positionPda.publicKey, - positionTokenAccount: positionTokenAccountAddress, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: tokenAccountB, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArrayLower: tickArrayPda.publicKey, - tickArrayUpper: tickArrayPda.publicKey, - }) - ).buildAndExecute(), - /0x7d1/ // A has_one constraint was violated - ); - }); - - it("fails when token vaults do not match whirlpool vaults", async () => { - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing: TickSpacing.Standard, - positions: [{ tickLowerIndex: 7168, tickUpperIndex: 8960, liquidityAmount: ZERO_BN }], - }); - const { poolInitInfo, positions, tokenAccountA, tokenAccountB } = fixture.getInfos(); - const { whirlpoolPda, tokenMintA, tokenMintB } = poolInitInfo; - const positionInitInfo = positions[0]; - const liquidityAmount = new anchor.BN(6_500_000); - - const fakeVaultA = await createAndMintToTokenAccount(provider, tokenMintA, 1_000); - const fakeVaultB = await createAndMintToTokenAccount(provider, tokenMintB, 1_000); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.increaseLiquidityIx(ctx.program, { - liquidityAmount, - tokenMaxA: new BN(0), - tokenMaxB: new BN(1_000_000), - whirlpool: whirlpoolPda.publicKey, - positionAuthority: provider.wallet.publicKey, - position: positionInitInfo.publicKey, - positionTokenAccount: positionInitInfo.tokenAccount, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: tokenAccountB, - tokenVaultA: fakeVaultA, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArrayLower: positionInitInfo.tickArrayLower, - tickArrayUpper: positionInitInfo.tickArrayUpper, - }) - ).buildAndExecute(), - /0x7d3/ // ConstraintRaw - ); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.increaseLiquidityIx(ctx.program, { - liquidityAmount, - tokenMaxA: new BN(0), - tokenMaxB: new BN(1_000_000), - whirlpool: whirlpoolPda.publicKey, - positionAuthority: provider.wallet.publicKey, - position: positionInitInfo.publicKey, - positionTokenAccount: positionInitInfo.tokenAccount, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: tokenAccountB, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenVaultB: fakeVaultB, - tickArrayLower: positionInitInfo.tickArrayLower, - tickArrayUpper: positionInitInfo.tickArrayUpper, - }) - ).buildAndExecute(), - /0x7d3/ // ConstraintRaw - ); - }); - - it("fails when owner token account mint does not match whirlpool token mint", async () => { - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing: TickSpacing.Standard, - positions: [{ tickLowerIndex: 7168, tickUpperIndex: 8960, liquidityAmount: ZERO_BN }], - }); - const { poolInitInfo, positions, tokenAccountA, tokenAccountB } = fixture.getInfos(); - const { whirlpoolPda } = poolInitInfo; - const positionInitInfo = positions[0]; - const liquidityAmount = new anchor.BN(6_500_000); - - const invalidMint = await createMint(provider); - const invalidTokenAccount = await createAndMintToTokenAccount(provider, invalidMint, 1_000_000); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.increaseLiquidityIx(ctx.program, { - liquidityAmount, - tokenMaxA: new BN(0), - tokenMaxB: new BN(1_000_000), - whirlpool: whirlpoolPda.publicKey, - positionAuthority: provider.wallet.publicKey, - position: positionInitInfo.publicKey, - positionTokenAccount: positionInitInfo.tokenAccount, - tokenOwnerAccountA: invalidTokenAccount, - tokenOwnerAccountB: tokenAccountB, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArrayLower: positionInitInfo.tickArrayLower, - tickArrayUpper: positionInitInfo.tickArrayUpper, - }) - ).buildAndExecute(), - /0x7d3/ // ConstraintRaw - ); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.increaseLiquidityIx(ctx.program, { - liquidityAmount, - tokenMaxA: new BN(0), - tokenMaxB: new BN(1_000_000), - whirlpool: whirlpoolPda.publicKey, - positionAuthority: provider.wallet.publicKey, - position: positionInitInfo.publicKey, - positionTokenAccount: positionInitInfo.tokenAccount, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: invalidTokenAccount, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArrayLower: positionInitInfo.tickArrayLower, - tickArrayUpper: positionInitInfo.tickArrayUpper, - }) - ).buildAndExecute(), - /0x7d3/ // ConstraintRaw - ); - }); - - it("fails when position authority is not approved delegate for position token account", async () => { - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing: TickSpacing.Standard, - positions: [{ tickLowerIndex: -1280, tickUpperIndex: 1280, liquidityAmount: ZERO_BN }], - }); - const { poolInitInfo, positions, tokenAccountA, tokenAccountB } = fixture.getInfos(); - const { whirlpoolPda } = poolInitInfo; - const positionInitInfo = positions[0]; - - const delegate = anchor.web3.Keypair.generate(); - - const liquidityAmount = new anchor.BN(1_250_000); - - await approveToken(provider, tokenAccountA, delegate.publicKey, 1_000_000); - await approveToken(provider, tokenAccountB, delegate.publicKey, 1_000_000); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.increaseLiquidityIx(ctx.program, { - liquidityAmount, - tokenMaxA: new BN(0), - tokenMaxB: new BN(167_000), - whirlpool: whirlpoolPda.publicKey, - positionAuthority: delegate.publicKey, - position: positionInitInfo.publicKey, - positionTokenAccount: positionInitInfo.tokenAccount, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: tokenAccountB, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArrayLower: positionInitInfo.tickArrayLower, - tickArrayUpper: positionInitInfo.tickArrayUpper, - }) - ) - .addSigner(delegate) - .buildAndExecute(), - /0x1783/ // MissingOrInvalidDelegate - ); - }); - - it("fails when position authority is not authorized for exactly 1 token", async () => { - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing: TickSpacing.Standard, - positions: [{ tickLowerIndex: -1280, tickUpperIndex: 1280, liquidityAmount: ZERO_BN }], - }); - const { poolInitInfo, positions, tokenAccountA, tokenAccountB } = fixture.getInfos(); - const { whirlpoolPda } = poolInitInfo; - const positionInitInfo = positions[0]; - - const delegate = anchor.web3.Keypair.generate(); - - const liquidityAmount = new anchor.BN(1_250_000); - - await approveToken(provider, positionInitInfo.tokenAccount, delegate.publicKey, 0); - await approveToken(provider, tokenAccountA, delegate.publicKey, 1_000_000); - await approveToken(provider, tokenAccountB, delegate.publicKey, 1_000_000); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.increaseLiquidityIx(ctx.program, { - liquidityAmount, - tokenMaxA: new BN(0), - tokenMaxB: new BN(167_000), - whirlpool: whirlpoolPda.publicKey, - positionAuthority: delegate.publicKey, - position: positionInitInfo.publicKey, - positionTokenAccount: positionInitInfo.tokenAccount, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: tokenAccountB, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArrayLower: positionInitInfo.tickArrayLower, - tickArrayUpper: positionInitInfo.tickArrayUpper, - }) - ) - .addSigner(delegate) - .buildAndExecute(), - /0x1784/ // InvalidPositionTokenAmount - ); - }); - - it("fails when position authority was not a signer", async () => { - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing: TickSpacing.Standard, - positions: [{ tickLowerIndex: -1280, tickUpperIndex: 1280, liquidityAmount: ZERO_BN }], - }); - const { poolInitInfo, positions, tokenAccountA, tokenAccountB } = fixture.getInfos(); - const { whirlpoolPda } = poolInitInfo; - const positionInitInfo = positions[0]; - - const delegate = anchor.web3.Keypair.generate(); - - const liquidityAmount = new anchor.BN(1_250_000); - - await approveToken(provider, positionInitInfo.tokenAccount, delegate.publicKey, 1); - await approveToken(provider, tokenAccountA, delegate.publicKey, 1_000_000); - await approveToken(provider, tokenAccountB, delegate.publicKey, 1_000_000); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.increaseLiquidityIx(ctx.program, { - liquidityAmount, - tokenMaxA: new BN(0), - tokenMaxB: new BN(167_000), - whirlpool: whirlpoolPda.publicKey, - positionAuthority: delegate.publicKey, - position: positionInitInfo.publicKey, - positionTokenAccount: positionInitInfo.tokenAccount, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: tokenAccountB, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArrayLower: positionInitInfo.tickArrayLower, - tickArrayUpper: positionInitInfo.tickArrayUpper, - }) - ).buildAndExecute(), - /.*signature verification fail.*/i - ); - }); - - it("fails when position authority is not approved for token owner accounts", async () => { - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing: TickSpacing.Standard, - positions: [{ tickLowerIndex: -1280, tickUpperIndex: 1280, liquidityAmount: ZERO_BN }], - }); - const { poolInitInfo, positions, tokenAccountA, tokenAccountB } = fixture.getInfos(); - const { whirlpoolPda } = poolInitInfo; - const positionInitInfo = positions[0]; - - const delegate = anchor.web3.Keypair.generate(); - - const liquidityAmount = new anchor.BN(1_250_000); - - await approveToken(provider, positionInitInfo.tokenAccount, delegate.publicKey, 1); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.increaseLiquidityIx(ctx.program, { - liquidityAmount, - tokenMaxA: new BN(0), - tokenMaxB: new BN(167_000), - whirlpool: whirlpoolPda.publicKey, - positionAuthority: delegate.publicKey, - position: positionInitInfo.publicKey, - positionTokenAccount: positionInitInfo.tokenAccount, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: tokenAccountB, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArrayLower: positionInitInfo.tickArrayLower, - tickArrayUpper: positionInitInfo.tickArrayUpper, - }) - ) - .addSigner(delegate) - .buildAndExecute(), - /0x4/ // owner does not match - ); - }); - - it("fails when tick arrays do not match the position", async () => { - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing: TickSpacing.Standard, - positions: [{ tickLowerIndex: -1280, tickUpperIndex: 1280, liquidityAmount: ZERO_BN }], - }); - const { poolInitInfo, positions, tokenAccountA, tokenAccountB } = fixture.getInfos(); - const { whirlpoolPda } = poolInitInfo; - const positionInitInfo = positions[0]; - - const { - params: { tickArrayPda: tickArrayLowerPda }, - } = await initTickArray(ctx, whirlpoolPda.publicKey, 11264); - - const { - params: { tickArrayPda: tickArrayUpperPda }, - } = await initTickArray(ctx, whirlpoolPda.publicKey, 22528); - - const liquidityAmount = new anchor.BN(1_250_000); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.increaseLiquidityIx(ctx.program, { - liquidityAmount, - tokenMaxA: new BN(0), - tokenMaxB: new BN(167_000), - whirlpool: whirlpoolPda.publicKey, - positionAuthority: provider.wallet.publicKey, - position: positionInitInfo.publicKey, - positionTokenAccount: positionInitInfo.tokenAccount, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: tokenAccountB, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArrayLower: tickArrayLowerPda.publicKey, - tickArrayUpper: tickArrayUpperPda.publicKey, - }) - ).buildAndExecute(), - /0x1779/ // TicKNotFound - ); - }); - - it("fails when the tick arrays are for a different whirlpool", async () => { - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing: TickSpacing.Standard, - positions: [{ tickLowerIndex: -1280, tickUpperIndex: 1280, liquidityAmount: ZERO_BN }], - }); - const { poolInitInfo, positions, tokenAccountA, tokenAccountB } = fixture.getInfos(); - const { whirlpoolPda } = poolInitInfo; - const positionInitInfo = positions[0]; - - const { poolInitInfo: poolInitInfo2 } = await initTestPool(ctx, TickSpacing.Standard); - - const { - params: { tickArrayPda: tickArrayLowerPda }, - } = await initTickArray(ctx, poolInitInfo2.whirlpoolPda.publicKey, -11264); - - const { - params: { tickArrayPda: tickArrayUpperPda }, - } = await initTickArray(ctx, poolInitInfo2.whirlpoolPda.publicKey, 0); - - const liquidityAmount = new anchor.BN(1_250_000); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.increaseLiquidityIx(ctx.program, { - liquidityAmount, - tokenMaxA: new BN(0), - tokenMaxB: new BN(167_000), - whirlpool: whirlpoolPda.publicKey, - positionAuthority: provider.wallet.publicKey, - position: positionInitInfo.publicKey, - positionTokenAccount: positionInitInfo.tokenAccount, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: tokenAccountB, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArrayLower: tickArrayLowerPda.publicKey, - tickArrayUpper: tickArrayUpperPda.publicKey, - }) - ).buildAndExecute(), - /0x7d1/ // A has one constraint was violated - ); - }); -}); diff --git a/sdk/tests/integration/initialize_config.test.ts b/sdk/tests/integration/initialize_config.test.ts deleted file mode 100644 index 75424dc..0000000 --- a/sdk/tests/integration/initialize_config.test.ts +++ /dev/null @@ -1,70 +0,0 @@ -import * as anchor from "@coral-xyz/anchor"; -import * as assert from "assert"; -import { - InitConfigParams, - toTx, - WhirlpoolContext, - WhirlpoolIx, - WhirlpoolsConfigData -} from "../../src"; -import { ONE_SOL, systemTransferTx } from "../utils"; -import { defaultConfirmOptions } from "../utils/const"; -import { generateDefaultConfigParams } from "../utils/test-builders"; - -describe("initialize_config", () => { - const provider = anchor.AnchorProvider.local(undefined, defaultConfirmOptions); - - const program = anchor.workspace.Whirlpool; - const ctx = WhirlpoolContext.fromWorkspace(provider, program); - const fetcher = ctx.fetcher; - - let initializedConfigInfo: InitConfigParams; - - it("successfully init a WhirlpoolsConfig account", async () => { - const { configInitInfo } = generateDefaultConfigParams(ctx); - await toTx(ctx, WhirlpoolIx.initializeConfigIx(ctx.program, configInitInfo)).buildAndExecute(); - - const configAccount = (await fetcher.getConfig( - configInitInfo.whirlpoolsConfigKeypair.publicKey - )) as WhirlpoolsConfigData; - - assert.ok( - configAccount.collectProtocolFeesAuthority.equals(configInitInfo.collectProtocolFeesAuthority) - ); - - assert.ok(configAccount.feeAuthority.equals(configInitInfo.feeAuthority)); - - assert.ok( - configAccount.rewardEmissionsSuperAuthority.equals( - configInitInfo.rewardEmissionsSuperAuthority - ) - ); - - assert.equal(configAccount.defaultProtocolFeeRate, configInitInfo.defaultProtocolFeeRate); - - initializedConfigInfo = configInitInfo; - }); - - it("fail on passing in already initialized whirlpool account", async () => { - let infoWithDupeConfigKey = { - ...generateDefaultConfigParams(ctx).configInitInfo, - whirlpoolsConfigKeypair: initializedConfigInfo.whirlpoolsConfigKeypair, - }; - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.initializeConfigIx(ctx.program, infoWithDupeConfigKey) - ).buildAndExecute(), - /0x0/ - ); - }); - - it("succeeds when funder is different than account paying for transaction fee", async () => { - const funderKeypair = anchor.web3.Keypair.generate(); - await systemTransferTx(provider, funderKeypair.publicKey, ONE_SOL).buildAndExecute(); - const { configInitInfo } = generateDefaultConfigParams(ctx, funderKeypair.publicKey); - await toTx(ctx, WhirlpoolIx.initializeConfigIx(ctx.program, configInitInfo)) - .addSigner(funderKeypair) - .buildAndExecute(); - }); -}); diff --git a/sdk/tests/integration/initialize_fee_tier.test.ts b/sdk/tests/integration/initialize_fee_tier.test.ts deleted file mode 100644 index 397210e..0000000 --- a/sdk/tests/integration/initialize_fee_tier.test.ts +++ /dev/null @@ -1,161 +0,0 @@ -import * as anchor from "@coral-xyz/anchor"; -import * as assert from "assert"; -import { FeeTierData, PDAUtil, toTx, WhirlpoolContext, WhirlpoolIx } from "../../src"; -import { ONE_SOL, systemTransferTx, TickSpacing } from "../utils"; -import { defaultConfirmOptions } from "../utils/const"; -import { initFeeTier } from "../utils/init-utils"; -import { - generateDefaultConfigParams, - generateDefaultInitFeeTierParams -} from "../utils/test-builders"; - -describe("initialize_fee_tier", () => { - const provider = anchor.AnchorProvider.local(undefined, defaultConfirmOptions); - - const program = anchor.workspace.Whirlpool; - const ctx = WhirlpoolContext.fromWorkspace(provider, program); - const fetcher = ctx.fetcher; - - it("successfully init a FeeRate stable account", async () => { - const { configInitInfo, configKeypairs } = generateDefaultConfigParams(ctx); - await toTx(ctx, WhirlpoolIx.initializeConfigIx(ctx.program, configInitInfo)).buildAndExecute(); - - const testTickSpacing = TickSpacing.Stable; - const { params } = await initFeeTier( - ctx, - configInitInfo, - configKeypairs.feeAuthorityKeypair, - testTickSpacing, - 800 - ); - - const generatedPda = PDAUtil.getFeeTier( - ctx.program.programId, - configInitInfo.whirlpoolsConfigKeypair.publicKey, - testTickSpacing - ); - - const feeTierAccount = (await fetcher.getFeeTier(generatedPda.publicKey)) as FeeTierData; - - assert.ok(feeTierAccount.tickSpacing == params.tickSpacing); - assert.ok(feeTierAccount.defaultFeeRate == params.defaultFeeRate); - }); - - it("successfully init a FeeRate standard account", async () => { - const { configInitInfo, configKeypairs } = generateDefaultConfigParams(ctx); - await toTx(ctx, WhirlpoolIx.initializeConfigIx(ctx.program, configInitInfo)).buildAndExecute(); - - const testTickSpacing = TickSpacing.Standard; - const { params } = await initFeeTier( - ctx, - configInitInfo, - configKeypairs.feeAuthorityKeypair, - testTickSpacing, - 3000 - ); - - const feeTierAccount = (await fetcher.getFeeTier(params.feeTierPda.publicKey)) as FeeTierData; - - assert.ok(feeTierAccount.tickSpacing == params.tickSpacing); - assert.ok(feeTierAccount.defaultFeeRate == params.defaultFeeRate); - }); - - it("successfully init a FeeRate max account", async () => { - const { configInitInfo, configKeypairs } = generateDefaultConfigParams(ctx); - await toTx(ctx, WhirlpoolIx.initializeConfigIx(ctx.program, configInitInfo)).buildAndExecute(); - - const testTickSpacing = TickSpacing.Standard; - const { params } = await initFeeTier( - ctx, - configInitInfo, - configKeypairs.feeAuthorityKeypair, - testTickSpacing, - 30_000 // 3 % - ); - - const feeTierAccount = (await fetcher.getFeeTier(params.feeTierPda.publicKey)) as FeeTierData; - - assert.ok(feeTierAccount.tickSpacing == params.tickSpacing); - assert.ok(feeTierAccount.defaultFeeRate == params.defaultFeeRate); - assert.ok(params.defaultFeeRate === 30_000); - }); - - it("successfully init a FeeRate with another funder wallet", async () => { - const { configInitInfo, configKeypairs } = generateDefaultConfigParams(ctx); - await toTx(ctx, WhirlpoolIx.initializeConfigIx(ctx.program, configInitInfo)).buildAndExecute(); - const funderKeypair = anchor.web3.Keypair.generate(); - await systemTransferTx(provider, funderKeypair.publicKey, ONE_SOL).buildAndExecute(); - - await initFeeTier( - ctx, - configInitInfo, - configKeypairs.feeAuthorityKeypair, - TickSpacing.Stable, - 3000, - funderKeypair - ); - }); - - it("fails when default fee rate exceeds max", async () => { - const { configInitInfo, configKeypairs } = generateDefaultConfigParams(ctx); - await toTx(ctx, WhirlpoolIx.initializeConfigIx(ctx.program, configInitInfo)).buildAndExecute(); - - await assert.rejects( - initFeeTier( - ctx, - configInitInfo, - configKeypairs.feeAuthorityKeypair, - TickSpacing.Stable, - 30_000 + 1 - ), - /0x178c/ // FeeRateMaxExceeded - ); - }); - - it("fails when fee authority is not a signer", async () => { - const { configInitInfo } = generateDefaultConfigParams(ctx); - await toTx(ctx, WhirlpoolIx.initializeConfigIx(ctx.program, configInitInfo)).buildAndExecute(); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.initializeFeeTierIx( - ctx.program, - generateDefaultInitFeeTierParams( - ctx, - configInitInfo.whirlpoolsConfigKeypair.publicKey, - configInitInfo.feeAuthority, - TickSpacing.Stable, - 3000 - ) - ) - ).buildAndExecute(), - /.*signature verification fail.*/i - ); - }); - - it("fails when invalid fee authority provided", async () => { - const { configInitInfo } = generateDefaultConfigParams(ctx); - await toTx(ctx, WhirlpoolIx.initializeConfigIx(ctx.program, configInitInfo)).buildAndExecute(); - const fakeFeeAuthorityKeypair = anchor.web3.Keypair.generate(); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.initializeFeeTierIx( - ctx.program, - generateDefaultInitFeeTierParams( - ctx, - configInitInfo.whirlpoolsConfigKeypair.publicKey, - fakeFeeAuthorityKeypair.publicKey, - TickSpacing.Stable, - 3000 - ) - ) - ) - .addSigner(fakeFeeAuthorityKeypair) - .buildAndExecute(), - /0x7dc/ // ConstraintAddress - ); - }); -}); diff --git a/sdk/tests/integration/initialize_pool.test.ts b/sdk/tests/integration/initialize_pool.test.ts deleted file mode 100644 index f85d36a..0000000 --- a/sdk/tests/integration/initialize_pool.test.ts +++ /dev/null @@ -1,287 +0,0 @@ -import * as anchor from "@coral-xyz/anchor"; -import { MathUtil, PDA } from "@orca-so/common-sdk"; -import * as assert from "assert"; -import Decimal from "decimal.js"; -import { - InitPoolParams, - MAX_SQRT_PRICE, - MIN_SQRT_PRICE, - PDAUtil, - PriceMath, - WhirlpoolContext, - WhirlpoolData, - WhirlpoolIx, - toTx -} from "../../src"; -import { - ONE_SOL, - TickSpacing, - ZERO_BN, - asyncAssertTokenVault, - createMint, - systemTransferTx -} from "../utils"; -import { defaultConfirmOptions } from "../utils/const"; -import { buildTestPoolParams, initTestPool } from "../utils/init-utils"; - -describe("initialize_pool", () => { - const provider = anchor.AnchorProvider.local(undefined, defaultConfirmOptions); - - const program = anchor.workspace.Whirlpool; - const ctx = WhirlpoolContext.fromWorkspace(provider, program); - const fetcher = ctx.fetcher; - - it("successfully init a Standard account", async () => { - const price = MathUtil.toX64(new Decimal(5)); - const { configInitInfo, poolInitInfo, feeTierParams } = await initTestPool( - ctx, - TickSpacing.Standard, - price - ); - const whirlpool = (await fetcher.getPool(poolInitInfo.whirlpoolPda.publicKey)) as WhirlpoolData; - - const expectedWhirlpoolPda = PDAUtil.getWhirlpool( - program.programId, - configInitInfo.whirlpoolsConfigKeypair.publicKey, - poolInitInfo.tokenMintA, - poolInitInfo.tokenMintB, - TickSpacing.Standard - ); - - assert.ok(poolInitInfo.whirlpoolPda.publicKey.equals(expectedWhirlpoolPda.publicKey)); - assert.equal(expectedWhirlpoolPda.bump, whirlpool.whirlpoolBump[0]); - - assert.ok(whirlpool.whirlpoolsConfig.equals(poolInitInfo.whirlpoolsConfig)); - assert.ok(whirlpool.tokenMintA.equals(poolInitInfo.tokenMintA)); - assert.ok(whirlpool.tokenVaultA.equals(poolInitInfo.tokenVaultAKeypair.publicKey)); - - assert.ok(whirlpool.tokenMintB.equals(poolInitInfo.tokenMintB)); - assert.ok(whirlpool.tokenVaultB.equals(poolInitInfo.tokenVaultBKeypair.publicKey)); - - assert.equal(whirlpool.feeRate, feeTierParams.defaultFeeRate); - assert.equal(whirlpool.protocolFeeRate, configInitInfo.defaultProtocolFeeRate); - - assert.ok(whirlpool.sqrtPrice.eq(new anchor.BN(poolInitInfo.initSqrtPrice.toString()))); - assert.ok(whirlpool.liquidity.eq(ZERO_BN)); - - assert.equal( - whirlpool.tickCurrentIndex, - PriceMath.sqrtPriceX64ToTickIndex(poolInitInfo.initSqrtPrice) - ); - - assert.ok(whirlpool.protocolFeeOwedA.eq(ZERO_BN)); - assert.ok(whirlpool.protocolFeeOwedB.eq(ZERO_BN)); - assert.ok(whirlpool.feeGrowthGlobalA.eq(ZERO_BN)); - assert.ok(whirlpool.feeGrowthGlobalB.eq(ZERO_BN)); - - assert.ok(whirlpool.tickSpacing === TickSpacing.Standard); - - await asyncAssertTokenVault(program, poolInitInfo.tokenVaultAKeypair.publicKey, { - expectedOwner: poolInitInfo.whirlpoolPda.publicKey, - expectedMint: poolInitInfo.tokenMintA, - }); - await asyncAssertTokenVault(program, poolInitInfo.tokenVaultBKeypair.publicKey, { - expectedOwner: poolInitInfo.whirlpoolPda.publicKey, - expectedMint: poolInitInfo.tokenMintB, - }); - - whirlpool.rewardInfos.forEach((rewardInfo) => { - assert.equal(rewardInfo.emissionsPerSecondX64, 0); - assert.equal(rewardInfo.growthGlobalX64, 0); - assert.ok(rewardInfo.authority.equals(configInitInfo.rewardEmissionsSuperAuthority)); - assert.ok(rewardInfo.mint.equals(anchor.web3.PublicKey.default)); - assert.ok(rewardInfo.vault.equals(anchor.web3.PublicKey.default)); - }); - }); - - it("successfully init a Stable account", async () => { - const price = MathUtil.toX64(new Decimal(5)); - const { configInitInfo, poolInitInfo, feeTierParams } = await initTestPool( - ctx, - TickSpacing.Stable, - price - ); - const whirlpool = (await fetcher.getPool(poolInitInfo.whirlpoolPda.publicKey)) as WhirlpoolData; - - assert.ok(whirlpool.whirlpoolsConfig.equals(poolInitInfo.whirlpoolsConfig)); - assert.ok(whirlpool.tokenMintA.equals(poolInitInfo.tokenMintA)); - assert.ok(whirlpool.tokenVaultA.equals(poolInitInfo.tokenVaultAKeypair.publicKey)); - - assert.ok(whirlpool.tokenMintB.equals(poolInitInfo.tokenMintB)); - assert.ok(whirlpool.tokenVaultB.equals(poolInitInfo.tokenVaultBKeypair.publicKey)); - - assert.equal(whirlpool.feeRate, feeTierParams.defaultFeeRate); - assert.equal(whirlpool.protocolFeeRate, configInitInfo.defaultProtocolFeeRate); - - assert.ok(whirlpool.sqrtPrice.eq(new anchor.BN(poolInitInfo.initSqrtPrice.toString()))); - assert.ok(whirlpool.liquidity.eq(ZERO_BN)); - - assert.equal( - whirlpool.tickCurrentIndex, - PriceMath.sqrtPriceX64ToTickIndex(poolInitInfo.initSqrtPrice) - ); - - assert.ok(whirlpool.protocolFeeOwedA.eq(ZERO_BN)); - assert.ok(whirlpool.protocolFeeOwedB.eq(ZERO_BN)); - assert.ok(whirlpool.feeGrowthGlobalA.eq(ZERO_BN)); - assert.ok(whirlpool.feeGrowthGlobalB.eq(ZERO_BN)); - - assert.ok(whirlpool.tickSpacing === TickSpacing.Stable); - - await asyncAssertTokenVault(program, poolInitInfo.tokenVaultAKeypair.publicKey, { - expectedOwner: poolInitInfo.whirlpoolPda.publicKey, - expectedMint: poolInitInfo.tokenMintA, - }); - await asyncAssertTokenVault(program, poolInitInfo.tokenVaultBKeypair.publicKey, { - expectedOwner: poolInitInfo.whirlpoolPda.publicKey, - expectedMint: poolInitInfo.tokenMintB, - }); - - whirlpool.rewardInfos.forEach((rewardInfo) => { - assert.equal(rewardInfo.emissionsPerSecondX64, 0); - assert.equal(rewardInfo.growthGlobalX64, 0); - assert.ok(rewardInfo.authority.equals(configInitInfo.rewardEmissionsSuperAuthority)); - assert.ok(rewardInfo.mint.equals(anchor.web3.PublicKey.default)); - assert.ok(rewardInfo.vault.equals(anchor.web3.PublicKey.default)); - }); - }); - - it("succeeds when funder is different than account paying for transaction fee", async () => { - const funderKeypair = anchor.web3.Keypair.generate(); - await systemTransferTx(provider, funderKeypair.publicKey, ONE_SOL).buildAndExecute(); - await initTestPool(ctx, TickSpacing.Standard, MathUtil.toX64(new Decimal(5)), funderKeypair); - }); - - it("fails when tokenVaultA mint does not match tokenA mint", async () => { - const { poolInitInfo } = await buildTestPoolParams(ctx, TickSpacing.Standard); - const otherTokenPublicKey = await createMint(provider); - - const modifiedPoolInitInfo: InitPoolParams = { - ...poolInitInfo, - tokenMintA: otherTokenPublicKey, - }; - - await assert.rejects( - toTx(ctx, WhirlpoolIx.initializePoolIx(ctx.program, modifiedPoolInitInfo)).buildAndExecute(), - /custom program error: 0x7d6/ // ConstraintSeeds - ); - }); - - it("fails when tokenVaultB mint does not match tokenB mint", async () => { - const { poolInitInfo } = await buildTestPoolParams(ctx, TickSpacing.Standard); - const otherTokenPublicKey = await createMint(provider); - - const modifiedPoolInitInfo: InitPoolParams = { - ...poolInitInfo, - tokenMintB: otherTokenPublicKey, - }; - - await assert.rejects( - toTx(ctx, WhirlpoolIx.initializePoolIx(ctx.program, modifiedPoolInitInfo)).buildAndExecute(), - /custom program error: 0x7d6/ // ConstraintSeeds - ); - }); - - it("fails when token mints are in the wrong order", async () => { - const { poolInitInfo, configInitInfo } = await buildTestPoolParams(ctx, TickSpacing.Standard); - - const whirlpoolPda = PDAUtil.getWhirlpool( - ctx.program.programId, - configInitInfo.whirlpoolsConfigKeypair.publicKey, - poolInitInfo.tokenMintB, - poolInitInfo.tokenMintA, - TickSpacing.Stable - ); - - const modifiedPoolInitInfo: InitPoolParams = { - ...poolInitInfo, - whirlpoolPda, - tickSpacing: TickSpacing.Stable, - tokenMintA: poolInitInfo.tokenMintB, - tokenMintB: poolInitInfo.tokenMintA, - }; - - await assert.rejects( - toTx(ctx, WhirlpoolIx.initializePoolIx(ctx.program, modifiedPoolInitInfo)).buildAndExecute(), - /custom program error: 0x1788/ // InvalidTokenMintOrder - ); - }); - - it("fails when the same token mint is passed in", async () => { - const { poolInitInfo, configInitInfo } = await buildTestPoolParams(ctx, TickSpacing.Standard); - - const whirlpoolPda = PDAUtil.getWhirlpool( - ctx.program.programId, - configInitInfo.whirlpoolsConfigKeypair.publicKey, - poolInitInfo.tokenMintA, - poolInitInfo.tokenMintA, - TickSpacing.Stable - ); - - const modifiedPoolInitInfo: InitPoolParams = { - ...poolInitInfo, - whirlpoolPda, - tickSpacing: TickSpacing.Stable, - tokenMintB: poolInitInfo.tokenMintA, - }; - - await assert.rejects( - toTx(ctx, WhirlpoolIx.initializePoolIx(ctx.program, modifiedPoolInitInfo)).buildAndExecute(), - /custom program error: 0x1788/ // InvalidTokenMintOrder - ); - }); - - it("fails when sqrt-price exceeds max", async () => { - const { poolInitInfo } = await buildTestPoolParams(ctx, TickSpacing.Standard); - const otherTokenPublicKey = await createMint(provider); - - const modifiedPoolInitInfo: InitPoolParams = { - ...poolInitInfo, - initSqrtPrice: new anchor.BN(MAX_SQRT_PRICE).add(new anchor.BN(1)), - }; - - await assert.rejects( - toTx(ctx, WhirlpoolIx.initializePoolIx(ctx.program, modifiedPoolInitInfo)).buildAndExecute(), - /custom program error: 0x177b/ // SqrtPriceOutOfBounds - ); - }); - - it("fails when sqrt-price subceeds min", async () => { - const { poolInitInfo } = await buildTestPoolParams(ctx, TickSpacing.Standard); - - const modifiedPoolInitInfo: InitPoolParams = { - ...poolInitInfo, - initSqrtPrice: new anchor.BN(MIN_SQRT_PRICE).sub(new anchor.BN(1)), - }; - - await assert.rejects( - toTx(ctx, WhirlpoolIx.initializePoolIx(ctx.program, modifiedPoolInitInfo)).buildAndExecute(), - /custom program error: 0x177b/ // SqrtPriceOutOfBounds - ); - }); - - it("ignore passed bump", async () => { - const { poolInitInfo } = await buildTestPoolParams(ctx, TickSpacing.Standard); - - const whirlpoolPda = poolInitInfo.whirlpoolPda; - const validBump = whirlpoolPda.bump; - const invalidBump = (validBump + 1) % 256; // +1 shift mod 256 - const modifiedWhirlpoolPda: PDA = { - publicKey: whirlpoolPda.publicKey, - bump: invalidBump, - }; - - const modifiedPoolInitInfo: InitPoolParams = { - ...poolInitInfo, - whirlpoolPda: modifiedWhirlpoolPda, - }; - - await toTx(ctx, WhirlpoolIx.initializePoolIx(ctx.program, modifiedPoolInitInfo)).buildAndExecute(); - - // check if passed invalid bump was ignored - const whirlpool = (await fetcher.getPool(poolInitInfo.whirlpoolPda.publicKey)) as WhirlpoolData; - assert.equal(whirlpool.whirlpoolBump, validBump); - assert.notEqual(whirlpool.whirlpoolBump, invalidBump); - }); - -}); diff --git a/sdk/tests/integration/initialize_position_bundle.test.ts b/sdk/tests/integration/initialize_position_bundle.test.ts deleted file mode 100644 index ed90fe9..0000000 --- a/sdk/tests/integration/initialize_position_bundle.test.ts +++ /dev/null @@ -1,264 +0,0 @@ -import * as anchor from "@coral-xyz/anchor"; -import { Account, ASSOCIATED_TOKEN_PROGRAM_ID, getAssociatedTokenAddressSync, Mint, TOKEN_PROGRAM_ID } from "@solana/spl-token"; -import { Keypair, LAMPORTS_PER_SOL, PublicKey, SystemProgram } from "@solana/web3.js"; -import * as assert from "assert"; -import { - PDAUtil, - POSITION_BUNDLE_SIZE, - PositionBundleData, - toTx, - WhirlpoolContext -} from "../../src"; -import { IGNORE_CACHE } from "../../src/network/public/fetcher"; -import { - createMintInstructions, - mintToDestination -} from "../utils"; -import { defaultConfirmOptions } from "../utils/const"; -import { initializePositionBundle } from "../utils/init-utils"; - -describe("initialize_position_bundle", () => { - const provider = anchor.AnchorProvider.local(undefined, defaultConfirmOptions); - - - const program = anchor.workspace.Whirlpool; - const ctx = WhirlpoolContext.fromWorkspace(provider, program); - const fetcher = ctx.fetcher; - - async function createInitializePositionBundleTx(ctx: WhirlpoolContext, overwrite: any, mintKeypair?: Keypair) { - const positionBundleMintKeypair = mintKeypair ?? Keypair.generate(); - const positionBundlePda = PDAUtil.getPositionBundle(ctx.program.programId, positionBundleMintKeypair.publicKey); - const positionBundleTokenAccount = getAssociatedTokenAddressSync(positionBundleMintKeypair.publicKey, ctx.wallet.publicKey); - - const defaultAccounts = { - positionBundle: positionBundlePda.publicKey, - positionBundleMint: positionBundleMintKeypair.publicKey, - positionBundleTokenAccount, - positionBundleOwner: ctx.wallet.publicKey, - funder: ctx.wallet.publicKey, - associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID, - tokenProgram: TOKEN_PROGRAM_ID, - systemProgram: SystemProgram.programId, - rent: anchor.web3.SYSVAR_RENT_PUBKEY, - }; - - const ix = program.instruction.initializePositionBundle({ - accounts: { - ...defaultAccounts, - ...overwrite, - } - }); - - return toTx(ctx, { - instructions: [ix], - cleanupInstructions: [], - signers: [positionBundleMintKeypair], - }); - } - - async function checkPositionBundleMint(positionBundleMintPubkey: PublicKey) { - // verify position bundle Mint account - const positionBundleMint = (await ctx.fetcher.getMintInfo(positionBundleMintPubkey, IGNORE_CACHE)) as Mint; - // should have NFT characteristics - assert.strictEqual(positionBundleMint.decimals, 0); - assert.ok(positionBundleMint.supply === 1n); - // mint auth & freeze auth should be set to None - assert.ok(positionBundleMint.mintAuthority === null); - assert.ok(positionBundleMint.freezeAuthority === null); - } - - async function checkPositionBundleTokenAccount(positionBundleTokenAccountPubkey: PublicKey, owner: PublicKey, positionBundleMintPubkey: PublicKey) { - // verify position bundle Token account - const positionBundleTokenAccount = (await ctx.fetcher.getTokenInfo(positionBundleTokenAccountPubkey, IGNORE_CACHE)) as Account; - assert.ok(positionBundleTokenAccount.amount === 1n); - assert.ok(positionBundleTokenAccount.mint.equals(positionBundleMintPubkey)); - assert.ok(positionBundleTokenAccount.owner.equals(owner)); - } - - async function checkPositionBundle(positionBundlePubkey: PublicKey, positionBundleMintPubkey: PublicKey) { - // verify PositionBundle account - const positionBundle = (await ctx.fetcher.getPositionBundle(positionBundlePubkey, IGNORE_CACHE)) as PositionBundleData; - assert.ok(positionBundle.positionBundleMint.equals(positionBundleMintPubkey)); - assert.strictEqual(positionBundle.positionBitmap.length * 8, POSITION_BUNDLE_SIZE); - for (const bitmap of positionBundle.positionBitmap) { - assert.strictEqual(bitmap, 0); - } - } - - async function createOtherWallet(): Promise { - const keypair = Keypair.generate(); - const signature = await provider.connection.requestAirdrop(keypair.publicKey, 100 * LAMPORTS_PER_SOL); - await provider.connection.confirmTransaction(signature, "confirmed"); - return keypair; - } - - it("successfully initialize position bundle and verify initialized account contents", async () => { - const positionBundleInfo = await initializePositionBundle( - ctx, - ctx.wallet.publicKey, - // funder = ctx.wallet.publicKey - ); - - const { - positionBundleMintKeypair, - positionBundlePda, - positionBundleTokenAccount, - } = positionBundleInfo; - - await checkPositionBundleMint(positionBundleMintKeypair.publicKey); - await checkPositionBundleTokenAccount(positionBundleTokenAccount, ctx.wallet.publicKey, positionBundleMintKeypair.publicKey); - await checkPositionBundle(positionBundlePda.publicKey, positionBundleMintKeypair.publicKey); - }); - - it("successfully initialize when funder is different than account paying for transaction fee", async () => { - const preBalance = await ctx.connection.getBalance(ctx.wallet.publicKey); - - const otherWallet = await createOtherWallet(); - const positionBundleInfo = await initializePositionBundle( - ctx, - ctx.wallet.publicKey, - otherWallet, - ); - - const postBalance = await ctx.connection.getBalance(ctx.wallet.publicKey); - const diffBalance = preBalance - postBalance; - const minRent = await ctx.connection.getMinimumBalanceForRentExemption(0); - assert.ok(diffBalance < minRent); // ctx.wallet didn't pay any rent - - const { - positionBundleMintKeypair, - positionBundlePda, - positionBundleTokenAccount, - } = positionBundleInfo; - - await checkPositionBundleMint(positionBundleMintKeypair.publicKey); - await checkPositionBundleTokenAccount(positionBundleTokenAccount, ctx.wallet.publicKey, positionBundleMintKeypair.publicKey); - await checkPositionBundle(positionBundlePda.publicKey, positionBundleMintKeypair.publicKey); - }); - - it("PositionBundle account has reserved space", async () => { - const positionBundleAccountSizeIncludingReserve = 8 + 32 + 32 + 64; - - const positionBundleInfo = await initializePositionBundle( - ctx, - ctx.wallet.publicKey, - ); - - const account = await ctx.connection.getAccountInfo(positionBundleInfo.positionBundlePda.publicKey, "confirmed"); - assert.equal(account!.data.length, positionBundleAccountSizeIncludingReserve); - }); - - it("should be failed: cannot mint additional NFT by owner", async () => { - const positionBundleInfo = await initializePositionBundle( - ctx, - ctx.wallet.publicKey, - ); - - await assert.rejects( - mintToDestination( - provider, - positionBundleInfo.positionBundleMintKeypair.publicKey, - positionBundleInfo.positionBundleTokenAccount, - 1 - ), - /0x5/ // the total supply of this token is fixed - ); - }); - - it("should be failed: already used mint is passed as position bundle mint", async () => { - const positionBundleMintKeypair = Keypair.generate(); - - // create mint - const createMintIx = await createMintInstructions( - provider, - ctx.wallet.publicKey, - positionBundleMintKeypair.publicKey - ); - const createMintTx = toTx(ctx, { - instructions: createMintIx, - cleanupInstructions: [], - signers: [positionBundleMintKeypair] - }); - await createMintTx.buildAndExecute(); - - const tx = await createInitializePositionBundleTx(ctx, {}, positionBundleMintKeypair); - await assert.rejects( - tx.buildAndExecute(), - (err) => { return JSON.stringify(err).includes("already in use") } - ); - }); - - describe("invalid input account", () => { - it("should be failed: invalid position bundle address", async () => { - const tx = await createInitializePositionBundleTx(ctx, { - // invalid parameter - positionBundle: PDAUtil.getPositionBundle(ctx.program.programId, Keypair.generate().publicKey).publicKey, - }); - - await assert.rejects( - tx.buildAndExecute(), - /0x7d6/ // ConstraintSeeds - ); - }); - - it("should be failed: invalid ATA address", async () => { - const tx = await createInitializePositionBundleTx(ctx, { - // invalid parameter - positionBundleTokenAccount: getAssociatedTokenAddressSync(Keypair.generate().publicKey, ctx.wallet.publicKey), - }); - - await assert.rejects( - tx.buildAndExecute(), - /An account required by the instruction is missing/ // Anchor cannot create derived ATA - ); - }); - - it("should be failed: invalid token program", async () => { - const tx = await createInitializePositionBundleTx(ctx, { - // invalid parameter - tokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID, - }); - - await assert.rejects( - tx.buildAndExecute(), - /0xbc0/ // InvalidProgramId - ); - }); - - it("should be failed: invalid system program", async () => { - const tx = await createInitializePositionBundleTx(ctx, { - // invalid parameter - systemProgram: TOKEN_PROGRAM_ID, - }); - - await assert.rejects( - tx.buildAndExecute(), - /0xbc0/ // InvalidProgramId - ); - }); - - it("should be failed: invalid rent sysvar", async () => { - const tx = await createInitializePositionBundleTx(ctx, { - // invalid parameter - rent: anchor.web3.SYSVAR_CLOCK_PUBKEY, - }); - - await assert.rejects( - tx.buildAndExecute(), - /0xbc7/ // AccountSysvarMismatch - ); - }); - - it("should be failed: invalid associated token program", async () => { - const tx = await createInitializePositionBundleTx(ctx, { - // invalid parameter - associatedTokenProgram: TOKEN_PROGRAM_ID, - }); - - await assert.rejects( - tx.buildAndExecute(), - /0xbc0/ // InvalidProgramId - ); - }); - }); -}); diff --git a/sdk/tests/integration/initialize_position_bundle_with_metadata.test.ts b/sdk/tests/integration/initialize_position_bundle_with_metadata.test.ts deleted file mode 100644 index 55bfbfd..0000000 --- a/sdk/tests/integration/initialize_position_bundle_with_metadata.test.ts +++ /dev/null @@ -1,388 +0,0 @@ -import * as anchor from "@coral-xyz/anchor"; -import { Metadata } from "@metaplex-foundation/mpl-token-metadata"; -import { PDA } from "@orca-so/common-sdk"; -import { - Account, - ASSOCIATED_TOKEN_PROGRAM_ID, - getAssociatedTokenAddressSync, - Mint, - TOKEN_PROGRAM_ID -} from "@solana/spl-token"; -import { Keypair, LAMPORTS_PER_SOL, PublicKey, SystemProgram } from "@solana/web3.js"; -import * as assert from "assert"; -import { - METADATA_PROGRAM_ADDRESS, - PDAUtil, - POSITION_BUNDLE_SIZE, - PositionBundleData, - toTx, - WHIRLPOOL_NFT_UPDATE_AUTH, - WhirlpoolContext, -} from "../../src"; -import { IGNORE_CACHE } from "../../src/network/public/fetcher"; -import { - createMintInstructions, - mintToDestination -} from "../utils"; -import { defaultConfirmOptions } from "../utils/const"; -import { initializePositionBundleWithMetadata } from "../utils/init-utils"; - -describe("initialize_position_bundle_with_metadata", () => { - const provider = anchor.AnchorProvider.local(undefined, defaultConfirmOptions); - - const program = anchor.workspace.Whirlpool; - const ctx = WhirlpoolContext.fromWorkspace(provider, program); - - async function createInitializePositionBundleWithMetadataTx( - ctx: WhirlpoolContext, - overwrite: any, - mintKeypair?: Keypair - ) { - const positionBundleMintKeypair = mintKeypair ?? Keypair.generate(); - const positionBundlePda = PDAUtil.getPositionBundle( - ctx.program.programId, - positionBundleMintKeypair.publicKey - ); - const positionBundleMetadataPda = PDAUtil.getPositionBundleMetadata( - positionBundleMintKeypair.publicKey - ); - const positionBundleTokenAccount = getAssociatedTokenAddressSync( - positionBundleMintKeypair.publicKey, - ctx.wallet.publicKey - ); - - const defaultAccounts = { - positionBundle: positionBundlePda.publicKey, - positionBundleMint: positionBundleMintKeypair.publicKey, - positionBundleMetadata: positionBundleMetadataPda.publicKey, - positionBundleTokenAccount, - positionBundleOwner: ctx.wallet.publicKey, - funder: ctx.wallet.publicKey, - associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID, - tokenProgram: TOKEN_PROGRAM_ID, - systemProgram: SystemProgram.programId, - rent: anchor.web3.SYSVAR_RENT_PUBKEY, - metadataProgram: METADATA_PROGRAM_ADDRESS, - metadataUpdateAuth: WHIRLPOOL_NFT_UPDATE_AUTH, - }; - - const ix = program.instruction.initializePositionBundleWithMetadata({ - accounts: { - ...defaultAccounts, - ...overwrite, - }, - }); - - return toTx(ctx, { - instructions: [ix], - cleanupInstructions: [], - signers: [positionBundleMintKeypair], - }); - } - - async function checkPositionBundleMint(positionBundleMintPubkey: PublicKey) { - // verify position bundle Mint account - const positionBundleMint = (await ctx.fetcher.getMintInfo( - positionBundleMintPubkey, - IGNORE_CACHE - )) as Mint; - // should have NFT characteristics - assert.strictEqual(positionBundleMint.decimals, 0); - assert.ok(positionBundleMint.supply === 1n); - // mint auth & freeze auth should be set to None - assert.ok(positionBundleMint.mintAuthority === null); - assert.ok(positionBundleMint.freezeAuthority === null); - } - - async function checkPositionBundleTokenAccount( - positionBundleTokenAccountPubkey: PublicKey, - owner: PublicKey, - positionBundleMintPubkey: PublicKey - ) { - // verify position bundle Token account - const positionBundleTokenAccount = (await ctx.fetcher.getTokenInfo( - positionBundleTokenAccountPubkey, - IGNORE_CACHE - )) as Account; - assert.ok(positionBundleTokenAccount.amount === 1n); - assert.ok(positionBundleTokenAccount.mint.equals(positionBundleMintPubkey)); - assert.ok(positionBundleTokenAccount.owner.equals(owner)); - } - - async function checkPositionBundle( - positionBundlePubkey: PublicKey, - positionBundleMintPubkey: PublicKey - ) { - // verify PositionBundle account - const positionBundle = (await ctx.fetcher.getPositionBundle( - positionBundlePubkey, - IGNORE_CACHE - )) as PositionBundleData; - assert.ok(positionBundle.positionBundleMint.equals(positionBundleMintPubkey)); - assert.strictEqual(positionBundle.positionBitmap.length * 8, POSITION_BUNDLE_SIZE); - for (const bitmap of positionBundle.positionBitmap) { - assert.strictEqual(bitmap, 0); - } - } - - async function checkPositionBundleMetadata(metadataPda: PDA, positionMint: PublicKey) { - const WPB_METADATA_NAME_PREFIX = "Orca Position Bundle"; - const WPB_METADATA_SYMBOL = "OPB"; - const WPB_METADATA_URI = "https://arweave.net/A_Wo8dx2_3lSUwMIi7bdT_sqxi8soghRNAWXXiqXpgE"; - - const mintAddress = positionMint.toBase58(); - const nftName = - WPB_METADATA_NAME_PREFIX + " " + mintAddress.slice(0, 4) + "..." + mintAddress.slice(-4); - - assert.ok(metadataPda != null); - const metadata = await Metadata.fromAccountAddress(provider.connection, metadataPda.publicKey); - assert.ok(metadata.mint.toBase58() === positionMint.toString()); - assert.ok(metadata.updateAuthority.toBase58() === WHIRLPOOL_NFT_UPDATE_AUTH.toBase58()); - assert.ok(metadata.isMutable); - assert.strictEqual(metadata.data.name.replace(/\0/g, ''), nftName); - assert.strictEqual(metadata.data.symbol.replace(/\0/g, ''), WPB_METADATA_SYMBOL); - assert.strictEqual(metadata.data.uri.replace(/\0/g, ''), WPB_METADATA_URI); - } - - async function createOtherWallet(): Promise { - const keypair = Keypair.generate(); - const signature = await provider.connection.requestAirdrop( - keypair.publicKey, - 100 * LAMPORTS_PER_SOL - ); - await provider.connection.confirmTransaction(signature, "confirmed"); - return keypair; - } - - it("successfully initialize position bundle and verify initialized account contents", async () => { - const positionBundleInfo = await initializePositionBundleWithMetadata( - ctx, - ctx.wallet.publicKey - // funder = ctx.wallet.publicKey - ); - - const { - positionBundleMintKeypair, - positionBundlePda, - positionBundleMetadataPda, - positionBundleTokenAccount, - } = positionBundleInfo; - - await checkPositionBundleMint(positionBundleMintKeypair.publicKey); - await checkPositionBundleTokenAccount( - positionBundleTokenAccount, - ctx.wallet.publicKey, - positionBundleMintKeypair.publicKey - ); - await checkPositionBundle(positionBundlePda.publicKey, positionBundleMintKeypair.publicKey); - await checkPositionBundleMetadata( - positionBundleMetadataPda, - positionBundleMintKeypair.publicKey - ); - }); - - it("successfully initialize when funder is different than account paying for transaction fee", async () => { - const preBalance = await ctx.connection.getBalance(ctx.wallet.publicKey); - - const otherWallet = await createOtherWallet(); - const positionBundleInfo = await initializePositionBundleWithMetadata( - ctx, - ctx.wallet.publicKey, - otherWallet - ); - - const postBalance = await ctx.connection.getBalance(ctx.wallet.publicKey); - const diffBalance = preBalance - postBalance; - const minRent = await ctx.connection.getMinimumBalanceForRentExemption(0); - assert.ok(diffBalance < minRent); // ctx.wallet didn't pay any rent - - const { - positionBundleMintKeypair, - positionBundlePda, - positionBundleMetadataPda, - positionBundleTokenAccount, - } = positionBundleInfo; - - await checkPositionBundleMint(positionBundleMintKeypair.publicKey); - await checkPositionBundleTokenAccount( - positionBundleTokenAccount, - ctx.wallet.publicKey, - positionBundleMintKeypair.publicKey - ); - await checkPositionBundle(positionBundlePda.publicKey, positionBundleMintKeypair.publicKey); - await checkPositionBundleMetadata( - positionBundleMetadataPda, - positionBundleMintKeypair.publicKey - ); - }); - - it("PositionBundle account has reserved space", async () => { - const positionBundleAccountSizeIncludingReserve = 8 + 32 + 32 + 64; - - const positionBundleInfo = await initializePositionBundleWithMetadata( - ctx, - ctx.wallet.publicKey - ); - - const account = await ctx.connection.getAccountInfo( - positionBundleInfo.positionBundlePda.publicKey, - "confirmed" - ); - assert.equal(account!.data.length, positionBundleAccountSizeIncludingReserve); - }); - - it("should be failed: cannot mint additional NFT by owner", async () => { - const positionBundleInfo = await initializePositionBundleWithMetadata( - ctx, - ctx.wallet.publicKey - ); - - await assert.rejects( - mintToDestination(provider, positionBundleInfo.positionBundleMintKeypair.publicKey, positionBundleInfo.positionBundleTokenAccount, 1), - /0x5/ // the total supply of this token is fixed - ); - }); - - it("should be failed: already used mint is passed as position bundle mint", async () => { - const positionBundleMintKeypair = Keypair.generate(); - - // create mint - const createMintIx = await createMintInstructions( - provider, - ctx.wallet.publicKey, - positionBundleMintKeypair.publicKey - ); - const createMintTx = toTx(ctx, { - instructions: createMintIx, - cleanupInstructions: [], - signers: [positionBundleMintKeypair], - }); - await createMintTx.buildAndExecute(); - - const tx = await createInitializePositionBundleWithMetadataTx( - ctx, - {}, - positionBundleMintKeypair - ); - await assert.rejects(tx.buildAndExecute(), (err) => { - return JSON.stringify(err).includes("already in use"); - }); - }); - - describe("invalid input account", () => { - it("should be failed: invalid position bundle address", async () => { - const tx = await createInitializePositionBundleWithMetadataTx(ctx, { - // invalid parameter - positionBundle: PDAUtil.getPositionBundle( - ctx.program.programId, - Keypair.generate().publicKey - ).publicKey, - }); - - await assert.rejects( - tx.buildAndExecute(), - /0x7d6/ // ConstraintSeeds - ); - }); - - it("should be failed: invalid metadata address", async () => { - const tx = await createInitializePositionBundleWithMetadataTx(ctx, { - // invalid parameter - positionBundleMetadata: PDAUtil.getPositionBundleMetadata(Keypair.generate().publicKey) - .publicKey, - }); - - await assert.rejects( - tx.buildAndExecute(), - /0x5/ // InvalidMetadataKey: cannot create Metadata - ); - }); - - it("should be failed: invalid ATA address", async () => { - const tx = await createInitializePositionBundleWithMetadataTx(ctx, { - // invalid parameter - positionBundleTokenAccount: getAssociatedTokenAddressSync( - Keypair.generate().publicKey, - ctx.wallet.publicKey - ), - }); - - await assert.rejects( - tx.buildAndExecute(), - /An account required by the instruction is missing/ // Anchor cannot create derived ATA - ); - }); - - it("should be failed: invalid update auth", async () => { - const tx = await createInitializePositionBundleWithMetadataTx(ctx, { - // invalid parameter - metadataUpdateAuth: Keypair.generate().publicKey, - }); - - await assert.rejects( - tx.buildAndExecute(), - /0x7dc/ // ConstraintAddress - ); - }); - - it("should be failed: invalid token program", async () => { - const tx = await createInitializePositionBundleWithMetadataTx(ctx, { - // invalid parameter - tokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID, - }); - - await assert.rejects( - tx.buildAndExecute(), - /0xbc0/ // InvalidProgramId - ); - }); - - it("should be failed: invalid system program", async () => { - const tx = await createInitializePositionBundleWithMetadataTx(ctx, { - // invalid parameter - systemProgram: TOKEN_PROGRAM_ID, - }); - - await assert.rejects( - tx.buildAndExecute(), - /0xbc0/ // InvalidProgramId - ); - }); - - it("should be failed: invalid rent sysvar", async () => { - const tx = await createInitializePositionBundleWithMetadataTx(ctx, { - // invalid parameter - rent: anchor.web3.SYSVAR_CLOCK_PUBKEY, - }); - - await assert.rejects( - tx.buildAndExecute(), - /0xbc7/ // AccountSysvarMismatch - ); - }); - - it("should be failed: invalid associated token program", async () => { - const tx = await createInitializePositionBundleWithMetadataTx(ctx, { - // invalid parameter - associatedTokenProgram: TOKEN_PROGRAM_ID, - }); - - await assert.rejects( - tx.buildAndExecute(), - /0xbc0/ // InvalidProgramId - ); - }); - - it("should be failed: invalid metadata program", async () => { - const tx = await createInitializePositionBundleWithMetadataTx(ctx, { - // invalid parameter - metadataProgram: TOKEN_PROGRAM_ID, - }); - - await assert.rejects( - tx.buildAndExecute(), - /0x7dc/ // ConstraintAddress - ); - }); - }); -}); diff --git a/sdk/tests/integration/initialize_reward.test.ts b/sdk/tests/integration/initialize_reward.test.ts deleted file mode 100644 index 85082c2..0000000 --- a/sdk/tests/integration/initialize_reward.test.ts +++ /dev/null @@ -1,121 +0,0 @@ -import * as anchor from "@coral-xyz/anchor"; -import * as assert from "assert"; -import { toTx, WhirlpoolContext, WhirlpoolData, WhirlpoolIx } from "../../src"; -import { IGNORE_CACHE } from "../../src/network/public/fetcher"; -import { createMint, ONE_SOL, systemTransferTx, TickSpacing } from "../utils"; -import { defaultConfirmOptions } from "../utils/const"; -import { initializeReward, initTestPool } from "../utils/init-utils"; - -describe("initialize_reward", () => { - const provider = anchor.AnchorProvider.local(undefined, defaultConfirmOptions); - - const program = anchor.workspace.Whirlpool; - const ctx = WhirlpoolContext.fromWorkspace(provider, program); - const fetcher = ctx.fetcher; - - it("successfully initializes reward at index 0", async () => { - const { poolInitInfo, configKeypairs } = await initTestPool(ctx, TickSpacing.Standard); - - const { params } = await initializeReward( - ctx, - configKeypairs.rewardEmissionsSuperAuthorityKeypair, - poolInitInfo.whirlpoolPda.publicKey, - 0 - ); - - const whirlpool = (await fetcher.getPool( - poolInitInfo.whirlpoolPda.publicKey, - IGNORE_CACHE - )) as WhirlpoolData; - - assert.ok(whirlpool.rewardInfos[0].mint.equals(params.rewardMint)); - assert.ok(whirlpool.rewardInfos[0].vault.equals(params.rewardVaultKeypair.publicKey)); - - await assert.rejects( - initializeReward( - ctx, - configKeypairs.rewardEmissionsSuperAuthorityKeypair, - poolInitInfo.whirlpoolPda.publicKey, - 0 - ), - /custom program error: 0x178a/ // InvalidRewardIndex - ); - - const { params: params2 } = await initializeReward( - ctx, - configKeypairs.rewardEmissionsSuperAuthorityKeypair, - poolInitInfo.whirlpoolPda.publicKey, - 1 - ); - - const whirlpool2 = (await fetcher.getPool( - poolInitInfo.whirlpoolPda.publicKey, - IGNORE_CACHE - )) as WhirlpoolData; - - assert.ok(whirlpool2.rewardInfos[0].mint.equals(params.rewardMint)); - assert.ok(whirlpool2.rewardInfos[0].vault.equals(params.rewardVaultKeypair.publicKey)); - assert.ok(whirlpool2.rewardInfos[1].mint.equals(params2.rewardMint)); - assert.ok(whirlpool2.rewardInfos[1].vault.equals(params2.rewardVaultKeypair.publicKey)); - assert.ok(whirlpool2.rewardInfos[2].mint.equals(anchor.web3.PublicKey.default)); - assert.ok(whirlpool2.rewardInfos[2].vault.equals(anchor.web3.PublicKey.default)); - }); - - it("succeeds when funder is different than account paying for transaction fee", async () => { - const { poolInitInfo, configKeypairs } = await initTestPool(ctx, TickSpacing.Standard); - const funderKeypair = anchor.web3.Keypair.generate(); - await systemTransferTx(provider, funderKeypair.publicKey, ONE_SOL).buildAndExecute(); - await initializeReward( - ctx, - configKeypairs.rewardEmissionsSuperAuthorityKeypair, - poolInitInfo.whirlpoolPda.publicKey, - 0, - funderKeypair - ); - }); - - it("fails to initialize reward at index 1", async () => { - const { poolInitInfo, configKeypairs } = await initTestPool(ctx, TickSpacing.Standard); - - await assert.rejects( - initializeReward( - ctx, - configKeypairs.rewardEmissionsSuperAuthorityKeypair, - poolInitInfo.whirlpoolPda.publicKey, - 1 - ), - /custom program error: 0x178a/ // InvalidRewardIndex - ); - }); - - it("fails to initialize reward at out-of-bound index", async () => { - const { poolInitInfo, configKeypairs } = await initTestPool(ctx, TickSpacing.Standard); - - await assert.rejects( - initializeReward( - ctx, - configKeypairs.rewardEmissionsSuperAuthorityKeypair, - poolInitInfo.whirlpoolPda.publicKey, - 3 - ) - ); - }); - - it("fails to initialize if authority signature is missing", async () => { - const { poolInitInfo, configKeypairs } = await initTestPool(ctx, TickSpacing.Standard); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.initializeRewardIx(ctx.program, { - rewardAuthority: configKeypairs.rewardEmissionsSuperAuthorityKeypair.publicKey, - funder: provider.wallet.publicKey, - whirlpool: poolInitInfo.whirlpoolPda.publicKey, - rewardMint: await createMint(provider), - rewardVaultKeypair: anchor.web3.Keypair.generate(), - rewardIndex: 0, - }) - ).buildAndExecute() - ); - }); -}); diff --git a/sdk/tests/integration/initialize_tick_array.test.ts b/sdk/tests/integration/initialize_tick_array.test.ts deleted file mode 100644 index 59118c3..0000000 --- a/sdk/tests/integration/initialize_tick_array.test.ts +++ /dev/null @@ -1,101 +0,0 @@ -import * as anchor from "@coral-xyz/anchor"; -import * as assert from "assert"; -import { - InitPoolParams, - InitTickArrayParams, - TICK_ARRAY_SIZE, - TickArrayData, - WhirlpoolContext, - WhirlpoolIx, - toTx -} from "../../src"; -import { ONE_SOL, TickSpacing, systemTransferTx } from "../utils"; -import { defaultConfirmOptions } from "../utils/const"; -import { initTestPool, initTickArray } from "../utils/init-utils"; -import { generateDefaultInitTickArrayParams } from "../utils/test-builders"; - -describe("initialize_tick_array", () => { - const provider = anchor.AnchorProvider.local(undefined, defaultConfirmOptions); - - const program = anchor.workspace.Whirlpool; - const ctx = WhirlpoolContext.fromWorkspace(provider, program); - const fetcher = ctx.fetcher; - - it("successfully init a TickArray account", async () => { - const tickSpacing = TickSpacing.Standard; - const { poolInitInfo } = await initTestPool(ctx, TickSpacing.Standard); - await fetcher.getPool(poolInitInfo.whirlpoolPda.publicKey); - const startTick = TICK_ARRAY_SIZE * tickSpacing * 2; - - const tickArrayInitInfo = generateDefaultInitTickArrayParams( - ctx, - poolInitInfo.whirlpoolPda.publicKey, - startTick - ); - - await toTx(ctx, WhirlpoolIx.initTickArrayIx(ctx.program, tickArrayInitInfo)).buildAndExecute(); - assertTickArrayInitialized(ctx, tickArrayInitInfo, poolInitInfo, startTick); - }); - - it("successfully init a TickArray account with a negative index", async () => { - const tickSpacing = TickSpacing.Standard; - const { poolInitInfo } = await initTestPool(ctx, TickSpacing.Standard); - await fetcher.getPool(poolInitInfo.whirlpoolPda.publicKey); - const startTick = TICK_ARRAY_SIZE * tickSpacing * -2; - - const tickArrayInitInfo = generateDefaultInitTickArrayParams( - ctx, - poolInitInfo.whirlpoolPda.publicKey, - startTick - ); - - await toTx(ctx, WhirlpoolIx.initTickArrayIx(ctx.program, tickArrayInitInfo)).buildAndExecute(); - assertTickArrayInitialized(ctx, tickArrayInitInfo, poolInitInfo, startTick); - }); - - it("succeeds when funder is different than account paying for transaction fee", async () => { - const tickSpacing = TickSpacing.Standard; - const { poolInitInfo } = await initTestPool(ctx, TickSpacing.Standard); - const funderKeypair = anchor.web3.Keypair.generate(); - await systemTransferTx(provider, funderKeypair.publicKey, ONE_SOL).buildAndExecute(); - await fetcher.getPool(poolInitInfo.whirlpoolPda.publicKey); - const startTick = TICK_ARRAY_SIZE * tickSpacing * 3; - await initTickArray(ctx, poolInitInfo.whirlpoolPda.publicKey, startTick, funderKeypair); - }); - - it("fails when start tick index is not a valid start index", async () => { - const tickSpacing = TickSpacing.Standard; - const { poolInitInfo } = await initTestPool(ctx, TickSpacing.Standard); - await fetcher.getPool(poolInitInfo.whirlpoolPda.publicKey); - const startTick = TICK_ARRAY_SIZE * tickSpacing * 2 + 1; - - const params = generateDefaultInitTickArrayParams( - ctx, - poolInitInfo.whirlpoolPda.publicKey, - startTick - ); - - try { - await toTx(ctx, WhirlpoolIx.initTickArrayIx(ctx.program, params)).buildAndExecute(); - assert.fail( - "should fail if start-tick is not a multiple of tick spacing and num ticks in array" - ); - } catch (e) { - const error = e as Error; - assert.match(error.message, /0x1771/); // InvalidStartTick - } - }); - - async function assertTickArrayInitialized( - ctx: WhirlpoolContext, - tickArrayInitInfo: InitTickArrayParams, - poolInitInfo: InitPoolParams, - startTick: number - ) { - let tickArrayData = (await fetcher.getTickArray( - tickArrayInitInfo.tickArrayPda.publicKey - )) as TickArrayData; - assert.ok(tickArrayData.whirlpool.equals(poolInitInfo.whirlpoolPda.publicKey)); - assert.ok(tickArrayData.startTickIndex == startTick); - } -}); diff --git a/sdk/tests/integration/multi-ix/bundled_position_management.test.ts b/sdk/tests/integration/multi-ix/bundled_position_management.test.ts deleted file mode 100644 index 650ac4b..0000000 --- a/sdk/tests/integration/multi-ix/bundled_position_management.test.ts +++ /dev/null @@ -1,1229 +0,0 @@ -import * as anchor from "@coral-xyz/anchor"; -import { MathUtil, TransactionBuilder, ZERO } from "@orca-so/common-sdk"; -import { getAssociatedTokenAddressSync } from "@solana/spl-token"; -import { Keypair, SystemProgram } from "@solana/web3.js"; -import * as assert from "assert"; -import { BN } from "bn.js"; -import Decimal from "decimal.js"; -import { NUM_REWARDS, PDAUtil, POSITION_BUNDLE_SIZE, PoolUtil, PositionBundleData, PriceMath, Whirlpool, WhirlpoolClient, WhirlpoolIx, buildWhirlpoolClient, collectFeesQuote, toTx } from "../../../src"; -import { WhirlpoolContext } from "../../../src/context"; -import { IGNORE_CACHE } from "../../../src/network/public/fetcher"; -import { TickSpacing, ZERO_BN, createTokenAccount } from "../../utils"; -import { defaultConfirmOptions } from "../../utils/const"; -import { WhirlpoolTestFixture } from "../../utils/fixture"; -import { initializePositionBundle, openBundledPosition } from "../../utils/init-utils"; - - -interface SharedTestContext { - provider: anchor.AnchorProvider; - program: Whirlpool; - whirlpoolCtx: WhirlpoolContext; - whirlpoolClient: WhirlpoolClient; -} - -describe("bundled position management tests", () => { - const provider = anchor.AnchorProvider.local(undefined, defaultConfirmOptions); - - let testCtx: SharedTestContext; - const tickLowerIndex = 29440; - const tickUpperIndex = 33536; - const tickSpacing = TickSpacing.Standard; - const vaultStartBalance = 1_000_000; - const liquidityAmount = new BN(10_000_000); - const sleep = (second: number) => new Promise(resolve => setTimeout(resolve, second * 1000)) - - before(() => { - anchor.setProvider(provider); - const program = anchor.workspace.Whirlpool; - const whirlpoolCtx = WhirlpoolContext.fromWorkspace(provider, program); - const whirlpoolClient = buildWhirlpoolClient(whirlpoolCtx); - - testCtx = { - provider, - program, - whirlpoolCtx, - whirlpoolClient, - }; - }); - - function checkBitmapIsOpened(account: PositionBundleData, bundleIndex: number): boolean { - if (bundleIndex < 0 || bundleIndex >= POSITION_BUNDLE_SIZE) throw Error("bundleIndex is out of bounds"); - - const bitmapIndex = Math.floor(bundleIndex / 8); - const bitmapOffset = bundleIndex % 8; - return (account.positionBitmap[bitmapIndex] & (1 << bitmapOffset)) > 0; - } - - function checkBitmapIsClosed(account: PositionBundleData, bundleIndex: number): boolean { - if (bundleIndex < 0 || bundleIndex >= POSITION_BUNDLE_SIZE) throw Error("bundleIndex is out of bounds"); - - const bitmapIndex = Math.floor(bundleIndex / 8); - const bitmapOffset = bundleIndex % 8; - return (account.positionBitmap[bitmapIndex] & (1 << bitmapOffset)) === 0; - } - - function checkBitmap(account: PositionBundleData, openedBundleIndexes: number[]) { - for (let i = 0; i < POSITION_BUNDLE_SIZE; i++) { - if (openedBundleIndexes.includes(i)) { - assert.ok(checkBitmapIsOpened(account, i)); - } - else { - assert.ok(checkBitmapIsClosed(account, i)); - } - } - } - - async function accrueFees(fixture: WhirlpoolTestFixture) { - const ctx = testCtx.whirlpoolCtx; - const { - poolInitInfo, - positions, - tokenAccountA, - tokenAccountB, - } = fixture.getInfos(); - - const { whirlpoolPda, tokenVaultAKeypair, tokenVaultBKeypair } = poolInitInfo; - - const tickArrayPda = PDAUtil.getTickArray(ctx.program.programId, whirlpoolPda.publicKey, 22528); - const oraclePda = PDAUtil.getOracle(ctx.program.programId, whirlpoolPda.publicKey); - - const pool = await testCtx.whirlpoolClient.getPool(whirlpoolPda.publicKey); - - // Accrue fees in token A - await toTx( - ctx, - WhirlpoolIx.swapIx(ctx.program, { - amount: new BN(200_000), - otherAmountThreshold: ZERO_BN, - sqrtPriceLimit: MathUtil.toX64(new Decimal(4)), - amountSpecifiedIsInput: true, - aToB: true, - whirlpool: whirlpoolPda.publicKey, - tokenAuthority: ctx.wallet.publicKey, - tokenOwnerAccountA: tokenAccountA, - tokenVaultA: tokenVaultAKeypair.publicKey, - tokenOwnerAccountB: tokenAccountB, - tokenVaultB: tokenVaultBKeypair.publicKey, - tickArray0: tickArrayPda.publicKey, - tickArray1: tickArrayPda.publicKey, - tickArray2: tickArrayPda.publicKey, - oracle: oraclePda.publicKey, - }) - ).buildAndExecute(); - - // Accrue fees in token B - await toTx( - ctx, - WhirlpoolIx.swapIx(ctx.program, { - amount: new BN(200_000), - otherAmountThreshold: ZERO_BN, - sqrtPriceLimit: MathUtil.toX64(new Decimal(5)), - amountSpecifiedIsInput: true, - aToB: false, - whirlpool: whirlpoolPda.publicKey, - tokenAuthority: ctx.wallet.publicKey, - tokenOwnerAccountA: tokenAccountA, - tokenVaultA: tokenVaultAKeypair.publicKey, - tokenOwnerAccountB: tokenAccountB, - tokenVaultB: tokenVaultBKeypair.publicKey, - tickArray0: tickArrayPda.publicKey, - tickArray1: tickArrayPda.publicKey, - tickArray2: tickArrayPda.publicKey, - oracle: oraclePda.publicKey, - }) - ).buildAndExecute(); - - // all position should get some fees - for (const positionInfo of positions) { - const position = await testCtx.whirlpoolClient.getPosition(positionInfo.publicKey); - - const poolData = await pool.refreshData(); - const positionData = await position.refreshData(); - const tickLowerData = position.getLowerTickData(); - const tickUpperData = position.getLowerTickData(); - - const quote = collectFeesQuote({ - whirlpool: poolData, - position: positionData, - tickLower: tickLowerData, - tickUpper: tickUpperData, - }); - - assert.ok(quote.feeOwedA.gtn(0) || quote.feeOwedB.gtn(0)); - } - } - - async function stopRewardsEmission(fixture: WhirlpoolTestFixture) { - const ctx = testCtx.whirlpoolCtx; - const { poolInitInfo, configKeypairs } = fixture.getInfos(); - const { whirlpoolPda } = poolInitInfo; - - const pool = await testCtx.whirlpoolClient.getPool(whirlpoolPda.publicKey); - - for (let i = 0; i < NUM_REWARDS; i++) { - await toTx( - ctx, - WhirlpoolIx.setRewardEmissionsIx(ctx.program, { - whirlpool: pool.getAddress(), - rewardVaultKey: pool.getData().rewardInfos[i].vault, - rewardAuthority: configKeypairs.rewardEmissionsSuperAuthorityKeypair.publicKey, - rewardIndex: i, - emissionsPerSecondX64: ZERO, - }) - ).addSigner(configKeypairs.rewardEmissionsSuperAuthorityKeypair).buildAndExecute(); - } - } - - it(`successfully open POSITION_BUNDLE_SIZE(${POSITION_BUNDLE_SIZE}) bundled positions and then close them`, async () => { - // create test pool - const ctx = testCtx.whirlpoolCtx; - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing, - positions: [], - rewards: [], - }); - const { poolInitInfo, rewards } = fixture.getInfos(); - // initialize position bundle - const positionBundleInfo = await initializePositionBundle(ctx, ctx.wallet.publicKey); - const positionBundlePubkey = positionBundleInfo.positionBundlePda.publicKey; - const whirlpoolPubkey = poolInitInfo.whirlpoolPda.publicKey; - - const batchSize = 12; - const openedBundleIndexes: number[] = []; - - // open all - for (let startBundleIndex = 0; startBundleIndex < POSITION_BUNDLE_SIZE; startBundleIndex += batchSize) { - const minBundleIndex = startBundleIndex; - const maxBundleIndex = Math.min(startBundleIndex + batchSize, POSITION_BUNDLE_SIZE) - 1; - - const builder = new TransactionBuilder(ctx.connection, ctx.wallet, ctx.txBuilderOpts); - - for (let bundleIndex = minBundleIndex; bundleIndex <= maxBundleIndex; bundleIndex++) { - const bundledPositionPda = PDAUtil.getBundledPosition(ctx.program.programId, positionBundleInfo.positionBundleMintKeypair.publicKey, bundleIndex); - builder.addInstruction(WhirlpoolIx.openBundledPositionIx(ctx.program, { - bundledPositionPda, - bundleIndex, - positionBundle: positionBundlePubkey, - positionBundleAuthority: ctx.wallet.publicKey, - positionBundleTokenAccount: positionBundleInfo.positionBundleTokenAccount, - tickLowerIndex, - tickUpperIndex, - whirlpool: whirlpoolPubkey, - funder: ctx.wallet.publicKey - })); - openedBundleIndexes.push(bundleIndex); - } - - await builder.buildAndExecute(); - const positionBundleAccount = await ctx.fetcher.getPositionBundle(positionBundlePubkey, IGNORE_CACHE); - checkBitmap(positionBundleAccount!, openedBundleIndexes); - } - assert.equal(openedBundleIndexes.length, POSITION_BUNDLE_SIZE); - - // close all - for (let startBundleIndex = 0; startBundleIndex < POSITION_BUNDLE_SIZE; startBundleIndex += batchSize) { - const minBundleIndex = startBundleIndex; - const maxBundleIndex = Math.min(startBundleIndex + batchSize, POSITION_BUNDLE_SIZE) - 1; - - const builder = new TransactionBuilder(ctx.connection, ctx.wallet, ctx.txBuilderOpts); - - for (let bundleIndex = minBundleIndex; bundleIndex <= maxBundleIndex; bundleIndex++) { - const bundledPositionPda = PDAUtil.getBundledPosition(ctx.program.programId, positionBundleInfo.positionBundleMintKeypair.publicKey, bundleIndex); - builder.addInstruction(WhirlpoolIx.closeBundledPositionIx(ctx.program, { - bundledPosition: bundledPositionPda.publicKey, - bundleIndex, - positionBundle: positionBundlePubkey, - positionBundleAuthority: ctx.wallet.publicKey, - positionBundleTokenAccount: positionBundleInfo.positionBundleTokenAccount, - receiver: ctx.wallet.publicKey - })); - openedBundleIndexes.shift(); - } - - await builder.buildAndExecute(); - const positionBundleAccount = await ctx.fetcher.getPositionBundle(positionBundlePubkey, IGNORE_CACHE); - checkBitmap(positionBundleAccount!, openedBundleIndexes); - } - assert.equal(openedBundleIndexes.length, 0); - - // delete position bundle - await toTx( - ctx, - WhirlpoolIx.deletePositionBundleIx(ctx.program, { - positionBundle: positionBundlePubkey, - positionBundleMint: positionBundleInfo.positionBundleMintKeypair.publicKey, - positionBundleTokenAccount: positionBundleInfo.positionBundleTokenAccount, - owner: ctx.wallet.publicKey, - receiver: ctx.wallet.publicKey, - }) - ).buildAndExecute(); - const positionBundleAccount = await ctx.fetcher.getPositionBundle(positionBundlePubkey, IGNORE_CACHE); - assert.ok(positionBundleAccount === null); - }); - - it("successfully increase/decrease liquidity and harvest on bundled position", async () => { - // create test pool - const ctx = testCtx.whirlpoolCtx; - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing, - positions: [ - { liquidityAmount, tickLowerIndex, tickUpperIndex }, // non bundled position (to create TickArrays) - ], - rewards: [ - { - emissionsPerSecondX64: MathUtil.toX64(new Decimal(10)), - vaultAmount: new BN(vaultStartBalance), - }, - { - emissionsPerSecondX64: MathUtil.toX64(new Decimal(10)), - vaultAmount: new BN(vaultStartBalance), - }, - { - emissionsPerSecondX64: MathUtil.toX64(new Decimal(10)), - vaultAmount: new BN(vaultStartBalance), - }, - ], - }); - const { poolInitInfo, rewards } = fixture.getInfos(); - - // initialize position bundle - const positionBundleInfo = await initializePositionBundle(ctx, ctx.wallet.publicKey); - - // open bundled position - const bundleIndex = 0; - const positionInitInfo = await openBundledPosition( - ctx, - poolInitInfo.whirlpoolPda.publicKey, - positionBundleInfo.positionBundleMintKeypair.publicKey, - bundleIndex, - tickLowerIndex, - tickUpperIndex - ); - const { bundledPositionPda } = positionInitInfo.params; - - const bundledPositionPubkey = bundledPositionPda.publicKey; - const tickArrayLower = PDAUtil.getTickArrayFromTickIndex(positionInitInfo.params.tickLowerIndex, poolInitInfo.tickSpacing, poolInitInfo.whirlpoolPda.publicKey, ctx.program.programId).publicKey; - const tickArrayUpper = PDAUtil.getTickArrayFromTickIndex(positionInitInfo.params.tickUpperIndex, poolInitInfo.tickSpacing, poolInitInfo.whirlpoolPda.publicKey, ctx.program.programId).publicKey; - const whirlpoolPubkey = poolInitInfo.whirlpoolPda.publicKey; - const tokenOwnerAccountA = getAssociatedTokenAddressSync(poolInitInfo.tokenMintA, ctx.wallet.publicKey); - const tokenOwnerAccountB = getAssociatedTokenAddressSync(poolInitInfo.tokenMintB, ctx.wallet.publicKey); - - const modifyLiquidityParams = { - liquidityAmount, - position: bundledPositionPubkey, - positionAuthority: ctx.wallet.publicKey, - positionTokenAccount: positionBundleInfo.positionBundleTokenAccount, - tickArrayLower, - tickArrayUpper, - tokenOwnerAccountA, - tokenOwnerAccountB, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - whirlpool: whirlpoolPubkey, - } - - // increaseLiquidity - const depositAmounts = PoolUtil.getTokenAmountsFromLiquidity( - liquidityAmount, - (await ctx.fetcher.getPool(whirlpoolPubkey, IGNORE_CACHE))!.sqrtPrice, - PriceMath.tickIndexToSqrtPriceX64(tickLowerIndex), - PriceMath.tickIndexToSqrtPriceX64(tickUpperIndex), - true - ); - - const preIncrease = await ctx.fetcher.getPosition(bundledPositionPubkey, IGNORE_CACHE); - assert.ok(preIncrease!.liquidity.isZero()); - await toTx( - ctx, - WhirlpoolIx.increaseLiquidityIx(ctx.program, { - ...modifyLiquidityParams, - tokenMaxA: depositAmounts.tokenA, - tokenMaxB: depositAmounts.tokenB, - }) - ).buildAndExecute(); - const postIncrease = await ctx.fetcher.getPosition(bundledPositionPubkey, IGNORE_CACHE); - assert.ok(postIncrease!.liquidity.eq(liquidityAmount)); - - await sleep(2); // accrueRewards - await accrueFees(fixture); - await stopRewardsEmission(fixture); - - // updateFeesAndRewards - const preUpdate = await ctx.fetcher.getPosition(bundledPositionPubkey, IGNORE_CACHE); - assert.ok(preUpdate!.feeOwedA.isZero()); - assert.ok(preUpdate!.feeOwedB.isZero()); - assert.ok(preUpdate!.rewardInfos.every((r) => r.amountOwed.isZero())); - await toTx( - ctx, - WhirlpoolIx.updateFeesAndRewardsIx(ctx.program, { - position: bundledPositionPubkey, - tickArrayLower, - tickArrayUpper, - whirlpool: whirlpoolPubkey, - }) - ).buildAndExecute(); - const postUpdate = await ctx.fetcher.getPosition(bundledPositionPubkey, IGNORE_CACHE); - assert.ok(postUpdate!.feeOwedA.gtn(0)); - assert.ok(postUpdate!.feeOwedB.gtn(0)); - assert.ok(postUpdate!.rewardInfos.every((r) => r.amountOwed.gtn(0))); - - // collectFees - await toTx( - ctx, - WhirlpoolIx.collectFeesIx(ctx.program, { - position: bundledPositionPubkey, - positionAuthority: ctx.wallet.publicKey, - positionTokenAccount: positionBundleInfo.positionBundleTokenAccount, - tokenOwnerAccountA, - tokenOwnerAccountB, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - whirlpool: whirlpoolPubkey, - }) - ).buildAndExecute(); - const postCollectFees = await ctx.fetcher.getPosition(bundledPositionPubkey, IGNORE_CACHE); - assert.ok(postCollectFees!.feeOwedA.isZero()); - assert.ok(postCollectFees!.feeOwedB.isZero()); - - // collectReward - for (let i = 0; i < NUM_REWARDS; i++) { - const ata = await createTokenAccount( - provider, - rewards[i].rewardMint, - ctx.wallet.publicKey - ); - - const preCollectReward = await ctx.fetcher.getPosition(bundledPositionPubkey, IGNORE_CACHE); - assert.ok(preCollectReward!.rewardInfos[i].amountOwed.gtn(0)); - await toTx( - ctx, - WhirlpoolIx.collectRewardIx(ctx.program, { - position: bundledPositionPubkey, - positionAuthority: ctx.wallet.publicKey, - positionTokenAccount: positionBundleInfo.positionBundleTokenAccount, - rewardIndex: i, - rewardVault: rewards[i].rewardVaultKeypair.publicKey, - rewardOwnerAccount: ata, - whirlpool: whirlpoolPubkey, - }) - ).buildAndExecute(); - const postCollectReward = await ctx.fetcher.getPosition(bundledPositionPubkey, IGNORE_CACHE); - assert.ok(postCollectReward!.rewardInfos[i].amountOwed.isZero()); - } - // decreaseLiquidity - const withdrawAmounts = PoolUtil.getTokenAmountsFromLiquidity( - liquidityAmount, - (await ctx.fetcher.getPool(whirlpoolPubkey, IGNORE_CACHE))!.sqrtPrice, - PriceMath.tickIndexToSqrtPriceX64(tickLowerIndex), - PriceMath.tickIndexToSqrtPriceX64(tickUpperIndex), - false - ); - - const preDecrease = await ctx.fetcher.getPosition(bundledPositionPubkey, IGNORE_CACHE); - assert.ok(preDecrease!.liquidity.eq(liquidityAmount)); - await toTx( - ctx, - WhirlpoolIx.decreaseLiquidityIx(ctx.program, { - ...modifyLiquidityParams, - tokenMinA: withdrawAmounts.tokenA, - tokenMinB: withdrawAmounts.tokenB, - }) - ).buildAndExecute(); - const postDecrease = await ctx.fetcher.getPosition(bundledPositionPubkey, IGNORE_CACHE); - assert.ok(postDecrease!.liquidity.isZero()); - - // close bundled position - await toTx( - ctx, - WhirlpoolIx.closeBundledPositionIx(ctx.program, { - bundledPosition: bundledPositionPubkey, - bundleIndex, - positionBundle: positionBundleInfo.positionBundlePda.publicKey, - positionBundleAuthority: ctx.wallet.publicKey, - positionBundleTokenAccount: positionBundleInfo.positionBundleTokenAccount, - receiver: ctx.wallet.publicKey, - }) - ).buildAndExecute(); - const postClose = await ctx.fetcher.getPosition(bundledPositionPubkey, IGNORE_CACHE); - assert.ok(postClose === null); - }); - - it("successfully repeatedly open bundled position & close bundled position", async () => { - const openCloseIterationNum = 5; - - // create test pool - const ctx = testCtx.whirlpoolCtx; - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing, - positions: [ - { liquidityAmount, tickLowerIndex, tickUpperIndex }, // non bundled position (to create TickArrays) - ], - rewards: [ - { - emissionsPerSecondX64: MathUtil.toX64(new Decimal(10)), - vaultAmount: new BN(vaultStartBalance), - }, - { - emissionsPerSecondX64: MathUtil.toX64(new Decimal(10)), - vaultAmount: new BN(vaultStartBalance), - }, - { - emissionsPerSecondX64: MathUtil.toX64(new Decimal(10)), - vaultAmount: new BN(vaultStartBalance), - }, - ], - }); - const { poolInitInfo, rewards } = fixture.getInfos(); - - // increase feeGrowth - await accrueFees(fixture); - - // increase rewardGrowth - await sleep(2); - - // initialize position bundle - const positionBundleInfo = await initializePositionBundle(ctx, ctx.wallet.publicKey); - const bundleIndex = Math.floor(Math.random() * POSITION_BUNDLE_SIZE); - - for (let iter = 0; iter < openCloseIterationNum; iter++) { - // open bundled position - const positionInitInfo = await openBundledPosition( - ctx, - poolInitInfo.whirlpoolPda.publicKey, - positionBundleInfo.positionBundleMintKeypair.publicKey, - bundleIndex, - tickLowerIndex, - tickUpperIndex - ); - const { bundledPositionPda } = positionInitInfo.params; - - const bundledPositionPubkey = bundledPositionPda.publicKey; - const tickArrayLower = PDAUtil.getTickArrayFromTickIndex(positionInitInfo.params.tickLowerIndex, poolInitInfo.tickSpacing, poolInitInfo.whirlpoolPda.publicKey, ctx.program.programId).publicKey; - const tickArrayUpper = PDAUtil.getTickArrayFromTickIndex(positionInitInfo.params.tickUpperIndex, poolInitInfo.tickSpacing, poolInitInfo.whirlpoolPda.publicKey, ctx.program.programId).publicKey; - const whirlpoolPubkey = poolInitInfo.whirlpoolPda.publicKey; - const tokenOwnerAccountA = getAssociatedTokenAddressSync(poolInitInfo.tokenMintA, ctx.wallet.publicKey); - const tokenOwnerAccountB = getAssociatedTokenAddressSync(poolInitInfo.tokenMintB, ctx.wallet.publicKey); - - // initialized check (No data left over from previous opening) - const postOpen = await ctx.fetcher.getPosition(bundledPositionPubkey, IGNORE_CACHE); - assert.ok(postOpen!.feeGrowthCheckpointA.isZero()); - assert.ok(postOpen!.feeGrowthCheckpointB.isZero()); - assert.ok(postOpen!.rewardInfos.every((r) => r.growthInsideCheckpoint.isZero())); - - const modifyLiquidityParams = { - liquidityAmount, - position: bundledPositionPubkey, - positionAuthority: ctx.wallet.publicKey, - positionTokenAccount: positionBundleInfo.positionBundleTokenAccount, - tickArrayLower, - tickArrayUpper, - tokenOwnerAccountA, - tokenOwnerAccountB, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - whirlpool: whirlpoolPubkey, - } - - // increaseLiquidity - const depositAmounts = PoolUtil.getTokenAmountsFromLiquidity( - liquidityAmount, - (await ctx.fetcher.getPool(whirlpoolPubkey, IGNORE_CACHE))!.sqrtPrice, - PriceMath.tickIndexToSqrtPriceX64(tickLowerIndex), - PriceMath.tickIndexToSqrtPriceX64(tickUpperIndex), - true - ); - const preIncrease = await ctx.fetcher.getPosition(bundledPositionPubkey, IGNORE_CACHE); - assert.ok(preIncrease!.liquidity.isZero()); - await toTx( - ctx, - WhirlpoolIx.increaseLiquidityIx(ctx.program, { - ...modifyLiquidityParams, - tokenMaxA: depositAmounts.tokenA, - tokenMaxB: depositAmounts.tokenB, - }) - ).buildAndExecute(); - const postIncrease = await ctx.fetcher.getPosition(bundledPositionPubkey, IGNORE_CACHE); - assert.ok(postIncrease!.liquidity.eq(liquidityAmount)); - - // non-zero check - assert.ok(postIncrease!.feeGrowthCheckpointA.gtn(0)); - assert.ok(postIncrease!.feeGrowthCheckpointB.gtn(0)); - assert.ok(postIncrease!.rewardInfos.every((r) => r.growthInsideCheckpoint.gtn(0))); - - await sleep(2); // accrueRewards - await accrueFees(fixture); - // decreaseLiquidity - const withdrawAmounts = PoolUtil.getTokenAmountsFromLiquidity( - liquidityAmount, - (await ctx.fetcher.getPool(whirlpoolPubkey, IGNORE_CACHE))!.sqrtPrice, - PriceMath.tickIndexToSqrtPriceX64(tickLowerIndex), - PriceMath.tickIndexToSqrtPriceX64(tickUpperIndex), - false - ); - - const preDecrease = await ctx.fetcher.getPosition(bundledPositionPubkey, IGNORE_CACHE); - assert.ok(preDecrease!.liquidity.eq(liquidityAmount)); - await toTx( - ctx, - WhirlpoolIx.decreaseLiquidityIx(ctx.program, { - ...modifyLiquidityParams, - tokenMinA: withdrawAmounts.tokenA, - tokenMinB: withdrawAmounts.tokenB, - }) - ).buildAndExecute(); - const postDecrease = await ctx.fetcher.getPosition(bundledPositionPubkey, IGNORE_CACHE); - assert.ok(postDecrease!.liquidity.isZero()); - - // collectFees - await toTx( - ctx, - WhirlpoolIx.collectFeesIx(ctx.program, { - position: bundledPositionPubkey, - positionAuthority: ctx.wallet.publicKey, - positionTokenAccount: positionBundleInfo.positionBundleTokenAccount, - tokenOwnerAccountA, - tokenOwnerAccountB, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - whirlpool: whirlpoolPubkey, - }) - ).buildAndExecute(); - const postCollectFees = await ctx.fetcher.getPosition(bundledPositionPubkey, IGNORE_CACHE); - assert.ok(postCollectFees!.feeOwedA.isZero()); - assert.ok(postCollectFees!.feeOwedB.isZero()); - - // collectReward - for (let i = 0; i < NUM_REWARDS; i++) { - const ata = await createTokenAccount( - provider, - rewards[i].rewardMint, - ctx.wallet.publicKey - ); - - const preCollectReward = await ctx.fetcher.getPosition(bundledPositionPubkey, IGNORE_CACHE); - assert.ok(preCollectReward!.rewardInfos[i].amountOwed.gtn(0)); - await toTx( - ctx, - WhirlpoolIx.collectRewardIx(ctx.program, { - position: bundledPositionPubkey, - positionAuthority: ctx.wallet.publicKey, - positionTokenAccount: positionBundleInfo.positionBundleTokenAccount, - rewardIndex: i, - rewardVault: rewards[i].rewardVaultKeypair.publicKey, - rewardOwnerAccount: ata, - whirlpool: whirlpoolPubkey, - }) - ).buildAndExecute(); - const postCollectReward = await ctx.fetcher.getPosition(bundledPositionPubkey, IGNORE_CACHE); - assert.ok(postCollectReward!.rewardInfos[i].amountOwed.isZero()); - } - - // close bundled position - await toTx( - ctx, - WhirlpoolIx.closeBundledPositionIx(ctx.program, { - bundledPosition: bundledPositionPubkey, - bundleIndex, - positionBundle: positionBundleInfo.positionBundlePda.publicKey, - positionBundleAuthority: ctx.wallet.publicKey, - positionBundleTokenAccount: positionBundleInfo.positionBundleTokenAccount, - receiver: ctx.wallet.publicKey, - }) - ).buildAndExecute(); - const postClose = await ctx.fetcher.getPosition(bundledPositionPubkey, IGNORE_CACHE); - assert.ok(postClose === null); - } - }); - - describe("Single Transaction", () => { - it("successfully openBundledPosition+increaseLiquidity / decreaseLiquidity+closeBundledPosition in single Tx", async () => { - // create test pool - const ctx = testCtx.whirlpoolCtx; - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing, - positions: [ - { liquidityAmount, tickLowerIndex, tickUpperIndex }, // non bundled position (to create TickArrays) - ], - rewards: [], - }); - const { poolInitInfo, rewards } = fixture.getInfos(); - - // initialize position bundle - const positionBundleInfo = await initializePositionBundle(ctx, ctx.wallet.publicKey); - const bundleIndex = Math.floor(Math.random() * POSITION_BUNDLE_SIZE); - - const bundledPositionPda = PDAUtil.getBundledPosition(ctx.program.programId, positionBundleInfo.positionBundleMintKeypair.publicKey, bundleIndex); - const bundledPositionPubkey = bundledPositionPda.publicKey; - const tickArrayLower = PDAUtil.getTickArrayFromTickIndex(tickLowerIndex, poolInitInfo.tickSpacing, poolInitInfo.whirlpoolPda.publicKey, ctx.program.programId).publicKey; - const tickArrayUpper = PDAUtil.getTickArrayFromTickIndex(tickUpperIndex, poolInitInfo.tickSpacing, poolInitInfo.whirlpoolPda.publicKey, ctx.program.programId).publicKey; - const whirlpoolPubkey = poolInitInfo.whirlpoolPda.publicKey; - const tokenOwnerAccountA = getAssociatedTokenAddressSync(poolInitInfo.tokenMintA, ctx.wallet.publicKey); - const tokenOwnerAccountB = getAssociatedTokenAddressSync(poolInitInfo.tokenMintB, ctx.wallet.publicKey); - - const modifyLiquidityParams = { - liquidityAmount, - position: bundledPositionPubkey, - positionAuthority: ctx.wallet.publicKey, - positionTokenAccount: positionBundleInfo.positionBundleTokenAccount, - tickArrayLower, - tickArrayUpper, - tokenOwnerAccountA, - tokenOwnerAccountB, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - whirlpool: whirlpoolPubkey, - } - - const depositAmounts = PoolUtil.getTokenAmountsFromLiquidity( - liquidityAmount, - (await ctx.fetcher.getPool(whirlpoolPubkey, IGNORE_CACHE))!.sqrtPrice, - PriceMath.tickIndexToSqrtPriceX64(tickLowerIndex), - PriceMath.tickIndexToSqrtPriceX64(tickUpperIndex), - true - ); - - // openBundledPosition + increaseLiquidity - const openIncreaseBuilder = new TransactionBuilder(ctx.connection, ctx.wallet, ctx.txBuilderOpts); - openIncreaseBuilder - .addInstruction(WhirlpoolIx.openBundledPositionIx(ctx.program, { - bundledPositionPda, - bundleIndex, - positionBundle: positionBundleInfo.positionBundlePda.publicKey, - positionBundleAuthority: ctx.wallet.publicKey, - positionBundleTokenAccount: positionBundleInfo.positionBundleTokenAccount, - tickLowerIndex, - tickUpperIndex, - whirlpool: whirlpoolPubkey, - funder: ctx.wallet.publicKey - })) - .addInstruction(WhirlpoolIx.increaseLiquidityIx(ctx.program, { - ...modifyLiquidityParams, - tokenMaxA: depositAmounts.tokenA, - tokenMaxB: depositAmounts.tokenB, - })); - await openIncreaseBuilder.buildAndExecute(); - const postIncrease = await ctx.fetcher.getPosition(bundledPositionPubkey, IGNORE_CACHE); - assert.ok(postIncrease!.liquidity.eq(liquidityAmount)); - - const withdrawAmounts = PoolUtil.getTokenAmountsFromLiquidity( - liquidityAmount, - (await ctx.fetcher.getPool(whirlpoolPubkey, IGNORE_CACHE))!.sqrtPrice, - PriceMath.tickIndexToSqrtPriceX64(tickLowerIndex), - PriceMath.tickIndexToSqrtPriceX64(tickUpperIndex), - false - ); - - const decreaseCloseBuilder = new TransactionBuilder(ctx.connection, ctx.wallet, ctx.txBuilderOpts); - decreaseCloseBuilder - .addInstruction(WhirlpoolIx.decreaseLiquidityIx(ctx.program, { - ...modifyLiquidityParams, - tokenMinA: withdrawAmounts.tokenA, - tokenMinB: withdrawAmounts.tokenB, - })) - .addInstruction(WhirlpoolIx.closeBundledPositionIx(ctx.program, { - bundledPosition: bundledPositionPubkey, - bundleIndex, - positionBundle: positionBundleInfo.positionBundlePda.publicKey, - positionBundleAuthority: ctx.wallet.publicKey, - positionBundleTokenAccount: positionBundleInfo.positionBundleTokenAccount, - receiver: ctx.wallet.publicKey, - })); - await decreaseCloseBuilder.buildAndExecute(); - const postClose = await ctx.fetcher.getPosition(bundledPositionPubkey, IGNORE_CACHE); - assert.ok(postClose === null); - }); - - it("successfully open bundled position & close bundled position in single Tx", async () => { - // create test pool - const ctx = testCtx.whirlpoolCtx; - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing, - positions: [ - { liquidityAmount, tickLowerIndex, tickUpperIndex }, // non bundled position (to create TickArrays) - ], - rewards: [ - { - emissionsPerSecondX64: MathUtil.toX64(new Decimal(10)), - vaultAmount: new BN(vaultStartBalance), - }, - { - emissionsPerSecondX64: MathUtil.toX64(new Decimal(10)), - vaultAmount: new BN(vaultStartBalance), - }, - { - emissionsPerSecondX64: MathUtil.toX64(new Decimal(10)), - vaultAmount: new BN(vaultStartBalance), - }, - ], - }); - const { poolInitInfo, rewards } = fixture.getInfos(); - - // initialize position bundle - const positionBundleInfo = await initializePositionBundle(ctx, ctx.wallet.publicKey); - const bundleIndex = Math.floor(Math.random() * POSITION_BUNDLE_SIZE); - - const bundledPositionPda = PDAUtil.getBundledPosition(ctx.program.programId, positionBundleInfo.positionBundleMintKeypair.publicKey, bundleIndex); - const bundledPositionPubkey = bundledPositionPda.publicKey; - const tickArrayLower = PDAUtil.getTickArrayFromTickIndex(tickLowerIndex, poolInitInfo.tickSpacing, poolInitInfo.whirlpoolPda.publicKey, ctx.program.programId).publicKey; - const tickArrayUpper = PDAUtil.getTickArrayFromTickIndex(tickUpperIndex, poolInitInfo.tickSpacing, poolInitInfo.whirlpoolPda.publicKey, ctx.program.programId).publicKey; - const whirlpoolPubkey = poolInitInfo.whirlpoolPda.publicKey; - const tokenOwnerAccountA = getAssociatedTokenAddressSync(poolInitInfo.tokenMintA, ctx.wallet.publicKey); - const tokenOwnerAccountB = getAssociatedTokenAddressSync(poolInitInfo.tokenMintB, ctx.wallet.publicKey); - - const modifyLiquidityParams = { - liquidityAmount, - position: bundledPositionPubkey, - positionAuthority: ctx.wallet.publicKey, - positionTokenAccount: positionBundleInfo.positionBundleTokenAccount, - tickArrayLower, - tickArrayUpper, - tokenOwnerAccountA, - tokenOwnerAccountB, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - whirlpool: whirlpoolPubkey, - } - - const depositAmounts = PoolUtil.getTokenAmountsFromLiquidity( - liquidityAmount, - (await ctx.fetcher.getPool(whirlpoolPubkey, IGNORE_CACHE))!.sqrtPrice, - PriceMath.tickIndexToSqrtPriceX64(tickLowerIndex), - PriceMath.tickIndexToSqrtPriceX64(tickUpperIndex), - true - ); - - const receiver = Keypair.generate(); - const builder = new TransactionBuilder(ctx.connection, ctx.wallet, ctx.txBuilderOpts); - builder - .addInstruction(WhirlpoolIx.openBundledPositionIx(ctx.program, { - bundledPositionPda, - bundleIndex, - positionBundle: positionBundleInfo.positionBundlePda.publicKey, - positionBundleAuthority: ctx.wallet.publicKey, - positionBundleTokenAccount: positionBundleInfo.positionBundleTokenAccount, - tickLowerIndex, - tickUpperIndex, - whirlpool: whirlpoolPubkey, - funder: ctx.wallet.publicKey - })) - .addInstruction(WhirlpoolIx.increaseLiquidityIx(ctx.program, { - ...modifyLiquidityParams, - tokenMaxA: depositAmounts.tokenA, - tokenMaxB: depositAmounts.tokenB, - })) - .addInstruction(WhirlpoolIx.decreaseLiquidityIx(ctx.program, { - ...modifyLiquidityParams, - tokenMinA: new BN(0), - tokenMinB: new BN(0), - })) - .addInstruction(WhirlpoolIx.closeBundledPositionIx(ctx.program, { - bundledPosition: bundledPositionPubkey, - bundleIndex, - positionBundle: positionBundleInfo.positionBundlePda.publicKey, - positionBundleAuthority: ctx.wallet.publicKey, - positionBundleTokenAccount: positionBundleInfo.positionBundleTokenAccount, - receiver: receiver.publicKey, - })); - - await builder.buildAndExecute(); - const receiverBalance = await ctx.connection.getBalance(receiver.publicKey, "confirmed"); - assert.ok(receiverBalance > 0); - }); - - it("successfully close & re-open bundled position with the same bundle index in single Tx", async () => { - // create test pool - const ctx = testCtx.whirlpoolCtx; - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing, - positions: [], - rewards: [], - }); - const { poolInitInfo, rewards } = fixture.getInfos(); - - // initialize position bundle - const positionBundleInfo = await initializePositionBundle(ctx, ctx.wallet.publicKey); - const bundleIndex = Math.floor(Math.random() * POSITION_BUNDLE_SIZE); - - const bundledPositionPda = PDAUtil.getBundledPosition(ctx.program.programId, positionBundleInfo.positionBundleMintKeypair.publicKey, bundleIndex); - const bundledPositionPubkey = bundledPositionPda.publicKey; - const whirlpoolPubkey = poolInitInfo.whirlpoolPda.publicKey; - - const builder = new TransactionBuilder(ctx.connection, ctx.wallet, ctx.txBuilderOpts); - builder - // open - .addInstruction(WhirlpoolIx.openBundledPositionIx(ctx.program, { - bundledPositionPda, - bundleIndex, - positionBundle: positionBundleInfo.positionBundlePda.publicKey, - positionBundleAuthority: ctx.wallet.publicKey, - positionBundleTokenAccount: positionBundleInfo.positionBundleTokenAccount, - tickLowerIndex, - tickUpperIndex, - whirlpool: whirlpoolPubkey, - funder: ctx.wallet.publicKey - })) - // close - .addInstruction(WhirlpoolIx.closeBundledPositionIx(ctx.program, { - bundledPosition: bundledPositionPubkey, - bundleIndex, - positionBundle: positionBundleInfo.positionBundlePda.publicKey, - positionBundleAuthority: ctx.wallet.publicKey, - positionBundleTokenAccount: positionBundleInfo.positionBundleTokenAccount, - receiver: whirlpoolPubkey, - })) - // reopen bundled position with same bundleIndex in single Tx - .addInstruction(WhirlpoolIx.openBundledPositionIx(ctx.program, { - bundledPositionPda, - bundleIndex, - positionBundle: positionBundleInfo.positionBundlePda.publicKey, - positionBundleAuthority: ctx.wallet.publicKey, - positionBundleTokenAccount: positionBundleInfo.positionBundleTokenAccount, - tickLowerIndex: tickLowerIndex + tickSpacing, - tickUpperIndex: tickUpperIndex + tickSpacing, - whirlpool: whirlpoolPubkey, - funder: ctx.wallet.publicKey - })); - - // Account closing reassigns to system program and reallocates - // https://github.com/coral-xyz/anchor/pull/2169 - // in Anchor v0.26.0, close & open in same Tx will success. - await builder.buildAndExecute(); - const postReopen = await ctx.fetcher.getPosition(bundledPositionPubkey, IGNORE_CACHE); - assert.ok(postReopen!.liquidity.isZero()); - assert.ok(postReopen!.tickLowerIndex === tickLowerIndex + tickSpacing); - assert.ok(postReopen!.tickUpperIndex === tickUpperIndex + tickSpacing); - }); - - it("successfully open bundled position & swap & close bundled position in single Tx", async () => { - // create test pool - const ctx = testCtx.whirlpoolCtx; - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing, - positions: [ - { liquidityAmount, tickLowerIndex, tickUpperIndex }, // non bundled position (to create TickArrays) - ], - rewards: [ - { - emissionsPerSecondX64: MathUtil.toX64(new Decimal(10)), - vaultAmount: new BN(vaultStartBalance), - }, - { - emissionsPerSecondX64: MathUtil.toX64(new Decimal(10)), - vaultAmount: new BN(vaultStartBalance), - }, - { - emissionsPerSecondX64: MathUtil.toX64(new Decimal(10)), - vaultAmount: new BN(vaultStartBalance), - }, - ], - }); - const { poolInitInfo, rewards } = fixture.getInfos(); - - // initialize position bundle - const positionBundleInfo = await initializePositionBundle(ctx, ctx.wallet.publicKey); - const bundleIndex = Math.floor(Math.random() * POSITION_BUNDLE_SIZE); - - const bundledPositionPda = PDAUtil.getBundledPosition(ctx.program.programId, positionBundleInfo.positionBundleMintKeypair.publicKey, bundleIndex); - const bundledPositionPubkey = bundledPositionPda.publicKey; - const tickArrayLower = PDAUtil.getTickArrayFromTickIndex(tickLowerIndex, poolInitInfo.tickSpacing, poolInitInfo.whirlpoolPda.publicKey, ctx.program.programId).publicKey; - const tickArrayUpper = PDAUtil.getTickArrayFromTickIndex(tickUpperIndex, poolInitInfo.tickSpacing, poolInitInfo.whirlpoolPda.publicKey, ctx.program.programId).publicKey; - const whirlpoolPubkey = poolInitInfo.whirlpoolPda.publicKey; - const tokenOwnerAccountA = getAssociatedTokenAddressSync(poolInitInfo.tokenMintA, ctx.wallet.publicKey); - const tokenOwnerAccountB = getAssociatedTokenAddressSync(poolInitInfo.tokenMintB, ctx.wallet.publicKey); - - const tickArrayPda = PDAUtil.getTickArray(ctx.program.programId, whirlpoolPubkey, 22528); - const oraclePda = PDAUtil.getOracle(ctx.program.programId, whirlpoolPubkey); - - const modifyLiquidityParams = { - liquidityAmount, - position: bundledPositionPubkey, - positionAuthority: ctx.wallet.publicKey, - positionTokenAccount: positionBundleInfo.positionBundleTokenAccount, - tickArrayLower, - tickArrayUpper, - tokenOwnerAccountA, - tokenOwnerAccountB, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - whirlpool: whirlpoolPubkey, - } - - const depositAmounts = PoolUtil.getTokenAmountsFromLiquidity( - liquidityAmount, - (await ctx.fetcher.getPool(whirlpoolPubkey, IGNORE_CACHE))!.sqrtPrice, - PriceMath.tickIndexToSqrtPriceX64(tickLowerIndex), - PriceMath.tickIndexToSqrtPriceX64(tickUpperIndex), - true - ); - - const swapInput = new BN(200_000); - const poolLiquidity = new BN(liquidityAmount.muln(2).toString()); - const estimatedFee = new BN(swapInput.toString()) - .muln(3).divn(1000) // feeRate 0.3% - .muln(97).divn(100) // minus protocolFee 3% - .shln(64).div(poolLiquidity) // to X64 growth - .mul(liquidityAmount) - .shrn(64) - .toNumber(); - - const receiver = Keypair.generate(); - const receiverAtaA = await createTokenAccount(provider, poolInitInfo.tokenMintA, receiver.publicKey); - const receiverAtaB = await createTokenAccount(provider, poolInitInfo.tokenMintB, receiver.publicKey); - - const builder = new TransactionBuilder(ctx.connection, ctx.wallet, ctx.txBuilderOpts); - builder - .addInstruction(WhirlpoolIx.openBundledPositionIx(ctx.program, { - bundledPositionPda, - bundleIndex, - positionBundle: positionBundleInfo.positionBundlePda.publicKey, - positionBundleAuthority: ctx.wallet.publicKey, - positionBundleTokenAccount: positionBundleInfo.positionBundleTokenAccount, - tickLowerIndex, - tickUpperIndex, - whirlpool: whirlpoolPubkey, - funder: ctx.wallet.publicKey - })) - .addInstruction(WhirlpoolIx.increaseLiquidityIx(ctx.program, { - ...modifyLiquidityParams, - tokenMaxA: depositAmounts.tokenA, - tokenMaxB: depositAmounts.tokenB, - })) - .addInstruction(WhirlpoolIx.swapIx(ctx.program, { - amount: swapInput, - otherAmountThreshold: ZERO_BN, - sqrtPriceLimit: MathUtil.toX64(new Decimal(4)), - amountSpecifiedIsInput: true, - aToB: true, - whirlpool: whirlpoolPubkey, - tokenAuthority: ctx.wallet.publicKey, - tokenOwnerAccountA, - tokenOwnerAccountB, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArray0: tickArrayPda.publicKey, - tickArray1: tickArrayPda.publicKey, - tickArray2: tickArrayPda.publicKey, - oracle: oraclePda.publicKey, - })) - .addInstruction(WhirlpoolIx.swapIx(ctx.program, { - amount: swapInput, - otherAmountThreshold: ZERO_BN, - sqrtPriceLimit: MathUtil.toX64(new Decimal(5)), - amountSpecifiedIsInput: true, - aToB: false, - whirlpool: whirlpoolPubkey, - tokenAuthority: ctx.wallet.publicKey, - tokenOwnerAccountA, - tokenOwnerAccountB, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArray0: tickArrayPda.publicKey, - tickArray1: tickArrayPda.publicKey, - tickArray2: tickArrayPda.publicKey, - oracle: oraclePda.publicKey, - })) - .addInstruction(WhirlpoolIx.decreaseLiquidityIx(ctx.program, { - ...modifyLiquidityParams, - tokenMinA: new BN(0), - tokenMinB: new BN(0), - })) - .addInstruction(WhirlpoolIx.collectFeesIx(ctx.program, { - position: bundledPositionPubkey, - positionAuthority: ctx.wallet.publicKey, - positionTokenAccount: positionBundleInfo.positionBundleTokenAccount, - tokenOwnerAccountA: receiverAtaA, - tokenOwnerAccountB: receiverAtaB, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - whirlpool: whirlpoolPubkey, - })) - .addInstruction(WhirlpoolIx.closeBundledPositionIx(ctx.program, { - bundledPosition: bundledPositionPubkey, - bundleIndex, - positionBundle: positionBundleInfo.positionBundlePda.publicKey, - positionBundleAuthority: ctx.wallet.publicKey, - positionBundleTokenAccount: positionBundleInfo.positionBundleTokenAccount, - receiver: receiver.publicKey, - })); - - await builder.buildAndExecute(); - assert.ok((await ctx.fetcher.getTokenInfo(receiverAtaA, IGNORE_CACHE))!.amount === BigInt(estimatedFee.toString())); - assert.ok((await ctx.fetcher.getTokenInfo(receiverAtaB, IGNORE_CACHE))!.amount === BigInt(estimatedFee.toString())); - }); - }); - - describe("Ensuring that the account is closed", () => { - it("The discriminator of the deleted position bundle is marked as closed", async () => { - const ctx = testCtx.whirlpoolCtx; - - // initialize position bundle - const positionBundleInfo = await initializePositionBundle(ctx, ctx.wallet.publicKey); - - const preClose = await ctx.connection.getAccountInfo(positionBundleInfo.positionBundlePda.publicKey, "confirmed"); - assert.ok(preClose !== null); - const rentOfPositionBundle = preClose.lamports; - assert.ok(rentOfPositionBundle > 0); - - const builder = new TransactionBuilder(ctx.connection, ctx.wallet, ctx.txBuilderOpts); - builder - // close - .addInstruction(WhirlpoolIx.deletePositionBundleIx(ctx.program, { - positionBundle: positionBundleInfo.positionBundlePda.publicKey, - positionBundleMint: positionBundleInfo.positionBundleMintKeypair.publicKey, - positionBundleTokenAccount: positionBundleInfo.positionBundleTokenAccount, - owner: ctx.wallet.publicKey, - receiver: ctx.wallet.publicKey, - })) - // fund rent - .addInstruction({ - instructions: [ - SystemProgram.transfer({ - fromPubkey: ctx.wallet.publicKey, - toPubkey: positionBundleInfo.positionBundlePda.publicKey, - lamports: rentOfPositionBundle, - }) - ], - cleanupInstructions: [], - signers: [], - }); - await builder.buildAndExecute(); - - // Account closing reassigns to system program and reallocates - // https://github.com/coral-xyz/anchor/pull/2169 - const postClose = await ctx.connection.getAccountInfo(positionBundleInfo.positionBundlePda.publicKey, "confirmed"); - assert.ok(postClose !== null); - assert.ok(postClose.owner.equals(SystemProgram.programId)); - assert.ok(postClose.data.length === 0); - }); - - it("The owner of closed account should be system program", async () => { - // create test pool - const ctx = testCtx.whirlpoolCtx; - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing, - positions: [], - rewards: [], - }); - const { poolInitInfo, rewards } = fixture.getInfos(); - - // initialize position bundle - const positionBundleInfo = await initializePositionBundle(ctx, ctx.wallet.publicKey); - const bundleIndex = Math.floor(Math.random() * POSITION_BUNDLE_SIZE); - - const bundledPositionPda = PDAUtil.getBundledPosition(ctx.program.programId, positionBundleInfo.positionBundleMintKeypair.publicKey, bundleIndex); - const bundledPositionPubkey = bundledPositionPda.publicKey; - const whirlpoolPubkey = poolInitInfo.whirlpoolPda.publicKey; - - // open - await toTx( - ctx, - WhirlpoolIx.openBundledPositionIx(ctx.program, { - bundledPositionPda, - bundleIndex, - positionBundle: positionBundleInfo.positionBundlePda.publicKey, - positionBundleAuthority: ctx.wallet.publicKey, - positionBundleTokenAccount: positionBundleInfo.positionBundleTokenAccount, - tickLowerIndex, - tickUpperIndex, - whirlpool: whirlpoolPubkey, - funder: ctx.wallet.publicKey - }) - ).buildAndExecute(); - - const preClose = await ctx.connection.getAccountInfo(bundledPositionPubkey, "confirmed"); - assert.ok(preClose !== null); - const rentOfBundledPosition = preClose.lamports; - assert.ok(rentOfBundledPosition > 0); - - const builder = new TransactionBuilder(ctx.connection, ctx.wallet, ctx.txBuilderOpts); - builder - // close - .addInstruction(WhirlpoolIx.closeBundledPositionIx(ctx.program, { - bundledPosition: bundledPositionPubkey, - bundleIndex, - positionBundle: positionBundleInfo.positionBundlePda.publicKey, - positionBundleAuthority: ctx.wallet.publicKey, - positionBundleTokenAccount: positionBundleInfo.positionBundleTokenAccount, - receiver: whirlpoolPubkey, - })) - // fund rent - .addInstruction({ - instructions: [ - SystemProgram.transfer({ - fromPubkey: ctx.wallet.publicKey, - toPubkey: bundledPositionPubkey, - lamports: rentOfBundledPosition, - }) - ], - cleanupInstructions: [], - signers: [], - }); - await builder.buildAndExecute(); - - // Account closing reassigns to system program and reallocates - // https://github.com/coral-xyz/anchor/pull/2169 - const postClose = await ctx.connection.getAccountInfo(bundledPositionPubkey, "confirmed"); - assert.ok(postClose !== null); - assert.ok(postClose.owner.equals(SystemProgram.programId)); - assert.ok(postClose.data.length === 0); - }); - - it("should be failed: close bundled position and then updateFeesAndRewards in single Tx", async () => { - // create test pool - const ctx = testCtx.whirlpoolCtx; - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing, - positions: [], - rewards: [], - }); - const { poolInitInfo, rewards } = fixture.getInfos(); - - // initialize position bundle - const positionBundleInfo = await initializePositionBundle(ctx, ctx.wallet.publicKey); - const bundleIndex = Math.floor(Math.random() * POSITION_BUNDLE_SIZE); - - const bundledPositionPda = PDAUtil.getBundledPosition(ctx.program.programId, positionBundleInfo.positionBundleMintKeypair.publicKey, bundleIndex); - const bundledPositionPubkey = bundledPositionPda.publicKey; - const whirlpoolPubkey = poolInitInfo.whirlpoolPda.publicKey; - const tickArrayLower = PDAUtil.getTickArrayFromTickIndex(tickLowerIndex, poolInitInfo.tickSpacing, poolInitInfo.whirlpoolPda.publicKey, ctx.program.programId).publicKey; - const tickArrayUpper = PDAUtil.getTickArrayFromTickIndex(tickUpperIndex, poolInitInfo.tickSpacing, poolInitInfo.whirlpoolPda.publicKey, ctx.program.programId).publicKey; - - const builder = new TransactionBuilder(ctx.connection, ctx.wallet, ctx.txBuilderOpts); - builder - // open - .addInstruction(WhirlpoolIx.openBundledPositionIx(ctx.program, { - bundledPositionPda, - bundleIndex, - positionBundle: positionBundleInfo.positionBundlePda.publicKey, - positionBundleAuthority: ctx.wallet.publicKey, - positionBundleTokenAccount: positionBundleInfo.positionBundleTokenAccount, - tickLowerIndex, - tickUpperIndex, - whirlpool: whirlpoolPubkey, - funder: ctx.wallet.publicKey - })) - // close - .addInstruction(WhirlpoolIx.closeBundledPositionIx(ctx.program, { - bundledPosition: bundledPositionPubkey, - bundleIndex, - positionBundle: positionBundleInfo.positionBundlePda.publicKey, - positionBundleAuthority: ctx.wallet.publicKey, - positionBundleTokenAccount: positionBundleInfo.positionBundleTokenAccount, - receiver: whirlpoolPubkey, - })) - // try to use closed bundled position - .addInstruction(WhirlpoolIx.updateFeesAndRewardsIx(ctx.program, { - position: bundledPositionPubkey, - tickArrayLower, - tickArrayUpper, - whirlpool: whirlpoolPubkey, - })); - - await assert.rejects( - builder.buildAndExecute(), - /0xbc4/ // AccountNotInitialized - ); - }); - }); - -}); diff --git a/sdk/tests/integration/multi-ix/position_management.test.ts b/sdk/tests/integration/multi-ix/position_management.test.ts deleted file mode 100644 index 6e93e26..0000000 --- a/sdk/tests/integration/multi-ix/position_management.test.ts +++ /dev/null @@ -1,51 +0,0 @@ -import * as anchor from "@coral-xyz/anchor"; -import * as assert from "assert"; -import { toTx, WhirlpoolIx } from "../../../src"; -import { WhirlpoolContext } from "../../../src/context"; -import { TickSpacing } from "../../utils"; -import { defaultConfirmOptions } from "../../utils/const"; -import { initTestPool, openPosition } from "../../utils/init-utils"; -import { generateDefaultOpenPositionParams } from "../../utils/test-builders"; - -describe("position management tests", () => { - const provider = anchor.AnchorProvider.local(undefined, defaultConfirmOptions); - - const program = anchor.workspace.Whirlpool; - const ctx = WhirlpoolContext.fromWorkspace(provider, program); - const fetcher = ctx.fetcher; - - it("successfully closes and opens a position in one transaction", async () => { - const { poolInitInfo } = await initTestPool(ctx, TickSpacing.Standard); - - const { params } = await openPosition(ctx, poolInitInfo.whirlpoolPda.publicKey, 0, 128); - const receiverKeypair = anchor.web3.Keypair.generate(); - - const { params: newParams, mint } = await generateDefaultOpenPositionParams( - ctx, - poolInitInfo.whirlpoolPda.publicKey, - 0, - 128, - ctx.wallet.publicKey, - ctx.wallet.publicKey - ); - - await toTx( - ctx, - WhirlpoolIx.closePositionIx(ctx.program, { - positionAuthority: provider.wallet.publicKey, - receiver: receiverKeypair.publicKey, - position: params.positionPda.publicKey, - positionMint: params.positionMintAddress, - positionTokenAccount: params.positionTokenAccount, - }) - ) - .addInstruction(WhirlpoolIx.openPositionIx(ctx.program, newParams)) - .addSigner(mint) - .buildAndExecute(); - - const closedResponse = await provider.connection.getTokenSupply(params.positionMintAddress); - assert.equal(closedResponse.value.uiAmount, 0); - const openResponse = await provider.connection.getTokenSupply(newParams.positionMintAddress); - assert.equal(openResponse.value.uiAmount, 1); - }); -}); diff --git a/sdk/tests/integration/open_bundled_position.test.ts b/sdk/tests/integration/open_bundled_position.test.ts deleted file mode 100644 index 237efb8..0000000 --- a/sdk/tests/integration/open_bundled_position.test.ts +++ /dev/null @@ -1,606 +0,0 @@ -import * as anchor from "@coral-xyz/anchor"; -import { PDA } from "@orca-so/common-sdk"; -import { getAssociatedTokenAddressSync, TOKEN_PROGRAM_ID } from "@solana/spl-token"; -import { PublicKey, SystemProgram } from "@solana/web3.js"; -import * as assert from "assert"; -import { - InitPoolParams, - MAX_TICK_INDEX, - MIN_TICK_INDEX, - PDAUtil, - POSITION_BUNDLE_SIZE, - PositionBundleData, - PositionData, - toTx, - WhirlpoolContext, - WhirlpoolIx -} from "../../src"; -import { IGNORE_CACHE } from "../../src/network/public/fetcher"; -import { - approveToken, - createAssociatedTokenAccount, - ONE_SOL, - systemTransferTx, - TickSpacing, - transferToken, - ZERO_BN -} from "../utils"; -import { defaultConfirmOptions } from "../utils/const"; -import { initializePositionBundle, initTestPool, openBundledPosition } from "../utils/init-utils"; - -describe("open_bundled_position", () => { - const provider = anchor.AnchorProvider.local(undefined, defaultConfirmOptions); - - - const program = anchor.workspace.Whirlpool; - const ctx = WhirlpoolContext.fromWorkspace(provider, program); - const fetcher = ctx.fetcher; - - const tickLowerIndex = 0; - const tickUpperIndex = 128; - let poolInitInfo: InitPoolParams; - let whirlpoolPda: PDA; - const funderKeypair = anchor.web3.Keypair.generate(); - - before(async () => { - poolInitInfo = (await initTestPool(ctx, TickSpacing.Standard)).poolInitInfo; - whirlpoolPda = poolInitInfo.whirlpoolPda; - await systemTransferTx(provider, funderKeypair.publicKey, ONE_SOL).buildAndExecute(); - }); - - async function createOpenBundledPositionTx( - ctx: WhirlpoolContext, - positionBundleMint: PublicKey, - bundleIndex: number, - overwrite: any, - ) { - const bundledPositionPda = PDAUtil.getBundledPosition(ctx.program.programId, positionBundleMint, bundleIndex); - const positionBundle = PDAUtil.getPositionBundle(ctx.program.programId, positionBundleMint).publicKey; - const positionBundleTokenAccount = getAssociatedTokenAddressSync( - positionBundleMint, - ctx.wallet.publicKey - ); - const defaultAccounts = { - bundledPosition: bundledPositionPda.publicKey, - positionBundle, - positionBundleTokenAccount, - positionBundleAuthority: ctx.wallet.publicKey, - whirlpool: whirlpoolPda.publicKey, - funder: ctx.wallet.publicKey, - systemProgram: SystemProgram.programId, - rent: anchor.web3.SYSVAR_RENT_PUBKEY, - }; - - const ix = program.instruction.openBundledPosition(bundleIndex, tickLowerIndex, tickUpperIndex, { - accounts: { - ...defaultAccounts, - ...overwrite, - } - }); - - return toTx(ctx, { - instructions: [ix], - cleanupInstructions: [], - signers: [], - }); - } - - function checkPositionAccountContents(position: PositionData, mint: PublicKey) { - assert.strictEqual(position.tickLowerIndex, tickLowerIndex); - assert.strictEqual(position.tickUpperIndex, tickUpperIndex); - assert.ok(position.whirlpool.equals(poolInitInfo.whirlpoolPda.publicKey)); - assert.ok(position.positionMint.equals(mint)); - assert.ok(position.liquidity.eq(ZERO_BN)); - assert.ok(position.feeGrowthCheckpointA.eq(ZERO_BN)); - assert.ok(position.feeGrowthCheckpointB.eq(ZERO_BN)); - assert.ok(position.feeOwedA.eq(ZERO_BN)); - assert.ok(position.feeOwedB.eq(ZERO_BN)); - assert.ok(position.rewardInfos[0].amountOwed.eq(ZERO_BN)); - assert.ok(position.rewardInfos[1].amountOwed.eq(ZERO_BN)); - assert.ok(position.rewardInfos[2].amountOwed.eq(ZERO_BN)); - assert.ok(position.rewardInfos[0].growthInsideCheckpoint.eq(ZERO_BN)); - assert.ok(position.rewardInfos[1].growthInsideCheckpoint.eq(ZERO_BN)); - assert.ok(position.rewardInfos[2].growthInsideCheckpoint.eq(ZERO_BN)); - } - - function checkBitmapIsOpened(account: PositionBundleData, bundleIndex: number): boolean { - if (bundleIndex < 0 || bundleIndex >= POSITION_BUNDLE_SIZE) throw Error("bundleIndex is out of bounds"); - - const bitmapIndex = Math.floor(bundleIndex / 8); - const bitmapOffset = bundleIndex % 8; - return (account.positionBitmap[bitmapIndex] & (1 << bitmapOffset)) > 0; - } - - function checkBitmapIsClosed(account: PositionBundleData, bundleIndex: number): boolean { - if (bundleIndex < 0 || bundleIndex >= POSITION_BUNDLE_SIZE) throw Error("bundleIndex is out of bounds"); - - const bitmapIndex = Math.floor(bundleIndex / 8); - const bitmapOffset = bundleIndex % 8; - return (account.positionBitmap[bitmapIndex] & (1 << bitmapOffset)) === 0; - } - - function checkBitmap(account: PositionBundleData, openedBundleIndexes: number[]) { - for (let i = 0; i < POSITION_BUNDLE_SIZE; i++) { - if (openedBundleIndexes.includes(i)) { - assert.ok(checkBitmapIsOpened(account, i)); - } - else { - assert.ok(checkBitmapIsClosed(account, i)); - } - } - } - - it("successfully opens bundled position and verify position address contents", async () => { - const positionBundleInfo = await initializePositionBundle(ctx, ctx.wallet.publicKey); - - const bundleIndex = 0; - const positionInitInfo = await openBundledPosition( - ctx, - whirlpoolPda.publicKey, - positionBundleInfo.positionBundleMintKeypair.publicKey, - bundleIndex, - tickLowerIndex, - tickUpperIndex - ); - const { bundledPositionPda } = positionInitInfo.params; - - const position = (await fetcher.getPosition(bundledPositionPda.publicKey)) as PositionData; - checkPositionAccountContents(position, positionBundleInfo.positionBundleMintKeypair.publicKey); - - const positionBundle = (await fetcher.getPositionBundle(positionBundleInfo.positionBundlePda.publicKey, IGNORE_CACHE)) as PositionBundleData; - checkBitmap(positionBundle, [bundleIndex]); - }); - - it("successfully opens bundled position when funder is different than account paying for transaction fee", async () => { - const positionBundleInfo = await initializePositionBundle(ctx, ctx.wallet.publicKey); - - const preBalance = await ctx.connection.getBalance(ctx.wallet.publicKey); - - const bundleIndex = POSITION_BUNDLE_SIZE - 1; - const positionInitInfo = await openBundledPosition( - ctx, - whirlpoolPda.publicKey, - positionBundleInfo.positionBundleMintKeypair.publicKey, - bundleIndex, - tickLowerIndex, - tickUpperIndex, - ctx.wallet.publicKey, - funderKeypair, - ); - const { bundledPositionPda } = positionInitInfo.params; - - const postBalance = await ctx.connection.getBalance(ctx.wallet.publicKey); - const diffBalance = preBalance - postBalance; - const minRent = await ctx.connection.getMinimumBalanceForRentExemption(0); - assert.ok(diffBalance < minRent); // ctx.wallet didn't any rent - - const position = (await fetcher.getPosition(bundledPositionPda.publicKey)) as PositionData; - checkPositionAccountContents(position, positionBundleInfo.positionBundleMintKeypair.publicKey); - - const positionBundle = (await fetcher.getPositionBundle(positionBundleInfo.positionBundlePda.publicKey, IGNORE_CACHE)) as PositionBundleData; - checkBitmap(positionBundle, [bundleIndex]); - }); - - it("successfully opens multiple bundled position and verify bitmap", async () => { - const positionBundleInfo = await initializePositionBundle(ctx, ctx.wallet.publicKey); - - const bundleIndexes = [1, 7, 8, 64, 127, 128, 254, 255]; - for (const bundleIndex of bundleIndexes) { - const positionInitInfo = await openBundledPosition( - ctx, - whirlpoolPda.publicKey, - positionBundleInfo.positionBundleMintKeypair.publicKey, - bundleIndex, - tickLowerIndex, - tickUpperIndex - ); - const { bundledPositionPda } = positionInitInfo.params; - - const position = (await fetcher.getPosition(bundledPositionPda.publicKey)) as PositionData; - checkPositionAccountContents(position, positionBundleInfo.positionBundleMintKeypair.publicKey); - } - - const positionBundle = (await fetcher.getPositionBundle(positionBundleInfo.positionBundlePda.publicKey, IGNORE_CACHE)) as PositionBundleData; - checkBitmap(positionBundle, bundleIndexes); - }); - - describe("invalid bundle index", () => { - it("should be failed: invalid bundle index (< 0)", async () => { - const positionBundleInfo = await initializePositionBundle(ctx, ctx.wallet.publicKey); - - const bundleIndex = -1; - await assert.rejects( - openBundledPosition( - ctx, - whirlpoolPda.publicKey, - positionBundleInfo.positionBundleMintKeypair.publicKey, - bundleIndex, - tickLowerIndex, - tickUpperIndex, - ), - /It must be >= 0 and <= 65535/ // rejected by client - ); - }); - - it("should be failed: invalid bundle index (POSITION_BUNDLE_SIZE)", async () => { - const positionBundleInfo = await initializePositionBundle(ctx, ctx.wallet.publicKey); - - const bundleIndex = POSITION_BUNDLE_SIZE; - await assert.rejects( - openBundledPosition( - ctx, - whirlpoolPda.publicKey, - positionBundleInfo.positionBundleMintKeypair.publicKey, - bundleIndex, - tickLowerIndex, - tickUpperIndex, - ), - /0x179b/ // InvalidBundleIndex - ); - }); - - - it("should be failed: invalid bundle index (u16 max)", async () => { - const positionBundleInfo = await initializePositionBundle(ctx, ctx.wallet.publicKey); - - const bundleIndex = 2 ** 16 - 1; - await assert.rejects( - openBundledPosition( - ctx, - whirlpoolPda.publicKey, - positionBundleInfo.positionBundleMintKeypair.publicKey, - bundleIndex, - tickLowerIndex, - tickUpperIndex, - ), - /0x179b/ // InvalidBundleIndex - ); - }); - }); - - describe("invalid tick index", () => { - async function assertTicksFail(lowerTick: number, upperTick: number) { - const positionBundleInfo = await initializePositionBundle(ctx, ctx.wallet.publicKey); - const bundleIndex = 0; - await assert.rejects( - openBundledPosition( - ctx, - whirlpoolPda.publicKey, - positionBundleInfo.positionBundleMintKeypair.publicKey, - bundleIndex, - lowerTick, - upperTick, - provider.wallet.publicKey, - funderKeypair - ), - /0x177a/ // InvalidTickIndex - ); - } - - it("should be failed: user pass in an out of bound tick index for upper-index", async () => { - await assertTicksFail(0, MAX_TICK_INDEX + 1); - }); - - it("should be failed: user pass in a lower tick index that is higher than the upper-index", async () => { - await assertTicksFail(-22534, -22534 - 1); - }); - - it("should be failed: user pass in a lower tick index that equals the upper-index", async () => { - await assertTicksFail(22365, 22365); - }); - - it("should be failed: user pass in an out of bound tick index for lower-index", async () => { - await assertTicksFail(MIN_TICK_INDEX - 1, 0); - }); - - it("should be failed: user pass in a non-initializable tick index for upper-index", async () => { - await assertTicksFail(0, 1); - }); - - it("should be failed: user pass in a non-initializable tick index for lower-index", async () => { - await assertTicksFail(1, 2); - }); - }); - - it("should be fail: user opens bundled position with bundle index whose state is opened", async () => { - const positionBundleInfo = await initializePositionBundle(ctx, ctx.wallet.publicKey); - - const bundleIndex = 0; - await openBundledPosition( - ctx, - whirlpoolPda.publicKey, - positionBundleInfo.positionBundleMintKeypair.publicKey, - bundleIndex, - tickLowerIndex, - tickUpperIndex - ); - - const positionBundle = (await fetcher.getPositionBundle(positionBundleInfo.positionBundlePda.publicKey, IGNORE_CACHE)) as PositionBundleData; - assert.ok(checkBitmapIsOpened(positionBundle, bundleIndex)); - - await assert.rejects( - openBundledPosition( - ctx, - whirlpoolPda.publicKey, - positionBundleInfo.positionBundleMintKeypair.publicKey, - bundleIndex, - tickLowerIndex, - tickUpperIndex - ), - (err) => { return JSON.stringify(err).includes("already in use") } - ); - }); - - describe("invalid input account", () => { - it("should be failed: invalid bundled position", async () => { - const positionBundleInfo = await initializePositionBundle(ctx, ctx.wallet.publicKey); - - const tx = await createOpenBundledPositionTx( - ctx, positionBundleInfo.positionBundleMintKeypair.publicKey, 0, { - // invalid parameter - bundledPosition: PDAUtil.getBundledPosition( - ctx.program.programId, - positionBundleInfo.positionBundleMintKeypair.publicKey, - 1 // another bundle index - ).publicKey - } - ); - - await assert.rejects( - tx.buildAndExecute(), - /0x7d6/ // ConstraintSeeds - ); - }); - - it("should be failed: invalid position bundle", async () => { - const positionBundleInfo = await initializePositionBundle(ctx, ctx.wallet.publicKey); - const otherPositionBundleInfo = await initializePositionBundle(ctx, ctx.wallet.publicKey); - - const tx = await createOpenBundledPositionTx( - ctx, positionBundleInfo.positionBundleMintKeypair.publicKey, 0, { - // invalid parameter - positionBundle: otherPositionBundleInfo.positionBundlePda.publicKey, - } - ); - - await assert.rejects( - tx.buildAndExecute(), - /0x7d6/ // ConstraintSeeds - ); - }); - - it("should be failed: invalid ATA (amount is zero)", async () => { - const positionBundleInfo = await initializePositionBundle(ctx, funderKeypair.publicKey, funderKeypair); - - const ata = await createAssociatedTokenAccount( - provider, - positionBundleInfo.positionBundleMintKeypair.publicKey, - ctx.wallet.publicKey, - ctx.wallet.publicKey - ); - - const tx = await createOpenBundledPositionTx( - ctx, positionBundleInfo.positionBundleMintKeypair.publicKey, 0, { - // invalid parameter - positionBundleTokenAccount: ata, - } - ); - - await assert.rejects( - tx.buildAndExecute(), - /0x7d3/ // ConstraintRaw (amount == 1) - ); - }); - - it("should be failed: invalid ATA (invalid mint)", async () => { - const positionBundleInfo = await initializePositionBundle(ctx, funderKeypair.publicKey, funderKeypair); - const otherPositionBundleInfo = await initializePositionBundle(ctx, ctx.wallet.publicKey); - - const tx = await createOpenBundledPositionTx( - ctx, positionBundleInfo.positionBundleMintKeypair.publicKey, 0, { - // invalid parameter - positionBundleTokenAccount: otherPositionBundleInfo.positionBundleTokenAccount, - } - ); - - await assert.rejects( - tx.buildAndExecute(), - /0x7d3/ // ConstraintRaw (mint == position_bundle.position_bundle_mint) - ); - }); - - it("should be failed: invalid position bundle authority", async () => { - const positionBundleInfo = await initializePositionBundle(ctx, funderKeypair.publicKey, funderKeypair); - - const tx = await createOpenBundledPositionTx( - ctx, positionBundleInfo.positionBundleMintKeypair.publicKey, 0, { - positionBundleTokenAccount: positionBundleInfo.positionBundleTokenAccount, - // invalid parameter - positionBundleAuthority: ctx.wallet.publicKey, - } - ); - - await assert.rejects( - tx.buildAndExecute(), - /0x1783/ // MissingOrInvalidDelegate - ); - }); - - it("should be failed: invalid whirlpool", async () => { - const positionBundleInfo = await initializePositionBundle(ctx); - - const tx = await createOpenBundledPositionTx( - ctx, positionBundleInfo.positionBundleMintKeypair.publicKey, 0, { - // invalid parameter - whirlpool: positionBundleInfo.positionBundlePda.publicKey, - } - ); - - await assert.rejects( - tx.buildAndExecute(), - /0xbba/ // AccountDiscriminatorMismatch - ); - }); - - - it("should be failed: invalid system program", async () => { - const positionBundleInfo = await initializePositionBundle(ctx); - - const tx = await createOpenBundledPositionTx( - ctx, positionBundleInfo.positionBundleMintKeypair.publicKey, 0, { - // invalid parameter - systemProgram: TOKEN_PROGRAM_ID, - } - ); - - await assert.rejects( - tx.buildAndExecute(), - /0xbc0/ // InvalidProgramId - ); - }); - - it("should be failed: invalid rent", async () => { - const positionBundleInfo = await initializePositionBundle(ctx); - - const tx = await createOpenBundledPositionTx( - ctx, positionBundleInfo.positionBundleMintKeypair.publicKey, 0, { - // invalid parameter - rent: anchor.web3.SYSVAR_CLOCK_PUBKEY, - } - ); - - await assert.rejects( - tx.buildAndExecute(), - /0xbc7/ // AccountSysvarMismatch - ); - }); - }); - - describe("authority delegation", () => { - it("successfully opens bundled position with delegated authority", async () => { - const positionBundleInfo = await initializePositionBundle(ctx, funderKeypair.publicKey, funderKeypair); - - const tx = await createOpenBundledPositionTx( - ctx, positionBundleInfo.positionBundleMintKeypair.publicKey, 0, { - positionBundleTokenAccount: positionBundleInfo.positionBundleTokenAccount, - positionBundleAuthority: ctx.wallet.publicKey, - } - ); - - await assert.rejects( - tx.buildAndExecute(), - /0x1783/ // MissingOrInvalidDelegate - ); - - // delegate 1 token from funder to ctx.wallet - await approveToken( - provider, - positionBundleInfo.positionBundleTokenAccount, - ctx.wallet.publicKey, - 1, - funderKeypair - ); - await tx.buildAndExecute(); - const positionBundle = await fetcher.getPositionBundle(positionBundleInfo.positionBundlePda.publicKey, IGNORE_CACHE); - checkBitmapIsOpened(positionBundle!, 0); - }); - - it("successfully opens bundled position even if delegation exists", async () => { - const positionBundleInfo = await initializePositionBundle(ctx); - - const tx = await createOpenBundledPositionTx( - ctx, positionBundleInfo.positionBundleMintKeypair.publicKey, 0, { - positionBundleTokenAccount: positionBundleInfo.positionBundleTokenAccount, - positionBundleAuthority: ctx.wallet.publicKey, - } - ); - - // delegate 1 token from ctx.wallet to funder - await approveToken( - provider, - positionBundleInfo.positionBundleTokenAccount, - funderKeypair.publicKey, - 1, - ); - // owner can open even if delegation exists - await tx.buildAndExecute(); - const positionBundle = await fetcher.getPositionBundle(positionBundleInfo.positionBundlePda.publicKey, IGNORE_CACHE); - checkBitmapIsOpened(positionBundle!, 0); - }); - - - it("should be failed: delegated amount is zero", async () => { - const positionBundleInfo = await initializePositionBundle(ctx, funderKeypair.publicKey, funderKeypair); - - const tx = await createOpenBundledPositionTx( - ctx, positionBundleInfo.positionBundleMintKeypair.publicKey, 0, { - positionBundleTokenAccount: positionBundleInfo.positionBundleTokenAccount, - positionBundleAuthority: ctx.wallet.publicKey, - } - ); - - await assert.rejects( - tx.buildAndExecute(), - /0x1783/ // MissingOrInvalidDelegate - ); - - // delegate ZERO token from funder to ctx.wallet - await approveToken( - provider, - positionBundleInfo.positionBundleTokenAccount, - ctx.wallet.publicKey, - 0, - funderKeypair - ); - - await assert.rejects( - tx.buildAndExecute(), - /0x1784/ // InvalidPositionTokenAmount - ); - }); - }); - - describe("transfer position bundle", () => { - it("successfully opens bundled position after position bundle token transfer", async () => { - const positionBundleInfo = await initializePositionBundle(ctx); - - const funderATA = await createAssociatedTokenAccount( - provider, - positionBundleInfo.positionBundleMintKeypair.publicKey, - funderKeypair.publicKey, - ctx.wallet.publicKey, - ); - - await transferToken( - provider, - positionBundleInfo.positionBundleTokenAccount, - funderATA, - 1 - ); - - const tokenInfo = await fetcher.getTokenInfo(funderATA, IGNORE_CACHE); - assert.ok(tokenInfo?.amount === 1n); - - const tx = toTx( - ctx, - WhirlpoolIx.openBundledPositionIx(ctx.program, { - bundledPositionPda: PDAUtil.getBundledPosition(ctx.program.programId, positionBundleInfo.positionBundleMintKeypair.publicKey, 0), - bundleIndex: 0, - funder: funderKeypair.publicKey, - positionBundle: positionBundleInfo.positionBundlePda.publicKey, - positionBundleAuthority: funderKeypair.publicKey, - positionBundleTokenAccount: funderATA, - tickLowerIndex, - tickUpperIndex, - whirlpool: whirlpoolPda.publicKey, - }) - ); - tx.addSigner(funderKeypair); - - await tx.buildAndExecute(); - const positionBundle = await fetcher.getPositionBundle(positionBundleInfo.positionBundlePda.publicKey, IGNORE_CACHE); - checkBitmapIsOpened(positionBundle!, 0); - }); - }); - -}); diff --git a/sdk/tests/integration/open_position.test.ts b/sdk/tests/integration/open_position.test.ts deleted file mode 100644 index b83511b..0000000 --- a/sdk/tests/integration/open_position.test.ts +++ /dev/null @@ -1,214 +0,0 @@ -import * as anchor from "@coral-xyz/anchor"; -import { web3 } from "@coral-xyz/anchor"; -import { PDA } from "@orca-so/common-sdk"; -import { getAccount, getAssociatedTokenAddressSync } from "@solana/spl-token"; -import { Keypair } from "@solana/web3.js"; -import * as assert from "assert"; -import { - InitPoolParams, - MAX_TICK_INDEX, - MIN_TICK_INDEX, - OpenPositionParams, - PDAUtil, - PositionData, - WhirlpoolContext, - WhirlpoolIx, - toTx -} from "../../src"; -import { - ONE_SOL, - TickSpacing, - ZERO_BN, - createMint, - createMintInstructions, - mintToDestination, - systemTransferTx -} from "../utils"; -import { defaultConfirmOptions } from "../utils/const"; -import { initTestPool, openPosition } from "../utils/init-utils"; -import { generateDefaultOpenPositionParams } from "../utils/test-builders"; - -describe("open_position", () => { - const provider = anchor.AnchorProvider.local(undefined, defaultConfirmOptions); - - const program = anchor.workspace.Whirlpool; - const ctx = WhirlpoolContext.fromWorkspace(provider, program); - const fetcher = ctx.fetcher; - - let defaultParams: OpenPositionParams; - let defaultMint: Keypair; - const tickLowerIndex = 0; - const tickUpperIndex = 128; - let poolInitInfo: InitPoolParams; - let whirlpoolPda: PDA; - const funderKeypair = anchor.web3.Keypair.generate(); - - before(async () => { - poolInitInfo = (await initTestPool(ctx, TickSpacing.Standard)).poolInitInfo; - whirlpoolPda = poolInitInfo.whirlpoolPda; - - const { params, mint } = await generateDefaultOpenPositionParams( - ctx, - whirlpoolPda.publicKey, - 0, - 128, - provider.wallet.publicKey - ); - defaultParams = params; - defaultMint = mint; - await systemTransferTx(provider, funderKeypair.publicKey, ONE_SOL).buildAndExecute(); - }); - - it("successfully opens position and verify position address contents", async () => { - const positionInitInfo = await openPosition( - ctx, - whirlpoolPda.publicKey, - tickLowerIndex, - tickUpperIndex - ); - const { positionPda, positionMintAddress } = positionInitInfo.params; - - const position = (await fetcher.getPosition(positionPda.publicKey)) as PositionData; - - assert.strictEqual(position.tickLowerIndex, tickLowerIndex); - assert.strictEqual(position.tickUpperIndex, tickUpperIndex); - assert.ok(position.whirlpool.equals(poolInitInfo.whirlpoolPda.publicKey)); - assert.ok(position.positionMint.equals(positionMintAddress)); - assert.ok(position.liquidity.eq(ZERO_BN)); - assert.ok(position.feeGrowthCheckpointA.eq(ZERO_BN)); - assert.ok(position.feeGrowthCheckpointB.eq(ZERO_BN)); - assert.ok(position.feeOwedA.eq(ZERO_BN)); - assert.ok(position.feeOwedB.eq(ZERO_BN)); - - // TODO: Add tests for rewards - }); - - it("succeeds when funder is different than account paying for transaction fee", async () => { - await openPosition( - ctx, - whirlpoolPda.publicKey, - tickLowerIndex, - tickUpperIndex, - provider.wallet.publicKey, - funderKeypair - ); - }); - - it("open position & verify position mint behavior", async () => { - const newOwner = web3.Keypair.generate(); - - const positionInitInfo = await openPosition( - ctx, - whirlpoolPda.publicKey, - tickLowerIndex, - tickUpperIndex, - newOwner.publicKey - ); - const { positionMintAddress, positionTokenAccount: positionTokenAccountAddress } = - positionInitInfo.params; - - const userTokenAccount = await getAccount(ctx.connection, positionTokenAccountAddress); - assert.ok(userTokenAccount.amount === 1n); - assert.ok(userTokenAccount.owner.equals(newOwner.publicKey)); - - await assert.rejects( - mintToDestination(provider, positionMintAddress, positionTokenAccountAddress, 1), - /0x5/ // the total supply of this token is fixed - ); - }); - - it("user must pass the valid token ATA account", async () => { - const anotherMintKey = await createMint(provider, provider.wallet.publicKey); - const positionTokenAccountAddress = getAssociatedTokenAddressSync(anotherMintKey, provider.wallet.publicKey) - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.openPositionIx(ctx.program, { - ...defaultParams, - positionTokenAccount: positionTokenAccountAddress, - }) - ) - .addSigner(defaultMint) - .buildAndExecute(), - /An account required by the instruction is missing/ - ); - }); - - describe("invalid ticks", () => { - async function assertTicksFail(lowerTick: number, upperTick: number) { - await assert.rejects( - openPosition( - ctx, - whirlpoolPda.publicKey, - lowerTick, - upperTick, - provider.wallet.publicKey, - funderKeypair - ), - /0x177a/ // InvalidTickIndex - ); - } - - it("fail when user pass in an out of bound tick index for upper-index", async () => { - await assertTicksFail(0, MAX_TICK_INDEX + 1); - }); - - it("fail when user pass in a lower tick index that is higher than the upper-index", async () => { - await assertTicksFail(-22534, -22534 - 1); - }); - - it("fail when user pass in a lower tick index that equals the upper-index", async () => { - await assertTicksFail(22365, 22365); - }); - - it("fail when user pass in an out of bound tick index for lower-index", async () => { - await assertTicksFail(MIN_TICK_INDEX - 1, 0); - }); - - it("fail when user pass in a non-initializable tick index for upper-index", async () => { - await assertTicksFail(0, 1); - }); - - it("fail when user pass in a non-initializable tick index for lower-index", async () => { - await assertTicksFail(1, 2); - }); - }); - - it("fail when position mint already exists", async () => { - const positionMintKeypair = anchor.web3.Keypair.generate(); - const positionPda = PDAUtil.getPosition(ctx.program.programId, positionMintKeypair.publicKey); - - const positionTokenAccountAddress = getAssociatedTokenAddressSync(positionMintKeypair.publicKey, provider.wallet.publicKey) - - const tx = new web3.Transaction(); - tx.add( - ...(await createMintInstructions( - provider, - provider.wallet.publicKey, - positionMintKeypair.publicKey - )) - ); - - await provider.sendAndConfirm(tx, [positionMintKeypair], { commitment: "confirmed" }); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.openPositionIx(ctx.program, { - funder: provider.wallet.publicKey, - owner: provider.wallet.publicKey, - positionPda, - positionMintAddress: positionMintKeypair.publicKey, - positionTokenAccount: positionTokenAccountAddress, - whirlpool: whirlpoolPda.publicKey, - tickLowerIndex: 0, - tickUpperIndex: 128, - }) - ) - .addSigner(positionMintKeypair) - .buildAndExecute(), - /0x0/ - ); - }); -}); diff --git a/sdk/tests/integration/open_position_with_metadata.test.ts b/sdk/tests/integration/open_position_with_metadata.test.ts deleted file mode 100644 index 0988ffd..0000000 --- a/sdk/tests/integration/open_position_with_metadata.test.ts +++ /dev/null @@ -1,341 +0,0 @@ -import * as anchor from "@coral-xyz/anchor"; -import { web3 } from "@coral-xyz/anchor"; -import { Metadata } from "@metaplex-foundation/mpl-token-metadata"; -import { PDA, TransactionBuilder } from "@orca-so/common-sdk"; -import { TOKEN_PROGRAM_ID, getAccount, getAssociatedTokenAddressSync } from "@solana/spl-token"; -import { Keypair, PublicKey } from "@solana/web3.js"; -import * as assert from "assert"; -import { - InitPoolParams, - MAX_TICK_INDEX, - METADATA_PROGRAM_ADDRESS, - MIN_TICK_INDEX, - OpenPositionParams, - OpenPositionWithMetadataBumpsData, - PDAUtil, - PositionData, - WhirlpoolContext, - WhirlpoolIx, - toTx -} from "../../src"; -import { openPositionAccounts } from "../../src/utils/instructions-util"; -import { - ONE_SOL, - TickSpacing, - ZERO_BN, - createMint, - createMintInstructions, - mintToDestination, - systemTransferTx -} from "../utils"; -import { defaultConfirmOptions } from "../utils/const"; -import { initTestPool, openPositionWithMetadata } from "../utils/init-utils"; -import { generateDefaultOpenPositionParams } from "../utils/test-builders"; - -describe("open_position_with_metadata", () => { - const provider = anchor.AnchorProvider.local(undefined, defaultConfirmOptions); - - const program = anchor.workspace.Whirlpool; - const ctx = WhirlpoolContext.fromWorkspace(provider, program); - const fetcher = ctx.fetcher; - - let defaultParams: Required; - let defaultMint: Keypair; - const tickLowerIndex = 0; - const tickUpperIndex = 128; - let poolInitInfo: InitPoolParams; - let whirlpoolPda: PDA; - const funderKeypair = anchor.web3.Keypair.generate(); - - before(async () => { - poolInitInfo = (await initTestPool(ctx, TickSpacing.Standard)).poolInitInfo; - whirlpoolPda = poolInitInfo.whirlpoolPda; - - const { params, mint } = await generateDefaultOpenPositionParams( - ctx, - whirlpoolPda.publicKey, - 0, - 128, - provider.wallet.publicKey - ); - defaultParams = params; - defaultMint = mint; - await systemTransferTx(provider, funderKeypair.publicKey, ONE_SOL).buildAndExecute(); - }); - - async function checkMetadata(metadataPda: PDA | undefined, positionMint: PublicKey) { - assert.ok(metadataPda != null); - - const metadata = await Metadata.fromAccountAddress(provider.connection, metadataPda.publicKey); - assert.ok(metadata.updateAuthority.toBase58() === "3axbTs2z5GBy6usVbNVoqEgZMng3vZvMnAoX29BFfwhr"); - assert.ok(metadata.mint.toBase58() === positionMint.toString()); - assert.ok( - metadata.data.uri.replace(/\0/g, '') === `https://arweave.net/E19ZNY2sqMqddm1Wx7mrXPUZ0ZZ5ISizhebb0UsVEws` - ); - } - - it("successfully opens position and verify position address contents", async () => { - const positionInitInfo = await openPositionWithMetadata( - ctx, - whirlpoolPda.publicKey, - tickLowerIndex, - tickUpperIndex - ); - const { positionPda, metadataPda, positionMintAddress } = positionInitInfo.params; - const position = (await fetcher.getPosition(positionPda.publicKey)) as PositionData; - - assert.strictEqual(position.tickLowerIndex, tickLowerIndex); - assert.strictEqual(position.tickUpperIndex, tickUpperIndex); - assert.ok(position.whirlpool.equals(poolInitInfo.whirlpoolPda.publicKey)); - assert.ok(position.positionMint.equals(positionMintAddress)); - assert.ok(position.liquidity.eq(ZERO_BN)); - assert.ok(position.feeGrowthCheckpointA.eq(ZERO_BN)); - assert.ok(position.feeGrowthCheckpointB.eq(ZERO_BN)); - assert.ok(position.feeOwedA.eq(ZERO_BN)); - assert.ok(position.feeOwedB.eq(ZERO_BN)); - - await checkMetadata(metadataPda, position.positionMint); - // TODO: Add tests for rewards - }); - - it("succeeds when funder is different than account paying for transaction fee", async () => { - const { params } = await openPositionWithMetadata( - ctx, - whirlpoolPda.publicKey, - tickLowerIndex, - tickUpperIndex, - provider.wallet.publicKey, - funderKeypair - ); - - await checkMetadata(params.metadataPda, params.positionMintAddress); - }); - - it("open position & verify position mint behavior", async () => { - const newOwner = web3.Keypair.generate(); - - const positionInitInfo = await openPositionWithMetadata( - ctx, - whirlpoolPda.publicKey, - tickLowerIndex, - tickUpperIndex, - newOwner.publicKey - ); - const { - metadataPda, - positionMintAddress, - positionTokenAccount: positionTokenAccountAddress, - } = positionInitInfo.params; - - await checkMetadata(metadataPda, positionMintAddress); - - const userTokenAccount = await getAccount(ctx.connection, positionTokenAccountAddress); - assert.ok(userTokenAccount.amount === 1n); - assert.ok(userTokenAccount.owner.equals(newOwner.publicKey)); - - await assert.rejects( - mintToDestination(provider, positionMintAddress, positionTokenAccountAddress, 1), - /0x5/ // the total supply of this token is fixed - ); - }); - - it("user must pass the valid token ATA account", async () => { - const anotherMintKey = await createMint(provider, provider.wallet.publicKey); - const positionTokenAccountAddress = getAssociatedTokenAddressSync(anotherMintKey, provider.wallet.publicKey) - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.openPositionWithMetadataIx(ctx.program, { - ...defaultParams, - positionTokenAccount: positionTokenAccountAddress, - }) - ) - .addSigner(defaultMint) - .buildAndExecute(), - /An account required by the instruction is missing/ - ); - }); - - describe("invalid ticks", () => { - async function assertTicksFail(lowerTick: number, upperTick: number) { - await assert.rejects( - openPositionWithMetadata( - ctx, - whirlpoolPda.publicKey, - lowerTick, - upperTick, - provider.wallet.publicKey, - funderKeypair - ), - /0x177a/ // InvalidTickIndex - ); - } - - it("fail when user pass in an out of bound tick index for upper-index", async () => { - await assertTicksFail(0, MAX_TICK_INDEX + 1); - }); - - it("fail when user pass in a lower tick index that is higher than the upper-index", async () => { - await assertTicksFail(-22534, -22534 - 1); - }); - - it("fail when user pass in a lower tick index that equals the upper-index", async () => { - await assertTicksFail(22365, 22365); - }); - - it("fail when user pass in an out of bound tick index for lower-index", async () => { - await assertTicksFail(MIN_TICK_INDEX - 1, 0); - }); - - it("fail when user pass in a non-initializable tick index for upper-index", async () => { - await assertTicksFail(0, 1); - }); - - it("fail when user pass in a non-initializable tick index for lower-index", async () => { - await assertTicksFail(1, 2); - }); - }); - - it("fail when position mint already exists", async () => { - const positionMintKeypair = anchor.web3.Keypair.generate(); - const positionPda = PDAUtil.getPosition(ctx.program.programId, positionMintKeypair.publicKey); - const metadataPda = PDAUtil.getPositionMetadata(positionMintKeypair.publicKey); - - const positionTokenAccountAddress = getAssociatedTokenAddressSync(positionMintKeypair.publicKey, provider.wallet.publicKey); - - const tx = new web3.Transaction(); - tx.add( - ...(await createMintInstructions( - provider, - provider.wallet.publicKey, - positionMintKeypair.publicKey - )) - ); - - await provider.sendAndConfirm(tx, [positionMintKeypair], { commitment: "confirmed" }); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.openPositionWithMetadataIx(ctx.program, { - ...defaultParams, - positionPda, - metadataPda, - positionMintAddress: positionMintKeypair.publicKey, - positionTokenAccount: positionTokenAccountAddress, - whirlpool: whirlpoolPda.publicKey, - tickLowerIndex, - tickUpperIndex, - }) - ) - .addSigner(positionMintKeypair) - .buildAndExecute(), - /0x0/ - ); - }); - - describe("invalid account constraints", () => { - function buildOpenWithAccountOverrides( - overrides: Partial< - ReturnType & { - positionMetadataAccount: PublicKey; - metadataProgram: PublicKey; - metadataUpdateAuth: PublicKey; - } - > - ) { - const { positionPda, metadataPda, tickLowerIndex, tickUpperIndex } = defaultParams; - - const bumps: OpenPositionWithMetadataBumpsData = { - positionBump: positionPda.bump, - metadataBump: metadataPda.bump, - }; - - const ix = ctx.program.instruction.openPositionWithMetadata( - bumps, - tickLowerIndex, - tickUpperIndex, - { - accounts: { - ...openPositionAccounts(defaultParams), - positionMetadataAccount: metadataPda.publicKey, - metadataProgram: METADATA_PROGRAM_ADDRESS, - metadataUpdateAuth: new PublicKey("3axbTs2z5GBy6usVbNVoqEgZMng3vZvMnAoX29BFfwhr"), - ...overrides, - }, - } - ); - - return { - instructions: [ix], - cleanupInstructions: [], - signers: [], - }; - } - - it("fails with non-mint metadataPda", async () => { - const notMintKeypair = Keypair.generate(); - const invalidParams = { - ...defaultParams, - metadataPda: PDAUtil.getPositionMetadata(notMintKeypair.publicKey), - }; - - await assert.rejects( - toTx(ctx, WhirlpoolIx.openPositionWithMetadataIx(ctx.program, invalidParams)) - .addSigner(defaultMint) - .buildAndExecute(), - // Invalid Metadata Key - // https://github.com/metaplex-foundation/metaplex-program-library/blob/master/token-metadata/program/src/error.rs#L36 - /0x5/ - ); - }); - - it("fails with non-program metadata program", async () => { - const notMetadataProgram = Keypair.generate(); - const tx = new TransactionBuilder(ctx.provider.connection, ctx.wallet, ctx.txBuilderOpts).addInstruction( - buildOpenWithAccountOverrides({ - metadataProgram: notMetadataProgram.publicKey, - }) - ); - - await assert.rejects( - tx.addSigner(defaultMint).buildAndExecute(), - // AddressConstraint - // https://github.com/project-serum/anchor/blob/master/lang/src/error.rs#L84 - /0x7dc/ - ); - }); - - it("fails with non-metadata program ", async () => { - const tx = new TransactionBuilder(ctx.provider.connection, ctx.wallet, ctx.txBuilderOpts).addInstruction( - buildOpenWithAccountOverrides({ - metadataProgram: TOKEN_PROGRAM_ID, - }) - ); - - await assert.rejects( - tx.addSigner(defaultMint).buildAndExecute(), - // AddressConstraint - // https://github.com/project-serum/anchor/blob/master/lang/src/error.rs#L84 - /0x7dc/ - ); - }); - - it("fails with non-valid update_authority program", async () => { - const notUpdateAuth = Keypair.generate(); - const tx = new TransactionBuilder(ctx.provider.connection, ctx.wallet, ctx.txBuilderOpts).addInstruction( - buildOpenWithAccountOverrides({ - metadataUpdateAuth: notUpdateAuth.publicKey, - }) - ); - - await assert.rejects( - tx.addSigner(defaultMint).buildAndExecute(), - // AddressConstraint - // https://github.com/project-serum/anchor/blob/master/lang/src/error.rs#L84 - /0x7dc/ - ); - }); - }); -}); diff --git a/sdk/tests/integration/set_collect_protocol_fee_authority.test.ts b/sdk/tests/integration/set_collect_protocol_fee_authority.test.ts deleted file mode 100644 index f302570..0000000 --- a/sdk/tests/integration/set_collect_protocol_fee_authority.test.ts +++ /dev/null @@ -1,73 +0,0 @@ -import * as anchor from "@coral-xyz/anchor"; -import * as assert from "assert"; -import { toTx, WhirlpoolContext, WhirlpoolIx, WhirlpoolsConfigData } from "../../src"; -import { defaultConfirmOptions } from "../utils/const"; -import { generateDefaultConfigParams } from "../utils/test-builders"; - -describe("set_collect_protocol_fee_authority", () => { - const provider = anchor.AnchorProvider.local(undefined, defaultConfirmOptions); - - const program = anchor.workspace.Whirlpool; - const ctx = WhirlpoolContext.fromWorkspace(provider, program); - const fetcher = ctx.fetcher; - - it("successfully set_collect_protocol_fee_authority", async () => { - const { - configInitInfo, - configKeypairs: { collectProtocolFeesAuthorityKeypair }, - } = generateDefaultConfigParams(ctx); - await toTx(ctx, WhirlpoolIx.initializeConfigIx(ctx.program, configInitInfo)).buildAndExecute(); - const newAuthorityKeypair = anchor.web3.Keypair.generate(); - await toTx( - ctx, - WhirlpoolIx.setCollectProtocolFeesAuthorityIx(ctx.program, { - whirlpoolsConfig: configInitInfo.whirlpoolsConfigKeypair.publicKey, - collectProtocolFeesAuthority: collectProtocolFeesAuthorityKeypair.publicKey, - newCollectProtocolFeesAuthority: newAuthorityKeypair.publicKey, - }) - ) - .addSigner(collectProtocolFeesAuthorityKeypair) - .buildAndExecute(); - const config = (await fetcher.getConfig( - configInitInfo.whirlpoolsConfigKeypair.publicKey - )) as WhirlpoolsConfigData; - assert.ok(config.collectProtocolFeesAuthority.equals(newAuthorityKeypair.publicKey)); - }); - - it("fails if current collect_protocol_fee_authority is not a signer", async () => { - const { - configInitInfo, - configKeypairs: { collectProtocolFeesAuthorityKeypair }, - } = generateDefaultConfigParams(ctx); - await toTx(ctx, WhirlpoolIx.initializeConfigIx(ctx.program, configInitInfo)).buildAndExecute(); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.setCollectProtocolFeesAuthorityIx(ctx.program, { - whirlpoolsConfig: configInitInfo.whirlpoolsConfigKeypair.publicKey, - collectProtocolFeesAuthority: collectProtocolFeesAuthorityKeypair.publicKey, - newCollectProtocolFeesAuthority: provider.wallet.publicKey, - }) - ).buildAndExecute(), - /.*signature verification fail.*/i - ); - }); - - it("fails if invalid collect_protocol_fee_authority provided", async () => { - const { configInitInfo } = generateDefaultConfigParams(ctx); - await toTx(ctx, WhirlpoolIx.initializeConfigIx(ctx.program, configInitInfo)).buildAndExecute(); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.setCollectProtocolFeesAuthorityIx(ctx.program, { - whirlpoolsConfig: configInitInfo.whirlpoolsConfigKeypair.publicKey, - collectProtocolFeesAuthority: provider.wallet.publicKey, - newCollectProtocolFeesAuthority: provider.wallet.publicKey, - }) - ).buildAndExecute(), - /0x7dc/ // An address constraint was violated - ); - }); -}); diff --git a/sdk/tests/integration/set_default_fee_rate.test.ts b/sdk/tests/integration/set_default_fee_rate.test.ts deleted file mode 100644 index ef442fc..0000000 --- a/sdk/tests/integration/set_default_fee_rate.test.ts +++ /dev/null @@ -1,219 +0,0 @@ -import * as anchor from "@coral-xyz/anchor"; -import * as assert from "assert"; -import { - InitPoolParams, - PDAUtil, - toTx, - WhirlpoolContext, - WhirlpoolData, - WhirlpoolIx -} from "../../src"; -import { TickSpacing } from "../utils"; -import { defaultConfirmOptions } from "../utils/const"; -import { initTestPool } from "../utils/init-utils"; -import { createInOrderMints, generateDefaultConfigParams } from "../utils/test-builders"; - -describe("set_default_fee_rate", () => { - const provider = anchor.AnchorProvider.local(undefined, defaultConfirmOptions); - - const program = anchor.workspace.Whirlpool; - const ctx = WhirlpoolContext.fromWorkspace(provider, program); - const fetcher = ctx.fetcher; - - it("successfully set_default_fee_rate", async () => { - const { poolInitInfo, configInitInfo, configKeypairs, feeTierParams } = await initTestPool( - ctx, - TickSpacing.Standard - ); - const whirlpoolKey = poolInitInfo.whirlpoolPda.publicKey; - const whirlpoolsConfigKey = configInitInfo.whirlpoolsConfigKeypair.publicKey; - const feeAuthorityKeypair = configKeypairs.feeAuthorityKeypair; - - const newDefaultFeeRate = 45; - - // Fetch initial whirlpool and check it is default - let whirlpool_0 = (await fetcher.getPool(whirlpoolKey)) as WhirlpoolData; - assert.equal(whirlpool_0.feeRate, feeTierParams.defaultFeeRate); - - await toTx( - ctx, - WhirlpoolIx.setDefaultFeeRateIx(ctx.program, { - whirlpoolsConfig: whirlpoolsConfigKey, - feeAuthority: feeAuthorityKeypair.publicKey, - tickSpacing: TickSpacing.Standard, - defaultFeeRate: newDefaultFeeRate, - }) - ) - .addSigner(feeAuthorityKeypair) - .buildAndExecute(); - - // Setting the default rate did not change existing whirlpool fee rate - whirlpool_0 = (await fetcher.getPool(poolInitInfo.whirlpoolPda.publicKey)) as WhirlpoolData; - assert.equal(whirlpool_0.feeRate, feeTierParams.defaultFeeRate); - - // Newly initialized whirlpools have new default fee rate - const [tokenMintA, tokenMintB] = await createInOrderMints(ctx); - const whirlpoolPda = PDAUtil.getWhirlpool( - ctx.program.programId, - whirlpoolsConfigKey, - tokenMintA, - tokenMintB, - TickSpacing.Stable - ); - const tokenVaultAKeypair = anchor.web3.Keypair.generate(); - const tokenVaultBKeypair = anchor.web3.Keypair.generate(); - - const newPoolInitInfo: InitPoolParams = { - ...poolInitInfo, - tokenMintA, - tokenMintB, - whirlpoolPda, - tokenVaultAKeypair, - tokenVaultBKeypair, - tickSpacing: TickSpacing.Stable, - }; - await toTx(ctx, WhirlpoolIx.initializePoolIx(ctx.program, newPoolInitInfo)).buildAndExecute(); - - const whirlpool_1 = (await fetcher.getPool(whirlpoolPda.publicKey)) as WhirlpoolData; - assert.equal(whirlpool_1.feeRate, newDefaultFeeRate); - }); - - it("successfully set_default_fee_rate max", async () => { - const { poolInitInfo, configInitInfo, configKeypairs, feeTierParams } = await initTestPool( - ctx, - TickSpacing.Standard - ); - const whirlpoolsConfigKey = configInitInfo.whirlpoolsConfigKeypair.publicKey; - const feeAuthorityKeypair = configKeypairs.feeAuthorityKeypair; - - const newDefaultFeeRate = 30_000; - - await toTx( - ctx, - WhirlpoolIx.setDefaultFeeRateIx(ctx.program, { - whirlpoolsConfig: whirlpoolsConfigKey, - feeAuthority: feeAuthorityKeypair.publicKey, - tickSpacing: TickSpacing.Standard, - defaultFeeRate: newDefaultFeeRate, - }) - ) - .addSigner(feeAuthorityKeypair) - .buildAndExecute(); - - // Newly initialized whirlpools have new default fee rate - const [tokenMintA, tokenMintB] = await createInOrderMints(ctx); - const whirlpoolPda = PDAUtil.getWhirlpool( - ctx.program.programId, - whirlpoolsConfigKey, - tokenMintA, - tokenMintB, - TickSpacing.Stable - ); - const tokenVaultAKeypair = anchor.web3.Keypair.generate(); - const tokenVaultBKeypair = anchor.web3.Keypair.generate(); - - const newPoolInitInfo: InitPoolParams = { - ...poolInitInfo, - tokenMintA, - tokenMintB, - whirlpoolPda, - tokenVaultAKeypair, - tokenVaultBKeypair, - tickSpacing: TickSpacing.Stable, - }; - await toTx(ctx, WhirlpoolIx.initializePoolIx(ctx.program, newPoolInitInfo)).buildAndExecute(); - - const whirlpool_1 = (await fetcher.getPool(whirlpoolPda.publicKey)) as WhirlpoolData; - assert.equal(whirlpool_1.feeRate, newDefaultFeeRate); - }); - - it("fails when default fee rate exceeds max", async () => { - const { configInitInfo, configKeypairs } = await initTestPool(ctx, TickSpacing.Standard); - const whirlpoolsConfigKey = configInitInfo.whirlpoolsConfigKeypair.publicKey; - const feeAuthorityKeypair = configKeypairs.feeAuthorityKeypair; - - const newDefaultFeeRate = 30_000 + 1; - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.setDefaultFeeRateIx(ctx.program, { - whirlpoolsConfig: whirlpoolsConfigKey, - feeAuthority: feeAuthorityKeypair.publicKey, - tickSpacing: TickSpacing.Standard, - defaultFeeRate: newDefaultFeeRate, - }) - ) - .addSigner(feeAuthorityKeypair) - .buildAndExecute(), - /0x178c/ // FeeRateMaxExceeded - ); - }); - - it("fails when fee tier account has not been initialized", async () => { - const { configInitInfo, configKeypairs } = generateDefaultConfigParams(ctx); - await toTx(ctx, WhirlpoolIx.initializeConfigIx(ctx.program, configInitInfo)).buildAndExecute(); - const feeAuthorityKeypair = configKeypairs.feeAuthorityKeypair; - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.setDefaultFeeRateIx(ctx.program, { - whirlpoolsConfig: configInitInfo.whirlpoolsConfigKeypair.publicKey, - feeAuthority: feeAuthorityKeypair.publicKey, - tickSpacing: TickSpacing.Standard, - defaultFeeRate: 500, - }) - ) - .addSigner(feeAuthorityKeypair) - .buildAndExecute(), - /0xbc4/ // AccountNotInitialized - ); - }); - - it("fails when fee authority is not a signer", async () => { - const { configInitInfo, configKeypairs } = await initTestPool(ctx, TickSpacing.Standard); - const whirlpoolsConfigKey = configInitInfo.whirlpoolsConfigKeypair.publicKey; - const feeAuthorityKeypair = configKeypairs.feeAuthorityKeypair; - const feeTierPda = PDAUtil.getFeeTier( - ctx.program.programId, - configInitInfo.whirlpoolsConfigKeypair.publicKey, - TickSpacing.Standard - ); - - const newDefaultFeeRate = 1000; - await assert.rejects( - program.rpc.setDefaultFeeRate(newDefaultFeeRate, { - accounts: { - whirlpoolsConfig: whirlpoolsConfigKey, - feeTier: feeTierPda.publicKey, - feeAuthority: feeAuthorityKeypair.publicKey, - }, - }), - /.*signature verification fail.*/i - ); - }); - - it("fails when invalid fee authority provided", async () => { - const { configInitInfo } = await initTestPool(ctx, TickSpacing.Standard); - const whirlpoolsConfigKey = configInitInfo.whirlpoolsConfigKeypair.publicKey; - const fakeFeeAuthorityKeypair = anchor.web3.Keypair.generate(); - const feeTierPda = PDAUtil.getFeeTier( - ctx.program.programId, - configInitInfo.whirlpoolsConfigKeypair.publicKey, - TickSpacing.Standard - ); - - const newDefaultFeeRate = 1000; - await assert.rejects( - program.rpc.setDefaultFeeRate(newDefaultFeeRate, { - accounts: { - whirlpoolsConfig: whirlpoolsConfigKey, - feeTier: feeTierPda.publicKey, - feeAuthority: fakeFeeAuthorityKeypair.publicKey, - }, - signers: [fakeFeeAuthorityKeypair], - }), - /An address constraint was violated/ // ConstraintAddress - ); - }); -}); diff --git a/sdk/tests/integration/set_default_protocol_fee_rate.test.ts b/sdk/tests/integration/set_default_protocol_fee_rate.test.ts deleted file mode 100644 index 5eef756..0000000 --- a/sdk/tests/integration/set_default_protocol_fee_rate.test.ts +++ /dev/null @@ -1,134 +0,0 @@ -import * as anchor from "@coral-xyz/anchor"; -import * as assert from "assert"; -import { - InitPoolParams, - PDAUtil, - toTx, - WhirlpoolContext, - WhirlpoolData, - WhirlpoolIx -} from "../../src"; -import { TickSpacing } from "../utils"; -import { defaultConfirmOptions } from "../utils/const"; -import { initTestPool } from "../utils/init-utils"; -import { createInOrderMints } from "../utils/test-builders"; - -describe("set_default_protocol_fee_rate", () => { - const provider = anchor.AnchorProvider.local(undefined, defaultConfirmOptions); - - const program = anchor.workspace.Whirlpool; - const ctx = WhirlpoolContext.fromWorkspace(provider, program); - const fetcher = ctx.fetcher; - - it("successfully set_default_protocol_fee_rate", async () => { - const { poolInitInfo, configInitInfo, configKeypairs } = await initTestPool( - ctx, - TickSpacing.Standard - ); - const whirlpoolKey = poolInitInfo.whirlpoolPda.publicKey; - const whirlpoolsConfigKey = configInitInfo.whirlpoolsConfigKeypair.publicKey; - const feeAuthorityKeypair = configKeypairs.feeAuthorityKeypair; - - const newDefaultProtocolFeeRate = 45; - - // Fetch initial whirlpool and check it is default - let whirlpool_0 = (await fetcher.getPool(whirlpoolKey)) as WhirlpoolData; - assert.equal(whirlpool_0.protocolFeeRate, configInitInfo.defaultProtocolFeeRate); - - await toTx( - ctx, - WhirlpoolIx.setDefaultProtocolFeeRateIx(ctx.program, { - whirlpoolsConfig: whirlpoolsConfigKey, - feeAuthority: feeAuthorityKeypair.publicKey, - defaultProtocolFeeRate: newDefaultProtocolFeeRate, - }) - ) - .addSigner(feeAuthorityKeypair) - .buildAndExecute(); - - // Setting the default rate did not change existing whirlpool fee rate - whirlpool_0 = (await fetcher.getPool(whirlpoolKey)) as WhirlpoolData; - assert.equal(whirlpool_0.protocolFeeRate, configInitInfo.defaultProtocolFeeRate); - - const [tokenMintA, tokenMintB] = await createInOrderMints(ctx); - const whirlpoolPda = PDAUtil.getWhirlpool( - ctx.program.programId, - whirlpoolsConfigKey, - tokenMintA, - tokenMintB, - TickSpacing.Stable - ); - const tokenVaultAKeypair = anchor.web3.Keypair.generate(); - const tokenVaultBKeypair = anchor.web3.Keypair.generate(); - - const newPoolInitInfo: InitPoolParams = { - ...poolInitInfo, - tokenMintA, - tokenMintB, - whirlpoolPda, - tokenVaultAKeypair, - tokenVaultBKeypair, - tickSpacing: TickSpacing.Stable, - }; - await toTx(ctx, WhirlpoolIx.initializePoolIx(ctx.program, newPoolInitInfo)).buildAndExecute(); - - const whirlpool_1 = (await fetcher.getPool(whirlpoolPda.publicKey)) as WhirlpoolData; - assert.equal(whirlpool_1.protocolFeeRate, newDefaultProtocolFeeRate); - }); - - it("fails when default fee rate exceeds max", async () => { - const { configInitInfo, configKeypairs } = await initTestPool(ctx, TickSpacing.Standard); - const whirlpoolsConfigKey = configInitInfo.whirlpoolsConfigKeypair.publicKey; - const feeAuthorityKeypair = configKeypairs.feeAuthorityKeypair; - - const newDefaultProtocolFeeRate = 20_000; - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.setDefaultProtocolFeeRateIx(ctx.program, { - whirlpoolsConfig: whirlpoolsConfigKey, - feeAuthority: feeAuthorityKeypair.publicKey, - defaultProtocolFeeRate: newDefaultProtocolFeeRate, - }) - ) - .addSigner(feeAuthorityKeypair) - .buildAndExecute(), - /0x178d/ // ProtocolFeeRateMaxExceeded - ); - }); - - it("fails when fee authority is not a signer", async () => { - const { configInitInfo, configKeypairs } = await initTestPool(ctx, TickSpacing.Standard); - const whirlpoolsConfigKey = configInitInfo.whirlpoolsConfigKeypair.publicKey; - const feeAuthorityKeypair = configKeypairs.feeAuthorityKeypair; - - const newDefaultProtocolFeeRate = 1000; - await assert.rejects( - program.rpc.setDefaultProtocolFeeRate(newDefaultProtocolFeeRate, { - accounts: { - whirlpoolsConfig: whirlpoolsConfigKey, - feeAuthority: feeAuthorityKeypair.publicKey, - }, - }), - /.*signature verification fail.*/i - ); - }); - - it("fails when invalid fee authority provided", async () => { - const { configInitInfo } = await initTestPool(ctx, TickSpacing.Standard); - const whirlpoolsConfigKey = configInitInfo.whirlpoolsConfigKeypair.publicKey; - const fakeFeeAuthorityKeypair = anchor.web3.Keypair.generate(); - - const newDefaultProtocolFeeRate = 1000; - await assert.rejects( - program.rpc.setDefaultProtocolFeeRate(newDefaultProtocolFeeRate, { - accounts: { - whirlpoolsConfig: whirlpoolsConfigKey, - feeAuthority: fakeFeeAuthorityKeypair.publicKey, - }, - signers: [fakeFeeAuthorityKeypair], - }), - /An address constraint was violated/ - ); - }); -}); diff --git a/sdk/tests/integration/set_fee_authority.test.ts b/sdk/tests/integration/set_fee_authority.test.ts deleted file mode 100644 index d699025..0000000 --- a/sdk/tests/integration/set_fee_authority.test.ts +++ /dev/null @@ -1,73 +0,0 @@ -import * as anchor from "@coral-xyz/anchor"; -import * as assert from "assert"; -import { toTx, WhirlpoolContext, WhirlpoolIx, WhirlpoolsConfigData } from "../../src"; -import { defaultConfirmOptions } from "../utils/const"; -import { generateDefaultConfigParams } from "../utils/test-builders"; - -describe("set_fee_authority", () => { - const provider = anchor.AnchorProvider.local(undefined, defaultConfirmOptions); - - const program = anchor.workspace.Whirlpool; - const ctx = WhirlpoolContext.fromWorkspace(provider, program); - const fetcher = ctx.fetcher; - - it("successfully set_fee_authority", async () => { - const { - configInitInfo, - configKeypairs: { feeAuthorityKeypair }, - } = generateDefaultConfigParams(ctx); - await toTx(ctx, WhirlpoolIx.initializeConfigIx(ctx.program, configInitInfo)).buildAndExecute(); - const newAuthorityKeypair = anchor.web3.Keypair.generate(); - await toTx( - ctx, - WhirlpoolIx.setFeeAuthorityIx(ctx.program, { - whirlpoolsConfig: configInitInfo.whirlpoolsConfigKeypair.publicKey, - feeAuthority: feeAuthorityKeypair.publicKey, - newFeeAuthority: newAuthorityKeypair.publicKey, - }) - ) - .addSigner(feeAuthorityKeypair) - .buildAndExecute(); - const config = (await fetcher.getConfig( - configInitInfo.whirlpoolsConfigKeypair.publicKey - )) as WhirlpoolsConfigData; - assert.ok(config.feeAuthority.equals(newAuthorityKeypair.publicKey)); - }); - - it("fails if current fee_authority is not a signer", async () => { - const { - configInitInfo, - configKeypairs: { feeAuthorityKeypair }, - } = generateDefaultConfigParams(ctx); - await toTx(ctx, WhirlpoolIx.initializeConfigIx(ctx.program, configInitInfo)).buildAndExecute(); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.setFeeAuthorityIx(ctx.program, { - whirlpoolsConfig: configInitInfo.whirlpoolsConfigKeypair.publicKey, - feeAuthority: feeAuthorityKeypair.publicKey, - newFeeAuthority: provider.wallet.publicKey, - }) - ).buildAndExecute(), - /.*signature verification fail.*/i - ); - }); - - it("fails if invalid fee_authority provided", async () => { - const { configInitInfo } = generateDefaultConfigParams(ctx); - await toTx(ctx, WhirlpoolIx.initializeConfigIx(ctx.program, configInitInfo)).buildAndExecute(); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.setFeeAuthorityIx(ctx.program, { - whirlpoolsConfig: configInitInfo.whirlpoolsConfigKeypair.publicKey, - feeAuthority: provider.wallet.publicKey, - newFeeAuthority: provider.wallet.publicKey, - }) - ).buildAndExecute(), - /0x7dc/ // An address constraint was violated - ); - }); -}); diff --git a/sdk/tests/integration/set_fee_rate.test.ts b/sdk/tests/integration/set_fee_rate.test.ts deleted file mode 100644 index 21101c3..0000000 --- a/sdk/tests/integration/set_fee_rate.test.ts +++ /dev/null @@ -1,170 +0,0 @@ -import * as anchor from "@coral-xyz/anchor"; -import * as assert from "assert"; -import { toTx, WhirlpoolContext, WhirlpoolData, WhirlpoolIx } from "../../src"; -import { IGNORE_CACHE } from "../../src/network/public/fetcher"; -import { TickSpacing } from "../utils"; -import { defaultConfirmOptions } from "../utils/const"; -import { initTestPool } from "../utils/init-utils"; -import { generateDefaultConfigParams } from "../utils/test-builders"; - -describe("set_fee_rate", () => { - const provider = anchor.AnchorProvider.local(undefined, defaultConfirmOptions); - - const program = anchor.workspace.Whirlpool; - const ctx = WhirlpoolContext.fromWorkspace(provider, program); - const fetcher = ctx.fetcher; - - it("successfully sets_fee_rate", async () => { - const { poolInitInfo, configInitInfo, configKeypairs, feeTierParams } = await initTestPool( - ctx, - TickSpacing.Standard - ); - const whirlpoolKey = poolInitInfo.whirlpoolPda.publicKey; - const whirlpoolsConfigKey = configInitInfo.whirlpoolsConfigKeypair.publicKey; - const feeAuthorityKeypair = configKeypairs.feeAuthorityKeypair; - - const newFeeRate = 50; - - let whirlpool = (await fetcher.getPool(whirlpoolKey, IGNORE_CACHE)) as WhirlpoolData; - - assert.equal(whirlpool.feeRate, feeTierParams.defaultFeeRate); - - const setFeeRateTx = toTx(ctx, WhirlpoolIx.setFeeRateIx(program, { - whirlpool: whirlpoolKey, - whirlpoolsConfig: whirlpoolsConfigKey, - feeAuthority: feeAuthorityKeypair.publicKey, - feeRate: newFeeRate - })).addSigner(feeAuthorityKeypair); - await setFeeRateTx.buildAndExecute(); - - whirlpool = (await fetcher.getPool(poolInitInfo.whirlpoolPda.publicKey, IGNORE_CACHE)) as WhirlpoolData; - assert.equal(whirlpool.feeRate, newFeeRate); - }); - - it("successfully sets_fee_rate max", async () => { - const { poolInitInfo, configInitInfo, configKeypairs, feeTierParams } = await initTestPool( - ctx, - TickSpacing.Standard - ); - const whirlpoolKey = poolInitInfo.whirlpoolPda.publicKey; - const whirlpoolsConfigKey = configInitInfo.whirlpoolsConfigKeypair.publicKey; - const feeAuthorityKeypair = configKeypairs.feeAuthorityKeypair; - - const newFeeRate = 30_000; - - let whirlpool = (await fetcher.getPool(whirlpoolKey, IGNORE_CACHE)) as WhirlpoolData; - - assert.equal(whirlpool.feeRate, feeTierParams.defaultFeeRate); - - const setFeeRateTx = toTx(ctx, WhirlpoolIx.setFeeRateIx(program, { - whirlpool: whirlpoolKey, - whirlpoolsConfig: whirlpoolsConfigKey, - feeAuthority: feeAuthorityKeypair.publicKey, - feeRate: newFeeRate - })).addSigner(feeAuthorityKeypair); - await setFeeRateTx.buildAndExecute(); - - whirlpool = (await fetcher.getPool(poolInitInfo.whirlpoolPda.publicKey, IGNORE_CACHE)) as WhirlpoolData; - assert.equal(whirlpool.feeRate, newFeeRate); - }); - - it("fails when fee rate exceeds max", async () => { - const { poolInitInfo, configInitInfo, configKeypairs } = await initTestPool( - ctx, - TickSpacing.Standard - ); - const whirlpoolKey = poolInitInfo.whirlpoolPda.publicKey; - const whirlpoolsConfigKey = configInitInfo.whirlpoolsConfigKeypair.publicKey; - const feeAuthorityKeypair = configKeypairs.feeAuthorityKeypair; - - const newFeeRate = 30_000 + 1; - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.setFeeRateIx(ctx.program, { - whirlpoolsConfig: whirlpoolsConfigKey, - whirlpool: whirlpoolKey, - feeAuthority: feeAuthorityKeypair.publicKey, - feeRate: newFeeRate, - }) - ) - .addSigner(configKeypairs.feeAuthorityKeypair) - .buildAndExecute(), - /0x178c/ // FeeRateMaxExceeded - ); - }); - - it("fails when fee authority is not signer", async () => { - const { poolInitInfo, configInitInfo, configKeypairs } = await initTestPool( - ctx, - TickSpacing.Standard - ); - const whirlpoolKey = poolInitInfo.whirlpoolPda.publicKey; - const whirlpoolsConfigKey = configInitInfo.whirlpoolsConfigKeypair.publicKey; - const feeAuthorityKeypair = configKeypairs.feeAuthorityKeypair; - - const newFeeRate = 1000; - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.setFeeRateIx(ctx.program, { - whirlpoolsConfig: whirlpoolsConfigKey, - whirlpool: whirlpoolKey, - feeAuthority: feeAuthorityKeypair.publicKey, - feeRate: newFeeRate, - }) - ).buildAndExecute(), - /.*signature verification fail.*/i - ); - }); - - it("fails when whirlpool and whirlpools config don't match", async () => { - const { poolInitInfo, configInitInfo, configKeypairs } = await initTestPool( - ctx, - TickSpacing.Standard - ); - const whirlpoolKey = poolInitInfo.whirlpoolPda.publicKey; - const feeAuthorityKeypair = configKeypairs.feeAuthorityKeypair; - - const { configInitInfo: otherConfigInitInfo } = generateDefaultConfigParams(ctx); - await toTx( - ctx, - WhirlpoolIx.initializeConfigIx(ctx.program, otherConfigInitInfo) - ).buildAndExecute(); - - const newFeeRate = 1000; - await assert.rejects( - ctx.program.rpc.setFeeRate(newFeeRate, { - accounts: { - whirlpoolsConfig: otherConfigInitInfo.whirlpoolsConfigKeypair.publicKey, - whirlpool: whirlpoolKey, - feeAuthority: feeAuthorityKeypair.publicKey, - }, - signers: [configKeypairs.feeAuthorityKeypair], - }), - // message have been changed - // https://github.com/coral-xyz/anchor/pull/2101/files#diff-e564d6832afe5358ef129e96970ba1e5180b5e74aba761831e1923c06d7b839fR412 - /A has[_ ]one constraint was violated/ // ConstraintHasOne - ); - }); - - it("fails when fee authority is invalid", async () => { - const { poolInitInfo, configInitInfo } = await initTestPool(ctx, TickSpacing.Standard); - const whirlpoolKey = poolInitInfo.whirlpoolPda.publicKey; - - const fakeAuthorityKeypair = anchor.web3.Keypair.generate(); - - const newFeeRate = 1000; - await assert.rejects( - ctx.program.rpc.setFeeRate(newFeeRate, { - accounts: { - whirlpoolsConfig: configInitInfo.whirlpoolsConfigKeypair.publicKey, - whirlpool: whirlpoolKey, - feeAuthority: fakeAuthorityKeypair.publicKey, - }, - signers: [fakeAuthorityKeypair], - }), - /An address constraint was violated/ // ConstraintAddress - ); - }); -}); diff --git a/sdk/tests/integration/set_protocol_fee_rate.test.ts b/sdk/tests/integration/set_protocol_fee_rate.test.ts deleted file mode 100644 index 353ca5e..0000000 --- a/sdk/tests/integration/set_protocol_fee_rate.test.ts +++ /dev/null @@ -1,138 +0,0 @@ -import * as anchor from "@coral-xyz/anchor"; -import * as assert from "assert"; -import { toTx, WhirlpoolContext, WhirlpoolData, WhirlpoolIx } from "../../src"; -import { IGNORE_CACHE } from "../../src/network/public/fetcher"; -import { TickSpacing } from "../utils"; -import { defaultConfirmOptions } from "../utils/const"; -import { initTestPool } from "../utils/init-utils"; -import { generateDefaultConfigParams } from "../utils/test-builders"; - -describe("set_protocol_fee_rate", () => { - const provider = anchor.AnchorProvider.local(undefined, defaultConfirmOptions); - const program = anchor.workspace.Whirlpool; - const ctx = WhirlpoolContext.fromWorkspace(provider, program); - const fetcher = ctx.fetcher; - - it("successfully sets_protocol_fee_rate", async () => { - const { poolInitInfo, configInitInfo, configKeypairs } = await initTestPool( - ctx, - TickSpacing.Standard - ); - const whirlpoolKey = poolInitInfo.whirlpoolPda.publicKey; - const whirlpoolsConfigKey = configInitInfo.whirlpoolsConfigKeypair.publicKey; - const feeAuthorityKeypair = configKeypairs.feeAuthorityKeypair; - - const newProtocolFeeRate = 50; - - let whirlpool = (await fetcher.getPool(whirlpoolKey, IGNORE_CACHE)) as WhirlpoolData; - - assert.equal(whirlpool.protocolFeeRate, configInitInfo.defaultProtocolFeeRate); - - const txBuilder = toTx(ctx, WhirlpoolIx.setProtocolFeeRateIx(program, { - whirlpool: whirlpoolKey, - whirlpoolsConfig: whirlpoolsConfigKey, - feeAuthority: feeAuthorityKeypair.publicKey, - protocolFeeRate: newProtocolFeeRate - })).addSigner(feeAuthorityKeypair); - await txBuilder.buildAndExecute(); - - whirlpool = (await fetcher.getPool(poolInitInfo.whirlpoolPda.publicKey, IGNORE_CACHE)) as WhirlpoolData; - assert.equal(whirlpool.protocolFeeRate, newProtocolFeeRate); - }); - - it("fails when protocol fee rate exceeds max", async () => { - const { poolInitInfo, configInitInfo, configKeypairs } = await initTestPool( - ctx, - TickSpacing.Standard - ); - const whirlpoolKey = poolInitInfo.whirlpoolPda.publicKey; - const whirlpoolsConfigKey = configInitInfo.whirlpoolsConfigKeypair.publicKey; - const feeAuthorityKeypair = configKeypairs.feeAuthorityKeypair; - - const newProtocolFeeRate = 3_000; - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.setProtocolFeeRateIx(ctx.program, { - whirlpoolsConfig: whirlpoolsConfigKey, - whirlpool: whirlpoolKey, - feeAuthority: feeAuthorityKeypair.publicKey, - protocolFeeRate: newProtocolFeeRate, - }) - ) - .addSigner(configKeypairs.feeAuthorityKeypair) - .buildAndExecute(), - /0x178d/ // ProtocolFeeRateMaxExceeded - ); - }); - - it("fails when fee authority is not signer", async () => { - const { poolInitInfo, configInitInfo, configKeypairs } = await initTestPool( - ctx, - TickSpacing.Standard - ); - const whirlpoolKey = poolInitInfo.whirlpoolPda.publicKey; - const whirlpoolsConfigKey = configInitInfo.whirlpoolsConfigKeypair.publicKey; - const feeAuthorityKeypair = configKeypairs.feeAuthorityKeypair; - - const newProtocolFeeRate = 1000; - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.setProtocolFeeRateIx(ctx.program, { - whirlpoolsConfig: whirlpoolsConfigKey, - whirlpool: whirlpoolKey, - feeAuthority: feeAuthorityKeypair.publicKey, - protocolFeeRate: newProtocolFeeRate, - }) - ).buildAndExecute(), - /.*signature verification fail.*/i - ); - }); - - it("fails when whirlpool and whirlpools config don't match", async () => { - const { poolInitInfo, configKeypairs } = await initTestPool(ctx, TickSpacing.Standard); - const whirlpoolKey = poolInitInfo.whirlpoolPda.publicKey; - const feeAuthorityKeypair = configKeypairs.feeAuthorityKeypair; - - const { configInitInfo: otherConfigInitInfo } = generateDefaultConfigParams(ctx); - await toTx( - ctx, - WhirlpoolIx.initializeConfigIx(ctx.program, otherConfigInitInfo) - ).buildAndExecute(); - - const newProtocolFeeRate = 1000; - await assert.rejects( - ctx.program.rpc.setProtocolFeeRate(newProtocolFeeRate, { - accounts: { - whirlpoolsConfig: otherConfigInitInfo.whirlpoolsConfigKeypair.publicKey, - whirlpool: whirlpoolKey, - feeAuthority: feeAuthorityKeypair.publicKey, - }, - signers: [configKeypairs.feeAuthorityKeypair], - }), - // message have been changed - // https://github.com/coral-xyz/anchor/pull/2101/files#diff-e564d6832afe5358ef129e96970ba1e5180b5e74aba761831e1923c06d7b839fR412 - /A has[_ ]one constraint was violated/ // ConstraintHasOne - ); - }); - - it("fails when fee authority is invalid", async () => { - const { poolInitInfo, configInitInfo } = await initTestPool(ctx, TickSpacing.Standard); - const whirlpoolKey = poolInitInfo.whirlpoolPda.publicKey; - const fakeAuthorityKeypair = anchor.web3.Keypair.generate(); - - const newProtocolFeeRate = 1000; - await assert.rejects( - ctx.program.rpc.setProtocolFeeRate(newProtocolFeeRate, { - accounts: { - whirlpoolsConfig: configInitInfo.whirlpoolsConfigKeypair.publicKey, - whirlpool: whirlpoolKey, - feeAuthority: fakeAuthorityKeypair.publicKey, - }, - signers: [fakeAuthorityKeypair], - }), - /An address constraint was violated/ // ConstraintAddress - ); - }); -}); diff --git a/sdk/tests/integration/set_reward_authority.test.ts b/sdk/tests/integration/set_reward_authority.test.ts deleted file mode 100644 index 10c7355..0000000 --- a/sdk/tests/integration/set_reward_authority.test.ts +++ /dev/null @@ -1,121 +0,0 @@ -import * as anchor from "@coral-xyz/anchor"; -import { TransactionBuilder } from "@orca-so/common-sdk"; -import * as assert from "assert"; -import { NUM_REWARDS, toTx, WhirlpoolContext, WhirlpoolData, WhirlpoolIx } from "../../src"; -import { TickSpacing } from "../utils"; -import { defaultConfirmOptions } from "../utils/const"; -import { initTestPool } from "../utils/init-utils"; - -describe("set_reward_authority", () => { - const provider = anchor.AnchorProvider.local(undefined, defaultConfirmOptions); - - const program = anchor.workspace.Whirlpool; - const ctx = WhirlpoolContext.fromWorkspace(provider, program); - const fetcher = ctx.fetcher; - - it("successfully set_reward_authority at every reward index", async () => { - const { configKeypairs, poolInitInfo } = await initTestPool(ctx, TickSpacing.Standard); - - const newKeypairs = generateKeypairs(NUM_REWARDS); - const txBuilder = new TransactionBuilder(provider.connection, provider.wallet, ctx.txBuilderOpts); - for (let i = 0; i < NUM_REWARDS; i++) { - txBuilder.addInstruction( - WhirlpoolIx.setRewardAuthorityIx(ctx.program, { - whirlpool: poolInitInfo.whirlpoolPda.publicKey, - rewardAuthority: configKeypairs.rewardEmissionsSuperAuthorityKeypair.publicKey, - newRewardAuthority: newKeypairs[i].publicKey, - rewardIndex: i, - }) - ); - } - await txBuilder - .addSigner(configKeypairs.rewardEmissionsSuperAuthorityKeypair) - .buildAndExecute({ - maxSupportedTransactionVersion: undefined, - }); - - const pool = (await fetcher.getPool(poolInitInfo.whirlpoolPda.publicKey)) as WhirlpoolData; - for (let i = 0; i < NUM_REWARDS; i++) { - assert.ok(pool.rewardInfos[i].authority.equals(newKeypairs[i].publicKey)); - } - }); - - it("fails when provided reward_authority does not match whirlpool reward authority", async () => { - const { poolInitInfo } = await initTestPool(ctx, TickSpacing.Standard); - - const fakeAuthority = anchor.web3.Keypair.generate(); - const newAuthority = anchor.web3.Keypair.generate(); - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.setRewardAuthorityIx(ctx.program, { - whirlpool: poolInitInfo.whirlpoolPda.publicKey, - rewardAuthority: fakeAuthority.publicKey, - newRewardAuthority: newAuthority.publicKey, - rewardIndex: 0, - }) - ) - .addSigner(fakeAuthority) - .buildAndExecute(), - /0x7dc/ // An address constraint was violated - ); - }); - - it("fails on invalid reward index", async () => { - const { configKeypairs, poolInitInfo } = await initTestPool(ctx, TickSpacing.Standard); - - const newAuthority = anchor.web3.Keypair.generate(); - assert.throws(() => { - toTx( - ctx, - WhirlpoolIx.setRewardAuthorityIx(ctx.program, { - whirlpool: poolInitInfo.whirlpoolPda.publicKey, - rewardAuthority: configKeypairs.rewardEmissionsSuperAuthorityKeypair.publicKey, - newRewardAuthority: newAuthority.publicKey, - rewardIndex: -1, - }) - ).buildAndExecute(); - }, /out of range/); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.setRewardAuthorityIx(ctx.program, { - whirlpool: poolInitInfo.whirlpoolPda.publicKey, - rewardAuthority: configKeypairs.rewardEmissionsSuperAuthorityKeypair.publicKey, - newRewardAuthority: newAuthority.publicKey, - rewardIndex: 255, - }) - ) - .addSigner(configKeypairs.rewardEmissionsSuperAuthorityKeypair) - .buildAndExecute() - // /failed to send transaction/ - ); - }); - - it("fails when reward_authority is not a signer", async () => { - const { configKeypairs, poolInitInfo } = await initTestPool(ctx, TickSpacing.Standard); - - const newAuthority = anchor.web3.Keypair.generate(); - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.setRewardAuthorityIx(ctx.program, { - whirlpool: poolInitInfo.whirlpoolPda.publicKey, - rewardAuthority: configKeypairs.rewardEmissionsSuperAuthorityKeypair.publicKey, - newRewardAuthority: newAuthority.publicKey, - rewardIndex: 0, - }) - ).buildAndExecute(), - /.*signature verification fail.*/i - ); - }); -}); - -function generateKeypairs(n: number): anchor.web3.Keypair[] { - const keypairs = []; - for (let i = 0; i < n; i++) { - keypairs.push(anchor.web3.Keypair.generate()); - } - return keypairs; -} diff --git a/sdk/tests/integration/set_reward_authority_by_super_authority.test.ts b/sdk/tests/integration/set_reward_authority_by_super_authority.test.ts deleted file mode 100644 index 6f68b9f..0000000 --- a/sdk/tests/integration/set_reward_authority_by_super_authority.test.ts +++ /dev/null @@ -1,144 +0,0 @@ -import * as anchor from "@coral-xyz/anchor"; -import * as assert from "assert"; -import { toTx, WhirlpoolContext, WhirlpoolData, WhirlpoolIx } from "../../src"; -import { TickSpacing } from "../utils"; -import { defaultConfirmOptions } from "../utils/const"; -import { initTestPool } from "../utils/init-utils"; - -describe("set_reward_authority_by_super_authority", () => { - const provider = anchor.AnchorProvider.local(undefined, defaultConfirmOptions); - - const program = anchor.workspace.Whirlpool; - const ctx = WhirlpoolContext.fromWorkspace(provider, program); - const fetcher = ctx.fetcher; - - it("successfully set_reward_authority_by_super_authority", async () => { - const { configKeypairs, poolInitInfo, configInitInfo } = await initTestPool( - ctx, - TickSpacing.Standard - ); - const newAuthorityKeypair = anchor.web3.Keypair.generate(); - await toTx( - ctx, - WhirlpoolIx.setRewardAuthorityBySuperAuthorityIx(ctx.program, { - whirlpoolsConfig: configInitInfo.whirlpoolsConfigKeypair.publicKey, - whirlpool: poolInitInfo.whirlpoolPda.publicKey, - rewardEmissionsSuperAuthority: - configKeypairs.rewardEmissionsSuperAuthorityKeypair.publicKey, - newRewardAuthority: newAuthorityKeypair.publicKey, - rewardIndex: 0, - }) - ) - .addSigner(configKeypairs.rewardEmissionsSuperAuthorityKeypair) - .buildAndExecute(); - const pool = (await fetcher.getPool(poolInitInfo.whirlpoolPda.publicKey)) as WhirlpoolData; - assert.ok(pool.rewardInfos[0].authority.equals(newAuthorityKeypair.publicKey)); - }); - - it("fails if invalid whirlpool provided", async () => { - const { configKeypairs, configInitInfo } = await initTestPool(ctx, TickSpacing.Standard); - const { - poolInitInfo: { whirlpoolPda: invalidPool }, - } = await initTestPool(ctx, TickSpacing.Standard); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.setRewardAuthorityBySuperAuthorityIx(ctx.program, { - whirlpoolsConfig: configInitInfo.whirlpoolsConfigKeypair.publicKey, - whirlpool: invalidPool.publicKey, - rewardEmissionsSuperAuthority: - configKeypairs.rewardEmissionsSuperAuthorityKeypair.publicKey, - newRewardAuthority: provider.wallet.publicKey, - rewardIndex: 0, - }) - ) - .addSigner(configKeypairs.rewardEmissionsSuperAuthorityKeypair) - .buildAndExecute(), - /0x7d1/ // A has_one constraint was violated - ); - }); - - it("fails if invalid super authority provided", async () => { - const { poolInitInfo, configInitInfo } = await initTestPool(ctx, TickSpacing.Standard); - const invalidSuperAuthorityKeypair = anchor.web3.Keypair.generate(); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.setRewardAuthorityBySuperAuthorityIx(ctx.program, { - whirlpoolsConfig: configInitInfo.whirlpoolsConfigKeypair.publicKey, - whirlpool: poolInitInfo.whirlpoolPda.publicKey, - rewardEmissionsSuperAuthority: invalidSuperAuthorityKeypair.publicKey, - newRewardAuthority: provider.wallet.publicKey, - rewardIndex: 0, - }) - ) - .addSigner(invalidSuperAuthorityKeypair) - .buildAndExecute(), - /0x7dc/ // An address constraint was violated - ); - }); - - it("fails if super authority is not a signer", async () => { - const { configKeypairs, poolInitInfo, configInitInfo } = await initTestPool( - ctx, - TickSpacing.Standard - ); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.setRewardAuthorityBySuperAuthorityIx(ctx.program, { - whirlpoolsConfig: configInitInfo.whirlpoolsConfigKeypair.publicKey, - whirlpool: poolInitInfo.whirlpoolPda.publicKey, - rewardEmissionsSuperAuthority: - configKeypairs.rewardEmissionsSuperAuthorityKeypair.publicKey, - newRewardAuthority: provider.wallet.publicKey, - rewardIndex: 0, - }) - ).buildAndExecute(), - /.*signature verification fail.*/i - ); - }); - - it("fails on invalid reward index", async () => { - const { configKeypairs, poolInitInfo, configInitInfo } = await initTestPool( - ctx, - TickSpacing.Standard - ); - - assert.throws(() => { - toTx( - ctx, - WhirlpoolIx.setRewardAuthorityBySuperAuthorityIx(ctx.program, { - whirlpoolsConfig: configInitInfo.whirlpoolsConfigKeypair.publicKey, - whirlpool: poolInitInfo.whirlpoolPda.publicKey, - rewardEmissionsSuperAuthority: - configKeypairs.rewardEmissionsSuperAuthorityKeypair.publicKey, - newRewardAuthority: provider.wallet.publicKey, - rewardIndex: -1, - }) - ) - .addSigner(configKeypairs.rewardEmissionsSuperAuthorityKeypair) - .buildAndExecute(); - }, /out of range/); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.setRewardAuthorityBySuperAuthorityIx(ctx.program, { - whirlpoolsConfig: configInitInfo.whirlpoolsConfigKeypair.publicKey, - whirlpool: poolInitInfo.whirlpoolPda.publicKey, - rewardEmissionsSuperAuthority: - configKeypairs.rewardEmissionsSuperAuthorityKeypair.publicKey, - newRewardAuthority: provider.wallet.publicKey, - rewardIndex: 200, - }) - ) - .addSigner(configKeypairs.rewardEmissionsSuperAuthorityKeypair) - .buildAndExecute(), - /0x178a/ // InvalidRewardIndex - ); - }); -}); diff --git a/sdk/tests/integration/set_reward_emissions.test.ts b/sdk/tests/integration/set_reward_emissions.test.ts deleted file mode 100644 index 9439ae3..0000000 --- a/sdk/tests/integration/set_reward_emissions.test.ts +++ /dev/null @@ -1,197 +0,0 @@ -import * as anchor from "@coral-xyz/anchor"; -import * as assert from "assert"; -import { toTx, WhirlpoolContext, WhirlpoolData, WhirlpoolIx } from "../../src"; -import { IGNORE_CACHE } from "../../src/network/public/fetcher"; -import { createAndMintToTokenAccount, mintToDestination, TickSpacing, ZERO_BN } from "../utils"; -import { defaultConfirmOptions } from "../utils/const"; -import { initializeReward, initTestPool } from "../utils/init-utils"; - -describe("set_reward_emissions", () => { - const provider = anchor.AnchorProvider.local(undefined, defaultConfirmOptions); - - const program = anchor.workspace.Whirlpool; - const ctx = WhirlpoolContext.fromWorkspace(provider, program); - const fetcher = ctx.fetcher; - - const emissionsPerSecondX64 = new anchor.BN(10_000).shln(64).div(new anchor.BN(60 * 60 * 24)); - - it("successfully set_reward_emissions", async () => { - const { poolInitInfo, configInitInfo, configKeypairs } = await initTestPool( - ctx, - TickSpacing.Standard - ); - - const rewardIndex = 0; - - const { - params: { rewardVaultKeypair, rewardMint }, - } = await initializeReward( - ctx, - configKeypairs.rewardEmissionsSuperAuthorityKeypair, - poolInitInfo.whirlpoolPda.publicKey, - rewardIndex - ); - - await mintToDestination(provider, rewardMint, rewardVaultKeypair.publicKey, 10000); - - await toTx( - ctx, - WhirlpoolIx.setRewardEmissionsIx(ctx.program, { - rewardAuthority: configInitInfo.rewardEmissionsSuperAuthority, - whirlpool: poolInitInfo.whirlpoolPda.publicKey, - rewardIndex, - rewardVaultKey: rewardVaultKeypair.publicKey, - emissionsPerSecondX64, - }) - ) - .addSigner(configKeypairs.rewardEmissionsSuperAuthorityKeypair) - .buildAndExecute(); - - let whirlpool = (await fetcher.getPool( - poolInitInfo.whirlpoolPda.publicKey, - IGNORE_CACHE - )) as WhirlpoolData; - assert.ok(whirlpool.rewardInfos[0].emissionsPerSecondX64.eq(emissionsPerSecondX64)); - - // Successfuly set emissions back to zero - await toTx( - ctx, - WhirlpoolIx.setRewardEmissionsIx(ctx.program, { - rewardAuthority: configInitInfo.rewardEmissionsSuperAuthority, - whirlpool: poolInitInfo.whirlpoolPda.publicKey, - rewardIndex, - rewardVaultKey: rewardVaultKeypair.publicKey, - emissionsPerSecondX64: ZERO_BN, - }) - ) - .addSigner(configKeypairs.rewardEmissionsSuperAuthorityKeypair) - .buildAndExecute(); - - whirlpool = (await fetcher.getPool(poolInitInfo.whirlpoolPda.publicKey, IGNORE_CACHE)) as WhirlpoolData; - assert.ok(whirlpool.rewardInfos[0].emissionsPerSecondX64.eq(ZERO_BN)); - }); - - it("fails when token vault does not contain at least 1 day of emission runway", async () => { - const { poolInitInfo, configInitInfo, configKeypairs } = await initTestPool( - ctx, - TickSpacing.Standard - ); - - const rewardIndex = 0; - - const { - params: { rewardVaultKeypair }, - } = await initializeReward( - ctx, - configKeypairs.rewardEmissionsSuperAuthorityKeypair, - poolInitInfo.whirlpoolPda.publicKey, - rewardIndex - ); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.setRewardEmissionsIx(ctx.program, { - rewardAuthority: configInitInfo.rewardEmissionsSuperAuthority, - whirlpool: poolInitInfo.whirlpoolPda.publicKey, - rewardIndex, - rewardVaultKey: rewardVaultKeypair.publicKey, - emissionsPerSecondX64, - }) - ) - .addSigner(configKeypairs.rewardEmissionsSuperAuthorityKeypair) - .buildAndExecute(), - /0x178b/ // RewardVaultAmountInsufficient - ); - }); - - it("fails if provided reward vault does not match whirlpool reward vault", async () => { - const { poolInitInfo, configInitInfo, configKeypairs } = await initTestPool( - ctx, - TickSpacing.Standard - ); - - const rewardIndex = 0; - const { - params: { rewardVaultKeypair, rewardMint }, - } = await initializeReward( - ctx, - configKeypairs.rewardEmissionsSuperAuthorityKeypair, - poolInitInfo.whirlpoolPda.publicKey, - rewardIndex - ); - - const fakeVault = await createAndMintToTokenAccount(provider, rewardMint, 10000); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.setRewardEmissionsIx(ctx.program, { - whirlpool: poolInitInfo.whirlpoolPda.publicKey, - rewardAuthority: configInitInfo.rewardEmissionsSuperAuthority, - rewardVaultKey: fakeVault, - rewardIndex, - emissionsPerSecondX64, - }) - ) - .addSigner(configKeypairs.rewardEmissionsSuperAuthorityKeypair) - .buildAndExecute(), - /0x7dc/ // An address constraint was violated - ); - }); - - it("cannot set emission for an uninitialized reward", async () => { - const { poolInitInfo, configInitInfo, configKeypairs } = await initTestPool( - ctx, - TickSpacing.Standard - ); - - const rewardIndex = 0; - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.setRewardEmissionsIx(ctx.program, { - whirlpool: poolInitInfo.whirlpoolPda.publicKey, - rewardAuthority: configInitInfo.rewardEmissionsSuperAuthority, - rewardVaultKey: anchor.web3.PublicKey.default, - rewardIndex: rewardIndex, - emissionsPerSecondX64, - }) - ) - .addSigner(configKeypairs.rewardEmissionsSuperAuthorityKeypair) - .buildAndExecute(), - /0xbbf/ // AccountOwnedByWrongProgram - ); - }); - - it("cannot set emission without the authority's signature", async () => { - const { poolInitInfo, configInitInfo, configKeypairs } = await initTestPool( - ctx, - TickSpacing.Standard - ); - - const rewardIndex = 0; - - await initializeReward( - ctx, - configKeypairs.rewardEmissionsSuperAuthorityKeypair, - poolInitInfo.whirlpoolPda.publicKey, - rewardIndex - ); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.setRewardEmissionsIx(ctx.program, { - rewardAuthority: configInitInfo.rewardEmissionsSuperAuthority, - whirlpool: poolInitInfo.whirlpoolPda.publicKey, - rewardIndex, - rewardVaultKey: provider.wallet.publicKey, // TODO fix - emissionsPerSecondX64, - }) - ).buildAndExecute(), - /.*signature verification fail.*/i - ); - }); -}); diff --git a/sdk/tests/integration/set_reward_emissions_super_authority.test.ts b/sdk/tests/integration/set_reward_emissions_super_authority.test.ts deleted file mode 100644 index 8741579..0000000 --- a/sdk/tests/integration/set_reward_emissions_super_authority.test.ts +++ /dev/null @@ -1,75 +0,0 @@ -import * as anchor from "@coral-xyz/anchor"; -import * as assert from "assert"; -import { toTx, WhirlpoolContext, WhirlpoolIx, WhirlpoolsConfigData } from "../../src"; -import { defaultConfirmOptions } from "../utils/const"; -import { generateDefaultConfigParams } from "../utils/test-builders"; - -describe("set_reward_emissions_super_authority", () => { - const provider = anchor.AnchorProvider.local(undefined, defaultConfirmOptions); - - const program = anchor.workspace.Whirlpool; - const ctx = WhirlpoolContext.fromWorkspace(provider, program); - const fetcher = ctx.fetcher; - - it("successfully set_reward_emissions_super_authority with super authority keypair", async () => { - const { - configInitInfo, - configKeypairs: { rewardEmissionsSuperAuthorityKeypair }, - } = generateDefaultConfigParams(ctx); - - await toTx(ctx, WhirlpoolIx.initializeConfigIx(ctx.program, configInitInfo)).buildAndExecute(); - const newAuthorityKeypair = anchor.web3.Keypair.generate(); - - await toTx( - ctx, - WhirlpoolIx.setRewardEmissionsSuperAuthorityIx(ctx.program, { - whirlpoolsConfig: configInitInfo.whirlpoolsConfigKeypair.publicKey, - rewardEmissionsSuperAuthority: rewardEmissionsSuperAuthorityKeypair.publicKey, - newRewardEmissionsSuperAuthority: newAuthorityKeypair.publicKey, - }) - ) - .addSigner(rewardEmissionsSuperAuthorityKeypair) - .buildAndExecute(); - - const config = (await fetcher.getConfig( - configInitInfo.whirlpoolsConfigKeypair.publicKey - )) as WhirlpoolsConfigData; - assert.ok(config.rewardEmissionsSuperAuthority.equals(newAuthorityKeypair.publicKey)); - }); - - it("fails if current reward_emissions_super_authority is not a signer", async () => { - const { - configInitInfo, - configKeypairs: { rewardEmissionsSuperAuthorityKeypair }, - } = generateDefaultConfigParams(ctx); - await toTx(ctx, WhirlpoolIx.initializeConfigIx(ctx.program, configInitInfo)).buildAndExecute(); - - await assert.rejects( - ctx.program.rpc.setRewardEmissionsSuperAuthority({ - accounts: { - whirlpoolsConfig: configInitInfo.whirlpoolsConfigKeypair.publicKey, - rewardEmissionsSuperAuthority: rewardEmissionsSuperAuthorityKeypair.publicKey, - newRewardEmissionsSuperAuthority: provider.wallet.publicKey, - }, - }), - /.*signature verification fail.*/i - ); - }); - - it("fails if incorrect reward_emissions_super_authority is passed in", async () => { - const { configInitInfo } = generateDefaultConfigParams(ctx); - await toTx(ctx, WhirlpoolIx.initializeConfigIx(ctx.program, configInitInfo)).buildAndExecute(); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.setRewardEmissionsSuperAuthorityIx(ctx.program, { - whirlpoolsConfig: configInitInfo.whirlpoolsConfigKeypair.publicKey, - rewardEmissionsSuperAuthority: provider.wallet.publicKey, - newRewardEmissionsSuperAuthority: provider.wallet.publicKey, - }) - ).buildAndExecute(), - /0x7dc/ // An address constraint was violated - ); - }); -}); diff --git a/sdk/tests/integration/swap.test.ts b/sdk/tests/integration/swap.test.ts deleted file mode 100644 index 4776159..0000000 --- a/sdk/tests/integration/swap.test.ts +++ /dev/null @@ -1,1630 +0,0 @@ -import * as anchor from "@coral-xyz/anchor"; -import { web3 } from "@coral-xyz/anchor"; -import { MathUtil, Percentage } from "@orca-so/common-sdk"; -import * as assert from "assert"; -import { BN } from "bn.js"; -import Decimal from "decimal.js"; -import { - MAX_SQRT_PRICE, - MIN_SQRT_PRICE, - PDAUtil, - PriceMath, - SwapParams, - TICK_ARRAY_SIZE, - TickArrayData, - TickUtil, - WhirlpoolContext, - WhirlpoolIx, - buildWhirlpoolClient, - swapQuoteByInputToken, - toTx -} from "../../src"; -import { IGNORE_CACHE } from "../../src/network/public/fetcher"; -import { MAX_U64, TickSpacing, ZERO_BN, getTokenBalance } from "../utils"; -import { defaultConfirmOptions } from "../utils/const"; -import { - FundedPositionParams, - fundPositions, - initTestPool, - initTestPoolWithLiquidity, - initTestPoolWithTokens, - initTickArrayRange, - withdrawPositions -} from "../utils/init-utils"; - -describe("swap", () => { - const provider = anchor.AnchorProvider.local(undefined, defaultConfirmOptions); - - const program = anchor.workspace.Whirlpool; - const ctx = WhirlpoolContext.fromWorkspace(provider, program); - const fetcher = ctx.fetcher; - const client = buildWhirlpoolClient(ctx); - - it("fail on token vault mint a does not match whirlpool token a", async () => { - const { poolInitInfo, whirlpoolPda, tokenAccountA, tokenAccountB } = - await initTestPoolWithTokens(ctx, TickSpacing.Standard); - - const { poolInitInfo: anotherPoolInitInfo } = await initTestPoolWithTokens( - ctx, - TickSpacing.Stable - ); - - const tickArrays = await initTickArrayRange( - ctx, - whirlpoolPda.publicKey, - 22528, - 3, - TickSpacing.Standard, - false - ); - - const oraclePda = PDAUtil.getOracle(ctx.program.programId, whirlpoolPda.publicKey); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.swapIx(ctx.program, { - amount: new BN(10), - otherAmountThreshold: ZERO_BN, - sqrtPriceLimit: MathUtil.toX64(new Decimal(4.95)), - amountSpecifiedIsInput: true, - aToB: true, - whirlpool: whirlpoolPda.publicKey, - tokenAuthority: ctx.wallet.publicKey, - tokenOwnerAccountA: tokenAccountA, - tokenVaultA: anotherPoolInitInfo.tokenVaultAKeypair.publicKey, - tokenOwnerAccountB: tokenAccountB, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArray0: tickArrays[0].publicKey, - tickArray1: tickArrays[0].publicKey, - tickArray2: tickArrays[0].publicKey, - oracle: oraclePda.publicKey, - }) - ).buildAndExecute(), - /0x7dc/ // ConstraintAddress - ); - }); - - it("fail on token vault mint b does not match whirlpool token b", async () => { - const { poolInitInfo, whirlpoolPda, tokenAccountA, tokenAccountB } = - await initTestPoolWithTokens(ctx, TickSpacing.Standard); - - const { poolInitInfo: anotherPoolInitInfo } = await initTestPoolWithTokens( - ctx, - TickSpacing.Stable - ); - - const tickArrays = await initTickArrayRange( - ctx, - whirlpoolPda.publicKey, - 22528, - 3, - TickSpacing.Standard, - false - ); - - const oraclePda = PDAUtil.getOracle(ctx.program.programId, whirlpoolPda.publicKey); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.swapIx(ctx.program, { - amount: new BN(10), - otherAmountThreshold: ZERO_BN, - sqrtPriceLimit: MathUtil.toX64(new Decimal(4.95)), - amountSpecifiedIsInput: true, - aToB: true, - whirlpool: whirlpoolPda.publicKey, - tokenAuthority: ctx.wallet.publicKey, - tokenOwnerAccountA: tokenAccountA, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenOwnerAccountB: tokenAccountB, - tokenVaultB: anotherPoolInitInfo.tokenVaultBKeypair.publicKey, - tickArray0: tickArrays[0].publicKey, - tickArray1: tickArrays[0].publicKey, - tickArray2: tickArrays[0].publicKey, - oracle: oraclePda.publicKey, - }) - ).buildAndExecute(), - /0x7dc/ // ConstraintAddress - ); - }); - - it("fail on token owner account a does not match vault a mint", async () => { - const { poolInitInfo, whirlpoolPda, tokenAccountB } = await initTestPoolWithTokens( - ctx, - TickSpacing.Standard - ); - - const { tokenAccountA: anotherTokenAccountA } = await initTestPoolWithTokens( - ctx, - TickSpacing.Stable - ); - - const tickArrays = await initTickArrayRange( - ctx, - whirlpoolPda.publicKey, - 22528, - 3, - TickSpacing.Standard, - false - ); - - const oraclePda = PDAUtil.getOracle(ctx.program.programId, whirlpoolPda.publicKey); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.swapIx(ctx.program, { - amount: new BN(10), - otherAmountThreshold: ZERO_BN, - sqrtPriceLimit: MathUtil.toX64(new Decimal(4.95)), - amountSpecifiedIsInput: true, - aToB: true, - whirlpool: whirlpoolPda.publicKey, - tokenAuthority: ctx.wallet.publicKey, - tokenOwnerAccountA: anotherTokenAccountA, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenOwnerAccountB: tokenAccountB, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArray0: tickArrays[0].publicKey, - tickArray1: tickArrays[0].publicKey, - tickArray2: tickArrays[0].publicKey, - oracle: oraclePda.publicKey, - }) - ).buildAndExecute(), - /0x7d3/ // ConstraintRaw - ); - }); - - it("fail on token owner account b does not match vault b mint", async () => { - const { poolInitInfo, whirlpoolPda, tokenAccountA } = await initTestPoolWithTokens( - ctx, - TickSpacing.Standard - ); - - const { tokenAccountB: anotherTokenAccountB } = await initTestPoolWithTokens( - ctx, - TickSpacing.Stable - ); - - const tickArrays = await initTickArrayRange( - ctx, - whirlpoolPda.publicKey, - 22528, - 3, - TickSpacing.Standard, - false - ); - - const oraclePda = PDAUtil.getOracle(ctx.program.programId, whirlpoolPda.publicKey); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.swapIx(ctx.program, { - amount: new BN(10), - otherAmountThreshold: ZERO_BN, - sqrtPriceLimit: MathUtil.toX64(new Decimal(4.95)), - amountSpecifiedIsInput: true, - aToB: true, - whirlpool: whirlpoolPda.publicKey, - tokenAuthority: ctx.wallet.publicKey, - tokenOwnerAccountA: tokenAccountA, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenOwnerAccountB: anotherTokenAccountB, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArray0: tickArrays[0].publicKey, - tickArray1: tickArrays[0].publicKey, - tickArray2: tickArrays[0].publicKey, - oracle: oraclePda.publicKey, - }) - ).buildAndExecute(), - /0x7d3/ // ConstraintRaw - ); - }); - - it("fails to swap with incorrect token authority", async () => { - const { poolInitInfo, whirlpoolPda, tokenAccountA, tokenAccountB } = - await initTestPoolWithTokens(ctx, TickSpacing.Standard); - - const tickArrays = await initTickArrayRange( - ctx, - whirlpoolPda.publicKey, - 22528, - 3, - TickSpacing.Standard, - false - ); - - const otherTokenAuthority = web3.Keypair.generate(); - - const oraclePda = PDAUtil.getOracle(ctx.program.programId, whirlpoolPda.publicKey); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.swapIx(ctx.program, { - amount: new BN(10), - otherAmountThreshold: ZERO_BN, - sqrtPriceLimit: MathUtil.toX64(new Decimal(4.95)), - amountSpecifiedIsInput: true, - aToB: true, - whirlpool: whirlpoolPda.publicKey, - tokenAuthority: otherTokenAuthority.publicKey, - tokenOwnerAccountA: tokenAccountA, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenOwnerAccountB: tokenAccountB, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArray0: tickArrays[0].publicKey, - tickArray1: tickArrays[0].publicKey, - tickArray2: tickArrays[0].publicKey, - oracle: oraclePda.publicKey, - }) - ) - .addSigner(otherTokenAuthority) - .buildAndExecute(), - /0x4/ // OwnerMismatch - ); - }); - - it("fails on passing in the wrong tick-array", async () => { - const { poolInitInfo, whirlpoolPda, tokenAccountA, tokenAccountB } = - await initTestPoolWithTokens( - ctx, - TickSpacing.Standard, - MathUtil.toX64(new Decimal(0.0242).sqrt()) - ); // Negative Tick - - const tickArrays = await initTickArrayRange( - ctx, - whirlpoolPda.publicKey, - 22528, - 3, - TickSpacing.Standard, - false - ); - - const oraclePda = PDAUtil.getOracle(ctx.program.programId, whirlpoolPda.publicKey); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.swapIx(ctx.program, { - amount: new BN(10), - otherAmountThreshold: ZERO_BN, - sqrtPriceLimit: PriceMath.tickIndexToSqrtPriceX64(-50000), - amountSpecifiedIsInput: true, - aToB: true, - whirlpool: whirlpoolPda.publicKey, - tokenAuthority: ctx.wallet.publicKey, - tokenOwnerAccountA: tokenAccountA, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenOwnerAccountB: tokenAccountB, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArray0: tickArrays[0].publicKey, - tickArray1: tickArrays[0].publicKey, - tickArray2: tickArrays[0].publicKey, - oracle: oraclePda.publicKey, - }) - ).buildAndExecute(), - /0x1787/ // InvalidTickArraySequence - ); - }); - - it("fails on passing in the wrong whirlpool", async () => { - const { poolInitInfo, whirlpoolPda, tokenAccountA, tokenAccountB } = - await initTestPoolWithTokens(ctx, TickSpacing.Standard); - - const { poolInitInfo: anotherPoolInitInfo } = await initTestPool(ctx, TickSpacing.Standard); - - const tickArrays = await initTickArrayRange( - ctx, - whirlpoolPda.publicKey, - 22528, - 3, - TickSpacing.Standard, - false - ); - - const oraclePda = PDAUtil.getOracle(ctx.program.programId, whirlpoolPda.publicKey); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.swapIx(ctx.program, { - amount: new BN(10), - otherAmountThreshold: ZERO_BN, - sqrtPriceLimit: MathUtil.toX64(new Decimal(4.95)), - amountSpecifiedIsInput: true, - aToB: true, - whirlpool: anotherPoolInitInfo.whirlpoolPda.publicKey, - tokenAuthority: ctx.wallet.publicKey, - tokenOwnerAccountA: tokenAccountA, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenOwnerAccountB: tokenAccountB, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArray0: tickArrays[0].publicKey, - tickArray1: tickArrays[0].publicKey, - tickArray2: tickArrays[0].publicKey, - oracle: oraclePda.publicKey, - }) - ).buildAndExecute(), - /0x7d3/ // ConstraintRaw - ); - }); - - it("fails on passing in the tick-arrays from another whirlpool", async () => { - const { poolInitInfo, whirlpoolPda, tokenAccountA, tokenAccountB } = - await initTestPoolWithTokens(ctx, TickSpacing.Standard); - - const { poolInitInfo: anotherPoolInitInfo } = await initTestPool(ctx, TickSpacing.Standard); - - const tickArrays = await initTickArrayRange( - ctx, - anotherPoolInitInfo.whirlpoolPda.publicKey, - 22528, - 3, - TickSpacing.Standard, - false - ); - - const oraclePda = PDAUtil.getOracle(ctx.program.programId, whirlpoolPda.publicKey); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.swapIx(ctx.program, { - amount: new BN(10), - otherAmountThreshold: ZERO_BN, - sqrtPriceLimit: MathUtil.toX64(new Decimal(4.95)), - amountSpecifiedIsInput: true, - aToB: true, - whirlpool: anotherPoolInitInfo.whirlpoolPda.publicKey, - tokenAuthority: ctx.wallet.publicKey, - tokenOwnerAccountA: tokenAccountA, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenOwnerAccountB: tokenAccountB, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArray0: tickArrays[0].publicKey, - tickArray1: tickArrays[0].publicKey, - tickArray2: tickArrays[0].publicKey, - oracle: oraclePda.publicKey, - }) - ).buildAndExecute(), - /0x7d3/ // ConstraintRaw - ); - }); - - it("fails on passing in an account of another type for the oracle", async () => { - const { poolInitInfo, whirlpoolPda, tokenAccountA, tokenAccountB } = - await initTestPoolWithTokens(ctx, TickSpacing.Standard); - - const tickArrays = await initTickArrayRange( - ctx, - whirlpoolPda.publicKey, - 22528, - 3, - TickSpacing.Standard, - false - ); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.swapIx(ctx.program, { - amount: new BN(10), - otherAmountThreshold: ZERO_BN, - sqrtPriceLimit: MathUtil.toX64(new Decimal(4.95)), - amountSpecifiedIsInput: true, - aToB: true, - whirlpool: poolInitInfo.whirlpoolPda.publicKey, - tokenAuthority: ctx.wallet.publicKey, - tokenOwnerAccountA: tokenAccountA, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenOwnerAccountB: tokenAccountB, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArray0: tickArrays[0].publicKey, - tickArray1: tickArrays[0].publicKey, - tickArray2: tickArrays[0].publicKey, - oracle: tickArrays[0].publicKey, - }) - ).buildAndExecute(), - /0x7d6/ // ConstraintSeeds - ); - }); - - it("fails on passing in an incorrectly hashed oracle PDA", async () => { - const { poolInitInfo, whirlpoolPda, tokenAccountA, tokenAccountB } = - await initTestPoolWithTokens(ctx, TickSpacing.Standard); - - const { poolInitInfo: anotherPoolInitInfo } = await initTestPool(ctx, TickSpacing.Standard); - - const tickArrays = await initTickArrayRange( - ctx, - whirlpoolPda.publicKey, - 22528, - 3, - TickSpacing.Standard, - false - ); - - const anotherOraclePda = PDAUtil.getOracle( - ctx.program.programId, - anotherPoolInitInfo.whirlpoolPda.publicKey - ); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.swapIx(ctx.program, { - amount: new BN(10), - otherAmountThreshold: ZERO_BN, - sqrtPriceLimit: MathUtil.toX64(new Decimal(4.95)), - amountSpecifiedIsInput: true, - aToB: true, - whirlpool: poolInitInfo.whirlpoolPda.publicKey, - tokenAuthority: ctx.wallet.publicKey, - tokenOwnerAccountA: tokenAccountA, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenOwnerAccountB: tokenAccountB, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArray0: tickArrays[0].publicKey, - tickArray1: tickArrays[0].publicKey, - tickArray2: tickArrays[0].publicKey, - oracle: anotherOraclePda.publicKey, - }) - ).buildAndExecute(), - /0x7d6/ // ConstraintSeeds - ); - }); - - it("fail on passing in zero tradable amount", async () => { - const { poolInitInfo, whirlpoolPda, tokenAccountA, tokenAccountB } = - await initTestPoolWithTokens(ctx, TickSpacing.Standard); - - const tickArrays = await initTickArrayRange( - ctx, - whirlpoolPda.publicKey, - 33792, - 3, - TickSpacing.Standard, - false - ); - - const oraclePda = PDAUtil.getOracle(ctx.program.programId, whirlpoolPda.publicKey); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.swapIx(ctx.program, { - amount: new BN(0), - otherAmountThreshold: ZERO_BN, - sqrtPriceLimit: MathUtil.toX64(new Decimal(4.95)), - amountSpecifiedIsInput: true, - aToB: true, - whirlpool: whirlpoolPda.publicKey, - tokenAuthority: ctx.wallet.publicKey, - tokenOwnerAccountA: tokenAccountA, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenOwnerAccountB: tokenAccountB, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArray0: tickArrays[0].publicKey, - tickArray1: tickArrays[0].publicKey, - tickArray2: tickArrays[0].publicKey, - oracle: oraclePda.publicKey, - }) - ).buildAndExecute(), - /0x1793/ // ZeroTradableAmount - ); - }); - - it("swaps across one tick array", async () => { - const { poolInitInfo, whirlpoolPda, tokenAccountA, tokenAccountB } = - await initTestPoolWithTokens(ctx, TickSpacing.Standard); - const aToB = false; - await initTickArrayRange( - ctx, - whirlpoolPda.publicKey, - 22528, // to 33792 - 3, - TickSpacing.Standard, - aToB - ); - - const fundParams: FundedPositionParams[] = [ - { - liquidityAmount: new anchor.BN(10_000_000), - tickLowerIndex: 29440, - tickUpperIndex: 33536, - }, - ]; - - await fundPositions(ctx, poolInitInfo, tokenAccountA, tokenAccountB, fundParams); - - const tokenVaultABefore = new anchor.BN( - await getTokenBalance(provider, poolInitInfo.tokenVaultAKeypair.publicKey) - ); - const tokenVaultBBefore = new anchor.BN( - await getTokenBalance(provider, poolInitInfo.tokenVaultBKeypair.publicKey) - ); - - const oraclePda = PDAUtil.getOracle(ctx.program.programId, whirlpoolPda.publicKey); - - const whirlpoolKey = poolInitInfo.whirlpoolPda.publicKey; - const whirlpool = await client.getPool(whirlpoolKey, IGNORE_CACHE); - const whirlpoolData = whirlpool.getData(); - const quote = await swapQuoteByInputToken( - whirlpool, - whirlpoolData.tokenMintB, - new BN(100000), - Percentage.fromFraction(1, 100), - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - - await toTx( - ctx, - WhirlpoolIx.swapIx(ctx.program, { - ...quote, - whirlpool: whirlpoolPda.publicKey, - tokenAuthority: ctx.wallet.publicKey, - tokenOwnerAccountA: tokenAccountA, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenOwnerAccountB: tokenAccountB, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - oracle: oraclePda.publicKey, - }) - ).buildAndExecute(); - - assert.equal( - await getTokenBalance(provider, poolInitInfo.tokenVaultAKeypair.publicKey), - tokenVaultABefore.sub(quote.estimatedAmountOut).toString() - ); - assert.equal( - await getTokenBalance(provider, poolInitInfo.tokenVaultBKeypair.publicKey), - tokenVaultBBefore.add(quote.estimatedAmountIn).toString() - ); - }); - - it("swaps aToB across initialized tick with no movement", async () => { - const startingTick = 91720; - const tickSpacing = TickSpacing.Stable; - const startingTickArrayStartIndex = TickUtil.getStartTickIndex(startingTick, tickSpacing); - const aToB = true; - const startSqrtPrice = PriceMath.tickIndexToSqrtPriceX64(startingTick); - const initialLiquidity = new anchor.BN(10_000_000); - const additionalLiquidity = new anchor.BN(2_000_000); - - const { poolInitInfo, whirlpoolPda, tokenAccountA, tokenAccountB } = - await initTestPoolWithTokens(ctx, TickSpacing.Stable, startSqrtPrice); - await initTickArrayRange( - ctx, - whirlpoolPda.publicKey, - startingTickArrayStartIndex + TICK_ARRAY_SIZE * tickSpacing * 2, - 5, - TickSpacing.Stable, - aToB - ); - const oraclePda = PDAUtil.getOracle(ctx.program.programId, whirlpoolPda.publicKey); - - const initialParams: FundedPositionParams[] = [ - { - liquidityAmount: initialLiquidity, - tickLowerIndex: startingTickArrayStartIndex + tickSpacing, - tickUpperIndex: - startingTickArrayStartIndex + TICK_ARRAY_SIZE * tickSpacing * 2 - tickSpacing, - }, - ]; - - await fundPositions(ctx, poolInitInfo, tokenAccountA, tokenAccountB, initialParams); - - const whirlpoolKey = poolInitInfo.whirlpoolPda.publicKey; - let whirlpool = await client.getPool(whirlpoolKey, IGNORE_CACHE); - let whirlpoolData = whirlpool.getData(); - - // Position covers the current price, so liquidity should be equal to the initial funded position - assert.ok(whirlpoolData.liquidity.eq(new anchor.BN(10_000_000))); - - const nextParams: FundedPositionParams[] = [ - { - liquidityAmount: additionalLiquidity, - tickLowerIndex: startingTick - tickSpacing * 2, - tickUpperIndex: startingTick, - }, - ]; - - await fundPositions(ctx, poolInitInfo, tokenAccountA, tokenAccountB, nextParams); - - whirlpool = await client.getPool(whirlpoolKey, IGNORE_CACHE); - whirlpoolData = whirlpool.getData(); - // Whirlpool.currentTick is 91720, so the newly funded position's upper tick is not - // strictly less than 91720 so the liquidity is not added. - assert.ok(whirlpoolData.liquidity.eq(initialLiquidity)); - assert.ok(whirlpoolData.sqrtPrice.eq(startSqrtPrice)); - assert.equal(whirlpoolData.tickCurrentIndex, startingTick); - - const quote = await swapQuoteByInputToken( - whirlpool, - whirlpoolData.tokenMintA, - new BN(1), - Percentage.fromFraction(1, 100), - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - - await toTx( - ctx, - WhirlpoolIx.swapIx(ctx.program, { - ...quote, - whirlpool: whirlpoolPda.publicKey, - tokenAuthority: ctx.wallet.publicKey, - tokenOwnerAccountA: tokenAccountA, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenOwnerAccountB: tokenAccountB, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - oracle: oraclePda.publicKey, - }) - ).buildAndExecute(); - - whirlpool = await client.getPool(whirlpoolKey, IGNORE_CACHE); - whirlpoolData = whirlpool.getData(); - - // After the above swap, since the amount is so low, it is completely taken by fees - // thus, the sqrt price will remain the same, the starting tick will decrement since it - // is an aToB swap ending on initialized tick, and since the tick is crossed, - // the liquidity will be added - assert.equal(whirlpoolData.tickCurrentIndex, startingTick - 1); - assert.ok(whirlpoolData.sqrtPrice.eq(startSqrtPrice)); - assert.ok(whirlpoolData.liquidity.eq(initialLiquidity.add(additionalLiquidity))); - - const quote2 = await swapQuoteByInputToken( - whirlpool, - whirlpoolData.tokenMintA, - new BN(1), - Percentage.fromFraction(1, 100), - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - - await toTx( - ctx, - WhirlpoolIx.swapIx(ctx.program, { - ...quote2, - whirlpool: whirlpoolPda.publicKey, - tokenAuthority: ctx.wallet.publicKey, - tokenOwnerAccountA: tokenAccountA, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenOwnerAccountB: tokenAccountB, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - oracle: oraclePda.publicKey, - }) - ).buildAndExecute(); - - whirlpool = await client.getPool(whirlpoolKey, IGNORE_CACHE); - whirlpoolData = whirlpool.getData(); - - // After the above swap, since the amount is so low, it is completely taken by fees - // thus, the sqrt price will remaing the same, the starting tick will not decrement - // since it is an aToB swap ending on an uninitialized tick, no tick is crossed - assert.equal(whirlpoolData.tickCurrentIndex, startingTick - 1); - assert.ok(whirlpoolData.sqrtPrice.eq(startSqrtPrice)); - assert.ok(whirlpoolData.liquidity.eq(initialLiquidity.add(additionalLiquidity))); - }); - - it("swaps aToB with small remainder across initialized tick", async () => { - const startingTick = 91728; - const tickSpacing = TickSpacing.Stable; - const startingTickArrayStartIndex = TickUtil.getStartTickIndex(startingTick, tickSpacing); - const aToB = true; - const startSqrtPrice = PriceMath.tickIndexToSqrtPriceX64(startingTick); - const initialLiquidity = new anchor.BN(10_000_000); - const additionalLiquidity = new anchor.BN(2_000_000); - - const { poolInitInfo, whirlpoolPda, tokenAccountA, tokenAccountB } = - await initTestPoolWithTokens(ctx, TickSpacing.Stable, startSqrtPrice); - await initTickArrayRange( - ctx, - whirlpoolPda.publicKey, - startingTickArrayStartIndex + TICK_ARRAY_SIZE * tickSpacing * 2, - 5, - TickSpacing.Stable, - aToB - ); - const oraclePda = PDAUtil.getOracle(ctx.program.programId, whirlpoolPda.publicKey); - - const initialParams: FundedPositionParams[] = [ - { - liquidityAmount: initialLiquidity, - tickLowerIndex: startingTickArrayStartIndex + tickSpacing, - tickUpperIndex: - startingTickArrayStartIndex + TICK_ARRAY_SIZE * tickSpacing * 2 - tickSpacing, - }, - ]; - - await fundPositions(ctx, poolInitInfo, tokenAccountA, tokenAccountB, initialParams); - - const whirlpoolKey = poolInitInfo.whirlpoolPda.publicKey; - let whirlpool = await client.getPool(whirlpoolKey, IGNORE_CACHE); - let whirlpoolData = whirlpool.getData(); - - // Position covers the current price, so liquidity should be equal to the initial funded position - assert.ok(whirlpoolData.liquidity.eq(new anchor.BN(10_000_000))); - - const nextParams: FundedPositionParams[] = [ - { - liquidityAmount: additionalLiquidity, - tickLowerIndex: startingTick - tickSpacing * 3, - tickUpperIndex: startingTick - tickSpacing, - }, - ]; - - await fundPositions(ctx, poolInitInfo, tokenAccountA, tokenAccountB, nextParams); - - whirlpool = await client.getPool(whirlpoolKey, IGNORE_CACHE); - whirlpoolData = whirlpool.getData(); - // Whirlpool.currentTick is 91720, so the newly funded position's upper tick is not - // strictly less than 91720 so the liquidity is not added. - assert.ok(whirlpoolData.liquidity.eq(initialLiquidity)); - assert.ok(whirlpoolData.sqrtPrice.eq(startSqrtPrice)); - assert.equal(whirlpoolData.tickCurrentIndex, startingTick); - - const quote = await swapQuoteByInputToken( - whirlpool, - whirlpoolData.tokenMintA, - new BN(1), - Percentage.fromFraction(1, 100), - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - - await toTx( - ctx, - WhirlpoolIx.swapIx(ctx.program, { - ...quote, - whirlpool: whirlpoolPda.publicKey, - tokenAuthority: ctx.wallet.publicKey, - tokenOwnerAccountA: tokenAccountA, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenOwnerAccountB: tokenAccountB, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - oracle: oraclePda.publicKey, - }) - ).buildAndExecute(); - - whirlpool = await client.getPool(whirlpoolKey, IGNORE_CACHE); - whirlpoolData = whirlpool.getData(); - - // After the above swap, since the amount is so low, it is completely taken by fees - // thus, the sqrt price will remain the same, the starting tick will stay the same since it - // is an aToB swap ending on initialized tick and no tick is crossed - assert.equal(whirlpoolData.tickCurrentIndex, startingTick); - assert.ok(whirlpoolData.sqrtPrice.eq(startSqrtPrice)); - assert.ok(whirlpoolData.liquidity.eq(initialLiquidity)); - - const quote2 = await swapQuoteByInputToken( - whirlpool, - whirlpoolData.tokenMintA, - new BN(43), - Percentage.fromFraction(1, 100), - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - - await toTx( - ctx, - WhirlpoolIx.swapIx(ctx.program, { - ...quote2, - whirlpool: whirlpoolPda.publicKey, - tokenAuthority: ctx.wallet.publicKey, - tokenOwnerAccountA: tokenAccountA, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenOwnerAccountB: tokenAccountB, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - oracle: oraclePda.publicKey, - }) - ).buildAndExecute(); - - whirlpool = await client.getPool(whirlpoolKey, IGNORE_CACHE); - whirlpoolData = whirlpool.getData(); - - // After the above swap, there will be a small amount remaining that crosses - // an initialized tick index, but isn't enough to move the sqrt price. - assert.equal(whirlpoolData.tickCurrentIndex, startingTick - tickSpacing - 1); - assert.ok( - whirlpoolData.sqrtPrice.eq(PriceMath.tickIndexToSqrtPriceX64(startingTick - tickSpacing)) - ); - assert.ok(whirlpoolData.liquidity.eq(initialLiquidity.add(additionalLiquidity))); - }); - - it("swaps across three tick arrays", async () => { - const { poolInitInfo, whirlpoolPda, tokenAccountA, tokenAccountB } = - await initTestPoolWithTokens( - ctx, - TickSpacing.Stable, - PriceMath.tickIndexToSqrtPriceX64(27500) - ); - - const aToB = false; - const tickArrays = await initTickArrayRange( - ctx, - whirlpoolPda.publicKey, - 27456, // to 28160, 28864 - 5, - TickSpacing.Stable, - false - ); - - const fundParams: FundedPositionParams[] = [ - { - liquidityAmount: new anchor.BN(100_000_000), - tickLowerIndex: 27456, - tickUpperIndex: 27840, - }, - { - liquidityAmount: new anchor.BN(100_000_000), - tickLowerIndex: 28864, - tickUpperIndex: 28928, - }, - { - liquidityAmount: new anchor.BN(100_000_000), - tickLowerIndex: 27712, - tickUpperIndex: 28928, - }, - ]; - - await fundPositions(ctx, poolInitInfo, tokenAccountA, tokenAccountB, fundParams); - - assert.equal( - await getTokenBalance(provider, poolInitInfo.tokenVaultAKeypair.publicKey), - "1977429" - ); - assert.equal( - await getTokenBalance(provider, poolInitInfo.tokenVaultBKeypair.publicKey), - "869058" - ); - - const oraclePda = PDAUtil.getOracle(ctx.program.programId, whirlpoolPda.publicKey); - - // Tick - await toTx( - ctx, - WhirlpoolIx.swapIx(ctx.program, { - amount: new BN(7051000), - otherAmountThreshold: ZERO_BN, - sqrtPriceLimit: PriceMath.tickIndexToSqrtPriceX64(28500), - amountSpecifiedIsInput: true, - aToB: aToB, - whirlpool: whirlpoolPda.publicKey, - tokenAuthority: ctx.wallet.publicKey, - tokenOwnerAccountA: tokenAccountA, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenOwnerAccountB: tokenAccountB, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArray0: tickArrays[0].publicKey, - tickArray1: tickArrays[1].publicKey, - tickArray2: tickArrays[2].publicKey, - oracle: oraclePda.publicKey, - }) - ).buildAndExecute(); - - assert.equal( - await getTokenBalance(provider, poolInitInfo.tokenVaultAKeypair.publicKey), - "1535201" - ); - assert.equal( - await getTokenBalance(provider, poolInitInfo.tokenVaultBKeypair.publicKey), - "7920058" - ); - - // TODO: Verify fees and other whirlpool params - }); - - it("Error on passing in uninitialized tick-array", async () => { - const { poolInitInfo, tokenAccountA, tokenAccountB, tickArrays } = - await initTestPoolWithLiquidity(ctx); - const whirlpool = poolInitInfo.whirlpoolPda.publicKey; - - const uninitializedTickArrayPda = PDAUtil.getTickArray(ctx.program.programId, whirlpool, 0); - - const oraclePda = PDAUtil.getOracle(ctx.program.programId, poolInitInfo.whirlpoolPda.publicKey); - - const params: SwapParams = { - amount: new BN(10), - otherAmountThreshold: ZERO_BN, - sqrtPriceLimit: MathUtil.toX64(new Decimal(4294886578)), - amountSpecifiedIsInput: true, - aToB: true, - whirlpool: whirlpool, - tokenAuthority: ctx.wallet.publicKey, - tokenOwnerAccountA: tokenAccountA, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenOwnerAccountB: tokenAccountB, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArray0: tickArrays[0].publicKey, - tickArray1: uninitializedTickArrayPda.publicKey, - tickArray2: tickArrays[2].publicKey, - oracle: oraclePda.publicKey, - }; - - try { - await toTx(ctx, WhirlpoolIx.swapIx(ctx.program, params)).buildAndExecute(); - assert.fail("should fail if a tick-array is uninitialized"); - } catch (e) { - const error = e as Error; - assert.match(error.message, /0xbbf/); // AccountOwnedByWrongProgram - } - }); - - it("Error if sqrt_price_limit exceeds max", async () => { - const { poolInitInfo, tokenAccountA, tokenAccountB, tickArrays } = - await initTestPoolWithLiquidity(ctx); - const whirlpool = poolInitInfo.whirlpoolPda.publicKey; - - const oraclePda = PDAUtil.getOracle(ctx.program.programId, poolInitInfo.whirlpoolPda.publicKey); - - const params: SwapParams = { - amount: new BN(10), - otherAmountThreshold: ZERO_BN, - sqrtPriceLimit: new anchor.BN(MAX_SQRT_PRICE).add(new anchor.BN(1)), - amountSpecifiedIsInput: true, - aToB: true, - whirlpool: whirlpool, - tokenAuthority: ctx.wallet.publicKey, - tokenOwnerAccountA: tokenAccountA, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenOwnerAccountB: tokenAccountB, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArray0: tickArrays[0].publicKey, - tickArray1: tickArrays[1].publicKey, - tickArray2: tickArrays[2].publicKey, - oracle: oraclePda.publicKey, - }; - - try { - await toTx(ctx, WhirlpoolIx.swapIx(ctx.program, params)).buildAndExecute(); - assert.fail("should fail if sqrt_price exceeds maximum"); - } catch (e) { - const error = e as Error; - assert.match(error.message, /0x177b/); // SqrtPriceOutOfBounds - } - }); - - it("Error if sqrt_price_limit subceed min", async () => { - const { poolInitInfo, tokenAccountA, tokenAccountB, tickArrays } = - await initTestPoolWithLiquidity(ctx); - const whirlpool = poolInitInfo.whirlpoolPda.publicKey; - - const oraclePda = PDAUtil.getOracle(ctx.program.programId, poolInitInfo.whirlpoolPda.publicKey); - - const params: SwapParams = { - amount: new BN(10), - otherAmountThreshold: ZERO_BN, - sqrtPriceLimit: new anchor.BN(MIN_SQRT_PRICE).sub(new anchor.BN(1)), - amountSpecifiedIsInput: true, - aToB: true, - whirlpool: whirlpool, - tokenAuthority: ctx.wallet.publicKey, - tokenOwnerAccountA: tokenAccountA, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenOwnerAccountB: tokenAccountB, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArray0: tickArrays[0].publicKey, - tickArray1: tickArrays[1].publicKey, - tickArray2: tickArrays[2].publicKey, - oracle: oraclePda.publicKey, - }; - - try { - await toTx(ctx, WhirlpoolIx.swapIx(ctx.program, params)).buildAndExecute(); - assert.fail("should fail if sqrt_price subceeds minimum"); - } catch (e) { - const error = e as Error; - assert.match(error.message, /0x177b/); // SqrtPriceOutOfBounds - } - }); - - it("Error if a to b swap below minimum output", async () => { - const { poolInitInfo, whirlpoolPda, tokenAccountA, tokenAccountB } = - await initTestPoolWithTokens(ctx, TickSpacing.Standard); - - const tickArrays = await initTickArrayRange( - ctx, - whirlpoolPda.publicKey, - 22528, // to 33792 - 3, - TickSpacing.Standard, - false - ); - - const fundParams: FundedPositionParams[] = [ - { - liquidityAmount: new anchor.BN(100_000), - tickLowerIndex: 29440, - tickUpperIndex: 33536, - }, - ]; - - await fundPositions(ctx, poolInitInfo, tokenAccountA, tokenAccountB, fundParams); - - const oraclePda = PDAUtil.getOracle(ctx.program.programId, whirlpoolPda.publicKey); - - const params = { - amount: new BN(10), - otherAmountThreshold: MAX_U64, - sqrtPriceLimit: new anchor.BN(MIN_SQRT_PRICE), - amountSpecifiedIsInput: true, - aToB: true, - whirlpool: whirlpoolPda.publicKey, - tokenAuthority: ctx.wallet.publicKey, - tokenOwnerAccountA: tokenAccountA, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenOwnerAccountB: tokenAccountB, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArray0: tickArrays[0].publicKey, - tickArray1: tickArrays[0].publicKey, - tickArray2: tickArrays[0].publicKey, - oracle: oraclePda.publicKey, - }; - - try { - await toTx(ctx, WhirlpoolIx.swapIx(ctx.program, params)).buildAndExecute(); - assert.fail("should fail if amount out is below threshold"); - } catch (e) { - const error = e as Error; - assert.match(error.message, /0x1794/); // AmountOutBelowMinimum - } - }); - - it("Error if b to a swap below minimum output", async () => { - const { poolInitInfo, whirlpoolPda, tokenAccountA, tokenAccountB } = - await initTestPoolWithTokens(ctx, TickSpacing.Standard); - - const tickArrays = await initTickArrayRange( - ctx, - whirlpoolPda.publicKey, - 22528, // to 33792 - 3, - TickSpacing.Standard, - false - ); - - const fundParams: FundedPositionParams[] = [ - { - liquidityAmount: new anchor.BN(100_000), - tickLowerIndex: 29440, - tickUpperIndex: 33536, - }, - ]; - - await fundPositions(ctx, poolInitInfo, tokenAccountA, tokenAccountB, fundParams); - - const oraclePda = PDAUtil.getOracle(ctx.program.programId, whirlpoolPda.publicKey); - - const params = { - amount: new BN(10), - otherAmountThreshold: MAX_U64, - sqrtPriceLimit: new anchor.BN(MAX_SQRT_PRICE), - amountSpecifiedIsInput: true, - aToB: false, - whirlpool: whirlpoolPda.publicKey, - tokenAuthority: ctx.wallet.publicKey, - tokenOwnerAccountA: tokenAccountA, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenOwnerAccountB: tokenAccountB, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArray0: tickArrays[0].publicKey, - tickArray1: tickArrays[0].publicKey, - tickArray2: tickArrays[0].publicKey, - oracle: oraclePda.publicKey, - }; - - try { - await toTx(ctx, WhirlpoolIx.swapIx(ctx.program, params)).buildAndExecute(); - assert.fail("should fail if amount out is below threshold"); - } catch (e) { - const error = e as Error; - assert.match(error.message, /0x1794/); // AmountOutBelowMinimum - } - }); - - it("Error if a to b swap above maximum input", async () => { - const { poolInitInfo, whirlpoolPda, tokenAccountA, tokenAccountB } = - await initTestPoolWithTokens(ctx, TickSpacing.Standard); - - const tickArrays = await initTickArrayRange( - ctx, - whirlpoolPda.publicKey, - 22528, // to 33792 - 3, - TickSpacing.Standard, - false - ); - - const fundParams: FundedPositionParams[] = [ - { - liquidityAmount: new anchor.BN(100_000), - tickLowerIndex: 29440, - tickUpperIndex: 33536, - }, - ]; - - await fundPositions(ctx, poolInitInfo, tokenAccountA, tokenAccountB, fundParams); - - const oraclePda = PDAUtil.getOracle(ctx.program.programId, whirlpoolPda.publicKey); - - const params = { - amount: new BN(10), - otherAmountThreshold: ZERO_BN, - sqrtPriceLimit: new anchor.BN(MIN_SQRT_PRICE), - amountSpecifiedIsInput: false, - aToB: true, - whirlpool: whirlpoolPda.publicKey, - tokenAuthority: ctx.wallet.publicKey, - tokenOwnerAccountA: tokenAccountA, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenOwnerAccountB: tokenAccountB, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArray0: tickArrays[0].publicKey, - tickArray1: tickArrays[0].publicKey, - tickArray2: tickArrays[0].publicKey, - oracle: oraclePda.publicKey, - }; - - try { - await toTx(ctx, WhirlpoolIx.swapIx(ctx.program, params)).buildAndExecute(); - assert.fail("should fail if amount out is below threshold"); - } catch (e) { - const error = e as Error; - assert.match(error.message, /0x1795/); // AmountInAboveMaximum - } - }); - - it("Error if b to a swap below maximum input", async () => { - const { poolInitInfo, whirlpoolPda, tokenAccountA, tokenAccountB } = - await initTestPoolWithTokens(ctx, TickSpacing.Standard); - - const tickArrays = await initTickArrayRange( - ctx, - whirlpoolPda.publicKey, - 22528, // to 33792 - 3, - TickSpacing.Standard, - false - ); - - const fundParams: FundedPositionParams[] = [ - { - liquidityAmount: new anchor.BN(100_000), - tickLowerIndex: 29440, - tickUpperIndex: 33536, - }, - ]; - - await fundPositions(ctx, poolInitInfo, tokenAccountA, tokenAccountB, fundParams); - - const oraclePda = PDAUtil.getOracle(ctx.program.programId, whirlpoolPda.publicKey); - - const params = { - amount: new BN(10), - otherAmountThreshold: ZERO_BN, - sqrtPriceLimit: new anchor.BN(MAX_SQRT_PRICE), - amountSpecifiedIsInput: false, - aToB: false, - whirlpool: whirlpoolPda.publicKey, - tokenAuthority: ctx.wallet.publicKey, - tokenOwnerAccountA: tokenAccountA, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenOwnerAccountB: tokenAccountB, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArray0: tickArrays[0].publicKey, - tickArray1: tickArrays[0].publicKey, - tickArray2: tickArrays[0].publicKey, - oracle: oraclePda.publicKey, - }; - - try { - await toTx(ctx, WhirlpoolIx.swapIx(ctx.program, params)).buildAndExecute(); - assert.fail("should fail if amount out is below threshold"); - } catch (e) { - const error = e as Error; - assert.match(error.message, /0x1795/); // AmountInAboveMaximum - } - }); - - it("swaps across ten tick arrays", async () => { - const { - poolInitInfo, - configInitInfo, - configKeypairs, - whirlpoolPda, - tokenAccountA, - tokenAccountB, - } = await initTestPoolWithTokens( - ctx, - TickSpacing.Stable, - PriceMath.tickIndexToSqrtPriceX64(27500) - ); - - const aToB = false; - const tickArrays = await initTickArrayRange( - ctx, - whirlpoolPda.publicKey, - 27456, // to 30528 - 3, - TickSpacing.Stable, - aToB - ); - - // tick array range: 27658 to 29386 - // tick arrays: (27456, 28152), (28160, 28856), (28864, 29,560) - // current tick: 27727 - // initialized ticks: - // 27712, 27736, 27840, 28288, 28296, 28304, 28416, 28576, 28736, 29112, 29120, 29240, 29360 - - const fundParams: FundedPositionParams[] = [ - { - liquidityAmount: new anchor.BN(10_000_000), - tickLowerIndex: 27712, - tickUpperIndex: 29360, - }, - { - liquidityAmount: new anchor.BN(10_000_000), - tickLowerIndex: 27736, - tickUpperIndex: 29240, - }, - { - liquidityAmount: new anchor.BN(10_000_000), - tickLowerIndex: 27840, - tickUpperIndex: 29120, - }, - { - liquidityAmount: new anchor.BN(10_000_000), - tickLowerIndex: 28288, - tickUpperIndex: 29112, - }, - { - liquidityAmount: new anchor.BN(10_000_000), - tickLowerIndex: 28416, - tickUpperIndex: 29112, - }, - { - liquidityAmount: new anchor.BN(10_000_000), - tickLowerIndex: 28288, - tickUpperIndex: 28304, - }, - { - liquidityAmount: new anchor.BN(10_000_000), - tickLowerIndex: 28296, - tickUpperIndex: 29112, - }, - { - liquidityAmount: new anchor.BN(10_000_000), - tickLowerIndex: 28576, - tickUpperIndex: 28736, - }, - ]; - - const positionInfos = await fundPositions( - ctx, - poolInitInfo, - tokenAccountA, - tokenAccountB, - fundParams - ); - - console.log(await getTokenBalance(provider, poolInitInfo.tokenVaultAKeypair.publicKey)); - console.log(await getTokenBalance(provider, poolInitInfo.tokenVaultBKeypair.publicKey)); - - ( - await Promise.all(tickArrays.map((tickArray) => fetcher.getTickArray(tickArray.publicKey))) - ).map((tickArray) => { - const ta = tickArray as TickArrayData; - ta.ticks.forEach((tick, index) => { - if (!tick.initialized) { - return; - } - - console.log( - ta.startTickIndex + index * TickSpacing.Stable, - tick.feeGrowthOutsideA.toString(), - tick.feeGrowthOutsideB.toString() - ); - }); - }); - - const oraclePda = PDAUtil.getOracle(ctx.program.programId, whirlpoolPda.publicKey); - - // Tick - await toTx( - ctx, - WhirlpoolIx.swapIx(ctx.program, { - amount: new BN(829996), - otherAmountThreshold: MAX_U64, - sqrtPriceLimit: PriceMath.tickIndexToSqrtPriceX64(29240), - amountSpecifiedIsInput: false, - aToB, - whirlpool: whirlpoolPda.publicKey, - tokenAuthority: ctx.wallet.publicKey, - tokenOwnerAccountA: tokenAccountA, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenOwnerAccountB: tokenAccountB, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArray0: tickArrays[0].publicKey, - tickArray1: tickArrays[1].publicKey, - tickArray2: tickArrays[2].publicKey, - oracle: oraclePda.publicKey, - }) - ).buildAndExecute(); - - console.log(await getTokenBalance(provider, poolInitInfo.tokenVaultAKeypair.publicKey)); - console.log(await getTokenBalance(provider, poolInitInfo.tokenVaultBKeypair.publicKey)); - - ( - await Promise.all(tickArrays.map((tickArray) => fetcher.getTickArray(tickArray.publicKey))) - ).map((tickArray) => { - const ta = tickArray as TickArrayData; - ta.ticks.forEach((tick, index) => { - if (!tick.initialized) { - return; - } - - console.log( - ta.startTickIndex + index * TickSpacing.Stable, - tick.feeGrowthOutsideA.toString(), - tick.feeGrowthOutsideB.toString() - ); - }); - }); - - await toTx( - ctx, - WhirlpoolIx.swapIx(ctx.program, { - amount: new BN(14538074), - otherAmountThreshold: MAX_U64, - sqrtPriceLimit: PriceMath.tickIndexToSqrtPriceX64(27712), - amountSpecifiedIsInput: false, - aToB: true, - whirlpool: whirlpoolPda.publicKey, - tokenAuthority: ctx.wallet.publicKey, - tokenOwnerAccountA: tokenAccountA, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenOwnerAccountB: tokenAccountB, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArray0: tickArrays[2].publicKey, - tickArray1: tickArrays[1].publicKey, - tickArray2: tickArrays[0].publicKey, - oracle: oraclePda.publicKey, - }) - ).buildAndExecute(); - - console.log(await getTokenBalance(provider, poolInitInfo.tokenVaultAKeypair.publicKey)); - console.log(await getTokenBalance(provider, poolInitInfo.tokenVaultBKeypair.publicKey)); - - ( - await Promise.all(tickArrays.map((tickArray) => fetcher.getTickArray(tickArray.publicKey))) - ).map((tickArray) => { - const ta = tickArray as TickArrayData; - ta.ticks.forEach((tick, index) => { - if (!tick.initialized) { - return; - } - - console.log( - ta.startTickIndex + index * TickSpacing.Stable, - tick.feeGrowthOutsideA.toString(), - tick.feeGrowthOutsideB.toString() - ); - }); - }); - - await toTx( - ctx, - WhirlpoolIx.swapIx(ctx.program, { - amount: new BN(829996), - otherAmountThreshold: MAX_U64, - sqrtPriceLimit: PriceMath.tickIndexToSqrtPriceX64(29240), - amountSpecifiedIsInput: false, - aToB, - whirlpool: whirlpoolPda.publicKey, - tokenAuthority: ctx.wallet.publicKey, - tokenOwnerAccountA: tokenAccountA, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenOwnerAccountB: tokenAccountB, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArray0: tickArrays[0].publicKey, - tickArray1: tickArrays[1].publicKey, - tickArray2: tickArrays[2].publicKey, - oracle: oraclePda.publicKey, - }) - ).buildAndExecute(); - - console.log(await getTokenBalance(provider, poolInitInfo.tokenVaultAKeypair.publicKey)); - console.log(await getTokenBalance(provider, poolInitInfo.tokenVaultBKeypair.publicKey)); - - ( - await Promise.all(tickArrays.map((tickArray) => fetcher.getTickArray(tickArray.publicKey))) - ).map((tickArray) => { - const ta = tickArray as TickArrayData; - ta.ticks.forEach((tick, index) => { - if (!tick.initialized) { - return; - } - - console.log( - ta.startTickIndex + index * TickSpacing.Stable, - tick.feeGrowthOutsideA.toString(), - tick.feeGrowthOutsideB.toString() - ); - }); - }); - - await toTx( - ctx, - WhirlpoolIx.swapIx(ctx.program, { - amount: new BN(14538074), - otherAmountThreshold: MAX_U64, - sqrtPriceLimit: PriceMath.tickIndexToSqrtPriceX64(27712), - amountSpecifiedIsInput: false, - aToB: true, - whirlpool: whirlpoolPda.publicKey, - tokenAuthority: ctx.wallet.publicKey, - tokenOwnerAccountA: tokenAccountA, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenOwnerAccountB: tokenAccountB, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArray0: tickArrays[2].publicKey, - tickArray1: tickArrays[1].publicKey, - tickArray2: tickArrays[0].publicKey, - oracle: oraclePda.publicKey, - }) - ).buildAndExecute(); - - console.log(await getTokenBalance(provider, poolInitInfo.tokenVaultAKeypair.publicKey)); - console.log(await getTokenBalance(provider, poolInitInfo.tokenVaultBKeypair.publicKey)); - - ( - await Promise.all(tickArrays.map((tickArray) => fetcher.getTickArray(tickArray.publicKey))) - ).map((tickArray) => { - const ta = tickArray as TickArrayData; - ta.ticks.forEach((tick, index) => { - if (!tick.initialized) { - return; - } - - console.log( - ta.startTickIndex + index * TickSpacing.Stable, - tick.feeGrowthOutsideA.toString(), - tick.feeGrowthOutsideB.toString() - ); - }); - }); - - await toTx( - ctx, - WhirlpoolIx.swapIx(ctx.program, { - amount: new BN(829996), - otherAmountThreshold: MAX_U64, - sqrtPriceLimit: PriceMath.tickIndexToSqrtPriceX64(29240), - amountSpecifiedIsInput: false, - aToB, - whirlpool: whirlpoolPda.publicKey, - tokenAuthority: ctx.wallet.publicKey, - tokenOwnerAccountA: tokenAccountA, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenOwnerAccountB: tokenAccountB, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArray0: tickArrays[0].publicKey, - tickArray1: tickArrays[1].publicKey, - tickArray2: tickArrays[2].publicKey, - oracle: oraclePda.publicKey, - }) - ).buildAndExecute(); - - console.log(await getTokenBalance(provider, poolInitInfo.tokenVaultAKeypair.publicKey)); - console.log(await getTokenBalance(provider, poolInitInfo.tokenVaultBKeypair.publicKey)); - - ( - await Promise.all(tickArrays.map((tickArray) => fetcher.getTickArray(tickArray.publicKey))) - ).map((tickArray) => { - const ta = tickArray as TickArrayData; - ta.ticks.forEach((tick, index) => { - if (!tick.initialized) { - return; - } - - console.log( - ta.startTickIndex + index * TickSpacing.Stable, - tick.feeGrowthOutsideA.toString(), - tick.feeGrowthOutsideB.toString() - ); - }); - }); - - await toTx( - ctx, - WhirlpoolIx.swapIx(ctx.program, { - amount: new BN(14538074), - otherAmountThreshold: MAX_U64, - sqrtPriceLimit: PriceMath.tickIndexToSqrtPriceX64(27712), - amountSpecifiedIsInput: false, - aToB: true, - whirlpool: whirlpoolPda.publicKey, - tokenAuthority: ctx.wallet.publicKey, - tokenOwnerAccountA: tokenAccountA, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenOwnerAccountB: tokenAccountB, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tickArray0: tickArrays[2].publicKey, - tickArray1: tickArrays[1].publicKey, - tickArray2: tickArrays[0].publicKey, - oracle: oraclePda.publicKey, - }) - ).buildAndExecute(); - - console.log(await getTokenBalance(provider, poolInitInfo.tokenVaultAKeypair.publicKey)); - console.log(await getTokenBalance(provider, poolInitInfo.tokenVaultBKeypair.publicKey)); - - ( - await Promise.all(tickArrays.map((tickArray) => fetcher.getTickArray(tickArray.publicKey))) - ).map((tickArray) => { - const ta = tickArray as TickArrayData; - ta.ticks.forEach((tick, index) => { - if (!tick.initialized) { - return; - } - - console.log( - ta.startTickIndex + index * TickSpacing.Stable, - tick.feeGrowthOutsideA.toString(), - tick.feeGrowthOutsideB.toString() - ); - }); - }); - - await withdrawPositions(ctx, positionInfos, tokenAccountA, tokenAccountB); - - console.log(await getTokenBalance(provider, poolInitInfo.tokenVaultAKeypair.publicKey)); - console.log(await getTokenBalance(provider, poolInitInfo.tokenVaultBKeypair.publicKey)); - - ( - await Promise.all(tickArrays.map((tickArray) => fetcher.getTickArray(tickArray.publicKey))) - ).map((tickArray) => { - const ta = tickArray as TickArrayData; - ta.ticks.forEach((tick, index) => { - if (!tick.initialized) { - return; - } - - console.log( - ta.startTickIndex + index * TickSpacing.Stable, - tick.feeGrowthOutsideA.toString(), - tick.feeGrowthOutsideB.toString() - ); - }); - }); - - await toTx( - ctx, - WhirlpoolIx.collectProtocolFeesIx(ctx.program, { - whirlpoolsConfig: poolInitInfo.whirlpoolsConfig, - whirlpool: poolInitInfo.whirlpoolPda.publicKey, - collectProtocolFeesAuthority: configKeypairs.collectProtocolFeesAuthorityKeypair.publicKey, - tokenVaultA: poolInitInfo.tokenVaultAKeypair.publicKey, - tokenVaultB: poolInitInfo.tokenVaultBKeypair.publicKey, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: tokenAccountB, - }) - ) - .addSigner(configKeypairs.collectProtocolFeesAuthorityKeypair) - .buildAndExecute(); - - console.log(await getTokenBalance(provider, poolInitInfo.tokenVaultAKeypair.publicKey)); - console.log(await getTokenBalance(provider, poolInitInfo.tokenVaultBKeypair.publicKey)); - }); -}); diff --git a/sdk/tests/integration/two_hop_swap.test.ts b/sdk/tests/integration/two_hop_swap.test.ts deleted file mode 100644 index af7362c..0000000 --- a/sdk/tests/integration/two_hop_swap.test.ts +++ /dev/null @@ -1,840 +0,0 @@ -import * as anchor from "@coral-xyz/anchor"; -import { Percentage } from "@orca-so/common-sdk"; -import { PublicKey } from "@solana/web3.js"; -import * as assert from "assert"; -import { BN } from "bn.js"; -import { - buildWhirlpoolClient, - InitPoolParams, - PDAUtil, - swapQuoteByInputToken, - swapQuoteByOutputToken, - toTx, - twoHopSwapQuoteFromSwapQuotes, - WhirlpoolContext, - WhirlpoolIx -} from "../../src"; -import { TwoHopSwapParams } from "../../src/instructions"; -import { IGNORE_CACHE } from "../../src/network/public/fetcher"; -import { getTokenBalance, TickSpacing } from "../utils"; -import { defaultConfirmOptions } from "../utils/const"; -import { - buildTestAquariums, - FundedPositionParams, - getDefaultAquarium, - getTokenAccsForPools, - InitAquariumParams -} from "../utils/init-utils"; - -describe("two-hop swap", () => { - const provider = anchor.AnchorProvider.local(undefined, defaultConfirmOptions); - - const program = anchor.workspace.Whirlpool; - const ctx = WhirlpoolContext.fromWorkspace(provider, program); - const fetcher = ctx.fetcher; - const client = buildWhirlpoolClient(ctx); - - let aqConfig: InitAquariumParams; - beforeEach(async () => { - aqConfig = getDefaultAquarium(); - // Add a third token and account and a second pool - aqConfig.initMintParams.push({}); - aqConfig.initTokenAccParams.push({ mintIndex: 2 }); - aqConfig.initPoolParams.push({ mintIndices: [1, 2], tickSpacing: TickSpacing.Standard }); - - // Add tick arrays and positions - const aToB = false; - aqConfig.initTickArrayRangeParams.push({ - poolIndex: 0, - startTickIndex: 22528, - arrayCount: 3, - aToB, - }); - aqConfig.initTickArrayRangeParams.push({ - poolIndex: 1, - startTickIndex: 22528, - arrayCount: 3, - aToB, - }); - const fundParams: FundedPositionParams[] = [ - { - liquidityAmount: new anchor.BN(10_000_000), - tickLowerIndex: 29440, - tickUpperIndex: 33536, - }, - ]; - aqConfig.initPositionParams.push({ poolIndex: 0, fundParams }); - aqConfig.initPositionParams.push({ poolIndex: 1, fundParams }); - }); - - describe("fails [2] with two-hop swap, invalid accounts", () => { - let baseIxParams: TwoHopSwapParams; - beforeEach(async () => { - const aquarium = (await buildTestAquariums(ctx, [aqConfig]))[0]; - const { tokenAccounts, mintKeys, pools } = aquarium; - - const whirlpoolOneKey = pools[0].whirlpoolPda.publicKey; - const whirlpoolTwoKey = pools[1].whirlpoolPda.publicKey; - const whirlpoolOne = await client.getPool(whirlpoolOneKey, IGNORE_CACHE); - const whirlpoolTwo = await client.getPool(whirlpoolTwoKey, IGNORE_CACHE); - - const [inputToken, intermediaryToken, _outputToken] = mintKeys; - - const quote = await swapQuoteByInputToken( - whirlpoolOne, - inputToken, - new BN(1000), - Percentage.fromFraction(1, 100), - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - - const quote2 = await swapQuoteByInputToken( - whirlpoolTwo, - intermediaryToken, - quote.estimatedAmountOut, - Percentage.fromFraction(1, 100), - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - - const twoHopQuote = twoHopSwapQuoteFromSwapQuotes(quote, quote2); - baseIxParams = { - ...twoHopQuote, - ...getParamsFromPools([pools[0], pools[1]], tokenAccounts), - tokenAuthority: ctx.wallet.publicKey, - }; - }); - - it("fails invalid whirlpool", async () => { - await rejectParams( - { - ...baseIxParams, - whirlpoolOne: baseIxParams.whirlpoolTwo, - }, - /0x7d3/ // ConstraintRaw - ); - }); - - it("fails invalid token account", async () => { - await rejectParams( - { - ...baseIxParams, - tokenOwnerAccountOneA: baseIxParams.tokenOwnerAccountOneB, - }, - /0x7d3/ // ConstraintRaw - ); - }); - - it("fails invalid token vault", async () => { - await rejectParams( - { - ...baseIxParams, - tokenVaultOneA: baseIxParams.tokenVaultOneB, - }, - /0x7dc/ // ConstraintAddress - ); - }); - - it("fails invalid oracle one address", async () => { - await rejectParams( - { - ...baseIxParams, - oracleOne: PublicKey.unique(), - }, - /0x7d6/ // Constraint Seeds - ); - }); - - it("fails invalid oracle two address", async () => { - await rejectParams( - { - ...baseIxParams, - oracleTwo: PublicKey.unique(), - }, - /0x7d6/ // Constraint Seeds - ); - }); - - it("fails invalid tick array one", async () => { - await rejectParams( - { - ...baseIxParams, - tickArrayOne0: PublicKey.unique(), - }, - /0xbbf/ // AccountOwnedByWrongProgram - ); - await rejectParams( - { - ...baseIxParams, - tickArrayOne1: PublicKey.unique(), - }, - /0xbbf/ // AccountOwnedByWrongProgram - ); - await rejectParams( - { - ...baseIxParams, - tickArrayOne2: PublicKey.unique(), - }, - /0xbbf/ // AccountOwnedByWrongProgram - ); - }); - - it("fails invalid tick array two", async () => { - await rejectParams( - { - ...baseIxParams, - tickArrayTwo0: PublicKey.unique(), - }, - /0xbbf/ // AccountOwnedByWrongProgram - ); - await rejectParams( - { - ...baseIxParams, - tickArrayTwo1: PublicKey.unique(), - }, - /0xbbf/ // AccountOwnedByWrongProgram - ); - await rejectParams( - { - ...baseIxParams, - tickArrayTwo2: PublicKey.unique(), - }, - /0xbbf/ // AccountOwnedByWrongProgram - ); - }); - - async function rejectParams(params: TwoHopSwapParams, error: assert.AssertPredicate) { - await assert.rejects( - toTx(ctx, WhirlpoolIx.twoHopSwapIx(ctx.program, params)).buildAndExecute(), - error, - ); - } - - }); - - it("swaps [2] with two-hop swap, amountSpecifiedIsInput=true", async () => { - const aquarium = (await buildTestAquariums(ctx, [aqConfig]))[0]; - const { tokenAccounts, mintKeys, pools } = aquarium; - - let tokenBalances = await getTokenBalances(tokenAccounts.map((acc) => acc.account)); - - const tokenVaultBalances = await getTokenBalancesForVaults(pools); - - const whirlpoolOneKey = pools[0].whirlpoolPda.publicKey; - const whirlpoolTwoKey = pools[1].whirlpoolPda.publicKey; - let whirlpoolOne = await client.getPool(whirlpoolOneKey, IGNORE_CACHE); - let whirlpoolTwo = await client.getPool(whirlpoolTwoKey, IGNORE_CACHE); - - const [inputToken, intermediaryToken, _outputToken] = mintKeys; - - const quote = await swapQuoteByInputToken( - whirlpoolOne, - inputToken, - new BN(1000), - Percentage.fromFraction(1, 100), - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - - const quote2 = await swapQuoteByInputToken( - whirlpoolTwo, - intermediaryToken, - quote.estimatedAmountOut, - Percentage.fromFraction(1, 100), - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - - const twoHopQuote = twoHopSwapQuoteFromSwapQuotes(quote, quote2); - - await toTx( - ctx, - WhirlpoolIx.twoHopSwapIx(ctx.program, { - ...twoHopQuote, - ...getParamsFromPools([pools[0], pools[1]], tokenAccounts), - tokenAuthority: ctx.wallet.publicKey, - }) - ).buildAndExecute(); - - assert.deepEqual(await getTokenBalancesForVaults(pools), [ - tokenVaultBalances[0].add(quote.estimatedAmountIn), - tokenVaultBalances[1].sub(quote.estimatedAmountOut), - tokenVaultBalances[2].add(quote2.estimatedAmountIn), - tokenVaultBalances[3].sub(quote2.estimatedAmountOut), - ]); - - const prevTbs = [...tokenBalances]; - tokenBalances = await getTokenBalances(tokenAccounts.map((acc) => acc.account)); - - assert.deepEqual(tokenBalances, [ - prevTbs[0].sub(quote.estimatedAmountIn), - prevTbs[1], - prevTbs[2].add(quote2.estimatedAmountOut), - ]); - - whirlpoolOne = await client.getPool(whirlpoolOneKey, IGNORE_CACHE); - whirlpoolTwo = await client.getPool(whirlpoolTwoKey, IGNORE_CACHE); - }); - - - it("swaps [2] with two-hop swap, amountSpecifiedIsInput=true, A->B->A", async () => { - // Add another mint and update pool so there is no overlapping mint - aqConfig.initFeeTierParams.push({ tickSpacing: TickSpacing.ThirtyTwo }); - aqConfig.initPoolParams[1] = { mintIndices: [0, 1], tickSpacing: TickSpacing.ThirtyTwo, feeTierIndex: 1 }; - aqConfig.initTickArrayRangeParams.push({ - poolIndex: 1, - startTickIndex: 22528, - arrayCount: 12, - aToB: true, - }); - aqConfig.initTickArrayRangeParams.push({ - poolIndex: 1, - startTickIndex: 22528, - arrayCount: 12, - aToB: false, - }); - - - const aquarium = (await buildTestAquariums(ctx, [aqConfig]))[0]; - const { tokenAccounts, mintKeys, pools } = aquarium; - - let tokenBalances = await getTokenBalances(tokenAccounts.map((acc) => acc.account)); - - const tokenVaultBalances = await getTokenBalancesForVaults(pools); - - - const whirlpoolOneKey = pools[0].whirlpoolPda.publicKey; - const whirlpoolTwoKey = pools[1].whirlpoolPda.publicKey; - let whirlpoolOne = await client.getPool(whirlpoolOneKey, IGNORE_CACHE); - let whirlpoolTwo = await client.getPool(whirlpoolTwoKey, IGNORE_CACHE); - - const [tokenA, tokenB, _outputToken] = mintKeys; - - const quote = await swapQuoteByInputToken( - whirlpoolOne, - tokenA, - new BN(1000), - Percentage.fromFraction(1, 100), - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - - const quote2 = await swapQuoteByInputToken( - whirlpoolTwo, - tokenB, - quote.estimatedAmountOut, - Percentage.fromFraction(1, 100), - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - - const twoHopQuote = twoHopSwapQuoteFromSwapQuotes(quote, quote2); - - await toTx( - ctx, - WhirlpoolIx.twoHopSwapIx(ctx.program, { - ...twoHopQuote, - ...getParamsFromPools([pools[0], pools[1]], tokenAccounts), - tokenAuthority: ctx.wallet.publicKey, - }) - ).buildAndExecute(); - - assert.deepEqual(await getTokenBalancesForVaults(pools), [ - tokenVaultBalances[0].add(quote.estimatedAmountIn), - tokenVaultBalances[1].sub(quote.estimatedAmountOut), - tokenVaultBalances[2].sub(quote2.estimatedAmountOut), - tokenVaultBalances[3].add(quote2.estimatedAmountIn), - ]); - - const prevTbs = [...tokenBalances]; - tokenBalances = await getTokenBalances(tokenAccounts.map((acc) => acc.account)); - - assert.deepEqual(tokenBalances, [ - prevTbs[0].sub(quote.estimatedAmountIn).add(quote2.estimatedAmountOut), - prevTbs[1].add(quote.estimatedAmountOut).sub(quote2.estimatedAmountIn), - prevTbs[2], - ]); - }); - - it("fails swaps [2] with top-hop swap, amountSpecifiedIsInput=true, slippage", async () => { - const aquarium = (await buildTestAquariums(ctx, [aqConfig]))[0]; - const { tokenAccounts, mintKeys, pools } = aquarium; - - const whirlpoolOneKey = pools[0].whirlpoolPda.publicKey; - const whirlpoolTwoKey = pools[1].whirlpoolPda.publicKey; - const whirlpoolOne = await client.getPool(whirlpoolOneKey, IGNORE_CACHE); - const whirlpoolTwo = await client.getPool(whirlpoolTwoKey, IGNORE_CACHE); - - const [inputToken, intermediaryToken, _outputToken] = mintKeys; - - const quote = await swapQuoteByInputToken( - whirlpoolOne, - inputToken, - new BN(1000), - Percentage.fromFraction(1, 100), - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - - const quote2 = await swapQuoteByInputToken( - whirlpoolTwo, - intermediaryToken, - quote.estimatedAmountOut, - Percentage.fromFraction(1, 100), - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - - const twoHopQuote = twoHopSwapQuoteFromSwapQuotes(quote, quote2); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.twoHopSwapIx(ctx.program, { - ...twoHopQuote, - ...getParamsFromPools([pools[0], pools[1]], tokenAccounts), - otherAmountThreshold: new BN(613309), - tokenAuthority: ctx.wallet.publicKey, - }) - ).buildAndExecute(), - /0x1794/ // Above Out Below Minimum - ); - }); - - it("swaps [2] with two-hop swap, amountSpecifiedIsInput=false", async () => { - const aquarium = (await buildTestAquariums(ctx, [aqConfig]))[0]; - const { tokenAccounts, mintKeys, pools } = aquarium; - - const preSwapBalances = await getTokenBalances(tokenAccounts.map((acc) => acc.account)); - const tokenVaultBalances = await getTokenBalancesForVaults(pools); - - const whirlpoolOneKey = pools[0].whirlpoolPda.publicKey; - const whirlpoolTwoKey = pools[1].whirlpoolPda.publicKey; - const whirlpoolOne = await client.getPool(whirlpoolOneKey, IGNORE_CACHE); - const whirlpoolTwo = await client.getPool(whirlpoolTwoKey, IGNORE_CACHE); - - const [_inputToken, intermediaryToken, outputToken] = mintKeys; - - const quote2 = await swapQuoteByOutputToken( - whirlpoolTwo, - outputToken, - new BN(1000), - Percentage.fromFraction(1, 100), - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - - const quote = await swapQuoteByOutputToken( - whirlpoolOne, - intermediaryToken, - quote2.estimatedAmountIn, - Percentage.fromFraction(1, 100), - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - - const twoHopQuote = twoHopSwapQuoteFromSwapQuotes(quote, quote2); - - await toTx( - ctx, - WhirlpoolIx.twoHopSwapIx(ctx.program, { - ...twoHopQuote, - ...getParamsFromPools([pools[0], pools[1]], tokenAccounts), - tokenAuthority: ctx.wallet.publicKey, - }) - ).buildAndExecute(); - - assert.deepEqual(await getTokenBalancesForVaults(pools), [ - tokenVaultBalances[0].add(quote.estimatedAmountIn), - tokenVaultBalances[1].sub(quote.estimatedAmountOut), - tokenVaultBalances[2].add(quote2.estimatedAmountIn), - tokenVaultBalances[3].sub(quote2.estimatedAmountOut), - ]); - - assert.deepEqual(await getTokenBalances(tokenAccounts.map((acc) => acc.account)), [ - preSwapBalances[0].sub(quote.estimatedAmountIn), - preSwapBalances[1], - preSwapBalances[2].add(quote2.estimatedAmountOut), - ]); - }); - - it("fails swaps [2] with two-hop swap, amountSpecifiedIsInput=false slippage", async () => { - const aquarium = (await buildTestAquariums(ctx, [aqConfig]))[0]; - const { tokenAccounts, mintKeys, pools } = aquarium; - - const preSwapBalances = await getTokenBalances(tokenAccounts.map((acc) => acc.account)); - const tokenVaultBalances = await getTokenBalancesForVaults(pools); - - const whirlpoolOneKey = pools[0].whirlpoolPda.publicKey; - const whirlpoolTwoKey = pools[1].whirlpoolPda.publicKey; - const whirlpoolOne = await client.getPool(whirlpoolOneKey, IGNORE_CACHE); - const whirlpoolTwo = await client.getPool(whirlpoolTwoKey, IGNORE_CACHE); - - const [_inputToken, intermediaryToken, outputToken] = mintKeys; - - const quote2 = await swapQuoteByOutputToken( - whirlpoolTwo, - outputToken, - new BN(1000), - Percentage.fromFraction(1, 100), - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - - const quote = await swapQuoteByOutputToken( - whirlpoolOne, - intermediaryToken, - quote2.estimatedAmountIn, - Percentage.fromFraction(1, 100), - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - - const twoHopQuote = twoHopSwapQuoteFromSwapQuotes(quote, quote2); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.twoHopSwapIx(ctx.program, { - ...twoHopQuote, - ...getParamsFromPools([pools[0], pools[1]], tokenAccounts), - otherAmountThreshold: new BN(2), - tokenAuthority: ctx.wallet.publicKey, - }) - ).buildAndExecute(), - /0x1795/ // Above In Above Maximum - ); - }); - - it("fails swaps [2] with two-hop swap, no overlapping mints", async () => { - // Add another mint and update pool so there is no overlapping mint - aqConfig.initMintParams.push({}); - aqConfig.initTokenAccParams.push({ mintIndex: 3 }); - aqConfig.initPoolParams[1].mintIndices = [2, 3]; - const aquarium = (await buildTestAquariums(ctx, [aqConfig]))[0]; - const { tokenAccounts, mintKeys, pools } = aquarium; - - const whirlpoolOneKey = pools[0].whirlpoolPda.publicKey; - const whirlpoolTwoKey = pools[1].whirlpoolPda.publicKey; - const whirlpoolOne = await client.getPool(whirlpoolOneKey, IGNORE_CACHE); - const whirlpoolTwo = await client.getPool(whirlpoolTwoKey, IGNORE_CACHE); - - const [_inputToken, intermediaryToken, outputToken] = mintKeys; - - const quote2 = await swapQuoteByOutputToken( - whirlpoolTwo, - outputToken, - new BN(1000), - Percentage.fromFraction(1, 100), - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - - const quote = await swapQuoteByOutputToken( - whirlpoolOne, - intermediaryToken, - quote2.estimatedAmountIn, - Percentage.fromFraction(1, 100), - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - - const twoHopQuote = twoHopSwapQuoteFromSwapQuotes(quote, quote2); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.twoHopSwapIx(ctx.program, { - ...twoHopQuote, - ...getParamsFromPools([pools[0], pools[1]], tokenAccounts), - tokenAuthority: ctx.wallet.publicKey, - }) - ).buildAndExecute(), - /0x1799/ // Invalid intermediary mint - ); - }); - - it("swaps [2] with two-hop swap, amount_specified_is_input=true, first swap price limit", async () => { - const aquarium = (await buildTestAquariums(ctx, [aqConfig]))[0]; - const { tokenAccounts, mintKeys, pools } = aquarium; - - const whirlpoolOneKey = pools[0].whirlpoolPda.publicKey; - const whirlpoolTwoKey = pools[1].whirlpoolPda.publicKey; - let whirlpoolOne = await client.getPool(whirlpoolOneKey, IGNORE_CACHE); - let whirlpoolTwo = await client.getPool(whirlpoolTwoKey, IGNORE_CACHE); - - const [inputToken, intermediaryToken, _outputToken] = mintKeys; - - const quote = await swapQuoteByInputToken( - whirlpoolOne, - inputToken, - new BN(1000), - Percentage.fromFraction(0, 100), - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - - const quote2 = await swapQuoteByInputToken( - whirlpoolTwo, - intermediaryToken, - quote.estimatedAmountOut, - Percentage.fromFraction(1, 100), - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - - // Set a price limit that is less than the 1% slippage threshold, - // which will allow the swap to go through - quote.sqrtPriceLimit = quote.estimatedEndSqrtPrice.add( - whirlpoolOne - .getData() - .sqrtPrice.sub(quote.estimatedEndSqrtPrice) - .mul(new anchor.BN("5")) - .div(new anchor.BN("1000")) - ); - - const twoHopQuote = twoHopSwapQuoteFromSwapQuotes(quote, quote2); - - await toTx( - ctx, - WhirlpoolIx.twoHopSwapIx(ctx.program, { - ...twoHopQuote, - ...getParamsFromPools([pools[0], pools[1]], tokenAccounts), - tokenAuthority: ctx.wallet.publicKey, - }) - ).buildAndExecute(); - - whirlpoolOne = await client.getPool(whirlpoolOneKey, IGNORE_CACHE); - whirlpoolTwo = await client.getPool(whirlpoolTwoKey, IGNORE_CACHE); - - assert.equal(whirlpoolOne.getData().sqrtPrice.eq(quote.sqrtPriceLimit), true); - }); - - - it("swaps [2] with two-hop swap, amount_specified_is_input=true, second swap price limit", async () => { - const aquarium = (await buildTestAquariums(ctx, [aqConfig]))[0]; - const { tokenAccounts, mintKeys, pools } = aquarium; - - const whirlpoolOneKey = pools[0].whirlpoolPda.publicKey; - const whirlpoolTwoKey = pools[1].whirlpoolPda.publicKey; - let whirlpoolOne = await client.getPool(whirlpoolOneKey, IGNORE_CACHE); - let whirlpoolTwo = await client.getPool(whirlpoolTwoKey, IGNORE_CACHE); - - const [inputToken, intermediaryToken, _outputToken] = mintKeys; - - const quote = await swapQuoteByInputToken( - whirlpoolOne, - inputToken, - new BN(1000), - Percentage.fromFraction(0, 100), - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - - const quote2 = await swapQuoteByInputToken( - whirlpoolTwo, - intermediaryToken, - quote.estimatedAmountOut, - Percentage.fromFraction(1, 100), - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - - // Set a price limit that is less than the 1% slippage threshold, - // which will allow the swap to go through - quote2.sqrtPriceLimit = quote2.estimatedEndSqrtPrice.add( - whirlpoolTwo - .getData() - .sqrtPrice.sub(quote2.estimatedEndSqrtPrice) - .mul(new anchor.BN("5")) - .div(new anchor.BN("1000")) - ); - - const twoHopQuote = twoHopSwapQuoteFromSwapQuotes(quote, quote2); - - await toTx( - ctx, - WhirlpoolIx.twoHopSwapIx(ctx.program, { - ...twoHopQuote, - ...getParamsFromPools([pools[0], pools[1]], tokenAccounts), - tokenAuthority: ctx.wallet.publicKey, - }) - ).buildAndExecute(); - - whirlpoolOne = await client.getPool(whirlpoolOneKey, IGNORE_CACHE); - whirlpoolTwo = await client.getPool(whirlpoolTwoKey, IGNORE_CACHE); - - assert.equal(whirlpoolTwo.getData().sqrtPrice.eq(quote2.sqrtPriceLimit), true); - }); - - it("fails swaps [2] with two-hop swap, amount_specified_is_input=true, first swap price limit", async () => { - const aquarium = (await buildTestAquariums(ctx, [aqConfig]))[0]; - const { tokenAccounts, mintKeys, pools } = aquarium; - - const whirlpoolOneKey = pools[0].whirlpoolPda.publicKey; - const whirlpoolTwoKey = pools[1].whirlpoolPda.publicKey; - let whirlpoolOne = await client.getPool(whirlpoolOneKey, IGNORE_CACHE); - let whirlpoolTwo = await client.getPool(whirlpoolTwoKey, IGNORE_CACHE); - - const [inputToken, intermediaryToken, _outputToken] = mintKeys; - - const quote = await swapQuoteByInputToken( - whirlpoolOne, - inputToken, - new BN(1000), - Percentage.fromFraction(0, 100), - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - - const quote2 = await swapQuoteByInputToken( - whirlpoolTwo, - intermediaryToken, - quote.estimatedAmountOut, - Percentage.fromFraction(1, 100), - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - - // Set a price limit that is less than the 1% slippage threshold, - // which will allow the swap to go through - quote.sqrtPriceLimit = quote.estimatedEndSqrtPrice.add( - whirlpoolOne - .getData() - .sqrtPrice.sub(quote.estimatedEndSqrtPrice) - .mul(new anchor.BN("15")) - .div(new anchor.BN("1000")) - ); - - const twoHopQuote = twoHopSwapQuoteFromSwapQuotes(quote, quote2); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.twoHopSwapIx(ctx.program, { - ...twoHopQuote, - ...getParamsFromPools([pools[0], pools[1]], tokenAccounts), - tokenAuthority: ctx.wallet.publicKey, - }) - ).buildAndExecute() - ); - }); - - - it("fails swaps [2] with two-hop swap, amount_specified_is_input=true, second swap price limit", async () => { - const aquarium = (await buildTestAquariums(ctx, [aqConfig]))[0]; - const { tokenAccounts, mintKeys, pools } = aquarium; - - const whirlpoolOneKey = pools[0].whirlpoolPda.publicKey; - const whirlpoolTwoKey = pools[1].whirlpoolPda.publicKey; - let whirlpoolOne = await client.getPool(whirlpoolOneKey, IGNORE_CACHE); - let whirlpoolTwo = await client.getPool(whirlpoolTwoKey, IGNORE_CACHE); - - const [inputToken, intermediaryToken, _outputToken] = mintKeys; - - const quote = await swapQuoteByInputToken( - whirlpoolOne, - inputToken, - new BN(1000), - Percentage.fromFraction(0, 100), - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - - const quote2 = await swapQuoteByInputToken( - whirlpoolTwo, - intermediaryToken, - quote.estimatedAmountOut, - Percentage.fromFraction(1, 100), - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - - // Set a price limit that is greater than the 1% slippage threshold, - // which will cause the swap to fail - quote2.sqrtPriceLimit = quote2.estimatedEndSqrtPrice.add( - whirlpoolTwo - .getData() - .sqrtPrice.sub(quote2.estimatedEndSqrtPrice) - .mul(new anchor.BN("15")) - .div(new anchor.BN("1000")) - ); - - const twoHopQuote = twoHopSwapQuoteFromSwapQuotes(quote, quote2); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.twoHopSwapIx(ctx.program, { - ...twoHopQuote, - ...getParamsFromPools([pools[0], pools[1]], tokenAccounts), - tokenAuthority: ctx.wallet.publicKey, - }) - ).buildAndExecute() - ); - }); - - function getParamsFromPools( - pools: [InitPoolParams, InitPoolParams], - tokenAccounts: { mint: PublicKey; account: PublicKey }[] - ) { - const tokenAccKeys = getTokenAccsForPools(pools, tokenAccounts); - - const whirlpoolOne = pools[0].whirlpoolPda.publicKey; - const whirlpoolTwo = pools[1].whirlpoolPda.publicKey; - const oracleOne = PDAUtil.getOracle(ctx.program.programId, whirlpoolOne).publicKey; - const oracleTwo = PDAUtil.getOracle(ctx.program.programId, whirlpoolTwo).publicKey; - return { - whirlpoolOne: pools[0].whirlpoolPda.publicKey, - whirlpoolTwo: pools[1].whirlpoolPda.publicKey, - tokenOwnerAccountOneA: tokenAccKeys[0], - tokenVaultOneA: pools[0].tokenVaultAKeypair.publicKey, - tokenOwnerAccountOneB: tokenAccKeys[1], - tokenVaultOneB: pools[0].tokenVaultBKeypair.publicKey, - tokenOwnerAccountTwoA: tokenAccKeys[2], - tokenVaultTwoA: pools[1].tokenVaultAKeypair.publicKey, - tokenOwnerAccountTwoB: tokenAccKeys[3], - tokenVaultTwoB: pools[1].tokenVaultBKeypair.publicKey, - oracleOne, - oracleTwo, - }; - } - - async function getTokenBalancesForVaults(pools: InitPoolParams[]) { - const accs = []; - for (const pool of pools) { - accs.push(pool.tokenVaultAKeypair.publicKey); - accs.push(pool.tokenVaultBKeypair.publicKey); - } - return getTokenBalances(accs); - } - - async function getTokenBalances(keys: PublicKey[]) { - return Promise.all( - keys.map(async (key) => new anchor.BN(await getTokenBalance(provider, key))) - ); - } -}); diff --git a/sdk/tests/integration/update_fees_and_rewards.test.ts b/sdk/tests/integration/update_fees_and_rewards.test.ts deleted file mode 100644 index fcfd3c7..0000000 --- a/sdk/tests/integration/update_fees_and_rewards.test.ts +++ /dev/null @@ -1,229 +0,0 @@ -import * as anchor from "@coral-xyz/anchor"; -import { MathUtil } from "@orca-so/common-sdk"; -import * as assert from "assert"; -import { BN } from "bn.js"; -import Decimal from "decimal.js"; -import { PDAUtil, PositionData, toTx, WhirlpoolContext, WhirlpoolIx } from "../../src"; -import { IGNORE_CACHE } from "../../src/network/public/fetcher"; -import { sleep, TickSpacing, ZERO_BN } from "../utils"; -import { defaultConfirmOptions } from "../utils/const"; -import { WhirlpoolTestFixture } from "../utils/fixture"; -import { initTestPool } from "../utils/init-utils"; - -describe("update_fees_and_rewards", () => { - const provider = anchor.AnchorProvider.local(undefined, defaultConfirmOptions); - - const program = anchor.workspace.Whirlpool; - const ctx = WhirlpoolContext.fromWorkspace(provider, program); - const fetcher = ctx.fetcher; - - it("successfully updates fees and rewards", async () => { - // In same tick array - start index 22528 - const tickLowerIndex = 29440; - const tickUpperIndex = 33536; - - const tickSpacing = TickSpacing.Standard; - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing, - positions: [{ tickLowerIndex, tickUpperIndex, liquidityAmount: new anchor.BN(1_000_000) }], - rewards: [ - { emissionsPerSecondX64: MathUtil.toX64(new Decimal(2)), vaultAmount: new BN(1_000_000) }, - ], - }); - const { - poolInitInfo: { whirlpoolPda, tokenVaultAKeypair, tokenVaultBKeypair }, - tokenAccountA, - tokenAccountB, - positions, - } = fixture.getInfos(); - - const tickArrayPda = PDAUtil.getTickArray(ctx.program.programId, whirlpoolPda.publicKey, 22528); - - const positionBefore = (await fetcher.getPosition( - positions[0].publicKey, - IGNORE_CACHE - )) as PositionData; - assert.ok(positionBefore.feeGrowthCheckpointA.eq(ZERO_BN)); - assert.ok(positionBefore.feeGrowthCheckpointB.eq(ZERO_BN)); - assert.ok(positionBefore.rewardInfos[0].amountOwed.eq(ZERO_BN)); - assert.ok(positionBefore.rewardInfos[0].growthInsideCheckpoint.eq(ZERO_BN)); - - const oraclePda = PDAUtil.getOracle(ctx.program.programId, whirlpoolPda.publicKey); - - await toTx( - ctx, - WhirlpoolIx.swapIx(ctx.program, { - amount: new BN(100_000), - otherAmountThreshold: ZERO_BN, - sqrtPriceLimit: MathUtil.toX64(new Decimal(4.95)), - amountSpecifiedIsInput: true, - aToB: true, - whirlpool: whirlpoolPda.publicKey, - tokenAuthority: ctx.wallet.publicKey, - tokenOwnerAccountA: tokenAccountA, - tokenVaultA: tokenVaultAKeypair.publicKey, - tokenOwnerAccountB: tokenAccountB, - tokenVaultB: tokenVaultBKeypair.publicKey, - tickArray0: tickArrayPda.publicKey, - tickArray1: tickArrayPda.publicKey, - tickArray2: tickArrayPda.publicKey, - oracle: oraclePda.publicKey, - }) - ).buildAndExecute(); - - await sleep(1_000); - - await toTx( - ctx, - WhirlpoolIx.updateFeesAndRewardsIx(ctx.program, { - whirlpool: whirlpoolPda.publicKey, - position: positions[0].publicKey, - tickArrayLower: tickArrayPda.publicKey, - tickArrayUpper: tickArrayPda.publicKey, - }) - ).buildAndExecute(); - const positionAfter = (await fetcher.getPosition(positions[0].publicKey, IGNORE_CACHE)) as PositionData; - assert.ok(positionAfter.feeOwedA.gt(positionBefore.feeOwedA)); - assert.ok(positionAfter.feeOwedB.eq(ZERO_BN)); - assert.ok(positionAfter.feeGrowthCheckpointA.gt(positionBefore.feeGrowthCheckpointA)); - assert.ok(positionAfter.feeGrowthCheckpointB.eq(positionBefore.feeGrowthCheckpointB)); - assert.ok(positionAfter.rewardInfos[0].amountOwed.gt(positionBefore.rewardInfos[0].amountOwed)); - assert.ok( - positionAfter.rewardInfos[0].growthInsideCheckpoint.gt( - positionBefore.rewardInfos[0].growthInsideCheckpoint - ) - ); - assert.ok(positionAfter.liquidity.eq(positionBefore.liquidity)); - }); - - it("fails when position has zero liquidity", async () => { - // In same tick array - start index 22528 - const tickLowerIndex = 29440; - const tickUpperIndex = 33536; - - const tickSpacing = TickSpacing.Standard; - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing, - positions: [{ tickLowerIndex, tickUpperIndex, liquidityAmount: ZERO_BN }], - }); - const { - poolInitInfo: { whirlpoolPda }, - positions, - } = fixture.getInfos(); - - const tickArrayPda = PDAUtil.getTickArray(ctx.program.programId, whirlpoolPda.publicKey, 22528); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.updateFeesAndRewardsIx(ctx.program, { - whirlpool: whirlpoolPda.publicKey, - position: positions[0].publicKey, - tickArrayLower: tickArrayPda.publicKey, - tickArrayUpper: tickArrayPda.publicKey, - }) - ).buildAndExecute(), - /0x177c/ // LiquidityZero - ); - }); - - it("fails when position does not match whirlpool", async () => { - const tickLowerIndex = 29440; - const tickUpperIndex = 33536; - - const tickSpacing = TickSpacing.Standard; - const { - poolInitInfo: { whirlpoolPda }, - } = await initTestPool(ctx, tickSpacing); - const tickArrayPda = PDAUtil.getTickArray(ctx.program.programId, whirlpoolPda.publicKey, 22528); - - const other = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing, - positions: [{ tickLowerIndex, tickUpperIndex, liquidityAmount: new anchor.BN(1_000_000) }], - }); - const { positions: otherPositions } = other.getInfos(); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.updateFeesAndRewardsIx(ctx.program, { - whirlpool: whirlpoolPda.publicKey, - position: otherPositions[0].publicKey, - tickArrayLower: tickArrayPda.publicKey, - tickArrayUpper: tickArrayPda.publicKey, - }) - ).buildAndExecute(), - /0xbbf/ // AccountOwnedByWrongProgram - ); - }); - - it("fails when tick arrays do not match position", async () => { - // In same tick array - start index 22528 - const tickLowerIndex = 29440; - const tickUpperIndex = 33536; - - const tickSpacing = TickSpacing.Standard; - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing, - positions: [{ tickLowerIndex, tickUpperIndex, liquidityAmount: new anchor.BN(1_000_000) }], - }); - const { - poolInitInfo: { whirlpoolPda }, - positions, - } = fixture.getInfos(); - - const tickArrayPda = PDAUtil.getTickArray(ctx.program.programId, whirlpoolPda.publicKey, 0); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.updateFeesAndRewardsIx(ctx.program, { - whirlpool: whirlpoolPda.publicKey, - position: positions[0].publicKey, - tickArrayLower: tickArrayPda.publicKey, - tickArrayUpper: tickArrayPda.publicKey, - }) - ).buildAndExecute(), - /0xbbf/ // AccountOwnedByWrongProgram - ); - }); - - it("fails when tick arrays do not match whirlpool", async () => { - // In same tick array - start index 22528 - const tickLowerIndex = 29440; - const tickUpperIndex = 33536; - - const tickSpacing = TickSpacing.Standard; - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing, - positions: [{ tickLowerIndex, tickUpperIndex, liquidityAmount: ZERO_BN }], - }); - const { - poolInitInfo: { whirlpoolPda }, - positions, - } = fixture.getInfos(); - - const { - poolInitInfo: { whirlpoolPda: otherWhirlpoolPda }, - } = await initTestPool(ctx, tickSpacing); - - const tickArrayPda = PDAUtil.getTickArray( - ctx.program.programId, - otherWhirlpoolPda.publicKey, - 22528 - ); - - await assert.rejects( - toTx( - ctx, - WhirlpoolIx.updateFeesAndRewardsIx(ctx.program, { - whirlpool: whirlpoolPda.publicKey, - position: positions[0].publicKey, - tickArrayLower: tickArrayPda.publicKey, - tickArrayUpper: tickArrayPda.publicKey, - }) - ).buildAndExecute(), - /0xbbf/ // AccountOwnedByWrongProgram - ); - }); -}); diff --git a/sdk/tests/sdk/router/router-util#priceImpact.test.ts b/sdk/tests/sdk/router/router-util#priceImpact.test.ts deleted file mode 100644 index 59d845a..0000000 --- a/sdk/tests/sdk/router/router-util#priceImpact.test.ts +++ /dev/null @@ -1,281 +0,0 @@ -import { Percentage } from "@orca-so/common-sdk"; -import { PublicKey } from "@solana/web3.js"; -import * as assert from "assert"; -import BN from "bn.js"; -import Decimal from "decimal.js"; -import { PriceMath, RouterUtils } from "../../../src"; -import { U64 } from "../../../src/utils/math/constants"; - -const maxDecimalAccuracy = 4; -describe("RouterUtil - Price Impact tests", () => { - // Mock a Orca -> USDC ExactIn trade that has no split route and goes through a single hop (ORCA -> USDC) - it("ExactIn, a->b true, single-hop, 1 split", () => { - const params: RouteTestParam = { - amountSpecifiedIsInput: true, - totalAmountIn: new BN("1000000"), - totalAmountOut: new BN("581050"), - subRouteParams: [ - { - hops: [ - { - aToB: true, - feeRate: Percentage.fromFraction(3000, 1000000), - sqrtPrice: new BN("14082503933855903449"), - amountIn: new BN("1000000"), - amountOut: new BN("581050"), - }, - ], - }, - ], - }; - const { trade, routes } = buildRouteTest(params); - const impact = RouterUtils.getPriceImpactForRoute(trade, routes).toDecimalPlaces( - maxDecimalAccuracy - ); - const expect = calculateImpact(params).toDecimalPlaces(maxDecimalAccuracy); - assert.equal(impact.toString(), expect.toString()); - }); - - // Mock a Orca -> USDC ExactOut trade that has no split route and goes through a single hop (ORCA -> USDC) - it("ExactOut, a->b false, single-hop, 1 split", () => { - const params: RouteTestParam = { - amountSpecifiedIsInput: false, - totalAmountIn: new BN("5833496"), - totalAmountOut: new BN("10000000"), - subRouteParams: [ - { - hops: [ - { - aToB: false, - feeRate: Percentage.fromFraction(3000, 1000000), - sqrtPrice: new BN("14067691597581169278"), - amountIn: new BN("5833496"), - amountOut: new BN("10000000"), - }, - ], - }, - ], - }; - const { trade, routes } = buildRouteTest(params); - const impact = RouterUtils.getPriceImpactForRoute(trade, routes).toDecimalPlaces( - maxDecimalAccuracy - ); - const expect = calculateImpact(params).toDecimalPlaces(maxDecimalAccuracy); - assert.equal(impact.toString(), expect.toString()); - }); - - // Mock a ORCA -> USDC trade that has 2 split route and goes through a multi-hop (ORCA -> SOL -> USDC) - it("ExactIn, mix a->b, single & multi-hop, 2 splits", () => { - const params: RouteTestParam = { - amountSpecifiedIsInput: true, - totalAmountIn: new BN("40000000000"), - totalAmountOut: new BN("22277933969"), - subRouteParams: [ - { - hops: [ - { - aToB: false, - feeRate: Percentage.fromFraction(3000, 1000000), - sqrtPrice: new BN("3363616053614750676"), - amountIn: new BN("32000000000"), - amountOut: new BN("925083736236"), - }, - { - aToB: true, - feeRate: Percentage.fromFraction(3000, 1000000), - sqrtPrice: new BN("2567715337494939945"), - amountIn: new BN("925083736236"), - amountOut: new BN("17871834810"), - }, - ], - }, - { - hops: [ - { - aToB: true, - feeRate: Percentage.fromFraction(3000, 1000000), - sqrtPrice: new BN("14082503933855903449"), - amountIn: new BN("8000000000"), - amountOut: new BN("4406099159"), - }, - ], - }, - ], - }; - const { trade, routes } = buildRouteTest(params); - const impact = RouterUtils.getPriceImpactForRoute(trade, routes).toDecimalPlaces( - maxDecimalAccuracy - ); - const expect = calculateImpact(params).toDecimalPlaces(maxDecimalAccuracy); - assert.equal(impact.toString(), expect.toString()); - }); - - // Mock an ExactOut ORCA -> USDC trade that has 2 split route and goes through a multi-hop (ORCA -> SOL -> USDC) - it("ExactOut, mix a->b, single & multi-hop, 2 splits", () => { - const params: RouteTestParam = { - amountSpecifiedIsInput: false, - totalAmountIn: new BN("64800628033"), - totalAmountOut: new BN("34000000000"), - subRouteParams: [ - { - hops: [ - { - aToB: true, - feeRate: Percentage.fromFraction(3000, 1000000), - sqrtPrice: new BN("14067691597581169278"), - amountIn: new BN("13107594181"), - amountOut: new BN("6800000000"), - }, - ], - }, - { - hops: [ - { - aToB: false, - feeRate: Percentage.fromFraction(3000, 1000000), - sqrtPrice: new BN("3366318822902200326"), - amountIn: new BN("51693033852"), - amountOut: new BN("1403541983350"), - }, - { - aToB: true, - feeRate: Percentage.fromFraction(3000, 1000000), - sqrtPrice: new BN("2572953144905521240"), - amountIn: new BN("1403541983350"), - amountOut: new BN("27200000000"), - }, - ], - }, - ], - }; - const { trade, routes } = buildRouteTest(params); - const impact = RouterUtils.getPriceImpactForRoute(trade, routes).toDecimalPlaces( - maxDecimalAccuracy - ); - const expect = calculateImpact(params).toDecimalPlaces(maxDecimalAccuracy); - assert.equal(impact.toString(), expect.toString()); - }); - - // NOTE: The precision kept in these calculation slightly differs from the U64 calculation that we get from the RouterUtil function. - function calculateImpact(params: RouteTestParam): Decimal { - const { amountSpecifiedIsInput, totalAmountIn, totalAmountOut } = params; - - const finalBaseValue = params.subRouteParams - .map((subRoute) => { - const { hops } = subRoute; - const directionalHops = amountSpecifiedIsInput ? hops : hops.slice().reverse(); - const hopResults: Decimal[] = new Array(hops.length); - directionalHops.forEach((hop, index) => { - const { aToB, feeRate, sqrtPrice, amountIn, amountOut } = hop; - const directionalSqrtPrice = aToB - ? new Decimal(sqrtPrice.toString()) - : new Decimal(PriceMath.invertSqrtPriceX64(sqrtPrice).toString()); - const directionalPrice = directionalSqrtPrice - .pow(2) - .div(U64.toString()) - .div(U64.toString()); - if (amountSpecifiedIsInput) { - const amountInDec = - index === 0 ? new Decimal(amountIn.toString()) : hopResults[index - 1]; - const amountOutDec = amountInDec - .times(new Decimal(1).sub(feeRate.toDecimal())) - .times(directionalPrice); - hopResults[index] = amountOutDec.round(); - } else { - const amountOutDec = - index === 0 ? new Decimal(amountOut.toString()) : hopResults[index - 1]; - const amountInDec = amountOutDec - .div(new Decimal(1).sub(feeRate.toDecimal())) - .div(directionalPrice); - hopResults[index] = amountInDec.round(); - } - }); - return hopResults[hops.length - 1]; - }) - .reduce((acc, cur) => acc.add(cur), new Decimal(0)); - - if (amountSpecifiedIsInput) { - const totalAmountOutDec = new Decimal(totalAmountOut.toString()); - return finalBaseValue.sub(totalAmountOutDec).div(finalBaseValue).mul(100); - } else { - const totalAmountInDec = new Decimal(totalAmountIn.toString()); - return totalAmountInDec.sub(finalBaseValue).div(totalAmountInDec).mul(100); - } - } - - type TradeHopTestParam = { - aToB: boolean; - feeRate: Percentage; - sqrtPrice: BN; - amountIn: BN; - amountOut: BN; - }; - type SubRouteTestParam = { - hops: TradeHopTestParam[]; - }; - type RouteTestParam = { - amountSpecifiedIsInput: boolean; - subRouteParams: SubRouteTestParam[]; - totalAmountIn: BN; - totalAmountOut: BN; - }; - function buildRouteTest(params: RouteTestParam) { - return { - trade: { - tokenIn: "orcaEKTdK7LKz57vaAYr9QeNsVEPfiu6QeMU1kektZE", - tokenOut: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", - tradeAmount: new BN(0), - amountSpecifiedIsInput: params.amountSpecifiedIsInput, - }, - routes: { - subRoutes: params.subRouteParams.map((subRouteParam) => { - return { - hopQuotes: subRouteParam.hops.map((hopParam) => { - return { - amountIn: hopParam.amountIn, - amountOut: hopParam.amountOut, - whirlpool: PublicKey.default, - inputMint: PublicKey.default, - outputMint: PublicKey.default, - mintA: PublicKey.default, - mintB: PublicKey.default, - vaultA: PublicKey.default, - vaultB: PublicKey.default, - quote: { - amount: new BN(0), - otherAmountThreshold: new BN(0), - sqrtPriceLimit: new BN(0), - amountSpecifiedIsInput: params.amountSpecifiedIsInput, - aToB: hopParam.aToB, - tickArray0: PublicKey.default, - tickArray1: PublicKey.default, - tickArray2: PublicKey.default, - estimatedAmountIn: new BN(0), - estimatedAmountOut: new BN(0), - estimatedEndTickIndex: 0, - estimatedEndSqrtPrice: new BN(0), - estimatedFeeAmount: new BN(0), - }, - snapshot: { - aToB: hopParam.aToB, - feeRate: hopParam.feeRate, - sqrtPrice: hopParam.sqrtPrice, - }, - }; - }), - path: { - startTokenMint: "startTokenMint", - endTokenMint: "endTokenMint", - edges: [], - }, - splitPercent: 30, - amountIn: new BN(0), - amountOut: new BN(0), - }; - }), - totalAmountIn: params.totalAmountIn, - totalAmountOut: params.totalAmountOut, - }, - }; - } -}); diff --git a/sdk/tests/sdk/types/anchor-types.test.ts b/sdk/tests/sdk/types/anchor-types.test.ts deleted file mode 100644 index b7db61c..0000000 --- a/sdk/tests/sdk/types/anchor-types.test.ts +++ /dev/null @@ -1,28 +0,0 @@ -import * as assert from "assert"; -import { AccountName, getAccountSize } from "../../../src"; - -describe("anchor-types", () => { - it("all whirlpool account names exist in IDL", async () => { - type ExpectedSize = { [a in AccountName]: number }; - const expectedSizes: ExpectedSize = { - [AccountName.WhirlpoolsConfig]: 108, - [AccountName.Position]: 216, - [AccountName.TickArray]: 9988, - [AccountName.Whirlpool]: 653, - [AccountName.FeeTier]: 44, - [AccountName.PositionBundle]: 136, - }; - Object.values(AccountName).forEach((name) => { - try { - const actualSize = getAccountSize(name); - assert.equal( - actualSize, - expectedSizes[name], - `For ${name} expected ${expectedSizes[name]} but got ${actualSize}` - ); - } catch (e) { - assert.fail(`Error fetching size for ${name}: ${e}`); - } - }); - }); -}); diff --git a/sdk/tests/sdk/whirlpools/position-impl#collectFees.test.ts b/sdk/tests/sdk/whirlpools/position-impl#collectFees.test.ts deleted file mode 100644 index e34e44e..0000000 --- a/sdk/tests/sdk/whirlpools/position-impl#collectFees.test.ts +++ /dev/null @@ -1,262 +0,0 @@ -import * as anchor from "@coral-xyz/anchor"; -import { BN } from "@coral-xyz/anchor"; -import { MathUtil } from "@orca-so/common-sdk"; -import { getAssociatedTokenAddressSync } from "@solana/spl-token"; -import * as assert from "assert"; -import Decimal from "decimal.js"; -import { - PDAUtil, - Whirlpool, - WhirlpoolClient, - WhirlpoolContext, - WhirlpoolIx, - buildWhirlpoolClient, - collectFeesQuote, - toTx -} from "../../../src"; -import { IGNORE_CACHE } from "../../../src/network/public/fetcher"; -import { TickSpacing, ZERO_BN } from "../../utils"; -import { defaultConfirmOptions } from "../../utils/const"; -import { WhirlpoolTestFixture } from "../../utils/fixture"; - -interface SharedTestContext { - provider: anchor.AnchorProvider; - program: Whirlpool; - whirlpoolCtx: WhirlpoolContext; - whirlpoolClient: WhirlpoolClient; -} - -describe("PositionImpl#collectFees()", () => { - let testCtx: SharedTestContext; - const tickLowerIndex = 29440; - const tickUpperIndex = 33536; - const tickSpacing = TickSpacing.Standard; - const liquidityAmount = new BN(10_000_000); - - before(() => { - const provider = anchor.AnchorProvider.local(undefined, defaultConfirmOptions); - - anchor.setProvider(provider); - const program = anchor.workspace.Whirlpool; - const whirlpoolCtx = WhirlpoolContext.fromWorkspace(provider, program); - const whirlpoolClient = buildWhirlpoolClient(whirlpoolCtx); - - testCtx = { - provider, - program, - whirlpoolCtx, - whirlpoolClient, - }; - }); - - async function accrueFees(fixture: WhirlpoolTestFixture) { - const ctx = testCtx.whirlpoolCtx; - const { - poolInitInfo, - positions: [positionInfo], - tokenAccountA, - tokenAccountB, - } = fixture.getInfos(); - - const { whirlpoolPda, tokenVaultAKeypair, tokenVaultBKeypair } = poolInitInfo; - - const tickArrayPda = PDAUtil.getTickArray(ctx.program.programId, whirlpoolPda.publicKey, 22528); - const oraclePda = PDAUtil.getOracle(ctx.program.programId, whirlpoolPda.publicKey); - - const pool = await testCtx.whirlpoolClient.getPool(whirlpoolPda.publicKey); - const position = await testCtx.whirlpoolClient.getPosition(positionInfo.publicKey); - - // Accrue fees in token A - await toTx( - ctx, - WhirlpoolIx.swapIx(ctx.program, { - amount: new BN(200_000), - otherAmountThreshold: ZERO_BN, - sqrtPriceLimit: MathUtil.toX64(new Decimal(4)), - amountSpecifiedIsInput: true, - aToB: true, - whirlpool: whirlpoolPda.publicKey, - tokenAuthority: ctx.wallet.publicKey, - tokenOwnerAccountA: tokenAccountA, - tokenVaultA: tokenVaultAKeypair.publicKey, - tokenOwnerAccountB: tokenAccountB, - tokenVaultB: tokenVaultBKeypair.publicKey, - tickArray0: tickArrayPda.publicKey, - tickArray1: tickArrayPda.publicKey, - tickArray2: tickArrayPda.publicKey, - oracle: oraclePda.publicKey, - }) - ).buildAndExecute(); - - // Accrue fees in token B - await toTx( - ctx, - WhirlpoolIx.swapIx(ctx.program, { - amount: new BN(200_000), - otherAmountThreshold: ZERO_BN, - sqrtPriceLimit: MathUtil.toX64(new Decimal(5)), - amountSpecifiedIsInput: true, - aToB: false, - whirlpool: whirlpoolPda.publicKey, - tokenAuthority: ctx.wallet.publicKey, - tokenOwnerAccountA: tokenAccountA, - tokenVaultA: tokenVaultAKeypair.publicKey, - tokenOwnerAccountB: tokenAccountB, - tokenVaultB: tokenVaultBKeypair.publicKey, - tickArray0: tickArrayPda.publicKey, - tickArray1: tickArrayPda.publicKey, - tickArray2: tickArrayPda.publicKey, - oracle: oraclePda.publicKey, - }) - ).buildAndExecute(); - - const poolData = await pool.refreshData(); - const positionData = await position.refreshData(); - const tickLowerData = position.getLowerTickData(); - const tickUpperData = position.getLowerTickData(); - - const quote = collectFeesQuote({ - whirlpool: poolData, - position: positionData, - tickLower: tickLowerData, - tickUpper: tickUpperData, - }); - - assert.ok(quote.feeOwedA.gtn(0) || quote.feeOwedB.gtn(0)); - } - - context("when the whirlpool is SPL-only", () => { - it("should collect fees", async () => { - const fixture = await new WhirlpoolTestFixture(testCtx.whirlpoolCtx).init({ - tickSpacing, - positions: [ - { tickLowerIndex, tickUpperIndex, liquidityAmount }, // In range position - ], - }); - - await accrueFees(fixture); - - const { positions, poolInitInfo } = fixture.getInfos(); - - const pool = await testCtx.whirlpoolClient.getPool(poolInitInfo.whirlpoolPda.publicKey); - const position = await testCtx.whirlpoolClient.getPosition(positions[0].publicKey); - - const positionDataBefore = await testCtx.whirlpoolCtx.fetcher.getPosition( - position.getAddress(), - IGNORE_CACHE - ); - - const otherWallet = anchor.web3.Keypair.generate(); - - const poolData = await pool.refreshData(); - const positionData = await position.refreshData(); - const tickLowerData = position.getLowerTickData(); - const tickUpperData = position.getLowerTickData(); - - const quote = collectFeesQuote({ - whirlpool: poolData, - position: positionData, - tickLower: tickLowerData, - tickUpper: tickUpperData, - }); - - assert.notEqual(positionDataBefore, null); - - const tx = await position.collectFees( - true, - undefined, - otherWallet.publicKey, - testCtx.provider.wallet.publicKey, - testCtx.provider.wallet.publicKey, - IGNORE_CACHE - ); - - await tx.buildAndExecute(); - - const positionDataAfter = await testCtx.whirlpoolCtx.fetcher.getPosition( - position.getAddress(), - IGNORE_CACHE - ); - - assert.notEqual(positionDataAfter, null); - - const accountAPubkey = getAssociatedTokenAddressSync(poolInitInfo.tokenMintA, otherWallet.publicKey); - const accountA = await testCtx.whirlpoolCtx.fetcher.getTokenInfo(accountAPubkey, IGNORE_CACHE); - assert.ok(accountA && new BN(accountA.amount.toString()).eq(quote.feeOwedA)); - - const accountBPubkey = getAssociatedTokenAddressSync(poolInitInfo.tokenMintB, otherWallet.publicKey); - const accountB = await testCtx.whirlpoolCtx.fetcher.getTokenInfo(accountBPubkey, IGNORE_CACHE); - assert.ok(accountB && new BN(accountB.amount.toString()).eq(quote.feeOwedB)); - }); - }); - - context("when the whirlpool is SOL-SPL", () => { - it("should collect fees", async () => { - const fixture = await new WhirlpoolTestFixture(testCtx.whirlpoolCtx).init({ - tickSpacing, - positions: [ - { tickLowerIndex, tickUpperIndex, liquidityAmount }, // In range position - ], - tokenAIsNative: true, - }); - - await accrueFees(fixture); - - const { positions, poolInitInfo } = fixture.getInfos(); - - const pool = await testCtx.whirlpoolClient.getPool(poolInitInfo.whirlpoolPda.publicKey); - const position = await testCtx.whirlpoolClient.getPosition(positions[0].publicKey); - - const positionDataBefore = await testCtx.whirlpoolCtx.fetcher.getPosition( - position.getAddress(), - IGNORE_CACHE - ); - - const otherWallet = anchor.web3.Keypair.generate(); - - const poolData = await pool.refreshData(); - const positionData = await position.refreshData(); - const tickLowerData = position.getLowerTickData(); - const tickUpperData = position.getLowerTickData(); - - const quote = collectFeesQuote({ - whirlpool: poolData, - position: positionData, - tickLower: tickLowerData, - tickUpper: tickUpperData, - }); - - const solBalanceBefore = await testCtx.provider.connection.getBalance(otherWallet.publicKey); - assert.notEqual(positionDataBefore, null); - - const tx = await position.collectFees( - true, - undefined, - otherWallet.publicKey, - testCtx.provider.wallet.publicKey, - testCtx.provider.wallet.publicKey, - IGNORE_CACHE - ); - - await tx.addSigner(otherWallet).buildAndExecute(); - - const positionDataAfter = await testCtx.whirlpoolCtx.fetcher.getPosition( - position.getAddress(), - IGNORE_CACHE - ); - - assert.notEqual(positionDataAfter, null); - - const solBalanceAfter = await testCtx.provider.connection.getBalance(otherWallet.publicKey); - const minAccountExempt = await testCtx.whirlpoolCtx.fetcher.getAccountRentExempt(); - assert.equal( - solBalanceAfter - solBalanceBefore, - quote.feeOwedA.toNumber() + minAccountExempt - ); - - const accountBPubkey = getAssociatedTokenAddressSync(poolInitInfo.tokenMintB, otherWallet.publicKey); - const accountB = await testCtx.whirlpoolCtx.fetcher.getTokenInfo(accountBPubkey, IGNORE_CACHE); - assert.ok(accountB && new BN(accountB.amount.toString()).eq(quote.feeOwedB)); - }); - }); -}); diff --git a/sdk/tests/sdk/whirlpools/position-impl#collectRewards.test.ts b/sdk/tests/sdk/whirlpools/position-impl#collectRewards.test.ts deleted file mode 100644 index d55619c..0000000 --- a/sdk/tests/sdk/whirlpools/position-impl#collectRewards.test.ts +++ /dev/null @@ -1,187 +0,0 @@ -import * as anchor from "@coral-xyz/anchor"; -import { MathUtil } from "@orca-so/common-sdk"; -import { getAssociatedTokenAddressSync } from "@solana/spl-token"; -import * as assert from "assert"; -import { BN } from "bn.js"; -import Decimal from "decimal.js"; -import { - NUM_REWARDS, - Whirlpool, - WhirlpoolClient, - WhirlpoolContext, - buildWhirlpoolClient, - collectRewardsQuote -} from "../../../src"; -import { IGNORE_CACHE } from "../../../src/network/public/fetcher"; -import { TickSpacing, sleep } from "../../utils"; -import { defaultConfirmOptions } from "../../utils/const"; -import { WhirlpoolTestFixture } from "../../utils/fixture"; - -interface SharedTestContext { - provider: anchor.AnchorProvider; - program: Whirlpool; - whirlpoolCtx: WhirlpoolContext; - whirlpoolClient: WhirlpoolClient; -} - -describe("PositionImpl#collectRewards()", () => { - let testCtx: SharedTestContext; - const tickLowerIndex = 29440; - const tickUpperIndex = 33536; - const vaultStartBalance = 1_000_000; - const tickSpacing = TickSpacing.Standard; - const liquidityAmount = new BN(10_000_000); - - before(() => { - const provider = anchor.AnchorProvider.local(undefined, defaultConfirmOptions); - anchor.setProvider(provider); - const program = anchor.workspace.Whirlpool; - const whirlpoolCtx = WhirlpoolContext.fromWorkspace(provider, program); - const whirlpoolClient = buildWhirlpoolClient(whirlpoolCtx); - - testCtx = { - provider, - program, - whirlpoolCtx, - whirlpoolClient, - }; - }); - - context("when the whirlpool is SPL-only", () => { - it("should collect rewards", async () => { - const fixture = await new WhirlpoolTestFixture(testCtx.whirlpoolCtx).init({ - tickSpacing, - positions: [ - { tickLowerIndex, tickUpperIndex, liquidityAmount }, // In range position - ], - rewards: [ - { - emissionsPerSecondX64: MathUtil.toX64(new Decimal(10)), - vaultAmount: new BN(vaultStartBalance), - }, - { - emissionsPerSecondX64: MathUtil.toX64(new Decimal(10)), - vaultAmount: new BN(vaultStartBalance), - }, - { - emissionsPerSecondX64: MathUtil.toX64(new Decimal(10)), - vaultAmount: new BN(vaultStartBalance), - }, - ], - }); - - const { positions, poolInitInfo, rewards } = fixture.getInfos(); - - const pool = await testCtx.whirlpoolClient.getPool(poolInitInfo.whirlpoolPda.publicKey, IGNORE_CACHE); - const position = await testCtx.whirlpoolClient.getPosition(positions[0].publicKey, IGNORE_CACHE); - - const otherWallet = anchor.web3.Keypair.generate(); - const preCollectPoolData = pool.getData(); - - // accrue rewards - await sleep(1200); - - await ( - await position.collectRewards( - rewards.map((r) => r.rewardMint), - true, - undefined, - otherWallet.publicKey, - testCtx.provider.wallet.publicKey, - testCtx.provider.wallet.publicKey, - IGNORE_CACHE - ) - ).buildAndExecute(); - - // Verify the results fetched is the same as SDK estimate if the timestamp is the same - const postCollectPoolData = await pool.refreshData(); - const quote = collectRewardsQuote({ - whirlpool: preCollectPoolData, - position: position.getData(), - tickLower: position.getLowerTickData(), - tickUpper: position.getUpperTickData(), - timeStampInSeconds: postCollectPoolData.rewardLastUpdatedTimestamp, - }); - - // Check that the expectation is not zero - for (let i = 0; i < NUM_REWARDS; i++) { - assert.ok(!quote[i]!.isZero()); - } - - for (let i = 0; i < NUM_REWARDS; i++) { - const rewardATA = getAssociatedTokenAddressSync(rewards[i].rewardMint, otherWallet.publicKey); - const rewardTokenAccount = await testCtx.whirlpoolCtx.fetcher.getTokenInfo(rewardATA, IGNORE_CACHE); - assert.equal(rewardTokenAccount?.amount.toString(), quote[i]?.toString()); - } - }); - }); - - context("when the whirlpool is SOL-SPL", () => { - it("should collect rewards", async () => { - const fixture = await new WhirlpoolTestFixture(testCtx.whirlpoolCtx).init({ - tickSpacing, - positions: [ - { tickLowerIndex, tickUpperIndex, liquidityAmount }, // In range position - ], - rewards: [ - { - emissionsPerSecondX64: MathUtil.toX64(new Decimal(10)), - vaultAmount: new BN(vaultStartBalance), - }, - { - emissionsPerSecondX64: MathUtil.toX64(new Decimal(10)), - vaultAmount: new BN(vaultStartBalance), - }, - { - emissionsPerSecondX64: MathUtil.toX64(new Decimal(10)), - vaultAmount: new BN(vaultStartBalance), - }, - ], - tokenAIsNative: true, - }); - - const { positions, poolInitInfo, rewards } = fixture.getInfos(); - - const pool = await testCtx.whirlpoolClient.getPool(poolInitInfo.whirlpoolPda.publicKey, IGNORE_CACHE); - const position = await testCtx.whirlpoolClient.getPosition(positions[0].publicKey, IGNORE_CACHE); - const otherWallet = anchor.web3.Keypair.generate(); - const preCollectPoolData = pool.getData(); - - // accrue rewards - await sleep(1200); - - await ( - await position.collectRewards( - rewards.map((r) => r.rewardMint), - true, - undefined, - otherWallet.publicKey, - testCtx.provider.wallet.publicKey, - testCtx.provider.wallet.publicKey, - IGNORE_CACHE - ) - ).buildAndExecute(); - - // Verify the results fetched is the same as SDK estimate if the timestamp is the same - const postCollectPoolData = await pool.refreshData(); - const quote = collectRewardsQuote({ - whirlpool: preCollectPoolData, - position: position.getData(), - tickLower: position.getLowerTickData(), - tickUpper: position.getUpperTickData(), - timeStampInSeconds: postCollectPoolData.rewardLastUpdatedTimestamp, - }); - - // Check that the expectation is not zero - for (let i = 0; i < NUM_REWARDS; i++) { - assert.ok(!quote[i]!.isZero()); - } - - for (let i = 0; i < NUM_REWARDS; i++) { - const rewardATA = getAssociatedTokenAddressSync(rewards[i].rewardMint, otherWallet.publicKey); - const rewardTokenAccount = await testCtx.whirlpoolCtx.fetcher.getTokenInfo(rewardATA, IGNORE_CACHE); - assert.equal(rewardTokenAccount?.amount.toString(), quote[i]?.toString()); - } - }); - }); -}); diff --git a/sdk/tests/sdk/whirlpools/position-impl.test.ts b/sdk/tests/sdk/whirlpools/position-impl.test.ts deleted file mode 100644 index beefb43..0000000 --- a/sdk/tests/sdk/whirlpools/position-impl.test.ts +++ /dev/null @@ -1,244 +0,0 @@ -import * as anchor from "@coral-xyz/anchor"; -import { Percentage } from "@orca-so/common-sdk"; -import { getAssociatedTokenAddressSync } from "@solana/spl-token"; -import * as assert from "assert"; -import Decimal from "decimal.js"; -import { - buildWhirlpoolClient, - decreaseLiquidityQuoteByLiquidity, - increaseLiquidityQuoteByInputTokenUsingPriceSlippage, - PriceMath -} from "../../../src"; -import { WhirlpoolContext } from "../../../src/context"; -import { IGNORE_CACHE } from "../../../src/network/public/fetcher"; -import { createAssociatedTokenAccount, TickSpacing, transferToken } from "../../utils"; -import { defaultConfirmOptions } from "../../utils/const"; -import { initTestPool } from "../../utils/init-utils"; -import { initPosition, mintTokensToTestAccount } from "../../utils/test-builders"; - -describe("position-impl", () => { - const provider = anchor.AnchorProvider.local(undefined, defaultConfirmOptions); - - const program = anchor.workspace.Whirlpool; - const ctx = WhirlpoolContext.fromWorkspace(provider, program); - const fetcher = ctx.fetcher; - const client = buildWhirlpoolClient(ctx); - - it("increase and decrease liquidity on position", async () => { - const { poolInitInfo } = await initTestPool( - ctx, - TickSpacing.Standard, - PriceMath.priceToSqrtPriceX64(new Decimal(100), 6, 6) - ); - - // Create and mint tokens in this wallet - await mintTokensToTestAccount( - ctx.provider, - poolInitInfo.tokenMintA, - 10_500_000_000, - poolInitInfo.tokenMintB, - 10_500_000_000 - ); - - const pool = await client.getPool(poolInitInfo.whirlpoolPda.publicKey); - const lowerTick = PriceMath.priceToTickIndex( - new Decimal(89), - pool.getTokenAInfo().decimals, - pool.getTokenBInfo().decimals - ); - const upperTick = PriceMath.priceToTickIndex( - new Decimal(120), - pool.getTokenAInfo().decimals, - pool.getTokenBInfo().decimals - ); - - // [Action] Initialize Tick Arrays - const initTickArrayTx = (await pool.initTickArrayForTicks([lowerTick, upperTick]))!; - await initTickArrayTx.buildAndExecute(); - - // [Action] Create a position at price 89, 120 with 50 token A - const lowerPrice = new Decimal(89); - const upperPrice = new Decimal(120); - const { positionAddress } = await initPosition( - ctx, - pool, - lowerPrice, - upperPrice, - poolInitInfo.tokenMintA, - 50 - ); - - // [Action] Increase liquidity by 70 tokens of tokenB - const position = await client.getPosition(positionAddress.publicKey, IGNORE_CACHE); - const preIncreaseData = position.getData(); - const increase_quote = increaseLiquidityQuoteByInputTokenUsingPriceSlippage( - poolInitInfo.tokenMintB, - new Decimal(70), - lowerTick, - upperTick, - Percentage.fromFraction(1, 100), - pool - ); - - await ( - await position.increaseLiquidity(increase_quote, false, ctx.wallet.publicKey) - ).buildAndExecute(); - - const postIncreaseData = await position.refreshData(); - const expectedPostIncreaseLiquidity = preIncreaseData.liquidity.add( - increase_quote.liquidityAmount - ); - assert.equal(postIncreaseData.liquidity.toString(), expectedPostIncreaseLiquidity.toString()); - - // [Action] Withdraw half of the liquidity away from the position and verify - const withdrawHalf = postIncreaseData.liquidity.div(new anchor.BN(2)); - const decrease_quote = decreaseLiquidityQuoteByLiquidity( - withdrawHalf, - Percentage.fromFraction(0, 100), - position, - pool - ); - - await (await position.decreaseLiquidity(decrease_quote, false)).buildAndExecute(); - - const postWithdrawData = await position.refreshData(); - const expectedPostWithdrawLiquidity = postIncreaseData.liquidity.sub( - decrease_quote.liquidityAmount - ); - assert.equal(postWithdrawData.liquidity.toString(), expectedPostWithdrawLiquidity.toString()); - }); - - it("increase & decrease liquidity on position with a different destination, position wallet", async () => { - const { poolInitInfo } = await initTestPool( - ctx, - TickSpacing.Standard, - PriceMath.priceToSqrtPriceX64(new Decimal(100), 6, 6) - ); - - // Create and mint tokens in this wallet - await mintTokensToTestAccount( - ctx.provider, - poolInitInfo.tokenMintA, - 10_500_000_000, - poolInitInfo.tokenMintB, - 10_500_000_000 - ); - - const pool = await client.getPool(poolInitInfo.whirlpoolPda.publicKey); - const lowerTick = PriceMath.priceToTickIndex( - new Decimal(89), - pool.getTokenAInfo().decimals, - pool.getTokenBInfo().decimals - ); - const upperTick = PriceMath.priceToTickIndex( - new Decimal(120), - pool.getTokenAInfo().decimals, - pool.getTokenBInfo().decimals - ); - - // [Action] Initialize Tick Arrays - const initTickArrayTx = (await pool.initTickArrayForTicks([lowerTick, upperTick]))!; - await initTickArrayTx.buildAndExecute(); - - // [Action] Create a position at price 89, 120 with 50 token A - const lowerPrice = new Decimal(89); - const upperPrice = new Decimal(120); - const { positionMint, positionAddress } = await initPosition( - ctx, - pool, - lowerPrice, - upperPrice, - poolInitInfo.tokenMintA, - 50 - ); - - // [Action] Increase liquidity by 70 tokens of tokenB & create the ATA in the new source Wallet - const position = await client.getPosition(positionAddress.publicKey, IGNORE_CACHE); - const preIncreaseData = position.getData(); - const increase_quote = increaseLiquidityQuoteByInputTokenUsingPriceSlippage( - poolInitInfo.tokenMintB, - new Decimal(70), - lowerTick, - upperTick, - Percentage.fromFraction(1, 100), - pool - ); - - await (await position.increaseLiquidity(increase_quote, false)).buildAndExecute(); - - const postIncreaseData = await position.refreshData(); - const expectedPostIncreaseLiquidity = preIncreaseData.liquidity.add( - increase_quote.liquidityAmount - ); - assert.equal(postIncreaseData.liquidity.toString(), expectedPostIncreaseLiquidity.toString()); - - // [Action] Withdraw half of the liquidity away from the position and verify - const withdrawHalf = postIncreaseData.liquidity.div(new anchor.BN(2)); - const decrease_quote = await decreaseLiquidityQuoteByLiquidity( - withdrawHalf, - Percentage.fromFraction(0, 100), - position, - pool - ); - - // Transfer the position token to another wallet - const otherWallet = anchor.web3.Keypair.generate(); - const walletPositionTokenAccount = getAssociatedTokenAddressSync(positionMint, ctx.wallet.publicKey); - const newOwnerPositionTokenAccount = await createAssociatedTokenAccount( - ctx.provider, - positionMint, - otherWallet.publicKey, - ctx.wallet.publicKey - ); - await transferToken(provider, walletPositionTokenAccount, newOwnerPositionTokenAccount, 1); - - // Mint to this other wallet and increase more tokens - await mintTokensToTestAccount( - ctx.provider, - poolInitInfo.tokenMintA, - 10_500_000_000, - poolInitInfo.tokenMintB, - 10_500_000_000, - otherWallet.publicKey - ); - const increaseQuoteFromOtherWallet = increaseLiquidityQuoteByInputTokenUsingPriceSlippage( - poolInitInfo.tokenMintB, - new Decimal(80), - lowerTick, - upperTick, - Percentage.fromFraction(1, 100), - pool - ); - await ( - await position.increaseLiquidity( - increaseQuoteFromOtherWallet, - true, - otherWallet.publicKey, - otherWallet.publicKey - ) - ) - .addSigner(otherWallet) - .buildAndExecute(); - - const postSecondIncreaseData = await position.refreshData(); - - // Withdraw liquidity into another wallet - const destinationWallet = anchor.web3.Keypair.generate(); - await ( - await position.decreaseLiquidity( - decrease_quote, - true, - destinationWallet.publicKey, - otherWallet.publicKey - ) - ) - .addSigner(otherWallet) - .buildAndExecute(); - - const postWithdrawData = await position.refreshData(); - const expectedPostWithdrawLiquidity = postSecondIncreaseData.liquidity.sub( - decrease_quote.liquidityAmount - ); - assert.equal(postWithdrawData.liquidity.toString(), expectedPostWithdrawLiquidity.toString()); - }); -}); diff --git a/sdk/tests/sdk/whirlpools/quote/decrease-liquidity-quote.test.ts b/sdk/tests/sdk/whirlpools/quote/decrease-liquidity-quote.test.ts deleted file mode 100644 index 411da69..0000000 --- a/sdk/tests/sdk/whirlpools/quote/decrease-liquidity-quote.test.ts +++ /dev/null @@ -1,61 +0,0 @@ -import * as assert from "assert"; -import { PriceMath, decreaseLiquidityQuoteByLiquidityWithParams } from "../../../../src"; -import { BN } from "bn.js"; -import { PublicKey } from "@solana/web3.js"; -import { Percentage } from "@orca-so/common-sdk"; - -describe("edge cases", () => { - const tokenMintA = new PublicKey("orcaEKTdK7LKz57vaAYr9QeNsVEPfiu6QeMU1kektZE"); - const tokenMintB = new PublicKey("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"); - - it("sqrtPrice on lower bound", async () => { - const quote = decreaseLiquidityQuoteByLiquidityWithParams({ - liquidity: new BN(100000), - sqrtPrice: PriceMath.tickIndexToSqrtPriceX64(0), - tickLowerIndex: 0, - tickUpperIndex: 64, - tickCurrentIndex: 0, - slippageTolerance: Percentage.fromFraction(0, 100), - }); - - assert.ok(quote.tokenEstA.gtn(0)); - assert.ok(quote.tokenEstB.isZero()); - assert.ok(quote.tokenMinA.gtn(0)); - assert.ok(quote.tokenMinB.isZero()); - }); - - it("tickCurrentIndex on lower bound but sqrtPrice not on lower bound", async () => { - assert.ok(PriceMath.tickIndexToSqrtPriceX64(1).subn(1).gt(PriceMath.tickIndexToSqrtPriceX64(0))); - - const quote = decreaseLiquidityQuoteByLiquidityWithParams({ - liquidity: new BN(100000), - sqrtPrice: PriceMath.tickIndexToSqrtPriceX64(1).subn(1), - tickLowerIndex: 0, - tickUpperIndex: 64, - tickCurrentIndex: 0, - slippageTolerance: Percentage.fromFraction(0, 100), - }); - - assert.ok(quote.tokenEstA.gtn(0)); - assert.ok(quote.tokenEstB.gtn(0)); - assert.ok(quote.tokenMinA.gtn(0)); - assert.ok(quote.tokenMinB.gtn(0)); - }); - - it("sqrtPrice on upper bound", async () => { - const quote = decreaseLiquidityQuoteByLiquidityWithParams({ - liquidity: new BN(100000), - sqrtPrice: PriceMath.tickIndexToSqrtPriceX64(64), - tickLowerIndex: 0, - tickUpperIndex: 64, - tickCurrentIndex: 64, - slippageTolerance: Percentage.fromFraction(0, 100), - }); - - assert.ok(quote.tokenEstA.isZero()); - assert.ok(quote.tokenEstB.gtn(0)); - assert.ok(quote.tokenMinA.isZero()); - assert.ok(quote.tokenMinB.gtn(0)); - }); - -}); diff --git a/sdk/tests/sdk/whirlpools/quote/increase-liquidity-quote-by-input-token.test.ts b/sdk/tests/sdk/whirlpools/quote/increase-liquidity-quote-by-input-token.test.ts deleted file mode 100644 index 098b3c4..0000000 --- a/sdk/tests/sdk/whirlpools/quote/increase-liquidity-quote-by-input-token.test.ts +++ /dev/null @@ -1,450 +0,0 @@ -import { Percentage, ZERO } from "@orca-so/common-sdk"; -import { PublicKey } from "@solana/web3.js"; -import * as assert from "assert"; -import BN from "bn.js"; -import { - PriceMath, - increaseLiquidityQuoteByInputTokenWithParams, - increaseLiquidityQuoteByInputTokenWithParamsUsingPriceSlippage, - increaseLiquidityQuoteByLiquidityWithParams, -} from "../../../../src"; -import { - getLiquidityFromTokenA, - getLiquidityFromTokenB, -} from "../../../../src/utils/position-util"; - -function getTestSlippageRange(currIndex: number, slippage: Percentage) { - const sqrtPrice = PriceMath.tickIndexToSqrtPriceX64(currIndex); - const { - lowerBound: [_sLowerSqrtPrice, sLowerIndex], - upperBound: [_sUpperSqrtPrice, sUpperIndex], - } = PriceMath.getSlippageBoundForSqrtPrice(sqrtPrice, slippage); - - return { - tickLowerIndex: sLowerIndex === sUpperIndex ? sLowerIndex - 1 : sLowerIndex, - tickUpperIndex: sUpperIndex, - tickCurrentIndex: currIndex, - }; -} - -const variations = [ - [0, true, Percentage.fromFraction(1, 1000)] as const, - [0, false, Percentage.fromFraction(1, 1000)] as const, - [0, true, Percentage.fromFraction(1, 100)] as const, - [0, false, Percentage.fromFraction(1, 100)] as const, - [234653, true, Percentage.fromFraction(1, 1000)] as const, - [234653, false, Percentage.fromFraction(1, 1000)] as const, - [234653, true, Percentage.fromFraction(1, 100)] as const, - [234653, false, Percentage.fromFraction(1, 100)] as const, - [-234653, true, Percentage.fromFraction(1, 1000)] as const, - [-234653, false, Percentage.fromFraction(1, 1000)] as const, - [-234653, true, Percentage.fromFraction(1, 100)] as const, - [-234653, false, Percentage.fromFraction(1, 100)] as const, -]; - -// NOTE: Slippage range for current price (tick = 0) is [-101, 99] -// [---P---] = P is the current price & [] is the slippage boundary -// |-------| = Position Boundary -variations.forEach(([currentTickIndex, isTokenA, slippage]) => { - describe("increaseLiquidityQuoteByInputTokenUsingPriceSlippage", () => { - const tokenMintA = new PublicKey("orcaEKTdK7LKz57vaAYr9QeNsVEPfiu6QeMU1kektZE"); - const tokenMintB = new PublicKey("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"); - - it(`|[--------P--------]| @ isTokenA - ${isTokenA} tickCurrentIndex - ${currentTickIndex}, slippage - ${slippage.toDecimal()}%`, async () => { - const slippageRange = getTestSlippageRange(currentTickIndex, slippage); - testVariation({ - pTickLowerIndex: slippageRange.tickLowerIndex, - pTickUpperIndex: slippageRange.tickCurrentIndex, - tickCurrentIndex: slippageRange.tickCurrentIndex, - inputTokenAmount: new BN(100000), - isTokenA, - slippageTolerance: slippage, - }); - }); - - it(`|----------------| [---P---] @ isTokenA - ${isTokenA} tickCurrentIndex - ${currentTickIndex}, slippage - ${slippage.toDecimal()}%`, async () => { - const slippageRange = getTestSlippageRange(currentTickIndex, slippage); - testVariation({ - pTickLowerIndex: slippageRange.tickLowerIndex - 200, - pTickUpperIndex: slippageRange.tickLowerIndex - 100, - tickCurrentIndex: slippageRange.tickCurrentIndex, - inputTokenAmount: new BN(100000), - isTokenA, - slippageTolerance: slippage, - }); - }); - - it(`|--------------[--|--P----] @ isTokenA - ${isTokenA} tickCurrentIndex - ${currentTickIndex}, slippage - ${slippage.toDecimal()}%`, async () => { - const slippageRange = getTestSlippageRange(currentTickIndex, slippage); - testVariation({ - pTickLowerIndex: slippageRange.tickLowerIndex - 200, - pTickUpperIndex: slippageRange.tickLowerIndex + 5, - tickCurrentIndex: slippageRange.tickCurrentIndex, - inputTokenAmount: new BN(100000), - isTokenA, - slippageTolerance: slippage, - }); - }); - - it(`[|---|---P------] @ isTokenA - ${isTokenA} tickCurrentIndex - ${currentTickIndex}, slippage - ${slippage.toDecimal()}%`, async () => { - const slippageRange = getTestSlippageRange(currentTickIndex, slippage); - testVariation({ - pTickLowerIndex: slippageRange.tickLowerIndex, - pTickUpperIndex: slippageRange.tickCurrentIndex - 1, - tickCurrentIndex: slippageRange.tickCurrentIndex, - inputTokenAmount: new BN(100000), - isTokenA, - slippageTolerance: slippage, - }); - }); - - it(`[--|---|--P-------] @ isTokenA - ${isTokenA} tickCurrentIndex - ${currentTickIndex}, slippage - ${slippage.toDecimal()}%`, async () => { - const slippageRange = getTestSlippageRange(currentTickIndex, slippage); - testVariation({ - pTickLowerIndex: slippageRange.tickLowerIndex + 5, - pTickUpperIndex: slippageRange.tickCurrentIndex - 5, - tickCurrentIndex: slippageRange.tickCurrentIndex, - inputTokenAmount: new BN(100000), - isTokenA, - slippageTolerance: slippage, - }); - }); - - it(`|-----[---P---]-----| @ isTokenA - ${isTokenA} tickCurrentIndex - ${currentTickIndex}, slippage - ${slippage.toDecimal()}%`, async () => { - const slippageRange = getTestSlippageRange(currentTickIndex, slippage); - testVariation({ - pTickLowerIndex: slippageRange.tickLowerIndex - 200, - pTickUpperIndex: slippageRange.tickUpperIndex + 200, - tickCurrentIndex: slippageRange.tickCurrentIndex, - inputTokenAmount: new BN(100000), - isTokenA, - slippageTolerance: slippage, - }); - }); - - it(`[--|----P----]-----| @ isTokenA - ${isTokenA} tickCurrentIndex - ${currentTickIndex}, slippage - ${slippage.toDecimal()}%`, async () => { - const slippageRange = getTestSlippageRange(currentTickIndex, slippage); - testVariation({ - pTickLowerIndex: slippageRange.tickLowerIndex + 5, - pTickUpperIndex: slippageRange.tickUpperIndex + 5, - tickCurrentIndex: slippageRange.tickCurrentIndex, - inputTokenAmount: new BN(100000), - isTokenA, - slippageTolerance: slippage, - }); - }); - - it(`|--[---P---|-----] @ isTokenA - ${isTokenA} tickCurrentIndex - ${currentTickIndex}, slippage - ${slippage.toDecimal()}%`, async () => { - const slippageRange = getTestSlippageRange(currentTickIndex, slippage); - testVariation({ - pTickLowerIndex: slippageRange.tickLowerIndex - 125, - pTickUpperIndex: slippageRange.tickCurrentIndex + 5, - tickCurrentIndex: slippageRange.tickCurrentIndex, - inputTokenAmount: new BN(100000), - isTokenA, - slippageTolerance: slippage, - }); - }); - - it(`[---|---P---|----] @ isTokenA - ${isTokenA} tickCurrentIndex - ${currentTickIndex}, slippage - ${slippage.toDecimal()}%`, async () => { - const slippageRange = getTestSlippageRange(currentTickIndex, slippage); - testVariation({ - pTickLowerIndex: slippageRange.tickLowerIndex + 5, - pTickUpperIndex: slippageRange.tickCurrentIndex + 5, - tickCurrentIndex: slippageRange.tickCurrentIndex, - inputTokenAmount: new BN(100000), - isTokenA, - slippageTolerance: slippage, - }); - }); - - it(`[---P---] |---------| @ isTokenA - ${isTokenA} tickCurrentIndex - ${currentTickIndex}, slippage - ${slippage.toDecimal()}%`, async () => { - const slippageRange = getTestSlippageRange(currentTickIndex, slippage); - testVariation({ - pTickLowerIndex: slippageRange.tickUpperIndex + 100, - pTickUpperIndex: slippageRange.tickUpperIndex + 200, - tickCurrentIndex: slippageRange.tickCurrentIndex, - inputTokenAmount: new BN(100000), - isTokenA, - slippageTolerance: slippage, - }); - }); - - it(`[---P--|---]------| @ isTokenA - ${isTokenA} tickCurrentIndex - ${currentTickIndex}, slippage - ${slippage.toDecimal()}%`, async () => { - const slippageRange = getTestSlippageRange(currentTickIndex, slippage); - testVariation({ - pTickLowerIndex: slippageRange.tickCurrentIndex + 5, - pTickUpperIndex: slippageRange.tickUpperIndex + 100, - tickCurrentIndex: slippageRange.tickCurrentIndex, - inputTokenAmount: new BN(100000), - isTokenA, - slippageTolerance: slippage, - }); - }); - - it(`[-----P--|---|] @ isTokenA - ${isTokenA} tickCurrentIndex - ${currentTickIndex}, slippage - ${slippage.toDecimal()}%`, async () => { - const slippageRange = getTestSlippageRange(currentTickIndex, slippage); - testVariation({ - pTickLowerIndex: slippageRange.tickCurrentIndex + 5, - pTickUpperIndex: slippageRange.tickUpperIndex, - tickCurrentIndex: slippageRange.tickCurrentIndex, - inputTokenAmount: new BN(100000), - isTokenA, - slippageTolerance: slippage, - }); - }); - - it(`[-------P--|---|--] @ isTokenA - ${isTokenA} tickCurrentIndex - ${currentTickIndex}, slippage - ${slippage.toDecimal()}%`, async () => { - const slippageRange = getTestSlippageRange(currentTickIndex, slippage); - testVariation({ - pTickLowerIndex: slippageRange.tickCurrentIndex + 2, - pTickUpperIndex: slippageRange.tickUpperIndex - 2, - tickCurrentIndex: slippageRange.tickCurrentIndex, - inputTokenAmount: new BN(100000), - isTokenA, - slippageTolerance: slippage, - }); - }); - - function testVariation(params: { - pTickLowerIndex: number; - pTickUpperIndex: number; - tickCurrentIndex: number; - inputTokenAmount: BN; - isTokenA: boolean; - slippageTolerance: Percentage; - }) { - const { pTickLowerIndex, pTickUpperIndex, tickCurrentIndex, inputTokenAmount, isTokenA } = - params; - - const sqrtPrice = PriceMath.tickIndexToSqrtPriceX64(tickCurrentIndex); - - const inputTokenMint = isTokenA ? tokenMintA : tokenMintB; - - const quote = increaseLiquidityQuoteByInputTokenWithParamsUsingPriceSlippage({ - inputTokenAmount, - inputTokenMint, - sqrtPrice, - tokenMintA, - tokenMintB, - tickLowerIndex: pTickLowerIndex, - tickUpperIndex: pTickUpperIndex, - tickCurrentIndex, - slippageTolerance: slippage, - }); - - // Expectations - const liquidity = getLiquidityFromInputToken({ - inputTokenAmount, - isInputTokenA: isTokenA, - sqrtPrice, - currentTickIndex: tickCurrentIndex, - lowerTickIndex: pTickLowerIndex, - upperTickIndex: pTickUpperIndex, - }); - - const expectedQuote = increaseLiquidityQuoteByLiquidityWithParams({ - tickLowerIndex: pTickLowerIndex, - tickUpperIndex: pTickUpperIndex, - tickCurrentIndex, - liquidity, - sqrtPrice: sqrtPrice, - slippageTolerance: slippage, - }); - - const { - tokenEstA: expectedTokenEstA, - tokenEstB: expectedTokenEstB, - tokenMaxA: expectedTokenMaxA, - tokenMaxB: expectedTokenMaxB, - } = expectedQuote; - - assert.ok( - quote.tokenEstA.eq(expectedTokenEstA), - `tokenEstA: ${quote.tokenEstA.toString()} !== ${expectedTokenEstA.toString()}`, - ); - assert.ok( - quote.tokenEstB.eq(expectedTokenEstB), - `tokenEstB: ${quote.tokenEstB.toString()} !== ${expectedTokenEstB.toString()}`, - ); - assert.ok( - quote.tokenMaxA.eq(expectedTokenMaxA), - `tokenMaxA: ${quote.tokenMaxA.toString()} !== ${expectedTokenMaxA.toString()}`, - ); - assert.ok( - quote.tokenMaxB.eq(expectedTokenMaxB), - `tokenMaxB: ${quote.tokenMaxB.toString()} !== ${expectedTokenMaxB.toString()}`, - ); - } - }); -}); - -describe("edge cases for old slippage", () => { - const tokenMintA = new PublicKey("orcaEKTdK7LKz57vaAYr9QeNsVEPfiu6QeMU1kektZE"); - const tokenMintB = new PublicKey("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"); - - it("sqrtPrice on lower bound, tokenB input", async () => { - const quote = increaseLiquidityQuoteByInputTokenWithParams({ - inputTokenAmount: new BN(1000), - inputTokenMint: tokenMintB, - sqrtPrice: PriceMath.tickIndexToSqrtPriceX64(0), - tokenMintA, - tokenMintB, - tickLowerIndex: 0, - tickUpperIndex: 64, - tickCurrentIndex: 0, - slippageTolerance: Percentage.fromFraction(0, 100), - }); - - assert.ok(quote.liquidityAmount.isZero()); - assert.ok(quote.tokenEstA.isZero()); - assert.ok(quote.tokenEstB.isZero()); - assert.ok(quote.tokenMaxA.isZero()); - assert.ok(quote.tokenMaxB.isZero()); - }); - - it("sqrtPrice on lower bound, tokenA input", async () => { - const quote = increaseLiquidityQuoteByInputTokenWithParams({ - inputTokenAmount: new BN(1000), - inputTokenMint: tokenMintA, - sqrtPrice: PriceMath.tickIndexToSqrtPriceX64(0), - tokenMintA, - tokenMintB, - tickLowerIndex: 0, - tickUpperIndex: 64, - tickCurrentIndex: 0, - slippageTolerance: Percentage.fromFraction(0, 100), - }); - - assert.ok(quote.liquidityAmount.gtn(0)); - assert.ok(quote.tokenEstA.gtn(0)); - assert.ok(quote.tokenEstB.isZero()); - assert.ok(quote.tokenMaxA.gtn(0)); - assert.ok(quote.tokenMaxB.isZero()); - }); - - it("tickCurrentIndex on lower bound but sqrtPrice not on lower bound, tokenA input", async () => { - assert.ok( - PriceMath.tickIndexToSqrtPriceX64(1).subn(1).gt(PriceMath.tickIndexToSqrtPriceX64(0)), - ); - - const quote = increaseLiquidityQuoteByInputTokenWithParams({ - inputTokenAmount: new BN(1000), - inputTokenMint: tokenMintA, - sqrtPrice: PriceMath.tickIndexToSqrtPriceX64(1).subn(1), - tokenMintA, - tokenMintB, - tickLowerIndex: 0, - tickUpperIndex: 64, - tickCurrentIndex: 0, - slippageTolerance: Percentage.fromFraction(0, 100), - }); - - assert.ok(quote.liquidityAmount.gtn(0)); - assert.ok(quote.tokenEstA.gtn(0)); - assert.ok(quote.tokenEstB.gtn(0)); - assert.ok(quote.tokenMaxA.gtn(0)); - assert.ok(quote.tokenMaxB.gtn(0)); - }); - - it("tickCurrentIndex on lower bound but sqrtPrice not on lower bound, tokenB input", async () => { - assert.ok( - PriceMath.tickIndexToSqrtPriceX64(1).subn(1).gt(PriceMath.tickIndexToSqrtPriceX64(0)), - ); - - const quote = increaseLiquidityQuoteByInputTokenWithParams({ - inputTokenAmount: new BN(1000), - inputTokenMint: tokenMintB, - sqrtPrice: PriceMath.tickIndexToSqrtPriceX64(1).subn(1), - tokenMintA, - tokenMintB, - tickLowerIndex: 0, - tickUpperIndex: 64, - tickCurrentIndex: 0, - slippageTolerance: Percentage.fromFraction(0, 100), - }); - - assert.ok(quote.liquidityAmount.gtn(0)); - assert.ok(quote.tokenEstA.gtn(0)); - assert.ok(quote.tokenEstB.gtn(0)); - assert.ok(quote.tokenMaxA.gtn(0)); - assert.ok(quote.tokenMaxB.gtn(0)); - }); - - it("sqrtPrice on upper bound, tokenA input", async () => { - const quote = increaseLiquidityQuoteByInputTokenWithParams({ - inputTokenAmount: new BN(1000), - inputTokenMint: tokenMintA, - sqrtPrice: PriceMath.tickIndexToSqrtPriceX64(64), - tokenMintA, - tokenMintB, - tickLowerIndex: 0, - tickUpperIndex: 64, - tickCurrentIndex: 64, - slippageTolerance: Percentage.fromFraction(0, 100), - }); - - assert.ok(quote.liquidityAmount.isZero()); - assert.ok(quote.tokenEstA.isZero()); - assert.ok(quote.tokenEstB.isZero()); - assert.ok(quote.tokenMaxA.isZero()); - assert.ok(quote.tokenMaxB.isZero()); - }); - - it("sqrtPrice on upper bound, tokenB input", async () => { - const quote = increaseLiquidityQuoteByInputTokenWithParams({ - inputTokenAmount: new BN(1000), - inputTokenMint: tokenMintB, - sqrtPrice: PriceMath.tickIndexToSqrtPriceX64(64), - tokenMintA, - tokenMintB, - tickLowerIndex: 0, - tickUpperIndex: 64, - tickCurrentIndex: 64, - slippageTolerance: Percentage.fromFraction(0, 100), - }); - - assert.ok(quote.liquidityAmount.gtn(0)); - assert.ok(quote.tokenEstA.isZero()); - assert.ok(quote.tokenEstB.gtn(0)); - assert.ok(quote.tokenMaxA.isZero()); - assert.ok(quote.tokenMaxB.gtn(0)); - }); -}); - -function getLiquidityFromInputToken(params: { - inputTokenAmount: BN; - isInputTokenA: boolean; - currentTickIndex: number; - sqrtPrice: BN; - lowerTickIndex: number; - upperTickIndex: number; -}) { - const { - inputTokenAmount, - isInputTokenA, - sqrtPrice, - currentTickIndex, - lowerTickIndex, - upperTickIndex, - } = params; - - const lowerSqrtPrice = PriceMath.tickIndexToSqrtPriceX64(lowerTickIndex); - const upperSqrtPrice = PriceMath.tickIndexToSqrtPriceX64(upperTickIndex); - - if (currentTickIndex >= upperTickIndex) { - return isInputTokenA - ? ZERO - : getLiquidityFromTokenB(inputTokenAmount, lowerSqrtPrice, upperSqrtPrice, false); - } - - if (currentTickIndex < lowerTickIndex) { - return isInputTokenA - ? getLiquidityFromTokenA(inputTokenAmount, lowerSqrtPrice, upperSqrtPrice, false) - : ZERO; - } - - return isInputTokenA - ? getLiquidityFromTokenA(inputTokenAmount, sqrtPrice, upperSqrtPrice, false) - : getLiquidityFromTokenB(inputTokenAmount, lowerSqrtPrice, sqrtPrice, false); -} diff --git a/sdk/tests/sdk/whirlpools/quote/increase-liquidity-quote-by-liq.test.ts b/sdk/tests/sdk/whirlpools/quote/increase-liquidity-quote-by-liq.test.ts deleted file mode 100644 index 5514cc1..0000000 --- a/sdk/tests/sdk/whirlpools/quote/increase-liquidity-quote-by-liq.test.ts +++ /dev/null @@ -1,327 +0,0 @@ -import { Percentage, ZERO } from "@orca-so/common-sdk"; -import assert from "assert"; -import BN from "bn.js"; -import { PriceMath, increaseLiquidityQuoteByLiquidityWithParams } from "../../../../src"; -import { - getTokenAFromLiquidity, - getTokenBFromLiquidity, -} from "../../../../src/utils/position-util"; - -const variations = [ - [0, Percentage.fromFraction(1, 1000), new BN(17733543)] as const, - [0, Percentage.fromFraction(1, 100), new BN(17733543)] as const, - [0, Percentage.fromFraction(5, 100), new BN(17733543)] as const, - [234653, Percentage.fromFraction(1, 1000), new BN(17733543)] as const, - [234653, Percentage.fromFraction(1, 100), new BN(17733543)] as const, - [234653, Percentage.fromFraction(5, 100), new BN(17733543)] as const, - [-234653, Percentage.fromFraction(1, 1000), new BN(17733543)] as const, - [-234653, Percentage.fromFraction(1, 100), new BN(17733543)] as const, - [-234653, Percentage.fromFraction(5, 100), new BN(17733543)] as const, -]; - -function getTestSlipageRange(currIndex: number, slippage: Percentage) { - const sqrtPrice = PriceMath.tickIndexToSqrtPriceX64(currIndex); - const { - lowerBound: [_sLowerSqrtPrice, sLowerIndex], - upperBound: [_sUpperSqrtPrice, sUpperIndex], - } = PriceMath.getSlippageBoundForSqrtPrice(sqrtPrice, slippage); - - return { - tickLowerIndex: sLowerIndex === sUpperIndex ? sLowerIndex - 1 : sLowerIndex, - tickUpperIndex: sUpperIndex, - tickCurrentIndex: currIndex, - }; -} - -// [---P---] = P is the current price & [] is the slippage boundary -// |-------| = Position Boundary -variations.forEach(([currentTickIndex, slippage, liquidity]) => { - describe("increaseLiquidityQuoteByLiquidity", () => { - it(`|[--------P--------]| @ tickCurrentIndex - ${currentTickIndex}, slippage - ${slippage.toDecimal()}%`, async () => { - const slippageRange = getTestSlipageRange(currentTickIndex, slippage); - testVariation({ - pTickLowerIndex: slippageRange.tickLowerIndex, - pTickUpperIndex: slippageRange.tickCurrentIndex, - tickCurrentIndex: slippageRange.tickCurrentIndex, - liquidity, - slippageTolerance: slippage, - }); - }); - - it(`|----------------| [---P---] @ tickCurrentIndex - ${currentTickIndex}, slippage - ${slippage.toDecimal()}%`, async () => { - const slippageRange = getTestSlipageRange(currentTickIndex, slippage); - testVariation({ - pTickLowerIndex: slippageRange.tickLowerIndex - 200, - pTickUpperIndex: slippageRange.tickLowerIndex - 100, - tickCurrentIndex: slippageRange.tickCurrentIndex, - liquidity, - slippageTolerance: slippage, - }); - }); - - it(`|--------------[--|--P----] @ tickCurrentIndex - ${currentTickIndex}, slippage - ${slippage.toDecimal()}%`, async () => { - const slippageRange = getTestSlipageRange(currentTickIndex, slippage); - testVariation({ - pTickLowerIndex: slippageRange.tickLowerIndex - 200, - pTickUpperIndex: slippageRange.tickLowerIndex + 5, - tickCurrentIndex: slippageRange.tickCurrentIndex, - liquidity, - slippageTolerance: slippage, - }); - }); - - it(`[|---|---P------] @ tickCurrentIndex - ${currentTickIndex}, slippage - ${slippage.toDecimal()}%`, async () => { - const slippageRange = getTestSlipageRange(currentTickIndex, slippage); - testVariation({ - pTickLowerIndex: slippageRange.tickLowerIndex, - pTickUpperIndex: slippageRange.tickCurrentIndex - 5, - tickCurrentIndex: slippageRange.tickCurrentIndex, - liquidity, - slippageTolerance: slippage, - }); - }); - - it(`[--|---|--P-------] @ tickCurrentIndex - ${currentTickIndex}, slippage - ${slippage.toDecimal()}%`, async () => { - const slippageRange = getTestSlipageRange(currentTickIndex, slippage); - testVariation({ - pTickLowerIndex: slippageRange.tickLowerIndex + 5, - pTickUpperIndex: slippageRange.tickCurrentIndex - 5, - tickCurrentIndex: slippageRange.tickCurrentIndex, - liquidity, - slippageTolerance: slippage, - }); - }); - - it(`|-----[---P---]-----| @ tickCurrentIndex - ${currentTickIndex}, slippage - ${slippage.toDecimal()}%`, async () => { - const slippageRange = getTestSlipageRange(currentTickIndex, slippage); - testVariation({ - pTickLowerIndex: slippageRange.tickLowerIndex - 200, - pTickUpperIndex: slippageRange.tickUpperIndex + 200, - tickCurrentIndex: slippageRange.tickCurrentIndex, - liquidity, - slippageTolerance: slippage, - }); - }); - - it(`[--|----P----]-----| @ tickCurrentIndex - ${currentTickIndex}, slippage - ${slippage.toDecimal()}%`, async () => { - const slippageRange = getTestSlipageRange(currentTickIndex, slippage); - testVariation({ - pTickLowerIndex: slippageRange.tickLowerIndex + 5, - pTickUpperIndex: slippageRange.tickUpperIndex + 5, - tickCurrentIndex: slippageRange.tickCurrentIndex, - liquidity, - slippageTolerance: slippage, - }); - }); - - it(`|--[---P---|-----] @ tickCurrentIndex - ${currentTickIndex}, slippage - ${slippage.toDecimal()}%`, async () => { - const slippageRange = getTestSlipageRange(currentTickIndex, slippage); - testVariation({ - pTickLowerIndex: slippageRange.tickLowerIndex - 125, - pTickUpperIndex: slippageRange.tickCurrentIndex + 5, - tickCurrentIndex: slippageRange.tickCurrentIndex, - liquidity, - slippageTolerance: slippage, - }); - }); - - it(`[---|---P---|----] @ tickCurrentIndex - ${currentTickIndex}, slippage - ${slippage.toDecimal()}%`, async () => { - const slippageRange = getTestSlipageRange(currentTickIndex, slippage); - testVariation({ - pTickLowerIndex: slippageRange.tickLowerIndex + 5, - pTickUpperIndex: slippageRange.tickCurrentIndex + 5, - tickCurrentIndex: slippageRange.tickCurrentIndex, - liquidity, - slippageTolerance: slippage, - }); - }); - - it(`[---P---] |---------| @ tickCurrentIndex - ${currentTickIndex}, slippage - ${slippage.toDecimal()}%`, async () => { - const slippageRange = getTestSlipageRange(currentTickIndex, slippage); - testVariation({ - pTickLowerIndex: slippageRange.tickUpperIndex + 100, - pTickUpperIndex: slippageRange.tickUpperIndex + 200, - tickCurrentIndex: slippageRange.tickCurrentIndex, - liquidity, - slippageTolerance: slippage, - }); - }); - - it(`[---P--|---]------| @ tickCurrentIndex - ${currentTickIndex}, slippage - ${slippage.toDecimal()}%`, async () => { - const slippageRange = getTestSlipageRange(currentTickIndex, slippage); - testVariation({ - pTickLowerIndex: slippageRange.tickCurrentIndex + 5, - pTickUpperIndex: slippageRange.tickUpperIndex + 100, - tickCurrentIndex: slippageRange.tickCurrentIndex, - liquidity, - slippageTolerance: slippage, - }); - }); - - it(`[-----P--|---|] @ tickCurrentIndex - ${currentTickIndex}, slippage - ${slippage.toDecimal()}%`, async () => { - const slippageRange = getTestSlipageRange(currentTickIndex, slippage); - testVariation({ - pTickLowerIndex: slippageRange.tickCurrentIndex + 5, - pTickUpperIndex: slippageRange.tickUpperIndex, - tickCurrentIndex: slippageRange.tickCurrentIndex, - liquidity, - slippageTolerance: slippage, - }); - }); - - it(`[-------P--|---|--] @ tickCurrentIndex - ${currentTickIndex}, slippage - ${slippage.toDecimal()}%`, async () => { - const slippageRange = getTestSlipageRange(currentTickIndex, slippage); - testVariation({ - pTickLowerIndex: slippageRange.tickCurrentIndex + 2, - pTickUpperIndex: slippageRange.tickUpperIndex - 2, - tickCurrentIndex: slippageRange.tickCurrentIndex, - liquidity, - slippageTolerance: slippage, - }); - }); - - async function testVariation(params: { - pTickLowerIndex: number; - pTickUpperIndex: number; - tickCurrentIndex: number; - liquidity: BN; - slippageTolerance: Percentage; - }) { - const { pTickLowerIndex, pTickUpperIndex, tickCurrentIndex, liquidity } = params; - - const sqrtPrice = PriceMath.tickIndexToSqrtPriceX64(tickCurrentIndex); - - const quote = increaseLiquidityQuoteByLiquidityWithParams({ - liquidity, - sqrtPrice, - tickLowerIndex: pTickLowerIndex, - tickUpperIndex: pTickUpperIndex, - tickCurrentIndex, - slippageTolerance: params.slippageTolerance, - }); - - const { - lowerBound: [sLowerSqrtPrice, sLowerIndex], - upperBound: [sUpperSqrtPrice, sUpperIndex], - } = PriceMath.getSlippageBoundForSqrtPrice(sqrtPrice, slippage); - - const upperTokenEstA = getTokenEstA({ - liquidity, - sqrtPrice: sUpperSqrtPrice, - currentTickIndex: sUpperIndex, - lowerTickIndex: pTickLowerIndex, - upperTickIndex: pTickUpperIndex, - }); - const upperTokenEstB = getTokenEstB({ - liquidity, - sqrtPrice: sUpperSqrtPrice, - currentTickIndex: sUpperIndex, - lowerTickIndex: pTickLowerIndex, - upperTickIndex: pTickUpperIndex, - }); - - const lowerTokenEstA = getTokenEstA({ - liquidity, - sqrtPrice: sLowerSqrtPrice, - currentTickIndex: sLowerIndex, - lowerTickIndex: pTickLowerIndex, - upperTickIndex: pTickUpperIndex, - }); - const lowerTokenEstB = getTokenEstB({ - liquidity, - sqrtPrice: sLowerSqrtPrice, - currentTickIndex: sLowerIndex, - lowerTickIndex: pTickLowerIndex, - upperTickIndex: pTickUpperIndex, - }); - - const expectedTokenMaxA = BN.max( - BN.max(quote.tokenEstA, upperTokenEstA), - lowerTokenEstA, - ); - const expectedTokenMaxB = BN.max( - BN.max(quote.tokenEstB, upperTokenEstB), - lowerTokenEstB, - ); - - // Generate expectations for TokenEstA and TokenEstB - const expectedTokenEstA = getTokenEstA({ - liquidity, - sqrtPrice, - currentTickIndex: tickCurrentIndex, - lowerTickIndex: pTickLowerIndex, - upperTickIndex: pTickUpperIndex, - }); - const expectedTokenEstB = getTokenEstB({ - liquidity, - sqrtPrice, - currentTickIndex: tickCurrentIndex, - lowerTickIndex: pTickLowerIndex, - upperTickIndex: pTickUpperIndex, - }); - - assert.ok( - quote.tokenEstA.eq(expectedTokenEstA), - `tokenEstA: ${quote.tokenEstA.toString()} !== ${expectedTokenEstA.toString()}`, - ); - assert.ok( - quote.tokenEstB.eq(expectedTokenEstB), - `tokenEstB: ${quote.tokenEstB.toString()} !== ${expectedTokenEstB.toString()}`, - ); - assert.ok( - quote.tokenMaxA.eq(expectedTokenMaxA), - `tokenMaxA: ${quote.tokenMaxA.toString()} !== ${expectedTokenMaxA.toString()}`, - ); - assert.ok( - quote.tokenMaxB.eq(expectedTokenMaxB), - `tokenMaxB: ${quote.tokenMaxB.toString()} !== ${expectedTokenMaxB.toString()}`, - ); - } - }); -}); - -function getTokenEstA(params: { - liquidity: BN; - sqrtPrice: BN; - currentTickIndex: number; - lowerTickIndex: number; - upperTickIndex: number; -}) { - const { liquidity, sqrtPrice, currentTickIndex, lowerTickIndex, upperTickIndex } = params; - - const lowerSqrtPrice = PriceMath.tickIndexToSqrtPriceX64(lowerTickIndex); - const upperSqrtPrice = PriceMath.tickIndexToSqrtPriceX64(upperTickIndex); - - if (currentTickIndex >= upperTickIndex) { - return ZERO; - } - - if (currentTickIndex < lowerTickIndex) { - return getTokenAFromLiquidity(liquidity, lowerSqrtPrice, upperSqrtPrice, true); - } - - return getTokenAFromLiquidity(liquidity, sqrtPrice, upperSqrtPrice, true); -} - -function getTokenEstB(params: { - liquidity: BN; - sqrtPrice: BN; - currentTickIndex: number; - lowerTickIndex: number; - upperTickIndex: number; -}) { - const { liquidity, sqrtPrice, currentTickIndex, lowerTickIndex, upperTickIndex } = params; - - const lowerSqrtPrice = PriceMath.tickIndexToSqrtPriceX64(lowerTickIndex); - const upperSqrtPrice = PriceMath.tickIndexToSqrtPriceX64(upperTickIndex); - - if (currentTickIndex < lowerTickIndex) { - return ZERO; - } - - if (currentTickIndex >= upperTickIndex) { - return getTokenBFromLiquidity(liquidity, lowerSqrtPrice, upperSqrtPrice, true); - } - - return getTokenBFromLiquidity(liquidity, lowerSqrtPrice, sqrtPrice, true); -} diff --git a/sdk/tests/sdk/whirlpools/swap/swap-array.test.ts b/sdk/tests/sdk/whirlpools/swap/swap-array.test.ts deleted file mode 100644 index f26d0c3..0000000 --- a/sdk/tests/sdk/whirlpools/swap/swap-array.test.ts +++ /dev/null @@ -1,841 +0,0 @@ -import * as anchor from "@coral-xyz/anchor"; -import { AddressUtil, Percentage, ZERO } from "@orca-so/common-sdk"; -import * as assert from "assert"; -import BN from "bn.js"; -import { - PriceMath, - SwapUtils, - TICK_ARRAY_SIZE, - WhirlpoolContext, - buildWhirlpoolClient, - swapQuoteByInputToken, - swapQuoteWithParams -} from "../../../../src"; -import { SwapErrorCode, WhirlpoolsError } from "../../../../src/errors/errors"; -import { IGNORE_CACHE } from "../../../../src/network/public/fetcher"; -import { adjustForSlippage } from "../../../../src/utils/position-util"; -import { TickSpacing } from "../../../utils"; -import { defaultConfirmOptions } from "../../../utils/const"; -import { - arrayTickIndexToTickIndex, - buildPosition, - setupSwapTest -} from "../../../utils/swap-test-utils"; -import { getTickArrays } from "../../../utils/testDataTypes"; - -describe("swap arrays test", () => { - const provider = anchor.AnchorProvider.local(undefined, defaultConfirmOptions); - - const program = anchor.workspace.Whirlpool; - const ctx = WhirlpoolContext.fromWorkspace(provider, program); - const fetcher = ctx.fetcher; - const client = buildWhirlpoolClient(ctx); - const tickSpacing = TickSpacing.SixtyFour; - const slippageTolerance = Percentage.fromFraction(0, 100); - - /** - * |--------------------|xxxxxxxxxxxxxxxxx|-c2---c1-----------| - */ - it("3 sequential arrays, 2nd array not initialized, use tickArray0 only, a->b", async () => { - const currIndex = arrayTickIndexToTickIndex({ arrayIndex: 1, offsetIndex: 44 }, tickSpacing); - const whirlpool = await setupSwapTest({ - ctx, - client, - tickSpacing, - initSqrtPrice: PriceMath.tickIndexToSqrtPriceX64(currIndex), - initArrayStartTicks: [-11264, -5632, 5632, 11264], - fundedPositions: [ - buildPosition( - // a - { arrayIndex: -2, offsetIndex: 44 }, - { arrayIndex: 2, offsetIndex: 44 }, - tickSpacing, - new BN(250_000_000) - ), - ], - }); - - const whirlpoolData = await whirlpool.refreshData(); - const tradeAmount = new BN(10000); - const quote = await swapQuoteByInputToken( - whirlpool, - whirlpoolData.tokenMintA, - tradeAmount, - slippageTolerance, - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - - // Verify with an actual swap. - // estimatedEndTickIndex is 8446 (arrayIndex: 1) - assert.equal(quote.aToB, true); - assert.equal(quote.amountSpecifiedIsInput, true); - assert.equal( - quote.sqrtPriceLimit.toString(), - SwapUtils.getDefaultSqrtPriceLimit(true).toString() - ); - assert.equal( - quote.otherAmountThreshold.toString(), - adjustForSlippage(quote.estimatedAmountOut, slippageTolerance, false).toString() - ); - assert.equal(quote.estimatedAmountIn.toString(), tradeAmount); - assert.doesNotThrow(async () => await (await whirlpool.swap(quote)).buildAndExecute()); - }); - - /** - * |--------------------|xxxxxxxxxxxxxc2xx|------c1-----------| - */ - it("3 sequential arrays, 2nd array not initialized, a->b", async () => { - const currIndex = arrayTickIndexToTickIndex({ arrayIndex: 1, offsetIndex: 44 }, tickSpacing); - const whirlpool = await setupSwapTest({ - ctx, - client, - tickSpacing, - initSqrtPrice: PriceMath.tickIndexToSqrtPriceX64(currIndex), - initArrayStartTicks: [-11264, -5632, 5632, 11264], - fundedPositions: [ - buildPosition( - // a - { arrayIndex: -2, offsetIndex: 44 }, - { arrayIndex: 2, offsetIndex: 44 }, - tickSpacing, - new BN(250_000_000) - ), - ], - }); - - // estimatedEndTickIndex is 4091 (arrayIndex: 0 (not initialized)) - const whirlpoolData = await whirlpool.refreshData(); - const expectedError = "Swap input value traversed too many arrays."; - await assert.rejects( - swapQuoteByInputToken( - whirlpool, - whirlpoolData.tokenMintA, - new BN(40_000_000), - slippageTolerance, - ctx.program.programId, - fetcher, - IGNORE_CACHE - ), - (err: Error) => err.message.indexOf(expectedError) != -1 - ); - }); - - /** - * |-------------c1--c2-|xxxxxxxxxxxxxxxxx|-------------------| - */ - it("3 sequential arrays, 2nd array not initialized, use tickArray0 only, b->a", async () => { - const currIndex = arrayTickIndexToTickIndex({ arrayIndex: -1, offsetIndex: 44 }, tickSpacing); - const whirlpool = await setupSwapTest({ - ctx, - client, - tickSpacing, - initSqrtPrice: PriceMath.tickIndexToSqrtPriceX64(currIndex), - initArrayStartTicks: [-11264, -5632, 5632, 11264], - fundedPositions: [ - buildPosition( - // a - { arrayIndex: -2, offsetIndex: 44 }, - { arrayIndex: 2, offsetIndex: 44 }, - tickSpacing, - new BN(250_000_000) - ), - ], - }); - - const whirlpoolData = await whirlpool.refreshData(); - const tradeAmount = new BN(10000); - const quote = await swapQuoteByInputToken( - whirlpool, - whirlpoolData.tokenMintB, - tradeAmount, - slippageTolerance, - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - - // Verify with an actual swap. - // estimatedEndTickIndex is -2816 (arrayIndex: -1) - assert.equal(quote.aToB, false); - assert.equal(quote.amountSpecifiedIsInput, true); - assert.equal( - quote.sqrtPriceLimit.toString(), - SwapUtils.getDefaultSqrtPriceLimit(false).toString() - ); - assert.equal( - quote.otherAmountThreshold.toString(), - adjustForSlippage(quote.estimatedAmountOut, slippageTolerance, false).toString() - ); - assert.equal(quote.estimatedAmountIn.toString(), tradeAmount); - assert.doesNotThrow(async () => await (await whirlpool.swap(quote)).buildAndExecute()); - }); - - /** - * |-------------c1-----|xxc2xxxxxxxxxxxxx|-------------------| - */ - it("3 sequential arrays, 2nd array not initialized, b->a", async () => { - const currIndex = arrayTickIndexToTickIndex({ arrayIndex: -1, offsetIndex: 44 }, tickSpacing); - const whirlpool = await setupSwapTest({ - ctx, - client, - tickSpacing, - initSqrtPrice: PriceMath.tickIndexToSqrtPriceX64(currIndex), - initArrayStartTicks: [-11264, -5632, 5632, 11264], - fundedPositions: [ - buildPosition( - // a - { arrayIndex: -2, offsetIndex: 44 }, - { arrayIndex: 2, offsetIndex: 44 }, - tickSpacing, - new BN(250_000_000) - ), - ], - }); - - // estimatedEndTickIndex is 556 (arrayIndex: 0 (not initialized)) - const whirlpoolData = await whirlpool.refreshData(); - const expectedError = "Swap input value traversed too many arrays."; - await assert.rejects( - swapQuoteByInputToken( - whirlpool, - whirlpoolData.tokenMintB, - new BN(40_000_000), - slippageTolerance, - ctx.program.programId, - fetcher, - IGNORE_CACHE - ), - (err: Error) => err.message.indexOf(expectedError) != -1 - ); - }); - - /** - * |xxxxxxxxxxxxxxxxxxxx|xxxxxxxxxxxxxxxxx|-c2---c1-----------| - */ - it("3 sequential arrays, 2nd array and 3rd array not initialized, use tickArray0 only, a->b", async () => { - const currIndex = arrayTickIndexToTickIndex({ arrayIndex: 1, offsetIndex: 44 }, tickSpacing); - const whirlpool = await setupSwapTest({ - ctx, - client, - tickSpacing, - initSqrtPrice: PriceMath.tickIndexToSqrtPriceX64(currIndex), - initArrayStartTicks: [-11264, 5632, 11264], - fundedPositions: [ - buildPosition( - // a - { arrayIndex: -2, offsetIndex: 44 }, - { arrayIndex: 2, offsetIndex: 44 }, - tickSpacing, - new BN(250_000_000) - ), - ], - }); - - const whirlpoolData = await whirlpool.refreshData(); - const tradeAmount = new BN(10000); - const quote = await swapQuoteByInputToken( - whirlpool, - whirlpoolData.tokenMintA, - tradeAmount, - slippageTolerance, - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - - // Verify with an actual swap. - // estimatedEndTickIndex is 8446 (arrayIndex: 1) - assert.equal(quote.aToB, true); - assert.equal(quote.amountSpecifiedIsInput, true); - assert.equal( - quote.sqrtPriceLimit.toString(), - SwapUtils.getDefaultSqrtPriceLimit(true).toString() - ); - assert.equal( - quote.otherAmountThreshold.toString(), - adjustForSlippage(quote.estimatedAmountOut, slippageTolerance, false).toString() - ); - assert.equal(quote.estimatedAmountIn.toString(), tradeAmount); - assert.doesNotThrow(async () => await (await whirlpool.swap(quote)).buildAndExecute()); - }); - - /** - * |-------------c1--c2-|xxxxxxxxxxxxxxxxx|xxxxxxxxxxxxxxxxxxx| - */ - it("3 sequential arrays, 2nd array and 3rd array not initialized, use tickArray0 only, b->a", async () => { - const currIndex = arrayTickIndexToTickIndex({ arrayIndex: -1, offsetIndex: 44 }, tickSpacing); - const whirlpool = await setupSwapTest({ - ctx, - client, - tickSpacing, - initSqrtPrice: PriceMath.tickIndexToSqrtPriceX64(currIndex), - initArrayStartTicks: [-11264, -5632, 11264], - fundedPositions: [ - buildPosition( - // a - { arrayIndex: -2, offsetIndex: 44 }, - { arrayIndex: 2, offsetIndex: 44 }, - tickSpacing, - new BN(250_000_000) - ), - ], - }); - - const whirlpoolData = await whirlpool.refreshData(); - const tradeAmount = new BN(10000); - const quote = await swapQuoteByInputToken( - whirlpool, - whirlpoolData.tokenMintB, - tradeAmount, - slippageTolerance, - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - - // Verify with an actual swap. - // estimatedEndTickIndex is -2816 (arrayIndex: -1) - assert.equal(quote.aToB, false); - assert.equal(quote.amountSpecifiedIsInput, true); - assert.equal( - quote.sqrtPriceLimit.toString(), - SwapUtils.getDefaultSqrtPriceLimit(false).toString() - ); - assert.equal( - quote.otherAmountThreshold.toString(), - adjustForSlippage(quote.estimatedAmountOut, slippageTolerance, false).toString() - ); - assert.equal(quote.estimatedAmountIn.toString(), tradeAmount); - assert.doesNotThrow(async () => await (await whirlpool.swap(quote)).buildAndExecute()); - }); - - /** - * c1|------------------|-----------------|-------------------| - */ - it("3 sequential arrays does not contain curr_tick_index, a->b", async () => { - const currIndex = arrayTickIndexToTickIndex({ arrayIndex: -2, offsetIndex: 44 }, tickSpacing); - const whirlpool = await setupSwapTest({ - ctx, - client, - tickSpacing, - initSqrtPrice: PriceMath.tickIndexToSqrtPriceX64(currIndex), - initArrayStartTicks: [-11264, -5632, 0, 5632, 11264], - fundedPositions: [ - buildPosition( - // a - { arrayIndex: -2, offsetIndex: 44 }, - { arrayIndex: 2, offsetIndex: 44 }, - tickSpacing, - new BN(250_000_000) - ), - ], - }); - - const whirlpoolData = await whirlpool.refreshData(); - const aToB = true; - const tickArrays = await SwapUtils.getTickArrays( - arrayTickIndexToTickIndex({ arrayIndex: 0, offsetIndex: 10 }, tickSpacing), - tickSpacing, - aToB, - ctx.program.programId, - whirlpool.getAddress(), - fetcher, - IGNORE_CACHE - ); - assert.throws( - () => - swapQuoteWithParams( - { - aToB, - amountSpecifiedIsInput: true, - tokenAmount: new BN("10000"), - whirlpoolData, - tickArrays, - sqrtPriceLimit: SwapUtils.getDefaultSqrtPriceLimit(aToB), - otherAmountThreshold: ZERO, - }, - slippageTolerance - ), - (err) => (err as WhirlpoolsError).errorCode === SwapErrorCode.TickArraySequenceInvalid - ); - }); - - /** - * |--------------------|-----------------|-------------------|c1 - */ - it("3 sequential arrays does not contain curr_tick_index, b->a", async () => { - const currIndex = arrayTickIndexToTickIndex({ arrayIndex: 2, offsetIndex: 44 }, tickSpacing); - const whirlpool = await setupSwapTest({ - ctx, - client, - tickSpacing, - initSqrtPrice: PriceMath.tickIndexToSqrtPriceX64(currIndex), - initArrayStartTicks: [-11264, -5632, 0, 5632, 11264], - fundedPositions: [ - buildPosition( - // a - { arrayIndex: -2, offsetIndex: 44 }, - { arrayIndex: 2, offsetIndex: 44 }, - tickSpacing, - new BN(250_000_000) - ), - ], - }); - - const whirlpoolData = await whirlpool.getData(); - const aToB = false; - const tickArrays = await SwapUtils.getTickArrays( - arrayTickIndexToTickIndex({ arrayIndex: 0, offsetIndex: 10 }, tickSpacing), - tickSpacing, - aToB, - ctx.program.programId, - whirlpool.getAddress(), - fetcher, - IGNORE_CACHE - ); - assert.throws( - () => - swapQuoteWithParams( - { - aToB, - amountSpecifiedIsInput: true, - tokenAmount: new BN("10000"), - whirlpoolData, - tickArrays, - sqrtPriceLimit: SwapUtils.getDefaultSqrtPriceLimit(aToB), - otherAmountThreshold: ZERO, - }, - slippageTolerance - ), - (err) => (err as WhirlpoolsError).errorCode === SwapErrorCode.TickArraySequenceInvalid - ); - }); - - /** - * |--------------------|------c1---------|-------------------| - */ - it("3 sequential arrays, 2nd array contains curr_tick_index, a->b", async () => { - const currIndex = arrayTickIndexToTickIndex({ arrayIndex: 0, offsetIndex: 44 }, tickSpacing); - const whirlpool = await setupSwapTest({ - ctx, - client, - tickSpacing, - initSqrtPrice: PriceMath.tickIndexToSqrtPriceX64(currIndex), - initArrayStartTicks: [-11264, -5632, 0, 5632, 11264], - fundedPositions: [ - buildPosition( - { arrayIndex: -2, offsetIndex: 44 }, - { arrayIndex: 2, offsetIndex: 44 }, - tickSpacing, - new BN(250_000_000) - ), - ], - }); - - const whirlpoolData = await whirlpool.refreshData(); - const aToB = true; - const tickArrays = await SwapUtils.getTickArrays( - arrayTickIndexToTickIndex({ arrayIndex: 1, offsetIndex: 10 }, tickSpacing), - tickSpacing, - aToB, - ctx.program.programId, - whirlpool.getAddress(), - fetcher, - IGNORE_CACHE - ); - assert.throws( - () => - swapQuoteWithParams( - { - aToB, - amountSpecifiedIsInput: true, - tokenAmount: new BN("10000"), - whirlpoolData, - tickArrays, - sqrtPriceLimit: SwapUtils.getDefaultSqrtPriceLimit(aToB), - otherAmountThreshold: ZERO, - }, - slippageTolerance - ), - (err) => (err as WhirlpoolsError).errorCode === SwapErrorCode.TickArraySequenceInvalid - ); - }); - - /** - * |--------------------|------c1---------|-------------------| - */ - it("3 sequential arrays, 2nd array contains curr_tick_index, b->a", async () => { - const currIndex = arrayTickIndexToTickIndex({ arrayIndex: 0, offsetIndex: 44 }, tickSpacing); - const whirlpool = await setupSwapTest({ - ctx, - client, - tickSpacing, - initSqrtPrice: PriceMath.tickIndexToSqrtPriceX64(currIndex), - initArrayStartTicks: [-11264, -5632, 0, 5632, 11264, 16896], - fundedPositions: [ - buildPosition( - { arrayIndex: -2, offsetIndex: 44 }, - { arrayIndex: 2, offsetIndex: 44 }, - tickSpacing, - new BN(250_000_000) - ), - ], - }); - - const whirlpoolData = await whirlpool.refreshData(); - const aToB = false; - const tickArrays = await SwapUtils.getTickArrays( - arrayTickIndexToTickIndex({ arrayIndex: 1, offsetIndex: 10 }, tickSpacing), - tickSpacing, - aToB, - ctx.program.programId, - whirlpool.getAddress(), - fetcher, - IGNORE_CACHE - ); - - assert.throws( - () => - swapQuoteWithParams( - { - aToB, - amountSpecifiedIsInput: true, - tokenAmount: new BN("10000"), - whirlpoolData, - tickArrays, - sqrtPriceLimit: SwapUtils.getDefaultSqrtPriceLimit(aToB), - otherAmountThreshold: ZERO, - }, - slippageTolerance - ), - (err) => (err as WhirlpoolsError).errorCode === SwapErrorCode.TickArraySequenceInvalid - ); - }); - - /** - * |---a-c2--(5632)-----|------(0)--------|---c1--(11264)--a-| - */ - it("on first array, 2nd array is not sequential, a->b", async () => { - const currIndex = arrayTickIndexToTickIndex({ arrayIndex: 2, offsetIndex: 44 }, tickSpacing); - const whirlpool = await setupSwapTest({ - ctx, - client, - tickSpacing, - initSqrtPrice: PriceMath.tickIndexToSqrtPriceX64(currIndex), - initArrayStartTicks: [-11264, -5632, 0, 5632, 11264], - fundedPositions: [ - buildPosition( - { arrayIndex: 1, offsetIndex: 10 }, - { arrayIndex: 2, offsetIndex: 44 }, - tickSpacing, - new BN(250_000_000) - ), - ], - }); - - const whirlpoolData = await whirlpool.refreshData(); - const aToB = true; - const tickArrays = await getTickArrays( - [11264, 0, 5632], - ctx, - AddressUtil.toPubKey(whirlpool.getAddress()), - fetcher - ); - assert.throws( - () => - swapQuoteWithParams( - { - aToB, - amountSpecifiedIsInput: true, - tokenAmount: new BN("10000"), - whirlpoolData, - tickArrays, - sqrtPriceLimit: SwapUtils.getDefaultSqrtPriceLimit(aToB), - otherAmountThreshold: ZERO, - }, - slippageTolerance - ), - (err) => { - const whirlErr = err as WhirlpoolsError; - const errorCodeMatch = whirlErr.errorCode === SwapErrorCode.TickArraySequenceInvalid; - const messageMatch = whirlErr.message.indexOf("TickArray at index 1 is unexpected") >= 0; - return errorCodeMatch && messageMatch; - } - ); - }); - - /** - * |-a--(-11264)---c1---|--------(0)------|----(-5632)---c2--a-| - */ - it("on first array, 2nd array is not sequential, b->a", async () => { - const currIndex = arrayTickIndexToTickIndex({ arrayIndex: -2, offsetIndex: 44 }, tickSpacing); - const whirlpool = await setupSwapTest({ - ctx, - client, - tickSpacing, - initSqrtPrice: PriceMath.tickIndexToSqrtPriceX64(currIndex), - initArrayStartTicks: [-11264, -5632, 0, 5632, 11264], - fundedPositions: [ - buildPosition( - { arrayIndex: -2, offsetIndex: 10 }, - { arrayIndex: -1, offsetIndex: TICK_ARRAY_SIZE - 2 }, - tickSpacing, - new BN(250_000_000) - ), - ], - }); - - const whirlpoolData = await whirlpool.refreshData(); - const aToB = false; - const tickArrays = await getTickArrays( - [-11264, 0, -5632], - ctx, - AddressUtil.toPubKey(whirlpool.getAddress()), - fetcher - ); - assert.throws( - () => - swapQuoteWithParams( - { - aToB, - amountSpecifiedIsInput: true, - tokenAmount: new BN("10000"), - whirlpoolData, - tickArrays, - sqrtPriceLimit: SwapUtils.getDefaultSqrtPriceLimit(aToB), - otherAmountThreshold: ZERO, - }, - slippageTolerance - ), - (err) => { - const whirlErr = err as WhirlpoolsError; - const errorCodeMatch = whirlErr.errorCode === SwapErrorCode.TickArraySequenceInvalid; - const messageMatch = whirlErr.message.indexOf("TickArray at index 1 is unexpected") >= 0; - return errorCodeMatch && messageMatch; - } - ); - }); - - /** - * |-------(5632)------|-------(5632)------|---c2--(5632)-c1---| - */ - it("3 identical arrays, 1st contains curr_tick_index, a->b", async () => { - const currIndex = arrayTickIndexToTickIndex( - { arrayIndex: 1, offsetIndex: TICK_ARRAY_SIZE - 4 }, - tickSpacing - ); - const whirlpool = await setupSwapTest({ - ctx, - client, - tickSpacing, - initSqrtPrice: PriceMath.tickIndexToSqrtPriceX64(currIndex), - initArrayStartTicks: [5632], - fundedPositions: [ - buildPosition( - { arrayIndex: 1, offsetIndex: 0 }, - { arrayIndex: 1, offsetIndex: TICK_ARRAY_SIZE - 1 }, - tickSpacing, - new BN(250_000) - ), - ], - }); - - const whirlpoolData = await whirlpool.refreshData(); - const aToB = true; - const tickArrays = await getTickArrays( - [5632, 5632, 5632], - ctx, - AddressUtil.toPubKey(whirlpool.getAddress()), - fetcher - ); - const tradeAmount = new BN("33588"); - const quote = swapQuoteWithParams( - { - aToB, - amountSpecifiedIsInput: true, - tokenAmount: tradeAmount, - whirlpoolData, - tickArrays, - sqrtPriceLimit: SwapUtils.getDefaultSqrtPriceLimit(aToB), - otherAmountThreshold: ZERO, - }, - slippageTolerance - ); - - // Verify with an actual swap. - assert.equal(quote.aToB, aToB); - assert.equal(quote.amountSpecifiedIsInput, true); - assert.equal( - quote.sqrtPriceLimit.toString(), - SwapUtils.getDefaultSqrtPriceLimit(aToB).toString() - ); - assert.equal( - quote.otherAmountThreshold.toString(), - adjustForSlippage(quote.estimatedAmountOut, slippageTolerance, false).toString() - ); - assert.equal(quote.estimatedAmountIn.toString(), tradeAmount); - assert.doesNotThrow(async () => await (await whirlpool.swap(quote)).buildAndExecute()); - }); - - /** - * |---c1--(5632)-c2---|-------(5632)------|-------(5632)------| - */ - it("3 identical arrays, 1st contains curr_tick_index, b->a", async () => { - const currIndex = arrayTickIndexToTickIndex({ arrayIndex: 1, offsetIndex: 4 }, tickSpacing); - const whirlpool = await setupSwapTest({ - ctx, - client, - tickSpacing, - initSqrtPrice: PriceMath.tickIndexToSqrtPriceX64(currIndex), - initArrayStartTicks: [5632], - fundedPositions: [ - buildPosition( - { arrayIndex: 1, offsetIndex: 0 }, - { arrayIndex: 1, offsetIndex: TICK_ARRAY_SIZE - 1 }, - tickSpacing, - new BN(250_000) - ), - ], - }); - - const whirlpoolData = await whirlpool.refreshData(); - const aToB = false; - const tickArrays = await getTickArrays( - [5632, 5632, 5632], - ctx, - AddressUtil.toPubKey(whirlpool.getAddress()), - fetcher - ); - const tradeAmount = new BN("33588"); - const quote = swapQuoteWithParams( - { - aToB, - amountSpecifiedIsInput: true, - tokenAmount: tradeAmount, - whirlpoolData, - tickArrays, - sqrtPriceLimit: SwapUtils.getDefaultSqrtPriceLimit(aToB), - otherAmountThreshold: ZERO, - }, - slippageTolerance - ); - - // Verify with an actual swap. - assert.equal(quote.aToB, aToB); - assert.equal(quote.amountSpecifiedIsInput, true); - assert.equal( - quote.sqrtPriceLimit.toString(), - SwapUtils.getDefaultSqrtPriceLimit(aToB).toString() - ); - assert.equal( - quote.otherAmountThreshold.toString(), - adjustForSlippage(quote.estimatedAmountOut, slippageTolerance, false).toString() - ); - assert.equal(quote.estimatedAmountIn.toString(), tradeAmount); - assert.doesNotThrow(async () => await (await whirlpool.swap(quote)).buildAndExecute()); - }); - - /** - * |xxxxxxxxxxxxxxxxxxxx|xxxxxxxxxxxxxxxxx|-c2---c1-----------| - */ - it("Whirlpool.swap with uninitialized TickArrays, a->b", async () => { - const currIndex = arrayTickIndexToTickIndex({ arrayIndex: 1, offsetIndex: 44 }, tickSpacing); - const whirlpool = await setupSwapTest({ - ctx, - client, - tickSpacing, - initSqrtPrice: PriceMath.tickIndexToSqrtPriceX64(currIndex), - initArrayStartTicks: [-11264, 5632, 11264], - fundedPositions: [ - buildPosition( - // a - { arrayIndex: -2, offsetIndex: 44 }, - { arrayIndex: 2, offsetIndex: 44 }, - tickSpacing, - new BN(250_000_000) - ), - ], - }); - - const whirlpoolData = await whirlpool.refreshData(); - const tradeAmount = new BN(10000); - const aToB = true; - const tickArrays = SwapUtils.getTickArrayPublicKeys( - whirlpoolData.tickCurrentIndex, - whirlpoolData.tickSpacing, - aToB, - ctx.program.programId, - whirlpool.getAddress() - ); - - await assert.rejects( - whirlpool.swap({ - amount: tradeAmount, - amountSpecifiedIsInput: true, - aToB, - otherAmountThreshold: SwapUtils.getDefaultOtherAmountThreshold(true), - sqrtPriceLimit: SwapUtils.getDefaultSqrtPriceLimit(aToB), - tickArray0: tickArrays[0], - tickArray1: tickArrays[1], - tickArray2: tickArrays[2], - }), - (err: Error) => { - const uninitializedArrays = [tickArrays[1].toBase58(), tickArrays[2].toBase58()].join(", "); - return err.message.indexOf(`TickArray addresses - [${uninitializedArrays}] need to be initialized.`) >= 0; - } - ); - }); - - /** - * |-------------c1--c2-|xxxxxxxxxxxxxxxxx|xxxxxxxxxxxxxxxxxxx| - */ - it("Whirlpool.swap with uninitialized TickArrays, b->a", async () => { - const currIndex = arrayTickIndexToTickIndex({ arrayIndex: -1, offsetIndex: 44 }, tickSpacing); - const whirlpool = await setupSwapTest({ - ctx, - client, - tickSpacing, - initSqrtPrice: PriceMath.tickIndexToSqrtPriceX64(currIndex), - initArrayStartTicks: [-11264, -5632, 11264], - fundedPositions: [ - buildPosition( - // a - { arrayIndex: -2, offsetIndex: 44 }, - { arrayIndex: 2, offsetIndex: 44 }, - tickSpacing, - new BN(250_000_000) - ), - ], - }); - - const whirlpoolData = await whirlpool.refreshData(); - const tradeAmount = new BN(10000); - const aToB = false; - const tickArrays = SwapUtils.getTickArrayPublicKeys( - whirlpoolData.tickCurrentIndex, - whirlpoolData.tickSpacing, - aToB, - ctx.program.programId, - whirlpool.getAddress() - ); - - await assert.rejects( - whirlpool.swap({ - amount: tradeAmount, - amountSpecifiedIsInput: true, - aToB, - otherAmountThreshold: SwapUtils.getDefaultOtherAmountThreshold(true), - sqrtPriceLimit: SwapUtils.getDefaultSqrtPriceLimit(aToB), - tickArray0: tickArrays[0], - tickArray1: tickArrays[1], - tickArray2: tickArrays[2], - }), - (err: Error) => { - const uninitializedArrays = [tickArrays[1].toBase58(), tickArrays[2].toBase58()].join(", "); - return err.message.indexOf(`TickArray addresses - [${uninitializedArrays}] need to be initialized.`) >= 0; - } - ); - }); -}); diff --git a/sdk/tests/sdk/whirlpools/swap/swap-dev-fee.test.ts b/sdk/tests/sdk/whirlpools/swap/swap-dev-fee.test.ts deleted file mode 100644 index 3564351..0000000 --- a/sdk/tests/sdk/whirlpools/swap/swap-dev-fee.test.ts +++ /dev/null @@ -1,485 +0,0 @@ -import * as anchor from "@coral-xyz/anchor"; -import { Address } from "@coral-xyz/anchor"; -import { Percentage } from "@orca-so/common-sdk"; -import { Keypair } from "@solana/web3.js"; -import * as assert from "assert"; -import BN from "bn.js"; -import { - buildWhirlpoolClient, PriceMath, - swapQuoteByInputToken, - Whirlpool, - WhirlpoolContext -} from "../../../../src"; -import { SwapErrorCode, WhirlpoolsError } from "../../../../src/errors/errors"; -import { IGNORE_CACHE } from "../../../../src/network/public/fetcher"; -import { swapQuoteByInputTokenWithDevFees } from "../../../../src/quotes/public/dev-fee-swap-quote"; -import { - assertDevFeeQuotes, - assertDevTokenAmount, - assertQuoteAndResults, - TickSpacing -} from "../../../utils"; -import { defaultConfirmOptions } from "../../../utils/const"; -import { - arrayTickIndexToTickIndex, - buildPosition, - setupSwapTest -} from "../../../utils/swap-test-utils"; -import { getVaultAmounts } from "../../../utils/whirlpools-test-utils"; - -describe("whirlpool-dev-fee-swap", () => { - const provider = anchor.AnchorProvider.local(undefined, defaultConfirmOptions); - - const program = anchor.workspace.Whirlpool; - const ctx = WhirlpoolContext.fromWorkspace(provider, program); - const client = buildWhirlpoolClient(ctx); - const tickSpacing = TickSpacing.SixtyFour; - const slippageTolerance = Percentage.fromFraction(0, 100); - - it("swap with dev-fee 0% equals swap", async () => { - const currIndex = arrayTickIndexToTickIndex({ arrayIndex: -1, offsetIndex: 22 }, tickSpacing); - const devWallet = Keypair.generate(); - const aToB = false; - const whirlpool = await setupSwapTest({ - ctx, - client, - tickSpacing, - initSqrtPrice: PriceMath.tickIndexToSqrtPriceX64(currIndex), - initArrayStartTicks: [-5632, 0, 5632], - fundedPositions: [ - buildPosition( - // a - { arrayIndex: -1, offsetIndex: 10 }, - { arrayIndex: 1, offsetIndex: 23 }, - tickSpacing, - new anchor.BN(250_000_000) - ), - ], - }); - - const devFeePercentage = Percentage.fromFraction(0, 1000); // 0% - const inputTokenAmount = new BN(119500000); - const postFeeTokenAmount = inputTokenAmount.sub( - inputTokenAmount.mul(devFeePercentage.numerator).div(devFeePercentage.denominator) - ); - const whirlpoolData = await whirlpool.refreshData(); - const beforeVaultAmounts = await getVaultAmounts(ctx, whirlpoolData); - const inputTokenQuote = await swapQuoteByInputToken( - whirlpool, - whirlpoolData.tokenMintB, - inputTokenAmount, - slippageTolerance, - ctx.program.programId, - ctx.fetcher, - IGNORE_CACHE - ); - const postFeeInputTokenQuote = await swapQuoteByInputToken( - whirlpool, - whirlpoolData.tokenMintB, - postFeeTokenAmount, - slippageTolerance, - ctx.program.programId, - ctx.fetcher, - IGNORE_CACHE - ); - const inputTokenQuoteWithDevFees = await swapQuoteByInputTokenWithDevFees( - whirlpool, - whirlpoolData.tokenMintB, - inputTokenAmount, - slippageTolerance, - ctx.program.programId, - ctx.fetcher, - devFeePercentage, - IGNORE_CACHE - ); - assertDevFeeQuotes(inputTokenQuote, postFeeInputTokenQuote, inputTokenQuoteWithDevFees); - await ( - await whirlpool.swapWithDevFees(inputTokenQuoteWithDevFees, devWallet.publicKey) - ).buildAndExecute(); - - const newData = await whirlpool.refreshData(); - const afterVaultAmounts = await getVaultAmounts(ctx, whirlpoolData); - assertQuoteAndResults(aToB, inputTokenQuote, newData, beforeVaultAmounts, afterVaultAmounts); - }); - - it("swap with dev-fee 0.1%", async () => { - const currIndex = arrayTickIndexToTickIndex({ arrayIndex: -1, offsetIndex: 22 }, tickSpacing); - const devWallet = Keypair.generate(); - const aToB = false; - const whirlpool = await setupSwapTest({ - ctx, - client, - tickSpacing, - initSqrtPrice: PriceMath.tickIndexToSqrtPriceX64(currIndex), - initArrayStartTicks: [-5632, 0, 5632], - fundedPositions: [ - buildPosition( - // a - { arrayIndex: -1, offsetIndex: 10 }, - { arrayIndex: 1, offsetIndex: 23 }, - tickSpacing, - new anchor.BN(250_000_000) - ), - ], - }); - - const devFeePercentage = Percentage.fromFraction(1, 1000); // 0.1% - const inputTokenAmount = new BN(1195000); - const postFeeTokenAmount = inputTokenAmount.sub( - inputTokenAmount.mul(devFeePercentage.numerator).div(devFeePercentage.denominator) - ); - - const whirlpoolData = await whirlpool.refreshData(); - const swapToken = aToB ? whirlpoolData.tokenMintA : whirlpoolData.tokenMintB; - const beforeVaultAmounts = await getVaultAmounts(ctx, whirlpoolData); - - const { inputTokenQuote, postFeeInputTokenQuote, inputTokenQuoteWithDevFees } = await getQuotes( - ctx, - whirlpool, - swapToken, - inputTokenAmount, - postFeeTokenAmount, - slippageTolerance, - devFeePercentage - ); - assertDevFeeQuotes(inputTokenQuote, postFeeInputTokenQuote, inputTokenQuoteWithDevFees); - await ( - await whirlpool.swapWithDevFees(inputTokenQuoteWithDevFees, devWallet.publicKey) - ).buildAndExecute(); - - const newData = await whirlpool.refreshData(); - const afterVaultAmounts = await getVaultAmounts(ctx, whirlpoolData); - assertQuoteAndResults( - aToB, - postFeeInputTokenQuote, - newData, - beforeVaultAmounts, - afterVaultAmounts - ); - await assertDevTokenAmount(ctx, inputTokenQuoteWithDevFees, swapToken, devWallet.publicKey); - }); - - it("swap with dev-fee 1%", async () => { - const currIndex = arrayTickIndexToTickIndex({ arrayIndex: 1, offsetIndex: 22 }, tickSpacing); - const devWallet = Keypair.generate(); - const aToB = true; - const whirlpool = await setupSwapTest({ - ctx, - client, - tickSpacing, - initSqrtPrice: PriceMath.tickIndexToSqrtPriceX64(currIndex), - initArrayStartTicks: [-5632, 0, 5632], - fundedPositions: [ - buildPosition( - // a - { arrayIndex: -1, offsetIndex: 10 }, - { arrayIndex: 1, offsetIndex: 23 }, - tickSpacing, - new anchor.BN(250_000_000) - ), - ], - }); - - const devFeePercentage = Percentage.fromFraction(1, 100); // 1% - const inputTokenAmount = new BN(119500000); - const postFeeTokenAmount = inputTokenAmount.sub( - inputTokenAmount.mul(devFeePercentage.numerator).div(devFeePercentage.denominator) - ); - - const whirlpoolData = await whirlpool.refreshData(); - const swapToken = aToB ? whirlpoolData.tokenMintA : whirlpoolData.tokenMintB; - const beforeVaultAmounts = await getVaultAmounts(ctx, whirlpoolData); - const { inputTokenQuote, postFeeInputTokenQuote, inputTokenQuoteWithDevFees } = await getQuotes( - ctx, - whirlpool, - swapToken, - inputTokenAmount, - postFeeTokenAmount, - slippageTolerance, - devFeePercentage - ); - assertDevFeeQuotes(inputTokenQuote, postFeeInputTokenQuote, inputTokenQuoteWithDevFees); - await ( - await whirlpool.swapWithDevFees(inputTokenQuoteWithDevFees, devWallet.publicKey) - ).buildAndExecute(); - - const newData = await whirlpool.refreshData(); - const afterVaultAmounts = await getVaultAmounts(ctx, whirlpoolData); - assertQuoteAndResults( - aToB, - postFeeInputTokenQuote, - newData, - beforeVaultAmounts, - afterVaultAmounts - ); - await assertDevTokenAmount(ctx, inputTokenQuoteWithDevFees, swapToken, devWallet.publicKey); - }); - - it("swap with input-token as NATIVE_MINT & dev-fee 1%", async () => { - const currIndex = arrayTickIndexToTickIndex({ arrayIndex: 1, offsetIndex: 1 }, tickSpacing); - const aToB = true; - const tokenAIsNative = true; - const whirlpool = await setupSwapTest({ - ctx, - client, - tickSpacing, - initSqrtPrice: PriceMath.tickIndexToSqrtPriceX64(currIndex), - initArrayStartTicks: [-16896, -11264, -5632, 0, 5632], - fundedPositions: [ - buildPosition( - // a - { arrayIndex: -1, offsetIndex: 10 }, - { arrayIndex: 1, offsetIndex: 23 }, - tickSpacing, - new anchor.BN(990_000_000) - ), - buildPosition( - // a - { arrayIndex: -1, offsetIndex: 10 }, - { arrayIndex: 0, offsetIndex: 23 }, - tickSpacing, - new anchor.BN(990_000_000) - ), - buildPosition( - // a - { arrayIndex: 0, offsetIndex: 22 }, - { arrayIndex: 1, offsetIndex: 23 }, - tickSpacing, - new anchor.BN(1_990_000_000) - ), - buildPosition( - // a - { arrayIndex: 0, offsetIndex: 23 }, - { arrayIndex: 1, offsetIndex: 23 }, - tickSpacing, - new anchor.BN(990_000_000) - ), - ], - }, tokenAIsNative); - - const { devWallet, balance: preDevWalletBalance } = await setupDevWallet(ctx, 10_000_000) - - const devFeePercentage = Percentage.fromFraction(1, 10000); // 0.01% - const inputTokenAmount = new BN(1_000_000_000); // Swap 1SOL - const postFeeTokenAmount = inputTokenAmount.sub( - inputTokenAmount.mul(devFeePercentage.numerator).div(devFeePercentage.denominator) - ); - - const whirlpoolData = await whirlpool.refreshData(); - const swapToken = aToB ? whirlpoolData.tokenMintA : whirlpoolData.tokenMintB; - const beforeVaultAmounts = await getVaultAmounts(ctx, whirlpoolData); - - const { inputTokenQuote, postFeeInputTokenQuote, inputTokenQuoteWithDevFees } = await getQuotes( - ctx, - whirlpool, - swapToken, - inputTokenAmount, - postFeeTokenAmount, - slippageTolerance, - devFeePercentage - ); - - assertDevFeeQuotes(inputTokenQuote, postFeeInputTokenQuote, inputTokenQuoteWithDevFees); - await ( - await whirlpool.swapWithDevFees(inputTokenQuoteWithDevFees, devWallet.publicKey) - ).buildAndExecute(); - - const newData = await whirlpool.refreshData(); - const afterVaultAmounts = await getVaultAmounts(ctx, whirlpoolData); - assertQuoteAndResults( - aToB, - postFeeInputTokenQuote, - newData, - beforeVaultAmounts, - afterVaultAmounts - ); - await assertDevTokenAmount(ctx, inputTokenQuoteWithDevFees, swapToken, devWallet.publicKey, preDevWalletBalance); - }); - - it("swap with dev-fee 50%", async () => { - const currIndex = arrayTickIndexToTickIndex({ arrayIndex: -1, offsetIndex: 22 }, tickSpacing); - const devWallet = Keypair.generate(); - const aToB = false; - const whirlpool = await setupSwapTest({ - ctx, - client, - tickSpacing, - initSqrtPrice: PriceMath.tickIndexToSqrtPriceX64(currIndex), - initArrayStartTicks: [-5632, 0, 5632], - fundedPositions: [ - buildPosition( - // a - { arrayIndex: -1, offsetIndex: 10 }, - { arrayIndex: 1, offsetIndex: 23 }, - tickSpacing, - new anchor.BN(250_000_000) - ), - ], - }); - - const devFeePercentage = Percentage.fromFraction(500000, 1000000); // 50% - const inputTokenAmount = new BN(119500000); - const postFeeTokenAmount = inputTokenAmount.sub( - inputTokenAmount.mul(devFeePercentage.numerator).div(devFeePercentage.denominator) - ); - - const whirlpoolData = await whirlpool.refreshData(); - const swapToken = aToB ? whirlpoolData.tokenMintA : whirlpoolData.tokenMintB; - const beforeVaultAmounts = await getVaultAmounts(ctx, whirlpoolData); - const { inputTokenQuote, postFeeInputTokenQuote, inputTokenQuoteWithDevFees } = await getQuotes( - ctx, - whirlpool, - swapToken, - inputTokenAmount, - postFeeTokenAmount, - slippageTolerance, - devFeePercentage - ); - assertDevFeeQuotes(inputTokenQuote, postFeeInputTokenQuote, inputTokenQuoteWithDevFees); - await ( - await whirlpool.swapWithDevFees(inputTokenQuoteWithDevFees, devWallet.publicKey) - ).buildAndExecute(); - - const newData = await whirlpool.refreshData(); - const afterVaultAmounts = await getVaultAmounts(ctx, whirlpoolData); - assertQuoteAndResults( - aToB, - postFeeInputTokenQuote, - newData, - beforeVaultAmounts, - afterVaultAmounts - ); - await assertDevTokenAmount(ctx, inputTokenQuoteWithDevFees, swapToken, devWallet.publicKey); - }); - - it("swap with dev-fee of 100%", async () => { - const currIndex = arrayTickIndexToTickIndex({ arrayIndex: -1, offsetIndex: 22 }, tickSpacing); - const whirlpool = await setupSwapTest({ - ctx, - client, - tickSpacing, - initSqrtPrice: PriceMath.tickIndexToSqrtPriceX64(currIndex), - initArrayStartTicks: [-5632, 0, 5632], - fundedPositions: [ - buildPosition( - // a - { arrayIndex: -1, offsetIndex: 10 }, - { arrayIndex: 1, offsetIndex: 23 }, - tickSpacing, - new anchor.BN(250_000_000) - ), - ], - }); - - const devFeePercentage = Percentage.fromFraction(100, 100); // 100% - const inputTokenAmount = new BN(119500000); - const whirlpoolData = await whirlpool.refreshData(); - const swapToken = whirlpoolData.tokenMintB; - - assert.rejects( - () => - swapQuoteByInputTokenWithDevFees( - whirlpool, - swapToken, - inputTokenAmount, - slippageTolerance, - ctx.program.programId, - ctx.fetcher, - devFeePercentage, - IGNORE_CACHE - ), - (err) => (err as WhirlpoolsError).errorCode === SwapErrorCode.InvalidDevFeePercentage - ); - }); - - it("swap with dev-fee of 200%", async () => { - const currIndex = arrayTickIndexToTickIndex({ arrayIndex: -1, offsetIndex: 22 }, tickSpacing); - const whirlpool = await setupSwapTest({ - ctx, - client, - tickSpacing, - initSqrtPrice: PriceMath.tickIndexToSqrtPriceX64(currIndex), - initArrayStartTicks: [-5632, 0, 5632], - fundedPositions: [ - buildPosition( - // a - { arrayIndex: -1, offsetIndex: 10 }, - { arrayIndex: 1, offsetIndex: 23 }, - tickSpacing, - new anchor.BN(250_000_000) - ), - ], - }); - - const devFeePercentage = Percentage.fromFraction(200, 100); // 200% - const inputTokenAmount = new BN(119500000); - const whirlpoolData = await whirlpool.refreshData(); - const swapToken = whirlpoolData.tokenMintB; - - assert.rejects( - () => - swapQuoteByInputTokenWithDevFees( - whirlpool, - swapToken, - inputTokenAmount, - slippageTolerance, - ctx.program.programId, - ctx.fetcher, - devFeePercentage, - IGNORE_CACHE - ), - (err) => (err as WhirlpoolsError).errorCode === SwapErrorCode.InvalidDevFeePercentage - ); - }); -}); - -async function getQuotes( - ctx: WhirlpoolContext, - whirlpool: Whirlpool, - swapToken: Address, - inputTokenAmount: BN, - postFeeTokenAmount: BN, - slippageTolerance: Percentage, - devFeePercentage: Percentage -) { - const inputTokenQuote = await swapQuoteByInputToken( - whirlpool, - swapToken, - inputTokenAmount, - slippageTolerance, - ctx.program.programId, - ctx.fetcher, - IGNORE_CACHE - ); - const postFeeInputTokenQuote = await swapQuoteByInputToken( - whirlpool, - swapToken, - postFeeTokenAmount, - slippageTolerance, - ctx.program.programId, - ctx.fetcher, - IGNORE_CACHE - ); - const inputTokenQuoteWithDevFees = await swapQuoteByInputTokenWithDevFees( - whirlpool, - swapToken, - inputTokenAmount, - slippageTolerance, - ctx.program.programId, - ctx.fetcher, - devFeePercentage, - IGNORE_CACHE - ); - - return { inputTokenQuote, postFeeInputTokenQuote, inputTokenQuoteWithDevFees }; -} - -async function setupDevWallet(ctx: WhirlpoolContext, airdrop: number) { - // Setup dev-wallet. Airdrop some tokens in or it'll be difficult to account for - // rent-tokens when we do assertion - const devWallet = Keypair.generate(); - const txn = await ctx.provider.connection.requestAirdrop(devWallet.publicKey, airdrop); - await ctx.provider.connection.confirmTransaction(txn); - const balance = await ctx.provider.connection.getBalance(devWallet.publicKey); - return { devWallet, balance } -} diff --git a/sdk/tests/sdk/whirlpools/swap/swap-traverse.test.ts b/sdk/tests/sdk/whirlpools/swap/swap-traverse.test.ts deleted file mode 100644 index e46e2ad..0000000 --- a/sdk/tests/sdk/whirlpools/swap/swap-traverse.test.ts +++ /dev/null @@ -1,1436 +0,0 @@ -import * as anchor from "@coral-xyz/anchor"; -import { Percentage } from "@orca-so/common-sdk"; -import * as assert from "assert"; -import { BN } from "bn.js"; -import { - buildWhirlpoolClient, MAX_SQRT_PRICE, MAX_TICK_INDEX, MIN_SQRT_PRICE, MIN_TICK_INDEX, PriceMath, - swapQuoteByInputToken, - swapQuoteByOutputToken, - swapQuoteWithParams, SwapUtils, TICK_ARRAY_SIZE, - WhirlpoolContext -} from "../../../../src"; -import { SwapErrorCode, WhirlpoolsError } from "../../../../src/errors/errors"; -import { IGNORE_CACHE } from "../../../../src/network/public/fetcher"; -import { assertInputOutputQuoteEqual, assertQuoteAndResults, TickSpacing } from "../../../utils"; -import { defaultConfirmOptions } from "../../../utils/const"; -import { - arrayTickIndexToTickIndex, - buildPosition, - setupSwapTest -} from "../../../utils/swap-test-utils"; -import { getVaultAmounts } from "../../../utils/whirlpools-test-utils"; - -describe("swap traversal tests", () => { - const provider = anchor.AnchorProvider.local(undefined, defaultConfirmOptions); - - const program = anchor.workspace.Whirlpool; - const ctx = WhirlpoolContext.fromWorkspace(provider, program); - const fetcher = ctx.fetcher; - const client = buildWhirlpoolClient(ctx); - const tickSpacing = TickSpacing.SixtyFour; - const slippageTolerance = Percentage.fromFraction(0, 100); - - /** - * |--------------------|b-----x2----a-------b-|x1-a------------------| - */ - it("curr_index on the last initializable tick, a->b", async () => { - const currIndex = arrayTickIndexToTickIndex({ arrayIndex: 0, offsetIndex: 15 }, tickSpacing); - const aToB = true; - const whirlpool = await setupSwapTest({ - ctx, - client, - tickSpacing, - initSqrtPrice: PriceMath.tickIndexToSqrtPriceX64(currIndex), - initArrayStartTicks: [-11264, -5632, 0], - fundedPositions: [ - buildPosition( - // a - { arrayIndex: -1, offsetIndex: 44 }, - { arrayIndex: 0, offsetIndex: 30 }, - tickSpacing, - new BN(250_000) - ), - buildPosition( - //b - { arrayIndex: -1, offsetIndex: 0 }, - { arrayIndex: -1, offsetIndex: TICK_ARRAY_SIZE - 1 }, - tickSpacing, - new BN(350_000) - ), - ], - }); - - const whirlpoolData = await whirlpool.refreshData(); - const beforeVaultAmounts = await getVaultAmounts(ctx, whirlpoolData); - const inputTokenQuote = await swapQuoteByInputToken( - whirlpool, - whirlpoolData.tokenMintA, - new BN(150000), - slippageTolerance, - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - - const outputTokenQuote = await swapQuoteByOutputToken( - whirlpool, - whirlpoolData.tokenMintB, - inputTokenQuote.estimatedAmountOut, - slippageTolerance, - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - assertInputOutputQuoteEqual(inputTokenQuote, outputTokenQuote); - - await (await whirlpool.swap(inputTokenQuote)).buildAndExecute(); - - const newData = await whirlpool.refreshData(); - const afterVaultAmounts = await getVaultAmounts(ctx, whirlpoolData); - assertQuoteAndResults(aToB, inputTokenQuote, newData, beforeVaultAmounts, afterVaultAmounts); - }); - - /** - * |--------------------x1,a|-b--------a----x2---b-|-------------------| - */ - it("curr_index on the last initializable tick, b->a", async () => { - const currIndex = arrayTickIndexToTickIndex( - { arrayIndex: 0, offsetIndex: TICK_ARRAY_SIZE - 1 }, - tickSpacing - ); - const aToB = false; - const whirlpool = await setupSwapTest({ - ctx, - client, - tickSpacing, - initSqrtPrice: PriceMath.tickIndexToSqrtPriceX64(currIndex), - initArrayStartTicks: [0, 5632, 11264], - fundedPositions: [ - buildPosition( - // a - { arrayIndex: 0, offsetIndex: TICK_ARRAY_SIZE - 1 }, - { arrayIndex: 1, offsetIndex: 44 }, - tickSpacing, - new BN(250_000_000) - ), - buildPosition( - //b - { arrayIndex: 1, offsetIndex: 0 }, - { arrayIndex: 1, offsetIndex: TICK_ARRAY_SIZE - 1 }, - tickSpacing, - new BN(350_000_000) - ), - ], - }); - - const whirlpoolData = await whirlpool.refreshData(); - const beforeVaultAmounts = await getVaultAmounts(ctx, whirlpoolData); - const inputTokenQuote = await swapQuoteByInputToken( - whirlpool, - whirlpoolData.tokenMintB, - new BN(190000000), - slippageTolerance, - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - const outputTokenQuote = await swapQuoteByOutputToken( - whirlpool, - whirlpoolData.tokenMintA, - inputTokenQuote.estimatedAmountOut, - slippageTolerance, - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - assertInputOutputQuoteEqual(inputTokenQuote, outputTokenQuote); - - await (await whirlpool.swap(inputTokenQuote)).buildAndExecute(); - - const newData = await whirlpool.refreshData(); - const afterVaultAmounts = await getVaultAmounts(ctx, whirlpoolData); - assertQuoteAndResults(aToB, inputTokenQuote, newData, beforeVaultAmounts, afterVaultAmounts); - }); - - /** - * b|-----x2---------|a---------------|a,x1-------------b| - */ - it("curr_index on the first initializable tick, a->b", async () => { - const currIndex = arrayTickIndexToTickIndex({ arrayIndex: 1, offsetIndex: 0 }, tickSpacing); - const aToB = true; - const whirlpool = await setupSwapTest({ - ctx, - client, - tickSpacing, - initSqrtPrice: PriceMath.tickIndexToSqrtPriceX64(currIndex), - initArrayStartTicks: [-11264, -5632, 0, 5632, 11264], - fundedPositions: [ - buildPosition( - // a - { arrayIndex: 0, offsetIndex: 0 }, - { arrayIndex: 1, offsetIndex: 0 }, - tickSpacing, - new BN(250_000_000) - ), - buildPosition( - //b - { arrayIndex: -2, offsetIndex: 44 }, - { arrayIndex: 2, offsetIndex: TICK_ARRAY_SIZE - 1 }, - tickSpacing, - new BN(350_000_000) - ), - ], - }); - - const whirlpoolData = await whirlpool.refreshData(); - const beforeVaultAmounts = await getVaultAmounts(ctx, whirlpoolData); - const inputTokenQuote = await swapQuoteByInputToken( - whirlpool, - whirlpoolData.tokenMintA, - new BN(200000000), - slippageTolerance, - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - const outputTokenQuote = await swapQuoteByOutputToken( - whirlpool, - whirlpoolData.tokenMintB, - inputTokenQuote.estimatedAmountOut, - slippageTolerance, - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - assertInputOutputQuoteEqual(inputTokenQuote, outputTokenQuote); - await (await whirlpool.swap(inputTokenQuote)).buildAndExecute(); - - const newData = await whirlpool.refreshData(); - const afterVaultAmounts = await getVaultAmounts(ctx, whirlpoolData); - assertQuoteAndResults(aToB, inputTokenQuote, newData, beforeVaultAmounts, afterVaultAmounts); - }); - - /** - * b|a,x1--------------|a---------------|---------x2--------b| - */ - it("curr_index on the first initializable tick, b->a", async () => { - const currIndex = arrayTickIndexToTickIndex({ arrayIndex: 0, offsetIndex: 0 }, tickSpacing); - const aToB = false; - const whirlpool = await setupSwapTest({ - ctx, - client, - tickSpacing, - initSqrtPrice: PriceMath.tickIndexToSqrtPriceX64(currIndex), - initArrayStartTicks: [-5632, 0, 5632, 11264], - fundedPositions: [ - buildPosition( - // a - { arrayIndex: 0, offsetIndex: 0 }, - { arrayIndex: 1, offsetIndex: 0 }, - tickSpacing, - new BN(250_000_000) - ), - buildPosition( - //b - { arrayIndex: -1, offsetIndex: 44 }, - { arrayIndex: 2, offsetIndex: TICK_ARRAY_SIZE - 1 }, - tickSpacing, - new BN(350_000_000) - ), - ], - }); - - const whirlpoolData = await whirlpool.refreshData(); - const beforeVaultAmounts = await getVaultAmounts(ctx, whirlpoolData); - const inputTokenQuote = await swapQuoteByInputToken( - whirlpool, - whirlpoolData.tokenMintB, - new BN(450000000), - slippageTolerance, - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - const outputTokenQuote = await swapQuoteByOutputToken( - whirlpool, - whirlpoolData.tokenMintA, - inputTokenQuote.estimatedAmountOut, - slippageTolerance, - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - assertInputOutputQuoteEqual(inputTokenQuote, outputTokenQuote); - await (await whirlpool.swap(inputTokenQuote)).buildAndExecute(); - - const newData = await whirlpool.refreshData(); - const afterVaultAmounts = await getVaultAmounts(ctx, whirlpoolData); - assertQuoteAndResults(aToB, inputTokenQuote, newData, beforeVaultAmounts, afterVaultAmounts); - }); - - /** - * |--------b-----x1-a|------a---x2---b--|-------------------| - */ - it("curr_index on the 2nd last initialized tick, with the next tick initialized, b->a", async () => { - const currIndex = arrayTickIndexToTickIndex( - { arrayIndex: 0, offsetIndex: TICK_ARRAY_SIZE - 2 }, // 5504 - tickSpacing - ); - const aToB = false; - const whirlpool = await setupSwapTest({ - ctx, - client, - tickSpacing, - initSqrtPrice: PriceMath.tickIndexToSqrtPriceX64(currIndex), - initArrayStartTicks: [-5632, 0, 5632, 11264], - fundedPositions: [ - buildPosition( - // a - { arrayIndex: 0, offsetIndex: TICK_ARRAY_SIZE - 1 }, - { arrayIndex: 1, offsetIndex: 44 }, - tickSpacing, - new BN(250_000_000) - ), - buildPosition( - //b - { arrayIndex: 0, offsetIndex: 44 }, - { arrayIndex: 1, offsetIndex: TICK_ARRAY_SIZE - 4 }, - tickSpacing, - new BN(350_000_000) - ), - ], - }); - - const whirlpoolData = await whirlpool.refreshData(); - const beforeVaultAmounts = await getVaultAmounts(ctx, whirlpoolData); - const inputTokenQuote = await swapQuoteByInputToken( - whirlpool, - whirlpoolData.tokenMintB, - new BN(150000000), - slippageTolerance, - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - const outputTokenQuote = await swapQuoteByOutputToken( - whirlpool, - whirlpoolData.tokenMintA, - inputTokenQuote.estimatedAmountOut, - slippageTolerance, - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - assertInputOutputQuoteEqual(inputTokenQuote, outputTokenQuote); - await (await whirlpool.swap(inputTokenQuote)).buildAndExecute(); - - const newData = await whirlpool.refreshData(); - const afterVaultAmounts = await getVaultAmounts(ctx, whirlpoolData); - assertQuoteAndResults(aToB, inputTokenQuote, newData, beforeVaultAmounts, afterVaultAmounts); - }); - - /** - * |-----------b--x2--|-------a-----b-----|a-x1-------------| - */ - it("curr_index on the 2nd initialized tick, with the first tick initialized, a->b", async () => { - const currIndex = arrayTickIndexToTickIndex({ arrayIndex: 2, offsetIndex: 1 }, tickSpacing); - const aToB = true; - const whirlpool = await setupSwapTest({ - ctx, - client, - tickSpacing, - initSqrtPrice: PriceMath.tickIndexToSqrtPriceX64(currIndex), - initArrayStartTicks: [0, 5632, 11264], - fundedPositions: [ - buildPosition( - // a - { arrayIndex: 1, offsetIndex: 44 }, - { arrayIndex: 2, offsetIndex: 0 }, - tickSpacing, - new BN(250_000_000) - ), - buildPosition( - //b - { arrayIndex: 0, offsetIndex: 44 }, - { arrayIndex: 1, offsetIndex: 64 }, - tickSpacing, - new BN(350_000_000) - ), - ], - }); - - const whirlpoolData = await whirlpool.refreshData(); - const beforeVaultAmounts = await getVaultAmounts(ctx, whirlpoolData); - const inputTokenQuote = await swapQuoteByInputToken( - whirlpool, - whirlpoolData.tokenMintA, - new BN(75000000), - slippageTolerance, - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - const outputTokenQuote = await swapQuoteByOutputToken( - whirlpool, - whirlpoolData.tokenMintB, - inputTokenQuote.estimatedAmountOut, - slippageTolerance, - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - assertInputOutputQuoteEqual(inputTokenQuote, outputTokenQuote); - await (await whirlpool.swap(inputTokenQuote)).buildAndExecute(); - - const newData = await whirlpool.refreshData(); - const afterVaultAmounts = await getVaultAmounts(ctx, whirlpoolData); - assertQuoteAndResults(aToB, inputTokenQuote, newData, beforeVaultAmounts, afterVaultAmounts); - }); - - /** - * |--------b-----a-x1|a---------x2---b--|-------------------| - */ - it("curr_index btw end of last offset and next array, with the next tick initialized, b->a", async () => { - const currIndex = 5629; - const aToB = false; - const whirlpool = await setupSwapTest({ - ctx, - client, - tickSpacing, - initSqrtPrice: PriceMath.tickIndexToSqrtPriceX64(currIndex), - initArrayStartTicks: [-5632, 0, 5632, 11264], - fundedPositions: [ - buildPosition( - // a - { arrayIndex: 0, offsetIndex: TICK_ARRAY_SIZE - 1 }, - { arrayIndex: 1, offsetIndex: 1 }, - tickSpacing, - new BN(250_000_000) - ), - buildPosition( - //b - { arrayIndex: 0, offsetIndex: 44 }, - { arrayIndex: 1, offsetIndex: TICK_ARRAY_SIZE - 4 }, - tickSpacing, - new BN(350_000_000) - ), - ], - }); - - const whirlpoolData = await whirlpool.refreshData(); - const beforeVaultAmounts = await getVaultAmounts(ctx, whirlpoolData); - const inputTokenQuote = await swapQuoteByInputToken( - whirlpool, - whirlpoolData.tokenMintB, - new BN(15000000), - slippageTolerance, - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - const outputTokenQuote = await swapQuoteByOutputToken( - whirlpool, - whirlpoolData.tokenMintA, - inputTokenQuote.estimatedAmountOut, - slippageTolerance, - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - assertInputOutputQuoteEqual(inputTokenQuote, outputTokenQuote); - await (await whirlpool.swap(inputTokenQuote)).buildAndExecute(); - - const newData = await whirlpool.refreshData(); - const afterVaultAmounts = await getVaultAmounts(ctx, whirlpoolData); - assertQuoteAndResults(aToB, inputTokenQuote, newData, beforeVaultAmounts, afterVaultAmounts); - }); - - /** - * |-----------b--x2--|-------a-----b-----|x1,a-------------| - */ - it("curr_index btw end of last offset and next array, with the next tick initialized, a->b", async () => { - const currIndex = 11264 + 30; - const aToB = true; - const whirlpool = await setupSwapTest({ - ctx, - client, - tickSpacing, - initSqrtPrice: PriceMath.tickIndexToSqrtPriceX64(currIndex), - initArrayStartTicks: [0, 5632, 11264], - fundedPositions: [ - buildPosition( - // a - { arrayIndex: 1, offsetIndex: 44 }, - { arrayIndex: 2, offsetIndex: 0 }, - tickSpacing, - new BN(250_000_000) - ), - buildPosition( - //b - { arrayIndex: 0, offsetIndex: 44 }, - { arrayIndex: 1, offsetIndex: 64 }, - tickSpacing, - new BN(350_000_000) - ), - ], - }); - - const whirlpoolData = await whirlpool.refreshData(); - const beforeVaultAmounts = await getVaultAmounts(ctx, whirlpoolData); - const inputTokenQuote = await swapQuoteByInputToken( - whirlpool, - whirlpoolData.tokenMintA, - new BN(7500000), - slippageTolerance, - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - const outputTokenQuote = await swapQuoteByOutputToken( - whirlpool, - whirlpoolData.tokenMintB, - inputTokenQuote.estimatedAmountOut, - slippageTolerance, - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - assertInputOutputQuoteEqual(inputTokenQuote, outputTokenQuote); - await (await whirlpool.swap(inputTokenQuote)).buildAndExecute(); - - const newData = await whirlpool.refreshData(); - const afterVaultAmounts = await getVaultAmounts(ctx, whirlpoolData); - assertQuoteAndResults(aToB, inputTokenQuote, newData, beforeVaultAmounts, afterVaultAmounts); - }); - - /** - * |----------------|-----a----x2-----b|--------x1----a---b----| - */ - it("on some tick, traverse to the 1st initialized tick in the next tick-array, a->b", async () => { - const currIndex = arrayTickIndexToTickIndex({ arrayIndex: 2, offsetIndex: 22 }, tickSpacing); - const aToB = true; - const whirlpool = await setupSwapTest({ - ctx, - client, - tickSpacing, - initSqrtPrice: PriceMath.tickIndexToSqrtPriceX64(currIndex), - initArrayStartTicks: [0, 5632, 11264], - fundedPositions: [ - buildPosition( - // a - { arrayIndex: 1, offsetIndex: 44 }, - { arrayIndex: 2, offsetIndex: 44 }, - tickSpacing, - new BN(250_000_000) - ), - buildPosition( - //b - { arrayIndex: 1, offsetIndex: TICK_ARRAY_SIZE - 1 }, - { arrayIndex: 2, offsetIndex: 64 }, - tickSpacing, - new BN(350_000_000) - ), - ], - }); - - const whirlpoolData = await whirlpool.refreshData(); - const beforeVaultAmounts = await getVaultAmounts(ctx, whirlpoolData); - const inputTokenQuote = await swapQuoteByInputToken( - whirlpool, - whirlpoolData.tokenMintA, - new BN(45000000), - slippageTolerance, - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - const outputTokenQuote = await swapQuoteByOutputToken( - whirlpool, - whirlpoolData.tokenMintB, - inputTokenQuote.estimatedAmountOut, - slippageTolerance, - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - assertInputOutputQuoteEqual(inputTokenQuote, outputTokenQuote); - await (await whirlpool.swap(inputTokenQuote)).buildAndExecute(); - - const newData = await whirlpool.refreshData(); - const afterVaultAmounts = await getVaultAmounts(ctx, whirlpoolData); - assertQuoteAndResults(aToB, inputTokenQuote, newData, beforeVaultAmounts, afterVaultAmounts); - }); - - /** - * |----a--b---x1------|a---x2-----b-------|------------------| - */ - it("on some tick, traverse to the 1st initialized tick in the next tick-array, b->a", async () => { - const currIndex = arrayTickIndexToTickIndex({ arrayIndex: -1, offsetIndex: 64 }, tickSpacing); - const aToB = false; - const whirlpool = await setupSwapTest({ - ctx, - client, - tickSpacing, - initSqrtPrice: PriceMath.tickIndexToSqrtPriceX64(currIndex), - initArrayStartTicks: [-5632, 0, 5632], - fundedPositions: [ - buildPosition( - // a - { arrayIndex: -1, offsetIndex: 10 }, - { arrayIndex: 0, offsetIndex: 0 }, - tickSpacing, - new BN(250_000_000) - ), - buildPosition( - //b - { arrayIndex: -1, offsetIndex: 22 }, - { arrayIndex: 0, offsetIndex: 64 }, - tickSpacing, - new BN(350_000_000) - ), - ], - }); - - const whirlpoolData = await whirlpool.refreshData(); - const beforeVaultAmounts = await getVaultAmounts(ctx, whirlpoolData); - const inputTokenQuote = await swapQuoteByInputToken( - whirlpool, - whirlpoolData.tokenMintB, - new BN(49500000), - slippageTolerance, - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - const outputTokenQuote = await swapQuoteByOutputToken( - whirlpool, - whirlpoolData.tokenMintA, - inputTokenQuote.estimatedAmountOut, - slippageTolerance, - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - assertInputOutputQuoteEqual(inputTokenQuote, outputTokenQuote); - await (await whirlpool.swap(inputTokenQuote)).buildAndExecute(); - - const newData = await whirlpool.refreshData(); - const afterVaultAmounts = await getVaultAmounts(ctx, whirlpoolData); - assertQuoteAndResults(aToB, inputTokenQuote, newData, beforeVaultAmounts, afterVaultAmounts); - }); - - /** - * |-------a----x2------|-----------------|----x1-----a-------| - */ - it("on some tick, traverse to the next tick in the n+2 tick-array, a->b", async () => { - const currIndex = arrayTickIndexToTickIndex({ arrayIndex: 1, offsetIndex: 22 }, tickSpacing); - const aToB = true; - const whirlpool = await setupSwapTest({ - ctx, - client, - tickSpacing, - initSqrtPrice: PriceMath.tickIndexToSqrtPriceX64(currIndex), - initArrayStartTicks: [-5632, 0, 5632], - fundedPositions: [ - buildPosition( - // a - { arrayIndex: -1, offsetIndex: 10 }, - { arrayIndex: 1, offsetIndex: 23 }, - tickSpacing, - new BN(250_000_000) - ), - ], - }); - - const whirlpoolData = await whirlpool.refreshData(); - const beforeVaultAmounts = await getVaultAmounts(ctx, whirlpoolData); - const inputTokenQuote = await swapQuoteByInputToken( - whirlpool, - whirlpoolData.tokenMintA, - new BN(119500000), - slippageTolerance, - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - const outputTokenQuote = await swapQuoteByOutputToken( - whirlpool, - whirlpoolData.tokenMintB, - inputTokenQuote.estimatedAmountOut, - slippageTolerance, - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - assertInputOutputQuoteEqual(inputTokenQuote, outputTokenQuote); - await (await whirlpool.swap(inputTokenQuote)).buildAndExecute(); - - const newData = await whirlpool.refreshData(); - const afterVaultAmounts = await getVaultAmounts(ctx, whirlpoolData); - assertQuoteAndResults(aToB, inputTokenQuote, newData, beforeVaultAmounts, afterVaultAmounts); - }); - - /** - * |-------a------x1----|-----------------|-----x2--------a---| - */ - it("on some tick, traverse to the next tick in the n+2 tick-array, b->a", async () => { - const currIndex = arrayTickIndexToTickIndex({ arrayIndex: -1, offsetIndex: 22 }, tickSpacing); - const aToB = false; - const whirlpool = await setupSwapTest({ - ctx, - client, - tickSpacing, - initSqrtPrice: PriceMath.tickIndexToSqrtPriceX64(currIndex), - initArrayStartTicks: [-5632, 0, 5632], - fundedPositions: [ - buildPosition( - // a - { arrayIndex: -1, offsetIndex: 10 }, - { arrayIndex: 1, offsetIndex: 23 }, - tickSpacing, - new BN(250_000_000) - ), - ], - }); - - const whirlpoolData = await whirlpool.refreshData(); - const beforeVaultAmounts = await getVaultAmounts(ctx, whirlpoolData); - const inputTokenQuote = await swapQuoteByInputToken( - whirlpool, - whirlpoolData.tokenMintB, - new BN(119500000), - slippageTolerance, - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - const outputTokenQuote = await swapQuoteByOutputToken( - whirlpool, - whirlpoolData.tokenMintA, - inputTokenQuote.estimatedAmountOut, - slippageTolerance, - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - assertInputOutputQuoteEqual(inputTokenQuote, outputTokenQuote); - await (await whirlpool.swap(inputTokenQuote)).buildAndExecute(); - - const newData = await whirlpool.refreshData(); - const afterVaultAmounts = await getVaultAmounts(ctx, whirlpoolData); - assertQuoteAndResults(aToB, inputTokenQuote, newData, beforeVaultAmounts, afterVaultAmounts); - }); - - /** - * a|----------------|-----------------|-------x1--------|a - */ - it("3 arrays, on some initialized tick, no other initialized tick in the sequence, a->b", async () => { - const currIndex = arrayTickIndexToTickIndex({ arrayIndex: 1, offsetIndex: 22 }, tickSpacing); - const aToB = true; - const whirlpool = await setupSwapTest({ - ctx, - client, - tickSpacing, - initSqrtPrice: PriceMath.tickIndexToSqrtPriceX64(currIndex), - initArrayStartTicks: [-11264, -5632, 0, 5632, 11264], - fundedPositions: [ - buildPosition( - // a - { arrayIndex: -2, offsetIndex: 10 }, - { arrayIndex: 2, offsetIndex: 23 }, - tickSpacing, - new BN(250_000_000) - ), - ], - }); - - const whirlpoolData = await whirlpool.refreshData(); - const beforeVaultAmounts = await getVaultAmounts(ctx, whirlpoolData); - const inputTokenQuote = await swapQuoteByInputToken( - whirlpool, - whirlpoolData.tokenMintA, - new BN(119500000), - slippageTolerance, - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - const outputTokenQuote = await swapQuoteByOutputToken( - whirlpool, - whirlpoolData.tokenMintB, - inputTokenQuote.estimatedAmountOut, - slippageTolerance, - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - assertInputOutputQuoteEqual(inputTokenQuote, outputTokenQuote); - await (await whirlpool.swap(inputTokenQuote)).buildAndExecute(); - - const newData = await whirlpool.refreshData(); - const afterVaultAmounts = await getVaultAmounts(ctx, whirlpoolData); - assertQuoteAndResults(aToB, inputTokenQuote, newData, beforeVaultAmounts, afterVaultAmounts); - }); - - /** - * |-----x1-------------|-----------------|-------------------| - */ - it("3 arrays, on some initialized tick, no other initialized tick in the sequence, b->a", async () => { - const currIndex = arrayTickIndexToTickIndex({ arrayIndex: -1, offsetIndex: 22 }, tickSpacing); - const aToB = false; - const whirlpool = await setupSwapTest({ - ctx, - client, - tickSpacing, - initSqrtPrice: PriceMath.tickIndexToSqrtPriceX64(currIndex), - initArrayStartTicks: [-11264, -5632, 0, 5632, 11264], - fundedPositions: [ - buildPosition( - // a - { arrayIndex: -2, offsetIndex: 10 }, - { arrayIndex: 2, offsetIndex: 23 }, - tickSpacing, - new BN(250_000_000) - ), - ], - }); - - const whirlpoolData = await whirlpool.refreshData(); - const beforeVaultAmounts = await getVaultAmounts(ctx, whirlpoolData); - const inputTokenQuote = await swapQuoteByInputToken( - whirlpool, - whirlpoolData.tokenMintB, - new BN(159500000), - slippageTolerance, - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - const outputTokenQuote = await swapQuoteByOutputToken( - whirlpool, - whirlpoolData.tokenMintA, - inputTokenQuote.estimatedAmountOut, - slippageTolerance, - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - assertInputOutputQuoteEqual(inputTokenQuote, outputTokenQuote); - await (await whirlpool.swap(inputTokenQuote)).buildAndExecute(); - - const newData = await whirlpool.refreshData(); - const afterVaultAmounts = await getVaultAmounts(ctx, whirlpoolData); - assertQuoteAndResults(aToB, inputTokenQuote, newData, beforeVaultAmounts, afterVaultAmounts); - }); - - /** - * [1, 0, -1] - * e|---c--x2----a---d----b|f-----a--b----d----|f-----c---x1-------|e - */ - it("3 arrays, on some uninitialized tick, traverse lots of ticks, a->b", async () => { - const currIndex = - arrayTickIndexToTickIndex({ arrayIndex: 1, offsetIndex: 25 }, tickSpacing) - 30; - const aToB = true; - const whirlpool = await setupSwapTest({ - ctx, - client, - tickSpacing, - initSqrtPrice: PriceMath.tickIndexToSqrtPriceX64(currIndex), - initArrayStartTicks: [-11264, -5632, 0, 5632, 11264], - fundedPositions: [ - buildPosition( - // e - { arrayIndex: -2, offsetIndex: 10 }, - { arrayIndex: 2, offsetIndex: 23 }, - tickSpacing, - new BN(250_000) - ), - buildPosition( - // c - { arrayIndex: -1, offsetIndex: 10 }, - { arrayIndex: 1, offsetIndex: 15 }, - tickSpacing, - new BN(100_000_000) - ), - buildPosition( - // a - { arrayIndex: -1, offsetIndex: 30 }, - { arrayIndex: 0, offsetIndex: 20 }, - tickSpacing, - new BN(100_000_000) - ), - buildPosition( - // d - { arrayIndex: -1, offsetIndex: 60 }, - { arrayIndex: 0, offsetIndex: 60 }, - tickSpacing, - new BN(50_000_000) - ), - buildPosition( - // f - { arrayIndex: 0, offsetIndex: 0 }, - { arrayIndex: 1, offsetIndex: 0 }, - tickSpacing, - new BN(25_000_000) - ), - ], - }); - - const whirlpoolData = await whirlpool.refreshData(); - const beforeVaultAmounts = await getVaultAmounts(ctx, whirlpoolData); - const inputTokenQuote = await swapQuoteByInputToken( - whirlpool, - whirlpoolData.tokenMintA, - new BN(102195000), - slippageTolerance, - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - const outputTokenQuote = await swapQuoteByOutputToken( - whirlpool, - whirlpoolData.tokenMintB, - inputTokenQuote.estimatedAmountOut, - slippageTolerance, - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - assertInputOutputQuoteEqual(inputTokenQuote, outputTokenQuote); - await (await whirlpool.swap(inputTokenQuote)).buildAndExecute(); - - const newData = await whirlpool.refreshData(); - const afterVaultAmounts = await getVaultAmounts(ctx, whirlpoolData); - assertQuoteAndResults(aToB, inputTokenQuote, newData, beforeVaultAmounts, afterVaultAmounts); - }); - - /** - * e|---c--x1----a---d--b---|f-----a--b----d----|f------c---x2--------|e - */ - it("3 arrays, on some uninitialized tick, traverse lots of ticks, b->a", async () => { - const currIndex = - arrayTickIndexToTickIndex({ arrayIndex: -1, offsetIndex: 15 }, tickSpacing) - 30; - const aToB = false; - const whirlpool = await setupSwapTest({ - ctx, - client, - tickSpacing, - initSqrtPrice: PriceMath.tickIndexToSqrtPriceX64(currIndex), - initArrayStartTicks: [-11264, -5632, 0, 5632, 11264], - fundedPositions: [ - buildPosition( - // e - { arrayIndex: -2, offsetIndex: 10 }, - { arrayIndex: 2, offsetIndex: 23 }, - tickSpacing, - new BN(250_000) - ), - buildPosition( - // c - { arrayIndex: -1, offsetIndex: 10 }, - { arrayIndex: 1, offsetIndex: 15 }, - tickSpacing, - new BN(100_000_000) - ), - buildPosition( - // a - { arrayIndex: -1, offsetIndex: 30 }, - { arrayIndex: 0, offsetIndex: 20 }, - tickSpacing, - new BN(100_000_000) - ), - buildPosition( - // d - { arrayIndex: -1, offsetIndex: 60 }, - { arrayIndex: 0, offsetIndex: 60 }, - tickSpacing, - new BN(50_000_000) - ), - buildPosition( - // f - { arrayIndex: 0, offsetIndex: 0 }, - { arrayIndex: 1, offsetIndex: 0 }, - tickSpacing, - new BN(25_000_000) - ), - ], - }); - - const whirlpoolData = await whirlpool.refreshData(); - const beforeVaultAmounts = await getVaultAmounts(ctx, whirlpoolData); - const inputTokenQuote = await swapQuoteByInputToken( - whirlpool, - whirlpoolData.tokenMintB, - new BN(99900000), - slippageTolerance, - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - const outputTokenQuote = await swapQuoteByOutputToken( - whirlpool, - whirlpoolData.tokenMintA, - inputTokenQuote.estimatedAmountOut, - slippageTolerance, - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - assertInputOutputQuoteEqual(inputTokenQuote, outputTokenQuote); - await (await whirlpool.swap(inputTokenQuote)).buildAndExecute(); - - const newData = await whirlpool.refreshData(); - const afterVaultAmounts = await getVaultAmounts(ctx, whirlpoolData); - assertQuoteAndResults(aToB, inputTokenQuote, newData, beforeVaultAmounts, afterVaultAmounts); - }); - - /** - * trade amount > liquidity - * |----------x1----------|-----------------|-------------------| - */ - it("3 arrays, trade amount exceeds liquidity available in array sequence, b->a", async () => { - const currIndex = arrayTickIndexToTickIndex({ arrayIndex: -1, offsetIndex: 22 }, tickSpacing); - const whirlpool = await setupSwapTest({ - ctx, - client, - tickSpacing, - initSqrtPrice: PriceMath.tickIndexToSqrtPriceX64(currIndex), - initArrayStartTicks: [-11264, -5632, 0, 5632, 11264], - fundedPositions: [ - buildPosition( - // a - { arrayIndex: -2, offsetIndex: 10 }, - { arrayIndex: 2, offsetIndex: 23 }, - tickSpacing, - new BN(250_000_000) - ), - ], - }); - - const whirlpoolData = await whirlpool.refreshData(); - await assert.rejects( - async () => - await swapQuoteByInputToken( - whirlpool, - whirlpoolData.tokenMintB, - new BN(9159500000), - slippageTolerance, - ctx.program.programId, - fetcher, - IGNORE_CACHE - ), - (err) => { - const whirlErr = err as WhirlpoolsError; - const errorMatch = whirlErr.errorCode === SwapErrorCode.TickArraySequenceInvalid; - // Message contains failure on finding beyond tickIndex - const messageMatch = whirlErr.message.indexOf("11264") >= 0; - assert.ok(messageMatch, "Error Message must match condition."); - assert.ok(errorMatch, "Error Code must match condition."); - return true; - } - ); - }); - - /** - * trade amount > liquidity - * |--------------------|-----------------|---------x1----------| - */ - it("3 arrays, trade amount exceeds liquidity available in array sequence, a->b", async () => { - const currIndex = arrayTickIndexToTickIndex({ arrayIndex: 1, offsetIndex: 22 }, tickSpacing); - const whirlpool = await setupSwapTest({ - ctx, - client, - tickSpacing, - initSqrtPrice: PriceMath.tickIndexToSqrtPriceX64(currIndex), - initArrayStartTicks: [-11264, -5632, 0, 5632, 11264], - fundedPositions: [ - buildPosition( - // a - { arrayIndex: -2, offsetIndex: 10 }, - { arrayIndex: 2, offsetIndex: 23 }, - tickSpacing, - new BN(250_000_000) - ), - ], - }); - - const whirlpoolData = await whirlpool.refreshData(); - await assert.rejects( - async () => - await swapQuoteByInputToken( - whirlpool, - whirlpoolData.tokenMintA, - new BN(9159500000), - slippageTolerance, - ctx.program.programId, - fetcher, - IGNORE_CACHE - ), - (err) => { - const whirlErr = err as WhirlpoolsError; - const errorMatch = whirlErr.errorCode === SwapErrorCode.TickArraySequenceInvalid; - // Message contains failure on finding beyond tickIndex - const messageMatch = whirlErr.message.indexOf("-5696") >= 0; - assert.ok(messageMatch, "Error Message must match condition."); - assert.ok(errorMatch, "Error Code must match condition."); - return true; - } - ); - }); - - /** - * |a--------x1----------a| Max - */ - it("on the last tick-array, traverse to the MAX_TICK_INDEX tick", async () => { - const currIndex = arrayTickIndexToTickIndex({ arrayIndex: 78, offsetIndex: 22 }, tickSpacing); - const aToB = false; - const whirlpool = await setupSwapTest({ - ctx, - client, - tickSpacing, - initSqrtPrice: PriceMath.tickIndexToSqrtPriceX64(currIndex), - initArrayStartTicks: [MAX_TICK_INDEX], - fundedPositions: [ - buildPosition( - // a - { arrayIndex: 78, offsetIndex: 0 }, // 439,296 - { arrayIndex: 78, offsetIndex: 67 }, // 443,584 - tickSpacing, - new BN(250) - ), - ], - tokenMintAmount: new BN("95000000000000000"), - }); - - const whirlpoolData = await whirlpool.refreshData(); - const beforeVaultAmounts = await getVaultAmounts(ctx, whirlpoolData); - const quote = await swapQuoteByInputToken( - whirlpool, - whirlpoolData.tokenMintB, - new BN("12595000000000"), - slippageTolerance, - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - await (await whirlpool.swap(quote)).buildAndExecute(); - - const newData = await whirlpool.refreshData(); - const afterVaultAmounts = await getVaultAmounts(ctx, whirlpoolData); - assertQuoteAndResults(aToB, quote, newData, beforeVaultAmounts, afterVaultAmounts); - }); - - /** - * Min |a--------x2--------a----|-----------------|-------------------| - */ - it("on the first tick-array, traverse to the MIN_TICK_INDEX tick", async () => { - const currIndex = arrayTickIndexToTickIndex({ arrayIndex: -79, offsetIndex: 22 }, tickSpacing); - const aToB = true; - const whirlpool = await setupSwapTest({ - ctx, - client, - tickSpacing, - initSqrtPrice: PriceMath.tickIndexToSqrtPriceX64(currIndex), - initArrayStartTicks: [MIN_TICK_INDEX], - fundedPositions: [ - buildPosition( - // a -444,928 - { arrayIndex: -79, offsetIndex: 21 }, - { arrayIndex: -79, offsetIndex: TICK_ARRAY_SIZE - 1 }, - tickSpacing, - new BN(250) - ), - ], - tokenMintAmount: new BN("95000000000000000"), - }); - - const whirlpoolData = await whirlpool.refreshData(); - const beforeVaultAmounts = await getVaultAmounts(ctx, whirlpoolData); - const quote = await swapQuoteByInputToken( - whirlpool, - whirlpoolData.tokenMintA, - new BN("12595000000000"), - slippageTolerance, - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - await (await whirlpool.swap(quote)).buildAndExecute(); - - const newData = await whirlpool.refreshData(); - const afterVaultAmounts = await getVaultAmounts(ctx, whirlpoolData); - assertQuoteAndResults(aToB, quote, newData, beforeVaultAmounts, afterVaultAmounts); - }); - - /** - * -5632 0 5632 11264 - * |-a--------|-------x1-|----------|----------|-x2-----a-| - * ta0 ta1 ta2 - */ - it("b->a, tickCurrentIndex = -tickSpacing, shifted", async () => { - const currIndex = arrayTickIndexToTickIndex({ arrayIndex: -1, offsetIndex: 87 }, tickSpacing); - const aToB = false; - const whirlpool = await setupSwapTest({ - ctx, - client, - tickSpacing, - initSqrtPrice: PriceMath.tickIndexToSqrtPriceX64(currIndex), - initArrayStartTicks: [-11264, -5632, 0, 5632, 11264], - fundedPositions: [ - buildPosition( - // a - { arrayIndex: -2, offsetIndex: 10 }, - { arrayIndex: 2, offsetIndex: 80 }, - tickSpacing, - new BN(250_000_000) - ), - ], - }); - - const whirlpoolData = await whirlpool.refreshData(); - const beforeVaultAmounts = await getVaultAmounts(ctx, whirlpoolData); - const inputTokenQuote = await swapQuoteByInputToken( - whirlpool, - whirlpoolData.tokenMintB, - new BN(200000000), - slippageTolerance, - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - const ta2StartTickIndex = 11264 - assert.ok(inputTokenQuote.estimatedEndTickIndex > ta2StartTickIndex); // traverse ta0, ta1, and ta2 - - const outputTokenQuote = await swapQuoteByOutputToken( - whirlpool, - whirlpoolData.tokenMintA, - inputTokenQuote.estimatedAmountOut, - slippageTolerance, - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - assertInputOutputQuoteEqual(inputTokenQuote, outputTokenQuote); - await (await whirlpool.swap(inputTokenQuote)).buildAndExecute(); - - const newData = await whirlpool.refreshData(); - const afterVaultAmounts = await getVaultAmounts(ctx, whirlpoolData); - assertQuoteAndResults(aToB, inputTokenQuote, newData, beforeVaultAmounts, afterVaultAmounts); - }); - - /** - * -5632 0 5632 11264 - * |-a--------|--------x1|----------|----------|-x2-----a-| - * ta0 ta1 ta2 - */ - it("b->a, tickCurrentIndex = -1, shifted", async () => { - const currIndex = -1; - const aToB = false; - const whirlpool = await setupSwapTest({ - ctx, - client, - tickSpacing, - initSqrtPrice: PriceMath.tickIndexToSqrtPriceX64(currIndex), - initArrayStartTicks: [-11264, -5632, 0, 5632, 11264], - fundedPositions: [ - buildPosition( - // a - { arrayIndex: -2, offsetIndex: 10 }, - { arrayIndex: 2, offsetIndex: 80 }, - tickSpacing, - new BN(250_000_000) - ), - ], - }); - - const whirlpoolData = await whirlpool.refreshData(); - const beforeVaultAmounts = await getVaultAmounts(ctx, whirlpoolData); - const inputTokenQuote = await swapQuoteByInputToken( - whirlpool, - whirlpoolData.tokenMintB, - new BN(200000000), - slippageTolerance, - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - const ta2StartTickIndex = 11264 - assert.ok(inputTokenQuote.estimatedEndTickIndex > ta2StartTickIndex); // traverse ta0, ta1, and ta2 - - const outputTokenQuote = await swapQuoteByOutputToken( - whirlpool, - whirlpoolData.tokenMintA, - inputTokenQuote.estimatedAmountOut, - slippageTolerance, - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - assertInputOutputQuoteEqual(inputTokenQuote, outputTokenQuote); - await (await whirlpool.swap(inputTokenQuote)).buildAndExecute(); - - const newData = await whirlpool.refreshData(); - const afterVaultAmounts = await getVaultAmounts(ctx, whirlpoolData); - assertQuoteAndResults(aToB, inputTokenQuote, newData, beforeVaultAmounts, afterVaultAmounts); - }); - - /** - * -5632 0 5632 11264 - * |-a--------|XXXXXXXXx1|----------|----------|-x2-----a-| - * ta0 ta1 ta2 - */ - it("b->a, tickCurrentIndex = -1, tickCurrentIndex on uninitialized TickArray, shifted", async () => { - const currIndex = -1; - const aToB = false; - const whirlpool = await setupSwapTest({ - ctx, - client, - tickSpacing, - initSqrtPrice: PriceMath.tickIndexToSqrtPriceX64(currIndex), - initArrayStartTicks: [-11264, 0, 5632, 11264], - fundedPositions: [ - buildPosition( - // a - { arrayIndex: -2, offsetIndex: 10 }, - { arrayIndex: 2, offsetIndex: 80 }, - tickSpacing, - new BN(250_000_000) - ), - ], - }); - - const whirlpoolData = await whirlpool.refreshData(); - const beforeVaultAmounts = await getVaultAmounts(ctx, whirlpoolData); - const inputTokenQuote = await swapQuoteByInputToken( - whirlpool, - whirlpoolData.tokenMintB, - new BN(200000000), - slippageTolerance, - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - const ta2StartTickIndex = 11264 - assert.ok(inputTokenQuote.estimatedEndTickIndex > ta2StartTickIndex); // traverse ta0, ta1, and ta2 - - const outputTokenQuote = await swapQuoteByOutputToken( - whirlpool, - whirlpoolData.tokenMintA, - inputTokenQuote.estimatedAmountOut, - slippageTolerance, - ctx.program.programId, - fetcher, - IGNORE_CACHE - ); - assertInputOutputQuoteEqual(inputTokenQuote, outputTokenQuote); - await (await whirlpool.swap(inputTokenQuote)).buildAndExecute(); - - const newData = await whirlpool.refreshData(); - const afterVaultAmounts = await getVaultAmounts(ctx, whirlpoolData); - assertQuoteAndResults(aToB, inputTokenQuote, newData, beforeVaultAmounts, afterVaultAmounts); - }); - - /** - * sqrtPriceLimit < MIN_SQRT_PRICE - * |--------------------|-----------------|---------x1----------| - */ - it("3 arrays, sqrtPriceLimit is out of bounds (< MIN_SQRT_PRICE), a->b", async () => { - const currIndex = arrayTickIndexToTickIndex({ arrayIndex: 1, offsetIndex: 22 }, tickSpacing); - const whirlpool = await setupSwapTest({ - ctx, - client, - tickSpacing, - initSqrtPrice: PriceMath.tickIndexToSqrtPriceX64(currIndex), - initArrayStartTicks: [-11264, -5632, 0, 5632, 11264], - fundedPositions: [ - buildPosition( - // a - { arrayIndex: -2, offsetIndex: 10 }, - { arrayIndex: 2, offsetIndex: 23 }, - tickSpacing, - new BN(250_000_000) - ), - ], - }); - - const whirlpoolData = await whirlpool.refreshData(); - const aToB = true; - const tickArrays = await SwapUtils.getTickArrays( - currIndex, - tickSpacing, - aToB, - ctx.program.programId, - whirlpool.getAddress(), - fetcher, - IGNORE_CACHE - ); - assert.throws( - () => - swapQuoteWithParams( - { - aToB, - amountSpecifiedIsInput: true, - tokenAmount: new BN("10000"), - whirlpoolData, - tickArrays, - sqrtPriceLimit: new BN(MIN_SQRT_PRICE).subn(1), - otherAmountThreshold: SwapUtils.getDefaultOtherAmountThreshold(true), - }, - slippageTolerance - ), - (err) => (err as WhirlpoolsError).errorCode === SwapErrorCode.SqrtPriceOutOfBounds - ); - }); - - /** - * sqrtPriceLimit > MAX_SQRT_PRICE - * |-----x1-------------|-----------------|---------------------| - */ - it("3 arrays, sqrtPriceLimit is out of bounds (> MAX_SQRT_PRICE), b->a", async () => { - const currIndex = arrayTickIndexToTickIndex({ arrayIndex: -1, offsetIndex: 22 }, tickSpacing); - const whirlpool = await setupSwapTest({ - ctx, - client, - tickSpacing, - initSqrtPrice: PriceMath.tickIndexToSqrtPriceX64(currIndex), - initArrayStartTicks: [-11264, -5632, 0, 5632, 11264], - fundedPositions: [ - buildPosition( - // a - { arrayIndex: -2, offsetIndex: 10 }, - { arrayIndex: 2, offsetIndex: 23 }, - tickSpacing, - new BN(250_000_000) - ), - ], - }); - - const whirlpoolData = await whirlpool.refreshData(); - const aToB = false; - const tickArrays = await SwapUtils.getTickArrays( - currIndex, - tickSpacing, - aToB, - ctx.program.programId, - whirlpool.getAddress(), - fetcher, - IGNORE_CACHE - ); - assert.throws( - () => - swapQuoteWithParams( - { - aToB, - amountSpecifiedIsInput: true, - tokenAmount: new BN("10000"), - whirlpoolData, - tickArrays, - sqrtPriceLimit: new BN(MAX_SQRT_PRICE).addn(1), - otherAmountThreshold: SwapUtils.getDefaultOtherAmountThreshold(true), - }, - slippageTolerance - ), - (err) => (err as WhirlpoolsError).errorCode === SwapErrorCode.SqrtPriceOutOfBounds - ); - }); -}); diff --git a/sdk/tests/sdk/whirlpools/utils/pool-graph.test.ts b/sdk/tests/sdk/whirlpools/utils/pool-graph.test.ts deleted file mode 100644 index 8783a49..0000000 --- a/sdk/tests/sdk/whirlpools/utils/pool-graph.test.ts +++ /dev/null @@ -1,517 +0,0 @@ -import { Address } from "@coral-xyz/anchor"; -import { AddressUtil } from "@orca-so/common-sdk"; -import * as assert from "assert"; -import { Path, PathSearchEntries, PoolGraphBuilder, PoolGraphUtils, PoolTokenPair } from "../../../../src"; -import { - feeTierPoolsGraphData, - solConnectedPools, - uniqueTokenMintsGraphData, - uniqueTokenMintsGraphTokenUnsortedData, - usdcConnectedPools -} from "../../../utils/graph-test-data"; - -const uniqueTokenPair = uniqueTokenMintsGraphData[0]; -const uniqueTokenPairSorted = uniqueTokenMintsGraphData[0]; -const rlbSolPool = solConnectedPools[0]; -const mSolSolPool = solConnectedPools[1]; -const dustSolPool = solConnectedPools[2]; -const stSolSolPool = solConnectedPools[3]; -const usdcSolPool = solConnectedPools[4]; -const rlbUsdcPool = usdcConnectedPools[0]; -const msolUsdcPool = usdcConnectedPools[1]; -const dustUsdcPool = usdcConnectedPools[2]; -const usdcMint: Address = feeTierPoolsGraphData[0].tokenMintB; - -describe("PoolGraph tests", () => { - describe("getPathsForPairs", () => { - it("Path does not exist", async () => { - const testData = [...solConnectedPools]; - const graph = PoolGraphBuilder.buildPoolGraph(testData); - const uniqueTokenPair = uniqueTokenMintsGraphTokenUnsortedData[0]; - const results = graph.getPathsForPairs([ - [uniqueTokenPair.tokenMintA, uniqueTokenPair.tokenMintB], - ]); - assert.equal(results.length, 1); - const searchId = PoolGraphUtils.getSearchPathId(uniqueTokenPair.tokenMintA, uniqueTokenPair.tokenMintB); - - assertGetPathsForPairsResult(results, [[searchId, []]]); - }); - - it("Path between the same token mint", async () => { - const testData = [...solConnectedPools, ...feeTierPoolsGraphData]; - const graph = PoolGraphBuilder.buildPoolGraph(testData); - - - const searchTokenPairs: [Address, Address][] = [ - [usdcMint, usdcMint] - ] - const results = graph.getPathsForPairs(searchTokenPairs); - assert.equal(results.length, 1); - - const searchId = PoolGraphUtils.getSearchPathId(uniqueTokenPair.tokenMintA, uniqueTokenPair.tokenMintA); - - assertGetPathsForPairsResult(results, [[searchId, []]]); - }) - - it("1 path exist", async () => { - const testData = [...solConnectedPools, ...uniqueTokenMintsGraphData]; - const graph = PoolGraphBuilder.buildPoolGraph(testData); - - - const searchTokenPairs: [Address, Address][] = [ - [uniqueTokenPair.tokenMintA, uniqueTokenPair.tokenMintB] - ] - const results = graph.getPathsForPairs(searchTokenPairs); - assert.equal(results.length, 1); - - const expectedPathsForTokenPairQueries: [string, PoolTokenPair[][]][] = [ - [PoolGraphUtils.getSearchPathId(searchTokenPairs[0][0], searchTokenPairs[0][1]), [ - [uniqueTokenPair] - ]]]; - - assertGetPathsForPairsResult(results, expectedPathsForTokenPairQueries); - }); - - it("1 path exist - token ordering reversed", async () => { - const testData = [...solConnectedPools, ...uniqueTokenMintsGraphTokenUnsortedData]; - const graph = PoolGraphBuilder.buildPoolGraph(testData); - - const searchTokenPairs: [Address, Address][] = [ - [uniqueTokenPair.tokenMintA, uniqueTokenPair.tokenMintB] - ] - const results = graph.getPathsForPairs(searchTokenPairs); - - assert.equal(results.length, 1); - - const expectedPathsForTokenPairQueries: [string, PoolTokenPair[][]][] = [ - [PoolGraphUtils.getSearchPathId(searchTokenPairs[0][0], searchTokenPairs[0][1]), [ - [uniqueTokenPairSorted] - ]]]; - assertGetPathsForPairsResult(results, expectedPathsForTokenPairQueries); - }); - - it("1 path with 2 edges exist - verify edge ordering correct", async () => { - const testData = [...solConnectedPools]; - const graph = PoolGraphBuilder.buildPoolGraph(testData); - - - const searchTokenPairs: [Address, Address][] = [ - [rlbSolPool.tokenMintB, mSolSolPool.tokenMintB] - ] - const results = graph.getPathsForPairs(searchTokenPairs); - - assert.equal(results.length, 1); - - const expectedPathsForTokenPairQueries: [string, PoolTokenPair[][]][] = [ - [PoolGraphUtils.getSearchPathId(searchTokenPairs[0][0], searchTokenPairs[0][1]), [ - [rlbSolPool, mSolSolPool] - ]]]; - - assertGetPathsForPairsResult(results, expectedPathsForTokenPairQueries); - }); - - it("1 path with 2 edges exist - verify edge ordering correct (reverse)", async () => { - const testData = [...solConnectedPools]; - const graph = PoolGraphBuilder.buildPoolGraph(testData); - - const searchTokenPairs: [Address, Address][] = [ - [mSolSolPool.tokenMintB, rlbSolPool.tokenMintB] - ] - const results = graph.getPathsForPairs(searchTokenPairs); - - assert.equal(results.length, 1); - - const expectedPathsForTokenPairQueries: [string, PoolTokenPair[][]][] = [ - [PoolGraphUtils.getSearchPathId(searchTokenPairs[0][0], searchTokenPairs[0][1]), [ - [mSolSolPool, rlbSolPool] - ]]]; - assertGetPathsForPairsResult(results, expectedPathsForTokenPairQueries); - }); - - it("1 tokenPair input to multiple paths exist - verify token order, edge ordering", async () => { - const testData = [...solConnectedPools, ...usdcConnectedPools]; - const graph = PoolGraphBuilder.buildPoolGraph(testData); - - const searchTokenPairs: [Address, Address][] = [ - [rlbSolPool.tokenMintB, mSolSolPool.tokenMintB] - ] - const results = graph.getPathsForPairs(searchTokenPairs); - - assert.equal(results.length, 1); - - const expectedPathsForTokenPairQueries: [string, PoolTokenPair[][]][] = [ - [PoolGraphUtils.getSearchPathId(searchTokenPairs[0][0], searchTokenPairs[0][1]), [ - [rlbSolPool, mSolSolPool], - [rlbUsdcPool, msolUsdcPool], - ]]]; - - assertGetPathsForPairsResult(results, expectedPathsForTokenPairQueries); - }); - - it("duplicated token-pairs will still be executed and ordered in results", async () => { - const testData = [...solConnectedPools, ...usdcConnectedPools]; - const graph = PoolGraphBuilder.buildPoolGraph(testData); - - const searchTokenPairs: [Address, Address][] = [ - [rlbSolPool.tokenMintB, mSolSolPool.tokenMintB], - [rlbSolPool.tokenMintB, mSolSolPool.tokenMintB], - ] - - const results = graph.getPathsForPairs(searchTokenPairs); - assert.equal(results.length, 2); - - const expectedPathsForTokenPairQueries: [string, PoolTokenPair[][]][] = [ - [PoolGraphUtils.getSearchPathId(searchTokenPairs[0][0], searchTokenPairs[0][1]), [ - [rlbSolPool, mSolSolPool], - [rlbUsdcPool, msolUsdcPool], - ]], - [PoolGraphUtils.getSearchPathId(searchTokenPairs[1][0], searchTokenPairs[1][1]), [ - [rlbSolPool, mSolSolPool], - [rlbUsdcPool, msolUsdcPool], - ]]]; - - assertGetPathsForPairsResult(results, expectedPathsForTokenPairQueries); - }); - - it("same token-pairs but with reversed order has unique search ids", async () => { - const testData = [...solConnectedPools, ...usdcConnectedPools]; - const graph = PoolGraphBuilder.buildPoolGraph(testData); - - const searchTokenPairs: [Address, Address][] = [ - [rlbSolPool.tokenMintB, mSolSolPool.tokenMintB], - [mSolSolPool.tokenMintB, rlbSolPool.tokenMintB], - ] - - const results = graph.getPathsForPairs(searchTokenPairs); - assert.equal(results.length, 2); - - // TODO: Directionality of the edges is not being considered - const expectedPathsForTokenPairQueries: [string, PoolTokenPair[][]][] = [ - [PoolGraphUtils.getSearchPathId(searchTokenPairs[0][0], searchTokenPairs[0][1]), [ - [rlbSolPool, mSolSolPool], - [rlbUsdcPool, msolUsdcPool], - ]], - [PoolGraphUtils.getSearchPathId(searchTokenPairs[1][0], searchTokenPairs[1][1]), [ - [mSolSolPool, rlbSolPool], - [msolUsdcPool, rlbUsdcPool], - ]]]; - - assertGetPathsForPairsResult(results, expectedPathsForTokenPairQueries); - }); - - it("only allow 2-edge paths that go through tokens from the intermediate token list ", async () => { - const testData = [...solConnectedPools, ...usdcConnectedPools]; - const graph = PoolGraphBuilder.buildPoolGraph(testData); - - const searchTokenPairs: [Address, Address][] = [ - [rlbUsdcPool.tokenMintB, msolUsdcPool.tokenMintB] - ]; - const results = graph.getPathsForPairs(searchTokenPairs, { - intermediateTokens: [rlbUsdcPool.tokenMintA], - }); - - // Assert that the SOL paths are filtered out - assert.equal(results.length, 1); - - const expectedPathsForTokenPairQueries: [string, PoolTokenPair[][]][] = [ - [PoolGraphUtils.getSearchPathId(searchTokenPairs[0][0], searchTokenPairs[0][1]), [ - [rlbUsdcPool, msolUsdcPool] - ]] - ]; - - assertGetPathsForPairsResult(results, expectedPathsForTokenPairQueries); - }); - - it("multiple tokenPair input to multiple paths exist - verify token order, edge ordering", async () => { - const testData = [...solConnectedPools, ...usdcConnectedPools]; - const graph = PoolGraphBuilder.buildPoolGraph(testData); - - const searchTokenPairs: [Address, Address][] = [ - [rlbSolPool.tokenMintB, mSolSolPool.tokenMintB], - [dustSolPool.tokenMintB, mSolSolPool.tokenMintB], - ] - - const results = graph.getPathsForPairs(searchTokenPairs); - - assert.equal(results.length, 2); - - const expectedPathsForTokenPairQueries: [string, PoolTokenPair[][]][] = [ - [PoolGraphUtils.getSearchPathId(searchTokenPairs[0][0], searchTokenPairs[0][1]), [ - [rlbSolPool, mSolSolPool], - [rlbUsdcPool, msolUsdcPool], - ]], - [PoolGraphUtils.getSearchPathId(searchTokenPairs[1][0], searchTokenPairs[1][1]), [ - [dustSolPool, mSolSolPool], - [dustUsdcPool, msolUsdcPool], - ]]]; - - assertGetPathsForPairsResult(results, expectedPathsForTokenPairQueries) - }); - }); - - describe("getPath", async () => { - it("Path does not exist", async () => { - const testData = [...solConnectedPools]; - const graph = PoolGraphBuilder.buildPoolGraph(testData); - const result = graph.getPath(uniqueTokenPair.tokenMintA, uniqueTokenPair.tokenMintB); - assert.equal(result.length, 0); - }); - - it("1 path exist", async () => { - const testData = [...solConnectedPools, ...uniqueTokenMintsGraphData]; - const graph = PoolGraphBuilder.buildPoolGraph(testData); - const result = graph.getPath(uniqueTokenPair.tokenMintA, uniqueTokenPair.tokenMintB); - - assertGetPathResult( - result, - [[uniqueTokenPair]], - uniqueTokenPair.tokenMintA, - uniqueTokenPair.tokenMintB - ); - }); - - it("1 path exist - token ordering reversed", async () => { - const testData = [...solConnectedPools, ...uniqueTokenMintsGraphTokenUnsortedData]; - const graph = PoolGraphBuilder.buildPoolGraph(testData); - - const result = graph.getPath(uniqueTokenPair.tokenMintA, uniqueTokenPair.tokenMintB); - assertGetPathResult( - result, - [[uniqueTokenPairSorted]], - uniqueTokenPair.tokenMintA, - uniqueTokenPair.tokenMintB - ); - }); - - it("Path between the same token mint", async () => { - const testData = [...solConnectedPools, ...feeTierPoolsGraphData]; - const graph = PoolGraphBuilder.buildPoolGraph(testData); - const results = graph.getPath(usdcMint, usdcMint); - - assertGetPathResult(results, [], usdcMint, usdcMint); - }) - - it("1 path with 2 edges exist - verify edge ordering correct", async () => { - const testData = [...solConnectedPools]; - const graph = PoolGraphBuilder.buildPoolGraph(testData); - - const result = graph.getPath(rlbSolPool.tokenMintB, mSolSolPool.tokenMintB); - assertGetPathResult( - result, - [[rlbSolPool, mSolSolPool]], - rlbSolPool.tokenMintB, - mSolSolPool.tokenMintB - ); - }); - - it("1 path with 2 edges exist - verify edge ordering correct (reverse)", async () => { - const testData = [...solConnectedPools]; - const graph = PoolGraphBuilder.buildPoolGraph(testData); - - const result = graph.getPath(mSolSolPool.tokenMintB, rlbSolPool.tokenMintB); - assertGetPathResult( - result, - [[mSolSolPool, rlbSolPool]], - mSolSolPool.tokenMintB, - rlbSolPool.tokenMintB - ); - }); - - it("1 tokenPair input to multiple paths exist - verify token order, edge ordering", async () => { - const testData = [...solConnectedPools, ...usdcConnectedPools]; - const graph = PoolGraphBuilder.buildPoolGraph(testData); - - const result = graph.getPath(rlbSolPool.tokenMintB, mSolSolPool.tokenMintB); - assertGetPathResult( - result, - [ - [rlbSolPool, mSolSolPool], - [rlbUsdcPool, msolUsdcPool], - ], - rlbSolPool.tokenMintB, - mSolSolPool.tokenMintB - ); - }); - - it("only allow 2-edge paths that go through tokens from the intermediate token list ", async () => { - const testData = [...solConnectedPools, ...usdcConnectedPools]; - const graph = PoolGraphBuilder.buildPoolGraph(testData); - - const result = graph.getPath(rlbUsdcPool.tokenMintB, msolUsdcPool.tokenMintB, { - intermediateTokens: [rlbUsdcPool.tokenMintA], - }); - assertGetPathResult( - result, - [[rlbUsdcPool, msolUsdcPool]], - rlbUsdcPool.tokenMintB, - msolUsdcPool.tokenMintB - ); - }); - }); - - describe("Pool graph edge cases", () => { - it("Zero pools in graph should not return any results", async () => { - const graph = PoolGraphBuilder.buildPoolGraph([]); - const uniqueTokenPair = uniqueTokenMintsGraphTokenUnsortedData[0]; - const results = graph.getPathsForPairs([ - [uniqueTokenPair.tokenMintA, uniqueTokenPair.tokenMintB], - ]); - assert.equal(results.length, 1); - const searchId = PoolGraphUtils.getSearchPathId(uniqueTokenPair.tokenMintA, uniqueTokenPair.tokenMintB); - - assertGetPathsForPairsResult(results, [[searchId, []]]); - }); - - it("Duplicate pool data in input should not affect output", async () => { - const testData = [...solConnectedPools, ...solConnectedPools, ...uniqueTokenMintsGraphData]; - const graph = PoolGraphBuilder.buildPoolGraph(testData); - - const searchTokenPairs: [Address, Address][] = [ - [uniqueTokenPair.tokenMintA, uniqueTokenPair.tokenMintB], - [rlbSolPool.tokenMintA, rlbSolPool.tokenMintB] - ] - const results = graph.getPathsForPairs(searchTokenPairs); - - assert.equal(results.length, 2); - - const expectedPathsForTokenPairQueries: [string, PoolTokenPair[][]][] = [ - [PoolGraphUtils.getSearchPathId(searchTokenPairs[0][0], searchTokenPairs[0][1]), [ - [uniqueTokenPair] - ]], [PoolGraphUtils.getSearchPathId(rlbSolPool.tokenMintA, rlbSolPool.tokenMintB), [ - [rlbSolPool] - ]]]; - - assertGetPathsForPairsResult(results, expectedPathsForTokenPairQueries); - }); - }); - - describe("getAllPaths", () => { - it("Zero pools", async () => { - const graph = PoolGraphBuilder.buildPoolGraph([]); - const results = graph.getAllPaths(); - assert.equal(results.length, 0); - }); - - it("solConnectedPools", () => { - const testData = solConnectedPools; - const graph = PoolGraphBuilder.buildPoolGraph(testData); - - const results = graph.getAllPaths(); - - const sol = rlbSolPool.tokenMintA; - const rlb = rlbSolPool.tokenMintB; - const msol = mSolSolPool.tokenMintB; - const dust = dustSolPool.tokenMintB; - const stSol = stSolSolPool.tokenMintB; - const usdc = usdcSolPool.tokenMintB; - - const expectedPaths = new Map(); - - // combinations - expectedPaths.set(PoolGraphUtils.getSearchPathId(sol, rlb), [[rlbSolPool]]); - expectedPaths.set(PoolGraphUtils.getSearchPathId(sol, msol), [[mSolSolPool]]); - expectedPaths.set(PoolGraphUtils.getSearchPathId(sol, dust), [[dustSolPool]]); - expectedPaths.set(PoolGraphUtils.getSearchPathId(sol, stSol), [[stSolSolPool]]); - expectedPaths.set(PoolGraphUtils.getSearchPathId(sol, usdc), [[usdcSolPool]]); - expectedPaths.set(PoolGraphUtils.getSearchPathId(rlb, msol), [[rlbSolPool, mSolSolPool]]); - expectedPaths.set(PoolGraphUtils.getSearchPathId(rlb, dust), [[rlbSolPool, dustSolPool]]); - expectedPaths.set(PoolGraphUtils.getSearchPathId(rlb, stSol), [[rlbSolPool, stSolSolPool]]); - expectedPaths.set(PoolGraphUtils.getSearchPathId(rlb, usdc), [[rlbSolPool, usdcSolPool]]); - expectedPaths.set(PoolGraphUtils.getSearchPathId(msol, dust), [[mSolSolPool, dustSolPool]]); - expectedPaths.set(PoolGraphUtils.getSearchPathId(msol, stSol), [[mSolSolPool, stSolSolPool]]); - expectedPaths.set(PoolGraphUtils.getSearchPathId(msol, usdc), [[mSolSolPool, usdcSolPool]]); - expectedPaths.set(PoolGraphUtils.getSearchPathId(dust, stSol), [[dustSolPool, stSolSolPool]]); - expectedPaths.set(PoolGraphUtils.getSearchPathId(dust, usdc), [[dustSolPool, usdcSolPool]]); - expectedPaths.set(PoolGraphUtils.getSearchPathId(stSol, usdc), [[stSolSolPool, usdcSolPool]]); - - // reverse - expectedPaths.set(PoolGraphUtils.getSearchPathId(rlb, sol), [[rlbSolPool]]); - expectedPaths.set(PoolGraphUtils.getSearchPathId(msol, sol), [[mSolSolPool]]); - expectedPaths.set(PoolGraphUtils.getSearchPathId(dust, sol), [[dustSolPool]]); - expectedPaths.set(PoolGraphUtils.getSearchPathId(stSol, sol), [[stSolSolPool]]); - expectedPaths.set(PoolGraphUtils.getSearchPathId(usdc, sol), [[usdcSolPool]]); - expectedPaths.set(PoolGraphUtils.getSearchPathId(msol, rlb), [[mSolSolPool, rlbSolPool]]); - expectedPaths.set(PoolGraphUtils.getSearchPathId(dust, rlb), [[dustSolPool, rlbSolPool]]); - expectedPaths.set(PoolGraphUtils.getSearchPathId(stSol, rlb), [[stSolSolPool, rlbSolPool]]); - expectedPaths.set(PoolGraphUtils.getSearchPathId(usdc, rlb), [[usdcSolPool, rlbSolPool]]); - expectedPaths.set(PoolGraphUtils.getSearchPathId(dust, msol), [[dustSolPool, mSolSolPool]]); - expectedPaths.set(PoolGraphUtils.getSearchPathId(stSol, msol), [[stSolSolPool, mSolSolPool]]); - expectedPaths.set(PoolGraphUtils.getSearchPathId(usdc, msol), [[usdcSolPool, mSolSolPool]]); - expectedPaths.set(PoolGraphUtils.getSearchPathId(stSol, dust), [[stSolSolPool, dustSolPool]]); - expectedPaths.set(PoolGraphUtils.getSearchPathId(usdc, dust), [[usdcSolPool, dustSolPool]]); - expectedPaths.set(PoolGraphUtils.getSearchPathId(usdc, stSol), [[usdcSolPool, stSolSolPool]]); - - assert.equal(results.length, expectedPaths.size, "Number of paths should match expected paths"); - - results.forEach((searchEntry) => { - const [pathId, paths] = searchEntry; - const [startMint, endMint] = PoolGraphUtils.deconstructPathId(pathId); - - const expected = expectedPaths.get(pathId); - assert.ok(!!expected, `Expected path for ${pathId} to exist`); - assertGetPathResult(paths, expected, startMint, endMint); - }); - }); - }); -}); - -function assertGetPathsForPairsResult( - searchResultEntires: PathSearchEntries, - expectedPaths: [string, PoolTokenPair[][]][] -) { - - assert.equal(searchResultEntires.length, expectedPaths.length, `Number of paths should match expected paths`); - - searchResultEntires.forEach((searchEntry, entryIndex) => { - const [pathId, paths] = searchEntry; - const [startMint, endMint] = PoolGraphUtils.deconstructPathId(pathId); - - // Assert path is correct - const expectedPathsForEntry = expectedPaths[entryIndex]; - - assert.equal( - paths.length, - expectedPathsForEntry[1].length, - "Expected number of paths to match expected pools" - ); - - assertGetPathResult(paths, expectedPathsForEntry[1], startMint, endMint); - }) -} - -function assertGetPathResult( - paths: Path[], - expectedPaths: PoolTokenPair[][], - expectedStartMint: Address, - expectedEndMint: Address -) { - assert.equal(paths.length, expectedPaths.length); - paths.forEach((path, pathIndex) => { - assertPath(path, pathIndex, expectedStartMint, expectedEndMint, expectedPaths); - }); -} - -function assertPath( - path: Path, - pathIndex: number, - expectedStartMint: Address, - expectedEndMint: Address, - expectedPaths: PoolTokenPair[][] -) { - assert.equal(path.startTokenMint, AddressUtil.toString(expectedStartMint)); - assert.equal(path.endTokenMint, AddressUtil.toString(expectedEndMint)); - - const expectedPath = expectedPaths[pathIndex]; - assert.equal( - path.edges.length, - expectedPath.length, - `Expected number of edges to match expected pools at index ${pathIndex}` - ); - path.edges.forEach((edge, edgeIndex) => { - assert.equal( - AddressUtil.toString(edge.poolAddress), - AddressUtil.toString(expectedPaths[pathIndex][edgeIndex].address), - `Expected edge pool address to match expected pool addr at edge index ${edgeIndex}` - ); - }); -} diff --git a/sdk/tests/sdk/whirlpools/utils/pool-utils.test.ts b/sdk/tests/sdk/whirlpools/utils/pool-utils.test.ts deleted file mode 100644 index 6657c07..0000000 --- a/sdk/tests/sdk/whirlpools/utils/pool-utils.test.ts +++ /dev/null @@ -1,26 +0,0 @@ -import * as assert from "assert"; -import { TokenType, PoolUtil } from "../../../../src"; -import { testWhirlpoolData } from "../../../utils/testDataTypes"; -import { Keypair } from "@solana/web3.js"; - -describe("PoolUtils tests", () => { - describe("getTokenType", () => { - it("Token is tokenA", async () => { - const whirlpoolData = testWhirlpoolData; - const result = PoolUtil.getTokenType(whirlpoolData, whirlpoolData.tokenMintA); - assert.equal(result, TokenType.TokenA); - }); - - it("Token is tokenB", async () => { - const whirlpoolData = testWhirlpoolData; - const result = PoolUtil.getTokenType(whirlpoolData, whirlpoolData.tokenMintB); - assert.equal(result, TokenType.TokenB); - }); - - it("Token is some other token", async () => { - const whirlpoolData = testWhirlpoolData; - const result = PoolUtil.getTokenType(whirlpoolData, Keypair.generate().publicKey); - assert.ok(result === undefined); - }); - }); -}); diff --git a/sdk/tests/sdk/whirlpools/utils/position-bundle-util.test.ts b/sdk/tests/sdk/whirlpools/utils/position-bundle-util.test.ts deleted file mode 100644 index 04e02a8..0000000 --- a/sdk/tests/sdk/whirlpools/utils/position-bundle-util.test.ts +++ /dev/null @@ -1,149 +0,0 @@ -import * as assert from "assert"; -import { PositionBundleUtil, POSITION_BUNDLE_SIZE } from "../../../../src"; -import { buildPositionBundleData } from "../../../utils/testDataTypes"; - -describe("PositionBundleUtil tests", () => { - const occupiedEmpty: number[] = []; - const occupiedPartial: number[] = [0, 1, 5, 49, 128, 193, 255]; - const occupiedFull: number[] = new Array(POSITION_BUNDLE_SIZE).fill(0).map((a, i) => i); - - describe("checkBundleIndexInBounds", () => { - it("valid bundle indexes", async () => { - for (let bundleIndex=0; bundleIndex { - assert.ok(!PositionBundleUtil.checkBundleIndexInBounds(-1)); - }); - - it("greater than or equal to POSITION_BUNDLE_SIZE", async () => { - assert.ok(!PositionBundleUtil.checkBundleIndexInBounds(POSITION_BUNDLE_SIZE)); - assert.ok(!PositionBundleUtil.checkBundleIndexInBounds(POSITION_BUNDLE_SIZE+1)); - }); - }); - - it("isOccupied / isUnoccupied", async () => { - const positionBundle = buildPositionBundleData(occupiedPartial); - - for (let bundleIndex=0; bundleIndex { - it("empty", async () => { - const positionBundle = buildPositionBundleData(occupiedEmpty); - assert.ok(PositionBundleUtil.isEmpty(positionBundle)); - assert.ok(!PositionBundleUtil.isFull(positionBundle)); - }); - - it("some bundle indexes are occupied", async () => { - const positionBundle = buildPositionBundleData(occupiedPartial); - assert.ok(!PositionBundleUtil.isEmpty(positionBundle)); - assert.ok(!PositionBundleUtil.isFull(positionBundle)); - }); - - it("full", async () => { - const positionBundle = buildPositionBundleData(occupiedFull); - assert.ok(!PositionBundleUtil.isEmpty(positionBundle)); - assert.ok(PositionBundleUtil.isFull(positionBundle)); - }) - }) - - describe("getOccupiedBundleIndexes", () => { - it("empty", async () => { - const positionBundle = buildPositionBundleData(occupiedEmpty); - const result = PositionBundleUtil.getOccupiedBundleIndexes(positionBundle); - assert.equal(result.length, 0); - }); - - it("some bundle indexes are occupied", async () => { - const positionBundle = buildPositionBundleData(occupiedPartial); - const result = PositionBundleUtil.getOccupiedBundleIndexes(positionBundle); - assert.equal(result.length, occupiedPartial.length); - assert.ok(occupiedPartial.every(index => result.includes(index))); - }); - - it("full", async () => { - const positionBundle = buildPositionBundleData(occupiedFull); - const result = PositionBundleUtil.getOccupiedBundleIndexes(positionBundle); - assert.equal(result.length, POSITION_BUNDLE_SIZE); - assert.ok(occupiedFull.every(index => result.includes(index))); - }) - }); - - describe("getUnoccupiedBundleIndexes", () => { - it("empty", async () => { - const positionBundle = buildPositionBundleData(occupiedEmpty); - const result = PositionBundleUtil.getUnoccupiedBundleIndexes(positionBundle); - assert.equal(result.length, POSITION_BUNDLE_SIZE); - assert.ok(occupiedFull.every(index => result.includes(index))); - }); - - it("some bundle indexes are occupied", async () => { - const positionBundle = buildPositionBundleData(occupiedPartial); - const result = PositionBundleUtil.getUnoccupiedBundleIndexes(positionBundle); - assert.equal(result.length, POSITION_BUNDLE_SIZE - occupiedPartial.length); - assert.ok(occupiedPartial.every(index => !result.includes(index))); - }); - - it("full", async () => { - const positionBundle = buildPositionBundleData(occupiedFull); - const result = PositionBundleUtil.getUnoccupiedBundleIndexes(positionBundle); - assert.equal(result.length, 0); - }) - }); - - - describe("findUnoccupiedBundleIndex", () => { - it("empty", async () => { - const positionBundle = buildPositionBundleData(occupiedEmpty); - const result = PositionBundleUtil.findUnoccupiedBundleIndex(positionBundle); - assert.equal(result, 0); - }); - - it("some bundle indexes are occupied", async () => { - const positionBundle = buildPositionBundleData(occupiedPartial); - const result = PositionBundleUtil.findUnoccupiedBundleIndex(positionBundle); - assert.equal(result, 2); - }); - - it("full", async () => { - const positionBundle = buildPositionBundleData(occupiedFull); - const result = PositionBundleUtil.findUnoccupiedBundleIndex(positionBundle); - assert.ok(result === null); - }) - }); - - describe("convertBitmapToArray", () => { - it("empty", async () => { - const positionBundle = buildPositionBundleData(occupiedEmpty); - const result = PositionBundleUtil.convertBitmapToArray(positionBundle); - assert.equal(result.length, POSITION_BUNDLE_SIZE); - assert.ok(result.every((occupied) => !occupied)); - }); - - it("some bundle indexes are occupied", async () => { - const positionBundle = buildPositionBundleData(occupiedPartial); - const result = PositionBundleUtil.convertBitmapToArray(positionBundle); - assert.equal(result.length, POSITION_BUNDLE_SIZE); - assert.ok(result.every((occupied, i) => occupied === occupiedPartial.includes(i))); - }); - - it("full", async () => { - const positionBundle = buildPositionBundleData(occupiedFull); - const result = PositionBundleUtil.convertBitmapToArray(positionBundle); - assert.equal(result.length, POSITION_BUNDLE_SIZE); - assert.ok(result.every((occupied) => occupied)); - }) - }); -}); diff --git a/sdk/tests/sdk/whirlpools/utils/position-util.test.ts b/sdk/tests/sdk/whirlpools/utils/position-util.test.ts deleted file mode 100644 index 9ca56db..0000000 --- a/sdk/tests/sdk/whirlpools/utils/position-util.test.ts +++ /dev/null @@ -1,98 +0,0 @@ -import * as assert from "assert"; -import { PriceMath } from "../../../../src"; -import { PositionStatus, PositionUtil } from "../../../../src/utils/position-util"; - -describe("PositionUtil tests", () => { - const tickLowerIndex = 64; - const tickUpperIndex = 128; - - describe("getPositionStatus", () => { - it("tickCurrentIndex < tickLowerIndex, BelowRange", async () => { - const tickCurrentIndex = 0; - const result = PositionUtil.getPositionStatus(tickCurrentIndex, tickLowerIndex, tickUpperIndex); - assert.equal(result, PositionStatus.BelowRange); - }); - - it("tickCurrentIndex + 1 == tickLowerIndex, BelowRange", async () => { - const tickCurrentIndex = tickLowerIndex - 1; - const result = PositionUtil.getPositionStatus(tickCurrentIndex, tickLowerIndex, tickUpperIndex); - assert.equal(result, PositionStatus.BelowRange); - }); - - it("tickCurrentIndex == tickLowerIndex, InRange", async () => { - const tickCurrentIndex = tickLowerIndex; - const result = PositionUtil.getPositionStatus(tickCurrentIndex, tickLowerIndex, tickUpperIndex); - assert.equal(result, PositionStatus.InRange); - }); - - it("tickCurrentIndex + 1 == tickUpperIndex, InRange", async () => { - const tickCurrentIndex = tickUpperIndex - 1; - const result = PositionUtil.getPositionStatus(tickCurrentIndex, tickLowerIndex, tickUpperIndex); - assert.equal(result, PositionStatus.InRange); - }); - - it("tickCurrentIndex == tickUpperIndex, AboveRange", async () => { - const tickCurrentIndex = tickUpperIndex; - const result = PositionUtil.getPositionStatus(tickCurrentIndex, tickLowerIndex, tickUpperIndex); - assert.equal(result, PositionStatus.AboveRange); - }); - - it("tickCurrentIndex > tickUpperIndex, AboveRange", async () => { - const tickCurrentIndex = 192; - const result = PositionUtil.getPositionStatus(tickCurrentIndex, tickLowerIndex, tickUpperIndex); - assert.equal(result, PositionStatus.AboveRange); - }); - - }); - - describe("getStrictPositionStatus", async () => { - it("sqrtPrice < toSqrtPrice(tickLowerIndex), BelowRange", async () => { - const sqrtPriceX64 = PriceMath.tickIndexToSqrtPriceX64(0); - const result = PositionUtil.getStrictPositionStatus(sqrtPriceX64, tickLowerIndex, tickUpperIndex); - assert.equal(result, PositionStatus.BelowRange); - }); - - it("sqrtPrice + 1 == toSqrtPrice(tickLowerIndex), BelowRange", async () => { - const sqrtPriceX64 = PriceMath.tickIndexToSqrtPriceX64(tickLowerIndex).subn(1); - const result = PositionUtil.getStrictPositionStatus(sqrtPriceX64, tickLowerIndex, tickUpperIndex); - assert.equal(result, PositionStatus.BelowRange); - }); - - it("sqrtPrice == toSqrtPrice(tickLowerIndex), BelowRange", async () => { - const sqrtPriceX64 = PriceMath.tickIndexToSqrtPriceX64(tickLowerIndex); - const result = PositionUtil.getStrictPositionStatus(sqrtPriceX64, tickLowerIndex, tickUpperIndex); - assert.equal(result, PositionStatus.BelowRange); - }); - - it("sqrtPrice - 1 == toSqrtPrice(tickLowerIndex), InRange", async () => { - const sqrtPriceX64 = PriceMath.tickIndexToSqrtPriceX64(tickLowerIndex).addn(1); - const result = PositionUtil.getStrictPositionStatus(sqrtPriceX64, tickLowerIndex, tickUpperIndex); - assert.equal(result, PositionStatus.InRange); - }); - - it("sqrtPrice + 1 == toSqrtPrice(tickUpperIndex), InRange", async () => { - const sqrtPriceX64 = PriceMath.tickIndexToSqrtPriceX64(tickUpperIndex).subn(1); - const result = PositionUtil.getStrictPositionStatus(sqrtPriceX64, tickLowerIndex, tickUpperIndex); - assert.equal(result, PositionStatus.InRange); - }); - - it("sqrtPrice == toSqrtPrice(tickUpperIndex), AboveRange", async () => { - const sqrtPriceX64 = PriceMath.tickIndexToSqrtPriceX64(tickUpperIndex); - const result = PositionUtil.getStrictPositionStatus(sqrtPriceX64, tickLowerIndex, tickUpperIndex); - assert.equal(result, PositionStatus.AboveRange); - }); - - it("sqrtPrice - 1 == toSqrtPrice(tickUpperIndex), AboveRange", async () => { - const sqrtPriceX64 = PriceMath.tickIndexToSqrtPriceX64(tickUpperIndex).addn(1); - const result = PositionUtil.getStrictPositionStatus(sqrtPriceX64, tickLowerIndex, tickUpperIndex); - assert.equal(result, PositionStatus.AboveRange); - }); - - it("sqrtPrice > toSqrtPrice(tickUpperIndex), AboveRange", async () => { - const sqrtPriceX64 = PriceMath.tickIndexToSqrtPriceX64(192); - const result = PositionUtil.getStrictPositionStatus(sqrtPriceX64, tickLowerIndex, tickUpperIndex); - assert.equal(result, PositionStatus.AboveRange); - }); - - }); -}); diff --git a/sdk/tests/sdk/whirlpools/utils/price-math.test.ts b/sdk/tests/sdk/whirlpools/utils/price-math.test.ts deleted file mode 100644 index b5859d1..0000000 --- a/sdk/tests/sdk/whirlpools/utils/price-math.test.ts +++ /dev/null @@ -1,126 +0,0 @@ -import { MathUtil, Percentage } from "@orca-so/common-sdk"; -import assert from "assert"; -import BN from "bn.js"; -import Decimal from "decimal.js"; -import { - MAX_SQRT_PRICE_BN, - MAX_TICK_INDEX, - MIN_SQRT_PRICE_BN, - MIN_TICK_INDEX, - PriceMath, -} from "../../../../src"; - -function toSqrtPrice(n: number) { - return PriceMath.priceToSqrtPriceX64(new Decimal(n), 6, 6); -} - -const EVAL_PRECISION = 16; -const variations = [ - [MAX_SQRT_PRICE_BN, Percentage.fromFraction(0, 100), true] as const, - [MAX_SQRT_PRICE_BN, Percentage.fromFraction(1, 1000), true] as const, - [MAX_SQRT_PRICE_BN, Percentage.fromFraction(1, 100), true] as const, - [MIN_SQRT_PRICE_BN, Percentage.fromFraction(0, 1000), true] as const, - [MIN_SQRT_PRICE_BN, Percentage.fromFraction(1, 1000), true] as const, - [MIN_SQRT_PRICE_BN, Percentage.fromFraction(1, 100), true] as const, - [MIN_SQRT_PRICE_BN, Percentage.fromFraction(1, 100), true] as const, - [toSqrtPrice(5), Percentage.fromFraction(0, 1000), false] as const, - [toSqrtPrice(5), Percentage.fromFraction(1, 1000), false] as const, - [toSqrtPrice(5), Percentage.fromFraction(10, 1000), false] as const, - [toSqrtPrice(1000000), Percentage.fromFraction(0, 1000), false] as const, - [toSqrtPrice(1000000), Percentage.fromFraction(5, 1000), false] as const, - [toSqrtPrice(1000000), Percentage.fromFraction(20, 1000), false] as const, - [toSqrtPrice(61235.33), Percentage.fromFraction(0, 1000), false] as const, - [toSqrtPrice(61235.33), Percentage.fromFraction(5, 1000), false] as const, - [toSqrtPrice(61235.33), Percentage.fromFraction(20, 1000), false] as const, -]; - -function toPrecisionLevel(decimal: Decimal) { - return decimal.toSignificantDigits(EVAL_PRECISION); -} - -variations.forEach(([sqrtPrice, slippage, ignorePrecisionVerification]) => { - describe("PriceMath - getSlippageBoundForSqrtPrice tests", () => { - it(`slippage boundary for sqrt price - ${sqrtPrice.toString()}, slippage - ${slippage - .toDecimal() - .mul(100)}%`, () => { - const { lowerBound, upperBound } = PriceMath.getSlippageBoundForSqrtPrice( - sqrtPrice, - slippage, - ); - - const price = PriceMath.sqrtPriceX64ToPrice(sqrtPrice, 6, 6); - const slippageDecimal = slippage.toDecimal(); - - const expectedUpperSlippagePrice = toPrecisionLevel(price.mul(slippageDecimal.add(1))); - const expectedLowerSlippagePrice = toPrecisionLevel( - price.mul(new Decimal(1).sub(slippageDecimal)), - ); - - const expectedUpperSqrtPrice = BN.min( - BN.max(MathUtil.toX64(expectedUpperSlippagePrice.sqrt()), MIN_SQRT_PRICE_BN), - MAX_SQRT_PRICE_BN, - ); - const expectedLowerSqrtPrice = BN.min( - BN.max(MathUtil.toX64(expectedLowerSlippagePrice.sqrt()), MIN_SQRT_PRICE_BN), - MAX_SQRT_PRICE_BN, - ); - - const expectedUpperTickIndex = PriceMath.sqrtPriceX64ToTickIndex(expectedUpperSqrtPrice); - const expectedLowerTickIndex = PriceMath.sqrtPriceX64ToTickIndex(expectedLowerSqrtPrice); - - const lowerBoundSqrtPrice = lowerBound[0]; - const lowerBoundTickIndex = lowerBound[1]; - const lowerBoundPrice = toPrecisionLevel( - PriceMath.sqrtPriceX64ToPrice(lowerBoundSqrtPrice, 6, 6), - ); - - const upperBoundSqrtPrice = upperBound[0]; - const upperBoundTickIndex = upperBound[1]; - const upperBoundPrice = toPrecisionLevel( - PriceMath.sqrtPriceX64ToPrice(upperBoundSqrtPrice, 6, 6), - ); - - // For larger sqrt-price boundary values, it's difficult to verify exactly due to the precision loss. - // We will only verify that it won't crash and the upper and lower bounds are within the expected range by - // testing that the function won't crash. - if (!ignorePrecisionVerification) { - assert.ok( - lowerBoundPrice.eq(expectedLowerSlippagePrice), - `lower slippage price ${lowerBoundPrice.toString()} should equal ${expectedLowerSlippagePrice.toString()}`, - ); - assert.ok( - upperBoundPrice.eq(expectedUpperSlippagePrice), - `upper slippage price ${upperBoundPrice.toString()} should equal ${expectedUpperSlippagePrice.toString()}`, - ); - assert.ok( - expectedUpperTickIndex === upperBoundTickIndex, - `upper tick index ${upperBoundTickIndex} should equal ${expectedUpperTickIndex}`, - ); - assert.ok( - expectedLowerTickIndex === lowerBoundTickIndex, - `lower tick index ${lowerBoundTickIndex} should equal ${expectedLowerTickIndex}`, - ); - } else { - // Verify generally the conditions hold between sqrtPrices and tick indicies - assert.ok( - lowerBoundSqrtPrice.gte(MIN_SQRT_PRICE_BN) && lowerBoundSqrtPrice.lte(MAX_SQRT_PRICE_BN), - `lower bound sqrt price ${lowerBoundSqrtPrice.toString()} should be within bounds of MIN_SQRT_PRICE_BN & MAX_SQRT_PRICE_BN`, - ); - assert.ok( - upperBoundSqrtPrice.gte(MIN_SQRT_PRICE_BN) && upperBoundSqrtPrice.lte(MAX_SQRT_PRICE_BN), - `lower bound sqrt price ${upperBoundSqrtPrice.toString()} should be within bounds of MIN_SQRT_PRICE_BN & MAX_SQRT_PRICE_BN`, - ); - - assert.ok( - lowerBoundTickIndex >= MIN_TICK_INDEX && lowerBoundTickIndex <= MAX_TICK_INDEX, - `lower bound tick index ${lowerBoundTickIndex} should be within bounds of MIN_TICK_INDEX & MAX_TICK_INDEX`, - ); - - assert.ok( - upperBoundTickIndex >= MIN_TICK_INDEX && upperBoundTickIndex <= MAX_TICK_INDEX, - `upper bound tick index ${upperBoundTickIndex} should be within bounds of MIN_TICK_INDEX & MAX_TICK_INDEX`, - ); - } - }); - }); -}); diff --git a/sdk/tests/sdk/whirlpools/utils/swap-utils.test.ts b/sdk/tests/sdk/whirlpools/utils/swap-utils.test.ts deleted file mode 100644 index 23142ea..0000000 --- a/sdk/tests/sdk/whirlpools/utils/swap-utils.test.ts +++ /dev/null @@ -1,223 +0,0 @@ -import * as anchor from "@coral-xyz/anchor"; -import { Keypair } from "@solana/web3.js"; -import * as assert from "assert"; -import { PDAUtil, SwapDirection, SwapUtils, TICK_ARRAY_SIZE } from "../../../../src"; -import { WhirlpoolContext } from "../../../../src/context"; -import { defaultConfirmOptions } from "../../../utils/const"; -import { testWhirlpoolData } from "../../../utils/testDataTypes"; - -describe("SwapUtils tests", () => { - const provider = anchor.AnchorProvider.local(undefined, defaultConfirmOptions); - - const program = anchor.workspace.Whirlpool; - const ctx = WhirlpoolContext.fromWorkspace(provider, program); - - describe("getSwapDirection", () => { - it("SwapToken is tokenA and is an input", async () => { - const whirlpoolData = testWhirlpoolData; - const result = SwapUtils.getSwapDirection(whirlpoolData, whirlpoolData.tokenMintA, true); - assert.equal(result, SwapDirection.AtoB); - }); - - it("SwapToken is tokenB and is an input", async () => { - const whirlpoolData = testWhirlpoolData; - const result = SwapUtils.getSwapDirection(whirlpoolData, whirlpoolData.tokenMintB, true); - assert.equal(result, SwapDirection.BtoA); - }); - - it("SwapToken is tokenA and is not an input", async () => { - const whirlpoolData = testWhirlpoolData; - const result = SwapUtils.getSwapDirection(whirlpoolData, whirlpoolData.tokenMintA, false); - assert.equal(result, SwapDirection.BtoA); - }); - - it("SwapToken is tokenB and is not an input", async () => { - const whirlpoolData = testWhirlpoolData; - const result = SwapUtils.getSwapDirection(whirlpoolData, whirlpoolData.tokenMintB, false); - assert.equal(result, SwapDirection.AtoB); - }); - - it("SwapToken is a random mint and is an input", async () => { - const whirlpoolData = testWhirlpoolData; - const result = SwapUtils.getSwapDirection(whirlpoolData, Keypair.generate().publicKey, true); - assert.equal(result, undefined); - }); - - it("SwapToken is a random mint and is not an input", async () => { - const whirlpoolData = testWhirlpoolData; - const result = SwapUtils.getSwapDirection(whirlpoolData, Keypair.generate().publicKey, false); - assert.equal(result, undefined); - }); - }); - - describe("getTickArrayPublicKeys", () => { - it("a->b, ts = 64, tickCurrentIndex = 0", () => { - const programId = ctx.program.programId; - const whirlpoolPubkey = Keypair.generate().publicKey; - const tickSpacing = 64; - const ticksInArray = tickSpacing * TICK_ARRAY_SIZE; - const aToB = true; - const tickCurrentIndex = 0; - - const result = SwapUtils.getTickArrayPublicKeys( - tickCurrentIndex, - tickSpacing, - aToB, - ctx.program.programId, - whirlpoolPubkey, - ); - - const expected = [ - PDAUtil.getTickArray(programId, whirlpoolPubkey, ticksInArray * 0).publicKey, - PDAUtil.getTickArray(programId, whirlpoolPubkey, ticksInArray * -1).publicKey, - PDAUtil.getTickArray(programId, whirlpoolPubkey, ticksInArray * -2).publicKey, - ]; - result.forEach((k, i) => assert.equal(k.toBase58(), expected[i].toBase58())); - }); - - it("a->b, ts = 64, tickCurrentIndex = 64*TICK_ARRAY_SIZE - 64", () => { - const programId = ctx.program.programId; - const whirlpoolPubkey = Keypair.generate().publicKey; - const tickSpacing = 64; - const ticksInArray = tickSpacing * TICK_ARRAY_SIZE; - const aToB = true; - const tickCurrentIndex = tickSpacing * TICK_ARRAY_SIZE - tickSpacing; - - const result = SwapUtils.getTickArrayPublicKeys( - tickCurrentIndex, - tickSpacing, - aToB, - ctx.program.programId, - whirlpoolPubkey, - ); - - const expected = [ - PDAUtil.getTickArray(programId, whirlpoolPubkey, ticksInArray * 0).publicKey, - PDAUtil.getTickArray(programId, whirlpoolPubkey, ticksInArray * -1).publicKey, - PDAUtil.getTickArray(programId, whirlpoolPubkey, ticksInArray * -2).publicKey, - ]; - result.forEach((k, i) => assert.equal(k.toBase58(), expected[i].toBase58())); - }); - - it("a->b, ts = 64, tickCurrentIndex = 64*TICK_ARRAY_SIZE - 1", () => { - const programId = ctx.program.programId; - const whirlpoolPubkey = Keypair.generate().publicKey; - const tickSpacing = 64; - const ticksInArray = tickSpacing * TICK_ARRAY_SIZE; - const aToB = true; - const tickCurrentIndex = tickSpacing * TICK_ARRAY_SIZE - 1; - - const result = SwapUtils.getTickArrayPublicKeys( - tickCurrentIndex, - tickSpacing, - aToB, - ctx.program.programId, - whirlpoolPubkey, - ); - - const expected = [ - PDAUtil.getTickArray(programId, whirlpoolPubkey, ticksInArray * 0).publicKey, - PDAUtil.getTickArray(programId, whirlpoolPubkey, ticksInArray * -1).publicKey, - PDAUtil.getTickArray(programId, whirlpoolPubkey, ticksInArray * -2).publicKey, - ]; - result.forEach((k, i) => assert.equal(k.toBase58(), expected[i].toBase58())); - }); - - it("b->a, shifted, ts = 64, tickCurrentIndex = 0", () => { - const programId = ctx.program.programId; - const whirlpoolPubkey = Keypair.generate().publicKey; - const tickSpacing = 64; - const ticksInArray = tickSpacing * TICK_ARRAY_SIZE; - const aToB = false; - const tickCurrentIndex = 0; - - const result = SwapUtils.getTickArrayPublicKeys( - tickCurrentIndex, - tickSpacing, - aToB, - ctx.program.programId, - whirlpoolPubkey, - ); - - const expected = [ - PDAUtil.getTickArray(programId, whirlpoolPubkey, ticksInArray * 0).publicKey, - PDAUtil.getTickArray(programId, whirlpoolPubkey, ticksInArray * 1).publicKey, - PDAUtil.getTickArray(programId, whirlpoolPubkey, ticksInArray * 2).publicKey, - ]; - result.forEach((k, i) => assert.equal(k.toBase58(), expected[i].toBase58())); - }); - - it("b->a, shifted, ts = 64, tickCurrentIndex = 64*TICK_ARRAY_SIZE - 64 - 1", () => { - const programId = ctx.program.programId; - const whirlpoolPubkey = Keypair.generate().publicKey; - const tickSpacing = 64; - const ticksInArray = tickSpacing * TICK_ARRAY_SIZE; - const aToB = false; - const tickCurrentIndex = tickSpacing * TICK_ARRAY_SIZE - tickSpacing - 1; - - const result = SwapUtils.getTickArrayPublicKeys( - tickCurrentIndex, - tickSpacing, - aToB, - ctx.program.programId, - whirlpoolPubkey, - ); - - const expected = [ - PDAUtil.getTickArray(programId, whirlpoolPubkey, ticksInArray * 0).publicKey, - PDAUtil.getTickArray(programId, whirlpoolPubkey, ticksInArray * 1).publicKey, - PDAUtil.getTickArray(programId, whirlpoolPubkey, ticksInArray * 2).publicKey, - ]; - result.forEach((k, i) => assert.equal(k.toBase58(), expected[i].toBase58())); - }); - - it("b->a, shifted, ts = 64, tickCurrentIndex = 64*TICK_ARRAY_SIZE - 64", () => { - const programId = ctx.program.programId; - const whirlpoolPubkey = Keypair.generate().publicKey; - const tickSpacing = 64; - const ticksInArray = tickSpacing * TICK_ARRAY_SIZE; - const aToB = false; - const tickCurrentIndex = tickSpacing * TICK_ARRAY_SIZE - tickSpacing; - - const result = SwapUtils.getTickArrayPublicKeys( - tickCurrentIndex, - tickSpacing, - aToB, - ctx.program.programId, - whirlpoolPubkey, - ); - - const expected = [ - PDAUtil.getTickArray(programId, whirlpoolPubkey, ticksInArray * 1).publicKey, - PDAUtil.getTickArray(programId, whirlpoolPubkey, ticksInArray * 2).publicKey, - PDAUtil.getTickArray(programId, whirlpoolPubkey, ticksInArray * 3).publicKey, - ]; - result.forEach((k, i) => assert.equal(k.toBase58(), expected[i].toBase58())); - }); - - it("b->a, shifted, ts = 64, tickCurrentIndex = 64*TICK_ARRAY_SIZE - 1", () => { - const programId = ctx.program.programId; - const whirlpoolPubkey = Keypair.generate().publicKey; - const tickSpacing = 64; - const ticksInArray = tickSpacing * TICK_ARRAY_SIZE; - const aToB = false; - const tickCurrentIndex = tickSpacing * TICK_ARRAY_SIZE - 1; - - const result = SwapUtils.getTickArrayPublicKeys( - tickCurrentIndex, - tickSpacing, - aToB, - ctx.program.programId, - whirlpoolPubkey, - ); - - const expected = [ - PDAUtil.getTickArray(programId, whirlpoolPubkey, ticksInArray * 1).publicKey, - PDAUtil.getTickArray(programId, whirlpoolPubkey, ticksInArray * 2).publicKey, - PDAUtil.getTickArray(programId, whirlpoolPubkey, ticksInArray * 3).publicKey, - ]; - result.forEach((k, i) => assert.equal(k.toBase58(), expected[i].toBase58())); - }); - }); - -}); diff --git a/sdk/tests/sdk/whirlpools/utils/tick-array-sequence.test.ts b/sdk/tests/sdk/whirlpools/utils/tick-array-sequence.test.ts deleted file mode 100644 index 49f2876..0000000 --- a/sdk/tests/sdk/whirlpools/utils/tick-array-sequence.test.ts +++ /dev/null @@ -1,340 +0,0 @@ -import { TICK_ARRAY_SIZE } from "../../../../src"; -import * as assert from "assert"; -import { TickArraySequence } from "../../../../src/quotes/swap/tick-array-sequence"; -import { buildTickArrayData, testEmptyTickArrray } from "../../../utils/testDataTypes"; -import { TickArrayIndex } from "../../../../src/quotes/swap/tick-array-index"; -import { Whirlpool } from "../../../../src/artifacts/whirlpool"; -import { SwapErrorCode, WhirlpoolsError } from "../../../../src/errors/errors"; - -describe("TickArray Sequence tests", () => { - const ts64 = 64; - const ts128 = 128; - - describe("isValidTickArray0 tests", () => { - const ta0 = buildTickArrayData(0, [0, 32, 63]); - const ta1 = buildTickArrayData(ts64 * TICK_ARRAY_SIZE * -1, [0, 50]); - const ta2 = buildTickArrayData(ts64 * TICK_ARRAY_SIZE * -2, [25, 50]); - - it("a->b, |--------ta2--------|--------ta1------i-|--------ta0--------|", () => { - const seq = new TickArraySequence([ta0, ta1, ta2], ts64, true); - assert.ok(!seq.isValidTickArray0(-1 * ts64)); - }); - - it("a->b, |--------ta2--------|--------ta1-------i|--------ta0--------|", () => { - const seq = new TickArraySequence([ta0, ta1, ta2], ts64, true); - assert.ok(!seq.isValidTickArray0(-1)); - }); - - it("a->b, |--------ta2--------|--------ta1--------|i-------ta0--------|", () => { - const seq = new TickArraySequence([ta0, ta1, ta2], ts64, true); - assert.ok(seq.isValidTickArray0(0)); - }); - - it("a->b, |--------ta2--------|--------ta1--------|-i------ta0--------|", () => { - const seq = new TickArraySequence([ta0, ta1, ta2], ts64, true); - assert.ok(seq.isValidTickArray0(ts64)); - }); - - it("a->b, |--------ta2--------|--------ta1--------|--------ta0-----i--|", () => { - const seq = new TickArraySequence([ta0, ta1, ta2], ts64, true); - assert.ok(seq.isValidTickArray0(ts64 * TICK_ARRAY_SIZE - ts64 - 1)); - }); - - it("a->b, |--------ta2--------|--------ta1--------|--------ta0------i-|", () => { - const seq = new TickArraySequence([ta0, ta1, ta2], ts64, true); - assert.ok(seq.isValidTickArray0(ts64 * TICK_ARRAY_SIZE - ts64)); - }); - - it("a->b, |--------ta2--------|--------ta1--------|--------ta0-------i|", () => { - const seq = new TickArraySequence([ta0, ta1, ta2], ts64, true); - assert.ok(seq.isValidTickArray0(ts64 * TICK_ARRAY_SIZE - 1)); - }); - - it("a->b, |--------ta2--------|--------ta1--------|--------ta0--------|i", () => { - const seq = new TickArraySequence([ta0, ta1, ta2], ts64, true); - assert.ok(!seq.isValidTickArray0(ts64 * TICK_ARRAY_SIZE)); - }); - - it("b->a, i--|--------ta2--------|--------ta1--------|--------ta0--------|", () => { - const seq = new TickArraySequence([ta2, ta1, ta0], ts64, false); - const ta2StartTickIndex = ts64 * TICK_ARRAY_SIZE * -2; - assert.ok(!seq.isValidTickArray0(ta2StartTickIndex - ts64 - 1)); - }); - - it("b->a, -i-|--------ta2--------|--------ta1--------|--------ta0--------|", () => { - const seq = new TickArraySequence([ta2, ta1, ta0], ts64, false); - const ta2StartTickIndex = ts64 * TICK_ARRAY_SIZE * -2; - assert.ok(seq.isValidTickArray0(ta2StartTickIndex - ts64)); - }); - - it("b->a, --i|--------ta2--------|--------ta1--------|--------ta0--------|", () => { - const seq = new TickArraySequence([ta2, ta1, ta0], ts64, false); - const ta2StartTickIndex = ts64 * TICK_ARRAY_SIZE * -2; - assert.ok(seq.isValidTickArray0(ta2StartTickIndex - 1)); - }); - - it("b->a, ---|i-------ta2--------|--------ta1--------|--------ta0--------|", () => { - const seq = new TickArraySequence([ta2, ta1, ta0], ts64, false); - const ta2StartTickIndex = ts64 * TICK_ARRAY_SIZE * -2; - assert.ok(seq.isValidTickArray0(ta2StartTickIndex)); - }); - - it("b->a, ---|-i------ta2--------|--------ta1--------|--------ta0--------|", () => { - const seq = new TickArraySequence([ta2, ta1, ta0], ts64, false); - const ta2StartTickIndex = ts64 * TICK_ARRAY_SIZE * -2; - assert.ok(seq.isValidTickArray0(ta2StartTickIndex + ts64)); - }); - - it("b->a, ---|--------ta2-----i--|--------ta1--------|--------ta0--------|", () => { - const seq = new TickArraySequence([ta2, ta1, ta0], ts64, false); - const ta1StartTickIndex = ts64 * TICK_ARRAY_SIZE * -1; - assert.ok(seq.isValidTickArray0(ta1StartTickIndex - ts64 - 1)); - }); - - it("b->a, ---|--------ta2------i-|--------ta1--------|--------ta0--------|", () => { - const seq = new TickArraySequence([ta2, ta1, ta0], ts64, false); - const ta1StartTickIndex = ts64 * TICK_ARRAY_SIZE * -1; - assert.ok(!seq.isValidTickArray0(ta1StartTickIndex - ts64)); - }); - - it("b->a, ---|--------ta2-------i|--------ta1--------|--------ta0--------|", () => { - const seq = new TickArraySequence([ta2, ta1, ta0], ts64, false); - const ta1StartTickIndex = ts64 * TICK_ARRAY_SIZE * -1; - assert.ok(!seq.isValidTickArray0(ta1StartTickIndex - 1)); - }); - - it("b->a, ---|--------ta2--------|i-------ta1--------|--------ta0--------|", () => { - const seq = new TickArraySequence([ta2, ta1, ta0], ts64, false); - const ta1StartTickIndex = ts64 * TICK_ARRAY_SIZE * -1; - assert.ok(!seq.isValidTickArray0(ta1StartTickIndex)); - }); - }); - - describe("findNextInitializedTickIndex tests", () => { - it("a->b, search reaches left bounds", async () => { - const ta0 = buildTickArrayData(0, [0, 32, 63]); - const ta1 = buildTickArrayData(ts64 * TICK_ARRAY_SIZE * -1, [0, 50]); - const ta2 = buildTickArrayData(ts64 * TICK_ARRAY_SIZE * -2, [25, 50]); - const seq = new TickArraySequence([ta0, ta1, ta2], ts64, true); - let i = 0; - let searchIndex = new TickArrayIndex(-2, 12, ts64).toTickIndex(); - - // First traversal brings swap to the left most edge - const { nextIndex } = seq.findNextInitializedTickIndex(searchIndex); - assert.equal(nextIndex, ta2.data!.startTickIndex); - - // The next one will throw an error - assert.throws( - () => seq.findNextInitializedTickIndex(nextIndex - 1), - (err) => { - const whirlErr = err as WhirlpoolsError; - return whirlErr.errorCode === SwapErrorCode.TickArraySequenceInvalid; - } - ); - }); - - it("b->a, search reaches right bounds", async () => { - const ta0 = buildTickArrayData(0, [0, 32]); - const ta1 = buildTickArrayData(ts64 * TICK_ARRAY_SIZE * -1, [0, 50]); - const ta2 = buildTickArrayData(ts64 * TICK_ARRAY_SIZE * -2, [25, 50]); - const seq = new TickArraySequence([ta2, ta1, ta0], ts64, false); - let i = 0; - let searchIndex = new TickArrayIndex(0, 33, ts64).toTickIndex(); - - // First traversal brings swap to the right most edge - const { nextIndex } = seq.findNextInitializedTickIndex(searchIndex); - assert.equal(nextIndex, ta0.data!.startTickIndex + TICK_ARRAY_SIZE * ts64 - 1); - - // The next one will throw an error - assert.throws( - () => seq.findNextInitializedTickIndex(nextIndex), - (err) => { - const whirlErr = err as WhirlpoolsError; - return whirlErr.errorCode === SwapErrorCode.TickArraySequenceInvalid; - } - ); - }); - - it("a->b, on initializable index, ts = 64", async () => { - const ta0 = buildTickArrayData(0, [0, 32, 63]); - const ta1 = buildTickArrayData(ts64 * TICK_ARRAY_SIZE * -1, [0, 50]); - const ta2 = buildTickArrayData(ts64 * TICK_ARRAY_SIZE * -2, [25, 50]); - const seq = new TickArraySequence([ta0, ta1, ta2], ts64, true); - let i = 0; - let searchIndex = new TickArrayIndex(0, 32, ts64).toTickIndex(); - const expectedIndicies = [ - new TickArrayIndex(0, 32, ts64).toTickIndex(), - new TickArrayIndex(0, 0, ts64).toTickIndex(), - new TickArrayIndex(-1, 50, ts64).toTickIndex(), - new TickArrayIndex(-1, 0, ts64).toTickIndex(), - new TickArrayIndex(-2, 50, ts64).toTickIndex(), - new TickArrayIndex(-2, 25, ts64).toTickIndex(), - ta2.data!.startTickIndex, // Last index in array 3 - ]; - - expectedIndicies.forEach((expectedIndex, expectedResultIndex) => { - const { nextIndex, nextTickData } = seq.findNextInitializedTickIndex(searchIndex)!; - if (expectedResultIndex === expectedIndicies.length - 1) { - assert.equal(nextIndex, expectedIndex); - assert.ok(nextTickData === null); - } else { - assert.equal(nextIndex, expectedIndex); - assert.ok(nextTickData!.initialized); - } - searchIndex = nextIndex - 1; - }); - }); - - it("a->b, on initializable index, ts = 64", async () => { - const ta0 = buildTickArrayData(0, [0, 32, 63]); - const ta1 = buildTickArrayData(ts64 * TICK_ARRAY_SIZE * -1, [0, 50]); - const ta2 = buildTickArrayData(ts64 * TICK_ARRAY_SIZE * -2, [25, 50]); - const seq = new TickArraySequence([ta0, ta1, ta2], ts64, true); - let i = 0; - let searchIndex = new TickArrayIndex(0, 32, ts64).toTickIndex(); - const expectedIndicies = [ - new TickArrayIndex(0, 32, ts64).toTickIndex(), - new TickArrayIndex(0, 0, ts64).toTickIndex(), - new TickArrayIndex(-1, 50, ts64).toTickIndex(), - new TickArrayIndex(-1, 0, ts64).toTickIndex(), - new TickArrayIndex(-2, 50, ts64).toTickIndex(), - new TickArrayIndex(-2, 25, ts64).toTickIndex(), - ta2.data!.startTickIndex, // Last index in array 3 - ]; - - expectedIndicies.forEach((expectedIndex, expectedResultIndex) => { - const { nextIndex, nextTickData } = seq.findNextInitializedTickIndex(searchIndex)!; - if (expectedResultIndex === expectedIndicies.length - 1) { - assert.equal(nextIndex, expectedIndex); - assert.ok(nextTickData === null); - } else { - assert.equal(nextIndex, expectedIndex); - assert.ok(nextTickData!.initialized); - } - searchIndex = nextIndex - 1; - }); - }); - - it("b->a, not on initializable index, ts = 128", async () => { - const ta0 = buildTickArrayData(0, [0, 32, 63]); - const ta1 = buildTickArrayData(ts128 * TICK_ARRAY_SIZE, [0, 50]); - const ta2 = buildTickArrayData(ts128 * TICK_ARRAY_SIZE * 2, [25, 50]); - const seq = new TickArraySequence([ta0, ta1, ta2], ts128, false); - let i = 0; - let searchIndex = new TickArrayIndex(0, 25, ts128).toTickIndex() + 64; - const expectedIndicies = [ - new TickArrayIndex(0, 32, ts128).toTickIndex(), - new TickArrayIndex(0, 63, ts128).toTickIndex(), - new TickArrayIndex(1, 0, ts128).toTickIndex(), - new TickArrayIndex(1, 50, ts128).toTickIndex(), - new TickArrayIndex(2, 25, ts128).toTickIndex(), - new TickArrayIndex(2, 50, ts128).toTickIndex(), - ta2.data!.startTickIndex + TICK_ARRAY_SIZE * ts128 - 1, // Last index in array 3 - ]; - - expectedIndicies.forEach((expectedIndex, expectedResultIndex) => { - const { nextIndex, nextTickData } = seq.findNextInitializedTickIndex(searchIndex)!; - if (expectedResultIndex === expectedIndicies.length - 1) { - assert.equal(nextIndex, expectedIndex); - assert.ok(nextTickData === null); - } else { - assert.equal(nextIndex, expectedIndex); - assert.ok(nextTickData!.initialized); - } - searchIndex = nextIndex; - }); - }); - - it("b->a, on initializable index, ts = 64", async () => { - const ta0 = buildTickArrayData(0, [0, 32, 63]); - const ta1 = buildTickArrayData(ts64 * TICK_ARRAY_SIZE, [0, 50]); - const ta2 = buildTickArrayData(ts64 * TICK_ARRAY_SIZE * 2, [25, 50]); - const seq = new TickArraySequence([ta0, ta1, ta2], ts64, false); - let i = 0; - let searchIndex = new TickArrayIndex(0, 25, ts64).toTickIndex(); - const expectedIndicies = [ - new TickArrayIndex(0, 32, ts64).toTickIndex(), - new TickArrayIndex(0, 63, ts64).toTickIndex(), - new TickArrayIndex(1, 0, ts64).toTickIndex(), - new TickArrayIndex(1, 50, ts64).toTickIndex(), - new TickArrayIndex(2, 25, ts64).toTickIndex(), - new TickArrayIndex(2, 50, ts64).toTickIndex(), - ta2.data!.startTickIndex + TICK_ARRAY_SIZE * ts64 - 1, // Last index in array 3 - ]; - - expectedIndicies.forEach((expectedIndex, expectedResultIndex) => { - const { nextIndex, nextTickData } = seq.findNextInitializedTickIndex(searchIndex)!; - if (expectedResultIndex === expectedIndicies.length - 1) { - assert.equal(nextIndex, expectedIndex); - assert.ok(nextTickData === null); - } else { - assert.equal(nextIndex, expectedIndex); - assert.ok(nextTickData!.initialized); - } - searchIndex = nextIndex; - }); - }); - - it("b->a, on initializable index, ts = 64, currentTickIndex = -64, shifted", async () => { - const ta0 = buildTickArrayData(0, [0, 32, 63]); - const ta1 = buildTickArrayData(ts64 * TICK_ARRAY_SIZE, [0, 50]); - const ta2 = buildTickArrayData(ts64 * TICK_ARRAY_SIZE * 2, [25, 50]); - const seq = new TickArraySequence([ta0, ta1, ta2], ts64, false); - let i = 0; - let searchIndex = -1 * ts64; - const expectedIndicies = [ - new TickArrayIndex(0, 0, ts64).toTickIndex(), - new TickArrayIndex(0, 32, ts64).toTickIndex(), - new TickArrayIndex(0, 63, ts64).toTickIndex(), - new TickArrayIndex(1, 0, ts64).toTickIndex(), - new TickArrayIndex(1, 50, ts64).toTickIndex(), - new TickArrayIndex(2, 25, ts64).toTickIndex(), - new TickArrayIndex(2, 50, ts64).toTickIndex(), - ta2.data!.startTickIndex + TICK_ARRAY_SIZE * ts64 - 1, // Last index in array 3 - ]; - - expectedIndicies.forEach((expectedIndex, expectedResultIndex) => { - const { nextIndex, nextTickData } = seq.findNextInitializedTickIndex(searchIndex)!; - if (expectedResultIndex === expectedIndicies.length - 1) { - assert.equal(nextIndex, expectedIndex); - assert.ok(nextTickData === null); - } else { - assert.equal(nextIndex, expectedIndex); - assert.ok(nextTickData!.initialized); - } - searchIndex = nextIndex; - }); - }); - - it("b->a, on initializable index, ts = 64, currentTickIndex = -1, shifted", async () => { - const ta0 = buildTickArrayData(0, [0, 32, 63]); - const ta1 = buildTickArrayData(ts64 * TICK_ARRAY_SIZE, [0, 50]); - const ta2 = buildTickArrayData(ts64 * TICK_ARRAY_SIZE * 2, [25, 50]); - const seq = new TickArraySequence([ta0, ta1, ta2], ts64, false); - let i = 0; - let searchIndex = -1; - const expectedIndicies = [ - new TickArrayIndex(0, 0, ts64).toTickIndex(), - new TickArrayIndex(0, 32, ts64).toTickIndex(), - new TickArrayIndex(0, 63, ts64).toTickIndex(), - new TickArrayIndex(1, 0, ts64).toTickIndex(), - new TickArrayIndex(1, 50, ts64).toTickIndex(), - new TickArrayIndex(2, 25, ts64).toTickIndex(), - new TickArrayIndex(2, 50, ts64).toTickIndex(), - ta2.data!.startTickIndex + TICK_ARRAY_SIZE * ts64 - 1, // Last index in array 3 - ]; - - expectedIndicies.forEach((expectedIndex, expectedResultIndex) => { - const { nextIndex, nextTickData } = seq.findNextInitializedTickIndex(searchIndex)!; - if (expectedResultIndex === expectedIndicies.length - 1) { - assert.equal(nextIndex, expectedIndex); - assert.ok(nextTickData === null); - } else { - assert.equal(nextIndex, expectedIndex); - assert.ok(nextTickData!.initialized); - } - searchIndex = nextIndex; - }); - }); - }); -}); diff --git a/sdk/tests/sdk/whirlpools/utils/tick-utils.test.ts b/sdk/tests/sdk/whirlpools/utils/tick-utils.test.ts deleted file mode 100644 index ad55d5e..0000000 --- a/sdk/tests/sdk/whirlpools/utils/tick-utils.test.ts +++ /dev/null @@ -1,61 +0,0 @@ -import * as assert from "assert"; -import { TickUtil, MIN_TICK_INDEX, MAX_TICK_INDEX } from "../../../../src"; - -describe("TickUtil tests", () => { - describe("getFullRangeTickIndex", () => { - function checkGetFullRangeTickIndex(tickSpacing: number, minMaxAbs: number) { - const [min, max] = TickUtil.getFullRangeTickIndex(tickSpacing); - assert.equal(min, -minMaxAbs); - assert.equal(max, +minMaxAbs); - assert.ok(-minMaxAbs - tickSpacing < MIN_TICK_INDEX); - assert.ok(+minMaxAbs + tickSpacing > MAX_TICK_INDEX); - } - - it("tickSpacing = 1", async () => { - const [min, max] = TickUtil.getFullRangeTickIndex(1); - assert.equal(min, MIN_TICK_INDEX); - assert.equal(max, MAX_TICK_INDEX); - }); - - it("tickSpacing = 8", async () => { - checkGetFullRangeTickIndex(8, 443632); - }); - - it("tickSpacing = 64", async () => { - checkGetFullRangeTickIndex(64, 443584); - }); - - it("tickSpacing = 128", async () => { - checkGetFullRangeTickIndex(128, 443520); - }); - }); - - describe("isFullRange", () => { - function checkIsFullRange(tickSpacing: number) { - const [min, max] = TickUtil.getFullRangeTickIndex(tickSpacing); - - assert.ok(TickUtil.isFullRange(tickSpacing, min, max)); - - for (let minShift = -1; minShift <= 1; minShift++) { - for (let maxShift = -1; maxShift <= 1; maxShift++) { - const isFullRange = minShift === 0 && maxShift === 0; - - assert.equal( - TickUtil.isFullRange( - tickSpacing, - min + minShift * tickSpacing, - max + maxShift * tickSpacing - ), - isFullRange - ); - } - } - } - - it("tickSpacing = [1, 2, 4, 8, ...., 128, 256]", async () => { - for (let tickSpacing = 1; tickSpacing <= 256; tickSpacing *= 2) { - checkIsFullRange(tickSpacing); - } - }); - }); -}); diff --git a/sdk/tests/sdk/whirlpools/whirlpool-client-impl.test.ts b/sdk/tests/sdk/whirlpools/whirlpool-client-impl.test.ts deleted file mode 100644 index 7505ad6..0000000 --- a/sdk/tests/sdk/whirlpools/whirlpool-client-impl.test.ts +++ /dev/null @@ -1,135 +0,0 @@ -import * as anchor from "@coral-xyz/anchor"; -import * as assert from "assert"; -import Decimal from "decimal.js"; -import { - buildWhirlpoolClient, - InitPoolParams, - PDAUtil, - PriceMath, - TickUtil, - WhirlpoolContext -} from "../../../src"; -import { IGNORE_CACHE } from "../../../src/network/public/fetcher"; -import { ONE_SOL, systemTransferTx, TickSpacing } from "../../utils"; -import { defaultConfirmOptions } from "../../utils/const"; -import { buildTestPoolParams } from "../../utils/init-utils"; - -describe("whirlpool-client-impl", () => { - const provider = anchor.AnchorProvider.local(undefined, defaultConfirmOptions); - - const program = anchor.workspace.Whirlpool; - const ctx = WhirlpoolContext.fromWorkspace(provider, program); - const client = buildWhirlpoolClient(ctx); - - let funderKeypair: anchor.web3.Keypair; - let poolInitInfo: InitPoolParams; - beforeEach(async () => { - funderKeypair = anchor.web3.Keypair.generate(); - await systemTransferTx(provider, funderKeypair.publicKey, ONE_SOL).buildAndExecute(); - poolInitInfo = ( - await buildTestPoolParams( - ctx, - TickSpacing.Standard, - 3000, - PriceMath.priceToSqrtPriceX64(new Decimal(100), 6, 6), - funderKeypair.publicKey - ) - ).poolInitInfo; - }); - - it("successfully creates a new whirpool account and initial tick array account", async () => { - const initalTick = TickUtil.getInitializableTickIndex( - PriceMath.sqrtPriceX64ToTickIndex(poolInitInfo.initSqrtPrice), - poolInitInfo.tickSpacing - ); - - const { poolKey: actualPubkey, tx } = await client.createPool( - poolInitInfo.whirlpoolsConfig, - poolInitInfo.tokenMintA, - poolInitInfo.tokenMintB, - poolInitInfo.tickSpacing, - initalTick, - funderKeypair.publicKey - ); - - const expectedPda = PDAUtil.getWhirlpool( - ctx.program.programId, - poolInitInfo.whirlpoolsConfig, - poolInitInfo.tokenMintA, - poolInitInfo.tokenMintB, - poolInitInfo.tickSpacing - ); - - const startTickArrayPda = PDAUtil.getTickArrayFromTickIndex( - initalTick, - poolInitInfo.tickSpacing, - expectedPda.publicKey, - ctx.program.programId - ); - - assert.ok(expectedPda.publicKey.equals(actualPubkey)); - - const [whirlpoolAccountBefore, tickArrayAccountBefore] = await Promise.all([ - ctx.fetcher.getPool(expectedPda.publicKey, IGNORE_CACHE), - ctx.fetcher.getTickArray(startTickArrayPda.publicKey, IGNORE_CACHE), - ]); - - assert.ok(whirlpoolAccountBefore === null); - assert.ok(tickArrayAccountBefore === null); - - await tx.addSigner(funderKeypair).buildAndExecute(); - - const [whirlpoolAccountAfter, tickArrayAccountAfter] = await Promise.all([ - ctx.fetcher.getPool(expectedPda.publicKey, IGNORE_CACHE), - ctx.fetcher.getTickArray(startTickArrayPda.publicKey, IGNORE_CACHE), - ]); - - assert.ok(whirlpoolAccountAfter !== null); - assert.ok(tickArrayAccountAfter !== null); - - assert.ok(whirlpoolAccountAfter.feeGrowthGlobalA.eqn(0)); - assert.ok(whirlpoolAccountAfter.feeGrowthGlobalB.eqn(0)); - assert.ok(whirlpoolAccountAfter.feeRate === 3000); - assert.ok(whirlpoolAccountAfter.liquidity.eqn(0)); - assert.ok(whirlpoolAccountAfter.protocolFeeOwedA.eqn(0)); - assert.ok(whirlpoolAccountAfter.protocolFeeOwedB.eqn(0)); - assert.ok(whirlpoolAccountAfter.protocolFeeRate === 300); - assert.ok(whirlpoolAccountAfter.rewardInfos.length === 3); - assert.ok(whirlpoolAccountAfter.rewardLastUpdatedTimestamp.eqn(0)); - assert.ok(whirlpoolAccountAfter.sqrtPrice.eq(PriceMath.tickIndexToSqrtPriceX64(initalTick))); - assert.ok(whirlpoolAccountAfter.tickCurrentIndex === initalTick); - assert.ok(whirlpoolAccountAfter.tickSpacing === poolInitInfo.tickSpacing); - assert.ok(whirlpoolAccountAfter.tokenMintA.equals(poolInitInfo.tokenMintA)); - assert.ok(whirlpoolAccountAfter.tokenMintB.equals(poolInitInfo.tokenMintB)); - assert.ok(whirlpoolAccountAfter.whirlpoolBump[0] === expectedPda.bump); - assert.ok(whirlpoolAccountAfter.whirlpoolsConfig.equals(poolInitInfo.whirlpoolsConfig)); - - assert.ok( - tickArrayAccountAfter.startTickIndex === - TickUtil.getStartTickIndex(initalTick, poolInitInfo.tickSpacing) - ); - assert.ok(tickArrayAccountAfter.ticks.length > 0); - assert.ok(tickArrayAccountAfter.whirlpool.equals(expectedPda.publicKey)); - }); - - it("throws an error when token order is incorrect", async () => { - const initalTick = TickUtil.getInitializableTickIndex( - PriceMath.sqrtPriceX64ToTickIndex(poolInitInfo.initSqrtPrice), - poolInitInfo.tickSpacing - ); - - const invInitialTick = TickUtil.invertTick(initalTick); - - await assert.rejects( - client.createPool( - poolInitInfo.whirlpoolsConfig, - poolInitInfo.tokenMintB, - poolInitInfo.tokenMintA, - poolInitInfo.tickSpacing, - invInitialTick, - funderKeypair.publicKey - ), - /Token order needs to be flipped to match the canonical ordering \(i.e. sorted on the byte repr. of the mint pubkeys\)/ - ); - }); -}); diff --git a/sdk/tests/sdk/whirlpools/whirlpool-impl#closePosition.test.ts b/sdk/tests/sdk/whirlpools/whirlpool-impl#closePosition.test.ts deleted file mode 100644 index 3493c08..0000000 --- a/sdk/tests/sdk/whirlpools/whirlpool-impl#closePosition.test.ts +++ /dev/null @@ -1,672 +0,0 @@ -import * as anchor from "@coral-xyz/anchor"; -import { MathUtil, Percentage } from "@orca-so/common-sdk"; -import { Account, getAssociatedTokenAddressSync } from "@solana/spl-token"; -import * as assert from "assert"; -import { BN } from "bn.js"; -import Decimal from "decimal.js"; -import { - NUM_REWARDS, - PDAUtil, Whirlpool, - WhirlpoolClient, - WhirlpoolContext, - buildWhirlpoolClient, - collectFeesQuote, - collectRewardsQuote, - decreaseLiquidityQuoteByLiquidity -} from "../../../src"; -import { IGNORE_CACHE } from "../../../src/network/public/fetcher"; -import { TickSpacing, ZERO_BN, createAssociatedTokenAccount, sleep, transferToken } from "../../utils"; -import { defaultConfirmOptions } from "../../utils/const"; -import { WhirlpoolTestFixture } from "../../utils/fixture"; - -interface SharedTestContext { - provider: anchor.AnchorProvider; - program: Whirlpool; - whirlpoolCtx: WhirlpoolContext; - whirlpoolClient: WhirlpoolClient; -} - -describe("WhirlpoolImpl#closePosition()", () => { - let testCtx: SharedTestContext; - const tickLowerIndex = 29440; - const tickUpperIndex = 33536; - const vaultStartBalance = 1_000_000; - const tickSpacing = TickSpacing.Standard; - const liquidityAmount = new BN(10_000_000); - - before(() => { - const provider = anchor.AnchorProvider.local(undefined, defaultConfirmOptions); - - anchor.setProvider(provider); - const program = anchor.workspace.Whirlpool; - const whirlpoolCtx = WhirlpoolContext.fromWorkspace(provider, program); - const whirlpoolClient = buildWhirlpoolClient(whirlpoolCtx); - - testCtx = { - provider, - program, - whirlpoolCtx, - whirlpoolClient, - }; - }); - - async function accrueFeesAndRewards(fixture: WhirlpoolTestFixture) { - const ctx = testCtx.whirlpoolCtx; - const { poolInitInfo } = fixture.getInfos(); - const { whirlpoolClient } = testCtx; - const { whirlpoolPda } = poolInitInfo; - const tickArrayPda = PDAUtil.getTickArray(ctx.program.programId, whirlpoolPda.publicKey, 22528); - - // Accrue fees in token A - const pool = await whirlpoolClient.getPool(whirlpoolPda.publicKey, IGNORE_CACHE); - await (await pool.swap({ - amount: new BN(200_000), - amountSpecifiedIsInput: true, - sqrtPriceLimit: MathUtil.toX64(new Decimal(4)), - otherAmountThreshold: ZERO_BN, - aToB: true, - tickArray0: tickArrayPda.publicKey, - tickArray1: tickArrayPda.publicKey, - tickArray2: tickArrayPda.publicKey, - })).buildAndExecute() - - // Accrue fees in token B - await (await pool.swap({ - amount: new BN(200_000), - otherAmountThreshold: ZERO_BN, - sqrtPriceLimit: MathUtil.toX64(new Decimal(5)), - amountSpecifiedIsInput: true, - aToB: false, - tickArray0: tickArrayPda.publicKey, - tickArray1: tickArrayPda.publicKey, - tickArray2: tickArrayPda.publicKey, - })).buildAndExecute() - - // accrue rewards - await sleep(1200); - } - - async function removeLiquidity(fixture: WhirlpoolTestFixture) { - const { - poolInitInfo, - positions: [positionInfo], - } = fixture.getInfos(); - const position = await testCtx.whirlpoolClient.getPosition(positionInfo.publicKey, IGNORE_CACHE); - const pool = await testCtx.whirlpoolClient.getPool(poolInitInfo.whirlpoolPda.publicKey, IGNORE_CACHE); - - - const liquidityCollectedQuote = await decreaseLiquidityQuoteByLiquidity( - position.getData().liquidity, - Percentage.fromDecimal(new Decimal(0)), - position, - pool - ); - - const tx = await position.decreaseLiquidity(liquidityCollectedQuote); - - await tx.buildAndExecute(); - } - - async function collectFees(fixture: WhirlpoolTestFixture) { - const { positions } = fixture.getInfos(); - const { whirlpoolClient } = testCtx; - const position = await whirlpoolClient.getPosition(positions[0].publicKey, IGNORE_CACHE); - const hasL = !position.getData().liquidity.isZero() - await (await position.collectFees(hasL)).buildAndExecute(); - } - - async function collectRewards(fixture: WhirlpoolTestFixture) { - const { positions } = fixture.getInfos(); - const { whirlpoolClient } = testCtx; - const position = await whirlpoolClient.getPosition(positions[0].publicKey, IGNORE_CACHE); - await (await position.collectRewards(undefined, true)).buildAndExecute(); - } - - async function testClosePosition(fixture: WhirlpoolTestFixture, isWSOLTest = false) { - const { positions, poolInitInfo, rewards } = fixture.getInfos(); - const { whirlpoolClient } = testCtx; - const ctx = whirlpoolClient.getContext(); - const otherWallet = anchor.web3.Keypair.generate(); - - const pool = await whirlpoolClient.getPool(poolInitInfo.whirlpoolPda.publicKey, IGNORE_CACHE); - const position = await whirlpoolClient.getPosition(positions[0].publicKey, IGNORE_CACHE); - const preClosePoolData = pool.getData(); - const positionAccountBalance = await ctx.connection.getBalance(positions[0].publicKey); - - const txs = await pool.closePosition( - position.getAddress(), - Percentage.fromFraction(10, 100), - otherWallet.publicKey, - undefined, - ctx.wallet.publicKey - ); - - // TODO: Our createWSOLAccountInstructions ignores payer and requires destinationWallet to sign - // We can remove this once we move to syncNative and wSOL becomes another ATA to handle. - if (isWSOLTest) { - txs[txs.length - 1].addSigner(otherWallet) - } - - for (const tx of txs) { - await tx.buildAndExecute(); - } - - // Verify liquidity and fees collected - const liquidityCollectedQuote = decreaseLiquidityQuoteByLiquidity( - position.getData().liquidity, - Percentage.fromDecimal(new Decimal(0)), - position, - pool - ); - - const feeQuote = collectFeesQuote({ - position: position.getData(), - whirlpool: pool.getData(), - tickLower: position.getLowerTickData(), - tickUpper: position.getUpperTickData(), - }); - const accountAPubkey = getAssociatedTokenAddressSync(poolInitInfo.tokenMintA, otherWallet.publicKey); - const accountA = (await ctx.fetcher.getTokenInfo(accountAPubkey, IGNORE_CACHE)) as Account; - const expectAmountA = liquidityCollectedQuote.tokenMinA.add(feeQuote.feeOwedA); - if (isWSOLTest) { - // If this is a WSOL test, we have to account for account rent retrieval - const solInOtherWallet = await ctx.connection.getBalance(otherWallet.publicKey); - const minAccountExempt = await ctx.fetcher.getAccountRentExempt(); - const expectedReceivedSol = liquidityCollectedQuote.tokenMinA - .add(feeQuote.feeOwedA) - .add(new BN(positionAccountBalance)) - .add(new BN(minAccountExempt)) - .add(new BN(minAccountExempt)) - .toNumber(); - assert.equal(solInOtherWallet, expectedReceivedSol); - } else if (expectAmountA.isZero()) { - assert.ok(!accountA || accountA.amount === 0n); - } else { - assert.equal( - accountA?.amount.toString(), - expectAmountA.toString() - ); - } - - const accountBPubkey = getAssociatedTokenAddressSync(poolInitInfo.tokenMintB, otherWallet.publicKey); - const accountB = await ctx.fetcher.getTokenInfo(accountBPubkey, IGNORE_CACHE); - const expectAmountB = liquidityCollectedQuote.tokenMinB.add(feeQuote.feeOwedB); - if (expectAmountB.isZero()) { - assert.ok(!accountB || accountB.amount === 0n); - } else { - assert.equal( - accountB?.amount.toString(), - expectAmountB.toString() - ); - } - - // Verify reward collected. We use the same timestamp that the closePosition call used to collectRewards. - const postClosePoolData = await pool.refreshData(); - const rewardQuote = collectRewardsQuote({ - position: position.getData(), - whirlpool: preClosePoolData, - tickLower: position.getLowerTickData(), - tickUpper: position.getUpperTickData(), - timeStampInSeconds: postClosePoolData.rewardLastUpdatedTimestamp, - }); - for (let i = 0; i < NUM_REWARDS; i++) { - if (!!rewards[i]) { - const rewardATA = getAssociatedTokenAddressSync(rewards[i].rewardMint, otherWallet.publicKey); - const rewardTokenAccount = await ctx.fetcher.getTokenInfo(rewardATA, IGNORE_CACHE); - assert.equal(rewardTokenAccount?.amount.toString(), rewardQuote[i]?.toString()); - } - } - } - - context("when the whirlpool is SPL-only", () => { - it("should close a position with no liquidity, fees, or rewards", async () => { - const fixture = await new WhirlpoolTestFixture(testCtx.whirlpoolCtx).init({ - tickSpacing, - positions: [ - { tickLowerIndex, tickUpperIndex, liquidityAmount }, // In range position - ], - }); - - await removeLiquidity(fixture); - await testClosePosition(fixture); - }); - - it("should close a position with only liquidity", async () => { - const fixture = await new WhirlpoolTestFixture(testCtx.whirlpoolCtx).init({ - tickSpacing, - positions: [ - { tickLowerIndex, tickUpperIndex, liquidityAmount }, // In range position - ], - }); - - await testClosePosition(fixture); - }); - - it("should close a position with only fees", async () => { - const fixture = await new WhirlpoolTestFixture(testCtx.whirlpoolCtx).init({ - tickSpacing, - positions: [ - { tickLowerIndex, tickUpperIndex, liquidityAmount }, // In range position - ], - }); - - await accrueFeesAndRewards(fixture); - await removeLiquidity(fixture); - await testClosePosition(fixture); - }); - - it("should close a position with only rewards", async () => { - const fixture = await new WhirlpoolTestFixture(testCtx.whirlpoolCtx).init({ - tickSpacing, - positions: [ - { tickLowerIndex, tickUpperIndex, liquidityAmount }, // In range position - ], - rewards: [ - { - emissionsPerSecondX64: MathUtil.toX64(new Decimal(10)), - vaultAmount: new BN(vaultStartBalance), - }, - { - emissionsPerSecondX64: MathUtil.toX64(new Decimal(10)), - vaultAmount: new BN(vaultStartBalance), - }, - { - emissionsPerSecondX64: MathUtil.toX64(new Decimal(10)), - vaultAmount: new BN(vaultStartBalance), - }, - ], - }); - - // accrue rewards - // closePosition does not attempt to create an ATA unless reward has accumulated. - await sleep(1200); - - await removeLiquidity(fixture); - await collectFees(fixture); - await testClosePosition(fixture); - }); - - it("should close a position with only liquidity and fees", async () => { - const fixture = await new WhirlpoolTestFixture(testCtx.whirlpoolCtx).init({ - tickSpacing, - positions: [ - { tickLowerIndex, tickUpperIndex, liquidityAmount }, // In range position - ], - }); - - await accrueFeesAndRewards(fixture); - await testClosePosition(fixture); - }); - - it("should close a position with only liquidity and rewards", async () => { - const fixture = await new WhirlpoolTestFixture(testCtx.whirlpoolCtx).init({ - tickSpacing, - positions: [ - { tickLowerIndex, tickUpperIndex, liquidityAmount }, // In range position - ], - rewards: [ - { - emissionsPerSecondX64: MathUtil.toX64(new Decimal(10)), - vaultAmount: new BN(vaultStartBalance), - }, - { - emissionsPerSecondX64: MathUtil.toX64(new Decimal(10)), - vaultAmount: new BN(vaultStartBalance), - }, - { - emissionsPerSecondX64: MathUtil.toX64(new Decimal(10)), - vaultAmount: new BN(vaultStartBalance), - }, - ], - }); - - // accrue rewards - // closePosition does not attempt to create an ATA unless reward has accumulated. - await sleep(1200); - - await testClosePosition(fixture); - }); - - it("should close a position with only fees and rewards", async () => { - const fixture = await new WhirlpoolTestFixture(testCtx.whirlpoolCtx).init({ - tickSpacing, - positions: [ - { tickLowerIndex, tickUpperIndex, liquidityAmount }, // In range position - ], - rewards: [ - { - emissionsPerSecondX64: MathUtil.toX64(new Decimal(10)), - vaultAmount: new BN(vaultStartBalance), - }, - { - emissionsPerSecondX64: MathUtil.toX64(new Decimal(10)), - vaultAmount: new BN(vaultStartBalance), - }, - { - emissionsPerSecondX64: MathUtil.toX64(new Decimal(10)), - vaultAmount: new BN(vaultStartBalance), - }, - ], - }); - - await accrueFeesAndRewards(fixture); - await removeLiquidity(fixture); - await testClosePosition(fixture); - }); - - it("should close a position with liquidity, fees, and rewards", async () => { - const fixture = await new WhirlpoolTestFixture(testCtx.whirlpoolCtx).init({ - tickSpacing, - positions: [ - { tickLowerIndex, tickUpperIndex, liquidityAmount }, // In range position - ], - rewards: [ - { - emissionsPerSecondX64: MathUtil.toX64(new Decimal(10)), - vaultAmount: new BN(vaultStartBalance), - }, - { - emissionsPerSecondX64: MathUtil.toX64(new Decimal(10)), - vaultAmount: new BN(vaultStartBalance), - }, - { - emissionsPerSecondX64: MathUtil.toX64(new Decimal(10)), - vaultAmount: new BN(vaultStartBalance), - }, - ], - }); - - await accrueFeesAndRewards(fixture); - await testClosePosition(fixture); - }); - - it("should close a position with liquidity, fees, and rewards (no ATAs)", async () => { - const ctx = testCtx.whirlpoolCtx; - const fixture = await new WhirlpoolTestFixture(testCtx.whirlpoolCtx).init({ - tickSpacing, - positions: [ - { tickLowerIndex, tickUpperIndex, liquidityAmount }, // In range position - ], - rewards: [ - { - emissionsPerSecondX64: MathUtil.toX64(new Decimal(10)), - vaultAmount: new BN(vaultStartBalance), - }, - { - emissionsPerSecondX64: MathUtil.toX64(new Decimal(10)), - vaultAmount: new BN(vaultStartBalance), - }, - { - emissionsPerSecondX64: MathUtil.toX64(new Decimal(10)), - vaultAmount: new BN(vaultStartBalance), - }, - ], - }); - - const otherWallet = anchor.web3.Keypair.generate(); - const positionData = fixture.getInfos().positions[0]; - - const position = await testCtx.whirlpoolClient.getPosition(positionData.publicKey, IGNORE_CACHE); - - const walletPositionTokenAccount = getAssociatedTokenAddressSync( - positionData.mintKeypair.publicKey, - testCtx.whirlpoolCtx.wallet.publicKey, - ); - - const newOwnerPositionTokenAccount = await createAssociatedTokenAccount( - ctx.provider, - positionData.mintKeypair.publicKey, - otherWallet.publicKey, - ctx.wallet.publicKey - ); - - await accrueFeesAndRewards(fixture); - await transferToken(testCtx.provider, walletPositionTokenAccount, newOwnerPositionTokenAccount, 1); - - const { poolInitInfo } = fixture.getInfos(); - - const pool = await testCtx.whirlpoolClient.getPool(poolInitInfo.whirlpoolPda.publicKey); - - const positionDataBefore = await testCtx.whirlpoolCtx.fetcher.getPosition( - position.getAddress(), - IGNORE_CACHE - ); - - assert.notEqual(positionDataBefore, null); - - const txs = await pool.closePosition( - position.getAddress(), - Percentage.fromFraction(10, 100), - otherWallet.publicKey, - otherWallet.publicKey, - ctx.wallet.publicKey - ); - - txs[txs.length - 1].addSigner(otherWallet) - - for (const tx of txs) { - await tx.buildAndExecute(); - } - - const positionDataAfter = await testCtx.whirlpoolCtx.fetcher.getPosition( - position.getAddress(), - IGNORE_CACHE - ); - - assert.equal(positionDataAfter, null); - }); - }); - - context("when the whirlpool is SOL-SPL", () => { - it("should close a position with liquidity, fees, and rewards", async () => { - const fixture = await new WhirlpoolTestFixture(testCtx.whirlpoolCtx).init({ - tickSpacing, - positions: [ - { tickLowerIndex, tickUpperIndex, liquidityAmount }, // In range position - ], - rewards: [ - { - emissionsPerSecondX64: MathUtil.toX64(new Decimal(10)), - vaultAmount: new BN(vaultStartBalance), - }, - { - emissionsPerSecondX64: MathUtil.toX64(new Decimal(10)), - vaultAmount: new BN(vaultStartBalance), - }, - { - emissionsPerSecondX64: MathUtil.toX64(new Decimal(10)), - vaultAmount: new BN(vaultStartBalance), - }, - ], - tokenAIsNative: true, - }); - - await accrueFeesAndRewards(fixture); - await testClosePosition(fixture, true); - }); - - it("should close a position with liquidity, fees, and rewards (no ATA)", async () => { - const ctx = testCtx.whirlpoolCtx; - const fixture = await new WhirlpoolTestFixture(testCtx.whirlpoolCtx).init({ - tickSpacing, - positions: [ - { tickLowerIndex, tickUpperIndex, liquidityAmount }, // In range position - ], - rewards: [ - { - emissionsPerSecondX64: MathUtil.toX64(new Decimal(10)), - vaultAmount: new BN(vaultStartBalance), - }, - { - emissionsPerSecondX64: MathUtil.toX64(new Decimal(10)), - vaultAmount: new BN(vaultStartBalance), - }, - { - emissionsPerSecondX64: MathUtil.toX64(new Decimal(10)), - vaultAmount: new BN(vaultStartBalance), - }, - ], - tokenAIsNative: true, - }); - - const otherWallet = anchor.web3.Keypair.generate(); - const positionData = fixture.getInfos().positions[0]; - - const position = await testCtx.whirlpoolClient.getPosition(positionData.publicKey, IGNORE_CACHE); - - const walletPositionTokenAccount = getAssociatedTokenAddressSync( - positionData.mintKeypair.publicKey, - testCtx.whirlpoolCtx.wallet.publicKey, - ); - - const newOwnerPositionTokenAccount = await createAssociatedTokenAccount( - ctx.provider, - positionData.mintKeypair.publicKey, - otherWallet.publicKey, - ctx.wallet.publicKey - ); - - await accrueFeesAndRewards(fixture); - await transferToken(testCtx.provider, walletPositionTokenAccount, newOwnerPositionTokenAccount, 1); - - const { poolInitInfo } = fixture.getInfos(); - - const pool = await testCtx.whirlpoolClient.getPool(poolInitInfo.whirlpoolPda.publicKey); - - const positionDataBefore = await testCtx.whirlpoolCtx.fetcher.getPosition( - position.getAddress(), - IGNORE_CACHE - ); - - assert.notEqual(positionDataBefore, null); - - const txs = await pool.closePosition( - position.getAddress(), - Percentage.fromFraction(10, 100), - otherWallet.publicKey, - otherWallet.publicKey, - ctx.wallet.publicKey - ); - - txs[txs.length - 1].addSigner(otherWallet) - - for (const tx of txs) { - await tx.buildAndExecute(); - } - - const positionDataAfter = await testCtx.whirlpoolCtx.fetcher.getPosition( - position.getAddress(), - IGNORE_CACHE - ); - - assert.equal(positionDataAfter, null); - }); - }); - - it("should only create 2 transactions if absolutely necessary", async () => { - const ctx = testCtx.whirlpoolCtx; - const fixture = await new WhirlpoolTestFixture(testCtx.whirlpoolCtx).init({ - tickSpacing, - positions: [ - { tickLowerIndex, tickUpperIndex, liquidityAmount }, // In range position - ], - rewards: [ - { - emissionsPerSecondX64: MathUtil.toX64(new Decimal(10)), - vaultAmount: new BN(vaultStartBalance), - }, - { - emissionsPerSecondX64: MathUtil.toX64(new Decimal(10)), - vaultAmount: new BN(vaultStartBalance), - }, - { - emissionsPerSecondX64: MathUtil.toX64(new Decimal(10)), - vaultAmount: new BN(vaultStartBalance), - }, - ], - tokenAIsNative: true, - }); - - const otherWallet = anchor.web3.Keypair.generate(); - const positionData = fixture.getInfos().positions[0]; - - const position = await testCtx.whirlpoolClient.getPosition(positionData.publicKey, IGNORE_CACHE); - - const walletPositionTokenAccount = getAssociatedTokenAddressSync( - positionData.mintKeypair.publicKey, - testCtx.whirlpoolCtx.wallet.publicKey, - ); - - const newOwnerPositionTokenAccount = await createAssociatedTokenAccount( - ctx.provider, - positionData.mintKeypair.publicKey, - otherWallet.publicKey, - ctx.wallet.publicKey - ); - - await accrueFeesAndRewards(fixture); - await transferToken(testCtx.provider, walletPositionTokenAccount, newOwnerPositionTokenAccount, 1); - - const { poolInitInfo } = fixture.getInfos(); - - const pool = await testCtx.whirlpoolClient.getPool(poolInitInfo.whirlpoolPda.publicKey); - - const txsWith4Ata = await pool.closePosition( - position.getAddress(), - Percentage.fromFraction(10, 100), - otherWallet.publicKey, - otherWallet.publicKey, - ctx.wallet.publicKey - ); - assert.equal(txsWith4Ata.length, 2); - - await createAssociatedTokenAccount( - ctx.provider, - position.getWhirlpoolData().rewardInfos[0].mint, - otherWallet.publicKey, - ctx.wallet.publicKey - ); - - const txsWith3Ata = await pool.closePosition( - position.getAddress(), - Percentage.fromFraction(10, 100), - otherWallet.publicKey, - otherWallet.publicKey, - ctx.wallet.publicKey - ); - assert.equal(txsWith3Ata.length, 2); - - await createAssociatedTokenAccount( - ctx.provider, - position.getWhirlpoolData().rewardInfos[1].mint, - otherWallet.publicKey, - ctx.wallet.publicKey - ); - - const txsWith2Ata = await pool.closePosition( - position.getAddress(), - Percentage.fromFraction(10, 100), - otherWallet.publicKey, - otherWallet.publicKey, - ctx.wallet.publicKey - ); - assert.equal(txsWith2Ata.length, 2); - - await createAssociatedTokenAccount( - ctx.provider, - position.getWhirlpoolData().rewardInfos[2].mint, - otherWallet.publicKey, - ctx.wallet.publicKey - ); - - const txsWith1Ata = await pool.closePosition( - position.getAddress(), - Percentage.fromFraction(10, 100), - otherWallet.publicKey, - otherWallet.publicKey, - ctx.wallet.publicKey - ); - assert.equal(txsWith1Ata.length, 1); - await txsWith1Ata[0].addSigner(otherWallet).buildAndExecute(); - }); -}); diff --git a/sdk/tests/sdk/whirlpools/whirlpool-impl#collectFeesAndRewardsForPositions.test.ts b/sdk/tests/sdk/whirlpools/whirlpool-impl#collectFeesAndRewardsForPositions.test.ts deleted file mode 100644 index 9b36b1b..0000000 --- a/sdk/tests/sdk/whirlpools/whirlpool-impl#collectFeesAndRewardsForPositions.test.ts +++ /dev/null @@ -1,404 +0,0 @@ -import * as anchor from "@coral-xyz/anchor"; -import { MathUtil, SendTxRequest, TransactionBuilder, TransactionProcessor, ZERO } from "@orca-so/common-sdk"; -import { NATIVE_MINT, createAssociatedTokenAccountInstruction, createBurnInstruction, createCloseAccountInstruction, getAssociatedTokenAddressSync } from "@solana/spl-token"; -import { PublicKey } from "@solana/web3.js"; -import * as assert from "assert"; -import { BN } from "bn.js"; -import Decimal from "decimal.js"; -import { - NUM_REWARDS, - PDAUtil, - PoolUtil, - Whirlpool, - WhirlpoolClient, - WhirlpoolContext, - WhirlpoolIx, - buildWhirlpoolClient, - collectFeesQuote, - collectRewardsQuote, - toTx -} from "../../../src"; -import { IGNORE_CACHE } from "../../../src/network/public/fetcher"; -import { TickSpacing, ZERO_BN } from "../../utils"; -import { defaultConfirmOptions } from "../../utils/const"; -import { WhirlpoolTestFixture } from "../../utils/fixture"; -import { FundedPositionInfo } from "../../utils/init-utils"; - -interface SharedTestContext { - provider: anchor.AnchorProvider; - program: Whirlpool; - whirlpoolCtx: WhirlpoolContext; - whirlpoolClient: WhirlpoolClient; -} - -describe("WhirlpoolImpl#collectFeesAndRewardsForPositions()", () => { - let testCtx: SharedTestContext; - const tickLowerIndex = 29440; - const tickUpperIndex = 33536; - const tickSpacing = TickSpacing.Standard; - const vaultStartBalance = 1_000_000; - const liquidityAmount = new BN(10_000_000); - const sleep = (second: number) => new Promise(resolve => setTimeout(resolve, second * 1000)) - - before(() => { - const provider = anchor.AnchorProvider.local(undefined, defaultConfirmOptions); - - anchor.setProvider(provider); - const program = anchor.workspace.Whirlpool; - const whirlpoolCtx = WhirlpoolContext.fromWorkspace(provider, program, undefined, undefined, { - userDefaultBuildOptions: { - maxSupportedTransactionVersion: "legacy", - } - }); - const whirlpoolClient = buildWhirlpoolClient(whirlpoolCtx); - - testCtx = { - provider, - program, - whirlpoolCtx, - whirlpoolClient, - }; - }); - - async function accrueFees(fixture: WhirlpoolTestFixture) { - const ctx = testCtx.whirlpoolCtx; - const { - poolInitInfo, - positions, - tokenAccountA, - tokenAccountB, - } = fixture.getInfos(); - - const { whirlpoolPda, tokenVaultAKeypair, tokenVaultBKeypair } = poolInitInfo; - - const tickArrayPda = PDAUtil.getTickArray(ctx.program.programId, whirlpoolPda.publicKey, 22528); - const oraclePda = PDAUtil.getOracle(ctx.program.programId, whirlpoolPda.publicKey); - - const pool = await testCtx.whirlpoolClient.getPool(whirlpoolPda.publicKey); - - // Accrue fees in token A - await toTx( - ctx, - WhirlpoolIx.swapIx(ctx.program, { - amount: new BN(200_000), - otherAmountThreshold: ZERO_BN, - sqrtPriceLimit: MathUtil.toX64(new Decimal(4)), - amountSpecifiedIsInput: true, - aToB: true, - whirlpool: whirlpoolPda.publicKey, - tokenAuthority: ctx.wallet.publicKey, - tokenOwnerAccountA: tokenAccountA, - tokenVaultA: tokenVaultAKeypair.publicKey, - tokenOwnerAccountB: tokenAccountB, - tokenVaultB: tokenVaultBKeypair.publicKey, - tickArray0: tickArrayPda.publicKey, - tickArray1: tickArrayPda.publicKey, - tickArray2: tickArrayPda.publicKey, - oracle: oraclePda.publicKey, - }) - ).buildAndExecute(); - - // Accrue fees in token B - await toTx( - ctx, - WhirlpoolIx.swapIx(ctx.program, { - amount: new BN(200_000), - otherAmountThreshold: ZERO_BN, - sqrtPriceLimit: MathUtil.toX64(new Decimal(5)), - amountSpecifiedIsInput: true, - aToB: false, - whirlpool: whirlpoolPda.publicKey, - tokenAuthority: ctx.wallet.publicKey, - tokenOwnerAccountA: tokenAccountA, - tokenVaultA: tokenVaultAKeypair.publicKey, - tokenOwnerAccountB: tokenAccountB, - tokenVaultB: tokenVaultBKeypair.publicKey, - tickArray0: tickArrayPda.publicKey, - tickArray1: tickArrayPda.publicKey, - tickArray2: tickArrayPda.publicKey, - oracle: oraclePda.publicKey, - }) - ).buildAndExecute(); - - // all position should get some fees - for (const positionInfo of positions) { - const position = await testCtx.whirlpoolClient.getPosition(positionInfo.publicKey); - - const poolData = await pool.refreshData(); - const positionData = await position.refreshData(); - const tickLowerData = position.getLowerTickData(); - const tickUpperData = position.getLowerTickData(); - - const quote = collectFeesQuote({ - whirlpool: poolData, - position: positionData, - tickLower: tickLowerData, - tickUpper: tickUpperData, - }); - - assert.ok(quote.feeOwedA.gtn(0) || quote.feeOwedB.gtn(0)); - } - } - - async function stopRewardsEmission(fixture: WhirlpoolTestFixture) { - const ctx = testCtx.whirlpoolCtx; - const { poolInitInfo, configKeypairs } = fixture.getInfos(); - const { whirlpoolPda } = poolInitInfo; - - const pool = await testCtx.whirlpoolClient.getPool(whirlpoolPda.publicKey); - - for (let i = 0; i < NUM_REWARDS; i++) { - await toTx( - ctx, - WhirlpoolIx.setRewardEmissionsIx(ctx.program, { - whirlpool: pool.getAddress(), - rewardVaultKey: pool.getData().rewardInfos[i].vault, - rewardAuthority: configKeypairs.rewardEmissionsSuperAuthorityKeypair.publicKey, - rewardIndex: i, - emissionsPerSecondX64: ZERO, - }) - ).addSigner(configKeypairs.rewardEmissionsSuperAuthorityKeypair).buildAndExecute(); - } - } - - async function burnAndCloseATAs(fixture: WhirlpoolTestFixture) { - const ctx = testCtx.whirlpoolCtx; - const { poolInitInfo, configKeypairs } = fixture.getInfos(); - const { whirlpoolPda } = poolInitInfo; - - const pool = await testCtx.whirlpoolClient.getPool(whirlpoolPda.publicKey); - - const mintA = pool.getTokenAInfo().mint; - const mintB = pool.getTokenBInfo().mint; - const ataA = getAssociatedTokenAddressSync(mintA, ctx.wallet.publicKey); - const ataB = getAssociatedTokenAddressSync(mintB, ctx.wallet.publicKey); - await burnAndCloseATA(ctx, ataA); - await burnAndCloseATA(ctx, ataB); - - for (let i = 0; i < NUM_REWARDS; i++) { - if (PoolUtil.isRewardInitialized(pool.getRewardInfos()[i])) { - const mintReward = pool.getRewardInfos()[i].mint; - const ataReward = getAssociatedTokenAddressSync(mintReward, ctx.wallet.publicKey); - await burnAndCloseATA(ctx, ataReward); - } - } - } - - async function burnAndCloseATA(ctx: WhirlpoolContext, ata: PublicKey) { - const account = await ctx.fetcher.getTokenInfo(ata, IGNORE_CACHE); - if (account === null) return; - - const burnIx = createBurnInstruction(ata, account.mint, ctx.wallet.publicKey, account.amount); - const closeIx = createCloseAccountInstruction(ata, ctx.wallet.publicKey, ctx.wallet.publicKey, []); - - const tx = new TransactionBuilder(ctx.connection, ctx.wallet, ctx.txBuilderOpts); - tx.addInstruction({ - instructions: [burnIx, closeIx], - cleanupInstructions: [], - signers: [], - }); - await tx.buildAndExecute(); - } - - async function createATAs(fixture: WhirlpoolTestFixture) { - const ctx = testCtx.whirlpoolCtx; - const { poolInitInfo, configKeypairs } = fixture.getInfos(); - const { whirlpoolPda } = poolInitInfo; - - const pool = await testCtx.whirlpoolClient.getPool(whirlpoolPda.publicKey); - - const mintA = pool.getTokenAInfo().mint; - const mintB = pool.getTokenBInfo().mint; - const ataA = getAssociatedTokenAddressSync(mintA, ctx.wallet.publicKey); - const ataB = getAssociatedTokenAddressSync(mintB, ctx.wallet.publicKey); - await createATA(ctx, ataA, mintA); - await createATA(ctx, ataB, mintB); - - for (let i = 0; i < NUM_REWARDS; i++) { - if (PoolUtil.isRewardInitialized(pool.getRewardInfos()[i])) { - const mintReward = pool.getRewardInfos()[i].mint; - const ataReward = getAssociatedTokenAddressSync(mintReward, ctx.wallet.publicKey); - await createATA(ctx, ataReward, mintReward); - } - } - } - - async function createATA(ctx: WhirlpoolContext, ata: PublicKey, mint: PublicKey) { - if (mint.equals(NATIVE_MINT)) return; - - const account = await ctx.fetcher.getTokenInfo(ata, IGNORE_CACHE); - if (account !== null) return; - const createATAIx = createAssociatedTokenAccountInstruction( - ctx.wallet.publicKey, - ata, - ctx.wallet.publicKey, - mint, - ); - - const tx = new TransactionBuilder(ctx.connection, ctx.wallet, ctx.txBuilderOpts); - tx.addInstruction({ - instructions: [createATAIx], - cleanupInstructions: [], - signers: [], - }); - await tx.buildAndExecute(); - } - - async function baseTestSenario(tokenAIsNative: boolean, ataExists: boolean) { - const fixtures: WhirlpoolTestFixture[] = []; - const positions: FundedPositionInfo[] = []; - const numOfPool = 3; - - for (let i = 0; i < numOfPool; i++) { - const fixture = await new WhirlpoolTestFixture(testCtx.whirlpoolCtx).init({ - tokenAIsNative, - tickSpacing, - positions: [ - // 3 Positions / pool - { tickLowerIndex, tickUpperIndex, liquidityAmount }, // In range position - { tickLowerIndex, tickUpperIndex, liquidityAmount }, // In range position - { tickLowerIndex, tickUpperIndex, liquidityAmount }, // In range position - ], - rewards: [ - { - emissionsPerSecondX64: MathUtil.toX64(new Decimal(10)), - vaultAmount: new BN(vaultStartBalance), - }, - { - emissionsPerSecondX64: MathUtil.toX64(new Decimal(10)), - vaultAmount: new BN(vaultStartBalance), - }, - { - emissionsPerSecondX64: MathUtil.toX64(new Decimal(10)), - vaultAmount: new BN(vaultStartBalance), - }, - ], - }); - - fixtures.push(fixture); - positions.push(...fixture.getInfos().positions); - } - - await sleep(2); // accrueRewards - for (const fixture of fixtures) { - await accrueFees(fixture); - await (ataExists ? createATAs : burnAndCloseATAs)(fixture); - await stopRewardsEmission(fixture); - } - - // check all positions have fees and rewards - for (const positionInfo of positions) { - const position = await testCtx.whirlpoolClient.getPosition(positionInfo.publicKey); - - const poolData = await testCtx.whirlpoolCtx.fetcher.getPool(position.getData().whirlpool, IGNORE_CACHE); - const positionData = await position.refreshData(); - const tickLowerData = position.getLowerTickData(); - const tickUpperData = position.getLowerTickData(); - - const feeQuote = collectFeesQuote({ - whirlpool: poolData!, - position: positionData, - tickLower: tickLowerData, - tickUpper: tickUpperData, - }); - - const rewardQuote = collectRewardsQuote({ - whirlpool: poolData!, - position: positionData, - tickLower: tickLowerData, - tickUpper: tickUpperData, - timeStampInSeconds: poolData!.rewardLastUpdatedTimestamp, - }); - - assert.ok(feeQuote.feeOwedA.gt(ZERO)); - assert.ok(feeQuote.feeOwedB.gt(ZERO)); - assert.ok(rewardQuote[0]?.gt(ZERO)); - assert.ok(rewardQuote[1]?.gt(ZERO)); - assert.ok(rewardQuote[2]?.gt(ZERO)); - } - - const txs = await testCtx.whirlpoolClient.collectFeesAndRewardsForPositions( - positions.map((p) => p.publicKey), - IGNORE_CACHE, - ); - assert.ok(txs.length >= 2); - - // TODO: We should not depend on Transaction Processor for mass txn sending. SendTxRequest is also a hack. - // Remove when we have an official multi-transaction sending solution. - const requests: SendTxRequest[] = []; - for (const tx of txs) { - requests.push(await tx.build() as SendTxRequest); - } - - const parallel = true; - const processor = new TransactionProcessor(testCtx.whirlpoolCtx.connection, testCtx.whirlpoolCtx.wallet); - const { execute } = await processor.signAndConstructTransactions(requests, parallel); - - const txResults = await execute(); - for (const result of txResults) { - if (result.status === "rejected") { - console.log(result.reason); - } - assert.equal(result.status, "fulfilled"); - } - - // check all positions have no fees and rewards - for (const positionInfo of positions) { - const position = await testCtx.whirlpoolClient.getPosition(positionInfo.publicKey); - - const poolData = await testCtx.whirlpoolCtx.fetcher.getPool(position.getData().whirlpool, IGNORE_CACHE); - const positionData = await position.refreshData(); - const tickLowerData = position.getLowerTickData(); - const tickUpperData = position.getLowerTickData(); - - const feeQuote = collectFeesQuote({ - whirlpool: poolData!, - position: positionData, - tickLower: tickLowerData, - tickUpper: tickUpperData, - }); - - const rewardQuote = collectRewardsQuote({ - whirlpool: poolData!, - position: positionData, - tickLower: tickLowerData, - tickUpper: tickUpperData, - timeStampInSeconds: poolData!.rewardLastUpdatedTimestamp, - }); - - assert.ok(feeQuote.feeOwedA.eq(ZERO)); - assert.ok(feeQuote.feeOwedB.eq(ZERO)); - assert.ok(rewardQuote[0]?.eq(ZERO)); - assert.ok(rewardQuote[1]?.eq(ZERO)); - assert.ok(rewardQuote[2]?.eq(ZERO)); - } - } - - context("when the whirlpool is SPL-only", () => { - it("should collect fees and rewards, create all ATAs", async () => { - const tokenAIsNative = false; - const ataExists = false; - await baseTestSenario(tokenAIsNative, ataExists); - }); - - it("should collect fees and rewards, all ATAs exists", async () => { - const tokenAIsNative = false; - const ataExists = true; - await baseTestSenario(tokenAIsNative, ataExists); - }); - }); - - context("when the whirlpool is SOL-SPL", () => { - it("should collect fees and rewards, create all ATAs", async () => { - const tokenAIsNative = true; - const ataExists = false; - await baseTestSenario(tokenAIsNative, ataExists); - }); - - it("should collect fees and rewards, all ATAs exists", async () => { - const tokenAIsNative = true; - const ataExists = true; - await baseTestSenario(tokenAIsNative, ataExists); - }); - }); -}); diff --git a/sdk/tests/sdk/whirlpools/whirlpool-impl.test.ts b/sdk/tests/sdk/whirlpools/whirlpool-impl.test.ts deleted file mode 100644 index 0fc718a..0000000 --- a/sdk/tests/sdk/whirlpools/whirlpool-impl.test.ts +++ /dev/null @@ -1,758 +0,0 @@ -import * as anchor from "@coral-xyz/anchor"; -import { MathUtil, Percentage, TransactionBuilder } from "@orca-so/common-sdk"; -import { createBurnInstruction, createCloseAccountInstruction, getAssociatedTokenAddressSync } from "@solana/spl-token"; -import * as assert from "assert"; -import { BN } from "bn.js"; -import Decimal from "decimal.js"; -import { - PDAUtil, - PriceMath, TickUtil, - WhirlpoolIx, - buildWhirlpoolClient, - collectFeesQuote, - collectRewardsQuote, - decreaseLiquidityQuoteByLiquidity, - increaseLiquidityQuoteByInputTokenUsingPriceSlippage, - swapQuoteByInputToken, - toTx -} from "../../../src"; -import { WhirlpoolContext } from "../../../src/context"; -import { IGNORE_CACHE } from "../../../src/network/public/fetcher"; -import { - ONE_SOL, - TickSpacing, - ZERO_BN, - createAssociatedTokenAccount, - getTokenBalance, - sleep, - systemTransferTx, - transferToken -} from "../../utils"; -import { defaultConfirmOptions } from "../../utils/const"; -import { WhirlpoolTestFixture } from "../../utils/fixture"; -import { initTestPool } from "../../utils/init-utils"; -import { mintTokensToTestAccount } from "../../utils/test-builders"; -import { ASSOCIATED_PROGRAM_ID } from "@coral-xyz/anchor/dist/cjs/utils/token"; - -describe("whirlpool-impl", () => { - const provider = anchor.AnchorProvider.local(undefined, defaultConfirmOptions); - - const program = anchor.workspace.Whirlpool; - const ctx = WhirlpoolContext.fromWorkspace(provider, program); - const fetcher = ctx.fetcher; - const client = buildWhirlpoolClient(ctx); - - it("open and add liquidity to a position, then close", async () => { - const funderKeypair = anchor.web3.Keypair.generate(); - await systemTransferTx(provider, funderKeypair.publicKey, ONE_SOL).buildAndExecute(); - - const { poolInitInfo } = await initTestPool( - ctx, - TickSpacing.Standard, - PriceMath.priceToSqrtPriceX64(new Decimal(100), 6, 6) - ); - const pool = await client.getPool(poolInitInfo.whirlpoolPda.publicKey); - - // Verify token mint info is correct - const tokenAInfo = pool.getTokenAInfo(); - const tokenBInfo = pool.getTokenBInfo(); - assert.ok(tokenAInfo.mint.equals(poolInitInfo.tokenMintA)); - assert.ok(tokenBInfo.mint.equals(poolInitInfo.tokenMintB)); - - // Create and mint tokens in this wallet - const mintedTokenAmount = 150_000_000; - const [userTokenAAccount, userTokenBAccount] = await mintTokensToTestAccount( - ctx.provider, - tokenAInfo.mint, - mintedTokenAmount, - tokenBInfo.mint, - mintedTokenAmount - ); - - // Open a position with no tick arrays initialized. - const lowerPrice = new Decimal(96); - const upperPrice = new Decimal(101); - const poolData = pool.getData(); - const tokenADecimal = tokenAInfo.decimals; - const tokenBDecimal = tokenBInfo.decimals; - - const tickLower = TickUtil.getInitializableTickIndex( - PriceMath.priceToTickIndex(lowerPrice, tokenADecimal, tokenBDecimal), - poolData.tickSpacing - ); - const tickUpper = TickUtil.getInitializableTickIndex( - PriceMath.priceToTickIndex(upperPrice, tokenADecimal, tokenBDecimal), - poolData.tickSpacing - ); - - const inputTokenMint = poolData.tokenMintA; - const quote = increaseLiquidityQuoteByInputTokenUsingPriceSlippage( - inputTokenMint, - new Decimal(50), - tickLower, - tickUpper, - Percentage.fromFraction(1, 100), - pool - ); - - // [Action] Initialize Tick Arrays - const initTickArrayTx = ( - await pool.initTickArrayForTicks([tickLower, tickUpper], funderKeypair.publicKey) - )?.addSigner(funderKeypair); - - assert.ok(!!initTickArrayTx); - - // [Action] Open Position (and increase L) - const { positionMint, tx: openIx } = await pool.openPosition( - tickLower, - tickUpper, - quote, - ctx.wallet.publicKey, - funderKeypair.publicKey - ); - openIx.addSigner(funderKeypair); - - await initTickArrayTx.buildAndExecute(); - await openIx.buildAndExecute(); - - // Verify position exists and numbers fit input parameters - const positionAddress = PDAUtil.getPosition(ctx.program.programId, positionMint).publicKey; - const position = await client.getPosition(positionAddress, IGNORE_CACHE); - const positionData = position.getData(); - - const tickLowerIndex = TickUtil.getInitializableTickIndex( - PriceMath.priceToTickIndex(lowerPrice, tokenAInfo.decimals, tokenBInfo.decimals), - poolData.tickSpacing - ); - const tickUpperIndex = TickUtil.getInitializableTickIndex( - PriceMath.priceToTickIndex(upperPrice, tokenAInfo.decimals, tokenBInfo.decimals), - poolData.tickSpacing - ); - assert.ok(positionData.liquidity.eq(quote.liquidityAmount)); - assert.ok(positionData.tickLowerIndex === tickLowerIndex); - assert.ok(positionData.tickUpperIndex === tickUpperIndex); - assert.ok(positionData.positionMint.equals(positionMint)); - assert.ok(positionData.whirlpool.equals(poolInitInfo.whirlpoolPda.publicKey)); - - // [Action] Close Position - const txs = await pool.closePosition(positionAddress, Percentage.fromFraction(1, 100)); - - for (const tx of txs) { - await tx.buildAndExecute(); - } - - // Verify position is closed and owner wallet has the tokens back - const postClosePosition = await fetcher.getPosition(positionAddress, IGNORE_CACHE); - assert.ok(postClosePosition === null); - - // TODO: we are leaking 1 decimal place of token? - assert.equal(await getTokenBalance(ctx.provider, userTokenAAccount), mintedTokenAmount - 1); - assert.equal(await getTokenBalance(ctx.provider, userTokenBAccount), mintedTokenAmount - 1); - }); - - it("open and add liquidity to a position, transfer position to another wallet, then close the tokens to another wallet", async () => { - const funderKeypair = anchor.web3.Keypair.generate(); - await systemTransferTx(provider, funderKeypair.publicKey, ONE_SOL).buildAndExecute(); - - const { poolInitInfo } = await initTestPool( - ctx, - TickSpacing.Standard, - PriceMath.priceToSqrtPriceX64(new Decimal(100), 6, 6) - ); - const pool = await client.getPool(poolInitInfo.whirlpoolPda.publicKey); - - // Verify token mint info is correct - const tokenAInfo = pool.getTokenAInfo(); - const tokenBInfo = pool.getTokenBInfo(); - assert.ok(tokenAInfo.mint.equals(poolInitInfo.tokenMintA)); - assert.ok(tokenBInfo.mint.equals(poolInitInfo.tokenMintB)); - - // Create and mint tokens in this wallet - const mintedTokenAmount = 150_000_000; - await mintTokensToTestAccount( - ctx.provider, - tokenAInfo.mint, - mintedTokenAmount, - tokenBInfo.mint, - mintedTokenAmount - ); - - // Open a position with no tick arrays initialized. - const lowerPrice = new Decimal(96); - const upperPrice = new Decimal(101); - const poolData = pool.getData(); - const tokenADecimal = tokenAInfo.decimals; - const tokenBDecimal = tokenBInfo.decimals; - - const tickLower = TickUtil.getInitializableTickIndex( - PriceMath.priceToTickIndex(lowerPrice, tokenADecimal, tokenBDecimal), - poolData.tickSpacing - ); - const tickUpper = TickUtil.getInitializableTickIndex( - PriceMath.priceToTickIndex(upperPrice, tokenADecimal, tokenBDecimal), - poolData.tickSpacing - ); - - const inputTokenMint = poolData.tokenMintA; - const depositAmount = new Decimal(50); - const quote = increaseLiquidityQuoteByInputTokenUsingPriceSlippage( - inputTokenMint, - depositAmount, - tickLower, - tickUpper, - Percentage.fromFraction(1, 100), - pool - ); - - // [Action] Initialize Tick Arrays - const initTickArrayTx = ( - await pool.initTickArrayForTicks([tickLower, tickUpper], funderKeypair.publicKey) - )?.addSigner(funderKeypair); - - assert.ok(!!initTickArrayTx); - - // [Action] Open Position (and increase L) - const { positionMint, tx: openIx } = await pool.openPosition( - tickLower, - tickUpper, - quote, - ctx.wallet.publicKey, - funderKeypair.publicKey - ); - openIx.addSigner(funderKeypair); - - await initTickArrayTx.buildAndExecute(); - await openIx.buildAndExecute(); - - // Verify position exists and numbers fit input parameters - const positionAddress = PDAUtil.getPosition(ctx.program.programId, positionMint).publicKey; - const position = await client.getPosition(positionAddress, IGNORE_CACHE); - const positionData = position.getData(); - - const tickLowerIndex = TickUtil.getInitializableTickIndex( - PriceMath.priceToTickIndex(lowerPrice, tokenAInfo.decimals, tokenBInfo.decimals), - poolData.tickSpacing - ); - const tickUpperIndex = TickUtil.getInitializableTickIndex( - PriceMath.priceToTickIndex(upperPrice, tokenAInfo.decimals, tokenBInfo.decimals), - poolData.tickSpacing - ); - assert.ok(positionData.liquidity.eq(quote.liquidityAmount)); - assert.ok(positionData.tickLowerIndex === tickLowerIndex); - assert.ok(positionData.tickUpperIndex === tickUpperIndex); - assert.ok(positionData.positionMint.equals(positionMint)); - assert.ok(positionData.whirlpool.equals(poolInitInfo.whirlpoolPda.publicKey)); - - // Transfer the position token to another wallet - const otherWallet = anchor.web3.Keypair.generate(); - const walletPositionTokenAccount = getAssociatedTokenAddressSync(positionMint, ctx.wallet.publicKey); - const newOwnerPositionTokenAccount = await createAssociatedTokenAccount( - ctx.provider, - positionMint, - otherWallet.publicKey, - ctx.wallet.publicKey - ); - await transferToken(provider, walletPositionTokenAccount, newOwnerPositionTokenAccount, 1); - - // [Action] Close Position - const expectationQuote = await decreaseLiquidityQuoteByLiquidity( - positionData.liquidity, - Percentage.fromDecimal(new Decimal(0)), - position, - pool - ); - - const destinationWallet = anchor.web3.Keypair.generate(); - - const txs = await pool.closePosition( - positionAddress, - Percentage.fromFraction(1, 100), - destinationWallet.publicKey, - otherWallet.publicKey, - ctx.wallet.publicKey - ); - - let ataTx: TransactionBuilder | undefined; - let closeTx: TransactionBuilder; - if (txs.length === 1) { - closeTx = txs[0]; - } else if (txs.length === 2) { - ataTx = txs[0]; - closeTx = txs[1]; - } else { - throw new Error(`Invalid length for txs ${txs}`); - } - - await ataTx?.buildAndExecute(); - await closeTx.addSigner(otherWallet).buildAndExecute(); - - // Verify position is closed and owner wallet has the tokens back - const postClosePosition = await fetcher.getPosition(positionAddress, IGNORE_CACHE); - assert.ok(postClosePosition === null); - - const dWalletTokenAAccount = getAssociatedTokenAddressSync(poolData.tokenMintA, destinationWallet.publicKey,); - const dWalletTokenBAccount = getAssociatedTokenAddressSync(poolData.tokenMintB, destinationWallet.publicKey); - - assert.equal( - await getTokenBalance(ctx.provider, dWalletTokenAAccount), - expectationQuote.tokenMinA.toString() - ); - assert.equal( - await getTokenBalance(ctx.provider, dWalletTokenBAccount), - expectationQuote.tokenMinB.toString() - ); - }); - - it("open and add liquidity to a position, trade against it, transfer position to another wallet, then close the tokens to another wallet", async () => { - // In same tick array - start index 22528 - const tickLowerIndex = 29440; - const tickUpperIndex = 33536; - const vaultStartBalance = 1_000_000_000; - const tickSpacing = TickSpacing.Standard; - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing, - positions: [ - { tickLowerIndex, tickUpperIndex, liquidityAmount: new anchor.BN(10_000_000) }, // In range position - { tickLowerIndex: 0, tickUpperIndex: 128, liquidityAmount: new anchor.BN(1_000_000) }, // Out of range position - ], - rewards: [ - { - emissionsPerSecondX64: MathUtil.toX64(new Decimal(10)), - vaultAmount: new BN(vaultStartBalance), - }, - { - emissionsPerSecondX64: MathUtil.toX64(new Decimal(5)), - vaultAmount: new BN(vaultStartBalance), - }, - { - emissionsPerSecondX64: MathUtil.toX64(new Decimal(10)), - vaultAmount: new BN(vaultStartBalance), - }, - ], - }); - const { - poolInitInfo: { whirlpoolPda, tokenVaultAKeypair, tokenVaultBKeypair }, - tokenAccountA, - tokenAccountB, - positions, - } = fixture.getInfos(); - - const tickArrayPda = PDAUtil.getTickArray(ctx.program.programId, whirlpoolPda.publicKey, 22528); - const oraclePda = PDAUtil.getOracle(ctx.program.programId, whirlpoolPda.publicKey); - - // Accrue fees in token A - await toTx( - ctx, - WhirlpoolIx.swapIx(ctx.program, { - amount: new BN(200_000), - otherAmountThreshold: ZERO_BN, - sqrtPriceLimit: MathUtil.toX64(new Decimal(4)), - amountSpecifiedIsInput: true, - aToB: true, - whirlpool: whirlpoolPda.publicKey, - tokenAuthority: ctx.wallet.publicKey, - tokenOwnerAccountA: tokenAccountA, - tokenVaultA: tokenVaultAKeypair.publicKey, - tokenOwnerAccountB: tokenAccountB, - tokenVaultB: tokenVaultBKeypair.publicKey, - tickArray0: tickArrayPda.publicKey, - tickArray1: tickArrayPda.publicKey, - tickArray2: tickArrayPda.publicKey, - oracle: oraclePda.publicKey, - }) - ).buildAndExecute(); - - // Accrue fees in token B - await toTx( - ctx, - WhirlpoolIx.swapIx(ctx.program, { - amount: new BN(200_000), - otherAmountThreshold: ZERO_BN, - sqrtPriceLimit: MathUtil.toX64(new Decimal(5)), - amountSpecifiedIsInput: true, - aToB: false, - whirlpool: whirlpoolPda.publicKey, - tokenAuthority: ctx.wallet.publicKey, - tokenOwnerAccountA: tokenAccountA, - tokenVaultA: tokenVaultAKeypair.publicKey, - tokenOwnerAccountB: tokenAccountB, - tokenVaultB: tokenVaultBKeypair.publicKey, - tickArray0: tickArrayPda.publicKey, - tickArray1: tickArrayPda.publicKey, - tickArray2: tickArrayPda.publicKey, - oracle: oraclePda.publicKey, - }) - ).buildAndExecute(); - - // accrue rewards - // closePosition does not attempt to create an ATA unless reward has accumulated. - await sleep(1200); - - const [positionWithFees] = positions; - - // Transfer the position token to another wallet - const otherWallet = anchor.web3.Keypair.generate(); - const walletPositionTokenAccount = getAssociatedTokenAddressSync( - positionWithFees.mintKeypair.publicKey, - ctx.wallet.publicKey, - ); - - const newOwnerPositionTokenAccount = await createAssociatedTokenAccount( - ctx.provider, - positionWithFees.mintKeypair.publicKey, - otherWallet.publicKey, - ctx.wallet.publicKey - ); - - await transferToken(provider, walletPositionTokenAccount, newOwnerPositionTokenAccount, 1); - - const pool = await client.getPool(whirlpoolPda.publicKey, IGNORE_CACHE); - const position = await client.getPosition(positionWithFees.publicKey, IGNORE_CACHE); - const positionData = position.getData(); - const poolData = pool.getData(); - const txs = await pool.closePosition( - positionWithFees.publicKey, - new Percentage(new BN(10), new BN(100)), - otherWallet.publicKey, - otherWallet.publicKey, - ctx.wallet.publicKey - ); - - const expectationQuote = decreaseLiquidityQuoteByLiquidity( - position.getData().liquidity, - Percentage.fromDecimal(new Decimal(0)), - position, - pool - ); - - const dWalletTokenAAccount = getAssociatedTokenAddressSync(poolData.tokenMintA, otherWallet.publicKey,); - const dWalletTokenBAccount = getAssociatedTokenAddressSync(poolData.tokenMintB, otherWallet.publicKey,); - const rewardAccount0 = getAssociatedTokenAddressSync(poolData.rewardInfos[0].mint, otherWallet.publicKey,); - const rewardAccount1 = getAssociatedTokenAddressSync(poolData.rewardInfos[1].mint, otherWallet.publicKey,); - const rewardAccount2 = getAssociatedTokenAddressSync(poolData.rewardInfos[2].mint, otherWallet.publicKey,); - - const feesQuote = collectFeesQuote({ - whirlpool: poolData, - position: positionData, - tickLower: position.getLowerTickData(), - tickUpper: position.getUpperTickData(), - }); - - let ataTx: TransactionBuilder | undefined; - let closeTx: TransactionBuilder; - if (txs.length === 1) { - closeTx = txs[0]; - } else if (txs.length === 2) { - ataTx = txs[0]; - closeTx = txs[1]; - } else { - throw new Error(`Invalid length for txs ${txs}`); - } - - await ataTx?.buildAndExecute(); - const signature = await closeTx.addSigner(otherWallet).buildAndExecute(); - - // To calculate the rewards that have accumulated up to the timing of the close, - // the block time at transaction execution is used. - // TODO: maxSupportedTransactionVersion needs to come from ctx - const tx = await ctx.provider.connection.getTransaction(signature, { - maxSupportedTransactionVersion: 0 - }); - const closeTimestampInSeconds = new anchor.BN(tx!.blockTime!.toString()); - const rewardsQuote = collectRewardsQuote({ - whirlpool: poolData, - position: positionData, - tickLower: position.getLowerTickData(), - tickUpper: position.getUpperTickData(), - timeStampInSeconds: closeTimestampInSeconds, - }); - - assert.equal( - await getTokenBalance(ctx.provider, dWalletTokenAAccount), - expectationQuote.tokenMinA.add(feesQuote.feeOwedA).toString() - ); - - assert.equal( - await getTokenBalance(ctx.provider, dWalletTokenBAccount), - expectationQuote.tokenMinB.add(feesQuote.feeOwedB).toString() - ); - - assert.equal(await getTokenBalance(ctx.provider, rewardAccount0), rewardsQuote[0]?.toString()); - assert.equal(await getTokenBalance(ctx.provider, rewardAccount1), rewardsQuote[1]?.toString()); - assert.equal(await getTokenBalance(ctx.provider, rewardAccount2), rewardsQuote[2]?.toString()); - }); - - it("open and add liquidity to a position with SOL as token A, trade against it, transfer position to another wallet, then close the tokens to another wallet", async () => { - // In same tick array - start index 22528 - const tickLowerIndex = 29440; - const tickUpperIndex = 33536; - const vaultStartBalance = 1_000_000_000; - const tickSpacing = TickSpacing.Standard; - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing, - positions: [ - { tickLowerIndex, tickUpperIndex, liquidityAmount: new anchor.BN(10_000_000_000) }, // In range position - { tickLowerIndex: 0, tickUpperIndex: 128, liquidityAmount: new anchor.BN(1_000_000_000) }, // Out of range position - ], - rewards: [ - { - emissionsPerSecondX64: MathUtil.toX64(new Decimal(10)), - vaultAmount: new BN(vaultStartBalance), - }, - { - emissionsPerSecondX64: MathUtil.toX64(new Decimal(10)), - vaultAmount: new BN(vaultStartBalance), - }, - { - emissionsPerSecondX64: MathUtil.toX64(new Decimal(10)), - vaultAmount: new BN(vaultStartBalance), - }, - ], - tokenAIsNative: true, - }); - const { - poolInitInfo: { whirlpoolPda, tokenVaultAKeypair, tokenVaultBKeypair }, - tokenAccountA, - tokenAccountB, - positions, - } = fixture.getInfos(); - - const tickArrayPda = PDAUtil.getTickArray(ctx.program.programId, whirlpoolPda.publicKey, 22528); - const oraclePda = PDAUtil.getOracle(ctx.program.programId, whirlpoolPda.publicKey); - - // Accrue fees in token A - await toTx( - ctx, - WhirlpoolIx.swapIx(ctx.program, { - amount: new BN(200_000_00), - otherAmountThreshold: ZERO_BN, - sqrtPriceLimit: MathUtil.toX64(new Decimal(4)), - amountSpecifiedIsInput: true, - aToB: true, - whirlpool: whirlpoolPda.publicKey, - tokenAuthority: ctx.wallet.publicKey, - tokenOwnerAccountA: tokenAccountA, - tokenVaultA: tokenVaultAKeypair.publicKey, - tokenOwnerAccountB: tokenAccountB, - tokenVaultB: tokenVaultBKeypair.publicKey, - tickArray0: tickArrayPda.publicKey, - tickArray1: tickArrayPda.publicKey, - tickArray2: tickArrayPda.publicKey, - oracle: oraclePda.publicKey, - }) - ).buildAndExecute(); - - // Accrue fees in token B - await toTx( - ctx, - WhirlpoolIx.swapIx(ctx.program, { - amount: new BN(200_000_00), - otherAmountThreshold: ZERO_BN, - sqrtPriceLimit: MathUtil.toX64(new Decimal(5)), - amountSpecifiedIsInput: true, - aToB: false, - whirlpool: whirlpoolPda.publicKey, - tokenAuthority: ctx.wallet.publicKey, - tokenOwnerAccountA: tokenAccountA, - tokenVaultA: tokenVaultAKeypair.publicKey, - tokenOwnerAccountB: tokenAccountB, - tokenVaultB: tokenVaultBKeypair.publicKey, - tickArray0: tickArrayPda.publicKey, - tickArray1: tickArrayPda.publicKey, - tickArray2: tickArrayPda.publicKey, - oracle: oraclePda.publicKey, - }) - ).buildAndExecute(); - - // accrue rewards - // closePosition does not attempt to create an ATA unless reward has accumulated. - await sleep(1200); - - const [positionWithFees] = positions; - - // Transfer the position token to another wallet - const otherWallet = anchor.web3.Keypair.generate(); - const walletPositionTokenAccount = getAssociatedTokenAddressSync( - positionWithFees.mintKeypair.publicKey, - ctx.wallet.publicKey, - ); - - const newOwnerPositionTokenAccount = await createAssociatedTokenAccount( - ctx.provider, - positionWithFees.mintKeypair.publicKey, - otherWallet.publicKey, - ctx.wallet.publicKey - ); - - await transferToken(provider, walletPositionTokenAccount, newOwnerPositionTokenAccount, 1); - - const pool = await client.getPool(whirlpoolPda.publicKey, IGNORE_CACHE); - const position = await client.getPosition(positionWithFees.publicKey, IGNORE_CACHE); - const positionData = position.getData(); - const poolData = pool.getData(); - - const decreaseLiquidityQuote = decreaseLiquidityQuoteByLiquidity( - position.getData().liquidity, - Percentage.fromDecimal(new Decimal(0)), - position, - pool - ); - - const feesQuote = collectFeesQuote({ - whirlpool: poolData, - position: positionData, - tickLower: position.getLowerTickData(), - tickUpper: position.getUpperTickData(), - }); - - const dWalletTokenBAccount = getAssociatedTokenAddressSync(poolData.tokenMintB, otherWallet.publicKey,); - const rewardAccount0 = getAssociatedTokenAddressSync(poolData.rewardInfos[0].mint, otherWallet.publicKey,); - const rewardAccount1 = getAssociatedTokenAddressSync(poolData.rewardInfos[1].mint, otherWallet.publicKey,); - const rewardAccount2 = getAssociatedTokenAddressSync(poolData.rewardInfos[2].mint, otherWallet.publicKey,); - - const txs = await pool.closePosition( - positionWithFees.publicKey, - new Percentage(new BN(10), new BN(100)), - otherWallet.publicKey, - otherWallet.publicKey, - ctx.wallet.publicKey - ); - - let ataTx: TransactionBuilder | undefined; - let closeTx: TransactionBuilder; - if (txs.length === 1) { - closeTx = txs[0]; - } else if (txs.length === 2) { - ataTx = txs[0]; - closeTx = txs[1]; - } else { - throw new Error(`Invalid length for txs ${txs}`); - } - - const otherWalletBalanceBefore = await ctx.connection.getBalance(otherWallet.publicKey); - const positionAccountBalance = await ctx.connection.getBalance(positionWithFees.publicKey); - - await ataTx?.buildAndExecute(); - const signature = await closeTx.addSigner(otherWallet).buildAndExecute(); - - // To calculate the rewards that have accumulated up to the timing of the close, - // the block time at transaction execution is used. - // TODO: maxSupportedTransactionVersion needs to come from ctx - const tx = await ctx.provider.connection.getTransaction(signature, { - maxSupportedTransactionVersion: 0, - }); - const closeTimestampInSeconds = new anchor.BN(tx!.blockTime!.toString()); - const rewardsQuote = collectRewardsQuote({ - whirlpool: poolData, - position: positionData, - tickLower: position.getLowerTickData(), - tickUpper: position.getUpperTickData(), - timeStampInSeconds: closeTimestampInSeconds, - }); - - const otherWalletBalanceAfter = await ctx.connection.getBalance(otherWallet.publicKey); - - const minAccountExempt = await ctx.fetcher.getAccountRentExempt(); - const solReceived = otherWalletBalanceAfter - otherWalletBalanceBefore; - - /** - * Expected tokenA (SOL) returns on other wallet - * 1. withdraw value from decrease_liq (decrease_quote, though not always accurate) - * 2. accrrued fees from trade (fee_quote) - * 3. Position PDA account rent return (balance from position address account) - * 4. wSOL rent-exemption close (getAccountExemption) - * 5. Position token account rent return (getAccountExemption) - * - * Other costs from payer, but not received by other wallet - * 1. close_position tx cost - * 2. ATA account initialization - */ - const expectedtokenA = decreaseLiquidityQuote.tokenMinA - .add(feesQuote.feeOwedA) - .add(new BN(positionAccountBalance)) - .add(new BN(minAccountExempt)) - .add(new BN(minAccountExempt)) - .toNumber(); - assert.ok(solReceived === expectedtokenA); - - assert.equal( - await getTokenBalance(ctx.provider, dWalletTokenBAccount), - decreaseLiquidityQuote.tokenMinB.add(feesQuote.feeOwedB).toString() - ); - - assert.equal(await getTokenBalance(ctx.provider, rewardAccount0), rewardsQuote[0]?.toString()); - assert.equal(await getTokenBalance(ctx.provider, rewardAccount1), rewardsQuote[1]?.toString()); - assert.equal(await getTokenBalance(ctx.provider, rewardAccount2), rewardsQuote[2]?.toString()); - }); - - it("swap with idempotent", async () => { - // In same tick array - start index 22528 - const tickLowerIndex = 29440; - const tickUpperIndex = 33536; - const vaultStartBalance = 1_000_000_000; - const tickSpacing = TickSpacing.Standard; - const fixture = await new WhirlpoolTestFixture(ctx).init({ - tickSpacing, - positions: [ - { tickLowerIndex, tickUpperIndex, liquidityAmount: new anchor.BN(10_000_000) }, // In range position - { tickLowerIndex: 0, tickUpperIndex: 128, liquidityAmount: new anchor.BN(1_000_000) }, // Out of range position - ], - rewards: [ - { - emissionsPerSecondX64: MathUtil.toX64(new Decimal(10)), - vaultAmount: new BN(vaultStartBalance), - }, - { - emissionsPerSecondX64: MathUtil.toX64(new Decimal(5)), - vaultAmount: new BN(vaultStartBalance), - }, - { - emissionsPerSecondX64: MathUtil.toX64(new Decimal(10)), - vaultAmount: new BN(vaultStartBalance), - }, - ], - }); - const { - poolInitInfo: { whirlpoolPda, tokenVaultAKeypair, tokenVaultBKeypair }, - tokenAccountA, - tokenAccountB, - positions, - } = fixture.getInfos(); - - const pool = await client.getPool(whirlpoolPda.publicKey, IGNORE_CACHE); - - // close ATA for token B - const balanceB = await getTokenBalance(ctx.provider, tokenAccountB); - await toTx(ctx, { - instructions: [ - createBurnInstruction(tokenAccountB, pool.getData().tokenMintB, ctx.wallet.publicKey, BigInt(balanceB.toString())), - createCloseAccountInstruction(tokenAccountB, ctx.wallet.publicKey, ctx.wallet.publicKey), - ], - cleanupInstructions: [], - signers: [], - }).buildAndExecute(); - const tokenAccountBData = await ctx.connection.getAccountInfo(tokenAccountB, "confirmed"); - assert.ok(tokenAccountBData === null); - - const quote = await swapQuoteByInputToken( - pool, - pool.getData().tokenMintA, - new BN(200_000), - Percentage.fromFraction(1, 100), - ctx.program.programId, - ctx.fetcher, - IGNORE_CACHE - ); - - const tx = await pool.swap(quote); - - // check generated instructions - const instructions = tx.compressIx(true).instructions; - const createIxs = instructions.filter((ix) => ix.programId.equals(ASSOCIATED_PROGRAM_ID)); - assert.ok(createIxs.length === 1); - assert.ok(createIxs[0].keys[1].pubkey.equals(tokenAccountB)); - assert.ok(createIxs[0].data.length === 1); - assert.ok(createIxs[0].data[0] === 1); // Idempotent - }); - -}); diff --git a/sdk/tests/tsconfig.json b/sdk/tests/tsconfig.json deleted file mode 100644 index 2339569..0000000 --- a/sdk/tests/tsconfig.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "extends": "../tsconfig-base.json", - "references": [ - { - "path": "../src" - } - ] -} diff --git a/sdk/tests/utils/assert.ts b/sdk/tests/utils/assert.ts deleted file mode 100644 index 0b0980a..0000000 --- a/sdk/tests/utils/assert.ts +++ /dev/null @@ -1,158 +0,0 @@ -import { BN, Program, web3 } from "@coral-xyz/anchor"; -import { ONE } from "@orca-so/common-sdk"; -import { AccountLayout, NATIVE_MINT, getAssociatedTokenAddressSync } from "@solana/spl-token"; -import { PublicKey } from "@solana/web3.js"; -import * as assert from "assert"; -import { SwapQuote, WhirlpoolContext } from "../../src"; -import { Whirlpool } from "../../src/artifacts/whirlpool"; -import { DevFeeSwapQuote } from "../../src/quotes/public/dev-fee-swap-quote"; -import { TickData, WhirlpoolData } from "../../src/types/public"; -import { TEST_TOKEN_PROGRAM_ID } from "./test-consts"; -import { getTokenBalance } from "./token"; -import { VaultAmounts } from "./whirlpools-test-utils"; - -export function assertInputOutputQuoteEqual( - inputTokenQuote: SwapQuote, - outputTokenQuote: SwapQuote -) { - assert.equal(inputTokenQuote.aToB, outputTokenQuote.aToB, "aToB not equal"); - // TODO: Sometimes input & output estimated In is off by 1. Same goes for sqrt-price - assert.ok( - inputTokenQuote.estimatedAmountIn.sub(outputTokenQuote.estimatedAmountIn).abs().lte(ONE), - `input estimated In ${inputTokenQuote.estimatedAmountIn} does not equal output estimated in ${outputTokenQuote.estimatedAmountIn}` - ); - assert.ok( - inputTokenQuote.estimatedAmountOut.sub(outputTokenQuote.estimatedAmountOut).abs().lte(ONE), - `input estimated out ${inputTokenQuote.estimatedAmountOut} does not equal output estimated out ${outputTokenQuote.estimatedAmountOut}` - ); - assert.equal( - inputTokenQuote.estimatedEndTickIndex, - outputTokenQuote.estimatedEndTickIndex, - "estimatedEndTickIndex not equal" - ); - assert.equal( - inputTokenQuote.estimatedFeeAmount.toString(), - outputTokenQuote.estimatedFeeAmount.toString(), - "estimatedFeeAmount not equal" - ); - assert.notEqual( - inputTokenQuote.amountSpecifiedIsInput, - outputTokenQuote.amountSpecifiedIsInput, - "amountSpecifiedIsInput equals" - ); -} - -export function assertDevFeeQuotes( - inputQuote: SwapQuote, - postFeeInputQuote: SwapQuote, - devFeeQuote: DevFeeSwapQuote -) { - assert.equal(inputQuote.aToB, devFeeQuote.aToB, "aToB not equal"); - assert.ok( - devFeeQuote.estimatedAmountIn.eq(inputQuote.estimatedAmountIn), - `the devFeeQuote's estimatedAmountIn ${devFeeQuote.estimatedAmountIn} should equal the normal quote's estimatedAmountIn ${inputQuote.estimatedAmountIn}` - ); - assert.ok( - devFeeQuote.estimatedAmountIn.eq( - postFeeInputQuote.estimatedAmountIn.add(devFeeQuote.devFeeAmount) - ), - `the devFeeQuote's estimatedAmountIn ${devFeeQuote.estimatedAmountIn} should equal the post-fee quote's estimatedAmountIn ${inputQuote.estimatedAmountIn} plus devFeeAmount ${devFeeQuote.devFeeAmount}` - ); - assert.ok( - postFeeInputQuote.estimatedAmountOut.sub(devFeeQuote.estimatedAmountOut).abs().lte(ONE), - `post-fee input estimatedAmountOut ${inputQuote.estimatedAmountOut} does not equal devFee quote estimatedAmountOut - ${devFeeQuote.estimatedAmountOut}` - ); - assert.equal( - postFeeInputQuote.estimatedEndTickIndex, - devFeeQuote.estimatedEndTickIndex, - "estimatedEndTickIndex not equal" - ); - assert.equal( - devFeeQuote.estimatedFeeAmount.toString(), - devFeeQuote.estimatedSwapFeeAmount.add(devFeeQuote.devFeeAmount).toString(), - "devFeeQuote estimatedFeeAmount is not the sum of estimatedSwapFeeAmount and devFeeAmount" - ); - assert.equal( - devFeeQuote.estimatedSwapFeeAmount.toString(), - postFeeInputQuote.estimatedFeeAmount.toString(), - "devFeeQuote's estimatedSwapFeeAmount should equal the quote's total swap fee (without dev fee)" - ); - assert.equal( - postFeeInputQuote.amountSpecifiedIsInput, - devFeeQuote.amountSpecifiedIsInput, - "amountSpecifiedIsInput not equal" - ); -} - -export async function assertDevTokenAmount( - ctx: WhirlpoolContext, - expectationQuote: DevFeeSwapQuote, - swapToken: PublicKey, - devWallet: PublicKey, - preDevWalletLamport = 0 -) { - - if (swapToken.equals(NATIVE_MINT)) { - const walletAmount = await ctx.provider.connection.getBalance(devWallet); - assert.equal(expectationQuote.devFeeAmount.toNumber() + preDevWalletLamport, walletAmount) - return; - } - - const tokenDevWalletAta = getAssociatedTokenAddressSync(swapToken, devWallet); - const afterDevWalletAmount = await getTokenBalance(ctx.provider, tokenDevWalletAta); - assert.equal( - expectationQuote.devFeeAmount, - afterDevWalletAmount, - "incorrect devFee amount sent to dev wallet." - ); -} - -export function assertQuoteAndResults( - aToB: boolean, - quote: SwapQuote, - endData: WhirlpoolData, - beforeVaultAmounts: VaultAmounts, - afterVaultAmounts: VaultAmounts -) { - const tokenADelta = beforeVaultAmounts.tokenA.sub(afterVaultAmounts.tokenA); - const tokenBDelta = beforeVaultAmounts.tokenB.sub(afterVaultAmounts.tokenB); - - assert.equal( - quote.estimatedAmountIn.toString(), - (aToB ? tokenADelta : tokenBDelta).neg().toString() - ); - assert.equal(quote.estimatedAmountOut.toString(), (aToB ? tokenBDelta : tokenADelta).toString()); - assert.equal(endData.tickCurrentIndex, quote.estimatedEndTickIndex); - assert.equal(quote.estimatedEndSqrtPrice.toString(), endData.sqrtPrice.toString()); -} - -// Helper for token vault assertion checks. -export async function asyncAssertTokenVault( - program: Program, - tokenVaultPublicKey: web3.PublicKey, - expectedValues: { - expectedOwner: web3.PublicKey; - expectedMint: web3.PublicKey; - } -) { - const tokenVault: web3.AccountInfo | null = - await program.provider.connection.getAccountInfo(tokenVaultPublicKey); - if (!tokenVault) { - assert.fail(`token vault does not exist at ${tokenVaultPublicKey.toBase58()}`); - } - const tokenVaultAData = AccountLayout.decode(tokenVault.data); - assert.ok(tokenVault.owner.equals(TEST_TOKEN_PROGRAM_ID)); - assert.ok(expectedValues.expectedOwner.equals(new web3.PublicKey(tokenVaultAData.owner))); - assert.ok(expectedValues.expectedMint.equals(new web3.PublicKey(tokenVaultAData.mint))); -} - -export function assertTick( - tick: TickData, - initialized: boolean, - liquidityGross: BN, - liquidityNet: BN -) { - assert.ok(tick.initialized == initialized); - assert.ok(tick.liquidityNet.eq(liquidityNet)); - assert.ok(tick.liquidityGross.eq(liquidityGross)); -} diff --git a/sdk/tests/utils/const.ts b/sdk/tests/utils/const.ts deleted file mode 100644 index 1747a0b..0000000 --- a/sdk/tests/utils/const.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { ConfirmOptions } from "@solana/web3.js"; - -export const defaultConfirmOptions: ConfirmOptions = { - commitment: "confirmed", - preflightCommitment: "confirmed", -} \ No newline at end of file diff --git a/sdk/tests/utils/fixture.ts b/sdk/tests/utils/fixture.ts deleted file mode 100644 index 55b48fb..0000000 --- a/sdk/tests/utils/fixture.ts +++ /dev/null @@ -1,159 +0,0 @@ -import { BN } from "@coral-xyz/anchor"; -import { NATIVE_MINT } from "@solana/spl-token"; -import { Keypair, PublicKey } from "@solana/web3.js"; -import { TickSpacing, ZERO_BN } from "."; -import { InitConfigParams, InitPoolParams, TickUtil, WhirlpoolContext } from "../../src"; -import { - FundedPositionInfo, - FundedPositionParams, - fundPositions, - initRewardAndSetEmissions, - initTestPoolWithTokens, - initTickArray -} from "./init-utils"; - -interface InitFixtureParams { - tickSpacing: number; - initialSqrtPrice?: BN; - positions?: FundedPositionParams[]; - rewards?: RewardParam[]; - tokenAIsNative?: boolean; -} - -interface RewardParam { - emissionsPerSecondX64: BN; - vaultAmount: BN; -} - -interface InitializedRewardInfo { - rewardMint: PublicKey; - rewardVaultKeypair: Keypair; -} - -export class WhirlpoolTestFixture { - private ctx: WhirlpoolContext; - private poolInitInfo: InitPoolParams = defaultPoolInitInfo; - private configInitInfo: InitConfigParams = defaultConfigInitInfo; - private configKeypairs = defaultConfigKeypairs; - private positions: FundedPositionInfo[] = []; - private rewards: InitializedRewardInfo[] = []; - private tokenAccountA = PublicKey.default; - private tokenAccountB = PublicKey.default; - private initialized = false; - - constructor(ctx: WhirlpoolContext) { - this.ctx = ctx; - } - - async init(params: InitFixtureParams): Promise { - const { tickSpacing, initialSqrtPrice, positions, rewards, tokenAIsNative } = params; - - const { poolInitInfo, configInitInfo, configKeypairs, tokenAccountA, tokenAccountB } = - await initTestPoolWithTokens( - this.ctx, - tickSpacing, - initialSqrtPrice, - undefined, - tokenAIsNative ? NATIVE_MINT : undefined - ); - - this.poolInitInfo = poolInitInfo; - this.configInitInfo = configInitInfo; - this.configKeypairs = configKeypairs; - this.tokenAccountA = tokenAccountA; - this.tokenAccountB = tokenAccountB; - - if (positions) { - await initTickArrays(this.ctx, poolInitInfo, positions); - - this.positions = await fundPositions( - this.ctx, - poolInitInfo, - tokenAccountA, - tokenAccountB, - positions - ); - } - - if (rewards) { - const initRewards: InitializedRewardInfo[] = []; - for (let i = 0; i < rewards.length; i++) { - // Iterate because we enforce sequential initialization on the smart contract - initRewards.push( - await initRewardAndSetEmissions( - this.ctx, - configKeypairs.rewardEmissionsSuperAuthorityKeypair, - poolInitInfo.whirlpoolPda.publicKey, - i, - rewards[i].vaultAmount, - rewards[i].emissionsPerSecondX64 - ) - ); - } - this.rewards = initRewards; - } - this.initialized = true; - return this; - } - - getInfos() { - if (!this.initialized) { - throw new Error("Test fixture is not initialized"); - } - return { - poolInitInfo: this.poolInitInfo, - configInitInfo: this.configInitInfo, - configKeypairs: this.configKeypairs, - tokenAccountA: this.tokenAccountA, - tokenAccountB: this.tokenAccountB, - positions: this.positions, - rewards: this.rewards, - }; - } -} - -async function initTickArrays( - ctx: WhirlpoolContext, - poolInitInfo: InitPoolParams, - positions: FundedPositionParams[] -) { - const startTickSet = new Set(); - positions.forEach((p) => { - startTickSet.add(TickUtil.getStartTickIndex(p.tickLowerIndex, poolInitInfo.tickSpacing)); - startTickSet.add(TickUtil.getStartTickIndex(p.tickUpperIndex, poolInitInfo.tickSpacing)); - }); - - return Promise.all( - Array.from(startTickSet).map((startTick) => - initTickArray(ctx, poolInitInfo.whirlpoolPda.publicKey, startTick) - ) - ); -} - -const defaultPoolInitInfo: InitPoolParams = { - initSqrtPrice: ZERO_BN, - whirlpoolsConfig: PublicKey.default, - tokenMintA: PublicKey.default, - tokenMintB: PublicKey.default, - whirlpoolPda: { publicKey: PublicKey.default, bump: 0 }, - tokenVaultAKeypair: Keypair.generate(), - tokenVaultBKeypair: Keypair.generate(), - tickSpacing: TickSpacing.Standard, - feeTierKey: PublicKey.default, - funder: PublicKey.default, -}; - -const defaultConfigInitInfo = { - whirlpoolsConfigKeypair: Keypair.generate(), - feeAuthority: PublicKey.default, - collectProtocolFeesAuthority: PublicKey.default, - rewardEmissionsSuperAuthority: PublicKey.default, - defaultProtocolFeeRate: 0, - funder: PublicKey.default, -}; - -const defaultConfigKeypairs = { - feeAuthorityKeypair: Keypair.generate(), - collectProtocolFeesAuthorityKeypair: Keypair.generate(), - rewardEmissionsSuperAuthorityKeypair: Keypair.generate(), -}; diff --git a/sdk/tests/utils/graph-test-data.ts b/sdk/tests/utils/graph-test-data.ts deleted file mode 100644 index 1fa93f5..0000000 --- a/sdk/tests/utils/graph-test-data.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { Address } from "@coral-xyz/anchor"; -import { PoolTokenPair } from "../../src"; - -export const solConnectedPools: PoolTokenPair[] = [ - { - address: "7qbRF6YsyGuLUVs6Y1q64bdVrfe4ZcUUz1JRdoVNUJnm", - tokenMintA: "So11111111111111111111111111111111111111112", - tokenMintB: "RLBxxFkseAZ4RgJH3Sqn8jXxhmGoz9jWxDNJMh8pL7a", - }, - { - address: "HQcY5n2zP6rW74fyFEhWeBd3LnJpBcZechkvJpmdb8cx", - tokenMintA: "So11111111111111111111111111111111111111112", - tokenMintB: "mSoLzYCxHdYgdzU16g5QSh3i5K3z3KZK7ytfqcJm7So", - }, - { - address: "2AEWSvUds1wsufnsDPCXjFsJCMJH5SNNm7fSF4kxys9a", - tokenMintA: "So11111111111111111111111111111111111111112", - tokenMintB: "DUSTawucrTsGU8hcqRdHDCbuYhCPADMLM2VcCb8VnFnQ", - }, - { - address: "CPsTfDvZYeVB5uTqQZcwwTTBJ7KPFvB6JKLGSWsFZEL7", - tokenMintA: "So11111111111111111111111111111111111111112", - tokenMintB: "7dHbWXmci3dT8UFYWYZweBLXgycu7Y3iL6trKn1Y7ARj", - }, - { - address: "HJPjoWUrhoZzkNfRpHuieeFk9WcZWjwy6PBjZ81ngndJ", - tokenMintA: "So11111111111111111111111111111111111111112", - tokenMintB: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", - }, -]; - -export const usdcConnectedPools: PoolTokenPair[] = [ - { - address: "7PNQ9rfSGCbCC3XTeL6CwwAzevqQGvKXeXMxP2TjS7rM", - tokenMintA: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", - tokenMintB: "RLBxxFkseAZ4RgJH3Sqn8jXxhmGoz9jWxDNJMh8pL7a", - }, - { - address: "7A1R3L7AxcxuZHMJjFgskKGeBR5Rwst3Ai5bv5uAWZFG", - tokenMintA: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", - tokenMintB: "mSoLzYCxHdYgdzU16g5QSh3i5K3z3KZK7ytfqcJm7So", - }, - { - address: "BVXNG6BrL2Tn3NmppnMeXHjBHTaQSnSnLE99JKwZSWPg", - tokenMintA: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", - tokenMintB: "DUSTawucrTsGU8hcqRdHDCbuYhCPADMLM2VcCb8VnFnQ", - }, -]; - -export const oneRouteTwoHopsThroughSOL: [Address, Address] = ["EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", "7dHbWXmci3dT8UFYWYZweBLXgycu7Y3iL6trKn1Y7ARj"]; - -export const feeTierPoolsGraphData: PoolTokenPair[] = [ - { - address: "Gr7WKYBqRLt7oUkjZ54LSbiUf8EgNWcj3ogtN8dKbfeb", - tokenMintA: "mSoLzYCxHdYgdzU16g5QSh3i5K3z3KZK7ytfqcJm7So", - tokenMintB: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", - }, - { - address: "7qbRF6YsyGuLUVs6Y1q64bdVrfe4ZcUUz1JRdoVNUJnm", - tokenMintA: "mSoLzYCxHdYgdzU16g5QSh3i5K3z3KZK7ytfqcJm7So", - tokenMintB: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", - }, - { - address: "67S6KLCtgFZmRYzy6dCDc1v754mmcpK33pZd7Hg2yeVj", - tokenMintA: "mSoLzYCxHdYgdzU16g5QSh3i5K3z3KZK7ytfqcJm7So", - tokenMintB: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", - }, -]; - -export const oneRouteTwoHopsThroughmSOL: [Address, Address] = ["So11111111111111111111111111111111111111112", "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"]; - -export const uniqueTokenMintsGraphData: PoolTokenPair[] = [ - { - address: "5Z66YYYaTmmx1R4mATAGLSc8aV4Vfy5tNdJQzk1GP9RF", - tokenMintA: "USDH1SM1ojwWUga67PGrgFWUHibbjqMvuMaDkRJTgkX", - tokenMintB: "orcaEKTdK7LKz57vaAYr9QeNsVEPfiu6QeMU1kektZE", - }, -]; - -export const uniqueTokenMintsGraphTokenUnsortedData: PoolTokenPair[] = [ - { - address: "5Z66YYYaTmmx1R4mATAGLSc8aV4Vfy5tNdJQzk1GP9RF", - tokenMintA: "orcaEKTdK7LKz57vaAYr9QeNsVEPfiu6QeMU1kektZE", - tokenMintB: "USDH1SM1ojwWUga67PGrgFWUHibbjqMvuMaDkRJTgkX", - }, -]; diff --git a/sdk/tests/utils/index.ts b/sdk/tests/utils/index.ts deleted file mode 100644 index e934fc0..0000000 --- a/sdk/tests/utils/index.ts +++ /dev/null @@ -1,12 +0,0 @@ -export * from "./test-consts"; -export * from "./token"; -export * from "./utils"; -export * from "./assert"; - -export enum TickSpacing { - One = 1, - Stable = 8, - ThirtyTwo = 32, - SixtyFour = 64, - Standard = 128, -} diff --git a/sdk/tests/utils/init-utils.ts b/sdk/tests/utils/init-utils.ts deleted file mode 100644 index 917004d..0000000 --- a/sdk/tests/utils/init-utils.ts +++ /dev/null @@ -1,990 +0,0 @@ -import * as anchor from "@coral-xyz/anchor"; -import { AddressUtil, MathUtil, PDA } from "@orca-so/common-sdk"; -import { NATIVE_MINT, getAssociatedTokenAddressSync } from "@solana/spl-token"; -import { Keypair, PublicKey } from "@solana/web3.js"; -import BN from "bn.js"; -import Decimal from "decimal.js"; -import { - TickSpacing, - ZERO_BN, - createAndMintToAssociatedTokenAccount, - createMint, - mintToDestination -} from "."; -import { - InitConfigParams, - InitFeeTierParams, - InitPoolParams, - InitTickArrayParams, - InitializeRewardParams, - OpenPositionParams, - PDAUtil, - PriceMath, - TICK_ARRAY_SIZE, - TickUtil, - WhirlpoolClient, - WhirlpoolContext, - WhirlpoolIx, - toTx -} from "../../src"; -import { IGNORE_CACHE } from "../../src/network/public/fetcher"; -import { PoolUtil } from "../../src/utils/public/pool-utils"; -import { - TestConfigParams, - TestWhirlpoolsConfigKeypairs, - generateDefaultConfigParams, - generateDefaultInitFeeTierParams, - generateDefaultInitPoolParams, - generateDefaultInitTickArrayParams, - generateDefaultOpenBundledPositionParams, - generateDefaultOpenPositionParams -} from "./test-builders"; - -interface TestPoolParams { - configInitInfo: InitConfigParams; - configKeypairs: TestWhirlpoolsConfigKeypairs; - poolInitInfo: InitPoolParams; - feeTierParams: any; -} - -interface InitTestFeeTierParams { - tickSpacing: number; - feeRate?: number; -} - -interface InitTestPoolParams { - mintIndices: [number, number]; - tickSpacing: number; - feeTierIndex?: number; - initSqrtPrice?: anchor.BN; -} - -interface InitTestMintParams { - // Default false - isNative?: boolean; -} - -interface InitTestTokenAccParams { - mintIndex: number; - mintAmount?: anchor.BN; -} - -interface InitTestTickArrayRangeParams { - poolIndex: number; - startTickIndex: number; - arrayCount: number; - aToB: boolean; -} - -interface InitTestPositionParams { - poolIndex: number; - fundParams: FundedPositionParams[]; -} - -export interface InitAquariumParams { - // Single-ton per aquarium - configParams?: TestConfigParams; - - initFeeTierParams: InitTestFeeTierParams[]; - - initMintParams: InitTestMintParams[]; - - initTokenAccParams: InitTestTokenAccParams[]; - - initPoolParams: InitTestPoolParams[]; - - initTickArrayRangeParams: InitTestTickArrayRangeParams[]; - - initPositionParams: InitTestPositionParams[]; -} - -export interface TestAquarium { - configParams: TestConfigParams; - feeTierParams: InitFeeTierParams[]; - mintKeys: PublicKey[]; - tokenAccounts: { mint: PublicKey; account: PublicKey }[]; - pools: InitPoolParams[]; - tickArrays: { params: InitTestTickArrayRangeParams; pdas: PDA[] }[]; -} - -const DEFAULT_FEE_RATE = 3000; -const DEFAULT_MINT_AMOUNT = new anchor.BN("15000000000"); -const DEFAULT_SQRT_PRICE = MathUtil.toX64(new Decimal(5)); - -const DEFAULT_INIT_FEE_TIER = [{ tickSpacing: TickSpacing.Standard }]; -const DEFAULT_INIT_MINT = [{}, {}]; -const DEFAULT_INIT_TOKEN = [{ mintIndex: 0 }, { mintIndex: 1 }]; -const DEFAULT_INIT_POOL: InitTestPoolParams[] = [ - { mintIndices: [0, 1], tickSpacing: TickSpacing.Standard }, -]; -const DEFAULT_INIT_TICK_ARR: InitTestTickArrayRangeParams[] = []; -const DEFAULT_INIT_POSITION: InitTestPositionParams[] = []; - -export function getDefaultAquarium(): InitAquariumParams { - return { - initFeeTierParams: [...DEFAULT_INIT_FEE_TIER], - initMintParams: [...DEFAULT_INIT_MINT], - initTokenAccParams: [...DEFAULT_INIT_TOKEN], - initPoolParams: [...DEFAULT_INIT_POOL], - initTickArrayRangeParams: [...DEFAULT_INIT_TICK_ARR], - initPositionParams: [...DEFAULT_INIT_POSITION], - }; -} - -export async function buildTestAquariums( - ctx: WhirlpoolContext, - initParams: InitAquariumParams[] -): Promise { - const aquariums = []; - // Airdrop SOL into provider wallet; - await ctx.connection.requestAirdrop(ctx.provider.wallet.publicKey, 100_000_000_000_000); - for (const initParam of initParams) { - // Create configs - let configParams = initParam.configParams; - if (!configParams) { - configParams = generateDefaultConfigParams(ctx); - } - // Could batch - await toTx( - ctx, - WhirlpoolIx.initializeConfigIx(ctx.program, configParams.configInitInfo) - ).buildAndExecute(); - - const { - initFeeTierParams, - initMintParams, - initTokenAccParams, - initPoolParams, - initTickArrayRangeParams, - initPositionParams, - } = initParam; - - const feeTierParams: InitFeeTierParams[] = []; - for (const initFeeTierParam of initFeeTierParams) { - const { tickSpacing } = initFeeTierParam; - const feeRate = - initFeeTierParam.feeRate !== undefined ? initFeeTierParam.feeRate : DEFAULT_FEE_RATE; - const { params } = await initFeeTier( - ctx, - configParams.configInitInfo, - configParams.configKeypairs.feeAuthorityKeypair, - tickSpacing, - feeRate - ); - feeTierParams.push(params); - } - - // TODO: Handle native vs sorted mint keys - const mintKeys = ( - await Promise.all( - initMintParams.map(({ isNative }) => (isNative ? NATIVE_MINT : createMint(ctx.provider))) - ) - ).sort(PoolUtil.compareMints); - - const tokenAccounts = await Promise.all( - initTokenAccParams.map(async (initTokenAccParam) => { - const { mintIndex, mintAmount = DEFAULT_MINT_AMOUNT } = initTokenAccParam; - const mintKey = mintKeys[mintIndex]; - const account = await createAndMintToAssociatedTokenAccount( - ctx.provider, - mintKey, - mintAmount - ); - return { mint: mintKey, account }; - }) - ); - - const pools = await Promise.all( - initPoolParams.map(async (initPoolParam) => { - const { - tickSpacing, - mintIndices, - initSqrtPrice = DEFAULT_SQRT_PRICE, - feeTierIndex = 0, - } = initPoolParam; - const [mintOne, mintTwo] = mintIndices.map((idx) => mintKeys[idx]); - const [tokenMintA, tokenMintB] = PoolUtil.orderMints(mintOne, mintTwo).map( - AddressUtil.toPubKey - ); - - const configKey = configParams!.configInitInfo.whirlpoolsConfigKeypair.publicKey; - const whirlpoolPda = PDAUtil.getWhirlpool( - ctx.program.programId, - configKey, - tokenMintA, - tokenMintB, - tickSpacing - ); - - const poolParam = { - initSqrtPrice, - whirlpoolsConfig: configKey, - tokenMintA, - tokenMintB, - whirlpoolPda, - tokenVaultAKeypair: Keypair.generate(), - tokenVaultBKeypair: Keypair.generate(), - feeTierKey: feeTierParams[feeTierIndex].feeTierPda.publicKey, - tickSpacing, - // TODO: funder - funder: ctx.wallet.publicKey, - }; - - const tx = toTx(ctx, WhirlpoolIx.initializePoolIx(ctx.program, poolParam)); - await tx.buildAndExecute(); - return poolParam; - }) - ); - - const tickArrays = await Promise.all( - initTickArrayRangeParams.map(async (initTickArrayRangeParam) => { - const { poolIndex, startTickIndex, arrayCount, aToB } = initTickArrayRangeParam; - const pool = pools[poolIndex]; - const pdas = await initTickArrayRange( - ctx, - pool.whirlpoolPda.publicKey, - startTickIndex, - arrayCount, - pool.tickSpacing, - aToB - ); - return { - params: initTickArrayRangeParam, - pdas, - }; - }) - ); - - await Promise.all( - initPositionParams.map(async (initPositionParam) => { - const { poolIndex, fundParams } = initPositionParam; - const pool = pools[poolIndex]; - const tokenAccKeys = getTokenAccsForPools([pool], tokenAccounts); - await fundPositions(ctx, pool, tokenAccKeys[0], tokenAccKeys[1], fundParams); - }) - ); - - aquariums.push({ - configParams, - feeTierParams, - mintKeys, - tokenAccounts, - pools, - tickArrays, - }); - } - return aquariums; -} - -export function getTokenAccsForPools( - pools: InitPoolParams[], - tokenAccounts: { mint: PublicKey; account: PublicKey }[] -) { - const mints = []; - for (const pool of pools) { - mints.push(pool.tokenMintA); - mints.push(pool.tokenMintB); - } - return mints.map((mint) => - tokenAccounts.find((acc) => acc.mint.equals(mint))!.account - ); -} - -/** - * Initialize a brand new WhirlpoolsConfig account and construct a set of InitPoolParams - * that can be used to initialize a pool with. - * @param client - an instance of whirlpool client containing the program & provider - * @param initSqrtPrice - the initial sqrt-price for this newly generated pool - * @returns An object containing the params used to init the config account & the param that can be used to init the pool account. - */ -export async function buildTestPoolParams( - ctx: WhirlpoolContext, - tickSpacing: number, - defaultFeeRate = 3000, - initSqrtPrice = DEFAULT_SQRT_PRICE, - funder?: PublicKey, - reuseTokenA?: PublicKey -) { - const { configInitInfo, configKeypairs } = generateDefaultConfigParams(ctx); - await toTx(ctx, WhirlpoolIx.initializeConfigIx(ctx.program, configInitInfo)).buildAndExecute(); - - const { params: feeTierParams } = await initFeeTier( - ctx, - configInitInfo, - configKeypairs.feeAuthorityKeypair, - tickSpacing, - defaultFeeRate - ); - const poolInitInfo = await generateDefaultInitPoolParams( - ctx, - configInitInfo.whirlpoolsConfigKeypair.publicKey, - feeTierParams.feeTierPda.publicKey, - tickSpacing, - initSqrtPrice, - funder, - reuseTokenA - ); - return { - configInitInfo, - configKeypairs, - poolInitInfo, - feeTierParams, - }; -} - -/** - * Initialize a brand new set of WhirlpoolsConfig & Whirlpool account - * @param client - an instance of whirlpool client containing the program & provider - * @param initSqrtPrice - the initial sqrt-price for this newly generated pool - * @returns An object containing the params used to initialize both accounts. - */ -export async function initTestPool( - ctx: WhirlpoolContext, - tickSpacing: number, - initSqrtPrice = DEFAULT_SQRT_PRICE, - funder?: Keypair, - reuseTokenA?: PublicKey -) { - const poolParams = await buildTestPoolParams( - ctx, - tickSpacing, - 3000, - initSqrtPrice, - funder?.publicKey, - reuseTokenA - ); - - return initTestPoolFromParams(ctx, poolParams, funder); -} - -export async function initTestPoolFromParams( - ctx: WhirlpoolContext, - poolParams: TestPoolParams, - funder?: Keypair -) { - const { configInitInfo, poolInitInfo, configKeypairs, feeTierParams } = poolParams; - const tx = toTx(ctx, WhirlpoolIx.initializePoolIx(ctx.program, poolInitInfo)); - if (funder) { - tx.addSigner(funder); - } - - return { - txId: await tx.buildAndExecute(), - configInitInfo, - configKeypairs, - poolInitInfo, - feeTierParams, - }; -} - -export async function initFeeTier( - ctx: WhirlpoolContext, - configInitInfo: InitConfigParams, - feeAuthorityKeypair: Keypair, - tickSpacing: number, - defaultFeeRate: number, - funder?: Keypair -) { - const params = generateDefaultInitFeeTierParams( - ctx, - configInitInfo.whirlpoolsConfigKeypair.publicKey, - configInitInfo.feeAuthority, - tickSpacing, - defaultFeeRate, - funder?.publicKey - ); - - const tx = toTx(ctx, WhirlpoolIx.initializeFeeTierIx(ctx.program, params)).addSigner( - feeAuthorityKeypair - ); - if (funder) { - tx.addSigner(funder); - } - - return { - txId: await tx.buildAndExecute(), - params, - }; -} - -export async function initializeReward( - ctx: WhirlpoolContext, - rewardAuthorityKeypair: anchor.web3.Keypair, - whirlpool: PublicKey, - rewardIndex: number, - funder?: Keypair -): Promise<{ txId: string; params: InitializeRewardParams }> { - const provider = ctx.provider; - const rewardMint = await createMint(provider); - const rewardVaultKeypair = anchor.web3.Keypair.generate(); - - const params = { - rewardAuthority: rewardAuthorityKeypair.publicKey, - funder: funder?.publicKey || ctx.wallet.publicKey, - whirlpool, - rewardMint, - rewardVaultKeypair, - rewardIndex, - }; - - const tx = toTx(ctx, WhirlpoolIx.initializeRewardIx(ctx.program, params)).addSigner( - rewardAuthorityKeypair - ); - if (funder) { - tx.addSigner(funder); - } - - return { - txId: await tx.buildAndExecute(), - params, - }; -} - -export async function initRewardAndSetEmissions( - ctx: WhirlpoolContext, - rewardAuthorityKeypair: anchor.web3.Keypair, - whirlpool: PublicKey, - rewardIndex: number, - vaultAmount: BN | number, - emissionsPerSecondX64: anchor.BN, - funder?: Keypair -) { - const { - params: { rewardMint, rewardVaultKeypair }, - } = await initializeReward(ctx, rewardAuthorityKeypair, whirlpool, rewardIndex, funder); - - await mintToDestination(ctx.provider, rewardMint, rewardVaultKeypair.publicKey, vaultAmount); - - await toTx( - ctx, - WhirlpoolIx.setRewardEmissionsIx(ctx.program, { - rewardAuthority: rewardAuthorityKeypair.publicKey, - whirlpool, - rewardIndex, - rewardVaultKey: rewardVaultKeypair.publicKey, - emissionsPerSecondX64, - }) - ) - .addSigner(rewardAuthorityKeypair) - .buildAndExecute(); - return { rewardMint, rewardVaultKeypair }; -} - -export async function openPosition( - ctx: WhirlpoolContext, - whirlpool: PublicKey, - tickLowerIndex: number, - tickUpperIndex: number, - owner: PublicKey = ctx.provider.wallet.publicKey, - funder?: Keypair -) { - return openPositionWithOptMetadata( - ctx, - whirlpool, - tickLowerIndex, - tickUpperIndex, - false, - owner, - funder - ); -} - -export async function openPositionWithMetadata( - ctx: WhirlpoolContext, - whirlpool: PublicKey, - tickLowerIndex: number, - tickUpperIndex: number, - owner: PublicKey = ctx.provider.wallet.publicKey, - funder?: Keypair -) { - return openPositionWithOptMetadata( - ctx, - whirlpool, - tickLowerIndex, - tickUpperIndex, - true, - owner, - funder - ); -} - -async function openPositionWithOptMetadata( - ctx: WhirlpoolContext, - whirlpool: PublicKey, - tickLowerIndex: number, - tickUpperIndex: number, - withMetadata: boolean = false, - owner: PublicKey = ctx.provider.wallet.publicKey, - funder?: Keypair -) { - const { params, mint } = await generateDefaultOpenPositionParams( - ctx, - whirlpool, - tickLowerIndex, - tickUpperIndex, - owner, - funder?.publicKey || ctx.provider.wallet.publicKey - ); - let tx = withMetadata - ? toTx(ctx, WhirlpoolIx.openPositionWithMetadataIx(ctx.program, params)) - : toTx(ctx, WhirlpoolIx.openPositionIx(ctx.program, params)); - tx.addSigner(mint); - if (funder) { - tx.addSigner(funder); - } - const txId = await tx.buildAndExecute(); - return { txId, params, mint }; -} - -export async function initTickArray( - ctx: WhirlpoolContext, - whirlpool: PublicKey, - startTickIndex: number, - funder?: Keypair -): Promise<{ txId: string; params: InitTickArrayParams }> { - const params = generateDefaultInitTickArrayParams( - ctx, - whirlpool, - startTickIndex, - funder?.publicKey - ); - const tx = toTx(ctx, WhirlpoolIx.initTickArrayIx(ctx.program, params)); - if (funder) { - tx.addSigner(funder); - } - return { txId: await tx.buildAndExecute(), params }; -} - -export async function initTestPoolWithTokens( - ctx: WhirlpoolContext, - tickSpacing: number, - initSqrtPrice = DEFAULT_SQRT_PRICE, - mintAmount = new anchor.BN("15000000000"), - reuseTokenA?: PublicKey -) { - const provider = ctx.provider; - - const { poolInitInfo, configInitInfo, configKeypairs, feeTierParams } = await initTestPool( - ctx, - tickSpacing, - initSqrtPrice, - undefined, - reuseTokenA - ); - - const { tokenMintA, tokenMintB, whirlpoolPda } = poolInitInfo; - - // Airdrop SOL into provider's wallet for SOL native token testing. - const connection = ctx.provider.connection; - const airdropTx = await connection.requestAirdrop( - ctx.provider.wallet.publicKey, - 100_000_000_000_000 - ); - await ctx.connection.confirmTransaction({ - signature: airdropTx, - ...(await ctx.connection.getLatestBlockhash("confirmed")), - }, "confirmed"); - - const tokenAccountA = await createAndMintToAssociatedTokenAccount( - provider, - tokenMintA, - mintAmount - ); - - const tokenAccountB = await createAndMintToAssociatedTokenAccount( - provider, - tokenMintB, - mintAmount - ); - - return { - poolInitInfo, - configInitInfo, - configKeypairs, - feeTierParams, - whirlpoolPda, - tokenAccountA, - tokenAccountB, - }; -} - -export async function initTickArrayRange( - ctx: WhirlpoolContext, - whirlpool: PublicKey, - startTickIndex: number, - arrayCount: number, - tickSpacing: number, - aToB: boolean -): Promise { - const ticksInArray = tickSpacing * TICK_ARRAY_SIZE; - const direction = aToB ? -1 : 1; - const result: PDA[] = []; - - for (let i = 0; i < arrayCount; i++) { - const { params } = await initTickArray( - ctx, - whirlpool, - startTickIndex + direction * ticksInArray * i - ); - result.push(params.tickArrayPda); - } - - return result; -} - -export type FundedPositionParams = { - tickLowerIndex: number; - tickUpperIndex: number; - liquidityAmount: anchor.BN; -}; - -export async function withdrawPositions( - ctx: WhirlpoolContext, - positionInfos: FundedPositionInfo[], - tokenOwnerAccountA: PublicKey, - tokenOwnerAccountB: PublicKey -) { - const fetcher = ctx.fetcher; - await Promise.all( - positionInfos.map(async (info) => { - const pool = await fetcher.getPool(info.initParams.whirlpool); - const position = await fetcher.getPosition(info.initParams.positionPda.publicKey); - - if (!pool) { - throw new Error(`Failed to fetch pool - ${info.initParams.whirlpool}`); - } - - if (!position) { - throw new Error(`Failed to fetch position - ${info.initParams.whirlpool}`); - } - - const priceLower = PriceMath.tickIndexToSqrtPriceX64(position.tickLowerIndex); - const priceUpper = PriceMath.tickIndexToSqrtPriceX64(position.tickUpperIndex); - - const { tokenA, tokenB } = PoolUtil.getTokenAmountsFromLiquidity( - position.liquidity, - pool.sqrtPrice, - priceLower, - priceUpper, - false - ); - - const numTicksInTickArray = pool.tickSpacing * TICK_ARRAY_SIZE; - const lowerStartTick = - position.tickLowerIndex - (position.tickLowerIndex % numTicksInTickArray); - const tickArrayLower = PDAUtil.getTickArray( - ctx.program.programId, - info.initParams.whirlpool, - lowerStartTick - ); - const upperStartTick = - position.tickUpperIndex - (position.tickUpperIndex % numTicksInTickArray); - const tickArrayUpper = PDAUtil.getTickArray( - ctx.program.programId, - info.initParams.whirlpool, - upperStartTick - ); - - await toTx( - ctx, - WhirlpoolIx.decreaseLiquidityIx(ctx.program, { - liquidityAmount: position.liquidity, - tokenMinA: tokenA, - tokenMinB: tokenB, - whirlpool: info.initParams.whirlpool, - positionAuthority: ctx.provider.wallet.publicKey, - position: info.initParams.positionPda.publicKey, - positionTokenAccount: info.initParams.positionTokenAccount, - tokenOwnerAccountA, - tokenOwnerAccountB, - tokenVaultA: pool.tokenVaultA, - tokenVaultB: pool.tokenVaultB, - tickArrayLower: tickArrayLower.publicKey, - tickArrayUpper: tickArrayUpper.publicKey, - }) - ).buildAndExecute(); - - await toTx( - ctx, - WhirlpoolIx.collectFeesIx(ctx.program, { - whirlpool: info.initParams.whirlpool, - positionAuthority: ctx.provider.wallet.publicKey, - position: info.initParams.positionPda.publicKey, - positionTokenAccount: info.initParams.positionTokenAccount, - tokenOwnerAccountA, - tokenOwnerAccountB, - tokenVaultA: pool.tokenVaultA, - tokenVaultB: pool.tokenVaultB, - }) - ).buildAndExecute(); - }) - ); -} - -export interface FundedPositionInfo { - initParams: OpenPositionParams; - publicKey: PublicKey; - tokenAccount: PublicKey; - mintKeypair: Keypair; - tickArrayLower: PublicKey; - tickArrayUpper: PublicKey; -} - -export async function fundPositionsWithClient( - client: WhirlpoolClient, - whirlpoolKey: PublicKey, - fundParams: FundedPositionParams[] -) { - const whirlpool = await client.getPool(whirlpoolKey, IGNORE_CACHE); - const whirlpoolData = whirlpool.getData(); - await Promise.all( - fundParams.map(async (param, idx) => { - const { tokenA, tokenB } = PoolUtil.getTokenAmountsFromLiquidity( - param.liquidityAmount, - whirlpoolData.sqrtPrice, - PriceMath.tickIndexToSqrtPriceX64(param.tickLowerIndex), - PriceMath.tickIndexToSqrtPriceX64(param.tickUpperIndex), - true - ); - - const { tx } = await whirlpool.openPosition(param.tickLowerIndex, param.tickUpperIndex, { - liquidityAmount: param.liquidityAmount, - tokenMaxA: tokenA, - tokenMaxB: tokenB, - }); - await tx.buildAndExecute(); - }) - ); -} - -export async function fundPositions( - ctx: WhirlpoolContext, - poolInitInfo: InitPoolParams, - tokenAccountA: PublicKey, - tokenAccountB: PublicKey, - fundParams: FundedPositionParams[] -): Promise { - const { - whirlpoolPda: { publicKey: whirlpool }, - tickSpacing, - tokenVaultAKeypair, - tokenVaultBKeypair, - initSqrtPrice, - } = poolInitInfo; - - return await Promise.all( - fundParams.map(async (param): Promise => { - const { params: positionInfo, mint } = await openPosition( - ctx, - whirlpool, - param.tickLowerIndex, - param.tickUpperIndex - ); - - const tickArrayLower = PDAUtil.getTickArray( - ctx.program.programId, - whirlpool, - TickUtil.getStartTickIndex(param.tickLowerIndex, tickSpacing) - ).publicKey; - - const tickArrayUpper = PDAUtil.getTickArray( - ctx.program.programId, - whirlpool, - TickUtil.getStartTickIndex(param.tickUpperIndex, tickSpacing) - ).publicKey; - - if (param.liquidityAmount.gt(ZERO_BN)) { - const { tokenA, tokenB } = PoolUtil.getTokenAmountsFromLiquidity( - param.liquidityAmount, - initSqrtPrice, - PriceMath.tickIndexToSqrtPriceX64(param.tickLowerIndex), - PriceMath.tickIndexToSqrtPriceX64(param.tickUpperIndex), - true - ); - await toTx( - ctx, - WhirlpoolIx.increaseLiquidityIx(ctx.program, { - liquidityAmount: param.liquidityAmount, - tokenMaxA: tokenA, - tokenMaxB: tokenB, - whirlpool: whirlpool, - positionAuthority: ctx.provider.wallet.publicKey, - position: positionInfo.positionPda.publicKey, - positionTokenAccount: positionInfo.positionTokenAccount, - tokenOwnerAccountA: tokenAccountA, - tokenOwnerAccountB: tokenAccountB, - tokenVaultA: tokenVaultAKeypair.publicKey, - tokenVaultB: tokenVaultBKeypair.publicKey, - tickArrayLower, - tickArrayUpper, - }) - ).buildAndExecute(); - } - return { - initParams: positionInfo, - publicKey: positionInfo.positionPda.publicKey, - tokenAccount: positionInfo.positionTokenAccount, - mintKeypair: mint, - tickArrayLower, - tickArrayUpper, - }; - }) - ); -} - -export async function initTestPoolWithLiquidity( - ctx: WhirlpoolContext, - initSqrtPrice = DEFAULT_SQRT_PRICE, - mintAmount = new anchor.BN("15000000000"), - reuseTokenA?: PublicKey -) { - const { - poolInitInfo, - configInitInfo, - configKeypairs, - feeTierParams, - whirlpoolPda, - tokenAccountA, - tokenAccountB, - } = await initTestPoolWithTokens( - ctx, - TickSpacing.Standard, - initSqrtPrice, - mintAmount, - reuseTokenA - ); - - const tickArrays = await initTickArrayRange( - ctx, - whirlpoolPda.publicKey, - 22528, // to 33792 - 3, - TickSpacing.Standard, - false - ); - - const fundParams: FundedPositionParams[] = [ - { - liquidityAmount: new anchor.BN(100_000), - tickLowerIndex: 27904, - tickUpperIndex: 33408, - }, - ]; - - const positionInfos = await fundPositions( - ctx, - poolInitInfo, - tokenAccountA, - tokenAccountB, - fundParams - ); - - return { - poolInitInfo, - configInitInfo, - configKeypairs, - positionInfo: positionInfos[0].initParams, - tokenAccountA, - tokenAccountB, - tickArrays, - feeTierParams, - }; -} - -export async function initializePositionBundleWithMetadata( - ctx: WhirlpoolContext, - owner: PublicKey = ctx.provider.wallet.publicKey, - funder?: Keypair -) { - const positionBundleMintKeypair = Keypair.generate(); - const positionBundlePda = PDAUtil.getPositionBundle(ctx.program.programId, positionBundleMintKeypair.publicKey); - const positionBundleMetadataPda = PDAUtil.getPositionBundleMetadata(positionBundleMintKeypair.publicKey); - const positionBundleTokenAccount = getAssociatedTokenAddressSync(positionBundleMintKeypair.publicKey, owner); - - const tx = toTx(ctx, WhirlpoolIx.initializePositionBundleWithMetadataIx( - ctx.program, - { - positionBundleMintKeypair, - positionBundlePda, - positionBundleMetadataPda, - owner, - positionBundleTokenAccount, - funder: !!funder ? funder.publicKey : owner, - }, - )); - if (funder) { - tx.addSigner(funder); - } - - const txId = await tx.buildAndExecute(); - - return { - txId, - positionBundleMintKeypair, - positionBundlePda, - positionBundleMetadataPda, - positionBundleTokenAccount, - }; -} - -export async function initializePositionBundle( - ctx: WhirlpoolContext, - owner: PublicKey = ctx.provider.wallet.publicKey, - funder?: Keypair -) { - const positionBundleMintKeypair = Keypair.generate(); - const positionBundlePda = PDAUtil.getPositionBundle(ctx.program.programId, positionBundleMintKeypair.publicKey); - const positionBundleTokenAccount = getAssociatedTokenAddressSync(positionBundleMintKeypair.publicKey, owner); - - const tx = toTx(ctx, WhirlpoolIx.initializePositionBundleIx( - ctx.program, - { - positionBundleMintKeypair, - positionBundlePda, - owner, - positionBundleTokenAccount, - funder: !!funder ? funder.publicKey : owner, - }, - )); - if (funder) { - tx.addSigner(funder); - } - - const txId = await tx.buildAndExecute(); - - return { - txId, - positionBundleMintKeypair, - positionBundlePda, - positionBundleTokenAccount, - }; -} - -export async function openBundledPosition( - ctx: WhirlpoolContext, - whirlpool: PublicKey, - positionBundleMint: PublicKey, - bundleIndex: number, - tickLowerIndex: number, - tickUpperIndex: number, - owner: PublicKey = ctx.provider.wallet.publicKey, - funder?: Keypair -) { - const { params } = await generateDefaultOpenBundledPositionParams( - ctx, - whirlpool, - positionBundleMint, - bundleIndex, - tickLowerIndex, - tickUpperIndex, - owner, - funder?.publicKey || owner - ); - - const tx = toTx(ctx, WhirlpoolIx.openBundledPositionIx(ctx.program, params)); - if (funder) { - tx.addSigner(funder); - } - const txId = await tx.buildAndExecute(); - return { txId, params }; -} diff --git a/sdk/tests/utils/pool-utils.test.ts b/sdk/tests/utils/pool-utils.test.ts deleted file mode 100644 index b25e6cd..0000000 --- a/sdk/tests/utils/pool-utils.test.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { PublicKey } from "@solana/web3.js"; -import { PoolUtil } from "../../src/utils/public/pool-utils"; -import * as assert from "assert"; - -const MINTS: { [symbol: string]: PublicKey } = { - FTM: new PublicKey("EsPKhGTMf3bGoy4Qm7pCv3UCcWqAmbC1UGHBTDxRjjD4"), - SOL: new PublicKey("So11111111111111111111111111111111111111112"), - mSOL: new PublicKey("mSoLzYCxHdYgdzU16g5QSh3i5K3z3KZK7ytfqcJm7So"), - USDH: new PublicKey("USDH1SM1ojwWUga67PGrgFWUHibbjqMvuMaDkRJTgkX"), - stSOL: new PublicKey("7dHbWXmci3dT8UFYWYZweBLXgycu7Y3iL6trKn1Y7ARj"), - BTC: new PublicKey("9n4nbM75f5Ui33ZbPYXn59EwSgE8CGsHtAeTH5YFeJ9E"), - whETH: new PublicKey("7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs"), - USDC: new PublicKey("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"), - USDT: new PublicKey("Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB"), - ORCA: new PublicKey("orcaEKTdK7LKz57vaAYr9QeNsVEPfiu6QeMU1kektZE"), -}; - -describe("determine base quote token ordering", () => { - it("USD stables", async () => { - // USDC/FTM => FTM/USDC - let pair = PoolUtil.toBaseQuoteOrder(MINTS.USDC, MINTS.FTM); - assert.equal(MINTS.FTM, pair[0]); - assert.equal(MINTS.USDC, pair[1]); - - // USDT/USDC => USDC/USDT - pair = PoolUtil.toBaseQuoteOrder(MINTS.USDT, MINTS.USDC); - assert.equal(MINTS.USDC, pair[0]); - assert.equal(MINTS.USDT, pair[1]); - - // USDH/stSOL => stSOL/USDH - pair = PoolUtil.toBaseQuoteOrder(MINTS.USDH, MINTS.stSOL); - assert.equal(MINTS.stSOL, pair[0]); - assert.equal(MINTS.USDH, pair[1]); - }); - - it("SOL variants", async () => { - // SOL/mSOL => mSOL/SOL - let pair = PoolUtil.toBaseQuoteOrder(MINTS.SOL, MINTS.mSOL); - assert.equal(MINTS.mSOL, pair[0]); - assert.equal(MINTS.SOL, pair[1]); - - // mSOL/BTC => BTC/mSOL - pair = PoolUtil.toBaseQuoteOrder(MINTS.mSOL, MINTS.BTC); - assert.equal(MINTS.BTC, pair[0]); - assert.equal(MINTS.mSOL, pair[1]); - - // mSOL/whETH => whETH/mSOL - pair = PoolUtil.toBaseQuoteOrder(MINTS.mSOL, MINTS.whETH); - assert.equal(MINTS.whETH, pair[0]); - assert.equal(MINTS.mSOL, pair[1]); - }); - - it("Order remains unchanged for exotic pairs", async () => { - // FTM/ORCA => FTM/ORCA (unchanged) - const pair = PoolUtil.toBaseQuoteOrder(MINTS.FTM, MINTS.ORCA); - assert.equal(MINTS.FTM, pair[0]); - assert.equal(MINTS.ORCA, pair[1]); - }); -}); diff --git a/sdk/tests/utils/swap-test-utils.ts b/sdk/tests/utils/swap-test-utils.ts deleted file mode 100644 index a97e3fc..0000000 --- a/sdk/tests/utils/swap-test-utils.ts +++ /dev/null @@ -1,76 +0,0 @@ -import * as anchor from "@coral-xyz/anchor"; -import { Percentage } from "@orca-so/common-sdk"; -import { NATIVE_MINT } from "@solana/spl-token"; -import { PublicKey } from "@solana/web3.js"; -import BN from "bn.js"; -import { TickSpacing } from "."; -import { TICK_ARRAY_SIZE, Whirlpool, WhirlpoolClient, WhirlpoolContext } from "../../src"; -import { IGNORE_CACHE } from "../../src/network/public/fetcher"; -import { - FundedPositionParams, - fundPositionsWithClient, - initTestPoolWithTokens -} from "./init-utils"; - -export interface SwapTestPoolParams { - ctx: WhirlpoolContext; - client: WhirlpoolClient; - tickSpacing: TickSpacing; - initSqrtPrice: anchor.BN; - initArrayStartTicks: number[]; - fundedPositions: FundedPositionParams[]; - tokenMintAmount?: anchor.BN; -} - -export interface SwapTestSwapParams { - swapAmount: BN; - aToB: boolean; - amountSpecifiedIsInput: boolean; - slippageTolerance: Percentage; - tickArrayAddresses: PublicKey[]; -} - -export interface SwapTestSetup { - whirlpool: Whirlpool; - tickArrayAddresses: PublicKey[]; -} - -export async function setupSwapTest(setup: SwapTestPoolParams, tokenAIsNative = false) { - const { whirlpoolPda } = await initTestPoolWithTokens( - setup.ctx, - setup.tickSpacing, - setup.initSqrtPrice, - setup.tokenMintAmount, - tokenAIsNative ? NATIVE_MINT : undefined - ); - - const whirlpool = await setup.client.getPool(whirlpoolPda.publicKey, IGNORE_CACHE); - - await (await whirlpool.initTickArrayForTicks(setup.initArrayStartTicks))?.buildAndExecute(); - - await fundPositionsWithClient(setup.client, whirlpoolPda.publicKey, setup.fundedPositions); - - return whirlpool; -} - -export interface ArrayTickIndex { - arrayIndex: number; - offsetIndex: number; -} - -export function arrayTickIndexToTickIndex(index: ArrayTickIndex, tickSpacing: number) { - return index.arrayIndex * TICK_ARRAY_SIZE * tickSpacing + index.offsetIndex * tickSpacing; -} - -export function buildPosition( - lower: ArrayTickIndex, - upper: ArrayTickIndex, - tickSpacing: number, - liquidityAmount: anchor.BN -) { - return { - tickLowerIndex: arrayTickIndexToTickIndex(lower, tickSpacing), - tickUpperIndex: arrayTickIndexToTickIndex(upper, tickSpacing), - liquidityAmount, - }; -} diff --git a/sdk/tests/utils/test-builders.ts b/sdk/tests/utils/test-builders.ts deleted file mode 100644 index da8e910..0000000 --- a/sdk/tests/utils/test-builders.ts +++ /dev/null @@ -1,277 +0,0 @@ -import { AnchorProvider } from "@coral-xyz/anchor"; -import { AddressUtil, MathUtil, PDA, Percentage } from "@orca-so/common-sdk"; -import { - getAssociatedTokenAddressSync -} from "@solana/spl-token"; -import { Keypair, PublicKey } from "@solana/web3.js"; -import Decimal from "decimal.js"; -import { createAndMintToAssociatedTokenAccount, createMint } from "."; -import { - InitConfigParams, - InitFeeTierParams, - InitPoolParams, - InitTickArrayParams, OpenBundledPositionParams, OpenPositionParams, PDAUtil, - PoolUtil, - PriceMath, - Whirlpool, - increaseLiquidityQuoteByInputTokenUsingPriceSlippage, -} from "../../src"; -import { WhirlpoolContext } from "../../src/context"; - -export interface TestWhirlpoolsConfigKeypairs { - feeAuthorityKeypair: Keypair; - collectProtocolFeesAuthorityKeypair: Keypair; - rewardEmissionsSuperAuthorityKeypair: Keypair; -} - -export interface TestConfigParams { - configInitInfo: InitConfigParams; - configKeypairs: TestWhirlpoolsConfigKeypairs; -} - -export const generateDefaultConfigParams = ( - context: WhirlpoolContext, - funder?: PublicKey -): TestConfigParams => { - const configKeypairs: TestWhirlpoolsConfigKeypairs = { - feeAuthorityKeypair: Keypair.generate(), - collectProtocolFeesAuthorityKeypair: Keypair.generate(), - rewardEmissionsSuperAuthorityKeypair: Keypair.generate(), - }; - const configInitInfo = { - whirlpoolsConfigKeypair: Keypair.generate(), - feeAuthority: configKeypairs.feeAuthorityKeypair.publicKey, - collectProtocolFeesAuthority: configKeypairs.collectProtocolFeesAuthorityKeypair.publicKey, - rewardEmissionsSuperAuthority: configKeypairs.rewardEmissionsSuperAuthorityKeypair.publicKey, - defaultProtocolFeeRate: 300, - funder: funder || context.wallet.publicKey, - }; - return { configInitInfo, configKeypairs }; -}; - -export const createInOrderMints = async (context: WhirlpoolContext, reuseTokenA?: PublicKey) => { - const provider = context.provider; - const tokenXMintPubKey = reuseTokenA ?? (await createMint(provider)); - - // ensure reuseTokenA is the first mint if reuseTokenA is provided - let ordered; - do { - const tokenYMintPubKey = await createMint(provider); - ordered = PoolUtil.orderMints(tokenXMintPubKey, tokenYMintPubKey).map(AddressUtil.toPubKey); - } while (!!reuseTokenA && !ordered[0].equals(reuseTokenA)); - return ordered; -}; - -export const generateDefaultInitPoolParams = async ( - context: WhirlpoolContext, - configKey: PublicKey, - feeTierKey: PublicKey, - tickSpacing: number, - initSqrtPrice = MathUtil.toX64(new Decimal(5)), - funder?: PublicKey, - reuseTokenA?: PublicKey -): Promise => { - const [tokenAMintPubKey, tokenBMintPubKey] = await createInOrderMints(context, reuseTokenA); - - const whirlpoolPda = PDAUtil.getWhirlpool( - context.program.programId, - configKey, - tokenAMintPubKey, - tokenBMintPubKey, - tickSpacing - ); - - return { - initSqrtPrice, - whirlpoolsConfig: configKey, - tokenMintA: tokenAMintPubKey, - tokenMintB: tokenBMintPubKey, - whirlpoolPda, - tokenVaultAKeypair: Keypair.generate(), - tokenVaultBKeypair: Keypair.generate(), - feeTierKey, - tickSpacing, - funder: funder || context.wallet.publicKey, - }; -}; - -export const generateDefaultInitFeeTierParams = ( - context: WhirlpoolContext, - whirlpoolsConfigKey: PublicKey, - whirlpoolFeeAuthority: PublicKey, - tickSpacing: number, - defaultFeeRate: number, - funder?: PublicKey -): InitFeeTierParams => { - const feeTierPda = PDAUtil.getFeeTier( - context.program.programId, - whirlpoolsConfigKey, - tickSpacing - ); - return { - feeTierPda, - whirlpoolsConfig: whirlpoolsConfigKey, - tickSpacing, - defaultFeeRate, - feeAuthority: whirlpoolFeeAuthority, - funder: funder || context.wallet.publicKey, - }; -}; - -export const generateDefaultInitTickArrayParams = ( - context: WhirlpoolContext, - whirlpool: PublicKey, - startTick: number, - funder?: PublicKey -): InitTickArrayParams => { - const tickArrayPda = PDAUtil.getTickArray(context.program.programId, whirlpool, startTick); - - return { - whirlpool, - tickArrayPda: tickArrayPda, - startTick, - funder: funder || context.wallet.publicKey, - }; -}; - -export async function generateDefaultOpenPositionParams( - context: WhirlpoolContext, - whirlpool: PublicKey, - tickLowerIndex: number, - tickUpperIndex: number, - owner: PublicKey, - funder?: PublicKey -): Promise<{ params: Required; mint: Keypair }> { - const positionMintKeypair = Keypair.generate(); - const positionPda = PDAUtil.getPosition(context.program.programId, positionMintKeypair.publicKey); - - const metadataPda = PDAUtil.getPositionMetadata(positionMintKeypair.publicKey); - - const positionTokenAccountAddress = getAssociatedTokenAddressSync(positionMintKeypair.publicKey, owner) - - const params: Required = { - funder: funder || context.wallet.publicKey, - owner: owner, - positionPda, - metadataPda, - positionMintAddress: positionMintKeypair.publicKey, - positionTokenAccount: positionTokenAccountAddress, - whirlpool: whirlpool, - tickLowerIndex, - tickUpperIndex, - }; - return { - params, - mint: positionMintKeypair, - }; -} - -export async function mintTokensToTestAccount( - provider: AnchorProvider, - tokenAMint: PublicKey, - tokenMintForA: number, - tokenBMint: PublicKey, - tokenMintForB: number, - destinationWallet?: PublicKey -) { - const userTokenAAccount = await createAndMintToAssociatedTokenAccount( - provider, - tokenAMint, - tokenMintForA, - destinationWallet - ); - const userTokenBAccount = await createAndMintToAssociatedTokenAccount( - provider, - tokenBMint, - tokenMintForB, - destinationWallet - ); - - return [userTokenAAccount, userTokenBAccount]; -} - -export async function initPosition( - ctx: WhirlpoolContext, - pool: Whirlpool, - lowerPrice: Decimal, - upperPrice: Decimal, - inputTokenMint: PublicKey, - inputTokenAmount: number, - sourceWallet?: Keypair -) { - const sourceWalletKey = sourceWallet ? sourceWallet.publicKey : ctx.wallet.publicKey; - const tokenADecimal = pool.getTokenAInfo().decimals; - const tokenBDecimal = pool.getTokenBInfo().decimals; - const tickSpacing = pool.getData().tickSpacing; - const lowerTick = PriceMath.priceToInitializableTickIndex( - lowerPrice, - tokenADecimal, - tokenBDecimal, - tickSpacing - ); - const upperTick = PriceMath.priceToInitializableTickIndex( - upperPrice, - tokenADecimal, - tokenBDecimal, - tickSpacing - ); - const quote = await increaseLiquidityQuoteByInputTokenUsingPriceSlippage( - inputTokenMint, - new Decimal(inputTokenAmount), - lowerTick, - upperTick, - Percentage.fromFraction(1, 100), - pool - ); - - // [Action] Open Position (and increase L) - const { positionMint, tx } = await pool.openPosition( - lowerTick, - upperTick, - quote, - sourceWalletKey, - ctx.wallet.publicKey - ); - - if (sourceWallet) { - tx.addSigner(sourceWallet); - } - - await tx.buildAndExecute(); - - return { - positionMint, - positionAddress: PDAUtil.getPosition(ctx.program.programId, positionMint), - }; -} - -export async function generateDefaultOpenBundledPositionParams( - context: WhirlpoolContext, - whirlpool: PublicKey, - positionBundleMint: PublicKey, - bundleIndex: number, - tickLowerIndex: number, - tickUpperIndex: number, - owner: PublicKey, - funder?: PublicKey -): Promise<{ params: Required }> { - const bundledPositionPda = PDAUtil.getBundledPosition(context.program.programId, positionBundleMint, bundleIndex); - const positionBundle = PDAUtil.getPositionBundle(context.program.programId, positionBundleMint).publicKey; - - const positionBundleTokenAccount = getAssociatedTokenAddressSync(positionBundleMint, owner); - - const params: Required = { - bundleIndex, - bundledPositionPda, - positionBundle, - positionBundleAuthority: owner, - funder: funder || owner, - positionBundleTokenAccount, - whirlpool: whirlpool, - tickLowerIndex, - tickUpperIndex, - }; - return { - params, - }; -} diff --git a/sdk/tests/utils/test-consts.ts b/sdk/tests/utils/test-consts.ts deleted file mode 100644 index 82d7673..0000000 --- a/sdk/tests/utils/test-consts.ts +++ /dev/null @@ -1,11 +0,0 @@ -import * as anchor from "@coral-xyz/anchor"; -import { TOKEN_PROGRAM_ID } from "@solana/spl-token"; -import { BN } from "bn.js"; - -export const TEST_TOKEN_PROGRAM_ID = new anchor.web3.PublicKey(TOKEN_PROGRAM_ID.toString()); - -export const ZERO_BN = new anchor.BN(0); - -export const ONE_SOL = 1000000000; - -export const MAX_U64 = new BN(new anchor.BN(2).pow(new anchor.BN(64)).sub(new anchor.BN(1)).toString()); diff --git a/sdk/tests/utils/testDataTypes.ts b/sdk/tests/utils/testDataTypes.ts deleted file mode 100644 index 5c4ab0a..0000000 --- a/sdk/tests/utils/testDataTypes.ts +++ /dev/null @@ -1,115 +0,0 @@ -import { ZERO } from "@orca-so/common-sdk"; -import { Keypair, PublicKey } from "@solana/web3.js"; -import { BN } from "bn.js"; -import invariant from "tiny-invariant"; -import { - PDAUtil, - POSITION_BUNDLE_SIZE, - PositionBundleData, - PriceMath, - TICK_ARRAY_SIZE, - TickArray, - TickArrayData, - TickData, - WhirlpoolContext -} from "../../src"; -import { IGNORE_CACHE, WhirlpoolAccountFetcherInterface } from "../../src/network/public/fetcher"; - -export const testWhirlpoolData = { - whirlpoolsConfig: Keypair.generate().publicKey, - whirlpoolBump: [], - feeRate: 300, - protocolFeeRate: 1800, - liquidity: new BN("32523523532"), - sqrtPrice: new BN("32523523532"), - tickCurrentIndex: PriceMath.sqrtPriceX64ToTickIndex(new BN("32523523532")), - protocolFeeOwedA: new BN("2314532532"), - protocolFeeOwedB: new BN("2314532532"), - tokenMintA: Keypair.generate().publicKey, - tokenVaultA: Keypair.generate().publicKey, - feeGrowthGlobalA: new BN("32532523523523523"), - tokenMintB: Keypair.generate().publicKey, - tokenVaultB: Keypair.generate().publicKey, - feeGrowthGlobalB: new BN("32532523523523523"), - rewardLastUpdatedTimestamp: new BN("3253252312412523523523"), - rewardInfos: [], - tickSpacing: 64, -}; - -export const testInitializedTickData: TickData = { - feeGrowthOutsideA: ZERO, - feeGrowthOutsideB: ZERO, - initialized: true, - liquidityGross: ZERO, - liquidityNet: ZERO, - rewardGrowthsOutside: [ZERO, ZERO], -}; - -export const testUninitializedTickData: TickData = { - feeGrowthOutsideA: ZERO, - feeGrowthOutsideB: ZERO, - liquidityGross: ZERO, - liquidityNet: ZERO, - initialized: false, - rewardGrowthsOutside: [ZERO, ZERO], -}; - -export const testTickArrayData: TickArrayData = { - startTickIndex: 0, - ticks: Array(TICK_ARRAY_SIZE).fill(testUninitializedTickData), - whirlpool: PublicKey.default, -}; - -export const testEmptyTickArrray: TickArray = { - address: PublicKey.default, - data: null, -}; - -export const buildTickArrayData = (startTick: number, initializedOffsets: number[]): TickArray => { - const result = { - ticks: Array(TICK_ARRAY_SIZE).fill(testUninitializedTickData), - whirlpool: PublicKey.default, - startTickIndex: startTick, - }; - - initializedOffsets.forEach((offset) => { - if (offset >= TICK_ARRAY_SIZE) { - throw new Error(`Cannot build tick-array with initialized offset - ${offset}`); - } - result.ticks[offset] = testInitializedTickData; - }); - const randomAddr = Keypair.generate().publicKey; - return { address: randomAddr, data: result }; -}; - -export async function getTickArrays( - startIndices: number[], - ctx: WhirlpoolContext, - whirlpoolKey: PublicKey, - fetcher: WhirlpoolAccountFetcherInterface -) { - const tickArrayPdas = await startIndices.map((value) => - PDAUtil.getTickArray(ctx.program.programId, whirlpoolKey, value) - ); - const tickArrayAddresses = tickArrayPdas.map((pda) => pda.publicKey); - const tickArrays = await fetcher.getTickArrays(tickArrayAddresses, IGNORE_CACHE); - return tickArrayAddresses.map((addr, index) => { - return { - address: addr, - data: tickArrays[index], - }; - }); -} - -export const buildPositionBundleData = (occupiedBundleIndexes: number[]): PositionBundleData => { - invariant(POSITION_BUNDLE_SIZE % 8 == 0, "POSITION_BUNDLE_SIZE should be multiple of 8"); - - const positionBundleMint = Keypair.generate().publicKey; - const positionBitmap: number[] = new Array(POSITION_BUNDLE_SIZE / 8).fill(0); - occupiedBundleIndexes.forEach((bundleIndex) => { - const index = Math.floor(bundleIndex / 8); - const offset = bundleIndex % 8; - positionBitmap[index] = positionBitmap[index] | (1 << offset); - }); - return { positionBundleMint, positionBitmap }; -}; diff --git a/sdk/tests/utils/token.ts b/sdk/tests/utils/token.ts deleted file mode 100644 index 5eb309d..0000000 --- a/sdk/tests/utils/token.ts +++ /dev/null @@ -1,269 +0,0 @@ -import { AnchorProvider, BN, web3 } from "@coral-xyz/anchor"; -import { TokenUtil, TransactionBuilder } from "@orca-so/common-sdk"; -import { - AccountLayout, - AuthorityType, - NATIVE_MINT, - TOKEN_PROGRAM_ID, - createApproveInstruction, - createAssociatedTokenAccountInstruction, - createBurnInstruction, - createInitializeAccount3Instruction, - createInitializeMintInstruction, - createMintToInstruction, - createSetAuthorityInstruction, - createTransferInstruction, - getAssociatedTokenAddressSync -} from "@solana/spl-token"; -import { TEST_TOKEN_PROGRAM_ID } from "./test-consts"; - -export async function createMint( - provider: AnchorProvider, - authority?: web3.PublicKey -): Promise { - if (authority === undefined) { - authority = provider.wallet.publicKey; - } - const mint = web3.Keypair.generate(); - const instructions = await createMintInstructions(provider, authority, mint.publicKey); - - const tx = new web3.Transaction(); - tx.add(...instructions); - - await provider.sendAndConfirm(tx, [mint], { commitment: "confirmed" }); - - return mint.publicKey; -} - -export async function createMintInstructions( - provider: AnchorProvider, - authority: web3.PublicKey, - mint: web3.PublicKey -) { - let instructions = [ - web3.SystemProgram.createAccount({ - fromPubkey: provider.wallet.publicKey, - newAccountPubkey: mint, - space: 82, - lamports: await provider.connection.getMinimumBalanceForRentExemption(82), - programId: TEST_TOKEN_PROGRAM_ID, - }), - createInitializeMintInstruction(mint, 0, authority, null) - ]; - return instructions; -} - -export async function createTokenAccount( - provider: AnchorProvider, - mint: web3.PublicKey, - owner: web3.PublicKey -) { - const tokenAccount = web3.Keypair.generate(); - const tx = new web3.Transaction(); - tx.add(...(await createTokenAccountInstrs(provider, tokenAccount.publicKey, mint, owner))); - await provider.sendAndConfirm(tx, [tokenAccount], { commitment: "confirmed" }); - return tokenAccount.publicKey; -} - -export async function createAssociatedTokenAccount( - provider: AnchorProvider, - mint: web3.PublicKey, - owner: web3.PublicKey, - payer: web3.PublicKey -) { - const ataAddress = getAssociatedTokenAddressSync(mint, owner); - const instr = createAssociatedTokenAccountInstruction( - payer, - ataAddress, - owner, - mint, - ); - const tx = new web3.Transaction(); - tx.add(instr); - await provider.sendAndConfirm(tx, [], { commitment: "confirmed" }); - return ataAddress; -} - -async function createTokenAccountInstrs( - provider: AnchorProvider, - newAccountPubkey: web3.PublicKey, - mint: web3.PublicKey, - owner: web3.PublicKey, - lamports?: number -) { - if (lamports === undefined) { - lamports = await provider.connection.getMinimumBalanceForRentExemption(165); - } - return [ - web3.SystemProgram.createAccount({ - fromPubkey: provider.wallet.publicKey, - newAccountPubkey, - space: 165, - lamports, - programId: TEST_TOKEN_PROGRAM_ID, - }), - createInitializeAccount3Instruction(newAccountPubkey, mint, owner) - ]; -} - -/** - * Mints tokens to the specified destination token account. - * @param provider An anchor AnchorProvider object used to send transactions - * @param mint Mint address of the token - * @param destination Destination token account to receive tokens - * @param amount Number of tokens to mint - */ -export async function mintToDestination( - provider: AnchorProvider, - mint: web3.PublicKey, - destination: web3.PublicKey, - amount: number | BN -): Promise { - const tx = new web3.Transaction(); - const amountVal = amount instanceof BN ? BigInt(amount.toString()) : amount; - tx.add( - createMintToInstruction( - mint, - destination, - provider.wallet.publicKey, - amountVal - ) - ); - return provider.sendAndConfirm(tx, [], { commitment: "confirmed" }); -} - -/** - * Creates a token account for the mint and mints the specified amount of tokens into the token account. - * The caller is assumed to be the mint authority. - * @param provider An anchor AnchorProvider object used to send transactions - * @param mint The mint address of the token - * @param amount Number of tokens to mint to the newly created token account - */ -export async function createAndMintToTokenAccount( - provider: AnchorProvider, - mint: web3.PublicKey, - amount: number | BN -): Promise { - const tokenAccount = await createTokenAccount(provider, mint, provider.wallet.publicKey); - await mintToDestination(provider, mint, tokenAccount, new BN(amount.toString())); - return tokenAccount; -} - -export async function createAndMintToAssociatedTokenAccount( - provider: AnchorProvider, - mint: web3.PublicKey, - amount: number | BN, - destinationWallet?: web3.PublicKey, - payer?: web3.PublicKey -): Promise { - const destinationWalletKey = destinationWallet ? destinationWallet : provider.wallet.publicKey; - const payerKey = payer ? payer : provider.wallet.publicKey; - - // Workaround For SOL - just create a wSOL account to satisfy the rest of the test building pipeline. - // Tests who want to test with SOL will have to request their own airdrop. - if (mint.equals(NATIVE_MINT)) { - const rentExemption = await provider.connection.getMinimumBalanceForRentExemption( - AccountLayout.span, - "confirmed" - ); - const txBuilder = new TransactionBuilder(provider.connection, provider.wallet); - const { address: tokenAccount, ...ix } = TokenUtil.createWrappedNativeAccountInstruction( - destinationWalletKey, - new BN(amount.toString()), - rentExemption - ); - txBuilder.addInstruction({ ...ix, cleanupInstructions: [] }); - await txBuilder.buildAndExecute(); - return tokenAccount; - } - - const tokenAccounts = await provider.connection.getParsedTokenAccountsByOwner(destinationWalletKey, { - programId: TOKEN_PROGRAM_ID, - }); - - let tokenAccount = tokenAccounts.value.map((account) => { - if (account.account.data.parsed.info.mint === mint.toString()) { - return account.pubkey - } - }).filter(Boolean)[0]; - - if (!tokenAccount) { - tokenAccount = await createAssociatedTokenAccount( - provider, - mint, - destinationWalletKey, - payerKey - ); - } - - await mintToDestination(provider, mint, tokenAccount!, new BN(amount.toString())); - return tokenAccount!; -} - -export async function getTokenBalance(provider: AnchorProvider, vault: web3.PublicKey) { - return (await provider.connection.getTokenAccountBalance(vault, "confirmed")).value.amount; -} - -export async function approveToken( - provider: AnchorProvider, - tokenAccount: web3.PublicKey, - delegate: web3.PublicKey, - amount: number | BN, - owner?: web3.Keypair -) { - const tx = new web3.Transaction(); - const amountVal = amount instanceof BN ? BigInt(amount.toString()) : amount; - tx.add( - createApproveInstruction(tokenAccount, delegate, owner?.publicKey || provider.wallet.publicKey, amountVal) - ); - return provider.sendAndConfirm(tx, !!owner ? [owner] : [], { commitment: "confirmed" }); -} - -export async function setAuthority( - provider: AnchorProvider, - tokenAccount: web3.PublicKey, - newAuthority: web3.PublicKey, - authorityType: AuthorityType, - authority: web3.Keypair -) { - const tx = new web3.Transaction(); - tx.add( - createSetAuthorityInstruction( - tokenAccount, - authority.publicKey, - authorityType, - newAuthority, - ) - ); - - return provider.sendAndConfirm(tx, [authority], { commitment: "confirmed" }); -} - -export async function transferToken( - provider: AnchorProvider, - source: web3.PublicKey, - destination: web3.PublicKey, - amount: number -) { - const tx = new web3.Transaction(); - tx.add( - createTransferInstruction(source, destination, provider.wallet.publicKey, amount) - ); - return provider.sendAndConfirm(tx, [], { commitment: "confirmed" }); -} - -export async function burnToken( - provider: AnchorProvider, - account: web3.PublicKey, - mint: web3.PublicKey, - amount: number | BN, - owner?: web3.PublicKey -) { - const ownerKey = owner ?? provider.wallet.publicKey; - const tx = new web3.Transaction(); - const amountVal = amount instanceof BN ? BigInt(amount.toString()) : amount; - tx.add( - createBurnInstruction(account, mint, ownerKey, amountVal) - ); - return provider.sendAndConfirm(tx, [], { commitment: "confirmed" }); -} \ No newline at end of file diff --git a/sdk/tests/utils/utils.ts b/sdk/tests/utils/utils.ts deleted file mode 100644 index d2e88f7..0000000 --- a/sdk/tests/utils/utils.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { AnchorProvider, web3 } from "@coral-xyz/anchor"; -import { TransactionBuilder } from "@orca-so/common-sdk"; - -export function systemTransferTx( - provider: AnchorProvider, - toPubkey: web3.PublicKey, - lamports: number -): TransactionBuilder { - return new TransactionBuilder(provider.connection, provider.wallet).addInstruction({ - instructions: [ - web3.SystemProgram.transfer({ - fromPubkey: provider.wallet.publicKey, - toPubkey, - lamports, - }), - ], - cleanupInstructions: [], - signers: [], - }); -} - -export function sleep(ms: number): Promise { - return new Promise((resolve) => setTimeout(resolve, ms)); -} diff --git a/sdk/tests/utils/whirlpools-test-utils.ts b/sdk/tests/utils/whirlpools-test-utils.ts deleted file mode 100644 index b71137c..0000000 --- a/sdk/tests/utils/whirlpools-test-utils.ts +++ /dev/null @@ -1,15 +0,0 @@ -import BN from "bn.js"; -import { WhirlpoolContext, WhirlpoolData } from "../../src"; -import { getTokenBalance } from "./token"; - -export type VaultAmounts = { - tokenA: BN; - tokenB: BN; -}; - -export async function getVaultAmounts(ctx: WhirlpoolContext, whirlpoolData: WhirlpoolData) { - return { - tokenA: new BN(await getTokenBalance(ctx.provider, whirlpoolData.tokenVaultA)), - tokenB: new BN(await getTokenBalance(ctx.provider, whirlpoolData.tokenVaultB)), - }; -} diff --git a/sdk/tsconfig-base.json b/sdk/tsconfig-base.json deleted file mode 100644 index a7e32fe..0000000 --- a/sdk/tsconfig-base.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2020", - "module": "commonjs", - "allowJs": false, - "declaration": true, - "lib": ["DOM", "ES2020", "DOM.Iterable", "ScriptHost"], - "outDir": "./dist", - "strict": true, - "esModuleInterop": true, - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, - "resolveJsonModule": true, - "experimentalDecorators": true, - "moduleResolution": "node" - }, - "exclude": ["./dist/**/*"], - "references": [ - { - "path": "./src/tsconfig.json" - }, - { - "path": "./tests/tsconfig.json" - } - ] -} diff --git a/sdk/typedoc.json b/sdk/typedoc.json deleted file mode 100644 index bab58cb..0000000 --- a/sdk/typedoc.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "$schema": "https://typedoc.org/schema.json", - "entryPoints": ["./src/index.ts"], - "tsconfig": "src/tsconfig.json", - "excludePrivate": true, - "categorizeByGroup": false, - "exclude": ["**/node_modules/**", "./src/impl/**"] -} diff --git a/tsconfig.json b/tsconfig.json deleted file mode 100644 index 56e10de..0000000 --- a/tsconfig.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "exclude": [ - "/**/tests/**", - "/**/dist/**" -], - "references": [ - { - "path": "./sdk/src" - }, - { - "path": "./scripts" - } -] -} diff --git a/yarn.lock b/yarn.lock deleted file mode 100644 index bda7bdb..0000000 --- a/yarn.lock +++ /dev/null @@ -1,2708 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@aashutoshrathi/word-wrap@^1.2.3": - version "1.2.6" - resolved "https://registry.yarnpkg.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz#bd9154aec9983f77b3a034ecaa015c2e4201f6cf" - integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA== - -"@babel/runtime@^7.10.5", "@babel/runtime@^7.17.2", "@babel/runtime@^7.22.3": - version "7.22.6" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.22.6.tgz#57d64b9ae3cff1d67eb067ae117dac087f5bd438" - integrity sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ== - dependencies: - regenerator-runtime "^0.13.11" - -"@babel/runtime@^7.23.4": - version "7.23.8" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.23.8.tgz#8ee6fe1ac47add7122902f257b8ddf55c898f650" - integrity sha512-Y7KbAP984rn1VGMbGqKmBLio9V7y5Je9GvU4rQPCPinCyNfUcToxIXl06d59URp/F3LwinvODxab5N/G6qggkw== - dependencies: - regenerator-runtime "^0.14.0" - -"@coral-xyz/anchor@^0.27.0": - version "0.27.0" - resolved "https://registry.yarnpkg.com/@coral-xyz/anchor/-/anchor-0.27.0.tgz#621e5ef123d05811b97e49973b4ed7ede27c705c" - integrity sha512-+P/vPdORawvg3A9Wj02iquxb4T0C5m4P6aZBVYysKl4Amk+r6aMPZkUhilBkD6E4Nuxnoajv3CFykUfkGE0n5g== - dependencies: - "@coral-xyz/borsh" "^0.27.0" - "@solana/web3.js" "^1.68.0" - base64-js "^1.5.1" - bn.js "^5.1.2" - bs58 "^4.0.1" - buffer-layout "^1.2.2" - camelcase "^6.3.0" - cross-fetch "^3.1.5" - crypto-hash "^1.3.0" - eventemitter3 "^4.0.7" - js-sha256 "^0.9.0" - pako "^2.0.3" - snake-case "^3.0.4" - superstruct "^0.15.4" - toml "^3.0.0" - -"@coral-xyz/borsh@^0.27.0": - version "0.27.0" - resolved "https://registry.yarnpkg.com/@coral-xyz/borsh/-/borsh-0.27.0.tgz#700c647ea5262b1488957ac7fb4e8acf72c72b63" - integrity sha512-tJKzhLukghTWPLy+n8K8iJKgBq1yLT/AxaNd10yJrX8mI56ao5+OFAKAqW/h0i79KCvb4BK0VGO5ECmmolFz9A== - dependencies: - bn.js "^5.1.2" - buffer-layout "^1.2.0" - -"@cspotcode/source-map-support@^0.8.0": - version "0.8.1" - resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" - integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== - dependencies: - "@jridgewell/trace-mapping" "0.3.9" - -"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": - version "4.4.0" - resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" - integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== - dependencies: - eslint-visitor-keys "^3.3.0" - -"@eslint-community/regexpp@^4.5.1", "@eslint-community/regexpp@^4.6.1": - version "4.10.0" - resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.10.0.tgz#548f6de556857c8bb73bbee70c35dc82a2e74d63" - integrity sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA== - -"@eslint/eslintrc@^2.1.4": - version "2.1.4" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.4.tgz#388a269f0f25c1b6adc317b5a2c55714894c70ad" - integrity sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ== - dependencies: - ajv "^6.12.4" - debug "^4.3.2" - espree "^9.6.0" - globals "^13.19.0" - ignore "^5.2.0" - import-fresh "^3.2.1" - js-yaml "^4.1.0" - minimatch "^3.1.2" - strip-json-comments "^3.1.1" - -"@eslint/js@8.56.0": - version "8.56.0" - resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.56.0.tgz#ef20350fec605a7f7035a01764731b2de0f3782b" - integrity sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A== - -"@humanwhocodes/config-array@^0.11.13": - version "0.11.13" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.13.tgz#075dc9684f40a531d9b26b0822153c1e832ee297" - integrity sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ== - dependencies: - "@humanwhocodes/object-schema" "^2.0.1" - debug "^4.1.1" - minimatch "^3.0.5" - -"@humanwhocodes/module-importer@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" - integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== - -"@humanwhocodes/object-schema@^2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz#e5211452df060fa8522b55c7b3c0c4d1981cb044" - integrity sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw== - -"@isaacs/cliui@^8.0.2": - version "8.0.2" - resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" - integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== - dependencies: - string-width "^5.1.2" - string-width-cjs "npm:string-width@^4.2.0" - strip-ansi "^7.0.1" - strip-ansi-cjs "npm:strip-ansi@^6.0.1" - wrap-ansi "^8.1.0" - wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" - -"@jridgewell/resolve-uri@^3.0.3": - version "3.1.1" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721" - integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA== - -"@jridgewell/sourcemap-codec@^1.4.10": - version "1.4.15" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" - integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== - -"@jridgewell/trace-mapping@0.3.9": - version "0.3.9" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" - integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== - dependencies: - "@jridgewell/resolve-uri" "^3.0.3" - "@jridgewell/sourcemap-codec" "^1.4.10" - -"@metaplex-foundation/beet-solana@^0.4.0": - version "0.4.1" - resolved "https://registry.yarnpkg.com/@metaplex-foundation/beet-solana/-/beet-solana-0.4.1.tgz#255747aa7feee1c20202146a752c057feca1948f" - integrity sha512-/6o32FNUtwK8tjhotrvU/vorP7umBuRFvBZrC6XCk51aKidBHe5LPVPA5AjGPbV3oftMfRuXPNd9yAGeEqeCDQ== - dependencies: - "@metaplex-foundation/beet" ">=0.1.0" - "@solana/web3.js" "^1.56.2" - bs58 "^5.0.0" - debug "^4.3.4" - -"@metaplex-foundation/beet@>=0.1.0", "@metaplex-foundation/beet@^0.7.1": - version "0.7.2" - resolved "https://registry.yarnpkg.com/@metaplex-foundation/beet/-/beet-0.7.2.tgz#fa4726e4cfd4fb6fed6cddc9b5213c1c2a2d0b77" - integrity sha512-K+g3WhyFxKPc0xIvcIjNyV1eaTVJTiuaHZpig7Xx0MuYRMoJLLvhLTnUXhFdR5Tu2l2QSyKwfyXDgZlzhULqFg== - dependencies: - ansicolors "^0.3.2" - assert "^2.1.0" - bn.js "^5.2.0" - debug "^4.3.3" - -"@metaplex-foundation/cusper@^0.0.2": - version "0.0.2" - resolved "https://registry.yarnpkg.com/@metaplex-foundation/cusper/-/cusper-0.0.2.tgz#dc2032a452d6c269e25f016aa4dd63600e2af975" - integrity sha512-S9RulC2fFCFOQraz61bij+5YCHhSO9llJegK8c8Y6731fSi6snUSQJdCUqYS8AIgR0TKbQvdvgSyIIdbDFZbBA== - -"@metaplex-foundation/mpl-token-metadata@2.12.0": - version "2.12.0" - resolved "https://registry.yarnpkg.com/@metaplex-foundation/mpl-token-metadata/-/mpl-token-metadata-2.12.0.tgz#9817b2d133c5af46c28ab284316b6985ef62b331" - integrity sha512-DetC2F5MwMRt4TmLXwj8PJ8nClRYGMecSQ4pr9iKKa+rWertHgKoJHl2XhheRa084GtL7i0ssOKbX2gfYFosuQ== - dependencies: - "@metaplex-foundation/beet" "^0.7.1" - "@metaplex-foundation/beet-solana" "^0.4.0" - "@metaplex-foundation/cusper" "^0.0.2" - "@solana/spl-token" "^0.3.6" - "@solana/web3.js" "^1.66.2" - bn.js "^5.2.0" - debug "^4.3.4" - -"@noble/curves@^1.0.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.1.0.tgz#f13fc667c89184bc04cccb9b11e8e7bae27d8c3d" - integrity sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA== - dependencies: - "@noble/hashes" "1.3.1" - -"@noble/curves@^1.2.0": - version "1.3.0" - resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.3.0.tgz#01be46da4fd195822dab821e72f71bf4aeec635e" - integrity sha512-t01iSXPuN+Eqzb4eBX0S5oubSqXbK/xXa1Ne18Hj8f9pStxztHCE2gfboSp/dZRLSqfuLpRK2nDXDK+W9puocA== - dependencies: - "@noble/hashes" "1.3.3" - -"@noble/hashes@1.3.1", "@noble/hashes@^1.3.0": - version "1.3.1" - resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.1.tgz#8831ef002114670c603c458ab8b11328406953a9" - integrity sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA== - -"@noble/hashes@1.3.3", "@noble/hashes@^1.3.2": - version "1.3.3" - resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.3.tgz#39908da56a4adc270147bb07968bf3b16cfe1699" - integrity sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA== - -"@nodelib/fs.scandir@2.1.5": - version "2.1.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" - integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== - dependencies: - "@nodelib/fs.stat" "2.0.5" - run-parallel "^1.1.9" - -"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" - integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== - -"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": - version "1.2.8" - resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" - integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== - dependencies: - "@nodelib/fs.scandir" "2.1.5" - fastq "^1.6.0" - -"@orca-so/common-sdk@^0.5.3": - version "0.5.3" - resolved "https://registry.yarnpkg.com/@orca-so/common-sdk/-/common-sdk-0.5.3.tgz#bec524984996a494ac00d9aa30be41d9457a2a92" - integrity sha512-PmlEZk6qidBZUenlx6qXWm4xdunyPj71N5bQvhkRb5iSo0rMs0zaevMGkZrIWNN80qf5tVgScsRfI9aAG9oQjg== - dependencies: - tiny-invariant "^1.3.1" - -"@pkgjs/parseargs@^0.11.0": - version "0.11.0" - resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" - integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== - -"@project-serum/anchor@~0.25.0": - version "0.25.0" - resolved "https://registry.yarnpkg.com/@project-serum/anchor/-/anchor-0.25.0.tgz#88ee4843336005cf5a64c80636ce626f0996f503" - integrity sha512-E6A5Y/ijqpfMJ5psJvbw0kVTzLZFUcOFgs6eSM2M2iWE1lVRF18T6hWZVNl6zqZsoz98jgnNHtVGJMs+ds9A7A== - dependencies: - "@project-serum/borsh" "^0.2.5" - "@solana/web3.js" "^1.36.0" - base64-js "^1.5.1" - bn.js "^5.1.2" - bs58 "^4.0.1" - buffer-layout "^1.2.2" - camelcase "^5.3.1" - cross-fetch "^3.1.5" - crypto-hash "^1.3.0" - eventemitter3 "^4.0.7" - js-sha256 "^0.9.0" - pako "^2.0.3" - snake-case "^3.0.4" - superstruct "^0.15.4" - toml "^3.0.0" - -"@project-serum/borsh@^0.2.5": - version "0.2.5" - resolved "https://registry.yarnpkg.com/@project-serum/borsh/-/borsh-0.2.5.tgz#6059287aa624ecebbfc0edd35e4c28ff987d8663" - integrity sha512-UmeUkUoKdQ7rhx6Leve1SssMR/Ghv8qrEiyywyxSWg7ooV7StdpPBhciiy5eB3T0qU1BXvdRNC8TdrkxK7WC5Q== - dependencies: - bn.js "^5.1.2" - buffer-layout "^1.2.0" - -"@solana/buffer-layout-utils@^0.2.0": - version "0.2.0" - resolved "https://registry.yarnpkg.com/@solana/buffer-layout-utils/-/buffer-layout-utils-0.2.0.tgz#b45a6cab3293a2eb7597cceb474f229889d875ca" - integrity sha512-szG4sxgJGktbuZYDg2FfNmkMi0DYQoVjN2h7ta1W1hPrwzarcFLBq9UpX1UjNXsNpT9dn+chgprtWGioUAr4/g== - dependencies: - "@solana/buffer-layout" "^4.0.0" - "@solana/web3.js" "^1.32.0" - bigint-buffer "^1.1.5" - bignumber.js "^9.0.1" - -"@solana/buffer-layout@^4.0.0", "@solana/buffer-layout@^4.0.1": - version "4.0.1" - resolved "https://registry.yarnpkg.com/@solana/buffer-layout/-/buffer-layout-4.0.1.tgz#b996235eaec15b1e0b5092a8ed6028df77fa6c15" - integrity sha512-E1ImOIAD1tBZFRdjeM4/pzTiTApC0AOBGwyAMS4fwIodCWArzJ3DWdoh8cKxeFM2fElkxBh2Aqts1BPC373rHA== - dependencies: - buffer "~6.0.3" - -"@solana/codecs-core@2.0.0-experimental.8618508": - version "2.0.0-experimental.8618508" - resolved "https://registry.yarnpkg.com/@solana/codecs-core/-/codecs-core-2.0.0-experimental.8618508.tgz#4f6709dd50e671267f3bea7d09209bc6471b7ad0" - integrity sha512-JCz7mKjVKtfZxkuDtwMAUgA7YvJcA2BwpZaA1NOLcted4OMC4Prwa3DUe3f3181ixPYaRyptbF0Ikq2MbDkYEA== - -"@solana/codecs-data-structures@2.0.0-experimental.8618508": - version "2.0.0-experimental.8618508" - resolved "https://registry.yarnpkg.com/@solana/codecs-data-structures/-/codecs-data-structures-2.0.0-experimental.8618508.tgz#c16a704ac0f743a2e0bf73ada42d830b3402d848" - integrity sha512-sLpjL9sqzaDdkloBPV61Rht1tgaKq98BCtIKRuyscIrmVPu3wu0Bavk2n/QekmUzaTsj7K1pVSniM0YqCdnEBw== - dependencies: - "@solana/codecs-core" "2.0.0-experimental.8618508" - "@solana/codecs-numbers" "2.0.0-experimental.8618508" - -"@solana/codecs-numbers@2.0.0-experimental.8618508": - version "2.0.0-experimental.8618508" - resolved "https://registry.yarnpkg.com/@solana/codecs-numbers/-/codecs-numbers-2.0.0-experimental.8618508.tgz#d84f9ed0521b22e19125eefc7d51e217fcaeb3e4" - integrity sha512-EXQKfzFr3CkKKNzKSZPOOOzchXsFe90TVONWsSnVkonO9z+nGKALE0/L9uBmIFGgdzhhU9QQVFvxBMclIDJo2Q== - dependencies: - "@solana/codecs-core" "2.0.0-experimental.8618508" - -"@solana/codecs-strings@2.0.0-experimental.8618508": - version "2.0.0-experimental.8618508" - resolved "https://registry.yarnpkg.com/@solana/codecs-strings/-/codecs-strings-2.0.0-experimental.8618508.tgz#72457b884d9be80b59b263bcce73892b081e9402" - integrity sha512-b2yhinr1+oe+JDmnnsV0641KQqqDG8AQ16Z/x7GVWO+AWHMpRlHWVXOq8U1yhPMA4VXxl7i+D+C6ql0VGFp0GA== - dependencies: - "@solana/codecs-core" "2.0.0-experimental.8618508" - "@solana/codecs-numbers" "2.0.0-experimental.8618508" - -"@solana/options@2.0.0-experimental.8618508": - version "2.0.0-experimental.8618508" - resolved "https://registry.yarnpkg.com/@solana/options/-/options-2.0.0-experimental.8618508.tgz#95385340e85f9e8a81b2bfba089404a61c8e9520" - integrity sha512-fy/nIRAMC3QHvnKi63KEd86Xr/zFBVxNW4nEpVEU2OT0gCEKwHY4Z55YHf7XujhyuM3PNpiBKg/YYw5QlRU4vg== - dependencies: - "@solana/codecs-core" "2.0.0-experimental.8618508" - "@solana/codecs-numbers" "2.0.0-experimental.8618508" - -"@solana/spl-token-metadata@^0.1.2": - version "0.1.2" - resolved "https://registry.yarnpkg.com/@solana/spl-token-metadata/-/spl-token-metadata-0.1.2.tgz#876e13432bd2960bd3cac16b9b0af63e69e37719" - integrity sha512-hJYnAJNkDrtkE2Q41YZhCpeOGU/0JgRFXbtrtOuGGeKc3pkEUHB9DDoxZAxx+XRno13GozUleyBi0qypz4c3bw== - dependencies: - "@solana/codecs-core" "2.0.0-experimental.8618508" - "@solana/codecs-data-structures" "2.0.0-experimental.8618508" - "@solana/codecs-numbers" "2.0.0-experimental.8618508" - "@solana/codecs-strings" "2.0.0-experimental.8618508" - "@solana/options" "2.0.0-experimental.8618508" - "@solana/spl-type-length-value" "0.1.0" - -"@solana/spl-token@^0.1.8": - version "0.1.8" - resolved "https://registry.yarnpkg.com/@solana/spl-token/-/spl-token-0.1.8.tgz#f06e746341ef8d04165e21fc7f555492a2a0faa6" - integrity sha512-LZmYCKcPQDtJgecvWOgT/cnoIQPWjdH+QVyzPcFvyDUiT0DiRjZaam4aqNUyvchLFhzgunv3d9xOoyE34ofdoQ== - dependencies: - "@babel/runtime" "^7.10.5" - "@solana/web3.js" "^1.21.0" - bn.js "^5.1.0" - buffer "6.0.3" - buffer-layout "^1.2.0" - dotenv "10.0.0" - -"@solana/spl-token@^0.3.11", "@solana/spl-token@^0.3.6": - version "0.3.11" - resolved "https://registry.yarnpkg.com/@solana/spl-token/-/spl-token-0.3.11.tgz#cdc10f9472b29b39c8983c92592cadd06627fb9a" - integrity sha512-bvohO3rIMSVL24Pb+I4EYTJ6cL82eFpInEXD/I8K8upOGjpqHsKUoAempR/RnUlI1qSFNyFlWJfu6MNUgfbCQQ== - dependencies: - "@solana/buffer-layout" "^4.0.0" - "@solana/buffer-layout-utils" "^0.2.0" - "@solana/spl-token-metadata" "^0.1.2" - buffer "^6.0.3" - -"@solana/spl-type-length-value@0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@solana/spl-type-length-value/-/spl-type-length-value-0.1.0.tgz#b5930cf6c6d8f50c7ff2a70463728a4637a2f26b" - integrity sha512-JBMGB0oR4lPttOZ5XiUGyvylwLQjt1CPJa6qQ5oM+MBCndfjz2TKKkw0eATlLLcYmq1jBVsNlJ2cD6ns2GR7lA== - dependencies: - buffer "^6.0.3" - -"@solana/web3.js@^1.21.0", "@solana/web3.js@^1.32.0", "@solana/web3.js@^1.36.0", "@solana/web3.js@^1.68.0": - version "1.78.0" - resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-1.78.0.tgz#82058f040c7706674d88db0afb8fbb2826f48bb6" - integrity sha512-CSjCjo+RELJ5puoZALfznN5EF0YvL1V8NQrQYovsdjE1lCV6SqbKAIZD0+9LlqCBoa1ibuUaR7G2SooYzvzmug== - dependencies: - "@babel/runtime" "^7.22.3" - "@noble/curves" "^1.0.0" - "@noble/hashes" "^1.3.0" - "@solana/buffer-layout" "^4.0.0" - agentkeepalive "^4.2.1" - bigint-buffer "^1.1.5" - bn.js "^5.0.0" - borsh "^0.7.0" - bs58 "^4.0.1" - buffer "6.0.3" - fast-stable-stringify "^1.0.0" - jayson "^4.1.0" - node-fetch "^2.6.11" - rpc-websockets "^7.5.1" - superstruct "^0.14.2" - -"@solana/web3.js@^1.56.2", "@solana/web3.js@^1.66.2", "@solana/web3.js@^1.88.0": - version "1.88.0" - resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-1.88.0.tgz#24e1482f63ac54914430b4ce5ab36eaf433ecdb8" - integrity sha512-E4BdfB0HZpb66OPFhIzPApNE2tG75Mc6XKIoeymUkx/IV+USSYuxDX29sjgE/KGNYxggrOf4YuYnRMI6UiPL8w== - dependencies: - "@babel/runtime" "^7.23.4" - "@noble/curves" "^1.2.0" - "@noble/hashes" "^1.3.2" - "@solana/buffer-layout" "^4.0.1" - agentkeepalive "^4.5.0" - bigint-buffer "^1.1.5" - bn.js "^5.2.1" - borsh "^0.7.0" - bs58 "^4.0.1" - buffer "6.0.3" - fast-stable-stringify "^1.0.0" - jayson "^4.1.0" - node-fetch "^2.7.0" - rpc-websockets "^7.5.1" - superstruct "^0.14.2" - -"@tsconfig/node10@^1.0.7": - version "1.0.9" - resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2" - integrity sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA== - -"@tsconfig/node12@^1.0.7": - version "1.0.11" - resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d" - integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== - -"@tsconfig/node14@^1.0.0": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1" - integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== - -"@tsconfig/node16@^1.0.2": - version "1.0.4" - resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9" - integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== - -"@types/bn.js@~5.1.5": - version "5.1.5" - resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.5.tgz#2e0dacdcce2c0f16b905d20ff87aedbc6f7b4bf0" - integrity sha512-V46N0zwKRF5Q00AZ6hWtN0T8gGmDUaUzLWQvHFo5yThtVwK/VCenFY3wXVbOvNfajEpsTfQM4IN9k/d6gUVX3A== - dependencies: - "@types/node" "*" - -"@types/connect@^3.4.33": - version "3.4.35" - resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.35.tgz#5fcf6ae445e4021d1fc2219a4873cc73a3bb2ad1" - integrity sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ== - dependencies: - "@types/node" "*" - -"@types/json-schema@^7.0.12": - version "7.0.15" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" - integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== - -"@types/json5@^0.0.29": - version "0.0.29" - resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" - integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== - -"@types/mocha@^10.0.6": - version "10.0.6" - resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-10.0.6.tgz#818551d39113081048bdddbef96701b4e8bb9d1b" - integrity sha512-dJvrYWxP/UcXm36Qn36fxhUKu8A/xMRXVT2cliFF1Z7UA9liG5Psj3ezNSZw+5puH2czDXRLcXQxf8JbJt0ejg== - -"@types/mocha@^9.0.0": - version "9.1.1" - resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-9.1.1.tgz#e7c4f1001eefa4b8afbd1eee27a237fee3bf29c4" - integrity sha512-Z61JK7DKDtdKTWwLeElSEBcWGRLY8g95ic5FoQqI9CMx0ns/Ghep3B4DfcEimiKMvtamNVULVNKEsiwV3aQmXw== - -"@types/mz@^2.7.3": - version "2.7.4" - resolved "https://registry.yarnpkg.com/@types/mz/-/mz-2.7.4.tgz#f9d1535cb5171199b28ae6abd6ec29e856551401" - integrity sha512-Zs0imXxyWT20j3Z2NwKpr0IO2LmLactBblNyLua5Az4UHuqOQ02V3jPTgyKwDkuc33/ahw+C3O1PIZdrhFMuQA== - dependencies: - "@types/node" "*" - -"@types/node@*": - version "20.4.5" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.4.5.tgz#9dc0a5cb1ccce4f7a731660935ab70b9c00a5d69" - integrity sha512-rt40Nk13II9JwQBdeYqmbn2Q6IVTA5uPhvSO+JVqdXw/6/4glI6oR9ezty/A9Hg5u7JH4OmYmuQ+XvjKm0Datg== - -"@types/node@^12.12.54": - version "12.20.55" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.55.tgz#c329cbd434c42164f846b909bd6f85b5537f6240" - integrity sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ== - -"@types/node@^20.10.8": - version "20.10.8" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.10.8.tgz#f1e223cbde9e25696661d167a5b93a9b2a5d57c7" - integrity sha512-f8nQs3cLxbAFc00vEU59yf9UyGUftkPaLGfvbVOIDdx2i1b8epBqj2aNGyP19fiyXWvlmZ7qC1XLjAzw/OKIeA== - dependencies: - undici-types "~5.26.4" - -"@types/semver@^7.5.0": - version "7.5.6" - resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.6.tgz#c65b2bfce1bec346582c07724e3f8c1017a20339" - integrity sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A== - -"@types/ws@^7.4.4": - version "7.4.7" - resolved "https://registry.yarnpkg.com/@types/ws/-/ws-7.4.7.tgz#f7c390a36f7a0679aa69de2d501319f4f8d9b702" - integrity sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww== - dependencies: - "@types/node" "*" - -"@typescript-eslint/eslint-plugin@^6.18.1": - version "6.18.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.18.1.tgz#0df881a47da1c1a9774f39495f5f7052f86b72e0" - integrity sha512-nISDRYnnIpk7VCFrGcu1rnZfM1Dh9LRHnfgdkjcbi/l7g16VYRri3TjXi9Ir4lOZSw5N/gnV/3H7jIPQ8Q4daA== - dependencies: - "@eslint-community/regexpp" "^4.5.1" - "@typescript-eslint/scope-manager" "6.18.1" - "@typescript-eslint/type-utils" "6.18.1" - "@typescript-eslint/utils" "6.18.1" - "@typescript-eslint/visitor-keys" "6.18.1" - debug "^4.3.4" - graphemer "^1.4.0" - ignore "^5.2.4" - natural-compare "^1.4.0" - semver "^7.5.4" - ts-api-utils "^1.0.1" - -"@typescript-eslint/parser@^6.18.1": - version "6.18.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-6.18.1.tgz#3c3987e186b38c77b30b6bfa5edf7c98ae2ec9d3" - integrity sha512-zct/MdJnVaRRNy9e84XnVtRv9Vf91/qqe+hZJtKanjojud4wAVy/7lXxJmMyX6X6J+xc6c//YEWvpeif8cAhWA== - dependencies: - "@typescript-eslint/scope-manager" "6.18.1" - "@typescript-eslint/types" "6.18.1" - "@typescript-eslint/typescript-estree" "6.18.1" - "@typescript-eslint/visitor-keys" "6.18.1" - debug "^4.3.4" - -"@typescript-eslint/scope-manager@6.18.1": - version "6.18.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.18.1.tgz#28c31c60f6e5827996aa3560a538693cb4bd3848" - integrity sha512-BgdBwXPFmZzaZUuw6wKiHKIovms97a7eTImjkXCZE04TGHysG+0hDQPmygyvgtkoB/aOQwSM/nWv3LzrOIQOBw== - dependencies: - "@typescript-eslint/types" "6.18.1" - "@typescript-eslint/visitor-keys" "6.18.1" - -"@typescript-eslint/type-utils@6.18.1": - version "6.18.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-6.18.1.tgz#115cf535f8b39db8301677199ce51151e2daee96" - integrity sha512-wyOSKhuzHeU/5pcRDP2G2Ndci+4g653V43gXTpt4nbyoIOAASkGDA9JIAgbQCdCkcr1MvpSYWzxTz0olCn8+/Q== - dependencies: - "@typescript-eslint/typescript-estree" "6.18.1" - "@typescript-eslint/utils" "6.18.1" - debug "^4.3.4" - ts-api-utils "^1.0.1" - -"@typescript-eslint/types@6.18.1": - version "6.18.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.18.1.tgz#91617d8080bcd99ac355d9157079970d1d49fefc" - integrity sha512-4TuMAe+tc5oA7wwfqMtB0Y5OrREPF1GeJBAjqwgZh1lEMH5PJQgWgHGfYufVB51LtjD+peZylmeyxUXPfENLCw== - -"@typescript-eslint/typescript-estree@6.18.1": - version "6.18.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.18.1.tgz#a12b6440175b4cbc9d09ab3c4966c6b245215ab4" - integrity sha512-fv9B94UAhywPRhUeeV/v+3SBDvcPiLxRZJw/xZeeGgRLQZ6rLMG+8krrJUyIf6s1ecWTzlsbp0rlw7n9sjufHA== - dependencies: - "@typescript-eslint/types" "6.18.1" - "@typescript-eslint/visitor-keys" "6.18.1" - debug "^4.3.4" - globby "^11.1.0" - is-glob "^4.0.3" - minimatch "9.0.3" - semver "^7.5.4" - ts-api-utils "^1.0.1" - -"@typescript-eslint/utils@6.18.1": - version "6.18.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-6.18.1.tgz#3451cfe2e56babb6ac657e10b6703393d4b82955" - integrity sha512-zZmTuVZvD1wpoceHvoQpOiewmWu3uP9FuTWo8vqpy2ffsmfCE8mklRPi+vmnIYAIk9t/4kOThri2QCDgor+OpQ== - dependencies: - "@eslint-community/eslint-utils" "^4.4.0" - "@types/json-schema" "^7.0.12" - "@types/semver" "^7.5.0" - "@typescript-eslint/scope-manager" "6.18.1" - "@typescript-eslint/types" "6.18.1" - "@typescript-eslint/typescript-estree" "6.18.1" - semver "^7.5.4" - -"@typescript-eslint/visitor-keys@6.18.1": - version "6.18.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.18.1.tgz#704d789bda2565a15475e7d22f145b8fe77443f4" - integrity sha512-/kvt0C5lRqGoCfsbmm7/CwMqoSkY3zzHLIjdhHZQW3VFrnz7ATecOHR7nb7V+xn4286MBxfnQfQhAmCI0u+bJA== - dependencies: - "@typescript-eslint/types" "6.18.1" - eslint-visitor-keys "^3.4.1" - -"@ungap/promise-all-settled@1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44" - integrity sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q== - -"@ungap/structured-clone@^1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" - integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== - -JSONStream@^1.3.5: - version "1.3.5" - resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0" - integrity sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ== - dependencies: - jsonparse "^1.2.0" - through ">=2.2.7 <3" - -acorn-jsx@^5.3.2: - version "5.3.2" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" - integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== - -acorn-walk@^8.1.1: - version "8.2.0" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" - integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== - -acorn@^8.4.1: - version "8.10.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5" - integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw== - -acorn@^8.9.0: - version "8.11.3" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a" - integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== - -agentkeepalive@^4.2.1: - version "4.3.0" - resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-4.3.0.tgz#bb999ff07412653c1803b3ced35e50729830a255" - integrity sha512-7Epl1Blf4Sy37j4v9f9FjICCh4+KAQOyXgHEwlyBiAQLbhKdq/i2QQU3amQalS/wPhdPzDXPL5DMR5bkn+YeWg== - dependencies: - debug "^4.1.0" - depd "^2.0.0" - humanize-ms "^1.2.1" - -agentkeepalive@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-4.5.0.tgz#2673ad1389b3c418c5a20c5d7364f93ca04be923" - integrity sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew== - dependencies: - humanize-ms "^1.2.1" - -ajv@^6.12.4: - version "6.12.6" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" - integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== - dependencies: - fast-deep-equal "^3.1.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.2" - -ansi-colors@4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" - integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== - -ansi-regex@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" - integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== - -ansi-regex@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a" - integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== - -ansi-sequence-parser@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ansi-sequence-parser/-/ansi-sequence-parser-1.1.1.tgz#e0aa1cdcbc8f8bb0b5bca625aac41f5f056973cf" - integrity sha512-vJXt3yiaUL4UU546s3rPXlsry/RnM730G1+HkpKE012AN0sx1eOrxSu95oKDIonskeLTijMgqWZ3uDEe3NFvyg== - -ansi-styles@^4.0.0, ansi-styles@^4.1.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" - integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== - dependencies: - color-convert "^2.0.1" - -ansi-styles@^6.1.0: - version "6.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" - integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== - -ansicolors@^0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/ansicolors/-/ansicolors-0.3.2.tgz#665597de86a9ffe3aa9bfbe6cae5c6ea426b4979" - integrity sha512-QXu7BPrP29VllRxH8GwB7x5iX5qWKAAMLqKQGWTeLWVlNHNOpVMJ91dsxQAIWXpjuW5wqvxu3Jd/nRjrJ+0pqg== - -any-promise@^1.0.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" - integrity sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A== - -anymatch@~3.1.2: - version "3.1.3" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" - integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== - dependencies: - normalize-path "^3.0.0" - picomatch "^2.0.4" - -arg@^4.1.0: - version "4.1.3" - resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" - integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== - -argparse@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" - integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== - -array-union@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" - integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== - -arrify@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" - integrity sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA== - -assert@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/assert/-/assert-2.1.0.tgz#6d92a238d05dc02e7427c881fb8be81c8448b2dd" - integrity sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw== - dependencies: - call-bind "^1.0.2" - is-nan "^1.3.2" - object-is "^1.1.5" - object.assign "^4.1.4" - util "^0.12.5" - -assertion-error@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" - integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== - -assertion-error@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-2.0.1.tgz#f641a196b335690b1070bf00b6e7593fec190bf7" - integrity sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA== - -available-typed-arrays@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" - integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== - -balanced-match@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" - integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== - -base-x@^3.0.2: - version "3.0.9" - resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.9.tgz#6349aaabb58526332de9f60995e548a53fe21320" - integrity sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ== - dependencies: - safe-buffer "^5.0.1" - -base-x@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/base-x/-/base-x-4.0.0.tgz#d0e3b7753450c73f8ad2389b5c018a4af7b2224a" - integrity sha512-FuwxlW4H5kh37X/oW59pwTzzTKRzfrrQwhmyspRM7swOEZcHtDZSCt45U6oKgtuFE+WYPblePMVIPR4RZrh/hw== - -base64-js@^1.3.1, base64-js@^1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" - integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== - -bigint-buffer@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/bigint-buffer/-/bigint-buffer-1.1.5.tgz#d038f31c8e4534c1f8d0015209bf34b4fa6dd442" - integrity sha512-trfYco6AoZ+rKhKnxA0hgX0HAbVP/s808/EuDSe2JDzUnCp/xAsli35Orvk67UrTEcwuxZqYZDmfA2RXJgxVvA== - dependencies: - bindings "^1.3.0" - -bignumber.js@^9.0.1: - version "9.1.1" - resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.1.1.tgz#c4df7dc496bd849d4c9464344c1aa74228b4dac6" - integrity sha512-pHm4LsMJ6lzgNGVfZHjMoO8sdoRhOzOH4MLmY65Jg70bpxCKu5iOHNJyfF6OyvYw7t8Fpf35RuzUyqnQsj8Vig== - -binary-extensions@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" - integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== - -bindings@^1.3.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" - integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== - dependencies: - file-uri-to-path "1.0.0" - -bn.js@^5.0.0, bn.js@^5.1.0, bn.js@^5.1.2, bn.js@^5.2.0, bn.js@^5.2.1: - version "5.2.1" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" - integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== - -borsh@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/borsh/-/borsh-0.7.0.tgz#6e9560d719d86d90dc589bca60ffc8a6c51fec2a" - integrity sha512-CLCsZGIBCFnPtkNnieW/a8wmreDmfUtjU2m9yHrzPXIlNbqVs0AQrSatSG6vdNYUqdc83tkQi2eHfF98ubzQLA== - dependencies: - bn.js "^5.2.0" - bs58 "^4.0.0" - text-encoding-utf-8 "^1.0.2" - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -brace-expansion@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" - integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== - dependencies: - balanced-match "^1.0.0" - -braces@^3.0.2, braces@~3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" - integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== - dependencies: - fill-range "^7.0.1" - -browser-stdout@1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" - integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== - -bs58@^4.0.0, bs58@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a" - integrity sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw== - dependencies: - base-x "^3.0.2" - -bs58@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/bs58/-/bs58-5.0.0.tgz#865575b4d13c09ea2a84622df6c8cbeb54ffc279" - integrity sha512-r+ihvQJvahgYT50JD05dyJNKlmmSlMoOGwn1lCcEzanPglg7TxYjioQUYehQ9mAR/+hOSd2jRc/Z2y5UxBymvQ== - dependencies: - base-x "^4.0.0" - -buffer-from@^1.0.0, buffer-from@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" - integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== - -buffer-layout@^1.2.0, buffer-layout@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/buffer-layout/-/buffer-layout-1.2.2.tgz#b9814e7c7235783085f9ca4966a0cfff112259d5" - integrity sha512-kWSuLN694+KTk8SrYvCqwP2WcgQjoRCiF5b4QDvkkz8EmgD+aWAIceGFKMIAdmF/pH+vpgNV3d3kAKorcdAmWA== - -buffer@6.0.3, buffer@^6.0.3, buffer@~6.0.3: - version "6.0.3" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" - integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== - dependencies: - base64-js "^1.3.1" - ieee754 "^1.2.1" - -bufferutil@^4.0.1: - version "4.0.7" - resolved "https://registry.yarnpkg.com/bufferutil/-/bufferutil-4.0.7.tgz#60c0d19ba2c992dd8273d3f73772ffc894c153ad" - integrity sha512-kukuqc39WOHtdxtw4UScxF/WVnMFVSQVKhtx3AjZJzhd0RGZZldcrfSEbVsWWe6KNH253574cq5F+wpv0G9pJw== - dependencies: - node-gyp-build "^4.3.0" - -call-bind@^1.0.0, call-bind@^1.0.2, call-bind@^1.0.4, call-bind@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.5.tgz#6fa2b7845ce0ea49bf4d8b9ef64727a2c2e2e513" - integrity sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ== - dependencies: - function-bind "^1.1.2" - get-intrinsic "^1.2.1" - set-function-length "^1.1.1" - -callsites@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" - integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== - -camelcase@^5.3.1: - version "5.3.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" - integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== - -camelcase@^6.0.0, camelcase@^6.3.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" - integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== - -chai@^4.3.4: - version "4.3.7" - resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.7.tgz#ec63f6df01829088e8bf55fca839bcd464a8ec51" - integrity sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A== - dependencies: - assertion-error "^1.1.0" - check-error "^1.0.2" - deep-eql "^4.1.2" - get-func-name "^2.0.0" - loupe "^2.3.1" - pathval "^1.1.1" - type-detect "^4.0.5" - -chai@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/chai/-/chai-5.0.0.tgz#da1ae496fdac30e97062cbd59e6e2f7bb4c78cc0" - integrity sha512-HO5p0oEKd5M6HEcwOkNAThAE3j960vIZvVcc0t2tI06Dd0ATu69cEnMB2wOhC5/ZyQ6m67w3ePjU/HzXsSsdBA== - dependencies: - assertion-error "^2.0.1" - check-error "^2.0.0" - deep-eql "^5.0.1" - loupe "^3.0.0" - pathval "^2.0.0" - -chalk@^4.0.0, chalk@^4.1.0: - version "4.1.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" - integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - -check-error@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" - integrity sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA== - -check-error@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/check-error/-/check-error-2.0.0.tgz#589a4f201b6256fd93a2d165089fe43d2676d8c6" - integrity sha512-tjLAOBHKVxtPoHe/SA7kNOMvhCRdCJ3vETdeY0RuAc9popf+hyaSV6ZEg9hr4cpWF7jmo/JSWEnLDrnijS9Tog== - -chokidar@3.5.3: - version "3.5.3" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" - integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== - dependencies: - anymatch "~3.1.2" - braces "~3.0.2" - glob-parent "~5.1.2" - is-binary-path "~2.1.0" - is-glob "~4.0.1" - normalize-path "~3.0.0" - readdirp "~3.6.0" - optionalDependencies: - fsevents "~2.3.2" - -cliui@^7.0.2: - version "7.0.4" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" - integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== - dependencies: - string-width "^4.2.0" - strip-ansi "^6.0.0" - wrap-ansi "^7.0.0" - -color-convert@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" - integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== - dependencies: - color-name "~1.1.4" - -color-name@~1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== - -commander@^2.20.3: - version "2.20.3" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" - integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== - -create-require@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" - integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== - -cross-fetch@^3.1.5: - version "3.1.8" - resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.8.tgz#0327eba65fd68a7d119f8fb2bf9334a1a7956f82" - integrity sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg== - dependencies: - node-fetch "^2.6.12" - -cross-spawn@^7.0.0, cross-spawn@^7.0.2: - version "7.0.3" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" - integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== - dependencies: - path-key "^3.1.0" - shebang-command "^2.0.0" - which "^2.0.1" - -crypto-hash@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/crypto-hash/-/crypto-hash-1.3.0.tgz#b402cb08f4529e9f4f09346c3e275942f845e247" - integrity sha512-lyAZ0EMyjDkVvz8WOeVnuCPvKVBXcMv1l5SVqO1yC7PzTwrD/pPje/BIRbWhMoPe436U+Y2nD7f5bFx0kt+Sbg== - -debug@4.3.3: - version "4.3.3" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" - integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== - dependencies: - ms "2.1.2" - -debug@4.3.4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4: - version "4.3.4" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" - integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== - dependencies: - ms "2.1.2" - -decamelize@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" - integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== - -decimal.js@^10.4.3: - version "10.4.3" - resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.4.3.tgz#1044092884d245d1b7f65725fa4ad4c6f781cc23" - integrity sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA== - -deep-eql@^4.1.2: - version "4.1.3" - resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-4.1.3.tgz#7c7775513092f7df98d8df9996dd085eb668cc6d" - integrity sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw== - dependencies: - type-detect "^4.0.0" - -deep-eql@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-5.0.1.tgz#21ea2c0d561a4d08cdd99c417ac584e0fb121385" - integrity sha512-nwQCf6ne2gez3o1MxWifqkciwt0zhl0LO1/UwVu4uMBuPmflWM4oQ70XMqHqnBJA+nhzncaqL9HVL6KkHJ28lw== - -deep-is@^0.1.3: - version "0.1.4" - resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" - integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== - -define-data-property@^1.0.1, define-data-property@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.1.tgz#c35f7cd0ab09883480d12ac5cb213715587800b3" - integrity sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ== - dependencies: - get-intrinsic "^1.2.1" - gopd "^1.0.1" - has-property-descriptors "^1.0.0" - -define-properties@^1.1.3, define-properties@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" - integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== - dependencies: - define-data-property "^1.0.1" - has-property-descriptors "^1.0.0" - object-keys "^1.1.1" - -delay@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/delay/-/delay-5.0.0.tgz#137045ef1b96e5071060dd5be60bf9334436bd1d" - integrity sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw== - -depd@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" - integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== - -diff@5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" - integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== - -diff@^3.1.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" - integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== - -diff@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" - integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== - -dir-glob@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" - integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== - dependencies: - path-type "^4.0.0" - -doctrine@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" - integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== - dependencies: - esutils "^2.0.2" - -dot-case@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.4.tgz#9b2b670d00a431667a8a75ba29cd1b98809ce751" - integrity sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w== - dependencies: - no-case "^3.0.4" - tslib "^2.0.3" - -dotenv@10.0.0: - version "10.0.0" - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-10.0.0.tgz#3d4227b8fb95f81096cdd2b66653fb2c7085ba81" - integrity sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q== - -eastasianwidth@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" - integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== - -emoji-regex@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" - integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== - -emoji-regex@^9.2.2: - version "9.2.2" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" - integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== - -es6-promise@^4.0.3: - version "4.2.8" - resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a" - integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w== - -es6-promisify@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203" - integrity sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ== - dependencies: - es6-promise "^4.0.3" - -escalade@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" - integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== - -escape-string-regexp@4.0.0, escape-string-regexp@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" - integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== - -eslint-config-prettier@^9.1.0: - version "9.1.0" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz#31af3d94578645966c082fcb71a5846d3c94867f" - integrity sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw== - -eslint-scope@^7.2.2: - version "7.2.2" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.2.tgz#deb4f92563390f32006894af62a22dba1c46423f" - integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg== - dependencies: - esrecurse "^4.3.0" - estraverse "^5.2.0" - -eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3: - version "3.4.3" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" - integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== - -eslint@^8.56.0: - version "8.56.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.56.0.tgz#4957ce8da409dc0809f99ab07a1b94832ab74b15" - integrity sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ== - dependencies: - "@eslint-community/eslint-utils" "^4.2.0" - "@eslint-community/regexpp" "^4.6.1" - "@eslint/eslintrc" "^2.1.4" - "@eslint/js" "8.56.0" - "@humanwhocodes/config-array" "^0.11.13" - "@humanwhocodes/module-importer" "^1.0.1" - "@nodelib/fs.walk" "^1.2.8" - "@ungap/structured-clone" "^1.2.0" - ajv "^6.12.4" - chalk "^4.0.0" - cross-spawn "^7.0.2" - debug "^4.3.2" - doctrine "^3.0.0" - escape-string-regexp "^4.0.0" - eslint-scope "^7.2.2" - eslint-visitor-keys "^3.4.3" - espree "^9.6.1" - esquery "^1.4.2" - esutils "^2.0.2" - fast-deep-equal "^3.1.3" - file-entry-cache "^6.0.1" - find-up "^5.0.0" - glob-parent "^6.0.2" - globals "^13.19.0" - graphemer "^1.4.0" - ignore "^5.2.0" - imurmurhash "^0.1.4" - is-glob "^4.0.0" - is-path-inside "^3.0.3" - js-yaml "^4.1.0" - json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.4.1" - lodash.merge "^4.6.2" - minimatch "^3.1.2" - natural-compare "^1.4.0" - optionator "^0.9.3" - strip-ansi "^6.0.1" - text-table "^0.2.0" - -espree@^9.6.0, espree@^9.6.1: - version "9.6.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" - integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== - dependencies: - acorn "^8.9.0" - acorn-jsx "^5.3.2" - eslint-visitor-keys "^3.4.1" - -esquery@^1.4.2: - version "1.5.0" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" - integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== - dependencies: - estraverse "^5.1.0" - -esrecurse@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" - integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== - dependencies: - estraverse "^5.2.0" - -estraverse@^5.1.0, estraverse@^5.2.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" - integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== - -esutils@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" - integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== - -eventemitter3@^4.0.7: - version "4.0.7" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" - integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== - -eyes@^0.1.8: - version "0.1.8" - resolved "https://registry.yarnpkg.com/eyes/-/eyes-0.1.8.tgz#62cf120234c683785d902348a800ef3e0cc20bc0" - integrity sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ== - -fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" - integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== - -fast-glob@^3.2.9: - version "3.3.1" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.1.tgz#784b4e897340f3dbbef17413b3f11acf03c874c4" - integrity sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg== - dependencies: - "@nodelib/fs.stat" "^2.0.2" - "@nodelib/fs.walk" "^1.2.3" - glob-parent "^5.1.2" - merge2 "^1.3.0" - micromatch "^4.0.4" - -fast-json-stable-stringify@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" - integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== - -fast-levenshtein@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" - integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== - -fast-stable-stringify@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fast-stable-stringify/-/fast-stable-stringify-1.0.0.tgz#5c5543462b22aeeefd36d05b34e51c78cb86d313" - integrity sha512-wpYMUmFu5f00Sm0cj2pfivpmawLZ0NKdviQ4w9zJeR8JVtOpOxHmLaJuj0vxvGqMJQWyP/COUkF75/57OKyRag== - -fastq@^1.6.0: - version "1.15.0" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a" - integrity sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw== - dependencies: - reusify "^1.0.4" - -file-entry-cache@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" - integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== - dependencies: - flat-cache "^3.0.4" - -file-uri-to-path@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" - integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== - -fill-range@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" - integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== - dependencies: - to-regex-range "^5.0.1" - -find-up@5.0.0, find-up@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" - integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== - dependencies: - locate-path "^6.0.0" - path-exists "^4.0.0" - -flat-cache@^3.0.4: - version "3.2.0" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.2.0.tgz#2c0c2d5040c99b1632771a9d105725c0115363ee" - integrity sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw== - dependencies: - flatted "^3.2.9" - keyv "^4.5.3" - rimraf "^3.0.2" - -flat@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" - integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== - -flatted@^3.2.9: - version "3.2.9" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.9.tgz#7eb4c67ca1ba34232ca9d2d93e9886e611ad7daf" - integrity sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ== - -for-each@^0.3.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" - integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== - dependencies: - is-callable "^1.1.3" - -foreground-child@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.1.1.tgz#1d173e776d75d2772fed08efe4a0de1ea1b12d0d" - integrity sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg== - dependencies: - cross-spawn "^7.0.0" - signal-exit "^4.0.1" - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== - -fsevents@~2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" - integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== - -function-bind@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" - integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== - -get-caller-file@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" - integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== - -get-func-name@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" - integrity sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig== - -get-func-name@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.2.tgz#0d7cf20cd13fda808669ffa88f4ffc7a3943fc41" - integrity sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ== - -get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.2.tgz#281b7622971123e1ef4b3c90fd7539306da93f3b" - integrity sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA== - dependencies: - function-bind "^1.1.2" - has-proto "^1.0.1" - has-symbols "^1.0.3" - hasown "^2.0.0" - -glob-parent@^5.1.2, glob-parent@~5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" - integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== - dependencies: - is-glob "^4.0.1" - -glob-parent@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" - integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== - dependencies: - is-glob "^4.0.3" - -glob@7.2.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" - integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^10.3.7: - version "10.3.10" - resolved "https://registry.yarnpkg.com/glob/-/glob-10.3.10.tgz#0351ebb809fd187fe421ab96af83d3a70715df4b" - integrity sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g== - dependencies: - foreground-child "^3.1.0" - jackspeak "^2.3.5" - minimatch "^9.0.1" - minipass "^5.0.0 || ^6.0.2 || ^7.0.0" - path-scurry "^1.10.1" - -glob@^7.1.3: - version "7.2.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" - integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.1.1" - once "^1.3.0" - path-is-absolute "^1.0.0" - -globals@^13.19.0: - version "13.24.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-13.24.0.tgz#8432a19d78ce0c1e833949c36adb345400bb1171" - integrity sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ== - dependencies: - type-fest "^0.20.2" - -globby@^11.1.0: - version "11.1.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" - integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== - dependencies: - array-union "^2.1.0" - dir-glob "^3.0.1" - fast-glob "^3.2.9" - ignore "^5.2.0" - merge2 "^1.4.1" - slash "^3.0.0" - -gopd@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" - integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== - dependencies: - get-intrinsic "^1.1.3" - -graphemer@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" - integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== - -growl@1.10.5: - version "1.10.5" - resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" - integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== - -has-flag@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" - integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== - -has-property-descriptors@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz#52ba30b6c5ec87fd89fa574bc1c39125c6f65340" - integrity sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg== - dependencies: - get-intrinsic "^1.2.2" - -has-proto@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" - integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== - -has-symbols@^1.0.2, has-symbols@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" - integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== - -has-tostringtag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" - integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== - dependencies: - has-symbols "^1.0.2" - -hasown@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.0.tgz#f4c513d454a57b7c7e1650778de226b11700546c" - integrity sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA== - dependencies: - function-bind "^1.1.2" - -he@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" - integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== - -humanize-ms@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed" - integrity sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ== - dependencies: - ms "^2.0.0" - -ieee754@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" - integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== - -ignore@^5.2.0: - version "5.2.4" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324" - integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ== - -ignore@^5.2.4: - version "5.3.0" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.0.tgz#67418ae40d34d6999c95ff56016759c718c82f78" - integrity sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg== - -import-fresh@^3.2.1: - version "3.3.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" - integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== - dependencies: - parent-module "^1.0.0" - resolve-from "^4.0.0" - -imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2, inherits@^2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -is-arguments@^1.0.4: - version "1.1.1" - resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" - integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-binary-path@~2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" - integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== - dependencies: - binary-extensions "^2.0.0" - -is-callable@^1.1.3: - version "1.2.7" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" - integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== - -is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== - -is-fullwidth-code-point@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" - integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== - -is-generator-function@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72" - integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A== - dependencies: - has-tostringtag "^1.0.0" - -is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: - version "4.0.3" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" - integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== - dependencies: - is-extglob "^2.1.1" - -is-nan@^1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/is-nan/-/is-nan-1.3.2.tgz#043a54adea31748b55b6cd4e09aadafa69bd9e1d" - integrity sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w== - dependencies: - call-bind "^1.0.0" - define-properties "^1.1.3" - -is-number@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" - integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== - -is-path-inside@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" - integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== - -is-plain-obj@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" - integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== - -is-typed-array@^1.1.3: - version "1.1.12" - resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.12.tgz#d0bab5686ef4a76f7a73097b95470ab199c57d4a" - integrity sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg== - dependencies: - which-typed-array "^1.1.11" - -is-unicode-supported@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" - integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== - -isomorphic-ws@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz#55fd4cd6c5e6491e76dc125938dd863f5cd4f2dc" - integrity sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w== - -jackspeak@^2.3.5: - version "2.3.6" - resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-2.3.6.tgz#647ecc472238aee4b06ac0e461acc21a8c505ca8" - integrity sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ== - dependencies: - "@isaacs/cliui" "^8.0.2" - optionalDependencies: - "@pkgjs/parseargs" "^0.11.0" - -jayson@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/jayson/-/jayson-4.1.0.tgz#60dc946a85197317f2b1439d672a8b0a99cea2f9" - integrity sha512-R6JlbyLN53Mjku329XoRT2zJAE6ZgOQ8f91ucYdMCD4nkGCF9kZSrcGXpHIU4jeKj58zUZke2p+cdQchU7Ly7A== - dependencies: - "@types/connect" "^3.4.33" - "@types/node" "^12.12.54" - "@types/ws" "^7.4.4" - JSONStream "^1.3.5" - commander "^2.20.3" - delay "^5.0.0" - es6-promisify "^5.0.0" - eyes "^0.1.8" - isomorphic-ws "^4.0.1" - json-stringify-safe "^5.0.1" - uuid "^8.3.2" - ws "^7.4.5" - -js-sha256@^0.9.0: - version "0.9.0" - resolved "https://registry.yarnpkg.com/js-sha256/-/js-sha256-0.9.0.tgz#0b89ac166583e91ef9123644bd3c5334ce9d0966" - integrity sha512-sga3MHh9sgQN2+pJ9VYZ+1LPwXOxuBJBA5nrR5/ofPfuiJBE2hnjsaN8se8JznOmGLN2p49Pe5U/ttafcs/apA== - -js-yaml@4.1.0, js-yaml@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" - integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== - dependencies: - argparse "^2.0.1" - -json-buffer@3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" - integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== - -json-schema-traverse@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" - integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== - -json-stable-stringify-without-jsonify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" - integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== - -json-stringify-safe@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" - integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== - -json5@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" - integrity sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA== - dependencies: - minimist "^1.2.0" - -jsonc-parser@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.2.0.tgz#31ff3f4c2b9793f89c67212627c51c6394f88e76" - integrity sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w== - -jsonparse@^1.2.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" - integrity sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg== - -keyv@^4.5.3: - version "4.5.4" - resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" - integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== - dependencies: - json-buffer "3.0.1" - -levn@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" - integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== - dependencies: - prelude-ls "^1.2.1" - type-check "~0.4.0" - -locate-path@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" - integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== - dependencies: - p-locate "^5.0.0" - -lodash.merge@^4.6.2: - version "4.6.2" - resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" - integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== - -log-symbols@4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" - integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== - dependencies: - chalk "^4.1.0" - is-unicode-supported "^0.1.0" - -loupe@^2.3.1: - version "2.3.6" - resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.6.tgz#76e4af498103c532d1ecc9be102036a21f787b53" - integrity sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA== - dependencies: - get-func-name "^2.0.0" - -loupe@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/loupe/-/loupe-3.1.0.tgz#46ef1a4ffee73145f5c0a627536d754787c1ea2a" - integrity sha512-qKl+FrLXUhFuHUoDJG7f8P8gEMHq9NFS0c6ghXG1J0rldmZFQZoNVv/vyirE9qwCIhWZDsvEFd1sbFu3GvRQFg== - dependencies: - get-func-name "^2.0.1" - -lower-case@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.2.tgz#6fa237c63dbdc4a82ca0fd882e4722dc5e634e28" - integrity sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg== - dependencies: - tslib "^2.0.3" - -lru-cache@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" - integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== - dependencies: - yallist "^4.0.0" - -"lru-cache@^9.1.1 || ^10.0.0": - version "10.0.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.0.0.tgz#b9e2a6a72a129d81ab317202d93c7691df727e61" - integrity sha512-svTf/fzsKHffP42sujkO/Rjs37BCIsQVRCeNYIm9WN8rgT7ffoUnRtZCqU+6BqcSBdv8gwJeTz8knJpgACeQMw== - -lunr@^2.3.9: - version "2.3.9" - resolved "https://registry.yarnpkg.com/lunr/-/lunr-2.3.9.tgz#18b123142832337dd6e964df1a5a7707b25d35e1" - integrity sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow== - -make-error@^1.1.1: - version "1.3.6" - resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" - integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== - -marked@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/marked/-/marked-4.3.0.tgz#796362821b019f734054582038b116481b456cf3" - integrity sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A== - -merge2@^1.3.0, merge2@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" - integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== - -micromatch@^4.0.4: - version "4.0.5" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" - integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== - dependencies: - braces "^3.0.2" - picomatch "^2.3.1" - -minimatch@4.2.1: - version "4.2.1" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-4.2.1.tgz#40d9d511a46bdc4e563c22c3080cde9c0d8299b4" - integrity sha512-9Uq1ChtSZO+Mxa/CL1eGizn2vRn3MlLgzhT0Iz8zaY8NdvxvB0d5QdPFmCKf7JKA9Lerx5vRrnwO03jsSfGG9g== - dependencies: - brace-expansion "^1.1.7" - -minimatch@5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.0.1.tgz#fb9022f7528125187c92bd9e9b6366be1cf3415b" - integrity sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g== - dependencies: - brace-expansion "^2.0.1" - -minimatch@9.0.3, minimatch@^9.0.1, minimatch@^9.0.3: - version "9.0.3" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" - integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== - dependencies: - brace-expansion "^2.0.1" - -minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" - integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== - dependencies: - brace-expansion "^1.1.7" - -minimist@^1.2.0, minimist@^1.2.6: - version "1.2.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" - integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== - -"minipass@^5.0.0 || ^6.0.2 || ^7.0.0": - version "7.0.2" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.0.2.tgz#58a82b7d81c7010da5bd4b2c0c85ac4b4ec5131e" - integrity sha512-eL79dXrE1q9dBbDCLg7xfn/vl7MS4F1gvJAgjJrQli/jbQWdUttuVawphqpffoIYfRdq78LHx6GP4bU/EQ2ATA== - -mkdirp@^0.5.1: - version "0.5.6" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" - integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== - dependencies: - minimist "^1.2.6" - -mocha@^10.2.0: - version "10.2.0" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.2.0.tgz#1fd4a7c32ba5ac372e03a17eef435bd00e5c68b8" - integrity sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg== - dependencies: - ansi-colors "4.1.1" - browser-stdout "1.3.1" - chokidar "3.5.3" - debug "4.3.4" - diff "5.0.0" - escape-string-regexp "4.0.0" - find-up "5.0.0" - glob "7.2.0" - he "1.2.0" - js-yaml "4.1.0" - log-symbols "4.1.0" - minimatch "5.0.1" - ms "2.1.3" - nanoid "3.3.3" - serialize-javascript "6.0.0" - strip-json-comments "3.1.1" - supports-color "8.1.1" - workerpool "6.2.1" - yargs "16.2.0" - yargs-parser "20.2.4" - yargs-unparser "2.0.0" - -mocha@^9.0.3: - version "9.2.2" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-9.2.2.tgz#d70db46bdb93ca57402c809333e5a84977a88fb9" - integrity sha512-L6XC3EdwT6YrIk0yXpavvLkn8h+EU+Y5UcCHKECyMbdUIxyMuZj4bX4U9e1nvnvUUvQVsV2VHQr5zLdcUkhW/g== - dependencies: - "@ungap/promise-all-settled" "1.1.2" - ansi-colors "4.1.1" - browser-stdout "1.3.1" - chokidar "3.5.3" - debug "4.3.3" - diff "5.0.0" - escape-string-regexp "4.0.0" - find-up "5.0.0" - glob "7.2.0" - growl "1.10.5" - he "1.2.0" - js-yaml "4.1.0" - log-symbols "4.1.0" - minimatch "4.2.1" - ms "2.1.3" - nanoid "3.3.1" - serialize-javascript "6.0.0" - strip-json-comments "3.1.1" - supports-color "8.1.1" - which "2.0.2" - workerpool "6.2.0" - yargs "16.2.0" - yargs-parser "20.2.4" - yargs-unparser "2.0.0" - -ms@2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -ms@2.1.3, ms@^2.0.0: - version "2.1.3" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" - integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== - -mz@^2.7.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" - integrity sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q== - dependencies: - any-promise "^1.0.0" - object-assign "^4.0.1" - thenify-all "^1.0.0" - -nanoid@3.3.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.1.tgz#6347a18cac88af88f58af0b3594b723d5e99bb35" - integrity sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw== - -nanoid@3.3.3: - version "3.3.3" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.3.tgz#fd8e8b7aa761fe807dba2d1b98fb7241bb724a25" - integrity sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w== - -natural-compare@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" - integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== - -no-case@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d" - integrity sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg== - dependencies: - lower-case "^2.0.2" - tslib "^2.0.3" - -node-fetch@^2.6.11, node-fetch@^2.6.12: - version "2.6.12" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.12.tgz#02eb8e22074018e3d5a83016649d04df0e348fba" - integrity sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g== - dependencies: - whatwg-url "^5.0.0" - -node-fetch@^2.7.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" - integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== - dependencies: - whatwg-url "^5.0.0" - -node-gyp-build@^4.3.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.6.0.tgz#0c52e4cbf54bbd28b709820ef7b6a3c2d6209055" - integrity sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ== - -normalize-path@^3.0.0, normalize-path@~3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" - integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== - -object-assign@^4.0.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== - -object-is@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac" - integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - -object-keys@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" - integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== - -object.assign@^4.1.4: - version "4.1.5" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.5.tgz#3a833f9ab7fdb80fc9e8d2300c803d216d8fdbb0" - integrity sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ== - dependencies: - call-bind "^1.0.5" - define-properties "^1.2.1" - has-symbols "^1.0.3" - object-keys "^1.1.1" - -once@^1.3.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== - dependencies: - wrappy "1" - -optionator@^0.9.3: - version "0.9.3" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.3.tgz#007397d44ed1872fdc6ed31360190f81814e2c64" - integrity sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg== - dependencies: - "@aashutoshrathi/word-wrap" "^1.2.3" - deep-is "^0.1.3" - fast-levenshtein "^2.0.6" - levn "^0.4.1" - prelude-ls "^1.2.1" - type-check "^0.4.0" - -p-limit@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" - integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== - dependencies: - yocto-queue "^0.1.0" - -p-locate@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" - integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== - dependencies: - p-limit "^3.0.2" - -pako@^2.0.3: - version "2.1.0" - resolved "https://registry.yarnpkg.com/pako/-/pako-2.1.0.tgz#266cc37f98c7d883545d11335c00fbd4062c9a86" - integrity sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug== - -parent-module@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" - integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== - dependencies: - callsites "^3.0.0" - -path-exists@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" - integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== - -path-key@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" - integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== - -path-scurry@^1.10.1: - version "1.10.1" - resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.10.1.tgz#9ba6bf5aa8500fe9fd67df4f0d9483b2b0bfc698" - integrity sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ== - dependencies: - lru-cache "^9.1.1 || ^10.0.0" - minipass "^5.0.0 || ^6.0.2 || ^7.0.0" - -path-type@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" - integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== - -pathval@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" - integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== - -pathval@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/pathval/-/pathval-2.0.0.tgz#7e2550b422601d4f6b8e26f1301bc8f15a741a25" - integrity sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA== - -picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" - integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== - -prelude-ls@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" - integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== - -prettier@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.1.1.tgz#6ba9f23165d690b6cbdaa88cb0807278f7019848" - integrity sha512-22UbSzg8luF4UuZtzgiUOfcGM8s4tjBv6dJRT7j275NXsy2jb4aJa4NNveul5x4eqlF1wuhuR2RElK71RvmVaw== - -process@^0.11.10: - version "0.11.10" - resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" - integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== - -punycode@^2.1.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" - integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== - -queue-microtask@^1.2.2: - version "1.2.3" - resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" - integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== - -randombytes@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" - integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== - dependencies: - safe-buffer "^5.1.0" - -readdirp@~3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" - integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== - dependencies: - picomatch "^2.2.1" - -regenerator-runtime@^0.13.11: - version "0.13.11" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9" - integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg== - -regenerator-runtime@^0.14.0: - version "0.14.1" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" - integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw== - -require-directory@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== - -resolve-from@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" - integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== - -reusify@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" - integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== - -rimraf@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" - integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== - dependencies: - glob "^7.1.3" - -rimraf@^5.0.5: - version "5.0.5" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-5.0.5.tgz#9be65d2d6e683447d2e9013da2bf451139a61ccf" - integrity sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A== - dependencies: - glob "^10.3.7" - -rpc-websockets@^7.5.1: - version "7.5.1" - resolved "https://registry.yarnpkg.com/rpc-websockets/-/rpc-websockets-7.5.1.tgz#e0a05d525a97e7efc31a0617f093a13a2e10c401" - integrity sha512-kGFkeTsmd37pHPMaHIgN1LVKXMi0JD782v4Ds9ZKtLlwdTKjn+CxM9A9/gLT2LaOuEcEFGL98h1QWQtlOIdW0w== - dependencies: - "@babel/runtime" "^7.17.2" - eventemitter3 "^4.0.7" - uuid "^8.3.2" - ws "^8.5.0" - optionalDependencies: - bufferutil "^4.0.1" - utf-8-validate "^5.0.2" - -run-parallel@^1.1.9: - version "1.2.0" - resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" - integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== - dependencies: - queue-microtask "^1.2.2" - -safe-buffer@^5.0.1, safe-buffer@^5.1.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== - -semver@^7.5.4: - version "7.5.4" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" - integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== - dependencies: - lru-cache "^6.0.0" - -serialize-javascript@6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" - integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== - dependencies: - randombytes "^2.1.0" - -set-function-length@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.1.1.tgz#4bc39fafb0307224a33e106a7d35ca1218d659ed" - integrity sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ== - dependencies: - define-data-property "^1.1.1" - get-intrinsic "^1.2.1" - gopd "^1.0.1" - has-property-descriptors "^1.0.0" - -shebang-command@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" - integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== - dependencies: - shebang-regex "^3.0.0" - -shebang-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" - integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== - -shiki@^0.14.7: - version "0.14.7" - resolved "https://registry.yarnpkg.com/shiki/-/shiki-0.14.7.tgz#c3c9e1853e9737845f1d2ef81b31bcfb07056d4e" - integrity sha512-dNPAPrxSc87ua2sKJ3H5dQ/6ZaY8RNnaAqK+t0eG7p0Soi2ydiqbGOTaZCqaYvA/uZYfS1LJnemt3Q+mSfcPCg== - dependencies: - ansi-sequence-parser "^1.1.0" - jsonc-parser "^3.2.0" - vscode-oniguruma "^1.7.0" - vscode-textmate "^8.0.0" - -signal-exit@^4.0.1: - version "4.1.0" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" - integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== - -slash@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" - integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== - -snake-case@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/snake-case/-/snake-case-3.0.4.tgz#4f2bbd568e9935abdfd593f34c691dadb49c452c" - integrity sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg== - dependencies: - dot-case "^3.0.4" - tslib "^2.0.3" - -source-map-support@^0.5.6: - version "0.5.21" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" - integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - -source-map@^0.6.0: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== - -"string-width-cjs@npm:string-width@^4.2.0": - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -string-width@^4.1.0, string-width@^4.2.0: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -string-width@^5.0.1, string-width@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" - integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== - dependencies: - eastasianwidth "^0.2.0" - emoji-regex "^9.2.2" - strip-ansi "^7.0.1" - -"strip-ansi-cjs@npm:strip-ansi@^6.0.1": - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-ansi@^7.0.1: - version "7.1.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" - integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== - dependencies: - ansi-regex "^6.0.1" - -strip-bom@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" - integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA== - -strip-json-comments@3.1.1, strip-json-comments@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" - integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== - -superstruct@^0.14.2: - version "0.14.2" - resolved "https://registry.yarnpkg.com/superstruct/-/superstruct-0.14.2.tgz#0dbcdf3d83676588828f1cf5ed35cda02f59025b" - integrity sha512-nPewA6m9mR3d6k7WkZ8N8zpTWfenFH3q9pA2PkuiZxINr9DKB2+40wEQf0ixn8VaGuJ78AB6iWOtStI+/4FKZQ== - -superstruct@^0.15.4: - version "0.15.5" - resolved "https://registry.yarnpkg.com/superstruct/-/superstruct-0.15.5.tgz#0f0a8d3ce31313f0d84c6096cd4fa1bfdedc9dab" - integrity sha512-4AOeU+P5UuE/4nOUkmcQdW5y7i9ndt1cQd/3iUe+LTz3RxESf/W/5lg4B74HbDMMv8PHnPnGCQFH45kBcrQYoQ== - -supports-color@8.1.1: - version "8.1.1" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" - integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== - dependencies: - has-flag "^4.0.0" - -supports-color@^7.1.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" - integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== - dependencies: - has-flag "^4.0.0" - -text-encoding-utf-8@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/text-encoding-utf-8/-/text-encoding-utf-8-1.0.2.tgz#585b62197b0ae437e3c7b5d0af27ac1021e10d13" - integrity sha512-8bw4MY9WjdsD2aMtO0OzOCY3pXGYNx2d2FfHRVUKkiCPDWjKuOlhLVASS+pD7VkLTVjW268LYJHwsnPFlBpbAg== - -text-table@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== - -thenify-all@^1.0.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726" - integrity sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA== - dependencies: - thenify ">= 3.1.0 < 4" - -"thenify@>= 3.1.0 < 4": - version "3.3.1" - resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.1.tgz#8932e686a4066038a016dd9e2ca46add9838a95f" - integrity sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw== - dependencies: - any-promise "^1.0.0" - -"through@>=2.2.7 <3": - version "2.3.8" - resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== - -tiny-invariant@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.1.tgz#8560808c916ef02ecfd55e66090df23a4b7aa642" - integrity sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw== - -to-regex-range@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" - integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== - dependencies: - is-number "^7.0.0" - -toml@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/toml/-/toml-3.0.0.tgz#342160f1af1904ec9d204d03a5d61222d762c5ee" - integrity sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w== - -tr46@~0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" - integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== - -ts-api-utils@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.0.3.tgz#f12c1c781d04427313dbac808f453f050e54a331" - integrity sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg== - -ts-mocha@^10.0.0: - version "10.0.0" - resolved "https://registry.yarnpkg.com/ts-mocha/-/ts-mocha-10.0.0.tgz#41a8d099ac90dbbc64b06976c5025ffaebc53cb9" - integrity sha512-VRfgDO+iiuJFlNB18tzOfypJ21xn2xbuZyDvJvqpTbWgkAgD17ONGr8t+Tl8rcBtOBdjXp5e/Rk+d39f7XBHRw== - dependencies: - ts-node "7.0.1" - optionalDependencies: - tsconfig-paths "^3.5.0" - -ts-node@7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-7.0.1.tgz#9562dc2d1e6d248d24bc55f773e3f614337d9baf" - integrity sha512-BVwVbPJRspzNh2yfslyT1PSbl5uIk03EZlb493RKHN4qej/D06n1cEhjlOJG69oFsE7OT8XjpTUcYf6pKTLMhw== - dependencies: - arrify "^1.0.0" - buffer-from "^1.1.0" - diff "^3.1.0" - make-error "^1.1.1" - minimist "^1.2.0" - mkdirp "^0.5.1" - source-map-support "^0.5.6" - yn "^2.0.0" - -ts-node@^10.9.2: - version "10.9.2" - resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.2.tgz#70f021c9e185bccdca820e26dc413805c101c71f" - integrity sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ== - dependencies: - "@cspotcode/source-map-support" "^0.8.0" - "@tsconfig/node10" "^1.0.7" - "@tsconfig/node12" "^1.0.7" - "@tsconfig/node14" "^1.0.0" - "@tsconfig/node16" "^1.0.2" - acorn "^8.4.1" - acorn-walk "^8.1.1" - arg "^4.1.0" - create-require "^1.1.0" - diff "^4.0.1" - make-error "^1.1.1" - v8-compile-cache-lib "^3.0.1" - yn "3.1.1" - -tsconfig-paths@^3.5.0: - version "3.14.2" - resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz#6e32f1f79412decd261f92d633a9dc1cfa99f088" - integrity sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g== - dependencies: - "@types/json5" "^0.0.29" - json5 "^1.0.2" - minimist "^1.2.6" - strip-bom "^3.0.0" - -tslib@^2.0.3: - version "2.6.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.1.tgz#fd8c9a0ff42590b25703c0acb3de3d3f4ede0410" - integrity sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig== - -type-check@^0.4.0, type-check@~0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" - integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== - dependencies: - prelude-ls "^1.2.1" - -type-detect@^4.0.0, type-detect@^4.0.5: - version "4.0.8" - resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" - integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== - -type-fest@^0.20.2: - version "0.20.2" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" - integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== - -typedoc@~0.25.7: - version "0.25.7" - resolved "https://registry.yarnpkg.com/typedoc/-/typedoc-0.25.7.tgz#11e3f527ca80ca3c029cb8e15f362e6d9f715e25" - integrity sha512-m6A6JjQRg39p2ZVRIN3NKXgrN8vzlHhOS+r9ymUYtcUP/TIQPvWSq7YgE5ZjASfv5Vd5BW5xrir6Gm2XNNcOow== - dependencies: - lunr "^2.3.9" - marked "^4.3.0" - minimatch "^9.0.3" - shiki "^0.14.7" - -typescript@^5.3.3: - version "5.3.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.3.3.tgz#b3ce6ba258e72e6305ba66f5c9b452aaee3ffe37" - integrity sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw== - -undici-types@~5.26.4: - version "5.26.5" - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" - integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== - -uri-js@^4.2.2: - version "4.4.1" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" - integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== - dependencies: - punycode "^2.1.0" - -utf-8-validate@^5.0.2: - version "5.0.10" - resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-5.0.10.tgz#d7d10ea39318171ca982718b6b96a8d2442571a2" - integrity sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ== - dependencies: - node-gyp-build "^4.3.0" - -util@^0.12.5: - version "0.12.5" - resolved "https://registry.yarnpkg.com/util/-/util-0.12.5.tgz#5f17a6059b73db61a875668781a1c2b136bd6fbc" - integrity sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA== - dependencies: - inherits "^2.0.3" - is-arguments "^1.0.4" - is-generator-function "^1.0.7" - is-typed-array "^1.1.3" - which-typed-array "^1.1.2" - -uuid@^8.3.2: - version "8.3.2" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" - integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== - -v8-compile-cache-lib@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" - integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== - -vscode-oniguruma@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz#439bfad8fe71abd7798338d1cd3dc53a8beea94b" - integrity sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA== - -vscode-textmate@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-8.0.0.tgz#2c7a3b1163ef0441097e0b5d6389cd5504b59e5d" - integrity sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg== - -webidl-conversions@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" - integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== - -whatwg-url@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" - integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== - dependencies: - tr46 "~0.0.3" - webidl-conversions "^3.0.0" - -which-typed-array@^1.1.11, which-typed-array@^1.1.2: - version "1.1.13" - resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.13.tgz#870cd5be06ddb616f504e7b039c4c24898184d36" - integrity sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow== - dependencies: - available-typed-arrays "^1.0.5" - call-bind "^1.0.4" - for-each "^0.3.3" - gopd "^1.0.1" - has-tostringtag "^1.0.0" - -which@2.0.2, which@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" - integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== - dependencies: - isexe "^2.0.0" - -workerpool@6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.0.tgz#827d93c9ba23ee2019c3ffaff5c27fccea289e8b" - integrity sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A== - -workerpool@6.2.1: - version "6.2.1" - resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" - integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== - -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -wrap-ansi@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" - integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== - dependencies: - ansi-styles "^6.1.0" - string-width "^5.0.1" - strip-ansi "^7.0.1" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== - -ws@^7.4.5: - version "7.5.9" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" - integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== - -ws@^8.5.0: - version "8.13.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.13.0.tgz#9a9fb92f93cf41512a0735c8f4dd09b8a1211cd0" - integrity sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA== - -y18n@^5.0.5: - version "5.0.8" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" - integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== - -yallist@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" - integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== - -yargs-parser@20.2.4: - version "20.2.4" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" - integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== - -yargs-parser@^20.2.2: - version "20.2.9" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" - integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== - -yargs-unparser@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" - integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== - dependencies: - camelcase "^6.0.0" - decamelize "^4.0.0" - flat "^5.0.2" - is-plain-obj "^2.1.0" - -yargs@16.2.0: - version "16.2.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" - integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== - dependencies: - cliui "^7.0.2" - escalade "^3.1.1" - get-caller-file "^2.0.5" - require-directory "^2.1.1" - string-width "^4.2.0" - y18n "^5.0.5" - yargs-parser "^20.2.2" - -yn@3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" - integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== - -yn@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/yn/-/yn-2.0.0.tgz#e5adabc8acf408f6385fc76495684c88e6af689a" - integrity sha512-uTv8J/wiWTgUTg+9vLTi//leUl5vDQS6uii/emeTb2ssY7vl6QWf2fFbIIGjnhjvbdKlU0ed7QPgY1htTC86jQ== - -yocto-queue@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" - integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==