diff --git a/Cargo.lock b/Cargo.lock index 67aee6a..e9a4b45 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -75,6 +75,12 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" +[[package]] +name = "arrayvec" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" + [[package]] name = "assert_matches" version = "1.5.0" @@ -88,7 +94,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ "hermit-abi", - "libc", + "libc 0.2.112", "winapi", ] @@ -107,7 +113,7 @@ dependencies = [ "addr2line", "cc", "cfg-if 1.0.0", - "libc", + "libc 0.2.112", "miniz_oxide", "object", "rustc-demangle", @@ -138,6 +144,12 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" +[[package]] +name = "bech32" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dabbe35f96fb9507f7330793dc490461b2962659ac5d427181e451a623751d1" + [[package]] name = "bincode" version = "1.3.3" @@ -147,6 +159,23 @@ dependencies = [ "serde", ] +[[package]] +name = "bitcoin" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6742ec672d3f12506f4ac5c0d853926ff1f94e675f60ffd3224039972bf663f1" +dependencies = [ + "bech32", + "bitcoin_hashes", + "secp256k1", +] + +[[package]] +name = "bitcoin_hashes" +version = "0.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ce18265ec2324ad075345d5814fbeed4f41f0a660055dc78840b74d19b874b1" + [[package]] name = "bitflags" version = "1.2.1" @@ -160,7 +189,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b64485778c4f16a6a5a9d335e80d449ac6c70cdd6a06d2af18a6f6f775a125b3" dependencies = [ "arrayref", - "arrayvec", + "arrayvec 0.5.2", "cc", "cfg-if 0.1.10", "constant_time_eq", @@ -340,7 +369,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42b7c3cbf0fa9c1b82308d57191728ca0256cb821220f4e2fd410a72ade26e3b" dependencies = [ "bzip2-sys", - "libc", + "libc 0.2.112", ] [[package]] @@ -350,7 +379,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc" dependencies = [ "cc", - "libc", + "libc 0.2.112", "pkg-config", ] @@ -381,7 +410,7 @@ version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" dependencies = [ - "libc", + "libc 0.2.112", "num-integer", "num-traits", "serde", @@ -421,10 +450,10 @@ checksum = "8c0994e656bba7b922d8dd1245db90672ffb701e684e45be58f20719d69abc5a" dependencies = [ "encode_unicode", "lazy_static", - "libc", + "libc 0.2.112", "regex", "terminal_size", - "termios", + "termios 0.3.3", "unicode-width", "winapi", "winapi-util", @@ -438,7 +467,7 @@ checksum = "3993e6445baa160675931ec041a5e03ca84b9c6e32a056150d3aa2bdda0a1f45" dependencies = [ "encode_unicode", "lazy_static", - "libc", + "libc 0.2.112", "regex", "terminal_size", "unicode-width", @@ -458,7 +487,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6888e10551bb93e424d8df1d07f1a8b4fceb0001a3a4b048bfc47554946f47b3" dependencies = [ "core-foundation-sys", - "libc", + "libc 0.2.112", ] [[package]] @@ -473,7 +502,7 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95059428f66df56b63431fdb4e1947ed2190586af5c5a8a8b71122bdf5a7f469" dependencies = [ - "libc", + "libc 0.2.112", ] [[package]] @@ -686,7 +715,7 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" dependencies = [ - "libc", + "libc 0.2.112", "redox_users", "winapi", ] @@ -763,6 +792,15 @@ dependencies = [ "termcolor", ] +[[package]] +name = "erased-serde" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44a5d80251b806a14cd3e4e1a582e912d5cbf6904ab19fdefbd7a56adca088e1" +dependencies = [ + "serde", +] + [[package]] name = "failure" version = "0.1.8" @@ -804,7 +842,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "975ccf83d8d9d0d84682850a38c8169027be83368805971cc4f238c2b245bc98" dependencies = [ "cfg-if 1.0.0", - "libc", + "libc 0.2.112", "redox_syscall 0.2.10", "winapi", ] @@ -817,7 +855,7 @@ checksum = "1e6988e897c1c9c485f43b47a529cef42fde0547f9d8d41a7062518f1d8fc53f" dependencies = [ "cfg-if 1.0.0", "crc32fast", - "libc", + "libc 0.2.112", "miniz_oxide", ] @@ -852,6 +890,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" + [[package]] name = "futures" version = "0.3.19" @@ -941,6 +985,12 @@ dependencies = [ "slab", ] +[[package]] +name = "gcc" +version = "0.3.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" + [[package]] name = "generic-array" version = "0.12.4" @@ -967,7 +1017,7 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e692e296bfac1d2533ef168d0b60ff5897b8b70a4009276834014dd8924cc028" dependencies = [ - "libc", + "libc 0.2.112", "winapi", ] @@ -979,7 +1029,7 @@ checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" dependencies = [ "cfg-if 1.0.0", "js-sys", - "libc", + "libc 0.2.112", "wasi 0.9.0+wasi-snapshot-preview1", "wasm-bindgen", ] @@ -991,7 +1041,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" dependencies = [ "cfg-if 1.0.0", - "libc", + "libc 0.2.112", "wasi 0.10.2+wasi-snapshot-preview1", ] @@ -1047,7 +1097,7 @@ version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" dependencies = [ - "libc", + "libc 0.2.112", ] [[package]] @@ -1063,7 +1113,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d6f5e247bc66f3255d755e96d9d43f6b191f4e182072b811d55584ff58c510f" dependencies = [ "cc", - "libc", + "libc 0.2.112", "pkg-config", ] @@ -1073,6 +1123,21 @@ version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12cb882ccb290b8646e554b157ab0b71e64e8d5bef775cd66b6531e52d302669" +[[package]] +name = "hkd32" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b68c4bfcead3bb33ccdc3e531879c7ddc44c952f44373f92d54485185335fda7" +dependencies = [ + "hmac 0.10.1", + "once_cell", + "pbkdf2 0.6.0", + "rand_core 0.5.1", + "sha2", + "subtle-encoding", + "zeroize", +] + [[package]] name = "hmac" version = "0.8.1" @@ -1191,6 +1256,19 @@ dependencies = [ "tokio-rustls", ] +[[package]] +name = "hyper-tls" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +dependencies = [ + "bytes 1.1.0", + "hyper", + "native-tls", + "tokio", + "tokio-native-tls", +] + [[package]] name = "idna" version = "0.2.3" @@ -1248,7 +1326,7 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" dependencies = [ - "libc", + "libc 0.2.112", ] [[package]] @@ -1284,7 +1362,7 @@ version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa" dependencies = [ - "libc", + "libc 0.2.112", ] [[package]] @@ -1326,6 +1404,12 @@ dependencies = [ "spin", ] +[[package]] +name = "libc" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e32a70cf75e5846d53a673923498228bbec6a8624708a9ea5645f075d6276122" + [[package]] name = "libc" version = "0.2.112" @@ -1447,7 +1531,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9b70ca2a6103ac8b665dc150b142ef0e4e89df640c9e6cf295d189c3caebe5a" dependencies = [ - "libc", + "libc 0.2.112", ] [[package]] @@ -1481,7 +1565,7 @@ version = "0.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc" dependencies = [ - "libc", + "libc 0.2.112", "log", "miow", "ntapi", @@ -1501,7 +1585,11 @@ dependencies = [ name = "multisend" version = "0.1.0" dependencies = [ + "base64 0.13.0", "clap", + "futures", + "rpassword 0.0.4", + "secp256k1", "serde", "serde_derive", "serde_json", @@ -1509,7 +1597,9 @@ dependencies = [ "solana-client", "solana-program", "solana-sdk", + "terra-rust-api", "thiserror", + "tokio", ] [[package]] @@ -1519,7 +1609,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48ba9f7719b5a0f42f338907614285fb5fd70e53858141f69898a1fb7203b24d" dependencies = [ "lazy_static", - "libc", + "libc 0.2.112", "log", "openssl", "openssl-probe", @@ -1537,7 +1627,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "391630d12b68002ae1e25e8f974306474966550ad82dac6886fb8910c19568ae" dependencies = [ "cfg-if 0.1.10", - "libc", + "libc 0.2.112", "winapi", ] @@ -1550,7 +1640,7 @@ dependencies = [ "bitflags", "cc", "cfg-if 1.0.0", - "libc", + "libc 0.2.112", "memoffset", ] @@ -1600,7 +1690,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" dependencies = [ "hermit-abi", - "libc", + "libc 0.2.112", ] [[package]] @@ -1666,7 +1756,7 @@ dependencies = [ "bitflags", "cfg-if 1.0.0", "foreign-types", - "libc", + "libc 0.2.112", "once_cell", "openssl-sys", ] @@ -1685,7 +1775,7 @@ checksum = "7e46109c383602735fa0a2e48dd2b7c892b048e1bf69e5c3b1d804b7d9c203cb" dependencies = [ "autocfg", "cc", - "libc", + "libc 0.2.112", "pkg-config", "vcpkg", ] @@ -1743,7 +1833,7 @@ checksum = "d58c7c768d4ba344e3e8d72518ac13e259d7c7ade24167003b8488e10b6740a3" dependencies = [ "cfg-if 0.1.10", "cloudabi", - "libc", + "libc 0.2.112", "redox_syscall 0.1.57", "smallvec", "winapi", @@ -1757,7 +1847,7 @@ checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" dependencies = [ "cfg-if 1.0.0", "instant", - "libc", + "libc 0.2.112", "redox_syscall 0.2.10", "smallvec", "winapi", @@ -1908,6 +1998,29 @@ dependencies = [ "proc-macro2 1.0.36", ] +[[package]] +name = "rand" +version = "0.3.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64ac302d8f83c0c1974bf758f6b041c6c8ada916fbb44a609158ca8b064cc76c" +dependencies = [ + "libc 0.2.112", + "rand 0.4.6", +] + +[[package]] +name = "rand" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" +dependencies = [ + "fuchsia-cprng", + "libc 0.2.112", + "rand_core 0.3.1", + "rdrand", + "winapi", +] + [[package]] name = "rand" version = "0.7.3" @@ -1915,7 +2028,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" dependencies = [ "getrandom 0.1.16", - "libc", + "libc 0.2.112", "rand_chacha 0.2.2", "rand_core 0.5.1", "rand_hc 0.2.0", @@ -1927,7 +2040,7 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" dependencies = [ - "libc", + "libc 0.2.112", "rand_chacha 0.3.1", "rand_core 0.6.3", "rand_hc 0.3.1", @@ -1953,6 +2066,21 @@ dependencies = [ "rand_core 0.6.3", ] +[[package]] +name = "rand_core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +dependencies = [ + "rand_core 0.4.2", +] + +[[package]] +name = "rand_core" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" + [[package]] name = "rand_core" version = "0.5.1" @@ -2014,6 +2142,15 @@ dependencies = [ "num_cpus", ] +[[package]] +name = "rdrand" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +dependencies = [ + "rand_core 0.3.1", +] + [[package]] name = "redox_syscall" version = "0.1.57" @@ -2080,11 +2217,13 @@ dependencies = [ "http-body", "hyper", "hyper-rustls", + "hyper-tls", "ipnet", "js-sys", "lazy_static", "log", "mime", + "native-tls", "percent-encoding", "pin-project-lite", "rustls", @@ -2093,6 +2232,7 @@ dependencies = [ "serde_json", "serde_urlencoded", "tokio", + "tokio-native-tls", "tokio-rustls", "url", "wasm-bindgen", @@ -2109,7 +2249,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" dependencies = [ "cc", - "libc", + "libc 0.2.112", "once_cell", "spin", "untrusted", @@ -2117,16 +2257,60 @@ dependencies = [ "winapi", ] +[[package]] +name = "rpassword" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a9dde63c78217c24d7f16dc1d60aac012124ba29d7bfa71bda532d4de668f44" +dependencies = [ + "libc 0.1.12", + "termios 0.0.5", +] + [[package]] name = "rpassword" version = "4.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99371657d3c8e4d816fb6221db98fa408242b0b53bac08f8676a41f8554fe99f" dependencies = [ - "libc", + "libc 0.2.112", "winapi", ] +[[package]] +name = "rust-crypto" +version = "0.2.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a" +dependencies = [ + "gcc", + "libc 0.2.112", + "rand 0.3.23", + "rustc-serialize", + "time", +] + +[[package]] +name = "rust_decimal" +version = "1.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0593ce4677e3800ddafb3de917e8397b1348e06e688128ade722d88fbe11ebf" +dependencies = [ + "arrayvec 0.7.2", + "num-traits", + "serde", +] + +[[package]] +name = "rust_decimal_macros" +version = "1.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07edd955ee62e68caa57633eefcb6bca56ebd3aafdeca3d441a86b14c69256fb" +dependencies = [ + "quote 1.0.14", + "rust_decimal", +] + [[package]] name = "rustc-demangle" version = "0.1.21" @@ -2139,6 +2323,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +[[package]] +name = "rustc-serialize" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" + [[package]] name = "rustc_version" version = "0.2.3" @@ -2216,6 +2406,24 @@ dependencies = [ "untrusted", ] +[[package]] +name = "secp256k1" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97d03ceae636d0fed5bae6a7f4f664354c5f4fcedf6eef053fef17e49f837d0a" +dependencies = [ + "secp256k1-sys", +] + +[[package]] +name = "secp256k1-sys" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "957da2573cde917463ece3570eab4a0b3f19de6f1646cde62e6fd3868f566036" +dependencies = [ + "cc", +] + [[package]] name = "security-framework" version = "2.3.1" @@ -2225,7 +2433,7 @@ dependencies = [ "bitflags", "core-foundation", "core-foundation-sys", - "libc", + "libc 0.2.112", "security-framework-sys", ] @@ -2236,7 +2444,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9dd14d83160b528b7bfd66439110573efcfbe281b17fc2ca9f39f550d619c7e" dependencies = [ "core-foundation-sys", - "libc", + "libc 0.2.112", ] [[package]] @@ -2379,7 +2587,7 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" dependencies = [ - "libc", + "libc 0.2.112", ] [[package]] @@ -2407,7 +2615,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e" dependencies = [ "cfg-if 1.0.0", - "libc", + "libc 0.2.112", "winapi", ] @@ -2417,7 +2625,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5dc90fe6c7be1a323296982db1836d1ea9e47b6839496dde9a541bc496df3516" dependencies = [ - "libc", + "libc 0.2.112", "winapi", ] @@ -2452,7 +2660,7 @@ checksum = "8e87ba7d3d05eca52fb9ed42aae1b65d8b1a50820b5c12729190beab08b15da4" dependencies = [ "chrono", "clap", - "rpassword", + "rpassword 4.0.5", "solana-remote-wallet", "solana-sdk", "thiserror", @@ -2546,7 +2754,7 @@ dependencies = [ "ed25519-dalek", "either", "lazy_static", - "libc", + "libc 0.2.112", "rand_chacha 0.2.2", "regex-syntax", "reqwest", @@ -2767,7 +2975,7 @@ dependencies = [ "histogram", "itertools", "lazy_static", - "libc", + "libc 0.2.112", "libloading", "log", "memmap2", @@ -3019,6 +3227,15 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" +[[package]] +name = "subtle-encoding" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dcb1ed7b8330c5eed5441052651dd7a12c75e2ed88f2ec024ae1fa3a5e59945" +dependencies = [ + "zeroize", +] + [[package]] name = "symlink" version = "0.1.0" @@ -3066,7 +3283,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b55807c0344e1e6c04d7c965f5289c39a8d94ae23ed5c0b57aabac549f871c6" dependencies = [ "filetime", - "libc", + "libc 0.2.112", "xattr", ] @@ -3077,7 +3294,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" dependencies = [ "cfg-if 1.0.0", - "libc", + "libc 0.2.112", "rand 0.8.4", "redox_syscall 0.2.10", "remove_dir_all", @@ -3099,17 +3316,60 @@ version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df" dependencies = [ - "libc", + "libc 0.2.112", "winapi", ] +[[package]] +name = "termios" +version = "0.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75071a31761781a74d091387713756966a74ce60eea99a093a5ab3f2cccac3fe" +dependencies = [ + "libc 0.1.12", +] + [[package]] name = "termios" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "411c5bf740737c7918b8b1fe232dca4dc9f8e754b8ad5e20966814001ed0ac6b" dependencies = [ - "libc", + "libc 0.2.112", +] + +[[package]] +name = "terra-rust-api" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81e56caa9882a9e551f9411f5338c4ee49a4d5013db9b3763a5514a37d54ec67" +dependencies = [ + "anyhow", + "base64 0.13.0", + "bitcoin", + "chrono", + "ed25519", + "ed25519-dalek", + "erased-serde", + "futures", + "hex", + "hkd32", + "lazy_static", + "log", + "num-traits", + "rand_core 0.5.1", + "regex", + "reqwest", + "rust-crypto", + "rust_decimal", + "rust_decimal_macros", + "rustc-serialize", + "secp256k1", + "serde", + "serde_json", + "subtle-encoding", + "thiserror", + "tokio", ] [[package]] @@ -3147,7 +3407,7 @@ version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" dependencies = [ - "libc", + "libc 0.2.112", "winapi", ] @@ -3192,7 +3452,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fbbf1c778ec206785635ce8ad57fe52b3009ae9e0c9f574a728f3049d3e55838" dependencies = [ "bytes 1.1.0", - "libc", + "libc 0.2.112", "memchr", "mio", "num_cpus", @@ -3215,6 +3475,16 @@ dependencies = [ "syn 1.0.84", ] +[[package]] +name = "tokio-native-tls" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b" +dependencies = [ + "native-tls", + "tokio", +] + [[package]] name = "tokio-rustls" version = "0.23.2" @@ -3572,7 +3842,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "244c3741f4240ef46274860397c7c74e50eb23624996930e484c16679633a54c" dependencies = [ - "libc", + "libc 0.2.112", ] [[package]] @@ -3620,7 +3890,7 @@ version = "2.0.6+zstd.1.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98aa931fb69ecee256d44589d19754e61851ae4769bf963b385119b1cc37a49e" dependencies = [ - "libc", + "libc 0.2.112", "zstd-sys", ] @@ -3633,5 +3903,5 @@ dependencies = [ "cc", "glob", "itertools", - "libc", + "libc 0.2.112", ] diff --git a/Cargo.toml b/Cargo.toml index 38f1e27..b30933c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,3 +16,9 @@ solana-client = "=1.8.1" solana-program = "=1.8.1" solana-sdk = "=1.8.1" thiserror = "1" +terra-rust-api = "1.1.8" +rpassword = "0.0.4" +base64 = "0.13.0" +futures = "0.3.19" +tokio = { version = "1.15.0", features = ["full"] } +secp256k1 = { version = "0.20.3", default-features = false } \ No newline at end of file diff --git a/src/chains.rs b/src/chains.rs index cac580f..59622ce 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -1,4 +1,5 @@ pub mod solana; +pub mod terra; use crate::{utils, Result}; @@ -6,20 +7,20 @@ pub struct Solana { pub network: String, } +pub struct Terra { + pub network: String, + pub gas_price: String, + pub memo: String, + pub gas_adj: f64, +} + pub trait Chain { - fn new(&self, name: String) -> Self - where - Self: Sized; fn execute_transaction(&self, data: &utils::MultisendInstruction) -> Result<()>; fn validate_addrs(&self, data: &utils::MultisendInstruction) -> Result<()>; fn validate_balance(&self, data: &utils::MultisendInstruction) -> Result<()>; } impl Chain for Solana { - fn new(&self, network: String) -> Solana { - Solana { network: network } - } - fn execute_transaction(&self, data: &utils::MultisendInstruction) -> Result<()> { // initialize wallet with seed phrase + optional derivation path. let keypair = solana::initialize_wallet("wallet", None).unwrap(); @@ -37,3 +38,31 @@ impl Chain for Solana { solana::validate_balance(&self.network, data) } } + +impl Chain for Terra { + fn execute_transaction(&self, data: &utils::MultisendInstruction) -> Result<()> { + // initialize wallet with seed phrase + optional derivation path. + let from_key = terra::initialize_wallet().unwrap(); + let public_key = terra::get_public_key(&from_key); + + let msgs = terra::build_transfer_msgs(&public_key, data); + terra::send_transaction( + &self.network, + &self.gas_price, + self.gas_adj, + &self.memo, + from_key, + msgs, + ) + .expect("Sending Transaction failed."); + Ok(()) + } + + fn validate_addrs(&self, data: &utils::MultisendInstruction) -> Result<()> { + Ok(()) + } + + fn validate_balance(&self, data: &utils::MultisendInstruction) -> Result<()> { + terra::validate_balance(&self.network, data) + } +} diff --git a/src/chains/solana.rs b/src/chains/solana.rs index dcc689c..6b2344b 100644 --- a/src/chains/solana.rs +++ b/src/chains/solana.rs @@ -25,6 +25,7 @@ pub fn initialize_wallet( let keys = keypair::keypair_from_seed_phrase(keypair_name, false, false, derivation_path, false) .expect("Couldn't derive seed"); + Ok(keys) } diff --git a/src/chains/terra.rs b/src/chains/terra.rs new file mode 100644 index 0000000..cadf5b2 --- /dev/null +++ b/src/chains/terra.rs @@ -0,0 +1,204 @@ +extern crate base64; +extern crate rpassword; +use crate::{utils, Error, Result}; +use rpassword::read_password; +use secp256k1::Secp256k1; +use serde::{Deserialize, Serialize}; +use std::io::Write; +use tokio; + +const TERRA_DECIMAL: f64 = 1_000_000.0; +use terra_rust_api::core_types::Coin; +use terra_rust_api::{GasOptions, Message, MsgExecuteContract, PrivateKey, PublicKey, Terra}; + +#[derive(Serialize, Debug)] +#[serde(rename_all = "snake_case")] +pub enum ExecuteMsg<'a> { + Transfer { amount: &'a str, recipient: &'a str }, +} + +impl ExecuteMsg<'static> { + pub fn create_transfer<'a>( + amount: u64, + from_address: &'a str, + to_address: &'a str, + contract: &'a str, + ) -> Message { + let transfer = ExecuteMsg::Transfer { + amount: &amount.to_string(), + recipient: to_address, + }; + let tranfser_json = serde_json::to_string(&transfer).unwrap(); + let coins: Vec = vec![]; + MsgExecuteContract::create_from_json(from_address, contract, &tranfser_json, &coins) + .unwrap() + } +} + +#[tokio::main] +pub async fn send_transaction( + network: &str, + gas_price: &str, + gas_adj: f64, + memo: &String, + from_key: PrivateKey, + msgs: Vec, +) -> Result<()> { + let client = rpc_connection(network, gas_price, gas_adj).unwrap(); + let secp = Secp256k1::new(); + print!("{}, {}, {:?}", gas_price, gas_adj, memo.to_string()); + // let resp = client + // .submit_transaction_sync(&secp, &from_key, msgs, Some(memo.to_string())) + // .await + // .unwrap(); + // let hash = resp.txhash; + // print!("https://finder.terra.money/mainnet/tx/{}", hash); + Ok(()) +} + +pub fn build_transfer_msgs( + sender_address: &PublicKey, + data: &utils::MultisendInstruction, +) -> Vec { + let transfer: Vec = data + .recipients + .iter() + .map(|instr| { + ExecuteMsg::create_transfer( + (instr.amount * TERRA_DECIMAL) as u64, + &sender_address.account().unwrap(), + &instr.address, + &instr.coin, + ) + }) + .collect(); + return transfer; +} + +#[derive(Deserialize, Serialize, Debug)] +#[serde(rename_all = "snake_case")] +pub struct QueryResult { + balance: String, +} + +#[derive(Serialize, Deserialize, Debug)] +#[serde(rename_all = "snake_case")] +pub enum QueryMsg { + Balance { address: String }, + + QueryResult(QueryResult), +} + +impl QueryMsg { + fn base64encode(&self) -> String { + let serialized = serde_json::to_string(&self).unwrap(); + base64::encode(serialized) + } + + fn balance(self) -> u64 { + if let QueryMsg::QueryResult(result) = self { + result.balance.parse::().unwrap() + } else { + panic!("Not a query result") + } + } +} + +pub fn initialize_wallet() -> Result { + print!("Seed phrase: "); + std::io::stdout().flush().unwrap(); + let password = read_password().unwrap(); + let secp = Secp256k1::new(); + let from_key = PrivateKey::from_words(&secp, &password, 0, 0).unwrap(); + Ok(from_key) +} + +fn sender_public_key() -> PublicKey { + let from_key = initialize_wallet().unwrap(); + get_public_key(&from_key) +} + +pub fn get_public_key(from_key: &PrivateKey) -> PublicKey { + let secp = Secp256k1::new(); + from_key.public_key(&secp) +} + +pub fn validate_balance(network: &str, data: &utils::MultisendInstruction) -> Result<()> { + let address = sender_public_key(); + let client = rpc_connection(network, "", 1.4).unwrap(); + for sender in &data.senders { + let balance = get_token_balance(&client, &sender.coin, &address)?; + println!( + "Balance for {} is {}", + sender.address, + balance as f64 / TERRA_DECIMAL + ); + if balance < (sender.amount * TERRA_DECIMAL) as u64 { + return Err(Error::InvalidConfig(format!( + "Address {} has a lower balance than send amount.", + sender.address + ))); + } + } + Ok(()) +} + +#[tokio::main] +async fn get_token_balance( + client: &Terra, + token_contract: &str, + address: &PublicKey, +) -> Result { + let balance_query = QueryMsg::Balance { + address: address.account().expect("Balance Lookup Failed"), + }; + + let balance_uri = format!( + "/terra/wasm/v1beta1/contracts/{}/store?query_msg={}", + token_contract, + balance_query.base64encode() + ); + let balance_obj: QueryMsg = client + .send_cmd(&balance_uri, None) + .await + .expect("Invalid Response"); + Ok(balance_obj.balance()) +} + +/// Balance Query for tokens +/// https://lcd.terra.dev/terra/wasm/v1beta1/contracts/{contract address}/store?query_msg={base 64 decode message} +/// https://docs.terraswap.io/docs/reference/token/ +/// +/// +/// +/// For transfer Implement https://github.com/PFC-Validator/terra-rust/blob/main/examples/do_swap.rs#L278 +/// +/// +/// For MultiSend, will need to add MsgSendStruct +// https://bombay-lcd.terra.dev/terra/wasm/v1beta/contracts/terra1kc87mu460fwkqte29rquh4hc20m54fxwtsx7gp/store?query_msg=eyJiYWxhbmNlIjp7ImFkZHJlc3MiOiJ0ZXJyYTF2Z3B5YXoyMzJ3Y2hrdGdrYzg4Z3IyeGhxZGpxdjQ5aHE0dG52ayJ9fQ== +pub fn rpc_connection(network: &str, gas_price: &str, gas_adj: f64) -> Result { + let gas_opts = + GasOptions::create_with_gas_estimate(gas_price, gas_adj).expect("Invalid Gas Parameters"); + let conn = match network { + //Config options + "devnet" => Terra::lcd_client( + "https://bombay-lcd.terra.dev", + "bombay-12", + &gas_opts, + Some(false), + ), + "mainnet" => Terra::lcd_client( + "https://lcd.terra.dev", + "columbus-5", + &gas_opts, + Some(false), + ), + _ => Terra::lcd_client( + "https://bombay-lcd.terra.dev", + "bombay-12", + &gas_opts, + Some(false), + ), + }; + Ok(conn) +} diff --git a/src/main.rs b/src/main.rs index 1911073..bd24fb1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,14 +1,41 @@ use clap::{crate_name, crate_version, App, AppSettings, Arg, ArgMatches, SubCommand}; -use multisend::chains::{Chain, Solana}; +use multisend::chains::{Chain, Solana, Terra}; use multisend::utils; use multisend::Result; use std::process; fn run(matches: &ArgMatches) -> Result<()> { + let chain: Box; let data = utils::read_instruction_json(matches.value_of("path").unwrap())?; let network = matches.value_of("network").unwrap_or("devnet").to_owned(); - let chain = match matches.value_of("network") { - // Right now there's only one option here but we can add more later. + // Implementing chains specific logic here. + print!( + "{:?}", + matches + .subcommand_matches("broadcast-transaction") + .unwrap() + .value_of("gas_price"). + ); + chain = match matches.value_of("chain").unwrap_or("terra") { + "solana" => Box::new(Solana { network }), + "terra" => { + let gas_price = matches.value_of("gas_price").unwrap_or("").to_owned(); + let gas_adjustment = matches + .value_of("gas_adjustment") + .unwrap_or("1.4") + .to_owned(); + let gas_adj: f64 = gas_adjustment + .parse() + .expect("Gas adjustment not a valid float value."); + let memo = matches.value_of("memo").unwrap_or("").to_owned(); + print!("TEST: {}", memo); + Box::new(Terra { + network, + gas_price, + gas_adj, + memo, + }) + } _ => Box::new(Solana { network }), }; let _results = match matches.subcommand() { @@ -57,7 +84,7 @@ fn main() { Arg::with_name("path") .short("p") .takes_value(true) - .required(true) + // .required(true) .help("Path for the transactions file."), ) .subcommand( @@ -65,7 +92,20 @@ fn main() { .about("Verifies sender/receipiant amts. match and contains valid addresses."), ) .subcommand( - SubCommand::with_name("broadcast-transaction").about("Send configured transaction"), + SubCommand::with_name("broadcast-transaction") + .about("Send configured transaction") + .arg( + Arg::with_name("gas_price") + .help("Gas price to pay for transactions [TERRA ONLY]") + .index(1), + ) + .arg( + Arg::with_name("gas_adjustment") + .help("Gas price to use for transactions [TERRA ONLY]") + .default_value("1.4") + .index(2), + ) + .arg(Arg::with_name("memo").help("Tranasction Memo").index(3)), ) .get_matches();