From ccc8cc4b99adcd192b363ecaecf5af92a02092db Mon Sep 17 00:00:00 2001 From: Christian Kamm Date: Wed, 12 Oct 2022 17:54:50 +0200 Subject: [PATCH 01/28] cli script to compute account equity from solana snapshot --- Cargo.lock | 2556 +++++++++++++++++++++++++++++++++++++++-------- Cargo.toml | 3 +- cli/Cargo.toml | 25 + cli/src/main.rs | 254 +++++ 4 files changed, 2412 insertions(+), 426 deletions(-) create mode 100644 cli/Cargo.toml create mode 100644 cli/src/main.rs diff --git a/Cargo.lock b/Cargo.lock index fac31927..8393fb56 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7,14 +7,9 @@ name = "Inflector" version = "0.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" - -[[package]] -name = "addr2line" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" dependencies = [ - "gimli", + "lazy_static", + "regex", ] [[package]] @@ -23,6 +18,42 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "aead" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b613b8e1e3cf911a086f53f03bf286f52fd7a7258e4fa606f0ef220d39d8877" +dependencies = [ + "generic-array", +] + +[[package]] +name = "aes" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8" +dependencies = [ + "cfg-if", + "cipher 0.3.0", + "cpufeatures", + "opaque-debug", +] + +[[package]] +name = "aes-gcm-siv" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589c637f0e68c877bbd59a4599bbe849cac8e5f3e4b5a3ebae8f528cd218dcdc" +dependencies = [ + "aead", + "aes", + "cipher 0.3.0", + "ctr", + "polyval", + "subtle", + "zeroize", +] + [[package]] name = "ahash" version = "0.7.6" @@ -49,6 +80,21 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "250f629c0161ad8107cf89319e990051fae62832fd343083bea452d93e2205fd" +[[package]] +name = "alloc-no-stdlib" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" + +[[package]] +name = "alloc-stdlib" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" +dependencies = [ + "alloc-no-stdlib", +] + [[package]] name = "alloc-traits" version = "0.1.1" @@ -57,127 +103,127 @@ checksum = "6b2d54853319fd101b8dd81de382bcbf3e03410a64d8928bbee85a3e7dcde483" [[package]] name = "anchor-attribute-access-control" -version = "0.24.2" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9b75d05b6b4ac9d95bb6e3b786b27d3a708c4c5a87c92ffaa25bbe9ae4c5d91" +checksum = "70f6ee9518f50ff4d434471ccf569186022bdd5ef65a21d14da3ea5231af944f" dependencies = [ "anchor-syn", "anyhow", - "proc-macro2", - "quote", + "proc-macro2 1.0.37", + "quote 1.0.18", "regex", - "syn", + "syn 1.0.91", ] [[package]] name = "anchor-attribute-account" -version = "0.24.2" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "485351a6d8157750d10d88c8e256f1bf8339262b2220ae9125aed3471309b5de" +checksum = "32c92bcf5388b52676d990f85bbfd838a8f5672393135063a50dc79b2b837c79" dependencies = [ "anchor-syn", "anyhow", "bs58 0.4.0", - "proc-macro2", - "quote", + "proc-macro2 1.0.37", + "quote 1.0.18", "rustversion", - "syn", + "syn 1.0.91", ] [[package]] name = "anchor-attribute-constant" -version = "0.24.2" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc632c540913dd051a78b00587cc47f57013d303163ddfaf4fa18717f7ccc1e0" +checksum = "0844974ac35e8ced62056b0d63777ebcdc5807438b8b189c881e2b647450b70a" dependencies = [ "anchor-syn", - "proc-macro2", - "syn", + "proc-macro2 1.0.37", + "syn 1.0.91", ] [[package]] name = "anchor-attribute-error" -version = "0.24.2" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b5bd1dcfa7f3bc22dacef233d70a9e0bee269c4ac484510662f257cba2353a1" +checksum = "0f7467345e67a6f1d4b862b9763a4160ad89d18c247b8c902807768f7b6e23df" dependencies = [ "anchor-syn", - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.37", + "quote 1.0.18", + "syn 1.0.91", ] [[package]] name = "anchor-attribute-event" -version = "0.24.2" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c6f9e6ce551ac9a177a45c99a65699a860c9e95fac68675138af1246e2591b0" +checksum = "8774e4c1ac71f71a5aea7e4932fb69c30e3b8155c4fa59fd69401195434528a9" dependencies = [ "anchor-syn", "anyhow", - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.37", + "quote 1.0.18", + "syn 1.0.91", ] [[package]] name = "anchor-attribute-interface" -version = "0.24.2" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d104aa17418cb329ed7418b227e083d5f326a27f26ce98f5d92e33da62a5f459" +checksum = "90eeb6e1c80f9f94fcef93a52813f6472186200e275e83cb3fac92b801de92f7" dependencies = [ "anchor-syn", "anyhow", - "heck", - "proc-macro2", - "quote", - "syn", + "heck 0.3.3", + "proc-macro2 1.0.37", + "quote 1.0.18", + "syn 1.0.91", ] [[package]] name = "anchor-attribute-program" -version = "0.24.2" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6831b920b173c004ddf7ae1167d1d25e9f002ffcb1773bbc5c7ce532a4441e1" +checksum = "ac515a7a5a4fea7fc768b1cec40ddb948e148ea657637c75f94f283212326cb9" dependencies = [ "anchor-syn", "anyhow", - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.37", + "quote 1.0.18", + "syn 1.0.91", ] [[package]] name = "anchor-attribute-state" -version = "0.24.2" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cde147b10c71d95dc679785db0b5f3abac0091f789167aa62ac0135e2f54e8b9" +checksum = "43dc667b62ff71450f19dcfcc37b0c408fd4ddd89e8650368c2b0984b110603f" dependencies = [ "anchor-syn", "anyhow", - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.37", + "quote 1.0.18", + "syn 1.0.91", ] [[package]] name = "anchor-derive-accounts" -version = "0.24.2" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cde98a0e1a56046b040ff591dfda391f88917af2b6487d02b45093c05be3514" +checksum = "7354d583a06701d24800a8ec4c2b0491f62581a331af349205e23421e0b56643" dependencies = [ "anchor-syn", "anyhow", - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.37", + "quote 1.0.18", + "syn 1.0.91", ] [[package]] name = "anchor-lang" -version = "0.24.2" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a85dd2c5e29e20c7f4701a43724d6cd5406d0ee5694705522e43da0f26542a84" +checksum = "ff5f57ec5e12fa6874b27f3d5c1f6f44302d3ad86c1266197ff7611bf6f5d251" dependencies = [ "anchor-attribute-access-control", "anchor-attribute-account", @@ -199,23 +245,32 @@ dependencies = [ [[package]] name = "anchor-syn" -version = "0.24.2" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03549dc2eae0b20beba6333b14520e511822a6321cdb1760f841064a69347316" +checksum = "55aa1e680d9471342122ed5b6bc13bf5da473b0f7e4677d41a6954e5cc8ad155" dependencies = [ "anyhow", "bs58 0.3.1", - "heck", - "proc-macro2", + "heck 0.3.3", + "proc-macro2 1.0.37", "proc-macro2-diagnostics", - "quote", + "quote 1.0.18", "serde", "serde_json", - "sha2", - "syn", + "sha2 0.9.9", + "syn 1.0.91", "thiserror", ] +[[package]] +name = "ansi_term" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +dependencies = [ + "winapi", +] + [[package]] name = "anyhow" version = "1.0.56" @@ -240,21 +295,83 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eab1c04a571841102f5345a8fc0f6bb3d31c315dec879b5c6e42e40ce7ffa34e" +[[package]] +name = "asn1-rs" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf6690c370453db30743b373a60ba498fc0d6d83b11f4abfd87a84a075db5dd4" +dependencies = [ + "asn1-rs-derive", + "asn1-rs-impl", + "displaydoc", + "nom", + "num-traits", + "rusticata-macros", + "thiserror", + "time 0.3.15", +] + +[[package]] +name = "asn1-rs-derive" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "726535892e8eae7e70657b4c8ea93d26b8553afb1ce617caee529ef96d7dee6c" +dependencies = [ + "proc-macro2 1.0.37", + "quote 1.0.18", + "syn 1.0.91", + "synstructure", +] + +[[package]] +name = "asn1-rs-impl" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2777730b2039ac0f95f093556e61b6d26cebed5393ca6f152717777cec3a42ed" +dependencies = [ + "proc-macro2 1.0.37", + "quote 1.0.18", + "syn 1.0.91", +] + [[package]] name = "assert_matches" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" +[[package]] +name = "async-compression" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "942c7cd7ae39e91bde4820d74132e9862e62c2f386c3aa90ccf55949f5bad63a" +dependencies = [ + "brotli", + "flate2", + "futures-core", + "memchr", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "async-mutex" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479db852db25d9dbf6204e6cb6253698f175c15726470f78af0d918e99d6156e" +dependencies = [ + "event-listener", +] + [[package]] name = "async-trait" version = "0.1.53" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed6aa3524a2dfcf9fe180c51eae2b58738348d819517ceadf95789c51fff7600" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.37", + "quote 1.0.18", + "syn 1.0.91", ] [[package]] @@ -280,21 +397,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f771a5d1f5503f7f4279a30f3643d3421ba149848b89ecaaec0ea2acf04a5ac4" -[[package]] -name = "backtrace" -version = "0.3.65" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11a17d453482a265fd5f8479f2a3f405566e6ca627837aaddb85af8b1ab8ef61" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", -] - [[package]] name = "base64" version = "0.12.3" @@ -307,6 +409,12 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" +[[package]] +name = "base64ct" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea2b2456fd614d856680dcd9fcc660a51a820fa09daef2e49772b56a193c8474" + [[package]] name = "bincode" version = "1.3.3" @@ -322,6 +430,15 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitmaps" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "031043d04099746d8db04daf1fa424b2bc8bd69d92b25962dcde24da39ab64a2" +dependencies = [ + "typenum", +] + [[package]] name = "blake3" version = "1.3.1" @@ -368,7 +485,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "15bf3650200d8bffa99015595e10f1fbd17de07abbc25bb067da79e769939bfa" dependencies = [ "borsh-derive", - "hashbrown", + "hashbrown 0.11.2", ] [[package]] @@ -380,8 +497,8 @@ dependencies = [ "borsh-derive-internal", "borsh-schema-derive-internal", "proc-macro-crate 0.1.5", - "proc-macro2", - "syn", + "proc-macro2 1.0.37", + "syn 1.0.91", ] [[package]] @@ -390,9 +507,9 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5449c28a7b352f2d1e592a8a28bf139bc71afb0764a14f3c02500935d8c44065" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.37", + "quote 1.0.18", + "syn 1.0.91", ] [[package]] @@ -401,9 +518,30 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdbd5696d8bfa21d53d9fe39a714a18538bad11492a42d066dbbc395fb1951c0" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.37", + "quote 1.0.18", + "syn 1.0.91", +] + +[[package]] +name = "brotli" +version = "3.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1a0b1dbcc8ae29329621f8d4f0d835787c1c38bb1401979b49d13b0b305ff68" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", + "brotli-decompressor", +] + +[[package]] +name = "brotli-decompressor" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ad2d4653bf5ca36ae797b1f4bb4dbddb60ce49ca4aed8a2ce4829f60425b80" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", ] [[package]] @@ -449,9 +587,9 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "562e382481975bc61d11275ac5e62a19abd00b0547d99516a415336f183dcd0e" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.37", + "quote 1.0.18", + "syn 1.0.91", ] [[package]] @@ -487,6 +625,16 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "caps" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "938c50180feacea622ef3b8f4a496057c868dcf8ac7a64d781dd8f3f51a9c143" +dependencies = [ + "libc", + "thiserror", +] + [[package]] name = "cc" version = "1.0.73" @@ -512,7 +660,7 @@ dependencies = [ "num-integer", "num-traits", "serde", - "time", + "time 0.1.43", "winapi", ] @@ -525,6 +673,102 @@ dependencies = [ "chrono", ] +[[package]] +name = "cipher" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" +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 = "clap" +version = "2.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +dependencies = [ + "ansi_term", + "atty", + "bitflags", + "strsim 0.8.0", + "textwrap 0.11.0", + "unicode-width", + "vec_map", +] + +[[package]] +name = "clap" +version = "3.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e538f9ee5aa3b3963f09a997035f883677966ed50fce0292611927ce6f6d8c6" +dependencies = [ + "atty", + "bitflags", + "clap_derive", + "clap_lex", + "indexmap", + "lazy_static", + "strsim 0.10.0", + "termcolor", + "textwrap 0.15.1", +] + +[[package]] +name = "clap_derive" +version = "3.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7f98063cac4652f23ccda556b8d04347a7fc4b2cff1f7577cc8c6546e0d8078" +dependencies = [ + "heck 0.4.0", + "proc-macro-error", + "proc-macro2 1.0.37", + "quote 1.0.18", + "syn 1.0.91", +] + +[[package]] +name = "clap_lex" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" +dependencies = [ + "os_str_bytes", +] + +[[package]] +name = "cli" +version = "0.1.0" +dependencies = [ + "anyhow", + "bytemuck", + "clap 3.2.2", + "dotenv", + "env_logger 0.8.4", + "fixed", + "fixed-macro", + "futures", + "log", + "mango", + "mango-common", + "pyth-sdk-solana", + "rusqlite", + "serum_dex", + "solana-client", + "solana-sdk", + "tokio", +] + [[package]] name = "combine" version = "3.8.1" @@ -538,6 +782,20 @@ dependencies = [ "unreachable", ] +[[package]] +name = "console" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c050367d967ced717c04b65d8c619d863ef9292ce0c5760028655a2fb298718c" +dependencies = [ + "encode_unicode", + "lazy_static", + "libc", + "terminal_size", + "unicode-width", + "winapi", +] + [[package]] name = "console_error_panic_hook" version = "0.1.7" @@ -558,12 +816,34 @@ dependencies = [ "web-sys", ] +[[package]] +name = "const-oid" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4c78c047431fee22c1a7bb92e00ad095a02a983affe4d8a72e2a2c62c1b94f3" + [[package]] name = "constant_time_eq" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" +[[package]] +name = "core-foundation" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" + [[package]] name = "cpufeatures" version = "0.2.2" @@ -654,23 +934,12 @@ dependencies = [ ] [[package]] -name = "crypto-mac" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58bcd97a54c7ca5ce2f6eb16f6bede5b0ab5f0055fedc17d2f0b4466e21671ca" -dependencies = [ - "generic-array", - "subtle", -] - -[[package]] -name = "crypto-mac" -version = "0.11.1" +name = "ctr" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" +checksum = "049bb91fb4aaf0e3c7efa6cd5ef877dbbbd15b39dad06d9948de4ec8a75761ea" dependencies = [ - "generic-array", - "subtle", + "cipher 0.3.0", ] [[package]] @@ -682,6 +951,7 @@ dependencies = [ "byteorder", "digest 0.9.0", "rand_core 0.5.1", + "serde", "subtle", "zeroize", ] @@ -697,13 +967,50 @@ dependencies = [ "rayon", ] +[[package]] +name = "data-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ee2393c4a91429dffb4bedf19f4d6abf27d8a732c8ce4980305d782e5426d57" + +[[package]] +name = "der" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6919815d73839e7ad218de758883aae3a257ba6759ce7a9992501efbb53d705c" +dependencies = [ + "const-oid", +] + +[[package]] +name = "der-parser" +version = "8.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42d4bc9b0db0a0df9ae64634ac5bdefb7afcb534e182275ca0beadbe486701c1" +dependencies = [ + "asn1-rs", + "displaydoc", + "nom", + "num-bigint 0.4.3", + "num-traits", + "rusticata-macros", +] + [[package]] name = "derivation-path" -version = "0.1.3" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "193388a8c8c75a490b604ff61775e236541b8975e98e5ca1f6ea97d122b7e2db" +checksum = "6e5c37193a1db1d8ed868c03ec7b152175f26160a5b740e5e484143877e0adf0" + +[[package]] +name = "dialoguer" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a92e7e37ecef6857fdc0c0c5d42fd5b0938e46590c2183cc92dd310a6d078eb1" dependencies = [ - "failure", + "console", + "tempfile", + "zeroize", ] [[package]] @@ -736,39 +1043,105 @@ dependencies = [ ] [[package]] -name = "ed25519" -version = "1.4.1" +name = "dirs-next" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d5c4b5e5959dc2c2b89918d8e2cc40fcdd623cef026ed09d2f0ee05199dc8e4" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" dependencies = [ - "signature", + "cfg-if", + "dirs-sys-next", ] [[package]] -name = "ed25519-dalek" -version = "1.0.1" +name = "dirs-sys-next" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" dependencies = [ - "curve25519-dalek", - "ed25519", - "rand 0.7.3", - "serde", - "sha2", - "zeroize", + "libc", + "redox_users", + "winapi", ] [[package]] -name = "ed25519-dalek-bip32" -version = "0.1.1" +name = "displaydoc" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "057f328f31294b5ab432e6c39642f54afd1531677d6d4ba2905932844cc242f3" +checksum = "3bf95dc3f046b9da4f2d51833c0d3547d8564ef6910f5c1ed130306a75b92886" +dependencies = [ + "proc-macro2 1.0.37", + "quote 1.0.18", + "syn 1.0.91", +] + +[[package]] +name = "dlopen" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71e80ad39f814a9abe68583cd50a2d45c8a67561c3361ab8da240587dda80937" +dependencies = [ + "dlopen_derive", + "lazy_static", + "libc", + "winapi", +] + +[[package]] +name = "dlopen_derive" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f236d9e1b1fbd81cea0f9cbdc8dcc7e8ebcd80e6659cd7cb2ad5f6c05946c581" +dependencies = [ + "libc", + "quote 0.6.13", + "syn 0.15.44", +] + +[[package]] +name = "dotenv" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" + +[[package]] +name = "dyn-clone" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f94fa09c2aeea5b8839e414b7b841bf429fd25b9c522116ac97ee87856d88b2" + +[[package]] +name = "ed25519" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d5c4b5e5959dc2c2b89918d8e2cc40fcdd623cef026ed09d2f0ee05199dc8e4" +dependencies = [ + "signature", +] + +[[package]] +name = "ed25519-dalek" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d" +dependencies = [ + "curve25519-dalek", + "ed25519", + "rand 0.7.3", + "serde", + "sha2 0.9.9", + "zeroize", +] + +[[package]] +name = "ed25519-dalek-bip32" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d2be62a4061b872c8c0873ee4fc6f101ce7b889d039f019c5fa2af471a59908" dependencies = [ "derivation-path", "ed25519-dalek", - "failure", - "hmac 0.9.0", - "sha2", + "hmac 0.12.1", + "sha2 0.10.5", ] [[package]] @@ -778,9 +1151,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c07b7cc9cd8c08d10db74fca3b20949b9b6199725c04a0cce6d543496098fcac" dependencies = [ "enum-ordinalize", - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.37", + "quote 1.0.18", + "syn 1.0.91", ] [[package]] @@ -789,6 +1162,12 @@ version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" +[[package]] +name = "encode_unicode" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" + [[package]] name = "encoding_rs" version = "0.8.31" @@ -798,18 +1177,50 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "enum-iterator" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4eeac5c5edb79e4e39fe8439ef35207780a11f69c52cbe424ce3dfad4cb78de6" +dependencies = [ + "enum-iterator-derive", +] + +[[package]] +name = "enum-iterator-derive" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c134c37760b27a871ba422106eedbb8247da973a09e82558bf26d619c882b159" +dependencies = [ + "proc-macro2 1.0.37", + "quote 1.0.18", + "syn 1.0.91", +] + [[package]] name = "enum-ordinalize" version = "3.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2170fc0efee383079a8bdd05d6ea2a184d2a0f07a1c1dcabdb2fd5e9f24bc36c" dependencies = [ - "num-bigint", + "num-bigint 0.4.3", "num-traits", - "proc-macro2", - "quote", + "proc-macro2 1.0.37", + "quote 1.0.18", "rustc_version 0.4.0", - "syn", + "syn 1.0.91", +] + +[[package]] +name = "enum_dispatch" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eb359f1476bf611266ac1f5355bc14aeca37b299d0ebccc038ee7058891c9cb" +dependencies = [ + "once_cell", + "proc-macro2 1.0.37", + "quote 1.0.18", + "syn 1.0.91", ] [[package]] @@ -827,16 +1238,16 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "946ee94e3dbf58fdd324f9ce245c7b238d46a66f00e86a020b71996349e46cce" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.37", + "quote 1.0.18", + "syn 1.0.91", ] [[package]] name = "env_logger" -version = "0.9.0" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3" +checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3" dependencies = [ "atty", "humantime", @@ -846,26 +1257,35 @@ dependencies = [ ] [[package]] -name = "failure" -version = "0.1.8" +name = "env_logger" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86" +checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3" dependencies = [ - "backtrace", - "failure_derive", + "atty", + "humantime", + "log", + "regex", + "termcolor", ] [[package]] -name = "failure_derive" -version = "0.1.8" +name = "event-listener" +version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "synstructure", -] +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + +[[package]] +name = "fallible-iterator" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" + +[[package]] +name = "fallible-streaming-iterator" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" [[package]] name = "fastrand" @@ -911,6 +1331,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "80a9a8cb2e34880a498f09367089339bda5e12d6f871640f947850f7113058c0" dependencies = [ "az", + "borsh", "bytemuck", "half", "serde", @@ -937,9 +1358,9 @@ dependencies = [ "fixed", "paste", "proc-macro-error", - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.37", + "quote 1.0.18", + "syn 1.0.91", ] [[package]] @@ -980,12 +1401,6 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "fs_extra" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2022715d62ab30faffd124d40b76f4134a550a87792276512b18d63272333394" - [[package]] name = "futures" version = "0.3.21" @@ -1040,9 +1455,9 @@ version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.37", + "quote 1.0.18", + "syn 1.0.91", ] [[package]] @@ -1075,6 +1490,15 @@ dependencies = [ "slab", ] +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + [[package]] name = "generic-array" version = "0.14.5" @@ -1120,12 +1544,6 @@ dependencies = [ "wasi 0.10.2+wasi-snapshot-preview1", ] -[[package]] -name = "gimli" -version = "0.26.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" - [[package]] name = "goblin" version = "0.4.3" @@ -1180,6 +1598,24 @@ dependencies = [ "ahash", ] +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash", +] + +[[package]] +name = "hashlink" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69fe1fcf8b4278d860ad0548329f892a3631fb63f82574df68275f34cdbe0ffa" +dependencies = [ + "hashbrown 0.12.3", +] + [[package]] name = "heck" version = "0.3.3" @@ -1189,6 +1625,12 @@ dependencies = [ "unicode-segmentation", ] +[[package]] +name = "heck" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" + [[package]] name = "hermit-abi" version = "0.1.19" @@ -1199,33 +1641,28 @@ dependencies = [ ] [[package]] -name = "hmac" -version = "0.8.1" +name = "histogram" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "126888268dcc288495a26bf004b38c5fdbb31682f992c84ceb046a1f0fe38840" -dependencies = [ - "crypto-mac 0.8.0", - "digest 0.9.0", -] +checksum = "12cb882ccb290b8646e554b157ab0b71e64e8d5bef775cd66b6531e52d302669" [[package]] name = "hmac" -version = "0.9.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "deae6d9dbb35ec2c502d62b8f7b1c000a0822c3b0794ba36b3149c0a1c840dff" +checksum = "126888268dcc288495a26bf004b38c5fdbb31682f992c84ceb046a1f0fe38840" dependencies = [ - "crypto-mac 0.9.1", + "crypto-mac", "digest 0.9.0", ] [[package]] name = "hmac" -version = "0.11.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "crypto-mac 0.11.1", - "digest 0.9.0", + "digest 0.10.3", ] [[package]] @@ -1327,6 +1764,22 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "im" +version = "15.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0acd33ff0285af998aaf9b57342af478078f53492322fafc47450e09397e0e9" +dependencies = [ + "bitmaps", + "rand_core 0.6.3", + "rand_xoshiro", + "rayon", + "serde", + "sized-chunks", + "typenum", + "version_check", +] + [[package]] name = "index_list" version = "0.2.7" @@ -1340,7 +1793,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f647032dfaa1f8b6dc29bd3edb7bbef4861b8b8007ebb118d6db284fd59f6ee" dependencies = [ "autocfg", - "hashbrown", + "hashbrown 0.11.2", +] + +[[package]] +name = "indicatif" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d207dc617c7a380ab07ff572a6e52fa202a2a8f355860ac9c38e23f8196be1b" +dependencies = [ + "console", + "lazy_static", + "number_prefix", + "regex", +] + +[[package]] +name = "inout" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "generic-array", ] [[package]] @@ -1400,6 +1874,21 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "jsonrpc-core" +version = "18.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14f7f76aef2d054868398427f6c54943cf3d1caa9a7ec7d0c38d69df97a965eb" +dependencies = [ + "futures", + "futures-executor", + "futures-util", + "log", + "serde", + "serde_derive", + "serde_json", +] + [[package]] name = "keccak" version = "0.1.0" @@ -1414,9 +1903,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.124" +version = "0.2.135" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21a41fed9d98f27ab1c6d161da622a4fa35e8a54a8adc24bbf3ddd0ef70b0e50" +checksum = "68783febc7782c6c5cb401fbda4de5a9898be1762314da0bb2c10ced61f18b0c" [[package]] name = "libloading" @@ -1443,7 +1932,7 @@ dependencies = [ "libsecp256k1-gen-genmult", "rand 0.7.3", "serde", - "sha2", + "sha2 0.9.9", "typenum", ] @@ -1476,6 +1965,22 @@ dependencies = [ "libsecp256k1-core", ] +[[package]] +name = "libsqlite3-sys" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f0455f2c1bc9a7caa792907026e469c1d91761fb0ea37cbb16427c77280cf35" +dependencies = [ + "pkg-config", + "vcpkg", +] + +[[package]] +name = "linked-hash-map" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" + [[package]] name = "lock_api" version = "0.4.7" @@ -1495,6 +2000,35 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "lru" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999beba7b6e8345721bd280141ed958096a2e4abdf74f67ff4ce49b4b54e47a" +dependencies = [ + "hashbrown 0.12.3", +] + +[[package]] +name = "lz4" +version = "1.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e9e2dd86df36ce760a60f6ff6ad526f7ba1f14ba0356f8254fb6905e6494df1" +dependencies = [ + "libc", + "lz4-sys", +] + +[[package]] +name = "lz4-sys" +version = "1.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57d27b317e207b10f69f5e75494119e391a96f48861ae870d1da6edac98ca900" +dependencies = [ + "cc", + "libc", +] + [[package]] name = "mango" version = "3.6.2" @@ -1550,10 +2084,10 @@ version = "3.0.0" dependencies = [ "bytemuck", "mango-common", - "quote", + "quote 1.0.18", "safe-transmute", "solana-program", - "syn", + "syn 1.0.91", ] [[package]] @@ -1586,12 +2120,30 @@ dependencies = [ "autocfg", ] +[[package]] +name = "merlin" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58c38e2799fc0978b65dfff8023ec7843e2330bb462f19198840b34b6582397d" +dependencies = [ + "byteorder", + "keccak", + "rand_core 0.6.3", + "zeroize", +] + [[package]] name = "mime" version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" version = "0.5.1" @@ -1603,15 +2155,14 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.2" +version = "0.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52da4364ffb0e4fe33a9841a98a3f3014fb964045ce4f7a45a398243c8d6b0c9" +checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc" dependencies = [ "libc", "log", "miow", "ntapi", - "wasi 0.11.0+wasi-snapshot-preview1", "winapi", ] @@ -1625,51 +2176,153 @@ dependencies = [ ] [[package]] -name = "ntapi" -version = "0.3.7" +name = "modular-bitfield" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f" +checksum = "a53d79ba8304ac1c4f9eb3b9d281f21f7be9d4626f72ce7df4ad8fbde4f38a74" dependencies = [ - "winapi", + "modular-bitfield-impl", + "static_assertions", ] [[package]] -name = "num-bigint" -version = "0.4.3" +name = "modular-bitfield-impl" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" +checksum = "5a7d5f7076603ebc68de2dc6a650ec331a062a13abaa346975be747bbfa4b789" dependencies = [ - "autocfg", - "num-integer", - "num-traits", + "proc-macro2 1.0.37", + "quote 1.0.18", + "syn 1.0.91", ] [[package]] -name = "num-derive" -version = "0.3.3" +name = "nix" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" +checksum = "9f866317acbd3a240710c63f065ffb1e4fd466259045ccb504130b7f668f35c6" dependencies = [ - "proc-macro2", - "quote", - "syn", + "bitflags", + "cc", + "cfg-if", + "libc", + "memoffset", ] [[package]] -name = "num-integer" -version = "0.1.44" +name = "nom" +version = "7.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" +checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36" dependencies = [ - "autocfg", - "num-traits", + "memchr", + "minimal-lexical", ] [[package]] -name = "num-traits" -version = "0.2.14" +name = "ntapi" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f" +dependencies = [ + "winapi", +] + +[[package]] +name = "num" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8536030f9fea7127f841b45bb6243b27255787fb4eb83958aa1ef9d2fdc0c36" +dependencies = [ + "num-bigint 0.2.6", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6b19411a9719e753aff12e5187b74d60d3dc449ec3f4dc21e3989c3f554bc95" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-derive" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" +dependencies = [ + "proc-macro2 1.0.37", + "quote 1.0.18", + "syn 1.0.91", +] + +[[package]] +name = "num-integer" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef" +dependencies = [ + "autocfg", + "num-bigint 0.2.6", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" dependencies = [ "autocfg", ] @@ -1700,18 +2353,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b0498641e53dd6ac1a4f22547548caa6864cc4933784319cd1775271c5a46ce" dependencies = [ "proc-macro-crate 1.1.3", - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.37", + "quote 1.0.18", + "syn 1.0.91", ] [[package]] -name = "object" -version = "0.28.3" +name = "num_threads" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40bec70ba014595f99f7aa110b84331ffe1ee9aece7fe6f387cc7e3ecda4d456" +checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" dependencies = [ - "memchr", + "libc", +] + +[[package]] +name = "number_prefix" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" + +[[package]] +name = "oid-registry" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d4bda43fd1b844cbc6e6e54b5444e2b1bc7838bce59ad205902cccbb26d6761" +dependencies = [ + "asn1-rs", ] [[package]] @@ -1726,6 +2394,12 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + [[package]] name = "opentelemetry" version = "0.13.0" @@ -1759,11 +2433,17 @@ dependencies = [ "thiserror", ] +[[package]] +name = "os_str_bytes" +version = "6.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ff7415e9ae3fff1225851df9e0d9e4e5479f947619774677a63572e55e80eff" + [[package]] name = "ouroboros" -version = "0.13.0" +version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f357ef82d1b4db66fbed0b8d542cbd3c22d0bf5b393b3c257b9ba4568e70c9c3" +checksum = "71643f290d126e18ac2598876d01e1d57aed164afc78fdb6e2a0c6589a1f6662" dependencies = [ "aliasable", "ouroboros_macro", @@ -1772,15 +2452,15 @@ dependencies = [ [[package]] name = "ouroboros_macro" -version = "0.13.0" +version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44a0b52c2cbaef7dffa5fec1a43274afe8bd2a644fa9fc50a9ef4ff0269b1257" +checksum = "ed9a247206016d424fe8497bc611e510887af5c261fbbf977877c4bb55ca4d82" dependencies = [ "Inflector", "proc-macro-error", - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.37", + "quote 1.0.18", + "syn 1.0.91", ] [[package]] @@ -1828,7 +2508,7 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "windows-sys", + "windows-sys 0.34.0", ] [[package]] @@ -1839,11 +2519,29 @@ checksum = "0c520e05135d6e763148b6426a837e239041653ba7becd2e538c076c738025fc" [[package]] name = "pbkdf2" -version = "0.9.0" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "216eaa586a190f0a738f2f918511eecfa90f13295abec0e457cdebcceda80cbd" +dependencies = [ + "crypto-mac", +] + +[[package]] +name = "pbkdf2" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271779f35b581956db91a3e55737327a03aa051e90b1c47aeb189508533adfd7" +dependencies = [ + "digest 0.10.3", +] + +[[package]] +name = "pem" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f05894bce6a1ba4be299d0c5f29563e08af2bc18bb7d48313113bed71e904739" +checksum = "03c64931a1a212348ec4f3b4362585eca7159d0d09cbdf4a7f74f02173596fd4" dependencies = [ - "crypto-mac 0.11.1", + "base64 0.13.0", ] [[package]] @@ -1852,6 +2550,15 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" +[[package]] +name = "percentage" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fd23b938276f14057220b707937bcb42fa76dda7560e57a2da30cb52d557937" +dependencies = [ + "num", +] + [[package]] name = "pest" version = "2.1.3" @@ -1876,9 +2583,9 @@ version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.37", + "quote 1.0.18", + "syn 1.0.91", ] [[package]] @@ -1893,6 +2600,17 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkcs8" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cabda3fb821068a9a4fab19a683eac3af12edf0f34b94a8be53c4972b8149d0" +dependencies = [ + "der", + "spki", + "zeroize", +] + [[package]] name = "pkg-config" version = "0.3.25" @@ -1905,6 +2623,18 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" +[[package]] +name = "polyval" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8419d2b623c7c0896ff2d5d96e2cb4ede590fed28fcc34934f4c33c036e620a1" +dependencies = [ + "cfg-if", + "cpufeatures", + "opaque-debug", + "universal-hash", +] + [[package]] name = "ppv-lite86" version = "0.2.16" @@ -1937,9 +2667,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.37", + "quote 1.0.18", + "syn 1.0.91", "version_check", ] @@ -1949,18 +2679,27 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.37", + "quote 1.0.18", "version_check", ] +[[package]] +name = "proc-macro2" +version = "0.4.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" +dependencies = [ + "unicode-xid 0.1.0", +] + [[package]] name = "proc-macro2" version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec757218438d5fda206afc041538b2f6d889286160d649a86a24d37e1235afd1" dependencies = [ - "unicode-xid", + "unicode-xid 0.2.2", ] [[package]] @@ -1969,9 +2708,9 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4bf29726d67464d49fa6224a1d07936a8c08bb3fba727c7493f6cf1616fdaada" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.37", + "quote 1.0.18", + "syn 1.0.91", "version_check", "yansi", ] @@ -1992,6 +2731,35 @@ dependencies = [ "thiserror", ] +[[package]] +name = "pyth-sdk" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "446ff07d7ef3bd98214f9b4fe6a611a69e36b5aad74b18cdbad5150193c1f204" +dependencies = [ + "borsh", + "borsh-derive", + "schemars", + "serde", +] + +[[package]] +name = "pyth-sdk-solana" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27a648739aa69cab94edd900a0d7ca37d8a789e9c88741b23deec11fab418d16" +dependencies = [ + "borsh", + "borsh-derive", + "bytemuck", + "num-derive", + "num-traits", + "pyth-sdk", + "serde", + "solana-program", + "thiserror", +] + [[package]] name = "qstring" version = "0.7.2" @@ -2010,13 +2778,75 @@ dependencies = [ "byteorder", ] +[[package]] +name = "quinn" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b435e71d9bfa0d8889927231970c51fb89c58fa63bffcab117c9c7a41e5ef8f" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "fxhash", + "quinn-proto", + "quinn-udp", + "rustls", + "thiserror", + "tokio", + "tracing", + "webpki", +] + +[[package]] +name = "quinn-proto" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fce546b9688f767a57530652488420d419a8b1f44a478b451c3d1ab6d992a55" +dependencies = [ + "bytes", + "fxhash", + "rand 0.8.5", + "ring", + "rustls", + "rustls-native-certs", + "rustls-pemfile 0.2.1", + "slab", + "thiserror", + "tinyvec", + "tracing", + "webpki", +] + +[[package]] +name = "quinn-udp" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f832d8958db3e84d2ec93b5eb2272b45aa23cf7f8fe6e79f578896f4e6c231b" +dependencies = [ + "futures-util", + "libc", + "quinn-proto", + "socket2", + "tokio", + "tracing", +] + +[[package]] +name = "quote" +version = "0.6.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" +dependencies = [ + "proc-macro2 0.4.30", +] + [[package]] name = "quote" version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" dependencies = [ - "proc-macro2", + "proc-macro2 1.0.37", ] [[package]] @@ -2100,6 +2930,15 @@ dependencies = [ "rand_core 0.5.1", ] +[[package]] +name = "rand_xoshiro" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa" +dependencies = [ + "rand_core 0.6.3", +] + [[package]] name = "rayon" version = "1.5.2" @@ -2124,6 +2963,18 @@ dependencies = [ "num_cpus", ] +[[package]] +name = "rcgen" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6413f3de1edee53342e6138e75b56d32e7bc6e332b3bd62d497b1929d4cfbcdd" +dependencies = [ + "pem", + "ring", + "time 0.3.15", + "yasna", +] + [[package]] name = "redox_syscall" version = "0.2.13" @@ -2133,6 +2984,17 @@ dependencies = [ "bitflags", ] +[[package]] +name = "redox_users" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +dependencies = [ + "getrandom 0.2.6", + "redox_syscall", + "thiserror", +] + [[package]] name = "regex" version = "1.5.5" @@ -2165,6 +3027,7 @@ version = "0.11.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46a1f7aa4f35e5e8b4160449f51afc758f0ce6454315a9fa7d0d113e958c41eb" dependencies = [ + "async-compression", "base64 0.13.0", "bytes", "encoding_rs", @@ -2183,12 +3046,13 @@ dependencies = [ "percent-encoding", "pin-project-lite", "rustls", - "rustls-pemfile", + "rustls-pemfile 0.3.0", "serde", "serde_json", "serde_urlencoded", "tokio", "tokio-rustls", + "tokio-util 0.6.9", "url", "wasm-bindgen", "wasm-bindgen-futures", @@ -2212,6 +3076,32 @@ dependencies = [ "winapi", ] +[[package]] +name = "rpassword" +version = "6.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bf099a1888612545b683d2661a1940089f6c2e5a8e38979b2159da876bfd956" +dependencies = [ + "libc", + "serde", + "serde_json", + "winapi", +] + +[[package]] +name = "rusqlite" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01e213bc3ecb39ac32e81e51ebe31fd888a940515173e3a18a35f8c6e896422a" +dependencies = [ + "bitflags", + "fallible-iterator", + "fallible-streaming-iterator", + "hashlink", + "libsqlite3-sys", + "smallvec", +] + [[package]] name = "rust_decimal" version = "1.23.1" @@ -2229,7 +3119,7 @@ version = "1.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4c70be9367d4bc095d10b48d41b819d09ed4dafc528765a144d32ed1d530654" dependencies = [ - "quote", + "quote 1.0.18", "rust_decimal", ] @@ -2240,7 +3130,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" [[package]] -name = "rustc_version" +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc_version" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" @@ -2257,6 +3153,15 @@ dependencies = [ "semver 1.0.7", ] +[[package]] +name = "rusticata-macros" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faf0c4a6ece9950b9abdb62b1cfcf2a68b3b67a10ba445b3bb85be2a293d0632" +dependencies = [ + "nom", +] + [[package]] name = "rustls" version = "0.20.4" @@ -2269,6 +3174,27 @@ dependencies = [ "webpki", ] +[[package]] +name = "rustls-native-certs" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0167bac7a9f490495f3c33013e7722b53cb087ecbe082fb0c6387c96f634ea50" +dependencies = [ + "openssl-probe", + "rustls-pemfile 1.0.1", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-pemfile" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eebeaeb360c87bfb72e84abdb3447159c0eaececf1bef2aecd65a8be949d1c9" +dependencies = [ + "base64 0.13.0", +] + [[package]] name = "rustls-pemfile" version = "0.3.0" @@ -2278,6 +3204,15 @@ dependencies = [ "base64 0.13.0", ] +[[package]] +name = "rustls-pemfile" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0864aeff53f8c05aa08d86e5ef839d3dfcf07aeba2db32f12db0ef716e87bd55" +dependencies = [ + "base64 0.13.0", +] + [[package]] name = "rustversion" version = "1.0.6" @@ -2305,6 +3240,40 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "schannel" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88d6731146462ea25d9244b2ed5fd1d716d25c52e4d54aa4fb0f3c4e9854dbe2" +dependencies = [ + "lazy_static", + "windows-sys 0.36.1", +] + +[[package]] +name = "schemars" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a5fb6c61f29e723026dc8e923d94c694313212abbecbbe5f55a7748eec5b307" +dependencies = [ + "dyn-clone", + "schemars_derive", + "serde", + "serde_json", +] + +[[package]] +name = "schemars_derive" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f188d036977451159430f3b8dc82ec76364a42b7e289c2b18a9a18f4470058e9" +dependencies = [ + "proc-macro2 1.0.37", + "quote 1.0.18", + "serde_derive_internals", + "syn 1.0.91", +] + [[package]] name = "scopeguard" version = "1.1.0" @@ -2326,9 +3295,9 @@ version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aaaae8f38bb311444cfb7f1979af0bc9240d95795f75f9ceddf6a59b79ceffa0" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.37", + "quote 1.0.18", + "syn 1.0.91", ] [[package]] @@ -2341,6 +3310,29 @@ dependencies = [ "untrusted", ] +[[package]] +name = "security-framework" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bc1bb97804af6631813c55739f771071e0f2ed33ee20b68c86ec505d906356c" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0160a13a177a45bfb43ce71c01580998474f556ad854dcbca936dd2841a5c556" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "semver" version = "0.11.0" @@ -2389,9 +3381,20 @@ version = "1.0.136" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.37", + "quote 1.0.18", + "syn 1.0.91", +] + +[[package]] +name = "serde_derive_internals" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c" +dependencies = [ + "proc-macro2 1.0.37", + "quote 1.0.18", + "syn 1.0.91", ] [[package]] @@ -2417,6 +3420,18 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_yaml" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578a7433b776b56a35785ed5ce9a7e777ac0598aac5a6dd1b4b18a307c7fc71b" +dependencies = [ + "indexmap", + "ryu", + "serde", + "yaml-rust", +] + [[package]] name = "serum_dex" version = "0.5.5" @@ -2440,6 +3455,17 @@ dependencies = [ "without-alloc", ] +[[package]] +name = "sha-1" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.3", +] + [[package]] name = "sha2" version = "0.9.9" @@ -2453,6 +3479,17 @@ dependencies = [ "opaque-debug", ] +[[package]] +name = "sha2" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf9db03534dff993187064c4e0c05a5708d2a9728ace9a8959b77bedf415dac5" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.3", +] + [[package]] name = "sha3" version = "0.9.1" @@ -2465,6 +3502,16 @@ dependencies = [ "opaque-debug", ] +[[package]] +name = "sha3" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaedf34ed289ea47c2b741bb72e5357a209512d67bcd4bda44359e5bf0470f56" +dependencies = [ + "digest 0.10.3", + "keccak", +] + [[package]] name = "sharded-slab" version = "0.1.4" @@ -2489,6 +3536,16 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f054c6c1a6e95179d6f23ed974060dcefb2d9388bb7256900badad682c499de4" +[[package]] +name = "sized-chunks" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16d69225bde7a69b235da73377861095455d298f2b970996eec25ddbb42b3d1e" +dependencies = [ + "bitmaps", + "typenum", +] + [[package]] name = "slab" version = "0.4.6" @@ -2511,11 +3568,35 @@ dependencies = [ "winapi", ] +[[package]] +name = "solana-account-decoder" +version = "1.10.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f66dee087a53e7ce07cbf02be14d5b7261d83ebe6f445ca777c18fa7821f027" +dependencies = [ + "Inflector", + "base64 0.13.0", + "bincode", + "bs58 0.4.0", + "bv", + "lazy_static", + "serde", + "serde_derive", + "serde_json", + "solana-config-program", + "solana-sdk", + "solana-vote-program", + "spl-token", + "spl-token-2022", + "thiserror", + "zstd", +] + [[package]] name = "solana-address-lookup-table-program" -version = "1.9.17" +version = "1.10.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1c55b7304ab892d207c68f6049b292d23c2b4533e09c65e0f909bf9b8475faa" +checksum = "1018ed920d3fdae80397da2640513946119be7fb327c8a2d8e8018b109df6768" dependencies = [ "bincode", "bytemuck", @@ -2526,6 +3607,7 @@ dependencies = [ "serde", "solana-frozen-abi", "solana-frozen-abi-macro", + "solana-program", "solana-program-runtime", "solana-sdk", "thiserror", @@ -2533,9 +3615,9 @@ dependencies = [ [[package]] name = "solana-banks-client" -version = "1.9.17" +version = "1.10.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f16e829fa2a389d63f3d19b73aa41919c9be20d3997ac32eeed978d5de3c0d2b" +checksum = "7a7762a0254ac809b97075fd6f9ec92edaa5de9a47a3494969d561d1fa6b979f" dependencies = [ "borsh", "futures", @@ -2550,9 +3632,9 @@ dependencies = [ [[package]] name = "solana-banks-interface" -version = "1.9.17" +version = "1.10.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96b7ea0bf3313b8773a23e81a235c399065ac80c1ca409a548cd6846f1de00ab" +checksum = "5178e2a0ede374043ddf5a825f1bb610188b0ad2c74d73676cd0f8ab59c5fd83" dependencies = [ "serde", "solana-sdk", @@ -2561,13 +3643,15 @@ dependencies = [ [[package]] name = "solana-banks-server" -version = "1.9.17" +version = "1.10.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22098f89ab47ec97c67a69609724009db8321c17ace35178b2356e92db9738b8" +checksum = "7f1c01d9ebe8a1c5cd45efda5cb60b31ab1c15589f835f280428d4241c76ef57" dependencies = [ "bincode", + "crossbeam-channel", "futures", "solana-banks-interface", + "solana-client", "solana-runtime", "solana-sdk", "solana-send-transaction-service", @@ -2577,30 +3661,11 @@ dependencies = [ "tokio-stream", ] -[[package]] -name = "solana-bloom" -version = "1.9.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07f309d576f01df9f91125dcf961655e61545ab3707cbddd38aea8cdc9573058" -dependencies = [ - "bv", - "fnv", - "log", - "rand 0.7.3", - "rayon", - "rustc_version 0.4.0", - "serde", - "serde_derive", - "solana-frozen-abi", - "solana-frozen-abi-macro", - "solana-sdk", -] - [[package]] name = "solana-bpf-loader-program" -version = "1.9.17" +version = "1.10.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9317274a9b3275aa5c900f06fcf5cdebd707e27530e1253dca1e5ebe32a28f6" +checksum = "cfe9ea7c9b3f2710b0d9696d54797784db79d9a84e7e88bea514178537c9b20c" dependencies = [ "bincode", "byteorder", @@ -2610,32 +3675,120 @@ dependencies = [ "solana-metrics", "solana-program-runtime", "solana-sdk", + "solana-zk-token-sdk 1.10.33", "solana_rbpf", "thiserror", ] [[package]] name = "solana-bucket-map" -version = "1.9.17" +version = "1.10.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06adcde94393e385cb80ef046b1bc58c1f4edcd6ddf2466cf6a6ab09523aa451" +checksum = "fb0d1e5523bcbd2869c5431bc1258cf995e2a4803bce9c7ddac6eb942e574bdd" dependencies = [ - "fs_extra", "log", "memmap2", + "modular-bitfield", "rand 0.7.3", - "rayon", - "solana-logger", "solana-measure", "solana-sdk", "tempfile", ] +[[package]] +name = "solana-clap-utils" +version = "1.10.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "974c122764ca2ef5335f133868c991a24bcd648bb4a66c81a289f9e5893c994f" +dependencies = [ + "chrono", + "clap 2.34.0", + "rpassword", + "solana-perf", + "solana-remote-wallet", + "solana-sdk", + "thiserror", + "tiny-bip39", + "uriparse", + "url", +] + +[[package]] +name = "solana-cli-config" +version = "1.10.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb6b92a2f9e42cf221880ec2198b5f1e872fdd0b23966ba488ffeada8b36c450" +dependencies = [ + "dirs-next", + "lazy_static", + "serde", + "serde_derive", + "serde_yaml", + "solana-clap-utils", + "solana-sdk", + "url", +] + +[[package]] +name = "solana-client" +version = "1.10.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e92734a47b2ab8846b0ea732f6a4541e6e46e0a9f6074cd715ecf12b5214bbd8" +dependencies = [ + "async-mutex", + "async-trait", + "base64 0.13.0", + "bincode", + "bs58 0.4.0", + "bytes", + "clap 2.34.0", + "crossbeam-channel", + "enum_dispatch", + "futures", + "futures-util", + "indexmap", + "indicatif", + "itertools 0.10.3", + "jsonrpc-core", + "lazy_static", + "log", + "lru", + "quinn", + "quinn-proto", + "rand 0.7.3", + "rand_chacha 0.2.2", + "rayon", + "reqwest", + "rustls", + "semver 1.0.7", + "serde", + "serde_derive", + "serde_json", + "solana-account-decoder", + "solana-clap-utils", + "solana-faucet", + "solana-measure", + "solana-metrics", + "solana-net-utils", + "solana-sdk", + "solana-streamer", + "solana-transaction-status", + "solana-version", + "solana-vote-program", + "spl-token-2022", + "thiserror", + "tokio", + "tokio-stream", + "tokio-tungstenite", + "tungstenite", + "url", +] + [[package]] name = "solana-compute-budget-program" -version = "1.9.17" +version = "1.10.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0c927ec4babd1e0f7521e4c28cee3256cd70337bfa74612df398ebfd4ec7604" +checksum = "9c5a23f363826f03ca34552b558ca478d99e0a03ab8de573ac7609dc7c6308c3" dependencies = [ "solana-program-runtime", "solana-sdk", @@ -2643,9 +3796,9 @@ dependencies = [ [[package]] name = "solana-config-program" -version = "1.9.17" +version = "1.10.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ae8513de0d713037466a27887c8e5b608ef3b15c2138be8628334fc6010be4d" +checksum = "6fae70ea08b7843ed7883a07b2769ffd15204be62cc7ef6150c9d54418522c1d" dependencies = [ "bincode", "chrono", @@ -2655,54 +3808,80 @@ dependencies = [ "solana-sdk", ] +[[package]] +name = "solana-faucet" +version = "1.10.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb7e99a5978347e936f17fd59dc10375db07036671f45a10e67e01fc504e6703" +dependencies = [ + "bincode", + "byteorder", + "clap 2.34.0", + "crossbeam-channel", + "log", + "serde", + "serde_derive", + "solana-clap-utils", + "solana-cli-config", + "solana-logger", + "solana-metrics", + "solana-sdk", + "solana-version", + "spl-memo", + "thiserror", + "tokio", +] + [[package]] name = "solana-frozen-abi" -version = "1.9.17" +version = "1.10.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a42d57a501d4e6b7f9867ba1d43e30fd2c01293018aee1bbdbe361fcb38ca8f" +checksum = "49a5d3280421bb53fc12bdba1eaa505153fb4f99a06b5609dae22192652ead3b" dependencies = [ "bs58 0.4.0", "bv", "generic-array", + "im", + "lazy_static", "log", "memmap2", "rustc_version 0.4.0", "serde", + "serde_bytes", "serde_derive", - "sha2", + "sha2 0.10.5", "solana-frozen-abi-macro", - "solana-logger", "thiserror", ] [[package]] name = "solana-frozen-abi-macro" -version = "1.9.17" +version = "1.10.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8e74b463a20856db7c34e623fb9e617f4487b6a9646db70e99fff2244a8d0dd" +checksum = "635c60ac96b1347af272c625465068b908aff919d19f29b5795a44310310494d" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.37", + "quote 1.0.18", "rustc_version 0.4.0", - "syn", + "syn 1.0.91", ] [[package]] name = "solana-logger" -version = "1.9.17" +version = "1.10.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0bbd0c9b975384bb5e775532cadf101e053858c52f58b970b2e2ad4f0ec3ad5" +checksum = "b12cb6e6f1f9c9876d356c928b8c2ac532f6715e7cd2a1b4343d747bee3eca73" dependencies = [ - "env_logger", + "env_logger 0.9.0", "lazy_static", "log", ] [[package]] name = "solana-measure" -version = "1.9.17" +version = "1.10.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4f8d52d73bbfa5cf9bb800c08cc8e4261f8cf4642940dc153db7826fdb1282c" +checksum = "03deb847b269c14a69956c9917697b221b4c7431ea35c221244c3a4d4a59ed7c" dependencies = [ "log", "solana-sdk", @@ -2710,11 +3889,11 @@ dependencies = [ [[package]] name = "solana-metrics" -version = "1.9.17" +version = "1.10.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f1c7084a52d604634c850762b01b85e46108751c310227f840a2e1c6e3826a6" +checksum = "9105cdcc6e42b8788250f6d3721c5d552b48e2cf8374b76c617639ba672c9302" dependencies = [ - "env_logger", + "crossbeam-channel", "gethostname", "lazy_static", "log", @@ -2722,11 +3901,60 @@ dependencies = [ "solana-sdk", ] +[[package]] +name = "solana-net-utils" +version = "1.10.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2434e5973ab61b1465d4642ddcce1616773fe53473bc2736771b76251ead99b8" +dependencies = [ + "bincode", + "clap 2.34.0", + "crossbeam-channel", + "log", + "nix", + "rand 0.7.3", + "serde", + "serde_derive", + "socket2", + "solana-logger", + "solana-sdk", + "solana-version", + "tokio", + "url", +] + +[[package]] +name = "solana-perf" +version = "1.10.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a38caa622fe38f83fc7b68ffc7c0b30a7fccd0d9173944ccea710119e9cdd7d4" +dependencies = [ + "ahash", + "bincode", + "bv", + "caps", + "curve25519-dalek", + "dlopen", + "dlopen_derive", + "fnv", + "lazy_static", + "libc", + "log", + "nix", + "rand 0.7.3", + "rayon", + "serde", + "solana-metrics", + "solana-rayon-threadlimit", + "solana-sdk", + "solana-vote-program", +] + [[package]] name = "solana-program" -version = "1.9.17" +version = "1.10.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b955659c41053e2e7d58d4716c15519dd67a418ac5a57c09499691322170911" +checksum = "eeecf504cee2821b006871f70e7a1f54db15f914cedf259eaf5976fe606470f0" dependencies = [ "base64 0.13.0", "bincode", @@ -2748,18 +3976,17 @@ dependencies = [ "log", "num-derive", "num-traits", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "rand 0.7.3", "rustc_version 0.4.0", "rustversion", "serde", "serde_bytes", "serde_derive", - "sha2", - "sha3", + "sha2 0.10.5", + "sha3 0.10.4", "solana-frozen-abi", "solana-frozen-abi-macro", - "solana-logger", "solana-sdk-macro", "thiserror", "wasm-bindgen", @@ -2767,12 +3994,13 @@ dependencies = [ [[package]] name = "solana-program-runtime" -version = "1.9.17" +version = "1.10.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be23f8b37543a44b8fc5172b3f76d928c966e49105a95312ffc7f4c35741963" +checksum = "f70c2156446824a18421c6be3976fd739cfa293e94ff44cd0954dfde5941233c" dependencies = [ "base64 0.13.0", "bincode", + "enum-iterator", "itertools 0.10.3", "libc", "libloading", @@ -2783,7 +4011,6 @@ dependencies = [ "serde", "solana-frozen-abi", "solana-frozen-abi-macro", - "solana-logger", "solana-measure", "solana-sdk", "thiserror", @@ -2791,12 +4018,12 @@ dependencies = [ [[package]] name = "solana-program-test" -version = "1.9.17" +version = "1.10.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd0625240876358ec4a29a2b8450917e32e44ef375b2eaa383302d40c2289ea1" +checksum = "f25303f31e6160c2b0fa15b840ce9ca652cb6d04e123230f705f498b73e33183" dependencies = [ "async-trait", - "base64 0.12.3", + "base64 0.13.0", "bincode", "chrono-humanize", "log", @@ -2815,19 +4042,38 @@ dependencies = [ [[package]] name = "solana-rayon-threadlimit" -version = "1.9.17" +version = "1.10.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6b577874682b894ba5c2dfd5fd7e3bbcb4ff09a74bd347346bf79a7d801078a" +checksum = "34f6dabbe88f6dffff8f88178635e0a81d603f056a32e3ad4787b442687500f2" dependencies = [ "lazy_static", "num_cpus", ] +[[package]] +name = "solana-remote-wallet" +version = "1.10.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0083b9dac3ff1a668057a75c3f49fae8eb8d5dfc9caece270679b396bb4d2846" +dependencies = [ + "console", + "dialoguer", + "log", + "num-derive", + "num-traits", + "parking_lot 0.12.0", + "qstring", + "semver 1.0.7", + "solana-sdk", + "thiserror", + "uriparse", +] + [[package]] name = "solana-runtime" -version = "1.9.17" +version = "1.10.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6154bbb33773d9a087450a5caa0ab613aa6dc7777074532e388d28ff75a655b" +checksum = "17af3f430e3c7d1f41af76d012582a2ad3188251abfe61c3fb4be6b8803a945b" dependencies = [ "arrayref", "bincode", @@ -2841,10 +4087,12 @@ dependencies = [ "dir-diff", "flate2", "fnv", + "im", "index_list", "itertools 0.10.3", "lazy_static", "log", + "lz4", "memmap2", "num-derive", "num-traits", @@ -2857,13 +4105,11 @@ dependencies = [ "serde", "serde_derive", "solana-address-lookup-table-program", - "solana-bloom", "solana-bucket-map", "solana-compute-budget-program", "solana-config-program", "solana-frozen-abi", "solana-frozen-abi-macro", - "solana-logger", "solana-measure", "solana-metrics", "solana-program-runtime", @@ -2871,6 +4117,10 @@ dependencies = [ "solana-sdk", "solana-stake-program", "solana-vote-program", + "solana-zk-token-proof-program", + "solana-zk-token-sdk 1.10.33", + "strum", + "strum_macros", "symlink", "tar", "tempfile", @@ -2880,9 +4130,9 @@ dependencies = [ [[package]] name = "solana-sdk" -version = "1.9.17" +version = "1.10.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34ea9fcedb32801da35d83ece7bdd0a42018e0263ef40adb2215c5f5b6e04119" +checksum = "636f6c615aca6f75e22b6baceaf0ffed9d74367f9320b07ed57cd9b5ce2e4ff9" dependencies = [ "assert_matches", "base64 0.13.0", @@ -2894,11 +4144,11 @@ dependencies = [ "byteorder", "chrono", "derivation-path", - "digest 0.9.0", + "digest 0.10.3", "ed25519-dalek", "ed25519-dalek-bip32", "generic-array", - "hmac 0.11.0", + "hmac 0.12.1", "itertools 0.10.3", "js-sys", "lazy_static", @@ -2907,7 +4157,7 @@ dependencies = [ "memmap2", "num-derive", "num-traits", - "pbkdf2", + "pbkdf2 0.10.1", "qstring", "rand 0.7.3", "rand_chacha 0.2.2", @@ -2917,8 +4167,8 @@ dependencies = [ "serde_bytes", "serde_derive", "serde_json", - "sha2", - "sha3", + "sha2 0.10.5", + "sha3 0.10.4", "solana-frozen-abi", "solana-frozen-abi-macro", "solana-logger", @@ -2931,73 +4181,223 @@ dependencies = [ [[package]] name = "solana-sdk-macro" -version = "1.9.17" +version = "1.10.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28b9e0d05a4a15d4d5f1c146437fc97319beceff21064f36d8f5280d03a82cd9" +checksum = "2b8bcac4394644f21dc013e932a7df9f536fcecef3e5df43fe362b4ec532ce30" dependencies = [ "bs58 0.4.0", - "proc-macro2", - "quote", + "proc-macro2 1.0.37", + "quote 1.0.18", "rustversion", - "syn", + "syn 1.0.91", ] [[package]] name = "solana-send-transaction-service" -version = "1.9.17" +version = "1.10.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31af72e5089666cb96553452d24ac2c8345ad9b3b6b0d5603e097a8c3ea27b18" +checksum = "0ffcfd3f7d9d77831cc14ec80b3f5e95efa56dd4bcac3156f01c5446030b95e2" dependencies = [ + "crossbeam-channel", "log", - "solana-logger", + "solana-client", + "solana-measure", "solana-metrics", "solana-runtime", "solana-sdk", ] [[package]] -name = "solana-stake-program" -version = "1.9.17" +name = "solana-stake-program" +version = "1.10.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ad00016a85a712b016e8965bfc47857b49fccf96aa436b1f74f8760cc4516be" +dependencies = [ + "bincode", + "log", + "num-derive", + "num-traits", + "rustc_version 0.4.0", + "serde", + "serde_derive", + "solana-config-program", + "solana-frozen-abi", + "solana-frozen-abi-macro", + "solana-metrics", + "solana-program-runtime", + "solana-sdk", + "solana-vote-program", + "thiserror", +] + +[[package]] +name = "solana-streamer" +version = "1.10.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6fe2555776c5cb437a6682fde283bf115e1230c7108ee8767cd74b395e644f9" +dependencies = [ + "crossbeam-channel", + "futures-util", + "histogram", + "indexmap", + "itertools 0.10.3", + "libc", + "log", + "nix", + "pem", + "percentage", + "pkcs8", + "quinn", + "rand 0.7.3", + "rcgen", + "rustls", + "solana-metrics", + "solana-perf", + "solana-sdk", + "thiserror", + "tokio", + "x509-parser", +] + +[[package]] +name = "solana-transaction-status" +version = "1.10.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3be33f630671045322f3f3b83e83b9f7dcc38629c75d5415456cc7a8cab5a6b" +dependencies = [ + "Inflector", + "base64 0.13.0", + "bincode", + "borsh", + "bs58 0.4.0", + "lazy_static", + "log", + "serde", + "serde_derive", + "serde_json", + "solana-account-decoder", + "solana-measure", + "solana-metrics", + "solana-runtime", + "solana-sdk", + "solana-vote-program", + "spl-associated-token-account", + "spl-memo", + "spl-token", + "spl-token-2022", + "thiserror", +] + +[[package]] +name = "solana-version" +version = "1.10.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c7016d49908046f61806bc327fba3f7cf8715d4aea7a3fff8edfd5f713743c4" +dependencies = [ + "log", + "rustc_version 0.4.0", + "semver 1.0.7", + "serde", + "serde_derive", + "solana-frozen-abi", + "solana-frozen-abi-macro", + "solana-sdk", +] + +[[package]] +name = "solana-vote-program" +version = "1.10.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a5e990bfaf78ca45d692993538d25c64d983397b6e68a5f25b7673ec082f446" +dependencies = [ + "bincode", + "log", + "num-derive", + "num-traits", + "rustc_version 0.4.0", + "serde", + "serde_derive", + "solana-frozen-abi", + "solana-frozen-abi-macro", + "solana-metrics", + "solana-program-runtime", + "solana-sdk", + "thiserror", +] + +[[package]] +name = "solana-zk-token-proof-program" +version = "1.10.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f363100394910c0c1d9c5451870d892d0613548b04a5450f32ad80e2731cf093" +dependencies = [ + "bytemuck", + "getrandom 0.1.16", + "num-derive", + "num-traits", + "solana-program-runtime", + "solana-sdk", + "solana-zk-token-sdk 1.10.33", +] + +[[package]] +name = "solana-zk-token-sdk" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9566af3477bafa9d7ec2b927579d896026724f646ebd393aa7ecd0646c473166" +checksum = "74b149253f9ed1afb68b3161b53b62b637d0dd7a3b328dffdc8bb5878d48358e" dependencies = [ + "aes-gcm-siv", + "arrayref", + "base64 0.13.0", "bincode", - "log", + "bytemuck", + "byteorder", + "cipher 0.3.0", + "curve25519-dalek", + "getrandom 0.1.16", + "lazy_static", + "merlin", "num-derive", "num-traits", - "rustc_version 0.4.0", + "rand 0.7.3", "serde", - "serde_derive", - "solana-config-program", - "solana-frozen-abi", - "solana-frozen-abi-macro", - "solana-metrics", - "solana-program-runtime", + "serde_json", + "sha3 0.9.1", + "solana-program", "solana-sdk", - "solana-vote-program", + "subtle", "thiserror", + "zeroize", ] [[package]] -name = "solana-vote-program" -version = "1.9.17" +name = "solana-zk-token-sdk" +version = "1.10.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "514eefafc9d1d6fb9bf88ef36fcf649eb2debafbbb57dc64fea03b44cbfed7d1" +checksum = "410ee53a26ac91098c289c983863535d4fbb6604b229ae1159503f48fa4fc90f" dependencies = [ + "aes-gcm-siv", + "arrayref", + "base64 0.13.0", "bincode", - "log", + "bytemuck", + "byteorder", + "cipher 0.4.3", + "curve25519-dalek", + "getrandom 0.1.16", + "lazy_static", + "merlin", "num-derive", "num-traits", - "rustc_version 0.4.0", + "rand 0.7.3", "serde", - "serde_derive", - "solana-frozen-abi", - "solana-frozen-abi-macro", - "solana-logger", - "solana-metrics", - "solana-program-runtime", + "serde_json", + "sha3 0.9.1", + "solana-program", "solana-sdk", + "subtle", "thiserror", + "zeroize", ] [[package]] @@ -3016,7 +4416,7 @@ dependencies = [ "rustc-demangle", "scroll", "thiserror", - "time", + "time 0.1.43", ] [[package]] @@ -3025,6 +4425,36 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +[[package]] +name = "spki" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d01ac02a6ccf3e07db148d2be087da624fea0221a16152ed01f0496a6b0a27" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "spl-associated-token-account" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b013067447a1396303ddfc294f36e3d260a32f8a16c501c295bcdc7de39b490" +dependencies = [ + "borsh", + "solana-program", + "spl-token", +] + +[[package]] +name = "spl-memo" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd0dc6f70db6bacea7ff25870b016a65ba1d1b6013536f08e4fd79a8f9005325" +dependencies = [ + "solana-program", +] + [[package]] name = "spl-token" version = "3.3.0" @@ -3039,6 +4469,24 @@ dependencies = [ "thiserror", ] +[[package]] +name = "spl-token-2022" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fce48c69350134e8678de5c0956a531b7de586b28eebdddc03211ceec0660983" +dependencies = [ + "arrayref", + "bytemuck", + "num-derive", + "num-traits", + "num_enum", + "solana-program", + "solana-zk-token-sdk 0.8.1", + "spl-memo", + "spl-token", + "thiserror", +] + [[package]] name = "stable_deref_trait" version = "1.2.0" @@ -3051,6 +4499,40 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "strsim" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "strum" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.24.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" +dependencies = [ + "heck 0.4.0", + "proc-macro2 1.0.37", + "quote 1.0.18", + "rustversion", + "syn 1.0.91", +] + [[package]] name = "subtle" version = "2.4.1" @@ -3108,15 +4590,26 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7973cce6668464ea31f176d85b13c7ab3bba2cb3b77a2ed26abd7801688010a" +[[package]] +name = "syn" +version = "0.15.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" +dependencies = [ + "proc-macro2 0.4.30", + "quote 0.6.13", + "unicode-xid 0.1.0", +] + [[package]] name = "syn" version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b683b2b825c8eef438b77c36a06dc262294da3d5a5813fac20da149241dcd44d" dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", + "proc-macro2 1.0.37", + "quote 1.0.18", + "unicode-xid 0.2.2", ] [[package]] @@ -3125,10 +4618,10 @@ version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" dependencies = [ - "proc-macro2", - "quote", - "syn", - "unicode-xid", + "proc-macro2 1.0.37", + "quote 1.0.18", + "syn 1.0.91", + "unicode-xid 0.2.2", ] [[package]] @@ -3196,9 +4689,9 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea80818e6c75f81d961d7426c1b938cbea6b3a51533b5ee71b61f82166b7ef3d" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.37", + "quote 1.0.18", + "syn 1.0.91", ] [[package]] @@ -3207,9 +4700,9 @@ version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ee42b4e559f17bce0385ebf511a7beb67d5cc33c12c96b7f4e9789919d9c10f" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.37", + "quote 1.0.18", + "syn 1.0.91", ] [[package]] @@ -3235,6 +4728,31 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "terminal_size" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "textwrap" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "949517c0cf1bf4ee812e2e07e08ab448e3ae0d23472aee8a06c985f0c8815b16" + [[package]] name = "thiserror" version = "1.0.30" @@ -3250,9 +4768,9 @@ version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.37", + "quote 1.0.18", + "syn 1.0.91", ] [[package]] @@ -3274,6 +4792,43 @@ dependencies = [ "winapi", ] +[[package]] +name = "time" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d634a985c4d4238ec39cacaed2e7ae552fbd3c476b552c1deac3021b7d7eaf0c" +dependencies = [ + "itoa", + "libc", + "num_threads", + "time-macros", +] + +[[package]] +name = "time-macros" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42657b1a6f4d817cda8e7a0ace261fe0cc946cf3a80314390b22cc61ae080792" + +[[package]] +name = "tiny-bip39" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffc59cb9dfc85bb312c3a78fd6aa8a8582e310b0fa885d5bb877f6dcc601839d" +dependencies = [ + "anyhow", + "hmac 0.8.1", + "once_cell", + "pbkdf2 0.4.0", + "rand 0.7.3", + "rustc-hash", + "sha2 0.9.9", + "thiserror", + "unicode-normalization", + "wasm-bindgen", + "zeroize", +] + [[package]] name = "tinyvec" version = "1.5.1" @@ -3291,20 +4846,20 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.17.0" +version = "1.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2af73ac49756f3f7c01172e34a23e5d0216f6c32333757c2c61feb2bbff5a5ee" +checksum = "b9d0183f6f6001549ab68f8c7585093bb732beefbcf6d23a10b9b95c73a1dd49" dependencies = [ + "autocfg", "bytes", "libc", "memchr", "mio", "num_cpus", "once_cell", - "parking_lot 0.12.0", + "parking_lot 0.11.2", "pin-project-lite", "signal-hook-registry", - "socket2", "tokio-macros", "winapi", ] @@ -3315,9 +4870,9 @@ version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.37", + "quote 1.0.18", + "syn 1.0.91", ] [[package]] @@ -3358,6 +4913,22 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-tungstenite" +version = "0.17.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f714dd15bead90401d77e04243611caec13726c2408afd5b31901dfcdcb3b181" +dependencies = [ + "futures-util", + "log", + "rustls", + "tokio", + "tokio-rustls", + "tungstenite", + "webpki", + "webpki-roots", +] + [[package]] name = "tokio-util" version = "0.6.9" @@ -3421,9 +4992,9 @@ version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e65ce065b4b5c53e73bb28912318cb8c9e9ad3921f1d669eb0e68b4c8143a2b" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.37", + "quote 1.0.18", + "syn 1.0.91", ] [[package]] @@ -3477,6 +5048,28 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" +[[package]] +name = "tungstenite" +version = "0.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e27992fd6a8c29ee7eef28fc78349aa244134e10ad447ce3b9f0ac0ed0fa4ce0" +dependencies = [ + "base64 0.13.0", + "byteorder", + "bytes", + "http", + "httparse", + "log", + "rand 0.8.5", + "rustls", + "sha-1", + "thiserror", + "url", + "utf-8", + "webpki", + "webpki-roots", +] + [[package]] name = "typenum" version = "1.15.0" @@ -3510,12 +5103,34 @@ version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99" +[[package]] +name = "unicode-width" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" + +[[package]] +name = "unicode-xid" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" + [[package]] name = "unicode-xid" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" +[[package]] +name = "universal-hash" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05" +dependencies = [ + "generic-array", + "subtle", +] + [[package]] name = "unreachable" version = "1.0.0" @@ -3553,12 +5168,30 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + [[package]] name = "valuable" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "vec_map" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" + [[package]] name = "version_check" version = "0.9.4" @@ -3604,12 +5237,6 @@ version = "0.10.2+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - [[package]] name = "wasm-bindgen" version = "0.2.80" @@ -3629,9 +5256,9 @@ dependencies = [ "bumpalo", "lazy_static", "log", - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.37", + "quote 1.0.18", + "syn 1.0.91", "wasm-bindgen-shared", ] @@ -3653,7 +5280,7 @@ version = "0.2.80" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17cae7ff784d7e83a2fe7611cfe766ecf034111b49deb850a3dc7699c08251f5" dependencies = [ - "quote", + "quote 1.0.18", "wasm-bindgen-macro-support", ] @@ -3663,9 +5290,9 @@ version = "0.2.80" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99ec0dc7a4756fffc231aab1b9f2f578d23cd391390ab27f952ae0c9b3ece20b" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.37", + "quote 1.0.18", + "syn 1.0.91", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3742,11 +5369,24 @@ version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5acdd78cb4ba54c0045ac14f62d8f94a03d10047904ae2a40afa1e99d8f70825" dependencies = [ - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_msvc", + "windows_aarch64_msvc 0.34.0", + "windows_i686_gnu 0.34.0", + "windows_i686_msvc 0.34.0", + "windows_x86_64_gnu 0.34.0", + "windows_x86_64_msvc 0.34.0", +] + +[[package]] +name = "windows-sys" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" +dependencies = [ + "windows_aarch64_msvc 0.36.1", + "windows_i686_gnu 0.36.1", + "windows_i686_msvc 0.36.1", + "windows_x86_64_gnu 0.36.1", + "windows_x86_64_msvc 0.36.1", ] [[package]] @@ -3755,30 +5395,60 @@ version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17cffbe740121affb56fad0fc0e421804adf0ae00891205213b5cecd30db881d" +[[package]] +name = "windows_aarch64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" + [[package]] name = "windows_i686_gnu" version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2564fde759adb79129d9b4f54be42b32c89970c18ebf93124ca8870a498688ed" +[[package]] +name = "windows_i686_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" + [[package]] name = "windows_i686_msvc" version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9cd9d32ba70453522332c14d38814bceeb747d80b3958676007acadd7e166956" +[[package]] +name = "windows_i686_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" + [[package]] name = "windows_x86_64_gnu" version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfce6deae227ee8d356d19effc141a509cc503dfd1f850622ec4b0f84428e1f4" +[[package]] +name = "windows_x86_64_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" + [[package]] name = "windows_x86_64_msvc" version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d19538ccc21819d01deaf88d6a17eae6596a12e9aafdbb97916fb49896d89de9" +[[package]] +name = "windows_x86_64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" + [[package]] name = "winreg" version = "0.10.1" @@ -3797,6 +5467,24 @@ dependencies = [ "alloc-traits", ] +[[package]] +name = "x509-parser" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0ecbeb7b67ce215e40e3cc7f2ff902f94a223acf44995934763467e7b1febc8" +dependencies = [ + "asn1-rs", + "base64 0.13.0", + "data-encoding", + "der-parser", + "lazy_static", + "nom", + "oid-registry", + "rusticata-macros", + "thiserror", + "time 0.3.15", +] + [[package]] name = "xattr" version = "0.2.2" @@ -3806,12 +5494,30 @@ dependencies = [ "libc", ] +[[package]] +name = "yaml-rust" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" +dependencies = [ + "linked-hash-map", +] + [[package]] name = "yansi" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" +[[package]] +name = "yasna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "346d34a236c9d3e5f3b9b74563f238f955bbd05fa0b8b4efa53c130c43982f4c" +dependencies = [ + "time 0.3.15", +] + [[package]] name = "zeroize" version = "1.3.0" @@ -3827,26 +5533,26 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f8f187641dad4f680d25c4bfc4225b418165984179f26ca76ec4fb6441d3a17" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.37", + "quote 1.0.18", + "syn 1.0.91", "synstructure", ] [[package]] name = "zstd" -version = "0.9.2+zstd.1.5.1" +version = "0.11.2+zstd.1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2390ea1bf6c038c39674f22d95f0564725fc06034a47129179810b2fc58caa54" +checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4" dependencies = [ "zstd-safe", ] [[package]] name = "zstd-safe" -version = "4.1.3+zstd.1.5.1" +version = "5.0.2+zstd.1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e99d81b99fb3c2c2c794e3fe56c305c63d5173a16a46b5850b07c935ffc7db79" +checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db" dependencies = [ "libc", "zstd-sys", @@ -3854,9 +5560,9 @@ dependencies = [ [[package]] name = "zstd-sys" -version = "1.6.2+zstd.1.5.1" +version = "2.0.1+zstd.1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2daf2f248d9ea44454bfcb2516534e8b8ad2fc91bf818a1885495fc42bc8ac9f" +checksum = "9fd07cbbc53846d9145dbffdf6dd09a7a0aa52be46741825f5c97bdd4f73f12b" dependencies = [ "cc", "libc", diff --git a/Cargo.toml b/Cargo.toml index 5f4374f4..48217e08 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,8 @@ members = [ "common", "mango-macro", "program", - "mango-logs" + "mango-logs", + "cli" ] [profile.release] diff --git a/cli/Cargo.toml b/cli/Cargo.toml new file mode 100644 index 00000000..2fb0f87a --- /dev/null +++ b/cli/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "cli" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +anyhow = "1.0" +clap = { version = "3.1.8", features = ["derive", "env"] } +dotenv = "0.15.0" +env_logger = "0.8.4" +fixed = { version = "=1.11.0", features = ["serde", "borsh"] } +fixed-macro = "^1.1.1" +futures = "0.3.21" +log = "0.4.0" +mango = { path = "../program", features = ["no-entrypoint", "client"] } +mango-common = { path = "../common" } +pyth-sdk-solana = "0.1.0" +serum_dex = { rev = "7f55a5ef5f7937b74381a3124021a261cd7d7283", git = "https://github.com/blockworks-foundation/serum-dex.git", default-features=false, features = ["no-entrypoint", "program"] } +solana-client = "~1.10.29" +solana-sdk = "~1.10.29" +tokio = { version = "1.14.1", features = ["rt-multi-thread", "time", "macros", "sync"] } +rusqlite = "0.28.0" +bytemuck = "^1.7.2" diff --git a/cli/src/main.rs b/cli/src/main.rs new file mode 100644 index 00000000..519f0c11 --- /dev/null +++ b/cli/src/main.rs @@ -0,0 +1,254 @@ +use anyhow::Context; +use clap::{Args, Parser, Subcommand}; +use fixed::types::I80F48; +use mango::state::*; +use mango_common::*; +use serum_dex::state::OpenOrders; +use solana_sdk::pubkey::Pubkey; +use std::mem::size_of; +use std::str::FromStr; +use std::sync::Arc; + +#[derive(Parser, Debug, Clone)] +#[clap()] +struct Cli { + #[clap(subcommand)] + command: Command, +} + +#[derive(Args, Debug, Clone)] +struct EquityFromSnapshotArgs { + sqlite: String, + program: Pubkey, + group: Pubkey, +} + +#[derive(Subcommand, Debug, Clone)] +enum Command { + EquityFromSnapshot(EquityFromSnapshotArgs), +} + +fn main() -> anyhow::Result<()> { + env_logger::init_from_env( + env_logger::Env::default().filter_or(env_logger::DEFAULT_FILTER_ENV, "info"), + ); + + dotenv::dotenv().ok(); + let cli = Cli::parse(); + + match cli.command { + Command::EquityFromSnapshot(args) => EquityFromSnapshot::run(args), + } +} + +fn mango_account_common_checks(bytes: &[u8], data_type: DataType) -> anyhow::Result<()> { + if bytes.len() != size_of::() { + anyhow::bail!("bad size: {}, expected {}", bytes.len(), size_of::()); + } + if bytes[2] != 1 { + anyhow::bail!("not initialized: {}", bytes[2]); + } + let data_type = data_type as u8; + if bytes[0] != data_type { + anyhow::bail!("bad data type: {}, expected {}", bytes[0], data_type); + } + + Ok(()) +} + +struct DataSource { + conn: rusqlite::Connection, +} + +impl DataSource { + fn new(path: String) -> anyhow::Result { + let conn = rusqlite::Connection::open(path)?; + Ok(Self { conn }) + } + + fn account_bytes(&self, address: Pubkey) -> anyhow::Result> { + let mut stmt = self.conn.prepare_cached( + "SELECT data FROM account WHERE pubkey = ? ORDER BY write_version DESC LIMIT 1", + )?; + let mut rows = stmt.query_map(rusqlite::params![address.as_ref()], |row| row.get(0))?; + if let Some(data) = rows.next() { + return Ok(data?); + } + anyhow::bail!("no data found for pubkey {}", address); + } + + fn program_account_list(&self, program: Pubkey) -> anyhow::Result> { + let mut stmt = + self.conn.prepare_cached("SELECT DISTINCT pubkey FROM account WHERE owner = ?")?; + let mut rows = stmt.query(rusqlite::params![program.as_ref()])?; + let mut list = Vec::new(); + while let Some(row) = rows.next()? { + let v: Vec = row.get(0)?; + list.push(Pubkey::new(&v)); + } + Ok(list) + } + + fn mango_account_list( + &self, + program: Pubkey, + data_type: DataType, + ) -> anyhow::Result> { + let mut stmt = self.conn.prepare_cached( + "SELECT DISTINCT pubkey FROM account WHERE owner = ? AND hex(substr(data, 1, 1)) = ?", + )?; + let data_type_hex = format!("{:#04X}", data_type as u8)[2..].to_string(); + let mut rows = stmt.query(rusqlite::params![program.as_ref(), &data_type_hex])?; + let mut list = Vec::new(); + while let Some(row) = rows.next()? { + let v: Vec = row.get(0)?; + list.push(Pubkey::new(&v)); + } + Ok(list) + } + + fn load_group(&self, address: Pubkey) -> anyhow::Result { + let bytes = self.account_bytes(address)?; + mango_account_common_checks::(&bytes, DataType::MangoGroup) + .context("loading group")?; + Ok(MangoGroup::load_from_bytes(&bytes)?.clone()) + } + + fn load_cache(&self, address: Pubkey) -> anyhow::Result { + let bytes = self.account_bytes(address)?; + mango_account_common_checks::(&bytes, DataType::MangoCache) + .context("loading cache")?; + Ok(MangoCache::load_from_bytes(&bytes)?.clone()) + } + + fn load_open_orders(&self, address: Pubkey) -> anyhow::Result { + let bytes = self.account_bytes(address)?; + if bytes.len() != size_of::() + 12 { + anyhow::bail!("bad open orders size"); + } + let oo: &OpenOrders = bytemuck::from_bytes(&bytes[5..5 + size_of::()]); + Ok(oo.clone()) + } +} + +struct EquityFromSnapshot { + args: EquityFromSnapshotArgs, + data: DataSource, + group: MangoGroup, + cache: MangoCache, +} + +impl EquityFromSnapshot { + fn run(args: EquityFromSnapshotArgs) -> anyhow::Result<()> { + let data = DataSource::new(args.sqlite.clone())?; + + let group = data.load_group(args.group)?; + let cache = data.load_cache(group.mango_cache)?; + + let ctx = EquityFromSnapshot { args, data, group, cache }; + + let account_addresses = + ctx.data.mango_account_list(ctx.args.program, DataType::MangoAccount)?; + + for account_address in account_addresses { + let equity_opt = ctx + .account_equity(account_address) + .context(format!("on account {}", account_address))?; + if let Some(equity) = equity_opt { + println!("{},{}", account_address, equity); + } + } + + Ok(()) + } + + fn account_equity(&self, account_address: Pubkey) -> anyhow::Result> { + if account_address + != Pubkey::from_str(&"3TXDBTHFwyKywjZj1vGdRVkrF5o4YZ1vZnMf3Hb9qALz").unwrap() + { + //return Ok(None); + } + let account_bytes = self.data.account_bytes(account_address)?; + mango_account_common_checks::(&account_bytes, DataType::MangoAccount)?; + let mango_account = MangoAccount::load_from_bytes(&account_bytes)?; + if mango_account.mango_group != self.args.group { + return Ok(None); + } + + let mut equity = I80F48::ZERO; + + // USDC + { + let bank_cache = &self.cache.root_bank_cache[QUOTE_INDEX]; + let usdc = mango_account.get_net(bank_cache, QUOTE_INDEX); + //println!("usdc {}", usdc); + equity = equity.checked_add(usdc).unwrap(); + } + + // Sum up the deposit/borrow equity + for oracle_index in 0..self.group.num_oracles { + if self.group.spot_markets[oracle_index].is_empty() { + continue; + } + let price = self.cache.price_cache[oracle_index].price; + let bank_cache = &self.cache.root_bank_cache[oracle_index]; + let net = mango_account.get_net(bank_cache, oracle_index); + let net_usd = net.checked_mul(price).unwrap(); + //println!("token {} {} {} {}", oracle_index, net, net_usd, price); + equity = equity.checked_add(net_usd).unwrap(); + } + + // Sum up the serum open orders equity + for oracle_index in 0..self.group.num_oracles { + if self.group.spot_markets[oracle_index].is_empty() { + continue; + } + let oo_address = mango_account.spot_open_orders[oracle_index]; + if oo_address == Pubkey::default() { + continue; + } + let price = self.cache.price_cache[oracle_index].price; + let oo_maybe = self.data.load_open_orders(oo_address); + if oo_maybe.is_err() { + println!( + "Error: can't find oo account {} for mango account {}", + oo_address, account_address + ); + continue; + } + let oo = oo_maybe.unwrap(); + let quote = I80F48::from(oo.native_pc_total + oo.referrer_rebates_accrued); + let base = I80F48::from(oo.native_coin_total); + let serum_equity = quote.checked_add(base.checked_mul(price).unwrap()).unwrap(); + if !mango_account.in_margin_basket[oracle_index] && serum_equity != 0 { + println!("Error: mango account {} lists oo account {} with equity {} but in_margin_basket is false", account_address, oo_address, serum_equity); + } + //println!("serum {} {} {}", quote, base, serum_equity); + equity = equity.checked_add(serum_equity).unwrap(); + } + + // Sum up the perp position equity + for oracle_index in 0..self.group.num_oracles { + if self.group.perp_markets[oracle_index].is_empty() + || !mango_account.perp_accounts[oracle_index].is_active() + { + continue; + } + let price = self.cache.price_cache[oracle_index].price; + let pmi = &self.group.perp_markets[oracle_index]; + let pmc = &self.cache.perp_market_cache[oracle_index]; + let pa = &mango_account.perp_accounts[oracle_index]; + let quote = + pa.get_quote_position(pmc) + I80F48::from_num(pa.taker_quote * pmi.quote_lot_size); + let base = I80F48::from(pa.base_position + pa.taker_base) + .checked_mul(I80F48::from(pmi.base_lot_size)) + .unwrap(); + let perp_equity = quote.checked_add(base.checked_mul(price).unwrap()).unwrap(); + //println!("perp {} {} {} {}", oracle_index, quote, base, perp_equity); + equity = equity.checked_add(perp_equity).unwrap(); + } + // ignore open perp orders + + Ok(Some(equity)) + } +} From 3507b8b77c80bd0f4cbd900e03b88f5d20322365 Mon Sep 17 00:00:00 2001 From: Christian Kamm Date: Thu, 13 Oct 2022 12:06:36 +0200 Subject: [PATCH 02/28] compute reimbursement amounts taking into account previous liabs and potentially available token balances --- cli/src/main.rs | 218 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 207 insertions(+), 11 deletions(-) diff --git a/cli/src/main.rs b/cli/src/main.rs index 519f0c11..f5c1e139 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -138,6 +138,12 @@ struct EquityFromSnapshot { cache: MangoCache, } +#[derive(Default, Clone)] +struct AccountEquity { + /// value of per-token equity in usd, ordered by mango group token index + tokens_usd: [i64; 16], +} + impl EquityFromSnapshot { fn run(args: EquityFromSnapshotArgs) -> anyhow::Result<()> { let data = DataSource::new(args.sqlite.clone())?; @@ -150,19 +156,202 @@ impl EquityFromSnapshot { let account_addresses = ctx.data.mango_account_list(ctx.args.program, DataType::MangoAccount)?; + let mut account_equities: Vec<(Pubkey, AccountEquity)> = + Vec::with_capacity(account_addresses.len()); for account_address in account_addresses { let equity_opt = ctx .account_equity(account_address) .context(format!("on account {}", account_address))?; - if let Some(equity) = equity_opt { - println!("{},{}", account_address, equity); + if equity_opt.is_none() { + continue; + } + account_equities.push((account_address, equity_opt.unwrap())); + } + + let available_tokens: [bool; 15] = [ + true, true, true, true, false, // usdt is gone + true, true, false, // cope delisted + true, false, // no spot ada + true, true, true, false, // luna delisted + true, + ]; + + //println!("{:?}", ctx.cache.price_cache.iter().map(|c| c.price).collect::>()); + + // test values only! + // TODO: pass in the actual prices and amounts! + let available_native_amounts: [u64; 15] = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + + let reimbursement_prices: [I80F48; 16] = [ + // TODO: bad prices + I80F48::from_num(0.038725), + I80F48::from_num(19036.47), + I80F48::from_num(1280.639999999999997), + I80F48::from_num(0.031244633849997), + I80F48::from_num(0.999905), + I80F48::from_num(0.74051845), + I80F48::from_num(0.511599999999998), + I80F48::from_num(0.051956999999998), + I80F48::from_num(23.248483429999997), + I80F48::from_num(0.393549989999997), + I80F48::from_num(0.033400008119997), + I80F48::from_num(2.7067999025), + I80F48::from_num(0.159774020999997), + I80F48::from_num(0.000156989999997), + I80F48::from_num(0.000636922499996), + I80F48::ONE, + ]; + + let available_amounts: [u64; 15] = available_native_amounts + .iter() + .zip(reimbursement_prices.iter()) + .map(|(&native, &price)| (I80F48::from(native) * price).to_num()) + .collect::>() + .try_into() + .unwrap(); + + let mut reimburse_amounts = account_equities.clone(); + + // all the equity in unavailable tokens is just considered usdc + for (_, equity) in reimburse_amounts.iter_mut() { + for i in 0..15 { + if !available_tokens[i] { + let amount = equity.tokens_usd[i]; + equity.tokens_usd[QUOTE_INDEX] = + equity.tokens_usd[QUOTE_INDEX].checked_add(amount).unwrap(); + equity.tokens_usd[i] = 0; + } + } + } + + // basic total amount of all positive equities per token (liabs handled later) + let mut reimburse_totals = [0u64; 16]; + for (_, equity) in account_equities.iter() { + for (i, value) in equity.tokens_usd.iter().enumerate() { + if *value >= 0 { + reimburse_totals[i] = reimburse_totals[i].checked_add(*value as u64).unwrap(); + } + } + } + + println!("sum of positive token equities: {:?}", reimburse_totals); + println!("sum of available token equities: {:?}", available_amounts); + + // resolve user's liabilities with their assets in a way that aims to bring the + // needed token amounts <= what's available + let mut reimburse_amounts = account_equities.clone(); + for (pubkey, equity) in reimburse_amounts.iter_mut() { + println!("new equity: {:?} {pubkey}", equity.tokens_usd); + + for i in 0..16 { + let mut value = equity.tokens_usd[i]; + // positive amounts get reimbursed + if value >= 0 { + continue; + } + + // Negative amounts must be settled against other token balances + // This is using a greedy strategy, reducing the most requested token first + let mut weighted_indexes = equity.tokens_usd[0..15] + .iter() + .enumerate() + .filter_map(|(i, v)| (*v > 0).then_some(i)) + .filter_map(|i| { + (available_amounts[i] < reimburse_totals[i]) + .then(|| (i, reimburse_totals[i] - available_amounts[i])) + }) + .collect::>(); + + weighted_indexes.sort_by(|a, b| a.1.cmp(&b.1)); + for &(j, _) in weighted_indexes.iter() { + let start = equity.tokens_usd[j]; + let amount = if start + value >= 0 { -value } else { start }; + equity.tokens_usd[j] = equity.tokens_usd[j].checked_sub(amount).unwrap(); + reimburse_totals[j] = reimburse_totals[j].checked_sub(amount as u64).unwrap(); + //println!("{value} {start} {amount} {i} {j}"); + value = value + amount; + if value >= 0 { + break; + } + } + + // All tokens fine? Try reducing some random one, starting with USDC + for j in (0..16).rev() { + if equity.tokens_usd[j] <= 0 { + continue; + } + let start = equity.tokens_usd[j]; + let amount = if start + value >= 0 { -value } else { start }; + equity.tokens_usd[j] = equity.tokens_usd[j].checked_sub(amount).unwrap(); + reimburse_totals[j] = reimburse_totals[j].checked_sub(amount as u64).unwrap(); + value = value + amount; + if value >= 0 { + break; + } + } + + assert!(value == 0); + equity.tokens_usd[i] = 0; } + println!("---- final: {:?}", equity.tokens_usd); } + // now all reimburse_amounts are >= 0 + + // Do a second pass where we scale up or down user reimbursement amounts to fully utilize funds + for i in 0..15 { + if reimburse_totals[i] == 0 || reimburse_totals[i] == available_amounts[i] { + continue; + } + let fraction = I80F48::from(available_amounts[i]) / I80F48::from(reimburse_totals[i]); + + // Scale down token reimbursements and replace them with USDC reimbursements + for (_, equity) in reimburse_amounts.iter_mut() { + let amount = &mut equity.tokens_usd[i]; + assert!(*amount >= 0); + if *amount == 0 { + continue; + } + + let new_amount: i64 = (I80F48::from(*amount) * fraction).to_num(); + if fraction < 1 { + let decrease = (*amount - new_amount) as u64; + *amount = new_amount; + reimburse_totals[i] = reimburse_totals[i].checked_sub(decrease).unwrap(); + equity.tokens_usd[QUOTE_INDEX] += decrease as i64; + reimburse_totals[QUOTE_INDEX] = + reimburse_totals[QUOTE_INDEX].checked_add(decrease).unwrap(); + } else { + let increase = (new_amount - *amount) as u64; + *amount = new_amount; + reimburse_totals[i] = reimburse_totals[i].checked_add(increase).unwrap(); + equity.tokens_usd[QUOTE_INDEX] -= increase as i64; + reimburse_totals[QUOTE_INDEX] = + reimburse_totals[QUOTE_INDEX].checked_sub(increase).unwrap(); + } + } + } + + println!("sum of positive token equities: {:?}", reimburse_totals); + for i in 0..15 { + println!( + "{i} {} {} {}", + available_amounts[i] / 1000000, + reimburse_totals[i] / 1000000, + (available_amounts[i] as i64 - reimburse_totals[i] as i64) / 1000000 + ); + } + println!("15 {}", reimburse_totals[15] / 1000000); + + println!("reimburse total {}", reimburse_totals.iter().sum::() / 1000000); + + // println!("{},{:?}", account_address, equity.tokens_usd); + // } + Ok(()) } - fn account_equity(&self, account_address: Pubkey) -> anyhow::Result> { + fn account_equity(&self, account_address: Pubkey) -> anyhow::Result> { if account_address != Pubkey::from_str(&"3TXDBTHFwyKywjZj1vGdRVkrF5o4YZ1vZnMf3Hb9qALz").unwrap() { @@ -175,14 +364,14 @@ impl EquityFromSnapshot { return Ok(None); } - let mut equity = I80F48::ZERO; + let mut equity = [I80F48::ZERO; 16]; // USDC { let bank_cache = &self.cache.root_bank_cache[QUOTE_INDEX]; let usdc = mango_account.get_net(bank_cache, QUOTE_INDEX); //println!("usdc {}", usdc); - equity = equity.checked_add(usdc).unwrap(); + equity[QUOTE_INDEX] = usdc; } // Sum up the deposit/borrow equity @@ -195,7 +384,7 @@ impl EquityFromSnapshot { let net = mango_account.get_net(bank_cache, oracle_index); let net_usd = net.checked_mul(price).unwrap(); //println!("token {} {} {} {}", oracle_index, net, net_usd, price); - equity = equity.checked_add(net_usd).unwrap(); + equity[oracle_index] = net_usd; } // Sum up the serum open orders equity @@ -217,14 +406,16 @@ impl EquityFromSnapshot { continue; } let oo = oo_maybe.unwrap(); - let quote = I80F48::from(oo.native_pc_total + oo.referrer_rebates_accrued); + let quote = oo.native_pc_total + oo.referrer_rebates_accrued; let base = I80F48::from(oo.native_coin_total); - let serum_equity = quote.checked_add(base.checked_mul(price).unwrap()).unwrap(); + let base_usd = base.checked_mul(price).unwrap(); + let serum_equity = I80F48::from(quote).checked_add(base_usd).unwrap(); if !mango_account.in_margin_basket[oracle_index] && serum_equity != 0 { println!("Error: mango account {} lists oo account {} with equity {} but in_margin_basket is false", account_address, oo_address, serum_equity); } //println!("serum {} {} {}", quote, base, serum_equity); - equity = equity.checked_add(serum_equity).unwrap(); + equity[QUOTE_INDEX] = equity[QUOTE_INDEX].checked_add(I80F48::from(quote)).unwrap(); + equity[oracle_index] = equity[oracle_index].checked_add(base_usd).unwrap(); } // Sum up the perp position equity @@ -245,10 +436,15 @@ impl EquityFromSnapshot { .unwrap(); let perp_equity = quote.checked_add(base.checked_mul(price).unwrap()).unwrap(); //println!("perp {} {} {} {}", oracle_index, quote, base, perp_equity); - equity = equity.checked_add(perp_equity).unwrap(); + equity[QUOTE_INDEX] = equity[QUOTE_INDEX].checked_add(perp_equity).unwrap(); } // ignore open perp orders - Ok(Some(equity)) + let mut account_equity = AccountEquity::default(); + for i in 0..16 { + account_equity.tokens_usd[i] = equity[i].round().to_num(); + } + + Ok(Some(account_equity)) } } From 880e90455e52a2842b5b4680b4bf8366de102f3b Mon Sep 17 00:00:00 2001 From: Christian Kamm Date: Fri, 14 Oct 2022 07:44:02 +0200 Subject: [PATCH 03/28] tentative numbers --- cli/src/main.rs | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/cli/src/main.rs b/cli/src/main.rs index f5c1e139..8afacd89 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -178,9 +178,24 @@ impl EquityFromSnapshot { //println!("{:?}", ctx.cache.price_cache.iter().map(|c| c.price).collect::>()); - // test values only! - // TODO: pass in the actual prices and amounts! - let available_native_amounts: [u64; 15] = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + // TODO: tentative numbers from "Repay bad Debt #2" proposal + let available_native_amounts: [u64; 15] = [ + 32409565000000, + 281498000, + 226000000, + 761577910000000, + 0, + 2354260000000, + 98295000000, + 0, + 11774000000, + 0, + 799155000000000, + 60800000000, + 180900000000, + 0, + 152843000000000, + ]; let reimbursement_prices: [I80F48; 16] = [ // TODO: bad prices From 6e041512af450cabfb0d1b469bc49752fba5d34c Mon Sep 17 00:00:00 2001 From: Christian Kamm Date: Fri, 14 Oct 2022 10:04:39 +0200 Subject: [PATCH 04/28] improvements --- Cargo.lock | 146 ++++++++++++++++++++--------------------- cli/Cargo.toml | 2 +- cli/src/main.rs | 170 ++++++++++++++++++++++++++++++++---------------- 3 files changed, 188 insertions(+), 130 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8393fb56..a38f118b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -109,7 +109,7 @@ checksum = "70f6ee9518f50ff4d434471ccf569186022bdd5ef65a21d14da3ea5231af944f" dependencies = [ "anchor-syn", "anyhow", - "proc-macro2 1.0.37", + "proc-macro2 1.0.46", "quote 1.0.18", "regex", "syn 1.0.91", @@ -124,7 +124,7 @@ dependencies = [ "anchor-syn", "anyhow", "bs58 0.4.0", - "proc-macro2 1.0.37", + "proc-macro2 1.0.46", "quote 1.0.18", "rustversion", "syn 1.0.91", @@ -137,7 +137,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0844974ac35e8ced62056b0d63777ebcdc5807438b8b189c881e2b647450b70a" dependencies = [ "anchor-syn", - "proc-macro2 1.0.37", + "proc-macro2 1.0.46", "syn 1.0.91", ] @@ -148,7 +148,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f7467345e67a6f1d4b862b9763a4160ad89d18c247b8c902807768f7b6e23df" dependencies = [ "anchor-syn", - "proc-macro2 1.0.37", + "proc-macro2 1.0.46", "quote 1.0.18", "syn 1.0.91", ] @@ -161,7 +161,7 @@ checksum = "8774e4c1ac71f71a5aea7e4932fb69c30e3b8155c4fa59fd69401195434528a9" dependencies = [ "anchor-syn", "anyhow", - "proc-macro2 1.0.37", + "proc-macro2 1.0.46", "quote 1.0.18", "syn 1.0.91", ] @@ -175,7 +175,7 @@ dependencies = [ "anchor-syn", "anyhow", "heck 0.3.3", - "proc-macro2 1.0.37", + "proc-macro2 1.0.46", "quote 1.0.18", "syn 1.0.91", ] @@ -188,7 +188,7 @@ checksum = "ac515a7a5a4fea7fc768b1cec40ddb948e148ea657637c75f94f283212326cb9" dependencies = [ "anchor-syn", "anyhow", - "proc-macro2 1.0.37", + "proc-macro2 1.0.46", "quote 1.0.18", "syn 1.0.91", ] @@ -201,7 +201,7 @@ checksum = "43dc667b62ff71450f19dcfcc37b0c408fd4ddd89e8650368c2b0984b110603f" dependencies = [ "anchor-syn", "anyhow", - "proc-macro2 1.0.37", + "proc-macro2 1.0.46", "quote 1.0.18", "syn 1.0.91", ] @@ -214,7 +214,7 @@ checksum = "7354d583a06701d24800a8ec4c2b0491f62581a331af349205e23421e0b56643" dependencies = [ "anchor-syn", "anyhow", - "proc-macro2 1.0.37", + "proc-macro2 1.0.46", "quote 1.0.18", "syn 1.0.91", ] @@ -252,7 +252,7 @@ dependencies = [ "anyhow", "bs58 0.3.1", "heck 0.3.3", - "proc-macro2 1.0.37", + "proc-macro2 1.0.46", "proc-macro2-diagnostics", "quote 1.0.18", "serde", @@ -317,7 +317,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "726535892e8eae7e70657b4c8ea93d26b8553afb1ce617caee529ef96d7dee6c" dependencies = [ - "proc-macro2 1.0.37", + "proc-macro2 1.0.46", "quote 1.0.18", "syn 1.0.91", "synstructure", @@ -329,7 +329,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2777730b2039ac0f95f093556e61b6d26cebed5393ca6f152717777cec3a42ed" dependencies = [ - "proc-macro2 1.0.37", + "proc-macro2 1.0.46", "quote 1.0.18", "syn 1.0.91", ] @@ -369,7 +369,7 @@ version = "0.1.53" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed6aa3524a2dfcf9fe180c51eae2b58738348d819517ceadf95789c51fff7600" dependencies = [ - "proc-macro2 1.0.37", + "proc-macro2 1.0.46", "quote 1.0.18", "syn 1.0.91", ] @@ -497,7 +497,7 @@ dependencies = [ "borsh-derive-internal", "borsh-schema-derive-internal", "proc-macro-crate 0.1.5", - "proc-macro2 1.0.37", + "proc-macro2 1.0.46", "syn 1.0.91", ] @@ -507,7 +507,7 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5449c28a7b352f2d1e592a8a28bf139bc71afb0764a14f3c02500935d8c44065" dependencies = [ - "proc-macro2 1.0.37", + "proc-macro2 1.0.46", "quote 1.0.18", "syn 1.0.91", ] @@ -518,7 +518,7 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdbd5696d8bfa21d53d9fe39a714a18538bad11492a42d066dbbc395fb1951c0" dependencies = [ - "proc-macro2 1.0.37", + "proc-macro2 1.0.46", "quote 1.0.18", "syn 1.0.91", ] @@ -587,7 +587,7 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "562e382481975bc61d11275ac5e62a19abd00b0547d99516a415336f183dcd0e" dependencies = [ - "proc-macro2 1.0.37", + "proc-macro2 1.0.46", "quote 1.0.18", "syn 1.0.91", ] @@ -702,46 +702,44 @@ dependencies = [ "atty", "bitflags", "strsim 0.8.0", - "textwrap 0.11.0", + "textwrap", "unicode-width", "vec_map", ] [[package]] name = "clap" -version = "3.2.2" +version = "4.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e538f9ee5aa3b3963f09a997035f883677966ed50fce0292611927ce6f6d8c6" +checksum = "6bf8832993da70a4c6d13c581f4463c2bdda27b9bf1c5498dc4365543abe6d6f" dependencies = [ "atty", "bitflags", "clap_derive", "clap_lex", - "indexmap", - "lazy_static", + "once_cell", "strsim 0.10.0", "termcolor", - "textwrap 0.15.1", ] [[package]] name = "clap_derive" -version = "3.2.2" +version = "4.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7f98063cac4652f23ccda556b8d04347a7fc4b2cff1f7577cc8c6546e0d8078" +checksum = "c42f169caba89a7d512b5418b09864543eeb4d497416c917d7137863bd2076ad" dependencies = [ "heck 0.4.0", "proc-macro-error", - "proc-macro2 1.0.37", + "proc-macro2 1.0.46", "quote 1.0.18", "syn 1.0.91", ] [[package]] name = "clap_lex" -version = "0.2.4" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" +checksum = "0d4198f73e42b4936b35b5bb248d81d2b595ecb170da0bac7655c54eedfa8da8" dependencies = [ "os_str_bytes", ] @@ -752,7 +750,7 @@ version = "0.1.0" dependencies = [ "anyhow", "bytemuck", - "clap 3.2.2", + "clap 4.0.15", "dotenv", "env_logger 0.8.4", "fixed", @@ -1069,7 +1067,7 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3bf95dc3f046b9da4f2d51833c0d3547d8564ef6910f5c1ed130306a75b92886" dependencies = [ - "proc-macro2 1.0.37", + "proc-macro2 1.0.46", "quote 1.0.18", "syn 1.0.91", ] @@ -1151,7 +1149,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c07b7cc9cd8c08d10db74fca3b20949b9b6199725c04a0cce6d543496098fcac" dependencies = [ "enum-ordinalize", - "proc-macro2 1.0.37", + "proc-macro2 1.0.46", "quote 1.0.18", "syn 1.0.91", ] @@ -1192,7 +1190,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c134c37760b27a871ba422106eedbb8247da973a09e82558bf26d619c882b159" dependencies = [ - "proc-macro2 1.0.37", + "proc-macro2 1.0.46", "quote 1.0.18", "syn 1.0.91", ] @@ -1205,7 +1203,7 @@ checksum = "2170fc0efee383079a8bdd05d6ea2a184d2a0f07a1c1dcabdb2fd5e9f24bc36c" dependencies = [ "num-bigint 0.4.3", "num-traits", - "proc-macro2 1.0.37", + "proc-macro2 1.0.46", "quote 1.0.18", "rustc_version 0.4.0", "syn 1.0.91", @@ -1218,7 +1216,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eb359f1476bf611266ac1f5355bc14aeca37b299d0ebccc038ee7058891c9cb" dependencies = [ "once_cell", - "proc-macro2 1.0.37", + "proc-macro2 1.0.46", "quote 1.0.18", "syn 1.0.91", ] @@ -1238,7 +1236,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "946ee94e3dbf58fdd324f9ce245c7b238d46a66f00e86a020b71996349e46cce" dependencies = [ - "proc-macro2 1.0.37", + "proc-macro2 1.0.46", "quote 1.0.18", "syn 1.0.91", ] @@ -1358,7 +1356,7 @@ dependencies = [ "fixed", "paste", "proc-macro-error", - "proc-macro2 1.0.37", + "proc-macro2 1.0.46", "quote 1.0.18", "syn 1.0.91", ] @@ -1455,7 +1453,7 @@ version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512" dependencies = [ - "proc-macro2 1.0.37", + "proc-macro2 1.0.46", "quote 1.0.18", "syn 1.0.91", ] @@ -2191,7 +2189,7 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a7d5f7076603ebc68de2dc6a650ec331a062a13abaa346975be747bbfa4b789" dependencies = [ - "proc-macro2 1.0.37", + "proc-macro2 1.0.46", "quote 1.0.18", "syn 1.0.91", ] @@ -2280,7 +2278,7 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" dependencies = [ - "proc-macro2 1.0.37", + "proc-macro2 1.0.46", "quote 1.0.18", "syn 1.0.91", ] @@ -2353,7 +2351,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b0498641e53dd6ac1a4f22547548caa6864cc4933784319cd1775271c5a46ce" dependencies = [ "proc-macro-crate 1.1.3", - "proc-macro2 1.0.37", + "proc-macro2 1.0.46", "quote 1.0.18", "syn 1.0.91", ] @@ -2384,9 +2382,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.10.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9" +checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1" [[package]] name = "opaque-debug" @@ -2458,7 +2456,7 @@ checksum = "ed9a247206016d424fe8497bc611e510887af5c261fbbf977877c4bb55ca4d82" dependencies = [ "Inflector", "proc-macro-error", - "proc-macro2 1.0.37", + "proc-macro2 1.0.46", "quote 1.0.18", "syn 1.0.91", ] @@ -2583,7 +2581,7 @@ version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb" dependencies = [ - "proc-macro2 1.0.37", + "proc-macro2 1.0.46", "quote 1.0.18", "syn 1.0.91", ] @@ -2667,7 +2665,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", - "proc-macro2 1.0.37", + "proc-macro2 1.0.46", "quote 1.0.18", "syn 1.0.91", "version_check", @@ -2679,7 +2677,7 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ - "proc-macro2 1.0.37", + "proc-macro2 1.0.46", "quote 1.0.18", "version_check", ] @@ -2695,11 +2693,11 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.37" +version = "1.0.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec757218438d5fda206afc041538b2f6d889286160d649a86a24d37e1235afd1" +checksum = "94e2ef8dbfc347b10c094890f778ee2e36ca9bb4262e86dc99cd217e35f3470b" dependencies = [ - "unicode-xid 0.2.2", + "unicode-ident", ] [[package]] @@ -2708,7 +2706,7 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4bf29726d67464d49fa6224a1d07936a8c08bb3fba727c7493f6cf1616fdaada" dependencies = [ - "proc-macro2 1.0.37", + "proc-macro2 1.0.46", "quote 1.0.18", "syn 1.0.91", "version_check", @@ -2846,7 +2844,7 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" dependencies = [ - "proc-macro2 1.0.37", + "proc-macro2 1.0.46", ] [[package]] @@ -3268,7 +3266,7 @@ version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f188d036977451159430f3b8dc82ec76364a42b7e289c2b18a9a18f4470058e9" dependencies = [ - "proc-macro2 1.0.37", + "proc-macro2 1.0.46", "quote 1.0.18", "serde_derive_internals", "syn 1.0.91", @@ -3295,7 +3293,7 @@ version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aaaae8f38bb311444cfb7f1979af0bc9240d95795f75f9ceddf6a59b79ceffa0" dependencies = [ - "proc-macro2 1.0.37", + "proc-macro2 1.0.46", "quote 1.0.18", "syn 1.0.91", ] @@ -3381,7 +3379,7 @@ version = "1.0.136" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9" dependencies = [ - "proc-macro2 1.0.37", + "proc-macro2 1.0.46", "quote 1.0.18", "syn 1.0.91", ] @@ -3392,7 +3390,7 @@ version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c" dependencies = [ - "proc-macro2 1.0.37", + "proc-macro2 1.0.46", "quote 1.0.18", "syn 1.0.91", ] @@ -3860,7 +3858,7 @@ version = "1.10.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "635c60ac96b1347af272c625465068b908aff919d19f29b5795a44310310494d" dependencies = [ - "proc-macro2 1.0.37", + "proc-macro2 1.0.46", "quote 1.0.18", "rustc_version 0.4.0", "syn 1.0.91", @@ -4186,7 +4184,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b8bcac4394644f21dc013e932a7df9f536fcecef3e5df43fe362b4ec532ce30" dependencies = [ "bs58 0.4.0", - "proc-macro2 1.0.37", + "proc-macro2 1.0.46", "quote 1.0.18", "rustversion", "syn 1.0.91", @@ -4527,7 +4525,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" dependencies = [ "heck 0.4.0", - "proc-macro2 1.0.37", + "proc-macro2 1.0.46", "quote 1.0.18", "rustversion", "syn 1.0.91", @@ -4607,7 +4605,7 @@ version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b683b2b825c8eef438b77c36a06dc262294da3d5a5813fac20da149241dcd44d" dependencies = [ - "proc-macro2 1.0.37", + "proc-macro2 1.0.46", "quote 1.0.18", "unicode-xid 0.2.2", ] @@ -4618,7 +4616,7 @@ version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" dependencies = [ - "proc-macro2 1.0.37", + "proc-macro2 1.0.46", "quote 1.0.18", "syn 1.0.91", "unicode-xid 0.2.2", @@ -4689,7 +4687,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea80818e6c75f81d961d7426c1b938cbea6b3a51533b5ee71b61f82166b7ef3d" dependencies = [ - "proc-macro2 1.0.37", + "proc-macro2 1.0.46", "quote 1.0.18", "syn 1.0.91", ] @@ -4700,7 +4698,7 @@ version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ee42b4e559f17bce0385ebf511a7beb67d5cc33c12c96b7f4e9789919d9c10f" dependencies = [ - "proc-macro2 1.0.37", + "proc-macro2 1.0.46", "quote 1.0.18", "syn 1.0.91", ] @@ -4747,12 +4745,6 @@ dependencies = [ "unicode-width", ] -[[package]] -name = "textwrap" -version = "0.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "949517c0cf1bf4ee812e2e07e08ab448e3ae0d23472aee8a06c985f0c8815b16" - [[package]] name = "thiserror" version = "1.0.30" @@ -4768,7 +4760,7 @@ version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" dependencies = [ - "proc-macro2 1.0.37", + "proc-macro2 1.0.46", "quote 1.0.18", "syn 1.0.91", ] @@ -4870,7 +4862,7 @@ version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7" dependencies = [ - "proc-macro2 1.0.37", + "proc-macro2 1.0.46", "quote 1.0.18", "syn 1.0.91", ] @@ -4992,7 +4984,7 @@ version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e65ce065b4b5c53e73bb28912318cb8c9e9ad3921f1d669eb0e68b4c8143a2b" dependencies = [ - "proc-macro2 1.0.37", + "proc-macro2 1.0.46", "quote 1.0.18", "syn 1.0.91", ] @@ -5088,6 +5080,12 @@ version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f" +[[package]] +name = "unicode-ident" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" + [[package]] name = "unicode-normalization" version = "0.1.19" @@ -5256,7 +5254,7 @@ dependencies = [ "bumpalo", "lazy_static", "log", - "proc-macro2 1.0.37", + "proc-macro2 1.0.46", "quote 1.0.18", "syn 1.0.91", "wasm-bindgen-shared", @@ -5290,7 +5288,7 @@ version = "0.2.80" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99ec0dc7a4756fffc231aab1b9f2f578d23cd391390ab27f952ae0c9b3ece20b" dependencies = [ - "proc-macro2 1.0.37", + "proc-macro2 1.0.46", "quote 1.0.18", "syn 1.0.91", "wasm-bindgen-backend", @@ -5533,7 +5531,7 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f8f187641dad4f680d25c4bfc4225b418165984179f26ca76ec4fb6441d3a17" dependencies = [ - "proc-macro2 1.0.37", + "proc-macro2 1.0.46", "quote 1.0.18", "syn 1.0.91", "synstructure", diff --git a/cli/Cargo.toml b/cli/Cargo.toml index 2fb0f87a..77f67c33 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" [dependencies] anyhow = "1.0" -clap = { version = "3.1.8", features = ["derive", "env"] } +clap = { version = "4.0.15", features = ["derive", "env"] } dotenv = "0.15.0" env_logger = "0.8.4" fixed = { version = "=1.11.0", features = ["serde", "borsh"] } diff --git a/cli/src/main.rs b/cli/src/main.rs index 8afacd89..96d8fb4d 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -7,7 +7,6 @@ use serum_dex::state::OpenOrders; use solana_sdk::pubkey::Pubkey; use std::mem::size_of; use std::str::FromStr; -use std::sync::Arc; #[derive(Parser, Debug, Clone)] #[clap()] @@ -77,6 +76,7 @@ impl DataSource { anyhow::bail!("no data found for pubkey {}", address); } + /* fn program_account_list(&self, program: Pubkey) -> anyhow::Result> { let mut stmt = self.conn.prepare_cached("SELECT DISTINCT pubkey FROM account WHERE owner = ?")?; @@ -88,6 +88,7 @@ impl DataSource { } Ok(list) } + */ fn mango_account_list( &self, @@ -138,11 +139,8 @@ struct EquityFromSnapshot { cache: MangoCache, } -#[derive(Default, Clone)] -struct AccountEquity { - /// value of per-token equity in usd, ordered by mango group token index - tokens_usd: [i64; 16], -} +/// value of per-token equity in usd, ordered by mango group token index +type AccountTokenAmounts = [i64; 16]; impl EquityFromSnapshot { fn run(args: EquityFromSnapshotArgs) -> anyhow::Result<()> { @@ -156,7 +154,7 @@ impl EquityFromSnapshot { let account_addresses = ctx.data.mango_account_list(ctx.args.program, DataType::MangoAccount)?; - let mut account_equities: Vec<(Pubkey, AccountEquity)> = + let mut account_equities: Vec<(Pubkey, AccountTokenAmounts)> = Vec::with_capacity(account_addresses.len()); for account_address in account_addresses { let equity_opt = ctx @@ -168,6 +166,11 @@ impl EquityFromSnapshot { account_equities.push((account_address, equity_opt.unwrap())); } + let token_names: [&str; 16] = [ + "MNGO", "BTC", "ETH", "SOL", "USDT", "SRM", "RAY", "COPE", "FTT", "ADA", "MSOL", "BNB", + "AVAX", "LUNA", "GMT", "USDC", + ]; + let available_tokens: [bool; 15] = [ true, true, true, true, false, // usdt is gone true, true, false, // cope delisted @@ -231,10 +234,9 @@ impl EquityFromSnapshot { for (_, equity) in reimburse_amounts.iter_mut() { for i in 0..15 { if !available_tokens[i] { - let amount = equity.tokens_usd[i]; - equity.tokens_usd[QUOTE_INDEX] = - equity.tokens_usd[QUOTE_INDEX].checked_add(amount).unwrap(); - equity.tokens_usd[i] = 0; + let amount = equity[i]; + equity[QUOTE_INDEX] += amount; + equity[i] = 0; } } } @@ -242,9 +244,9 @@ impl EquityFromSnapshot { // basic total amount of all positive equities per token (liabs handled later) let mut reimburse_totals = [0u64; 16]; for (_, equity) in account_equities.iter() { - for (i, value) in equity.tokens_usd.iter().enumerate() { + for (i, value) in equity.iter().enumerate() { if *value >= 0 { - reimburse_totals[i] = reimburse_totals[i].checked_add(*value as u64).unwrap(); + reimburse_totals[i] += *value as u64; } } } @@ -255,11 +257,9 @@ impl EquityFromSnapshot { // resolve user's liabilities with their assets in a way that aims to bring the // needed token amounts <= what's available let mut reimburse_amounts = account_equities.clone(); - for (pubkey, equity) in reimburse_amounts.iter_mut() { - println!("new equity: {:?} {pubkey}", equity.tokens_usd); - + for (_, equity) in reimburse_amounts.iter_mut() { for i in 0..16 { - let mut value = equity.tokens_usd[i]; + let mut value = equity[i]; // positive amounts get reimbursed if value >= 0 { continue; @@ -267,7 +267,7 @@ impl EquityFromSnapshot { // Negative amounts must be settled against other token balances // This is using a greedy strategy, reducing the most requested token first - let mut weighted_indexes = equity.tokens_usd[0..15] + let mut weighted_indexes = equity[0..15] .iter() .enumerate() .filter_map(|(i, v)| (*v > 0).then_some(i)) @@ -279,94 +279,154 @@ impl EquityFromSnapshot { weighted_indexes.sort_by(|a, b| a.1.cmp(&b.1)); for &(j, _) in weighted_indexes.iter() { - let start = equity.tokens_usd[j]; + let start = equity[j]; let amount = if start + value >= 0 { -value } else { start }; - equity.tokens_usd[j] = equity.tokens_usd[j].checked_sub(amount).unwrap(); - reimburse_totals[j] = reimburse_totals[j].checked_sub(amount as u64).unwrap(); - //println!("{value} {start} {amount} {i} {j}"); - value = value + amount; + equity[j] -= amount; + reimburse_totals[j] -= amount as u64; + value += amount; if value >= 0 { break; } } // All tokens fine? Try reducing some random one, starting with USDC - for j in (0..16).rev() { - if equity.tokens_usd[j] <= 0 { + for j in [15, 14, 13, 12, 11, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 10] { + if equity[j] <= 0 { continue; } - let start = equity.tokens_usd[j]; + let start = equity[j]; let amount = if start + value >= 0 { -value } else { start }; - equity.tokens_usd[j] = equity.tokens_usd[j].checked_sub(amount).unwrap(); - reimburse_totals[j] = reimburse_totals[j].checked_sub(amount as u64).unwrap(); - value = value + amount; + equity[j] -= amount; + reimburse_totals[j] -= amount as u64; + value += amount; if value >= 0 { break; } } assert!(value == 0); - equity.tokens_usd[i] = 0; + equity[i] = 0; } - println!("---- final: {:?}", equity.tokens_usd); } // now all reimburse_amounts are >= 0 - // Do a second pass where we scale up or down user reimbursement amounts to fully utilize funds + // Do a pass where we scale down user reimbursement token amounts and instead + // reimburse with USDC if there's not enough tokens for i in 0..15 { if reimburse_totals[i] == 0 || reimburse_totals[i] == available_amounts[i] { continue; } let fraction = I80F48::from(available_amounts[i]) / I80F48::from(reimburse_totals[i]); + if fraction >= 1 { + continue; + } // Scale down token reimbursements and replace them with USDC reimbursements for (_, equity) in reimburse_amounts.iter_mut() { - let amount = &mut equity.tokens_usd[i]; + let amount = &mut equity[i]; assert!(*amount >= 0); if *amount == 0 { continue; } let new_amount: i64 = (I80F48::from(*amount) * fraction).to_num(); - if fraction < 1 { - let decrease = (*amount - new_amount) as u64; - *amount = new_amount; - reimburse_totals[i] = reimburse_totals[i].checked_sub(decrease).unwrap(); - equity.tokens_usd[QUOTE_INDEX] += decrease as i64; - reimburse_totals[QUOTE_INDEX] = - reimburse_totals[QUOTE_INDEX].checked_add(decrease).unwrap(); + let decrease = (*amount - new_amount) as u64; + *amount = new_amount; + reimburse_totals[i] -= decrease; + let target = if i == 3 { + 10 // SOL -> mSOL } else { - let increase = (new_amount - *amount) as u64; - *amount = new_amount; - reimburse_totals[i] = reimburse_totals[i].checked_add(increase).unwrap(); - equity.tokens_usd[QUOTE_INDEX] -= increase as i64; - reimburse_totals[QUOTE_INDEX] = - reimburse_totals[QUOTE_INDEX].checked_sub(increase).unwrap(); + QUOTE_INDEX + }; + equity[target] += decrease as i64; + reimburse_totals[target] += decrease; + } + } + + // Do passes where we scale up token reimbursement amounts to try to fully utilize funds + for _ in 0..100 { + for i in 0..15 { + if reimburse_totals[i] == 0 || reimburse_totals[i] == available_amounts[i] { + continue; + } + + let fraction = + I80F48::from(available_amounts[i]) / I80F48::from(reimburse_totals[i]); + if fraction <= 1 { + continue; + } + + // Scale up token reimbursements and take away USDC reimbursements + for (_, equity) in reimburse_amounts.iter_mut() { + let amount = equity[i]; + assert!(amount >= 0); + if amount == 0 { + continue; + } + + let new_amount: i64 = (I80F48::from(amount) * fraction).to_num(); + let mut remaining_increase = new_amount - amount; // positive + + for j in (0..16).rev() { + let other_amount = equity[j]; + if (j != 15 && available_amounts[j] >= reimburse_totals[j]) + || other_amount == 0 + { + continue; + } + let increase = remaining_increase.min(other_amount); + equity[j] -= increase; + reimburse_totals[j] -= increase as u64; + equity[i] += increase; + reimburse_totals[i] += increase as u64; + remaining_increase -= increase; + } } } } - println!("sum of positive token equities: {:?}", reimburse_totals); + // double check that user equity is unchanged + for ((_, equity), (_, reimburse)) in account_equities.iter().zip(reimburse_amounts.iter()) { + let eqsum = equity.iter().sum::(); + let resum = reimburse.iter().sum::(); + assert_eq!(eqsum, resum); + } + for i in 0..15 { println!( - "{i} {} {} {}", + "{}: available {}, used {}, left over {}", + token_names[i], available_amounts[i] / 1000000, reimburse_totals[i] / 1000000, (available_amounts[i] as i64 - reimburse_totals[i] as i64) / 1000000 ); } - println!("15 {}", reimburse_totals[15] / 1000000); - + println!("USDC: used {}", reimburse_totals[15] / 1000000); println!("reimburse total {}", reimburse_totals.iter().sum::() / 1000000); - // println!("{},{:?}", account_address, equity.tokens_usd); - // } + println!("pubkey,{}", token_names.join(",")); + for (pubkey, amounts) in reimburse_amounts.iter() { + println!( + "{pubkey},{}", + amounts + .iter() + .enumerate() + .map(|(index, v)| (I80F48::from(*v) / reimbursement_prices[index]) + .floor() + .to_string()) + .collect::>() + .join(",") + ); + } Ok(()) } - fn account_equity(&self, account_address: Pubkey) -> anyhow::Result> { + fn account_equity( + &self, + account_address: Pubkey, + ) -> anyhow::Result> { if account_address != Pubkey::from_str(&"3TXDBTHFwyKywjZj1vGdRVkrF5o4YZ1vZnMf3Hb9qALz").unwrap() { @@ -455,9 +515,9 @@ impl EquityFromSnapshot { } // ignore open perp orders - let mut account_equity = AccountEquity::default(); + let mut account_equity = AccountTokenAmounts::default(); for i in 0..16 { - account_equity.tokens_usd[i] = equity[i].round().to_num(); + account_equity[i] = equity[i].round().to_num(); } Ok(Some(account_equity)) From 2eb92c3af118e55e317c8081a94bdbaec0a35b0f Mon Sep 17 00:00:00 2001 From: Christian Kamm Date: Fri, 14 Oct 2022 10:51:57 +0200 Subject: [PATCH 05/28] print out mango account address plus owner address --- cli/src/main.rs | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/cli/src/main.rs b/cli/src/main.rs index 96d8fb4d..493867dc 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -154,7 +154,7 @@ impl EquityFromSnapshot { let account_addresses = ctx.data.mango_account_list(ctx.args.program, DataType::MangoAccount)?; - let mut account_equities: Vec<(Pubkey, AccountTokenAmounts)> = + let mut account_equities: Vec<(Pubkey, Pubkey, AccountTokenAmounts)> = Vec::with_capacity(account_addresses.len()); for account_address in account_addresses { let equity_opt = ctx @@ -163,7 +163,8 @@ impl EquityFromSnapshot { if equity_opt.is_none() { continue; } - account_equities.push((account_address, equity_opt.unwrap())); + let (owner, equity) = equity_opt.unwrap(); + account_equities.push((account_address, owner, equity)); } let token_names: [&str; 16] = [ @@ -231,7 +232,7 @@ impl EquityFromSnapshot { let mut reimburse_amounts = account_equities.clone(); // all the equity in unavailable tokens is just considered usdc - for (_, equity) in reimburse_amounts.iter_mut() { + for (_, _, equity) in reimburse_amounts.iter_mut() { for i in 0..15 { if !available_tokens[i] { let amount = equity[i]; @@ -243,7 +244,7 @@ impl EquityFromSnapshot { // basic total amount of all positive equities per token (liabs handled later) let mut reimburse_totals = [0u64; 16]; - for (_, equity) in account_equities.iter() { + for (_, _, equity) in account_equities.iter() { for (i, value) in equity.iter().enumerate() { if *value >= 0 { reimburse_totals[i] += *value as u64; @@ -257,7 +258,7 @@ impl EquityFromSnapshot { // resolve user's liabilities with their assets in a way that aims to bring the // needed token amounts <= what's available let mut reimburse_amounts = account_equities.clone(); - for (_, equity) in reimburse_amounts.iter_mut() { + for (_, _, equity) in reimburse_amounts.iter_mut() { for i in 0..16 { let mut value = equity[i]; // positive amounts get reimbursed @@ -323,7 +324,7 @@ impl EquityFromSnapshot { } // Scale down token reimbursements and replace them with USDC reimbursements - for (_, equity) in reimburse_amounts.iter_mut() { + for (_, _, equity) in reimburse_amounts.iter_mut() { let amount = &mut equity[i]; assert!(*amount >= 0); if *amount == 0 { @@ -358,7 +359,7 @@ impl EquityFromSnapshot { } // Scale up token reimbursements and take away USDC reimbursements - for (_, equity) in reimburse_amounts.iter_mut() { + for (_, _, equity) in reimburse_amounts.iter_mut() { let amount = equity[i]; assert!(amount >= 0); if amount == 0 { @@ -387,10 +388,13 @@ impl EquityFromSnapshot { } // double check that user equity is unchanged - for ((_, equity), (_, reimburse)) in account_equities.iter().zip(reimburse_amounts.iter()) { + for ((_, ownerl, equity), (_, ownerr, reimburse)) in + account_equities.iter().zip(reimburse_amounts.iter()) + { let eqsum = equity.iter().sum::(); let resum = reimburse.iter().sum::(); assert_eq!(eqsum, resum); + assert_eq!(ownerl, ownerr); } for i in 0..15 { @@ -405,10 +409,10 @@ impl EquityFromSnapshot { println!("USDC: used {}", reimburse_totals[15] / 1000000); println!("reimburse total {}", reimburse_totals.iter().sum::() / 1000000); - println!("pubkey,{}", token_names.join(",")); - for (pubkey, amounts) in reimburse_amounts.iter() { + println!("account,owner,{}", token_names.join(",")); + for (account, owner, amounts) in reimburse_amounts.iter() { println!( - "{pubkey},{}", + "{account},{owner},{}", amounts .iter() .enumerate() @@ -426,7 +430,7 @@ impl EquityFromSnapshot { fn account_equity( &self, account_address: Pubkey, - ) -> anyhow::Result> { + ) -> anyhow::Result> { if account_address != Pubkey::from_str(&"3TXDBTHFwyKywjZj1vGdRVkrF5o4YZ1vZnMf3Hb9qALz").unwrap() { @@ -520,6 +524,6 @@ impl EquityFromSnapshot { account_equity[i] = equity[i].round().to_num(); } - Ok(Some(account_equity)) + Ok(Some((mango_account.owner, account_equity))) } } From a28140869a52d1fb255903c0349358e0fcc76245 Mon Sep 17 00:00:00 2001 From: Christian Kamm Date: Fri, 14 Oct 2022 16:22:02 +0200 Subject: [PATCH 06/28] take deposits/withdraws after snapshot into account --- cli/src/main.rs | 154 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 134 insertions(+), 20 deletions(-) diff --git a/cli/src/main.rs b/cli/src/main.rs index 493867dc..e12ec749 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -5,6 +5,7 @@ use mango::state::*; use mango_common::*; use serum_dex::state::OpenOrders; use solana_sdk::pubkey::Pubkey; +use std::collections::HashMap; use std::mem::size_of; use std::str::FromStr; @@ -18,6 +19,7 @@ struct Cli { #[derive(Args, Debug, Clone)] struct EquityFromSnapshotArgs { sqlite: String, + late_changes: String, program: Pubkey, group: Pubkey, } @@ -76,20 +78,6 @@ impl DataSource { anyhow::bail!("no data found for pubkey {}", address); } - /* - fn program_account_list(&self, program: Pubkey) -> anyhow::Result> { - let mut stmt = - self.conn.prepare_cached("SELECT DISTINCT pubkey FROM account WHERE owner = ?")?; - let mut rows = stmt.query(rusqlite::params![program.as_ref()])?; - let mut list = Vec::new(); - while let Some(row) = rows.next()? { - let v: Vec = row.get(0)?; - list.push(Pubkey::new(&v)); - } - Ok(list) - } - */ - fn mango_account_list( &self, program: Pubkey, @@ -132,6 +120,58 @@ impl DataSource { } } +fn late_deposits_withdrawals(filename: &str) -> anyhow::Result> { + // mango token index and decimals + let tokens: HashMap<&str, (usize, i32)> = HashMap::from([ + ("MNGO", (0, 6)), + ("BTC", (1, 6)), + ("ETH", (2, 6)), + ("SOL", (3, 9)), + ("USDT", (4, 6)), + ("SRM", (5, 6)), + ("RAY", (6, 6)), + ("FTT", (8, 6)), + ("MSOL", (10, 9)), + ("BNB", (11, 8)), + ("AVAX", (12, 8)), + ("GMT", (14, 9)), + ("USDC", (15, 6)), + ]); + + let mut list = Vec::new(); + + use std::io::{BufRead, BufReader}; + let file = std::fs::File::open(filename)?; + for line in BufReader::new(file).lines().skip(1) { + if let Ok(line) = line { + let fields = line.split("\t").collect::>(); + assert_eq!(fields.len(), 19); + let account = Pubkey::from_str(fields[5]).unwrap(); + // skip attacker accounts + if fields[5] == "4ND8FVPjUGGjx9VuGFuJefDWpg3THb58c277hbVRnjNa" + || fields[5] == "CQvKSNnYtPTZfQRQ5jkHq8q2swJyRsdQLcFcj3EmKFfX" + { + continue; + } + let owner = Pubkey::from_str(fields[6]).unwrap(); + let token = fields[7]; + let side = fields[8]; + let quantity = f64::from_str(&fields[9].replace(",", "")).unwrap(); + let token_info = tokens.get(token).unwrap(); + let change = (quantity + * 10f64.powi(token_info.1) + * (if side == "Withdraw" { + -1f64 + } else { + assert_eq!(side, "Deposit"); + 1f64 + })) as i64; + list.push((account, owner, token_info.0, change)); + } + } + Ok(list) +} + struct EquityFromSnapshot { args: EquityFromSnapshotArgs, data: DataSource, @@ -139,11 +179,21 @@ struct EquityFromSnapshot { cache: MangoCache, } +fn cache_price(cache: &MangoCache, index: usize) -> I80F48 { + if index == QUOTE_INDEX { + I80F48::ONE + } else { + cache.price_cache[index].price + } +} + /// value of per-token equity in usd, ordered by mango group token index type AccountTokenAmounts = [i64; 16]; impl EquityFromSnapshot { fn run(args: EquityFromSnapshotArgs) -> anyhow::Result<()> { + let late_changes = late_deposits_withdrawals(&args.late_changes)?; + let data = DataSource::new(args.sqlite.clone())?; let group = data.load_group(args.group)?; @@ -156,6 +206,8 @@ impl EquityFromSnapshot { let mut account_equities: Vec<(Pubkey, Pubkey, AccountTokenAmounts)> = Vec::with_capacity(account_addresses.len()); + + // get the snapshot account equities for account_address in account_addresses { let equity_opt = ctx .account_equity(account_address) @@ -167,6 +219,59 @@ impl EquityFromSnapshot { account_equities.push((account_address, owner, equity)); } + // apply the late deposits/withdrawals + for &(address, owner, token_index, change_native) in late_changes.iter() { + let change_usd = + (I80F48::from(change_native) * cache_price(&cache, token_index)).to_num(); + // slow, but just ran a handful times + let account_opt = account_equities.iter_mut().find(|(a, _, _)| a == &address); + if let Some((_, _, equity)) = account_opt { + equity[token_index] += change_usd; + } else { + assert!(change_usd > 0); + let mut equity = AccountTokenAmounts::default(); + equity[token_index] = change_usd; + account_equities.push((address, owner, equity)); + } + } + + // Some accounts already cached out on a MNGO PERP position that started to be valuable after the + // snapshot was taken, no reimbursements + { + let odd_accounts = [ + "9A6YVfa66kBEeCLtt6wyqdmjpib7UrybA5mHr3X3kyvf", + "AEYWfmFVu1huajTkT3UUbvhCZx92kZXwgpWgrMtocnzv", + "AZVbGBJ1DU2RnZNhZ72fcpo191DX3k1uyqDiPiaWoF1q", + "C19JAyRLUjkTWmj9VpYu5eVVCbSXcbqqhyF5588ERSSf", + "C9rprN4zcP7Wx87UcbLarTEAGCmGiPZp8gaFXPhY9HYm", + ]; + for odd_one in odd_accounts { + let address = Pubkey::from_str(odd_one).unwrap(); + let (_, _, equity) = + account_equities.iter_mut().find(|(a, _, _)| a == &address).unwrap(); + assert!(late_changes.iter().any(|(a, _, _, c)| a == &address && *c < 0)); + let total = equity.iter().sum::(); + assert!(total < 0); + assert!(total > -10_000_000_000); // none of these was bigger than 10000 USD + *equity = AccountTokenAmounts::default(); + } + } + + // Some accounts withdrew everything after the snapshot was taken. When doing that they + // probably withdrew a tiny bit more than their snapshot equity due to interest. + // These accounts have already cached out, no need to reimburse. + for (address, _, equity) in account_equities.iter_mut() { + let total = equity.iter().sum::(); + if total >= 0 { + continue; + } + assert!(late_changes.iter().any(|(a, _, _, c)| a == address && *c < 0)); + assert!(equity.iter().sum::() < 0); + // only up to -10 USD is expected, otherwise investigate manually! + assert!(equity.iter().sum::() > -10_000_000); + *equity = AccountTokenAmounts::default(); + } + let token_names: [&str; 16] = [ "MNGO", "BTC", "ETH", "SOL", "USDT", "SRM", "RAY", "COPE", "FTT", "ADA", "MSOL", "BNB", "AVAX", "LUNA", "GMT", "USDC", @@ -180,8 +285,6 @@ impl EquityFromSnapshot { true, ]; - //println!("{:?}", ctx.cache.price_cache.iter().map(|c| c.price).collect::>()); - // TODO: tentative numbers from "Repay bad Debt #2" proposal let available_native_amounts: [u64; 15] = [ 32409565000000, @@ -201,8 +304,11 @@ impl EquityFromSnapshot { 152843000000000, ]; + // Token prices at time of reimbursement + // Note that user equity at snapshot time is computed from the prices from the + // mango cache in the snapshot. let reimbursement_prices: [I80F48; 16] = [ - // TODO: bad prices + // TODO: bad prices, must be updated when time comes! I80F48::from_num(0.038725), I80F48::from_num(19036.47), I80F48::from_num(1280.639999999999997), @@ -221,6 +327,7 @@ impl EquityFromSnapshot { I80F48::ONE, ]; + // USD amounts in each token that can be used for reimbursement let available_amounts: [u64; 15] = available_native_amounts .iter() .zip(reimbursement_prices.iter()) @@ -229,6 +336,7 @@ impl EquityFromSnapshot { .try_into() .unwrap(); + // Amounts each user should be reimbursed let mut reimburse_amounts = account_equities.clone(); // all the equity in unavailable tokens is just considered usdc @@ -291,6 +399,8 @@ impl EquityFromSnapshot { } // All tokens fine? Try reducing some random one, starting with USDC + // (mSOL is last because it looks like we will have a lot of it and want + // to prefer giving it out to users that had it before) for j in [15, 14, 13, 12, 11, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 10] { if equity[j] <= 0 { continue; @@ -313,7 +423,7 @@ impl EquityFromSnapshot { // now all reimburse_amounts are >= 0 // Do a pass where we scale down user reimbursement token amounts and instead - // reimburse with USDC if there's not enough tokens + // reimburse with USDC if there's not enough tokens to give out for i in 0..15 { if reimburse_totals[i] == 0 || reimburse_totals[i] == available_amounts[i] { continue; @@ -346,6 +456,10 @@ impl EquityFromSnapshot { } // Do passes where we scale up token reimbursement amounts to try to fully utilize funds + // + // The idea here is that we have say 1000 SOL but only need 500 SOL to reimburse. + // To leave the DAO with fewer SOL at the end we prefer to give people who already + // had some SOL more of it (and compensate by giving them less of another token). for _ in 0..100 { for i in 0..15 { if reimburse_totals[i] == 0 || reimburse_totals[i] == available_amounts[i] { @@ -387,7 +501,7 @@ impl EquityFromSnapshot { } } - // double check that user equity is unchanged + // Double check that total user equity is unchanged for ((_, ownerl, equity), (_, ownerr, reimburse)) in account_equities.iter().zip(reimburse_amounts.iter()) { @@ -432,7 +546,7 @@ impl EquityFromSnapshot { account_address: Pubkey, ) -> anyhow::Result> { if account_address - != Pubkey::from_str(&"3TXDBTHFwyKywjZj1vGdRVkrF5o4YZ1vZnMf3Hb9qALz").unwrap() + != Pubkey::from_str(&"rwxRFn2S1DHkbA8wiCDxzMRMncgjUaa4LiJTagvLBr9").unwrap() { //return Ok(None); } From b0d6fefeed1d2979de564f0d3db0bd3439075ec7 Mon Sep 17 00:00:00 2001 From: Christian Kamm Date: Fri, 14 Oct 2022 18:19:06 +0200 Subject: [PATCH 07/28] MNGO incentives and MNGO special handling --- cli/src/main.rs | 52 +++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 44 insertions(+), 8 deletions(-) diff --git a/cli/src/main.rs b/cli/src/main.rs index e12ec749..d73e9d78 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -197,7 +197,7 @@ impl EquityFromSnapshot { let data = DataSource::new(args.sqlite.clone())?; let group = data.load_group(args.group)?; - let cache = data.load_cache(group.mango_cache)?; + let mut cache = data.load_cache(group.mango_cache)?; let ctx = EquityFromSnapshot { args, data, group, cache }; @@ -327,6 +327,13 @@ impl EquityFromSnapshot { I80F48::ONE, ]; + // Fix the MNGO snapshot price to be the same as the reimbursement price. + // This does two things: + // - the MNGO-based equity will be converted back to MNGO tokens at the same price, + // allowing the token count to stay unchanged + // - if MNGO tokens must be used as assets, they're valued with the less favorable price + cache.price_cache[0].price = reimbursement_prices[0]; + // USD amounts in each token that can be used for reimbursement let available_amounts: [u64; 15] = available_native_amounts .iter() @@ -379,6 +386,7 @@ impl EquityFromSnapshot { let mut weighted_indexes = equity[0..15] .iter() .enumerate() + .skip(1) // skip MNGO .filter_map(|(i, v)| (*v > 0).then_some(i)) .filter_map(|i| { (available_amounts[i] < reimburse_totals[i]) @@ -401,7 +409,9 @@ impl EquityFromSnapshot { // All tokens fine? Try reducing some random one, starting with USDC // (mSOL is last because it looks like we will have a lot of it and want // to prefer giving it out to users that had it before) - for j in [15, 14, 13, 12, 11, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 10] { + // This list has MNGO last, meaning that Mango tokens are only used as + // an asset to offset a liability as last resort. + for j in [15, 14, 13, 12, 11, 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, 0] { if equity[j] <= 0 { continue; } @@ -424,7 +434,8 @@ impl EquityFromSnapshot { // Do a pass where we scale down user reimbursement token amounts and instead // reimburse with USDC if there's not enough tokens to give out - for i in 0..15 { + // Don't do it for 0 (MNGO). + for i in 1..15 { if reimburse_totals[i] == 0 || reimburse_totals[i] == available_amounts[i] { continue; } @@ -461,7 +472,7 @@ impl EquityFromSnapshot { // To leave the DAO with fewer SOL at the end we prefer to give people who already // had some SOL more of it (and compensate by giving them less of another token). for _ in 0..100 { - for i in 0..15 { + for i in 1..15 { if reimburse_totals[i] == 0 || reimburse_totals[i] == available_amounts[i] { continue; } @@ -483,7 +494,7 @@ impl EquityFromSnapshot { let new_amount: i64 = (I80F48::from(amount) * fraction).to_num(); let mut remaining_increase = new_amount - amount; // positive - for j in (0..16).rev() { + for j in (1..16).rev() { let other_amount = equity[j]; if (j != 15 && available_amounts[j] >= reimburse_totals[j]) || other_amount == 0 @@ -502,15 +513,28 @@ impl EquityFromSnapshot { } // Double check that total user equity is unchanged + let mut accounts_with_mngo = 0; + let mut accounts_with_mngo_unchanged = 0; for ((_, ownerl, equity), (_, ownerr, reimburse)) in account_equities.iter().zip(reimburse_amounts.iter()) { let eqsum = equity.iter().sum::(); let resum = reimburse.iter().sum::(); assert_eq!(eqsum, resum); + if equity[0] > 0 { + // MNGO amount can only go down + assert!(reimburse[0] <= equity[0]); + accounts_with_mngo += 1; + if reimburse[0] == equity[0] { + accounts_with_mngo_unchanged += 1; + } + } + assert_eq!(ownerl, ownerr); } + println!("account w mango: {accounts_with_mngo}, unchanged {accounts_with_mngo_unchanged}"); + for i in 0..15 { println!( "{}: available {}, used {}, left over {}", @@ -613,9 +637,21 @@ impl EquityFromSnapshot { // Sum up the perp position equity for oracle_index in 0..self.group.num_oracles { - if self.group.perp_markets[oracle_index].is_empty() - || !mango_account.perp_accounts[oracle_index].is_active() - { + if self.group.perp_markets[oracle_index].is_empty() { + continue; + } + + let mngo_index = 0; + let mngo = mango_account.perp_accounts[oracle_index].mngo_accrued; + equity[mngo_index] = equity[mngo_index] + .checked_add( + I80F48::from(mngo) + .checked_mul(self.cache.price_cache[mngo_index].price) + .unwrap(), + ) + .unwrap(); + + if !mango_account.perp_accounts[oracle_index].is_active() { continue; } let price = self.cache.price_cache[oracle_index].price; From 3d46b155513da68f0cbc4d3675be05b63551768e Mon Sep 17 00:00:00 2001 From: Christian Kamm Date: Sat, 15 Oct 2022 15:41:28 +0200 Subject: [PATCH 08/28] fixes after analysis - disable giving people more tokens, prefer USDC settlement - settle borrows against non-USDC preferably, to treat delta neutral positions more gracefully - add debug output --- cli/src/main.rs | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/cli/src/main.rs b/cli/src/main.rs index d73e9d78..e736ba71 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -204,6 +204,13 @@ impl EquityFromSnapshot { let account_addresses = ctx.data.mango_account_list(ctx.args.program, DataType::MangoAccount)?; + let token_names: [&str; 16] = [ + "MNGO", "BTC", "ETH", "SOL", "USDT", "SRM", "RAY", "COPE", "FTT", "ADA", "MSOL", "BNB", + "AVAX", "LUNA", "GMT", "USDC", + ]; + + println!("table,account,owner,{}", token_names.join(",")); + let mut account_equities: Vec<(Pubkey, Pubkey, AccountTokenAmounts)> = Vec::with_capacity(account_addresses.len()); @@ -217,6 +224,10 @@ impl EquityFromSnapshot { } let (owner, equity) = equity_opt.unwrap(); account_equities.push((account_address, owner, equity)); + println!( + "snapshot,{account_address},{owner},{}", + equity.iter().map(|v| v.to_string()).collect::>().join(",") + ); } // apply the late deposits/withdrawals @@ -235,6 +246,13 @@ impl EquityFromSnapshot { } } + for &(address, owner, equity) in account_equities.iter() { + println!( + "dep/with,{address},{owner},{}", + equity.iter().map(|v| v.to_string()).collect::>().join(",") + ); + } + // Some accounts already cached out on a MNGO PERP position that started to be valuable after the // snapshot was taken, no reimbursements { @@ -272,11 +290,6 @@ impl EquityFromSnapshot { *equity = AccountTokenAmounts::default(); } - let token_names: [&str; 16] = [ - "MNGO", "BTC", "ETH", "SOL", "USDT", "SRM", "RAY", "COPE", "FTT", "ADA", "MSOL", "BNB", - "AVAX", "LUNA", "GMT", "USDC", - ]; - let available_tokens: [bool; 15] = [ true, true, true, true, false, // usdt is gone true, true, false, // cope delisted @@ -411,7 +424,7 @@ impl EquityFromSnapshot { // to prefer giving it out to users that had it before) // This list has MNGO last, meaning that Mango tokens are only used as // an asset to offset a liability as last resort. - for j in [15, 14, 13, 12, 11, 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, 0] { + for j in [14, 13, 12, 11, 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, 15, 0] { if equity[j] <= 0 { continue; } @@ -471,7 +484,7 @@ impl EquityFromSnapshot { // The idea here is that we have say 1000 SOL but only need 500 SOL to reimburse. // To leave the DAO with fewer SOL at the end we prefer to give people who already // had some SOL more of it (and compensate by giving them less of another token). - for _ in 0..100 { + /*for _ in 0..100 { for i in 1..15 { if reimburse_totals[i] == 0 || reimburse_totals[i] == available_amounts[i] { continue; @@ -510,7 +523,7 @@ impl EquityFromSnapshot { } } } - } + }*/ // Double check that total user equity is unchanged let mut accounts_with_mngo = 0; @@ -547,10 +560,15 @@ impl EquityFromSnapshot { println!("USDC: used {}", reimburse_totals[15] / 1000000); println!("reimburse total {}", reimburse_totals.iter().sum::() / 1000000); - println!("account,owner,{}", token_names.join(",")); for (account, owner, amounts) in reimburse_amounts.iter() { println!( - "{account},{owner},{}", + "usd final,{account},{owner},{}", + amounts.iter().map(|v| v.to_string()).collect::>().join(",") + ); + } + for (account, owner, amounts) in reimburse_amounts.iter() { + println!( + "token final,{account},{owner},{}", amounts .iter() .enumerate() From 721e9b4dc4b2ba2cc9fbd7816338fa3f066f470f Mon Sep 17 00:00:00 2001 From: Christian Kamm Date: Sat, 15 Oct 2022 17:19:06 +0200 Subject: [PATCH 09/28] code cleanup --- cli/src/main.rs | 335 ++++++++++++++++++++++++++++-------------------- 1 file changed, 197 insertions(+), 138 deletions(-) diff --git a/cli/src/main.rs b/cli/src/main.rs index e736ba71..0869de27 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -175,34 +175,62 @@ fn late_deposits_withdrawals(filename: &str) -> anyhow::Result, group: MangoGroup, cache: MangoCache, } -fn cache_price(cache: &MangoCache, index: usize) -> I80F48 { - if index == QUOTE_INDEX { - I80F48::ONE - } else { - cache.price_cache[index].price - } -} - /// value of per-token equity in usd, ordered by mango group token index type AccountTokenAmounts = [i64; 16]; +#[derive(Clone, Debug)] +struct AccountData { + mango_account: Pubkey, + owner: Pubkey, + amounts: AccountTokenAmounts, +} + +fn pay_liab( + amounts: &mut AccountTokenAmounts, + liab: usize, + asset: usize, + amount: i64, + totals: &mut [u64; 16], +) { + assert!(liab != asset); + assert!(amount >= 0); + amounts[asset] -= amount; + assert!(amounts[asset] >= 0); + amounts[liab] += amount; + totals[asset] -= amount as u64; + // liabs weren't counted in totals! +} + +fn move_amount( + amounts: &mut AccountTokenAmounts, + from: usize, + to: usize, + amount: i64, + totals: &mut [u64; 16], +) { + assert!(from != to); + assert!(amount >= 0); + amounts[from] -= amount; + assert!(amounts[from] >= 0); + amounts[to] += amount; + totals[from] -= amount as u64; + totals[to] += amount as u64; +} + impl EquityFromSnapshot { fn run(args: EquityFromSnapshotArgs) -> anyhow::Result<()> { let late_changes = late_deposits_withdrawals(&args.late_changes)?; - let data = DataSource::new(args.sqlite.clone())?; let group = data.load_group(args.group)?; let mut cache = data.load_cache(group.mango_cache)?; - let ctx = EquityFromSnapshot { args, data, group, cache }; - - let account_addresses = - ctx.data.mango_account_list(ctx.args.program, DataType::MangoAccount)?; + let ctx = EquityFromSnapshot { args, data, late_changes, group, cache }; let token_names: [&str; 16] = [ "MNGO", "BTC", "ETH", "SOL", "USDT", "SRM", "RAY", "COPE", "FTT", "ADA", "MSOL", "BNB", @@ -211,84 +239,26 @@ impl EquityFromSnapshot { println!("table,account,owner,{}", token_names.join(",")); - let mut account_equities: Vec<(Pubkey, Pubkey, AccountTokenAmounts)> = - Vec::with_capacity(account_addresses.len()); - - // get the snapshot account equities - for account_address in account_addresses { - let equity_opt = ctx - .account_equity(account_address) - .context(format!("on account {}", account_address))?; - if equity_opt.is_none() { - continue; + let debug_print = |table: &str, data: &[AccountData]| { + for account in data.iter() { + println!( + "{table},{},{},{}", + account.mango_account, + account.owner, + account.amounts.iter().map(|v| v.to_string()).collect::>().join(",") + ); } - let (owner, equity) = equity_opt.unwrap(); - account_equities.push((account_address, owner, equity)); - println!( - "snapshot,{account_address},{owner},{}", - equity.iter().map(|v| v.to_string()).collect::>().join(",") - ); - } + }; - // apply the late deposits/withdrawals - for &(address, owner, token_index, change_native) in late_changes.iter() { - let change_usd = - (I80F48::from(change_native) * cache_price(&cache, token_index)).to_num(); - // slow, but just ran a handful times - let account_opt = account_equities.iter_mut().find(|(a, _, _)| a == &address); - if let Some((_, _, equity)) = account_opt { - equity[token_index] += change_usd; - } else { - assert!(change_usd > 0); - let mut equity = AccountTokenAmounts::default(); - equity[token_index] = change_usd; - account_equities.push((address, owner, equity)); - } - } + let mut account_equities = ctx.snapshot_account_equities()?; - for &(address, owner, equity) in account_equities.iter() { - println!( - "dep/with,{address},{owner},{}", - equity.iter().map(|v| v.to_string()).collect::>().join(",") - ); - } + debug_print("snapshot", &account_equities); - // Some accounts already cached out on a MNGO PERP position that started to be valuable after the - // snapshot was taken, no reimbursements - { - let odd_accounts = [ - "9A6YVfa66kBEeCLtt6wyqdmjpib7UrybA5mHr3X3kyvf", - "AEYWfmFVu1huajTkT3UUbvhCZx92kZXwgpWgrMtocnzv", - "AZVbGBJ1DU2RnZNhZ72fcpo191DX3k1uyqDiPiaWoF1q", - "C19JAyRLUjkTWmj9VpYu5eVVCbSXcbqqhyF5588ERSSf", - "C9rprN4zcP7Wx87UcbLarTEAGCmGiPZp8gaFXPhY9HYm", - ]; - for odd_one in odd_accounts { - let address = Pubkey::from_str(odd_one).unwrap(); - let (_, _, equity) = - account_equities.iter_mut().find(|(a, _, _)| a == &address).unwrap(); - assert!(late_changes.iter().any(|(a, _, _, c)| a == &address && *c < 0)); - let total = equity.iter().sum::(); - assert!(total < 0); - assert!(total > -10_000_000_000); // none of these was bigger than 10000 USD - *equity = AccountTokenAmounts::default(); - } - } + ctx.apply_late_deposits_withdrawals(&mut account_equities)?; - // Some accounts withdrew everything after the snapshot was taken. When doing that they - // probably withdrew a tiny bit more than their snapshot equity due to interest. - // These accounts have already cached out, no need to reimburse. - for (address, _, equity) in account_equities.iter_mut() { - let total = equity.iter().sum::(); - if total >= 0 { - continue; - } - assert!(late_changes.iter().any(|(a, _, _, c)| a == address && *c < 0)); - assert!(equity.iter().sum::() < 0); - // only up to -10 USD is expected, otherwise investigate manually! - assert!(equity.iter().sum::() > -10_000_000); - *equity = AccountTokenAmounts::default(); - } + debug_print("after dep/with", &account_equities); + + ctx.skip_accounts(&mut account_equities)?; let available_tokens: [bool; 15] = [ true, true, true, true, false, // usdt is gone @@ -359,21 +329,22 @@ impl EquityFromSnapshot { // Amounts each user should be reimbursed let mut reimburse_amounts = account_equities.clone(); - // all the equity in unavailable tokens is just considered usdc - for (_, _, equity) in reimburse_amounts.iter_mut() { + // All the equity in unavailable tokens - that means tokens that are not available for + // reimbursing people with - is just considered usdc + for account in reimburse_amounts.iter_mut() { for i in 0..15 { if !available_tokens[i] { - let amount = equity[i]; - equity[QUOTE_INDEX] += amount; - equity[i] = 0; + let amount = account.amounts[i]; + account.amounts[QUOTE_INDEX] += amount; + account.amounts[i] = 0; } } } // basic total amount of all positive equities per token (liabs handled later) let mut reimburse_totals = [0u64; 16]; - for (_, _, equity) in account_equities.iter() { - for (i, value) in equity.iter().enumerate() { + for account in account_equities.iter() { + for (i, value) in account.amounts.iter().enumerate() { if *value >= 0 { reimburse_totals[i] += *value as u64; } @@ -386,9 +357,9 @@ impl EquityFromSnapshot { // resolve user's liabilities with their assets in a way that aims to bring the // needed token amounts <= what's available let mut reimburse_amounts = account_equities.clone(); - for (_, _, equity) in reimburse_amounts.iter_mut() { + for AccountData { amounts, .. } in reimburse_amounts.iter_mut() { for i in 0..16 { - let mut value = equity[i]; + let mut value = amounts[i]; // positive amounts get reimbursed if value >= 0 { continue; @@ -396,7 +367,7 @@ impl EquityFromSnapshot { // Negative amounts must be settled against other token balances // This is using a greedy strategy, reducing the most requested token first - let mut weighted_indexes = equity[0..15] + let mut weighted_indexes = amounts[0..15] .iter() .enumerate() .skip(1) // skip MNGO @@ -409,10 +380,9 @@ impl EquityFromSnapshot { weighted_indexes.sort_by(|a, b| a.1.cmp(&b.1)); for &(j, _) in weighted_indexes.iter() { - let start = equity[j]; + let start = amounts[j]; let amount = if start + value >= 0 { -value } else { start }; - equity[j] -= amount; - reimburse_totals[j] -= amount as u64; + pay_liab(amounts, i, j, amount, &mut reimburse_totals); value += amount; if value >= 0 { break; @@ -425,13 +395,12 @@ impl EquityFromSnapshot { // This list has MNGO last, meaning that Mango tokens are only used as // an asset to offset a liability as last resort. for j in [14, 13, 12, 11, 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, 15, 0] { - if equity[j] <= 0 { + if amounts[j] <= 0 { continue; } - let start = equity[j]; + let start = amounts[j]; let amount = if start + value >= 0 { -value } else { start }; - equity[j] -= amount; - reimburse_totals[j] -= amount as u64; + pay_liab(amounts, i, j, amount, &mut reimburse_totals); value += amount; if value >= 0 { break; @@ -439,7 +408,7 @@ impl EquityFromSnapshot { } assert!(value == 0); - equity[i] = 0; + assert!(amounts[i] == 0); } } @@ -458,24 +427,21 @@ impl EquityFromSnapshot { } // Scale down token reimbursements and replace them with USDC reimbursements - for (_, _, equity) in reimburse_amounts.iter_mut() { - let amount = &mut equity[i]; - assert!(*amount >= 0); - if *amount == 0 { + for AccountData { amounts, .. } in reimburse_amounts.iter_mut() { + let start_amount = amounts[i]; + assert!(start_amount >= 0); + if start_amount == 0 { continue; } - let new_amount: i64 = (I80F48::from(*amount) * fraction).to_num(); - let decrease = (*amount - new_amount) as u64; - *amount = new_amount; - reimburse_totals[i] -= decrease; + let new_amount: i64 = (I80F48::from(start_amount) * fraction).to_num(); + let amount = start_amount - new_amount; let target = if i == 3 { 10 // SOL -> mSOL } else { QUOTE_INDEX }; - equity[target] += decrease as i64; - reimburse_totals[target] += decrease; + move_amount(amounts, i, target, amount, &mut reimburse_totals); } } @@ -528,22 +494,23 @@ impl EquityFromSnapshot { // Double check that total user equity is unchanged let mut accounts_with_mngo = 0; let mut accounts_with_mngo_unchanged = 0; - for ((_, ownerl, equity), (_, ownerr, reimburse)) in - account_equities.iter().zip(reimburse_amounts.iter()) - { - let eqsum = equity.iter().sum::(); - let resum = reimburse.iter().sum::(); + for (a_equity, a_reimburse) in account_equities.iter().zip(reimburse_amounts.iter()) { + let eqsum = a_equity.amounts.iter().sum::(); + let resum = a_reimburse.amounts.iter().sum::(); assert_eq!(eqsum, resum); - if equity[0] > 0 { + + let mngo_equity = a_equity.amounts[0]; + let mngo_reimburse = a_reimburse.amounts[0]; + if mngo_equity > 0 { // MNGO amount can only go down - assert!(reimburse[0] <= equity[0]); + assert!(mngo_reimburse <= mngo_equity); accounts_with_mngo += 1; - if reimburse[0] == equity[0] { + if mngo_reimburse == mngo_equity { accounts_with_mngo_unchanged += 1; } } - assert_eq!(ownerl, ownerr); + assert_eq!(a_equity.owner, a_reimburse.owner); } println!("account w mango: {accounts_with_mngo}, unchanged {accounts_with_mngo_unchanged}"); @@ -560,16 +527,14 @@ impl EquityFromSnapshot { println!("USDC: used {}", reimburse_totals[15] / 1000000); println!("reimburse total {}", reimburse_totals.iter().sum::() / 1000000); - for (account, owner, amounts) in reimburse_amounts.iter() { - println!( - "usd final,{account},{owner},{}", - amounts.iter().map(|v| v.to_string()).collect::>().join(",") - ); - } - for (account, owner, amounts) in reimburse_amounts.iter() { + debug_print("usd final", &reimburse_amounts); + + for a in reimburse_amounts.iter() { println!( - "token final,{account},{owner},{}", - amounts + "token final,{},{},{}", + a.mango_account, + a.owner, + a.amounts .iter() .enumerate() .map(|(index, v)| (I80F48::from(*v) / reimbursement_prices[index]) @@ -583,6 +548,102 @@ impl EquityFromSnapshot { Ok(()) } + fn snapshot_price(&self, index: usize) -> I80F48 { + if index == QUOTE_INDEX { + I80F48::ONE + } else { + self.cache.price_cache[index].price + } + } + + fn snapshot_account_equities(&self) -> anyhow::Result> { + let account_addresses = + self.data.mango_account_list(self.args.program, DataType::MangoAccount)?; + + let mut account_equities: Vec = Vec::with_capacity(account_addresses.len()); // get the snapshot account equities + for mango_account in account_addresses { + let equity_opt = self + .account_equity(mango_account) + .context(format!("on account {}", mango_account))?; + if equity_opt.is_none() { + continue; + } + let (owner, amounts) = equity_opt.unwrap(); + account_equities.push(AccountData { mango_account, owner, amounts }); + } + + Ok(account_equities) + } + + fn apply_late_deposits_withdrawals( + &self, + account_equities: &mut Vec, + ) -> anyhow::Result<()> { + // apply the late deposits/withdrawals + for &(mango_account, owner, token_index, change_native) in self.late_changes.iter() { + let change_usd = + (I80F48::from(change_native) * self.snapshot_price(token_index)).to_num(); + // slow, but just ran a handful times + let account_opt = + account_equities.iter_mut().find(|a| a.mango_account == mango_account); + if let Some(account) = account_opt { + account.amounts[token_index] += change_usd; + } else { + assert!(change_usd > 0); + let mut amounts = AccountTokenAmounts::default(); + amounts[token_index] = change_usd; + account_equities.push(AccountData { mango_account, owner, amounts }); + } + } + + Ok(()) + } + + fn skip_accounts(&self, account_equities: &mut Vec) -> anyhow::Result<()> { + // Some accounts already cached out on a MNGO PERP position that started to be valuable after the + // snapshot was taken, no reimbursements + { + let odd_accounts = [ + "9A6YVfa66kBEeCLtt6wyqdmjpib7UrybA5mHr3X3kyvf", + "AEYWfmFVu1huajTkT3UUbvhCZx92kZXwgpWgrMtocnzv", + "AZVbGBJ1DU2RnZNhZ72fcpo191DX3k1uyqDiPiaWoF1q", + "C19JAyRLUjkTWmj9VpYu5eVVCbSXcbqqhyF5588ERSSf", + "C9rprN4zcP7Wx87UcbLarTEAGCmGiPZp8gaFXPhY9HYm", + ]; + for odd_one in odd_accounts { + let address = Pubkey::from_str(odd_one).unwrap(); + let account = + account_equities.iter_mut().find(|a| a.mango_account == address).unwrap(); + assert!(self.late_changes.iter().any(|(a, _, _, c)| a == &address && *c < 0)); + let total = account.amounts.iter().sum::(); + assert!(total < 0); + assert!(total > -10_000_000_000); // none of these was bigger than 10000 USD + account.amounts = AccountTokenAmounts::default(); + } + } + + // Some accounts withdrew everything after the snapshot was taken. When doing that they + // probably withdrew a tiny bit more than their snapshot equity due to interest. + // These accounts have already cached out, no need to reimburse. + for account in account_equities.iter_mut() { + let equity = &mut account.amounts; + let total = equity.iter().sum::(); + if total >= 0 { + continue; + } + assert!(self + .late_changes + .iter() + .any(|(a, _, _, c)| a == &account.mango_account && *c < 0)); + assert!(equity.iter().sum::() < 0); + // only up to -10 USD is expected, otherwise investigate manually! + assert!(equity.iter().sum::() > -10_000_000); + *equity = AccountTokenAmounts::default(); + } + + Ok(()) + } + fn account_equity( &self, account_address: Pubkey, @@ -614,7 +675,7 @@ impl EquityFromSnapshot { if self.group.spot_markets[oracle_index].is_empty() { continue; } - let price = self.cache.price_cache[oracle_index].price; + let price = self.snapshot_price(oracle_index); let bank_cache = &self.cache.root_bank_cache[oracle_index]; let net = mango_account.get_net(bank_cache, oracle_index); let net_usd = net.checked_mul(price).unwrap(); @@ -631,7 +692,7 @@ impl EquityFromSnapshot { if oo_address == Pubkey::default() { continue; } - let price = self.cache.price_cache[oracle_index].price; + let price = self.snapshot_price(oracle_index); let oo_maybe = self.data.load_open_orders(oo_address); if oo_maybe.is_err() { println!( @@ -663,16 +724,14 @@ impl EquityFromSnapshot { let mngo = mango_account.perp_accounts[oracle_index].mngo_accrued; equity[mngo_index] = equity[mngo_index] .checked_add( - I80F48::from(mngo) - .checked_mul(self.cache.price_cache[mngo_index].price) - .unwrap(), + I80F48::from(mngo).checked_mul(self.snapshot_price(mngo_index)).unwrap(), ) .unwrap(); if !mango_account.perp_accounts[oracle_index].is_active() { continue; } - let price = self.cache.price_cache[oracle_index].price; + let price = self.snapshot_price(oracle_index); let pmi = &self.group.perp_markets[oracle_index]; let pmc = &self.cache.perp_market_cache[oracle_index]; let pa = &mango_account.perp_accounts[oracle_index]; From 02c8d9c0bbc4882dd1a5df07c15d012afd378446 Mon Sep 17 00:00:00 2001 From: Christian Kamm Date: Sat, 15 Oct 2022 22:27:31 +0200 Subject: [PATCH 10/28] Fix bug and comment --- cli/src/main.rs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/cli/src/main.rs b/cli/src/main.rs index 0869de27..b0336a75 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -343,7 +343,7 @@ impl EquityFromSnapshot { // basic total amount of all positive equities per token (liabs handled later) let mut reimburse_totals = [0u64; 16]; - for account in account_equities.iter() { + for account in reimburse_amounts.iter() { for (i, value) in account.amounts.iter().enumerate() { if *value >= 0 { reimburse_totals[i] += *value as u64; @@ -356,7 +356,6 @@ impl EquityFromSnapshot { // resolve user's liabilities with their assets in a way that aims to bring the // needed token amounts <= what's available - let mut reimburse_amounts = account_equities.clone(); for AccountData { amounts, .. } in reimburse_amounts.iter_mut() { for i in 0..16 { let mut value = amounts[i]; @@ -389,11 +388,14 @@ impl EquityFromSnapshot { } } - // All tokens fine? Try reducing some random one, starting with USDC - // (mSOL is last because it looks like we will have a lot of it and want - // to prefer giving it out to users that had it before) - // This list has MNGO last, meaning that Mango tokens are only used as - // an asset to offset a liability as last resort. + // Otherwise settle against some other token with positive balance. + // + // mSOL is third to last because it looks like we will have a lot of it and want + // to prefer giving it out to users. + // USDC is after tokens, because settling tokens first leads to better results + // (consider delta-neutral positions) + // MNGO is last, meaning that Mango tokens are only used as an asset to offset a + // liability as last resort, because we force it to a bad price. for j in [14, 13, 12, 11, 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, 15, 0] { if amounts[j] <= 0 { continue; From 2e4ed12c96612ce0559ee02f113bc763f6547839 Mon Sep 17 00:00:00 2001 From: Christian Kamm Date: Sun, 16 Oct 2022 07:43:46 +0200 Subject: [PATCH 11/28] Clarify that account skipping is about negative equity --- cli/src/main.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/cli/src/main.rs b/cli/src/main.rs index b0336a75..1163890d 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -258,7 +258,7 @@ impl EquityFromSnapshot { debug_print("after dep/with", &account_equities); - ctx.skip_accounts(&mut account_equities)?; + ctx.skip_negative_equity_accounts(&mut account_equities)?; let available_tokens: [bool; 15] = [ true, true, true, true, false, // usdt is gone @@ -601,9 +601,12 @@ impl EquityFromSnapshot { Ok(()) } - fn skip_accounts(&self, account_equities: &mut Vec) -> anyhow::Result<()> { - // Some accounts already cached out on a MNGO PERP position that started to be valuable after the - // snapshot was taken, no reimbursements + fn skip_negative_equity_accounts( + &self, + account_equities: &mut Vec, + ) -> anyhow::Result<()> { + // Some accounts have negative equity because they already cashed out on a MNGO PERP position + // that started to be valuable after the snapshot was taken, skip them { let odd_accounts = [ "9A6YVfa66kBEeCLtt6wyqdmjpib7UrybA5mHr3X3kyvf", @@ -626,7 +629,7 @@ impl EquityFromSnapshot { // Some accounts withdrew everything after the snapshot was taken. When doing that they // probably withdrew a tiny bit more than their snapshot equity due to interest. - // These accounts have already cached out, no need to reimburse. + // These accounts have already cashed out, no need to reimburse. for account in account_equities.iter_mut() { let equity = &mut account.amounts; let total = equity.iter().sum::(); From 1cda61c99a6f87ffa9632287f6af552768b764e8 Mon Sep 17 00:00:00 2001 From: Christian Kamm Date: Sun, 16 Oct 2022 23:20:04 +0200 Subject: [PATCH 12/28] Use one table of token constants instead of multiple Also, don't merge USDT with USDC early, use the normal equity handling mechanism for it. Produces exactly the same output as 721e9b4dc4b2ba2cc9fbd7816338fa3f066f470f --- cli/src/main.rs | 259 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 172 insertions(+), 87 deletions(-) diff --git a/cli/src/main.rs b/cli/src/main.rs index 1163890d..d77e2a40 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -120,24 +120,163 @@ impl DataSource { } } -fn late_deposits_withdrawals(filename: &str) -> anyhow::Result> { - // mango token index and decimals - let tokens: HashMap<&str, (usize, i32)> = HashMap::from([ - ("MNGO", (0, 6)), - ("BTC", (1, 6)), - ("ETH", (2, 6)), - ("SOL", (3, 9)), - ("USDT", (4, 6)), - ("SRM", (5, 6)), - ("RAY", (6, 6)), - ("FTT", (8, 6)), - ("MSOL", (10, 9)), - ("BNB", (11, 8)), - ("AVAX", (12, 8)), - ("GMT", (14, 9)), - ("USDC", (15, 6)), - ]); +struct TokenInfo { + name: String, + index: usize, + decimals: i32, + available_native: u64, + reimbursement_price: I80F48, +} + +impl TokenInfo { + fn is_active(&self) -> bool { + self.decimals > 0 + } +} +struct Constants { + token_infos: Vec, +} + +impl Constants { + fn new() -> Self { + let out = Self { + // TODO: available_native needs to be double-checked + // TODO: reimbursement_price needs to be updated before execution! + // (Note that user equity at snapshot time is computed from the prices from the + // mango cache in the snapshot, not the reimbursement_price) + token_infos: vec![ + TokenInfo { + name: "MNGO".into(), + index: 0, + decimals: 6, + available_native: 32409565000000, + reimbursement_price: I80F48::from_num(0.038725), + }, + TokenInfo { + name: "BTC".into(), + index: 1, + decimals: 6, + available_native: 281498000, + reimbursement_price: I80F48::from_num(19036.47), + }, + TokenInfo { + name: "ETH".into(), + index: 2, + decimals: 6, + available_native: 226000000, + reimbursement_price: I80F48::from_num(1280.639999999999997), + }, + TokenInfo { + name: "SOL".into(), + index: 3, + decimals: 9, + available_native: 761577910000000, + reimbursement_price: I80F48::from_num(0.031244633849997), + }, + TokenInfo { + name: "USDT".into(), + index: 4, + decimals: 6, + available_native: 0, + reimbursement_price: I80F48::from_num(0.999905), + }, + TokenInfo { + name: "SRM".into(), + index: 5, + decimals: 6, + available_native: 2354260000000, + reimbursement_price: I80F48::from_num(0.74051845), + }, + TokenInfo { + name: "RAY".into(), + index: 6, + decimals: 6, + available_native: 98295000000, + reimbursement_price: I80F48::from_num(0.511599999999998), + }, + TokenInfo { + name: "COPE".into(), + index: 7, + decimals: i32::MIN, + available_native: 0, + reimbursement_price: I80F48::MIN, + }, + TokenInfo { + name: "FTT".into(), + index: 8, + decimals: 6, + available_native: 11774000000, + reimbursement_price: I80F48::from_num(23.248483429999997), + }, + TokenInfo { + name: "ADA".into(), + index: 9, + decimals: i32::MIN, + available_native: 0, + reimbursement_price: I80F48::MIN, + }, + TokenInfo { + name: "MSOL".into(), + index: 10, + decimals: 9, + available_native: 799155000000000, + reimbursement_price: I80F48::from_num(0.033400008119997), + }, + TokenInfo { + name: "BNB".into(), + index: 11, + decimals: 8, + available_native: 60800000000, + reimbursement_price: I80F48::from_num(2.7067999025), + }, + TokenInfo { + name: "AVAX".into(), + index: 12, + decimals: 8, + available_native: 180900000000, + reimbursement_price: I80F48::from_num(0.159774020999997), + }, + TokenInfo { + name: "LUNA".into(), + index: 13, + decimals: i32::MIN, + available_native: 0, + reimbursement_price: I80F48::MIN, + }, + TokenInfo { + name: "GMT".into(), + index: 14, + decimals: 9, + available_native: 152843000000000, + reimbursement_price: I80F48::from_num(0.000636922499996), + }, + TokenInfo { + name: "USDC".into(), + index: 15, + decimals: 6, + available_native: u64::MAX, + reimbursement_price: I80F48::ONE, + }, + ], + }; + assert!(out.token_infos.iter().map(|ti| ti.index).eq(0..16)); + out + } + + fn token_info_by_name(&self, name: &str) -> Option<&TokenInfo> { + self.token_infos.iter().find(|ti| ti.name == name) + } + + fn token_names(&self) -> Vec { + self.token_infos.iter().map(|ti| ti.name.clone()).collect() + } +} + +fn late_deposits_withdrawals( + filename: &str, + constants: &Constants, +) -> anyhow::Result> { let mut list = Vec::new(); use std::io::{BufRead, BufReader}; @@ -157,16 +296,16 @@ fn late_deposits_withdrawals(filename: &str) -> anyhow::Result anyhow::Result<()> { - let late_changes = late_deposits_withdrawals(&args.late_changes)?; + let constants = Constants::new(); + let late_changes = late_deposits_withdrawals(&args.late_changes, &constants)?; let data = DataSource::new(args.sqlite.clone())?; let group = data.load_group(args.group)?; @@ -232,10 +372,7 @@ impl EquityFromSnapshot { let ctx = EquityFromSnapshot { args, data, late_changes, group, cache }; - let token_names: [&str; 16] = [ - "MNGO", "BTC", "ETH", "SOL", "USDT", "SRM", "RAY", "COPE", "FTT", "ADA", "MSOL", "BNB", - "AVAX", "LUNA", "GMT", "USDC", - ]; + let token_names = constants.token_names(); println!("table,account,owner,{}", token_names.join(",")); @@ -260,68 +397,18 @@ impl EquityFromSnapshot { ctx.skip_negative_equity_accounts(&mut account_equities)?; - let available_tokens: [bool; 15] = [ - true, true, true, true, false, // usdt is gone - true, true, false, // cope delisted - true, false, // no spot ada - true, true, true, false, // luna delisted - true, - ]; - - // TODO: tentative numbers from "Repay bad Debt #2" proposal - let available_native_amounts: [u64; 15] = [ - 32409565000000, - 281498000, - 226000000, - 761577910000000, - 0, - 2354260000000, - 98295000000, - 0, - 11774000000, - 0, - 799155000000000, - 60800000000, - 180900000000, - 0, - 152843000000000, - ]; - - // Token prices at time of reimbursement - // Note that user equity at snapshot time is computed from the prices from the - // mango cache in the snapshot. - let reimbursement_prices: [I80F48; 16] = [ - // TODO: bad prices, must be updated when time comes! - I80F48::from_num(0.038725), - I80F48::from_num(19036.47), - I80F48::from_num(1280.639999999999997), - I80F48::from_num(0.031244633849997), - I80F48::from_num(0.999905), - I80F48::from_num(0.74051845), - I80F48::from_num(0.511599999999998), - I80F48::from_num(0.051956999999998), - I80F48::from_num(23.248483429999997), - I80F48::from_num(0.393549989999997), - I80F48::from_num(0.033400008119997), - I80F48::from_num(2.7067999025), - I80F48::from_num(0.159774020999997), - I80F48::from_num(0.000156989999997), - I80F48::from_num(0.000636922499996), - I80F48::ONE, - ]; - // Fix the MNGO snapshot price to be the same as the reimbursement price. // This does two things: // - the MNGO-based equity will be converted back to MNGO tokens at the same price, // allowing the token count to stay unchanged // - if MNGO tokens must be used as assets, they're valued with the less favorable price - cache.price_cache[0].price = reimbursement_prices[0]; + cache.price_cache[0].price = + constants.token_info_by_name("MNGO").unwrap().reimbursement_price; // USD amounts in each token that can be used for reimbursement - let available_amounts: [u64; 15] = available_native_amounts + let available_amounts: [u64; 15] = constants.token_infos[0..15] .iter() - .zip(reimbursement_prices.iter()) - .map(|(&native, &price)| (I80F48::from(native) * price).to_num()) + .map(|ti| (I80F48::from(ti.available_native) * ti.reimbursement_price).to_num()) .collect::>() .try_into() .unwrap(); @@ -329,14 +416,11 @@ impl EquityFromSnapshot { // Amounts each user should be reimbursed let mut reimburse_amounts = account_equities.clone(); - // All the equity in unavailable tokens - that means tokens that are not available for - // reimbursing people with - is just considered usdc + // Verify that equity for inactive tokens is zero for account in reimburse_amounts.iter_mut() { - for i in 0..15 { - if !available_tokens[i] { - let amount = account.amounts[i]; - account.amounts[QUOTE_INDEX] += amount; - account.amounts[i] = 0; + for ti in constants.token_infos.iter() { + if !ti.is_active() { + assert_eq!(account.amounts[ti.index], 0); } } } @@ -539,7 +623,8 @@ impl EquityFromSnapshot { a.amounts .iter() .enumerate() - .map(|(index, v)| (I80F48::from(*v) / reimbursement_prices[index]) + .map(|(index, v)| (I80F48::from(*v) + / constants.token_infos[index].reimbursement_price) .floor() .to_string()) .collect::>() From 84266e68bba3381de4674816c5550b08f385cab3 Mon Sep 17 00:00:00 2001 From: Christian Kamm Date: Mon, 17 Oct 2022 09:47:20 +0200 Subject: [PATCH 13/28] Allow for csv and binary output No change in computed values --- cli/src/main.rs | 132 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 100 insertions(+), 32 deletions(-) diff --git a/cli/src/main.rs b/cli/src/main.rs index d77e2a40..272402c9 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -1,11 +1,12 @@ use anyhow::Context; -use clap::{Args, Parser, Subcommand}; +use clap::{Args, Parser, Subcommand, ValueEnum}; use fixed::types::I80F48; use mango::state::*; use mango_common::*; use serum_dex::state::OpenOrders; use solana_sdk::pubkey::Pubkey; -use std::collections::HashMap; +use std::fs::File; +use std::io::Write; use std::mem::size_of; use std::str::FromStr; @@ -16,12 +17,27 @@ struct Cli { command: Command, } +#[derive(ValueEnum, Clone, Copy, Debug)] +enum OutType { + Csv, + Binary, +} + #[derive(Args, Debug, Clone)] struct EquityFromSnapshotArgs { - sqlite: String, + #[arg(long)] + snapshot: String, + #[arg(long)] late_changes: String, + #[arg(long)] program: Pubkey, + #[arg(long)] group: Pubkey, + + #[arg(long)] + outtype: OutType, + #[arg(long)] + outfile: String, } #[derive(Subcommand, Debug, Clone)] @@ -319,6 +335,53 @@ struct EquityFromSnapshot { cache: MangoCache, } +#[derive(bytemuck::Pod, bytemuck::Zeroable, Clone, Copy)] +#[repr(C)] +struct BinaryRow { + owner: Pubkey, + amounts: [u64; 16], +} + +struct OutWriter { + file: File, + outtype: OutType, +} + +impl OutWriter { + fn new(outfile: &str, outtype: OutType) -> Self { + let file = File::create(outfile).unwrap(); + Self { file, outtype } + } + + fn write(&mut self, account: &AccountData) { + match self.outtype { + OutType::Csv => { + write!( + &mut self.file, + "{},{},{}\n", + account.mango_account, + account.owner, + account.amounts.iter().map(|v| v.to_string()).collect::>().join(",") + ) + .unwrap(); + } + OutType::Binary => { + let row = BinaryRow { + owner: account.owner, + amounts: account + .amounts + .iter() + .map(|&v| v.try_into().unwrap()) + .collect::>() + .try_into() + .unwrap(), + }; + self.file.write_all(bytemuck::bytes_of(&row)).unwrap(); + } + } + } +} + /// value of per-token equity in usd, ordered by mango group token index type AccountTokenAmounts = [i64; 16]; @@ -365,10 +428,23 @@ impl EquityFromSnapshot { fn run(args: EquityFromSnapshotArgs) -> anyhow::Result<()> { let constants = Constants::new(); let late_changes = late_deposits_withdrawals(&args.late_changes, &constants)?; - let data = DataSource::new(args.sqlite.clone())?; + let data = DataSource::new(args.snapshot.clone())?; + + let mut outwriter = OutWriter::new(&args.outfile, args.outtype); let group = data.load_group(args.group)?; - let mut cache = data.load_cache(group.mango_cache)?; + + let cache = { + let mut cache = data.load_cache(group.mango_cache)?; + // Fix the MNGO snapshot price to be the same as the reimbursement price. + // This does two things: + // - the MNGO-based equity will be converted back to MNGO tokens at the same price, + // allowing the token count to stay unchanged + // - if MNGO tokens must be used as assets, they're valued with the less favorable price + cache.price_cache[0].price = + constants.token_info_by_name("MNGO").unwrap().reimbursement_price; + cache + }; let ctx = EquityFromSnapshot { args, data, late_changes, group, cache }; @@ -387,23 +463,19 @@ impl EquityFromSnapshot { } }; - let mut account_equities = ctx.snapshot_account_equities()?; + let account_equities = { + let mut equities = ctx.snapshot_account_equities()?; - debug_print("snapshot", &account_equities); + debug_print("snapshot", &equities); - ctx.apply_late_deposits_withdrawals(&mut account_equities)?; + ctx.apply_late_deposits_withdrawals(&mut equities)?; - debug_print("after dep/with", &account_equities); + debug_print("after dep/with", &equities); - ctx.skip_negative_equity_accounts(&mut account_equities)?; + ctx.skip_negative_equity_accounts(&mut equities)?; - // Fix the MNGO snapshot price to be the same as the reimbursement price. - // This does two things: - // - the MNGO-based equity will be converted back to MNGO tokens at the same price, - // allowing the token count to stay unchanged - // - if MNGO tokens must be used as assets, they're valued with the less favorable price - cache.price_cache[0].price = - constants.token_info_by_name("MNGO").unwrap().reimbursement_price; + equities + }; // USD amounts in each token that can be used for reimbursement let available_amounts: [u64; 15] = constants.token_infos[0..15] @@ -615,21 +687,17 @@ impl EquityFromSnapshot { debug_print("usd final", &reimburse_amounts); - for a in reimburse_amounts.iter() { - println!( - "token final,{},{},{}", - a.mango_account, - a.owner, - a.amounts - .iter() - .enumerate() - .map(|(index, v)| (I80F48::from(*v) - / constants.token_infos[index].reimbursement_price) - .floor() - .to_string()) - .collect::>() - .join(",") - ); + let mut reimburse_native = reimburse_amounts.clone(); + for a in reimburse_native.iter_mut() { + for (index, v) in a.amounts.iter_mut().enumerate() { + *v = (I80F48::from(*v) / constants.token_infos[index].reimbursement_price) + .floor() + .to_num(); + } + } + + for a in reimburse_native.iter() { + outwriter.write(a) } Ok(()) From 3ac2aeecb37b594a7edabed2fbbc59eaedca03ee Mon Sep 17 00:00:00 2001 From: Christian Kamm Date: Mon, 17 Oct 2022 11:14:38 +0200 Subject: [PATCH 14/28] Update available token balances Based on what's on 9mM6NfXauEFviFY1S1thbo7HXYNiSWSvwZEhguJw26wY --- cli/src/main.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/cli/src/main.rs b/cli/src/main.rs index 272402c9..c1ea920f 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -157,7 +157,6 @@ struct Constants { impl Constants { fn new() -> Self { let out = Self { - // TODO: available_native needs to be double-checked // TODO: reimbursement_price needs to be updated before execution! // (Note that user equity at snapshot time is computed from the prices from the // mango cache in the snapshot, not the reimbursement_price) @@ -166,14 +165,14 @@ impl Constants { name: "MNGO".into(), index: 0, decimals: 6, - available_native: 32409565000000, + available_native: 32904328899472, reimbursement_price: I80F48::from_num(0.038725), }, TokenInfo { name: "BTC".into(), index: 1, decimals: 6, - available_native: 281498000, + available_native: 281498500, reimbursement_price: I80F48::from_num(19036.47), }, TokenInfo { @@ -187,7 +186,7 @@ impl Constants { name: "SOL".into(), index: 3, decimals: 9, - available_native: 761577910000000, + available_native: 761577000000000, reimbursement_price: I80F48::from_num(0.031244633849997), }, TokenInfo { From f46a0f671a894952a8dfb55b5faac0c6da3b5cbf Mon Sep 17 00:00:00 2001 From: Christian Kamm Date: Mon, 17 Oct 2022 11:20:36 +0200 Subject: [PATCH 15/28] Update reimb prices for more realistic results Using coingecko as of 20221017 0920 UTC --- cli/src/main.rs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/cli/src/main.rs b/cli/src/main.rs index c1ea920f..7043821c 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -166,49 +166,49 @@ impl Constants { index: 0, decimals: 6, available_native: 32904328899472, - reimbursement_price: I80F48::from_num(0.038725), + reimbursement_price: I80F48::from_num(0.0236), }, TokenInfo { name: "BTC".into(), index: 1, decimals: 6, available_native: 281498500, - reimbursement_price: I80F48::from_num(19036.47), + reimbursement_price: I80F48::from_num(19272), }, TokenInfo { name: "ETH".into(), index: 2, decimals: 6, available_native: 226000000, - reimbursement_price: I80F48::from_num(1280.639999999999997), + reimbursement_price: I80F48::from_num(1309), }, TokenInfo { name: "SOL".into(), index: 3, decimals: 9, available_native: 761577000000000, - reimbursement_price: I80F48::from_num(0.031244633849997), + reimbursement_price: I80F48::from_num(0.03024), }, TokenInfo { name: "USDT".into(), index: 4, decimals: 6, available_native: 0, - reimbursement_price: I80F48::from_num(0.999905), + reimbursement_price: I80F48::from_num(1.00), }, TokenInfo { name: "SRM".into(), index: 5, decimals: 6, available_native: 2354260000000, - reimbursement_price: I80F48::from_num(0.74051845), + reimbursement_price: I80F48::from_num(0.7265), }, TokenInfo { name: "RAY".into(), index: 6, decimals: 6, available_native: 98295000000, - reimbursement_price: I80F48::from_num(0.511599999999998), + reimbursement_price: I80F48::from_num(0.4873), }, TokenInfo { name: "COPE".into(), @@ -222,7 +222,7 @@ impl Constants { index: 8, decimals: 6, available_native: 11774000000, - reimbursement_price: I80F48::from_num(23.248483429999997), + reimbursement_price: I80F48::from_num(23.78), }, TokenInfo { name: "ADA".into(), @@ -236,21 +236,21 @@ impl Constants { index: 10, decimals: 9, available_native: 799155000000000, - reimbursement_price: I80F48::from_num(0.033400008119997), + reimbursement_price: I80F48::from_num(0.03237), }, TokenInfo { name: "BNB".into(), index: 11, decimals: 8, available_native: 60800000000, - reimbursement_price: I80F48::from_num(2.7067999025), + reimbursement_price: I80F48::from_num(2.7149), }, TokenInfo { name: "AVAX".into(), index: 12, decimals: 8, available_native: 180900000000, - reimbursement_price: I80F48::from_num(0.159774020999997), + reimbursement_price: I80F48::from_num(0.1588), }, TokenInfo { name: "LUNA".into(), @@ -264,7 +264,7 @@ impl Constants { index: 14, decimals: 9, available_native: 152843000000000, - reimbursement_price: I80F48::from_num(0.000636922499996), + reimbursement_price: I80F48::from_num(0.0005814), }, TokenInfo { name: "USDC".into(), From e025016bffd66f3a158874c830308acff54c19e5 Mon Sep 17 00:00:00 2001 From: Christian Kamm Date: Mon, 17 Oct 2022 12:14:02 +0200 Subject: [PATCH 16/28] Use snapshot MNGO price for settling MNGO-PERP Perp positions should be settled at snapshot time. The new MNGO price should only be used for spot deposits/borrows. --- cli/src/main.rs | 65 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 51 insertions(+), 14 deletions(-) diff --git a/cli/src/main.rs b/cli/src/main.rs index 7043821c..f66bb3d9 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -332,6 +332,8 @@ struct EquityFromSnapshot { late_changes: Vec<(Pubkey, Pubkey, usize, i64)>, group: MangoGroup, cache: MangoCache, + constants: Constants, + mngo_perp_price: I80F48, } #[derive(bytemuck::Pod, bytemuck::Zeroable, Clone, Copy)] @@ -433,8 +435,9 @@ impl EquityFromSnapshot { let group = data.load_group(args.group)?; - let cache = { + let (cache, mngo_perp_price) = { let mut cache = data.load_cache(group.mango_cache)?; + let mngo_cache_price = cache.price_cache[0].price; // Fix the MNGO snapshot price to be the same as the reimbursement price. // This does two things: // - the MNGO-based equity will be converted back to MNGO tokens at the same price, @@ -442,13 +445,21 @@ impl EquityFromSnapshot { // - if MNGO tokens must be used as assets, they're valued with the less favorable price cache.price_cache[0].price = constants.token_info_by_name("MNGO").unwrap().reimbursement_price; - cache + (cache, mngo_cache_price) }; - let ctx = EquityFromSnapshot { args, data, late_changes, group, cache }; - let token_names = constants.token_names(); + let ctx = EquityFromSnapshot { + args, + data, + late_changes, + group, + cache, + constants, + mngo_perp_price, + }; + println!("table,account,owner,{}", token_names.join(",")); let debug_print = |table: &str, data: &[AccountData]| { @@ -477,7 +488,7 @@ impl EquityFromSnapshot { }; // USD amounts in each token that can be used for reimbursement - let available_amounts: [u64; 15] = constants.token_infos[0..15] + let available_amounts: [u64; 15] = ctx.constants.token_infos[0..15] .iter() .map(|ti| (I80F48::from(ti.available_native) * ti.reimbursement_price).to_num()) .collect::>() @@ -489,7 +500,7 @@ impl EquityFromSnapshot { // Verify that equity for inactive tokens is zero for account in reimburse_amounts.iter_mut() { - for ti in constants.token_infos.iter() { + for ti in ctx.constants.token_infos.iter() { if !ti.is_active() { assert_eq!(account.amounts[ti.index], 0); } @@ -689,7 +700,7 @@ impl EquityFromSnapshot { let mut reimburse_native = reimburse_amounts.clone(); for a in reimburse_native.iter_mut() { for (index, v) in a.amounts.iter_mut().enumerate() { - *v = (I80F48::from(*v) / constants.token_infos[index].reimbursement_price) + *v = (I80F48::from(*v) / ctx.constants.token_infos[index].reimbursement_price) .floor() .to_num(); } @@ -710,6 +721,14 @@ impl EquityFromSnapshot { } } + fn snapshot_price_perp(&self, index: usize) -> I80F48 { + if index == 0 { + self.mngo_perp_price + } else { + self.snapshot_price(index) + } + } + fn snapshot_account_equities(&self) -> anyhow::Result> { let account_addresses = self.data.mango_account_list(self.args.program, DataType::MangoAccount)?; @@ -779,6 +798,25 @@ impl EquityFromSnapshot { } } + // Negative equity accounts can happen due to us using a post-snapshot MNGO price + for account in account_equities.iter_mut() { + let equity = &mut account.amounts; + let total = equity.iter().sum::(); + if total >= 0 { + continue; + } + + let mngo_equity = I80F48::from(equity[0]); + let old_mngo_equity = mngo_equity / self.constants.token_infos[0].reimbursement_price + * I80F48::from_num(0.0387250); + let old_equity = old_mngo_equity.to_num::() + equity[1..].iter().sum::(); + + if old_equity >= 0 { + // negative equity due to changed MNGO price, is ok + *equity = AccountTokenAmounts::default(); + } + } + // Some accounts withdrew everything after the snapshot was taken. When doing that they // probably withdrew a tiny bit more than their snapshot equity due to interest. // These accounts have already cashed out, no need to reimburse. @@ -788,13 +826,12 @@ impl EquityFromSnapshot { if total >= 0 { continue; } - assert!(self - .late_changes - .iter() - .any(|(a, _, _, c)| a == &account.mango_account && *c < 0)); - assert!(equity.iter().sum::() < 0); + let had_withdrawal = + self.late_changes.iter().any(|(a, _, _, c)| a == &account.mango_account && *c < 0); + assert!(had_withdrawal); + // only up to -10 USD is expected, otherwise investigate manually! - assert!(equity.iter().sum::() > -10_000_000); + assert!(total > -10_000_000); *equity = AccountTokenAmounts::default(); } @@ -888,7 +925,7 @@ impl EquityFromSnapshot { if !mango_account.perp_accounts[oracle_index].is_active() { continue; } - let price = self.snapshot_price(oracle_index); + let price = self.snapshot_price_perp(oracle_index); let pmi = &self.group.perp_markets[oracle_index]; let pmc = &self.cache.perp_market_cache[oracle_index]; let pa = &mango_account.perp_accounts[oracle_index]; From e2ab4c54f080bbd7140843ce6f75b6d4bd26d44f Mon Sep 17 00:00:00 2001 From: Christian Kamm Date: Mon, 17 Oct 2022 12:15:14 +0200 Subject: [PATCH 17/28] Add a distribution-mode=usdc-only flag In this mode only USDC would be distributed --- cli/src/main.rs | 63 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 50 insertions(+), 13 deletions(-) diff --git a/cli/src/main.rs b/cli/src/main.rs index f66bb3d9..d3201728 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -23,6 +23,12 @@ enum OutType { Binary, } +#[derive(ValueEnum, Clone, Copy, Debug, PartialEq, Eq)] +enum DistributionMode { + UsdcOnly, + Tokens, +} + #[derive(Args, Debug, Clone)] struct EquityFromSnapshotArgs { #[arg(long)] @@ -38,6 +44,9 @@ struct EquityFromSnapshotArgs { outtype: OutType, #[arg(long)] outfile: String, + + #[arg(long, default_value = "tokens")] + distribution_mode: DistributionMode, } #[derive(Subcommand, Debug, Clone)] @@ -155,8 +164,8 @@ struct Constants { } impl Constants { - fn new() -> Self { - let out = Self { + fn new(mode: DistributionMode) -> Self { + let mut out = Self { // TODO: reimbursement_price needs to be updated before execution! // (Note that user equity at snapshot time is computed from the prices from the // mango cache in the snapshot, not the reimbursement_price) @@ -276,6 +285,13 @@ impl Constants { ], }; assert!(out.token_infos.iter().map(|ti| ti.index).eq(0..16)); + + if mode == DistributionMode::UsdcOnly { + for ti in out.token_infos[0..15].iter_mut() { + ti.available_native = 0; + } + } + out } @@ -381,6 +397,16 @@ impl OutWriter { } } } + + fn write_header(&mut self, constants: &Constants) { + match self.outtype { + OutType::Csv => { + write!(&mut self.file, "account,owner,{}", constants.token_names().join(",")) + .unwrap(); + } + OutType::Binary => {} + } + } } /// value of per-token equity in usd, ordered by mango group token index @@ -427,7 +453,7 @@ fn move_amount( impl EquityFromSnapshot { fn run(args: EquityFromSnapshotArgs) -> anyhow::Result<()> { - let constants = Constants::new(); + let constants = Constants::new(args.distribution_mode); let late_changes = late_deposits_withdrawals(&args.late_changes, &constants)?; let data = DataSource::new(args.snapshot.clone())?; @@ -584,8 +610,12 @@ impl EquityFromSnapshot { // Do a pass where we scale down user reimbursement token amounts and instead // reimburse with USDC if there's not enough tokens to give out - // Don't do it for 0 (MNGO). - for i in 1..15 { + let scale_down_iter = if ctx.args.distribution_mode == DistributionMode::UsdcOnly { + 0..15 + } else { + 1..15 // keep MNGO intact, DAO can provide extra from treasury + }; + for i in scale_down_iter { if reimburse_totals[i] == 0 || reimburse_totals[i] == available_amounts[i] { continue; } @@ -667,14 +697,16 @@ impl EquityFromSnapshot { let resum = a_reimburse.amounts.iter().sum::(); assert_eq!(eqsum, resum); - let mngo_equity = a_equity.amounts[0]; - let mngo_reimburse = a_reimburse.amounts[0]; - if mngo_equity > 0 { - // MNGO amount can only go down - assert!(mngo_reimburse <= mngo_equity); - accounts_with_mngo += 1; - if mngo_reimburse == mngo_equity { - accounts_with_mngo_unchanged += 1; + if ctx.args.distribution_mode == DistributionMode::Tokens { + let mngo_equity = a_equity.amounts[0]; + let mngo_reimburse = a_reimburse.amounts[0]; + if mngo_equity > 0 { + // MNGO amount can only go down + assert!(mngo_reimburse <= mngo_equity); + accounts_with_mngo += 1; + if mngo_reimburse == mngo_equity { + accounts_with_mngo_unchanged += 1; + } } } @@ -706,6 +738,11 @@ impl EquityFromSnapshot { } } + // drop any full-zero rows + reimburse_native = + reimburse_native.into_iter().filter(|a| a.amounts.iter().sum::() != 0).collect(); + + outwriter.write_header(&ctx.constants); for a in reimburse_native.iter() { outwriter.write(a) } From a0a5519722d951b83e94492839846c970eeb84ad Mon Sep 17 00:00:00 2001 From: Christian Kamm Date: Mon, 17 Oct 2022 14:24:12 +0200 Subject: [PATCH 18/28] Fixup headers --- cli/src/main.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/cli/src/main.rs b/cli/src/main.rs index d3201728..cbcca9d1 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -401,10 +401,13 @@ impl OutWriter { fn write_header(&mut self, constants: &Constants) { match self.outtype { OutType::Csv => { - write!(&mut self.file, "account,owner,{}", constants.token_names().join(",")) + write!(&mut self.file, "account,owner,{}\n", constants.token_names().join(",")) .unwrap(); } - OutType::Binary => {} + OutType::Binary => { + // buffer accounts have a 37 byte header -- add 3 bytes to 8-byte align the data + self.file.write_all(&[0u8; 3]).unwrap(); + } } } } From 13a3a7a59121853dc40343b7be21edc0a40fae58 Mon Sep 17 00:00:00 2001 From: Maximilian Schneider Date: Mon, 17 Oct 2022 14:42:36 +0200 Subject: [PATCH 19/28] set prices to 10/16/22 close from coingecko --- cli/src/main.rs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/cli/src/main.rs b/cli/src/main.rs index cbcca9d1..5b6dfa8a 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -175,49 +175,49 @@ impl Constants { index: 0, decimals: 6, available_native: 32904328899472, - reimbursement_price: I80F48::from_num(0.0236), + reimbursement_price: I80F48::from_num(0.02425361), }, TokenInfo { name: "BTC".into(), index: 1, decimals: 6, available_native: 281498500, - reimbursement_price: I80F48::from_num(19272), + reimbursement_price: I80F48::from_num(19272.92), }, TokenInfo { name: "ETH".into(), index: 2, decimals: 6, available_native: 226000000, - reimbursement_price: I80F48::from_num(1309), + reimbursement_price: I80F48::from_num(1306.94), }, TokenInfo { name: "SOL".into(), index: 3, decimals: 9, available_native: 761577000000000, - reimbursement_price: I80F48::from_num(0.03024), + reimbursement_price: I80F48::from_num(0.03017), }, TokenInfo { name: "USDT".into(), index: 4, decimals: 6, available_native: 0, - reimbursement_price: I80F48::from_num(1.00), + reimbursement_price: I80F48::from_num(1.000), }, TokenInfo { name: "SRM".into(), index: 5, decimals: 6, available_native: 2354260000000, - reimbursement_price: I80F48::from_num(0.7265), + reimbursement_price: I80F48::from_num(0.720998), }, TokenInfo { name: "RAY".into(), index: 6, decimals: 6, available_native: 98295000000, - reimbursement_price: I80F48::from_num(0.4873), + reimbursement_price: I80F48::from_num(0.491728), }, TokenInfo { name: "COPE".into(), @@ -231,7 +231,7 @@ impl Constants { index: 8, decimals: 6, available_native: 11774000000, - reimbursement_price: I80F48::from_num(23.78), + reimbursement_price: I80F48::from_num(23.73), }, TokenInfo { name: "ADA".into(), @@ -245,21 +245,21 @@ impl Constants { index: 10, decimals: 9, available_native: 799155000000000, - reimbursement_price: I80F48::from_num(0.03237), + reimbursement_price: I80F48::from_num(0.03227), }, TokenInfo { name: "BNB".into(), index: 11, decimals: 8, available_native: 60800000000, - reimbursement_price: I80F48::from_num(2.7149), + reimbursement_price: I80F48::from_num(2.7236), }, TokenInfo { name: "AVAX".into(), index: 12, decimals: 8, available_native: 180900000000, - reimbursement_price: I80F48::from_num(0.1588), + reimbursement_price: I80F48::from_num(0.1576), }, TokenInfo { name: "LUNA".into(), @@ -273,7 +273,7 @@ impl Constants { index: 14, decimals: 9, available_native: 152843000000000, - reimbursement_price: I80F48::from_num(0.0005814), + reimbursement_price: I80F48::from_num(0.000578548), }, TokenInfo { name: "USDC".into(), From a8a45377d90bf21b184f0b747dd92f0df4a03404 Mon Sep 17 00:00:00 2001 From: Christian Kamm Date: Mon, 17 Oct 2022 14:43:19 +0200 Subject: [PATCH 20/28] Add serum oo token amounts to redistributable tokens --- cli/src/main.rs | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/cli/src/main.rs b/cli/src/main.rs index 5b6dfa8a..006f7084 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -169,54 +169,57 @@ impl Constants { // TODO: reimbursement_price needs to be updated before execution! // (Note that user equity at snapshot time is computed from the prices from the // mango cache in the snapshot, not the reimbursement_price) + + // The available_native amounts are the sum of tokens recovered from the attacker + // (left) and tokens recovered from serum3 open orders (right). token_infos: vec![ TokenInfo { name: "MNGO".into(), index: 0, decimals: 6, - available_native: 32904328899472, + available_native: 32904328899472 + 17926416000000, reimbursement_price: I80F48::from_num(0.02425361), }, TokenInfo { name: "BTC".into(), index: 1, decimals: 6, - available_native: 281498500, + available_native: 281498500 + 15849599, reimbursement_price: I80F48::from_num(19272.92), }, TokenInfo { name: "ETH".into(), index: 2, decimals: 6, - available_native: 226000000, + available_native: 226000000 + 7431000, reimbursement_price: I80F48::from_num(1306.94), }, TokenInfo { name: "SOL".into(), index: 3, decimals: 9, - available_native: 761577000000000, + available_native: 761577000000000 + 4778699999999, reimbursement_price: I80F48::from_num(0.03017), }, TokenInfo { name: "USDT".into(), index: 4, decimals: 6, - available_native: 0, + available_native: 0 + 14646000000, reimbursement_price: I80F48::from_num(1.000), }, TokenInfo { name: "SRM".into(), index: 5, decimals: 6, - available_native: 2354260000000, + available_native: 2354260000000 + 10258200000, reimbursement_price: I80F48::from_num(0.720998), }, TokenInfo { name: "RAY".into(), index: 6, decimals: 6, - available_native: 98295000000, + available_native: 98295000000 + 10605100000, reimbursement_price: I80F48::from_num(0.491728), }, TokenInfo { @@ -230,7 +233,7 @@ impl Constants { name: "FTT".into(), index: 8, decimals: 6, - available_native: 11774000000, + available_native: 11774000000 + 214800000, reimbursement_price: I80F48::from_num(23.73), }, TokenInfo { @@ -244,21 +247,21 @@ impl Constants { name: "MSOL".into(), index: 10, decimals: 9, - available_native: 799155000000000, + available_native: 799155000000000 + 179378000000, reimbursement_price: I80F48::from_num(0.03227), }, TokenInfo { name: "BNB".into(), index: 11, decimals: 8, - available_native: 60800000000, + available_native: 60800000000 + 151100000, reimbursement_price: I80F48::from_num(2.7236), }, TokenInfo { name: "AVAX".into(), index: 12, decimals: 8, - available_native: 180900000000, + available_native: 180900000000 + 10225000000, reimbursement_price: I80F48::from_num(0.1576), }, TokenInfo { @@ -272,7 +275,7 @@ impl Constants { name: "GMT".into(), index: 14, decimals: 9, - available_native: 152843000000000, + available_native: 152843000000000 + 0, reimbursement_price: I80F48::from_num(0.000578548), }, TokenInfo { From daa7c18f1fae7367d6cd41896adbb5cf5fa65e2e Mon Sep 17 00:00:00 2001 From: Christian Kamm Date: Mon, 17 Oct 2022 14:49:48 +0200 Subject: [PATCH 21/28] Note about reimbursement prices source --- cli/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/src/main.rs b/cli/src/main.rs index 006f7084..30dd7f7f 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -166,7 +166,7 @@ struct Constants { impl Constants { fn new(mode: DistributionMode) -> Self { let mut out = Self { - // TODO: reimbursement_price needs to be updated before execution! + // Reimbursement prices: Coingecko market close prices of 2022-10-16 // (Note that user equity at snapshot time is computed from the prices from the // mango cache in the snapshot, not the reimbursement_price) From f12414e5706aeb05339a5013f995222ca41745b8 Mon Sep 17 00:00:00 2001 From: Christian Kamm Date: Mon, 17 Oct 2022 15:03:48 +0200 Subject: [PATCH 22/28] Make greedy settling and scale down optional --- cli/src/main.rs | 107 +++++++++++++++++------------------------------- 1 file changed, 37 insertions(+), 70 deletions(-) diff --git a/cli/src/main.rs b/cli/src/main.rs index 30dd7f7f..33a368a0 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -47,6 +47,12 @@ struct EquityFromSnapshotArgs { #[arg(long, default_value = "tokens")] distribution_mode: DistributionMode, + + #[arg(long, default_value = "false")] + enable_scale_down: bool, + + #[arg(long, default_value = "false")] + enable_greedy: bool, } #[derive(Subcommand, Debug, Clone)] @@ -562,27 +568,29 @@ impl EquityFromSnapshot { continue; } - // Negative amounts must be settled against other token balances - // This is using a greedy strategy, reducing the most requested token first - let mut weighted_indexes = amounts[0..15] - .iter() - .enumerate() - .skip(1) // skip MNGO - .filter_map(|(i, v)| (*v > 0).then_some(i)) - .filter_map(|i| { - (available_amounts[i] < reimburse_totals[i]) - .then(|| (i, reimburse_totals[i] - available_amounts[i])) - }) - .collect::>(); - - weighted_indexes.sort_by(|a, b| a.1.cmp(&b.1)); - for &(j, _) in weighted_indexes.iter() { - let start = amounts[j]; - let amount = if start + value >= 0 { -value } else { start }; - pay_liab(amounts, i, j, amount, &mut reimburse_totals); - value += amount; - if value >= 0 { - break; + if ctx.args.enable_greedy { + // Negative amounts must be settled against other token balances + // This is using a greedy strategy, reducing the most requested token first + let mut weighted_indexes = amounts[0..15] + .iter() + .enumerate() + .skip(1) // skip MNGO + .filter_map(|(i, v)| (*v > 0).then_some(i)) + .filter_map(|i| { + (available_amounts[i] < reimburse_totals[i]) + .then(|| (i, reimburse_totals[i] - available_amounts[i])) + }) + .collect::>(); + + weighted_indexes.sort_by(|a, b| a.1.cmp(&b.1)); + for &(j, _) in weighted_indexes.iter() { + let start = amounts[j]; + let amount = if start + value >= 0 { -value } else { start }; + pay_liab(amounts, i, j, amount, &mut reimburse_totals); + value += amount; + if value >= 0 { + break; + } } } @@ -616,7 +624,9 @@ impl EquityFromSnapshot { // Do a pass where we scale down user reimbursement token amounts and instead // reimburse with USDC if there's not enough tokens to give out - let scale_down_iter = if ctx.args.distribution_mode == DistributionMode::UsdcOnly { + let scale_down_iter = if !ctx.args.enable_scale_down { + 0..0 + } else if ctx.args.distribution_mode == DistributionMode::UsdcOnly { 0..15 } else { 1..15 // keep MNGO intact, DAO can provide extra from treasury @@ -649,52 +659,6 @@ impl EquityFromSnapshot { } } - // Do passes where we scale up token reimbursement amounts to try to fully utilize funds - // - // The idea here is that we have say 1000 SOL but only need 500 SOL to reimburse. - // To leave the DAO with fewer SOL at the end we prefer to give people who already - // had some SOL more of it (and compensate by giving them less of another token). - /*for _ in 0..100 { - for i in 1..15 { - if reimburse_totals[i] == 0 || reimburse_totals[i] == available_amounts[i] { - continue; - } - - let fraction = - I80F48::from(available_amounts[i]) / I80F48::from(reimburse_totals[i]); - if fraction <= 1 { - continue; - } - - // Scale up token reimbursements and take away USDC reimbursements - for (_, _, equity) in reimburse_amounts.iter_mut() { - let amount = equity[i]; - assert!(amount >= 0); - if amount == 0 { - continue; - } - - let new_amount: i64 = (I80F48::from(amount) * fraction).to_num(); - let mut remaining_increase = new_amount - amount; // positive - - for j in (1..16).rev() { - let other_amount = equity[j]; - if (j != 15 && available_amounts[j] >= reimburse_totals[j]) - || other_amount == 0 - { - continue; - } - let increase = remaining_increase.min(other_amount); - equity[j] -= increase; - reimburse_totals[j] -= increase as u64; - equity[i] += increase; - reimburse_totals[i] += increase as u64; - remaining_increase -= increase; - } - } - } - }*/ - // Double check that total user equity is unchanged let mut accounts_with_mngo = 0; let mut accounts_with_mngo_unchanged = 0; @@ -723,11 +687,14 @@ impl EquityFromSnapshot { for i in 0..15 { println!( - "{}: available {}, used {}, left over {}", + "{}: available ${}, used ${}, left over ${}, buy/sell native {}", token_names[i], available_amounts[i] / 1000000, reimburse_totals[i] / 1000000, - (available_amounts[i] as i64 - reimburse_totals[i] as i64) / 1000000 + (available_amounts[i] as i64 - reimburse_totals[i] as i64) / 1000000, + -(I80F48::from(available_amounts[i] as i64 - reimburse_totals[i] as i64) + / ctx.constants.token_infos[i].reimbursement_price) + .to_num::(), ); } println!("USDC: used {}", reimburse_totals[15] / 1000000); From 3c1f147743c9fcffcf5a38001a5d81987af501c8 Mon Sep 17 00:00:00 2001 From: Christian Kamm Date: Mon, 17 Oct 2022 15:20:25 +0200 Subject: [PATCH 23/28] Improve token usage debug output --- cli/src/main.rs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/cli/src/main.rs b/cli/src/main.rs index 33a368a0..aaabe015 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -311,6 +311,16 @@ impl Constants { fn token_names(&self) -> Vec { self.token_infos.iter().map(|ti| ti.name.clone()).collect() } + + fn usd_to_tokens_ui(&self, index: usize, usd: i64) -> I80F48 { + let ti = &self.token_infos[index]; + if !ti.is_active() { + assert!(usd == 0); + return I80F48::ZERO; + } + (I80F48::from(usd) / ti.reimbursement_price).floor() + / I80F48::from(10u64.pow(ti.decimals as u32)) + } } fn late_deposits_withdrawals( @@ -685,16 +695,16 @@ impl EquityFromSnapshot { println!("account w mango: {accounts_with_mngo}, unchanged {accounts_with_mngo_unchanged}"); + println!("token,available in usd,used in usd,remaining in usd,buy/sell in token ui"); for i in 0..15 { println!( - "{}: available ${}, used ${}, left over ${}, buy/sell native {}", + "{},{},{},{},{}", token_names[i], available_amounts[i] / 1000000, reimburse_totals[i] / 1000000, (available_amounts[i] as i64 - reimburse_totals[i] as i64) / 1000000, - -(I80F48::from(available_amounts[i] as i64 - reimburse_totals[i] as i64) - / ctx.constants.token_infos[i].reimbursement_price) - .to_num::(), + -ctx.constants + .usd_to_tokens_ui(i, available_amounts[i] as i64 - reimburse_totals[i] as i64), ); } println!("USDC: used {}", reimburse_totals[15] / 1000000); From 22ad122710c9de69a32b57523c9519b0a47b59a2 Mon Sep 17 00:00:00 2001 From: Christian Kamm Date: Mon, 17 Oct 2022 15:29:12 +0200 Subject: [PATCH 24/28] Minor debug output improvements --- cli/src/main.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cli/src/main.rs b/cli/src/main.rs index aaabe015..ddc8bf87 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -707,8 +707,8 @@ impl EquityFromSnapshot { .usd_to_tokens_ui(i, available_amounts[i] as i64 - reimburse_totals[i] as i64), ); } - println!("USDC: used {}", reimburse_totals[15] / 1000000); - println!("reimburse total {}", reimburse_totals.iter().sum::() / 1000000); + println!("USDC,,{},,", reimburse_totals[15] / 1000000); + println!("reimburse total,,{},,", reimburse_totals.iter().sum::() / 1000000); debug_print("usd final", &reimburse_amounts); From 7141ff8351712f133486de8d9b0bcc85f2c1ee6b Mon Sep 17 00:00:00 2001 From: Christian Kamm Date: Mon, 17 Oct 2022 16:42:21 +0200 Subject: [PATCH 25/28] Add USDC+MNGO mode --- cli/src/main.rs | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/cli/src/main.rs b/cli/src/main.rs index ddc8bf87..2f52b3d6 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -26,6 +26,7 @@ enum OutType { #[derive(ValueEnum, Clone, Copy, Debug, PartialEq, Eq)] enum DistributionMode { UsdcOnly, + UsdcAndMngo, Tokens, } @@ -295,10 +296,18 @@ impl Constants { }; assert!(out.token_infos.iter().map(|ti| ti.index).eq(0..16)); - if mode == DistributionMode::UsdcOnly { - for ti in out.token_infos[0..15].iter_mut() { - ti.available_native = 0; + match mode { + DistributionMode::UsdcOnly => { + for ti in out.token_infos[0..15].iter_mut() { + ti.available_native = 0; + } + } + DistributionMode::UsdcAndMngo => { + for ti in out.token_infos[1..15].iter_mut() { + ti.available_native = 0; + } } + _ => {} } out @@ -677,7 +686,7 @@ impl EquityFromSnapshot { let resum = a_reimburse.amounts.iter().sum::(); assert_eq!(eqsum, resum); - if ctx.args.distribution_mode == DistributionMode::Tokens { + if ctx.args.distribution_mode != DistributionMode::UsdcOnly { let mngo_equity = a_equity.amounts[0]; let mngo_reimburse = a_reimburse.amounts[0]; if mngo_equity > 0 { From 28aedce3208201f281550b3f775245af5da11109 Mon Sep 17 00:00:00 2001 From: Christian Kamm Date: Mon, 17 Oct 2022 16:42:30 +0200 Subject: [PATCH 26/28] Improve settlement matching order --- cli/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/src/main.rs b/cli/src/main.rs index 2f52b3d6..fb1d0cdc 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -621,7 +621,7 @@ impl EquityFromSnapshot { // (consider delta-neutral positions) // MNGO is last, meaning that Mango tokens are only used as an asset to offset a // liability as last resort, because we force it to a bad price. - for j in [14, 13, 12, 11, 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, 15, 0] { + for j in [14, 13, 12, 9, 7, 6, 5, 4, 3, 11, 8, 2, 1, 10, 15, 0] { if amounts[j] <= 0 { continue; } From 3a09eb9203b3a8c846e041a3e6e291edf16a9d60 Mon Sep 17 00:00:00 2001 From: dafyddd Date: Mon, 17 Oct 2022 17:25:23 -0700 Subject: [PATCH 27/28] adjust prices for reimbursement to be closing price on 2022-10-17 --- cli/src/main.rs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/cli/src/main.rs b/cli/src/main.rs index fb1d0cdc..7f62a5e2 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -173,7 +173,7 @@ struct Constants { impl Constants { fn new(mode: DistributionMode) -> Self { let mut out = Self { - // Reimbursement prices: Coingecko market close prices of 2022-10-16 + // Reimbursement prices: Coingecko market close prices of 2022-10-17 // (Note that user equity at snapshot time is computed from the prices from the // mango cache in the snapshot, not the reimbursement_price) @@ -185,28 +185,28 @@ impl Constants { index: 0, decimals: 6, available_native: 32904328899472 + 17926416000000, - reimbursement_price: I80F48::from_num(0.02425361), + reimbursement_price: I80F48::from_num(0.02414846), }, TokenInfo { name: "BTC".into(), index: 1, decimals: 6, available_native: 281498500 + 15849599, - reimbursement_price: I80F48::from_num(19272.92), + reimbursement_price: I80F48::from_num(19541.89), }, TokenInfo { name: "ETH".into(), index: 2, decimals: 6, available_native: 226000000 + 7431000, - reimbursement_price: I80F48::from_num(1306.94), + reimbursement_price: I80F48::from_num(1333.69), }, TokenInfo { name: "SOL".into(), index: 3, decimals: 9, available_native: 761577000000000 + 4778699999999, - reimbursement_price: I80F48::from_num(0.03017), + reimbursement_price: I80F48::from_num(0.03118), }, TokenInfo { name: "USDT".into(), @@ -220,14 +220,14 @@ impl Constants { index: 5, decimals: 6, available_native: 2354260000000 + 10258200000, - reimbursement_price: I80F48::from_num(0.720998), + reimbursement_price: I80F48::from_num(0.748324), }, TokenInfo { name: "RAY".into(), index: 6, decimals: 6, available_native: 98295000000 + 10605100000, - reimbursement_price: I80F48::from_num(0.491728), + reimbursement_price: I80F48::from_num(0.498757), }, TokenInfo { name: "COPE".into(), @@ -241,7 +241,7 @@ impl Constants { index: 8, decimals: 6, available_native: 11774000000 + 214800000, - reimbursement_price: I80F48::from_num(23.73), + reimbursement_price: I80F48::from_num(24.13), }, TokenInfo { name: "ADA".into(), @@ -255,21 +255,21 @@ impl Constants { index: 10, decimals: 9, available_native: 799155000000000 + 179378000000, - reimbursement_price: I80F48::from_num(0.03227), + reimbursement_price: I80F48::from_num(0.03335), }, TokenInfo { name: "BNB".into(), index: 11, decimals: 8, available_native: 60800000000 + 151100000, - reimbursement_price: I80F48::from_num(2.7236), + reimbursement_price: I80F48::from_num(2.7529), }, TokenInfo { name: "AVAX".into(), index: 12, decimals: 8, available_native: 180900000000 + 10225000000, - reimbursement_price: I80F48::from_num(0.1576), + reimbursement_price: I80F48::from_num(0.1624), }, TokenInfo { name: "LUNA".into(), @@ -283,7 +283,7 @@ impl Constants { index: 14, decimals: 9, available_native: 152843000000000 + 0, - reimbursement_price: I80F48::from_num(0.000578548), + reimbursement_price: I80F48::from_num(0.000592173), }, TokenInfo { name: "USDC".into(), From 9044bafaf7c4c2f8d6f1c89d3eb31b768cf663ab Mon Sep 17 00:00:00 2001 From: Christian Kamm Date: Tue, 18 Oct 2022 11:47:39 +0200 Subject: [PATCH 28/28] Binary output: Only one row per owner, summing accounts --- cli/src/main.rs | 119 ++++++++++++++++++++++++++++++------------------ 1 file changed, 74 insertions(+), 45 deletions(-) diff --git a/cli/src/main.rs b/cli/src/main.rs index 7f62a5e2..df996843 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -5,6 +5,7 @@ use mango::state::*; use mango_common::*; use serum_dex::state::OpenOrders; use solana_sdk::pubkey::Pubkey; +use std::collections::HashMap; use std::fs::File; use std::io::Write; use std::mem::size_of; @@ -380,62 +381,86 @@ struct EquityFromSnapshot { mngo_perp_price: I80F48, } -#[derive(bytemuck::Pod, bytemuck::Zeroable, Clone, Copy)] -#[repr(C)] -struct BinaryRow { - owner: Pubkey, - amounts: [u64; 16], +struct CsvOutWriter { + file: File, } -struct OutWriter { +impl CsvOutWriter { + fn new(outfile: &str) -> Self { + let file = File::create(outfile).unwrap(); + Self { file } + } +} + +struct BinaryOutWriter { file: File, - outtype: OutType, + owner_amounts: HashMap, + ordering: Vec, } -impl OutWriter { - fn new(outfile: &str, outtype: OutType) -> Self { +impl BinaryOutWriter { + fn new(outfile: &str) -> Self { let file = File::create(outfile).unwrap(); - Self { file, outtype } + Self { file, owner_amounts: HashMap::new(), ordering: Vec::new() } } +} + +trait OutWriter { + fn write(&mut self, account: &AccountData); + fn write_header(&mut self, constants: &Constants); + fn finish(&mut self); +} +impl OutWriter for CsvOutWriter { fn write(&mut self, account: &AccountData) { - match self.outtype { - OutType::Csv => { - write!( - &mut self.file, - "{},{},{}\n", - account.mango_account, - account.owner, - account.amounts.iter().map(|v| v.to_string()).collect::>().join(",") - ) - .unwrap(); - } - OutType::Binary => { - let row = BinaryRow { - owner: account.owner, - amounts: account - .amounts - .iter() - .map(|&v| v.try_into().unwrap()) - .collect::>() - .try_into() - .unwrap(), - }; - self.file.write_all(bytemuck::bytes_of(&row)).unwrap(); - } - } + write!( + &mut self.file, + "{},{},{}\n", + account.mango_account, + account.owner, + account.amounts.iter().map(|v| v.to_string()).collect::>().join(",") + ) + .unwrap(); } fn write_header(&mut self, constants: &Constants) { - match self.outtype { - OutType::Csv => { - write!(&mut self.file, "account,owner,{}\n", constants.token_names().join(",")) - .unwrap(); - } - OutType::Binary => { - // buffer accounts have a 37 byte header -- add 3 bytes to 8-byte align the data - self.file.write_all(&[0u8; 3]).unwrap(); - } + write!(&mut self.file, "account,owner,{}\n", constants.token_names().join(",")).unwrap(); + } + + fn finish(&mut self) {} +} + +#[derive(bytemuck::Pod, bytemuck::Zeroable, Clone, Copy)] +#[repr(C)] +struct BinaryRow { + owner: Pubkey, + amounts: [u64; 16], +} + +impl OutWriter for BinaryOutWriter { + fn write(&mut self, account: &AccountData) { + // Don't actually write, just sum up all per-owner reimbursements. + // Also keep the insertion ordering, to make inspecting the results easier. + let amounts = self.owner_amounts.entry(account.owner).or_insert_with(|| { + self.ordering.push(account.owner); + [0u64; 16] + }); + for (i, &v) in account.amounts.iter().enumerate() { + assert!(v >= 0); + amounts[i] += v as u64; + } + } + + fn write_header(&mut self, _constants: &Constants) { + // buffer accounts have a 37 byte header -- add 3 bytes to 8-byte align the data + self.file.write_all(&[0u8; 3]).unwrap(); + } + + fn finish(&mut self) { + for &owner in self.ordering.iter() { + let amounts = *self.owner_amounts.get(&owner).unwrap(); + let row = BinaryRow { owner, amounts }; + self.file.write_all(bytemuck::bytes_of(&row)).unwrap(); } } } @@ -488,7 +513,10 @@ impl EquityFromSnapshot { let late_changes = late_deposits_withdrawals(&args.late_changes, &constants)?; let data = DataSource::new(args.snapshot.clone())?; - let mut outwriter = OutWriter::new(&args.outfile, args.outtype); + let mut outwriter: Box = match args.outtype { + OutType::Csv => Box::new(CsvOutWriter::new(&args.outfile)), + OutType::Binary => Box::new(BinaryOutWriter::new(&args.outfile)), + }; let group = data.load_group(args.group)?; @@ -738,6 +766,7 @@ impl EquityFromSnapshot { for a in reimburse_native.iter() { outwriter.write(a) } + outwriter.finish(); Ok(()) }