diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..5865438 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,128 @@ +name: Aqd CI + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + build: + name: Sanity Check Codebase + runs-on: ubuntu-latest + + steps: + - name: Check out code + uses: actions/checkout@v2 + + - name: Set up Rust + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + override: true + components: rustfmt, clippy + + # Print Cargo version + - name: Print Cargo version + run: cargo --version + + # Install libudev (required for solana crates) + - name: Install libudev + run: | + sudo apt-get update + sudo apt-get install -y libudev-dev + + - name: Check formatting + run: | + cargo fmt -- --check + + - name: Check linting + run: | + cargo clippy --workspace --all-features + + - name: Build and test + run: | + cargo test --workspace --all-features + + solana: + name: Solana Integration Testing + runs-on: ubuntu-latest + + steps: + # Install jq to parse JSON (used in shell scripts) + - name: Install jq + run: | + sudo apt-get update + sudo apt-get install -y jq libudev-dev + + - name: Check out code + uses: actions/checkout@v3 + + - name: Set up Rust + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + override: true + components: rustfmt, clippy + + # Print Cargo version + - name: Print Cargo version + run: cargo --version + + # Set up Solana CLI + - name: Set up Solana CLI + working-directory: ./integration/solana + run: ./setup_solana.sh + + # Compile Aqd in release mode (solana feature) + - name: Compile Aqd for Solana target + run: | + cargo build --no-default-features --features "solana" --release + + # Run Solana integration tests + - name: Test Solana CLI + run: ./solana_cli.sh + working-directory: ./integration/solana + + polkadot: + name: Polkadot Integration Testing + runs-on: ubuntu-latest + + steps: + # Install jq to parse JSON (used in shell scripts) + - name: Install jq + run: | + sudo apt-get update + sudo apt-get install -y jq libudev-dev + + - name: Check out code + uses: actions/checkout@v3 + + - name: Set up Rust + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + override: true + + # Print Cargo version + - name: Print Cargo version + run: cargo --version + + - name: Start substrate-contracts-node + run: | + # Download and extract the substrate-contracts-node binary + wget https://github.com/paritytech/substrate-contracts-node/releases/download/v0.33.0/substrate-contracts-node-linux.tar.gz + tar -xzvf substrate-contracts-node-linux.tar.gz + + # Run substrate-contracts-node + nohup ./artifacts/substrate-contracts-node-linux/substrate-contracts-node --dev --rpc-external > substrate.out & + + # Compile Aqd in release mode (polkadot feature) + - name: Compile Aqd for Polkadot target + run: | + cargo build --no-default-features --features "polkadot" --release + + # Run Polkadot integration tests + - name: Test Polkadot CLI + run: ./polkadot_cli.sh + working-directory: ./integration/polkadot diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2ee62ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +/target +.vscode + +**/.DS_Store diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..1ab79d3 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,8948 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "Inflector" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" +dependencies = [ + "lazy_static", + "regex", +] + +[[package]] +name = "addr2line" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" +dependencies = [ + "gimli 0.27.3", +] + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli 0.28.0", +] + +[[package]] +name = "adler" +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 0.14.7", +] + +[[package]] +name = "aes" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", + "opaque-debug 0.3.0", +] + +[[package]] +name = "aes-gcm" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc3be92e19a7ef47457b8e6f90707e12b6ac5d20c6f3866584fa3be0787d839f" +dependencies = [ + "aead", + "aes", + "cipher", + "ctr 0.7.0", + "ghash", + "subtle", +] + +[[package]] +name = "aes-gcm-siv" +version = "0.10.3" +source = "git+https://github.com/RustCrypto/AEADs?rev=e1e35e0c4f4943da0a99ceb8477c421dcfae2c33#e1e35e0c4f4943da0a99ceb8477c421dcfae2c33" +dependencies = [ + "aead", + "aes", + "cipher", + "ctr 0.8.0", + "polyval", + "subtle", + "zeroize", +] + +[[package]] +name = "ahash" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +dependencies = [ + "getrandom 0.2.10", + "once_cell", + "version_check", +] + +[[package]] +name = "ahash" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" +dependencies = [ + "cfg-if", + "getrandom 0.2.10", + "once_cell", + "version_check", +] + +[[package]] +name = "aho-corasick" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +dependencies = [ + "memchr", +] + +[[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 = "anchor-syn" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a125e4b0cc046cfec58f5aa25038e34cf440151d58f0db3afc55308251fe936d" +dependencies = [ + "anyhow", + "bs58 0.5.0", + "heck 0.3.3", + "proc-macro2", + "quote", + "serde", + "serde_json", + "sha2 0.10.8", + "syn 1.0.109", + "thiserror", +] + +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "ansi_term" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +dependencies = [ + "winapi", +] + +[[package]] +name = "anstream" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" + +[[package]] +name = "anstyle-parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +dependencies = [ + "windows-sys 0.48.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" +dependencies = [ + "anstyle", + "windows-sys 0.48.0", +] + +[[package]] +name = "anyhow" +version = "1.0.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" + +[[package]] +name = "aqd" +version = "0.1.0" +dependencies = [ + "aqd-polkadot", + "aqd-solana", + "clap 4.4.7", + "tokio", +] + +[[package]] +name = "aqd-polkadot" +version = "0.1.0" +dependencies = [ + "anyhow", + "aqd-utils", + "clap 4.4.7", + "colored", + "contract-build", + "contract-extrinsics", + "hex", + "serde", + "serde_json", + "sp-core", + "subxt", + "url", +] + +[[package]] +name = "aqd-solana" +version = "0.1.0" +dependencies = [ + "anyhow", + "aqd-solana-contracts", + "aqd-utils", + "clap 4.4.7", + "serde_json", + "solana-clap-v3-utils", + "solana-cli-config", +] + +[[package]] +name = "aqd-solana-contracts" +version = "0.1.0" +dependencies = [ + "anchor-syn", + "anyhow", + "aqd-utils", + "base58", + "base64 0.21.4", + "byte-slice-cast", + "colored", + "convert_case 0.6.0", + "hex", + "num-bigint 0.4.4", + "num-traits", + "serde", + "serde_json", + "sha2 0.10.8", + "solana-clap-v3-utils", + "solana-cli", + "solana-cli-config", + "solana-cli-output", + "solana-client", + "solana-rpc-client-api", + "solana-sdk", + "solana-transaction-status", + "tokio", +] + +[[package]] +name = "aqd-utils" +version = "0.1.0" +dependencies = [ + "anyhow", + "toml 0.8.6", +] + +[[package]] +name = "ark-bn254" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a22f4561524cd949590d78d7d4c5df8f592430d221f7f3c9497bbafd8972120f" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-std", +] + +[[package]] +name = "ark-ec" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "defd9a439d56ac24968cca0571f598a61bc8c55f71d50a89cda591cb750670ba" +dependencies = [ + "ark-ff", + "ark-poly", + "ark-serialize", + "ark-std", + "derivative", + "hashbrown 0.13.2", + "itertools 0.10.5", + "num-traits", + "zeroize", +] + +[[package]] +name = "ark-ff" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" +dependencies = [ + "ark-ff-asm", + "ark-ff-macros", + "ark-serialize", + "ark-std", + "derivative", + "digest 0.10.7", + "itertools 0.10.5", + "num-bigint 0.4.4", + "num-traits", + "paste", + "rustc_version", + "zeroize", +] + +[[package]] +name = "ark-ff-asm" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-macros" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" +dependencies = [ + "num-bigint 0.4.4", + "num-traits", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-poly" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d320bfc44ee185d899ccbadfa8bc31aab923ce1558716e1997a1e74057fe86bf" +dependencies = [ + "ark-ff", + "ark-serialize", + "ark-std", + "derivative", + "hashbrown 0.13.2", +] + +[[package]] +name = "ark-serialize" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" +dependencies = [ + "ark-serialize-derive", + "ark-std", + "digest 0.10.7", + "num-bigint 0.4.4", +] + +[[package]] +name = "ark-serialize-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae3281bc6d0fd7e549af32b52511e1302185bd688fd3359fa36423346ff682ea" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-std" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" +dependencies = [ + "num-traits", + "rand 0.8.5", +] + +[[package]] +name = "array-bytes" +version = "6.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b1c5a481ec30a5abd8dfbd94ab5cf1bb4e9a66be7f1b3b322f2f1170c200fd" + +[[package]] +name = "arrayref" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" + +[[package]] +name = "arrayvec" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" +dependencies = [ + "nodrop", +] + +[[package]] +name = "arrayvec" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" + +[[package]] +name = "arrayvec" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" + +[[package]] +name = "ascii" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eab1c04a571841102f5345a8fc0f6bb3d31c315dec879b5c6e42e40ce7ffa34e" + +[[package]] +name = "asn1-rs" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6fd5ddaf0351dff5b8da21b2fb4ff8e08ddd02857f0bf69c47639106c0fff0" +dependencies = [ + "asn1-rs-derive", + "asn1-rs-impl", + "displaydoc", + "nom", + "num-traits", + "rusticata-macros", + "thiserror", + "time", +] + +[[package]] +name = "asn1-rs-derive" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "726535892e8eae7e70657b4c8ea93d26b8553afb1ce617caee529ef96d7dee6c" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", + "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", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "assert_matches" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" + +[[package]] +name = "async-channel" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" +dependencies = [ + "concurrent-queue", + "event-listener 2.5.3", + "futures-core", +] + +[[package]] +name = "async-compression" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f658e2baef915ba0f26f1f7c42bfb8e12f532a01f449a090ded75ae7a07e9ba2" +dependencies = [ + "brotli", + "flate2", + "futures-core", + "memchr", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "async-executor" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b0c4a4f319e45986f347ee47fef8bf5e81c9abc3f6f58dc2391439f30df65f0" +dependencies = [ + "async-lock", + "async-task", + "concurrent-queue", + "fastrand 2.0.1", + "futures-lite", + "slab", +] + +[[package]] +name = "async-fs" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "279cf904654eeebfa37ac9bb1598880884924aab82e290aa65c9e77a0e142e06" +dependencies = [ + "async-lock", + "autocfg", + "blocking", + "futures-lite", +] + +[[package]] +name = "async-io" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" +dependencies = [ + "async-lock", + "autocfg", + "cfg-if", + "concurrent-queue", + "futures-lite", + "log", + "parking", + "polling", + "rustix 0.37.26", + "slab", + "socket2 0.4.9", + "waker-fn", +] + +[[package]] +name = "async-lock" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" +dependencies = [ + "event-listener 2.5.3", +] + +[[package]] +name = "async-mutex" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479db852db25d9dbf6204e6cb6253698f175c15726470f78af0d918e99d6156e" +dependencies = [ + "event-listener 2.5.3", +] + +[[package]] +name = "async-net" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0434b1ed18ce1cf5769b8ac540e33f01fa9471058b5e89da9e06f3c882a8c12f" +dependencies = [ + "async-io", + "blocking", + "futures-lite", +] + +[[package]] +name = "async-process" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea6438ba0a08d81529c69b36700fa2f95837bfe3e776ab39cde9c14d9149da88" +dependencies = [ + "async-io", + "async-lock", + "async-signal", + "blocking", + "cfg-if", + "event-listener 3.0.0", + "futures-lite", + "rustix 0.38.19", + "windows-sys 0.48.0", +] + +[[package]] +name = "async-signal" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2a5415b7abcdc9cd7d63d6badba5288b2ca017e3fbd4173b8f405449f1a2399" +dependencies = [ + "async-io", + "async-lock", + "atomic-waker", + "cfg-if", + "futures-core", + "futures-io", + "rustix 0.38.19", + "signal-hook-registry", + "slab", + "windows-sys 0.48.0", +] + +[[package]] +name = "async-task" +version = "4.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4eb2cdb97421e01129ccb49169d8279ed21e829929144f4a22a6e54ac549ca1" + +[[package]] +name = "async-trait" +version = "0.1.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "atomic" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59bdb34bc650a32731b31bd8f0829cc15d24a708ee31559e0bb34f2bc320cba" + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi 0.1.19", + "libc", + "winapi", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "backtrace" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +dependencies = [ + "addr2line 0.21.0", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object 0.32.1", + "rustc-demangle", +] + +[[package]] +name = "base58" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6107fe1be6682a68940da878d9e9f5e90ca5745b3dec9fd1bb393c8777d4f581" + +[[package]] +name = "base64" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" + +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "base64" +version = "0.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ba43ea6f343b788c8764558649e08df62f86c6ef251fdaeb1ffd010a9ae50a2" + +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + +[[package]] +name = "beef" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1" +dependencies = [ + "serde", +] + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "bip39" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93f2635620bf0b9d4576eb7bb9a38a55df78bd1205d26fa994b25911a69f212f" +dependencies = [ + "bitcoin_hashes", + "serde", + "unicode-normalization", +] + +[[package]] +name = "bitcoin_hashes" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90064b8dee6815a6470d60bad07bbbaee885c0e12d04177138fa3291a01b7bc4" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +dependencies = [ + "serde", +] + +[[package]] +name = "bitmaps" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "031043d04099746d8db04daf1fa424b2bc8bd69d92b25962dcde24da39ab64a2" +dependencies = [ + "typenum", +] + +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + +[[package]] +name = "blake2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "blake2-rfc" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" +dependencies = [ + "arrayvec 0.4.12", + "constant_time_eq 0.1.5", +] + +[[package]] +name = "blake2b_simd" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23285ad32269793932e830392f2fe2f83e26488fd3ec778883a93c8323735780" +dependencies = [ + "arrayref", + "arrayvec 0.7.4", + "constant_time_eq 0.3.0", +] + +[[package]] +name = "blake3" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0231f06152bf547e9c2b5194f247cd97aacf6dcd8b15d8e5ec0663f64580da87" +dependencies = [ + "arrayref", + "arrayvec 0.7.4", + "cc", + "cfg-if", + "constant_time_eq 0.3.0", + "digest 0.10.7", +] + +[[package]] +name = "block-buffer" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" +dependencies = [ + "block-padding 0.1.5", + "byte-tools", + "byteorder", + "generic-array 0.12.4", +] + +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "block-padding 0.2.1", + "generic-array 0.14.7", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array 0.14.7", +] + +[[package]] +name = "block-padding" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" +dependencies = [ + "byte-tools", +] + +[[package]] +name = "block-padding" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" + +[[package]] +name = "blocking" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c36a4d0d48574b3dd360b4b7d95cc651d2b6557b6402848a27d4b228a473e2a" +dependencies = [ + "async-channel", + "async-lock", + "async-task", + "fastrand 2.0.1", + "futures-io", + "futures-lite", + "piper", + "tracing", +] + +[[package]] +name = "bollard" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f03db470b3c0213c47e978da93200259a1eb4dae2e5512cba9955e2b540a6fc6" +dependencies = [ + "base64 0.21.4", + "bollard-stubs", + "bytes", + "futures-core", + "futures-util", + "hex", + "http", + "hyper", + "hyperlocal", + "log", + "pin-project-lite", + "serde", + "serde_derive", + "serde_json", + "serde_repr", + "serde_urlencoded", + "thiserror", + "tokio", + "tokio-util", + "url", + "winapi", +] + +[[package]] +name = "bollard-stubs" +version = "1.43.0-rc.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b58071e8fd9ec1e930efd28e3a90c1251015872a2ce49f81f36421b86466932e" +dependencies = [ + "serde", + "serde_repr", + "serde_with 3.4.0", +] + +[[package]] +name = "borsh" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15bf3650200d8bffa99015595e10f1fbd17de07abbc25bb067da79e769939bfa" +dependencies = [ + "borsh-derive 0.9.3", + "hashbrown 0.11.2", +] + +[[package]] +name = "borsh" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4114279215a005bc675e386011e594e1d9b800918cea18fcadadcce864a2046b" +dependencies = [ + "borsh-derive 0.10.3", + "hashbrown 0.13.2", +] + +[[package]] +name = "borsh-derive" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6441c552f230375d18e3cc377677914d2ca2b0d36e52129fe15450a2dce46775" +dependencies = [ + "borsh-derive-internal 0.9.3", + "borsh-schema-derive-internal 0.9.3", + "proc-macro-crate 0.1.5", + "proc-macro2", + "syn 1.0.109", +] + +[[package]] +name = "borsh-derive" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0754613691538d51f329cce9af41d7b7ca150bc973056f1156611489475f54f7" +dependencies = [ + "borsh-derive-internal 0.10.3", + "borsh-schema-derive-internal 0.10.3", + "proc-macro-crate 0.1.5", + "proc-macro2", + "syn 1.0.109", +] + +[[package]] +name = "borsh-derive-internal" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5449c28a7b352f2d1e592a8a28bf139bc71afb0764a14f3c02500935d8c44065" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "borsh-derive-internal" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afb438156919598d2c7bad7e1c0adf3d26ed3840dbc010db1a882a65583ca2fb" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "borsh-schema-derive-internal" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdbd5696d8bfa21d53d9fe39a714a18538bad11492a42d066dbbc395fb1951c0" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "borsh-schema-derive-internal" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634205cc43f74a1b9046ef87c4540ebda95696ec0f315024860cad7c5b0f5ccd" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "bounded-collections" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca548b6163b872067dc5eb82fd130c56881435e30367d2073594a3d9744120dd" +dependencies = [ + "log", + "parity-scale-codec", + "scale-info", + "serde", +] + +[[package]] +name = "brotli" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "516074a47ef4bce09577a3b379392300159ce5b1ba2e501ff1c819950066100f" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", + "brotli-decompressor", +] + +[[package]] +name = "brotli-decompressor" +version = "2.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e2e4afe60d7dd600fdd3de8d0f08c2b7ec039712e3b6137ff98b7004e82de4f" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", +] + +[[package]] +name = "brownstone" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "030ea61398f34f1395ccbeb046fb68c87b631d1f34567fed0f0f11fa35d18d8d" +dependencies = [ + "arrayvec 0.7.4", +] + +[[package]] +name = "bs58" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" + +[[package]] +name = "bs58" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5353f36341f7451062466f0b755b96ac3a9547e4d7f6b70d603fc721a7d7896" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "bumpalo" +version = "3.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" + +[[package]] +name = "bv" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8834bb1d8ee5dc048ee3124f2c7c1afcc6bc9aed03f11e9dfd8c69470a5db340" +dependencies = [ + "feature-probe", + "serde", +] + +[[package]] +name = "byte-slice-cast" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" + +[[package]] +name = "byte-tools" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" + +[[package]] +name = "bytecheck" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b6372023ac861f6e6dc89c8344a8f398fb42aaba2b5dbc649ca0c0e9dbcb627" +dependencies = [ + "bytecheck_derive", + "ptr_meta", + "simdutf8", +] + +[[package]] +name = "bytecheck_derive" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7ec4c6f261935ad534c0c22dbef2201b45918860eb1c574b972bd213a76af61" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "bytemuck" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "965ab7eb5f8f97d2a083c799f3a1b994fc397b2fe2da5d1da1626ce15a39f2b1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" + +[[package]] +name = "camino" +version = "1.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" +dependencies = [ + "serde", +] + +[[package]] +name = "caps" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "190baaad529bcfbde9e1a19022c42781bdb6ff9de25721abdb8fd98c0807730b" +dependencies = [ + "libc", + "thiserror", +] + +[[package]] +name = "cargo-platform" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12024c4645c97566567129c204f65d5815a8c9aecf30fcbe682b2fe034996d36" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo_metadata" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037" +dependencies = [ + "camino", + "cargo-platform", + "semver", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "cast" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c24dab4283a142afa2fdca129b80ad2c6284e073930f964c3a1293c225ee39a" +dependencies = [ + "rustc_version", +] + +[[package]] +name = "cc" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "jobserver", + "libc", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chacha20" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c80e5460aa66fe3b91d40bcbdab953a597b60053e34d684ac6903f863b680a6" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", + "zeroize", +] + +[[package]] +name = "chacha20poly1305" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a18446b09be63d457bbec447509e85f662f32952b035ce892290396bc0b0cff5" +dependencies = [ + "aead", + "chacha20", + "cipher", + "poly1305", + "zeroize", +] + +[[package]] +name = "chrono" +version = "0.4.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "js-sys", + "num-traits", + "serde", + "wasm-bindgen", + "windows-targets 0.48.5", +] + +[[package]] +name = "cipher" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" +dependencies = [ + "generic-array 0.14.7", +] + +[[package]] +name = "clap" +version = "2.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +dependencies = [ + "ansi_term", + "atty", + "bitflags 1.3.2", + "strsim 0.8.0", + "textwrap 0.11.0", + "unicode-width", + "vec_map", +] + +[[package]] +name = "clap" +version = "3.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" +dependencies = [ + "atty", + "bitflags 1.3.2", + "clap_lex 0.2.4", + "indexmap 1.9.3", + "once_cell", + "strsim 0.10.0", + "termcolor", + "textwrap 0.16.0", +] + +[[package]] +name = "clap" +version = "4.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac495e00dcec98c83465d5ad66c5c4fabd652fd6686e7c6269b117e729a6f17b" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c77ed9a32a62e6ca27175d00d29d05ca32e396ea1eb5fb01d8256b669cec7663" +dependencies = [ + "anstream", + "anstyle", + "clap_lex 0.6.0", + "strsim 0.10.0", +] + +[[package]] +name = "clap_derive" +version = "4.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" +dependencies = [ + "heck 0.4.1", + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[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 = "clap_lex" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" + +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", +] + +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + +[[package]] +name = "colored" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2674ec482fbc38012cf31e6c42ba0177b431a0cb6f15fe40efa5aab1bda516f6" +dependencies = [ + "is-terminal", + "lazy_static", + "windows-sys 0.48.0", +] + +[[package]] +name = "combine" +version = "3.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da3da6baa321ec19e1cc41d31bf599f00c783d0517095cdaf0332e3fe8d20680" +dependencies = [ + "ascii", + "byteorder", + "either", + "memchr", + "unreachable", +] + +[[package]] +name = "concurrent-queue" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f057a694a54f12365049b0958a1685bb52d567f5593b355fbf685838e873d400" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "console" +version = "0.15.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c926e00cc70edefdc64d3a5ff31cc65bb97a3460097762bd23afb4d8145fccf8" +dependencies = [ + "encode_unicode", + "lazy_static", + "libc", + "unicode-width", + "windows-sys 0.45.0", +] + +[[package]] +name = "console_error_panic_hook" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" +dependencies = [ + "cfg-if", + "wasm-bindgen", +] + +[[package]] +name = "console_log" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89f72f65e8501878b8a004d5a1afb780987e2ce2b4532c562e367a72c57499f" +dependencies = [ + "log", + "web-sys", +] + +[[package]] +name = "const-oid" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4c78c047431fee22c1a7bb92e00ad095a02a983affe4d8a72e2a2c62c1b94f3" + +[[package]] +name = "const_env" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e9e4f72c6e3398ca6da372abd9affd8f89781fe728869bbf986206e9af9627e" +dependencies = [ + "const_env_impl", +] + +[[package]] +name = "const_env_impl" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a4f51209740b5e1589e702b3044cdd4562cef41b6da404904192ffffb852d62" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "const_format" +version = "0.2.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a214c7af3d04997541b18d432afaff4c455e79e2029079647e72fc2bd27673" +dependencies = [ + "const_format_proc_macros", +] + +[[package]] +name = "const_format_proc_macros" +version = "0.2.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7f6ff08fd20f4f299298a28e2dfa8a8ba1036e6cd2460ac1de7b425d76f2500" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "constant_time_eq" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" + +[[package]] +name = "constant_time_eq" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" + +[[package]] +name = "contract-build" +version = "4.0.0-alpha" +source = "git+https://github.com/paritytech/cargo-contract?rev=dfdc768bc430ba6e2967a482cb3016dba3785726#dfdc768bc430ba6e2967a482cb3016dba3785726" +dependencies = [ + "anyhow", + "blake2", + "bollard", + "cargo_metadata", + "clap 4.4.7", + "colored", + "contract-metadata", + "crossterm", + "duct", + "heck 0.4.1", + "hex", + "impl-serde", + "parity-scale-codec", + "parity-wasm", + "regex", + "rustc_version", + "semver", + "serde", + "serde_json", + "strum 0.25.0", + "tempfile", + "term_size", + "tokio", + "tokio-stream", + "toml 0.8.6", + "tracing", + "url", + "users", + "walkdir", + "wasm-opt", + "which", + "zip", +] + +[[package]] +name = "contract-extrinsics" +version = "4.0.0-alpha" +source = "git+https://github.com/paritytech/cargo-contract?rev=dfdc768bc430ba6e2967a482cb3016dba3785726#dfdc768bc430ba6e2967a482cb3016dba3785726" +dependencies = [ + "anyhow", + "clap 4.4.7", + "colored", + "contract-build", + "contract-metadata", + "contract-transcode", + "futures", + "hex", + "pallet-contracts-primitives", + "parity-scale-codec", + "rust_decimal", + "scale-info", + "serde", + "serde_json", + "sp-core", + "sp-runtime", + "sp-weights", + "subxt", + "subxt-signer", + "tokio", + "tracing", + "url", +] + +[[package]] +name = "contract-metadata" +version = "4.0.0-alpha" +source = "git+https://github.com/paritytech/cargo-contract?rev=dfdc768bc430ba6e2967a482cb3016dba3785726#dfdc768bc430ba6e2967a482cb3016dba3785726" +dependencies = [ + "anyhow", + "impl-serde", + "semver", + "serde", + "serde_json", + "url", +] + +[[package]] +name = "contract-transcode" +version = "4.0.0-alpha" +source = "git+https://github.com/paritytech/cargo-contract?rev=dfdc768bc430ba6e2967a482cb3016dba3785726#dfdc768bc430ba6e2967a482cb3016dba3785726" +dependencies = [ + "anyhow", + "base58", + "blake2", + "contract-metadata", + "escape8259", + "hex", + "indexmap 2.0.2", + "ink_env", + "ink_metadata", + "itertools 0.11.0", + "nom", + "nom-supreme", + "parity-scale-codec", + "primitive-types", + "scale-info", + "serde", + "serde_json", + "strsim 0.10.0", + "thiserror", + "tracing", +] + +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + +[[package]] +name = "convert_case" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" +dependencies = [ + "unicode-segmentation", +] + +[[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.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" + +[[package]] +name = "cpp_demangle" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eeaa953eaad386a53111e47172c2fedba671e5684c8dd601a5f474f4f118710f" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "cpufeatures" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" +dependencies = [ + "libc", +] + +[[package]] +name = "cranelift-entity" +version = "0.95.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40099d38061b37e505e63f89bab52199037a72b931ad4868d9089ff7268660b0" +dependencies = [ + "serde", +] + +[[package]] +name = "crc32fast" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "criterion-stats" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "387df94cb74ada1b33e10ce034bb0d9360cc73edb5063e7d7d4120a40ee1c9d2" +dependencies = [ + "cast", + "num-traits", + "num_cpus", + "rand 0.4.6", + "thread-scoped", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" +dependencies = [ + "autocfg", + "cfg-if", + "crossbeam-utils", + "memoffset 0.9.0", + "scopeguard", +] + +[[package]] +name = "crossbeam-queue" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossterm" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df" +dependencies = [ + "bitflags 2.4.1", + "crossterm_winapi", + "libc", + "mio", + "parking_lot", + "signal-hook", + "signal-hook-mio", + "winapi", +] + +[[package]] +name = "crossterm_winapi" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" +dependencies = [ + "winapi", +] + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array 0.14.7", + "typenum", +] + +[[package]] +name = "crypto-mac" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" +dependencies = [ + "generic-array 0.14.7", + "subtle", +] + +[[package]] +name = "crypto-mac" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25fab6889090c8133f3deb8f73ba3c65a7f456f66436fc012a1b1e272b1e103e" +dependencies = [ + "generic-array 0.14.7", + "subtle", +] + +[[package]] +name = "ctr" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a232f92a03f37dd7d7dd2adc67166c77e9cd88de5b019b9a9eecfaeaf7bfd481" +dependencies = [ + "cipher", +] + +[[package]] +name = "ctr" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "049bb91fb4aaf0e3c7efa6cd5ef877dbbbd15b39dad06d9948de4ec8a75761ea" +dependencies = [ + "cipher", +] + +[[package]] +name = "ctrlc" +version = "3.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82e95fbd621905b854affdc67943b043a0fbb6ed7385fd5a25650d19a8a6cfdf" +dependencies = [ + "nix 0.27.1", + "windows-sys 0.48.0", +] + +[[package]] +name = "curve25519-dalek" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a9b85542f99a2dfa2a1b8e192662741c9859a846b296bef1c92ef9b58b5a216" +dependencies = [ + "byteorder", + "digest 0.8.1", + "rand_core 0.5.1", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek" +version = "3.2.1" +source = "git+https://github.com/solana-labs/curve25519-dalek.git?rev=c14774464c4d38de553c6ef2f48a10982c1b4801#c14774464c4d38de553c6ef2f48a10982c1b4801" +dependencies = [ + "byteorder", + "digest 0.9.0", + "rand_core 0.5.1", + "serde", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek" +version = "4.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89b8c6a2e4b1f45971ad09761aafb85514a84744b67a95e32c3cc1352d1f65c" +dependencies = [ + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "digest 0.10.7", + "fiat-crypto", + "platforms", + "rustc_version", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83fdaf97f4804dcebfa5862639bc9ce4121e82140bec2a987ac5140294865b5b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "curve25519-dalek-ng" +version = "4.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c359b7249347e46fb28804470d071c921156ad62b3eef5d34e2ba867533dec8" +dependencies = [ + "byteorder", + "digest 0.9.0", + "rand_core 0.6.4", + "subtle-ng", + "zeroize", +] + +[[package]] +name = "cxx" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c390c123d671cc547244943ecad81bdaab756c6ea332d9ca9c1f48d952a24895" +dependencies = [ + "cc", + "cxxbridge-flags", + "cxxbridge-macro", + "link-cplusplus", +] + +[[package]] +name = "cxx-build" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00d3d3ac9ffb900304edf51ca719187c779f4001bb544f26c4511d621de905cf" +dependencies = [ + "cc", + "codespan-reporting", + "once_cell", + "proc-macro2", + "quote", + "scratch", + "syn 2.0.38", +] + +[[package]] +name = "cxxbridge-flags" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94415827ecfea0f0c74c8cad7d1a86ddb3f05354d6a6ddeda0adee5e875d2939" + +[[package]] +name = "cxxbridge-macro" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e33dbbe9f5621c9247f97ec14213b04f350bff4b6cebefe834c60055db266ecf" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "darling" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" +dependencies = [ + "darling_core 0.14.4", + "darling_macro 0.14.4", +] + +[[package]] +name = "darling" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e" +dependencies = [ + "darling_core 0.20.3", + "darling_macro 0.20.3", +] + +[[package]] +name = "darling_core" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim 0.10.0", + "syn 1.0.109", +] + +[[package]] +name = "darling_core" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim 0.10.0", + "syn 2.0.38", +] + +[[package]] +name = "darling_macro" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" +dependencies = [ + "darling_core 0.14.4", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "darling_macro" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" +dependencies = [ + "darling_core 0.20.3", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "dashmap" +version = "4.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e77a43b28d0668df09411cb0bc9a8c2adc40f9a048afe863e05fd43251e8e39c" +dependencies = [ + "cfg-if", + "num_cpus", +] + +[[package]] +name = "data-encoding" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" + +[[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.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbd676fbbab537128ef0278adb5576cf363cff6aa22a7b24effe97347cfab61e" +dependencies = [ + "asn1-rs", + "displaydoc", + "nom", + "num-bigint 0.4.4", + "num-traits", + "rusticata-macros", +] + +[[package]] +name = "deranged" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f32d04922c60427da6f9fef14d042d9edddef64cb9d4ce0d64d0685fbeb1fd3" +dependencies = [ + "powerfmt", + "serde", +] + +[[package]] +name = "derivation-path" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e5c37193a1db1d8ed868c03ec7b152175f26160a5b740e5e484143877e0adf0" + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "convert_case 0.4.0", + "proc-macro2", + "quote", + "rustc_version", + "syn 1.0.109", +] + +[[package]] +name = "dialoguer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59c6f2989294b9a498d3ad5491a79c6deb604617378e1cdc4bfc1c1361fe2f87" +dependencies = [ + "console", + "shell-words", + "tempfile", + "zeroize", +] + +[[package]] +name = "digest" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" +dependencies = [ + "generic-array 0.12.4", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array 0.14.7", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer 0.10.4", + "crypto-common", + "subtle", +] + +[[package]] +name = "dirs-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "displaydoc" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "dlopen2" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09b4f5f101177ff01b8ec4ecc81eead416a8aa42819a2869311b3420fa114ffa" +dependencies = [ + "dlopen2_derive", + "libc", + "once_cell", + "winapi", +] + +[[package]] +name = "dlopen2_derive" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6cbae11b3de8fce2a456e8ea3dada226b35fe791f0dc1d360c0941f0bb681f3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "downcast-rs" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" + +[[package]] +name = "duct" +version = "0.13.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37ae3fc31835f74c2a7ceda3aeede378b0ae2e74c8f1c36559fcc9ae2a4e7d3e" +dependencies = [ + "libc", + "once_cell", + "os_pipe", + "shared_child", +] + +[[package]] +name = "dyn-clonable" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e9232f0e607a262ceb9bd5141a3dfb3e4db6994b31989bbfd845878cba59fd4" +dependencies = [ + "dyn-clonable-impl", + "dyn-clone", +] + +[[package]] +name = "dyn-clonable-impl" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "558e40ea573c374cf53507fd240b7ee2f5477df7cfebdb97323ec61c719399c5" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "dyn-clone" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23d2f3407d9a573d666de4b5bdf10569d73ca9478087346697dcbae6244bfbcd" + +[[package]] +name = "eager" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abe71d579d1812060163dff96056261deb5bf6729b100fa2e36a68b9649ba3d3" + +[[package]] +name = "ed25519" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91cff35c70bba8a626e3185d8cd48cc11b5437e1a5bcd15b9b5fa3c64b6dfee7" +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 3.2.1", + "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", + "hmac 0.12.1", + "sha2 0.10.8", +] + +[[package]] +name = "ed25519-zebra" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c24f403d068ad0b359e577a77f92392118be3f3c927538f2bb544a5ecd828c6" +dependencies = [ + "curve25519-dalek 3.2.1", + "hashbrown 0.12.3", + "hex", + "rand_core 0.6.4", + "sha2 0.9.9", + "zeroize", +] + +[[package]] +name = "either" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" + +[[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.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "enum-iterator" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7add3873b5dd076766ee79c8e406ad1a472c385476b9e38849f8eec24f1be689" +dependencies = [ + "enum-iterator-derive", +] + +[[package]] +name = "enum-iterator-derive" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eecf8589574ce9b895052fa12d69af7a233f99e6107f5cb8dd1044f2a17bfdcb" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "env_logger" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7" +dependencies = [ + "atty", + "humantime", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "environmental" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e48c92028aaa870e83d51c64e5d4e0b6981b360c522198c23959f219a4e1b15b" + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860" +dependencies = [ + "libc", + "windows-sys 0.48.0", +] + +[[package]] +name = "escape8259" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba4f4911e3666fcd7826997b4745c8224295a6f3072f1418c3067b97a67557ee" +dependencies = [ + "rustversion", +] + +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + +[[package]] +name = "event-listener" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29e56284f00d94c1bc7fd3c77027b4623c88c1f53d8d2394c6199f2921dea325" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "fake-simd" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" + +[[package]] +name = "fallible-iterator" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" + +[[package]] +name = "fastrand" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +dependencies = [ + "instant", +] + +[[package]] +name = "fastrand" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" + +[[package]] +name = "feature-probe" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835a3dc7d1ec9e75e2b5fb4ba75396837112d2060b03f7d43bc1897c7f7211da" + +[[package]] +name = "fiat-crypto" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0870c84016d4b481be5c9f323c24f65e31e901ae618f0e80f4308fb00de1d2d" + +[[package]] +name = "fixed-hash" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" +dependencies = [ + "byteorder", + "rand 0.8.5", + "rustc-hex", + "static_assertions", +] + +[[package]] +name = "flate2" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "form_urlencoded" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "frame-metadata" +version = "15.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "878babb0b136e731cc77ec2fd883ff02745ff21e6fb662729953d44923df009c" +dependencies = [ + "cfg-if", + "parity-scale-codec", + "scale-info", +] + +[[package]] +name = "frame-metadata" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cf1549fba25a6fcac22785b61698317d958e96cac72a59102ea45b9ae64692" +dependencies = [ + "cfg-if", + "parity-scale-codec", + "scale-info", + "serde", +] + +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "futures" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" + +[[package]] +name = "futures-executor" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", + "num_cpus", +] + +[[package]] +name = "futures-io" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" + +[[package]] +name = "futures-lite" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" +dependencies = [ + "fastrand 1.9.0", + "futures-core", + "futures-io", + "memchr", + "parking", + "pin-project-lite", + "waker-fn", +] + +[[package]] +name = "futures-macro" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "futures-sink" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" + +[[package]] +name = "futures-task" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" + +[[package]] +name = "futures-timer" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" + +[[package]] +name = "futures-util" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" +dependencies = [ + "typenum", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "serde", + "typenum", + "version_check", +] + +[[package]] +name = "gethostname" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1ebd34e35c46e00bb73e81363248d627782724609fe1b6396f553f68fe3862e" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", + "wasm-bindgen", +] + +[[package]] +name = "ghash" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1583cc1656d7839fd3732b80cf4f38850336cdb9b8ded1cd399ca62958de3c99" +dependencies = [ + "opaque-debug 0.3.0", + "polyval", +] + +[[package]] +name = "gimli" +version = "0.27.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" +dependencies = [ + "fallible-iterator", + "indexmap 1.9.3", + "stable_deref_trait", +] + +[[package]] +name = "gimli" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" + +[[package]] +name = "goblin" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7666983ed0dd8d21a6f6576ee00053ca0926fb281a5522577a4dbd0f1b54143" +dependencies = [ + "log", + "plain", + "scroll", +] + +[[package]] +name = "h2" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91fc23aa11be92976ef4729127f1a74adf36d8436f7816b185d18df956790833" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap 1.9.3", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hash-db" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e7d7786361d7425ae2fe4f9e407eb0efaa0840f5212d109cc018c40c35c6ab4" + +[[package]] +name = "hash256-std-hasher" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92c171d55b98633f4ed3860808f004099b36c1cc29c42cfc53aa8591b21efcf2" +dependencies = [ + "crunchy", +] + +[[package]] +name = "hash32" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" +dependencies = [ + "byteorder", +] + +[[package]] +name = "hashbrown" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +dependencies = [ + "ahash 0.7.6", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash 0.7.6", +] + +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash 0.8.3", +] + +[[package]] +name = "hashbrown" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dfda62a12f55daeae5015f81b0baea145391cb4520f86c248fc615d72640d12" +dependencies = [ + "serde", +] + +[[package]] +name = "heck" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "hermit-abi" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hidapi" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "723777263b0dcc5730aec947496bd8c3940ba63c15f5633b288cc615f4f6af79" +dependencies = [ + "cc", + "libc", + "pkg-config", + "winapi", +] + +[[package]] +name = "histogram" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12cb882ccb290b8646e554b157ab0b71e64e8d5bef775cd66b6531e52d302669" + +[[package]] +name = "hmac" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "126888268dcc288495a26bf004b38c5fdbb31682f992c84ceb046a1f0fe38840" +dependencies = [ + "crypto-mac 0.8.0", + "digest 0.9.0", +] + +[[package]] +name = "hmac" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b" +dependencies = [ + "crypto-mac 0.11.0", + "digest 0.9.0", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "hmac-drbg" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17ea0a1394df5b6574da6e0c1ade9e78868c9fb0a4e5ef4428e32da4676b85b1" +dependencies = [ + "digest 0.9.0", + "generic-array 0.14.7", + "hmac 0.8.1", +] + +[[package]] +name = "home" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" +dependencies = [ + "windows-sys 0.48.0", +] + +[[package]] +name = "http" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "hyper" +version = "0.14.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2 0.4.9", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d78e1e73ec14cf7375674f74d7dde185c8206fd9dea6fb6295e8a98098aaa97" +dependencies = [ + "futures-util", + "http", + "hyper", + "log", + "rustls", + "rustls-native-certs", + "tokio", + "tokio-rustls", +] + +[[package]] +name = "hyperlocal" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fafdf7b2b2de7c9784f76e02c0935e65a8117ec3b768644379983ab333ac98c" +dependencies = [ + "futures-util", + "hex", + "hyper", + "pin-project", + "tokio", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +dependencies = [ + "unicode-bidi", + "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.4", + "rand_xoshiro", + "rayon", + "serde", + "sized-chunks", + "typenum", + "version_check", +] + +[[package]] +name = "impl-codec" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" +dependencies = [ + "parity-scale-codec", +] + +[[package]] +name = "impl-serde" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc88fc67028ae3db0c853baa36269d398d5f45b6982f95549ff5def78c935cd" +dependencies = [ + "serde", +] + +[[package]] +name = "impl-trait-for-tuples" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "indent_write" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cfe9645a18782869361d9c8732246be7b410ad4e919d3609ebabdac00ba12c3" + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + +[[package]] +name = "indexmap" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897" +dependencies = [ + "equivalent", + "hashbrown 0.14.1", + "serde", +] + +[[package]] +name = "indexmap-nostd" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e04e2fd2b8188ea827b32ef11de88377086d690286ab35747ef7f9bf3ccb590" + +[[package]] +name = "indicatif" +version = "0.17.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb28741c9db9a713d93deb3bb9515c20788cef5815265bee4980e87bde7e0f25" +dependencies = [ + "console", + "instant", + "number_prefix", + "portable-atomic", + "unicode-width", +] + +[[package]] +name = "ink_allocator" +version = "5.0.0-alpha" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "688a37ac26b6e101f6a263ab8e8b0ceac84b36cb805129a666cefed3ebf362e8" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "ink_engine" +version = "5.0.0-alpha" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d34dd340d4a2c2d1bb81cf52c8bdef71698871bba13a065f500a69508f23a171" +dependencies = [ + "blake2", + "derive_more", + "ink_primitives", + "parity-scale-codec", + "secp256k1 0.27.0", + "sha2 0.10.8", + "sha3 0.10.8", +] + +[[package]] +name = "ink_env" +version = "5.0.0-alpha" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16a28d3afbae0b316a0a5e86cd81704d67c98244d8c299fe88eee13f5c4dac0e" +dependencies = [ + "blake2", + "cfg-if", + "const_env", + "derive_more", + "ink_allocator", + "ink_engine", + "ink_prelude", + "ink_primitives", + "ink_storage_traits", + "num-traits", + "parity-scale-codec", + "paste", + "rlibc", + "scale-decode", + "scale-encode", + "scale-info", + "schnorrkel 0.11.3", + "secp256k1 0.27.0", + "sha2 0.10.8", + "sha3 0.10.8", + "static_assertions", +] + +[[package]] +name = "ink_metadata" +version = "5.0.0-alpha" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ad9535f950e210bf584ba008df5bf4f013e634cf0a468c2cbc6342bbed32014" +dependencies = [ + "derive_more", + "impl-serde", + "ink_prelude", + "ink_primitives", + "linkme", + "scale-info", + "schemars", + "serde", +] + +[[package]] +name = "ink_prelude" +version = "5.0.0-alpha" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74705c00d6993ccadb97675524b5b5d98e7292c49126c2daf87d1da63bed6aa7" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "ink_primitives" +version = "5.0.0-alpha" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "513e93039a85caf84637746e35d0ed0b71ac0ace7e5268650f3d90e413ba989b" +dependencies = [ + "derive_more", + "ink_prelude", + "parity-scale-codec", + "scale-decode", + "scale-encode", + "scale-info", + "xxhash-rust", +] + +[[package]] +name = "ink_storage_traits" +version = "5.0.0-alpha" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23206662b622a5b9053cb21b55bf7b7263b874836c98747717a62073797c5b3e" +dependencies = [ + "ink_metadata", + "ink_prelude", + "ink_primitives", + "parity-scale-codec", + "scale-info", +] + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "integer-sqrt" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "276ec31bcb4a9ee45f58bec6f9ec700ae4cf4f4f8f2fa7e06cb406bd5ffdd770" +dependencies = [ + "num-traits", +] + +[[package]] +name = "intx" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f38a50a899dc47a6d0ed5508e7f601a2e34c3a85303514b5d137f3c10a0c75" + +[[package]] +name = "io-lifetimes" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" +dependencies = [ + "hermit-abi 0.3.3", + "libc", + "windows-sys 0.48.0", +] + +[[package]] +name = "ipnet" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" + +[[package]] +name = "is-terminal" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" +dependencies = [ + "hermit-abi 0.3.3", + "rustix 0.38.19", + "windows-sys 0.48.0", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" + +[[package]] +name = "jobserver" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d" +dependencies = [ + "libc", +] + +[[package]] +name = "joinery" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72167d68f5fce3b8655487b8038691a3c9984ee769590f93f2a631f4ad64e4f5" + +[[package]] +name = "js-sys" +version = "0.3.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +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 = "jsonrpsee" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de902baa44bf34a58b1a4906f8b840d7d60dcec5f41fe08b4dbc14cf9efa821c" +dependencies = [ + "jsonrpsee-client-transport", + "jsonrpsee-core", + "jsonrpsee-http-client", + "jsonrpsee-types", +] + +[[package]] +name = "jsonrpsee-client-transport" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58d9851f8f5653e0433a898e9032bde4910b35d625bd9dcf33ef6e36e7c3d456" +dependencies = [ + "futures-util", + "http", + "jsonrpsee-core", + "pin-project", + "rustls-native-certs", + "soketto", + "thiserror", + "tokio", + "tokio-rustls", + "tokio-util", + "tracing", + "url", +] + +[[package]] +name = "jsonrpsee-core" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51f45d37af23707750136379f6799e76ebfcf2d425ec4e36d0deb7921da5e65c" +dependencies = [ + "anyhow", + "async-lock", + "async-trait", + "beef", + "futures-timer", + "futures-util", + "hyper", + "jsonrpsee-types", + "rustc-hash", + "serde", + "serde_json", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "jsonrpsee-http-client" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02308562f2e8162a32f8d6c3dc19c29c858d5d478047c886a5c3c25b5f7fa868" +dependencies = [ + "async-trait", + "hyper", + "hyper-rustls", + "jsonrpsee-core", + "jsonrpsee-types", + "serde", + "serde_json", + "thiserror", + "tokio", + "tower", + "tracing", + "url", +] + +[[package]] +name = "jsonrpsee-types" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05eaff23af19f10ba6fbb76519bed6da4d3b9bbaef13d39b7c2b6c14e532d27e" +dependencies = [ + "anyhow", + "beef", + "serde", + "serde_json", + "thiserror", + "tracing", +] + +[[package]] +name = "keccak" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f6d5ed8676d904364de097082f4e7d240b571b67989ced0240f08b7f966f940" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.149" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" + +[[package]] +name = "libm" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" + +[[package]] +name = "libsecp256k1" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9d220bc1feda2ac231cb78c3d26f27676b8cf82c96971f7aeef3d0cf2797c73" +dependencies = [ + "arrayref", + "base64 0.12.3", + "digest 0.9.0", + "hmac-drbg", + "libsecp256k1-core 0.2.2", + "libsecp256k1-gen-ecmult 0.2.1", + "libsecp256k1-gen-genmult 0.2.1", + "rand 0.7.3", + "serde", + "sha2 0.9.9", + "typenum", +] + +[[package]] +name = "libsecp256k1" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95b09eff1b35ed3b33b877ced3a691fc7a481919c7e29c53c906226fcf55e2a1" +dependencies = [ + "arrayref", + "base64 0.13.1", + "digest 0.9.0", + "hmac-drbg", + "libsecp256k1-core 0.3.0", + "libsecp256k1-gen-ecmult 0.3.0", + "libsecp256k1-gen-genmult 0.3.0", + "rand 0.8.5", + "serde", + "sha2 0.9.9", + "typenum", +] + +[[package]] +name = "libsecp256k1-core" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0f6ab710cec28cef759c5f18671a27dae2a5f952cdaaee1d8e2908cb2478a80" +dependencies = [ + "crunchy", + "digest 0.9.0", + "subtle", +] + +[[package]] +name = "libsecp256k1-core" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be9b9bb642d8522a44d533eab56c16c738301965504753b03ad1de3425d5451" +dependencies = [ + "crunchy", + "digest 0.9.0", + "subtle", +] + +[[package]] +name = "libsecp256k1-gen-ecmult" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccab96b584d38fac86a83f07e659f0deafd0253dc096dab5a36d53efe653c5c3" +dependencies = [ + "libsecp256k1-core 0.2.2", +] + +[[package]] +name = "libsecp256k1-gen-ecmult" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3038c808c55c87e8a172643a7d87187fc6c4174468159cb3090659d55bcb4809" +dependencies = [ + "libsecp256k1-core 0.3.0", +] + +[[package]] +name = "libsecp256k1-gen-genmult" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67abfe149395e3aa1c48a2beb32b068e2334402df8181f818d3aee2b304c4f5d" +dependencies = [ + "libsecp256k1-core 0.2.2", +] + +[[package]] +name = "libsecp256k1-gen-genmult" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3db8d6ba2cec9eacc40e6e8ccc98931840301f1006e95647ceb2dd5c3aa06f7c" +dependencies = [ + "libsecp256k1-core 0.3.0", +] + +[[package]] +name = "light-poseidon" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "949bdd22e4ed93481d45e9a6badb34b99132bcad0c8a8d4f05c42f7dcc7b90bc" +dependencies = [ + "ark-bn254", + "ark-ff", + "thiserror", +] + +[[package]] +name = "link-cplusplus" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d240c6f7e1ba3a28b0249f774e6a9dd0175054b52dfbb61b16eb8505c3785c9" +dependencies = [ + "cc", +] + +[[package]] +name = "linkme" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ed2ee9464ff9707af8e9ad834cffa4802f072caad90639c583dd3c62e6e608" +dependencies = [ + "linkme-impl", +] + +[[package]] +name = "linkme-impl" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba125974b109d512fccbc6c0244e7580143e460895dfd6ea7f8bbb692fd94396" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "linux-raw-sys" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" + +[[package]] +name = "linux-raw-sys" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" + +[[package]] +name = "linux-raw-sys" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f" + +[[package]] +name = "lock_api" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" + +[[package]] +name = "lru" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "718e8fae447df0c7e1ba7f5189829e63fd536945c8988d61444c19039f16b670" + +[[package]] +name = "mach" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa" +dependencies = [ + "libc", +] + +[[package]] +name = "matchers" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f099785f7595cc4b4553a174ce30dd7589ef93391ff414dbb67f62392b9e0ce1" +dependencies = [ + "regex-automata 0.1.10", +] + +[[package]] +name = "memchr" +version = "2.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" + +[[package]] +name = "memfd" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2cffa4ad52c6f791f4f8b15f0c05f9824b2ced1160e88cc393d64fff9a8ac64" +dependencies = [ + "rustix 0.38.19", +] + +[[package]] +name = "memmap2" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" +dependencies = [ + "libc", +] + +[[package]] +name = "memoffset" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" +dependencies = [ + "autocfg", +] + +[[package]] +name = "memoffset" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1" +dependencies = [ + "autocfg", +] + +[[package]] +name = "memoffset" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" +dependencies = [ + "autocfg", +] + +[[package]] +name = "memory-db" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808b50db46293432a45e63bc15ea51e0ab4c0a1647b8eb114e31a3e698dd6fbe" +dependencies = [ + "hash-db", +] + +[[package]] +name = "merlin" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e261cf0f8b3c42ded9f7d2bb59dea03aa52bc8a1cbc7482f9fc3fd1229d3b42" +dependencies = [ + "byteorder", + "keccak", + "rand_core 0.5.1", + "zeroize", +] + +[[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.4", + "zeroize", +] + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[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.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" +dependencies = [ + "libc", + "log", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys 0.48.0", +] + +[[package]] +name = "nix" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" +dependencies = [ + "bitflags 1.3.2", + "cfg-if", + "libc", + "memoffset 0.7.1", + "pin-utils", +] + +[[package]] +name = "nix" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" +dependencies = [ + "bitflags 2.4.1", + "cfg-if", + "libc", +] + +[[package]] +name = "no-std-net" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43794a0ace135be66a25d3ae77d41b91615fb68ae937f904090203e81f755b65" + +[[package]] +name = "nodrop" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" + +[[package]] +name = "nohash-hasher" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "nom-supreme" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f909b25a8371ad5c054abc2c48205d677231e6a2dcbf83704ed57bb147f30e0" +dependencies = [ + "brownstone", + "indent_write", + "joinery", + "memchr", + "nom", +] + +[[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 0.2.4", + "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.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", + "rand 0.8.5", + "serde", +] + +[[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", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "num-derive" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfb77679af88f8b125209d354a202862602672222e7f2313fdd6dc349bad4712" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "num-format" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a652d9771a63711fd3c3deb670acfbe5c30a4072e664d7a3bf5a9e1056ac72c3" +dependencies = [ + "arrayvec 0.7.4", + "itoa", +] + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +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-rational" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +dependencies = [ + "autocfg", + "num-bigint 0.4.4", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi 0.3.3", + "libc", +] + +[[package]] +name = "num_enum" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a015b430d3c108a207fd776d2e2196aaf8b1cf8cf93253e3a097ff3085076a1" +dependencies = [ + "num_enum_derive 0.6.1", +] + +[[package]] +name = "num_enum" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683751d591e6d81200c39fb0d1032608b77724f34114db54f571ff1317b337c0" +dependencies = [ + "num_enum_derive 0.7.1", +] + +[[package]] +name = "num_enum_derive" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96667db765a921f7b295ffee8b60472b686a51d4f21c2ee4ffdb94c7013b65a6" +dependencies = [ + "proc-macro-crate 1.3.1", + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c11e44798ad209ccdd91fc192f0526a369a01234f7373e1b141c96d7cee4f0e" +dependencies = [ + "proc-macro-crate 1.3.1", + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "number_prefix" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" + +[[package]] +name = "object" +version = "0.30.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03b4680b86d9cfafba8fc491dc9b6df26b68cf40e9e6cd73909194759a63c385" +dependencies = [ + "crc32fast", + "hashbrown 0.13.2", + "indexmap 1.9.3", + "memchr", +] + +[[package]] +name = "object" +version = "0.32.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +dependencies = [ + "memchr", +] + +[[package]] +name = "oid-registry" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bedf36ffb6ba96c2eb7144ef6270557b52e54b20c0a8e1eb2ff99a6c6959bff" +dependencies = [ + "asn1-rs", +] + +[[package]] +name = "once_cell" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" + +[[package]] +name = "opaque-debug" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" + +[[package]] +name = "opaque-debug" +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 = "os_pipe" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ae859aa07428ca9a929b936690f8b12dc5f11dd8c6992a18ca93919f28bc177" +dependencies = [ + "libc", + "windows-sys 0.48.0", +] + +[[package]] +name = "os_str_bytes" +version = "6.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" + +[[package]] +name = "pallet-contracts-primitives" +version = "25.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b9764b128f0712530bcd14cb01f1d8529f98c4e67866a22221b84fbe5854d93" +dependencies = [ + "bitflags 1.3.2", + "parity-scale-codec", + "scale-info", + "sp-runtime", + "sp-std 9.0.0", + "sp-weights", +] + +[[package]] +name = "parity-scale-codec" +version = "3.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dec8a8073036902368c2cdc0387e85ff9a37054d7e7c98e592145e0c92cd4fb" +dependencies = [ + "arrayvec 0.7.4", + "bitvec", + "byte-slice-cast", + "bytes", + "impl-trait-for-tuples", + "parity-scale-codec-derive", + "serde", +] + +[[package]] +name = "parity-scale-codec-derive" +version = "3.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "312270ee71e1cd70289dacf597cab7b207aa107d2f28191c2ae45b2ece18a260" +dependencies = [ + "proc-macro-crate 1.3.1", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "parity-wasm" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1ad0aff30c1da14b1254fcb2af73e1fa9a28670e584a626f53a369d0e157304" + +[[package]] +name = "parking" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" + +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall 0.3.5", + "smallvec", + "windows-targets 0.48.5", +] + +[[package]] +name = "paste" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" + +[[package]] +name = "pbkdf2" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "216eaa586a190f0a738f2f918511eecfa90f13295abec0e457cdebcceda80cbd" +dependencies = [ + "crypto-mac 0.8.0", +] + +[[package]] +name = "pbkdf2" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d95f5254224e617595d2cc3cc73ff0a5eaf2637519e25f03388154e9378b6ffa" +dependencies = [ + "crypto-mac 0.11.0", +] + +[[package]] +name = "pbkdf2" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "pbkdf2" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "pem" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8835c273a76a90455d7344889b0964598e3316e2a79ede8e36f16bdcf2228b8" +dependencies = [ + "base64 0.13.1", +] + +[[package]] +name = "percent-encoding" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" + +[[package]] +name = "percentage" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fd23b938276f14057220b707937bcb42fa76dda7560e57a2da30cb52d557937" +dependencies = [ + "num", +] + +[[package]] +name = "pin-project" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "piper" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "668d31b1c4eba19242f2088b2bf3316b82ca31082a8335764db4e083db7485d4" +dependencies = [ + "atomic-waker", + "fastrand 2.0.1", + "futures-io", +] + +[[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.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" + +[[package]] +name = "plain" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" + +[[package]] +name = "platforms" +version = "3.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4503fa043bf02cee09a9582e9554b4c6403b2ef55e4612e96561d294419429f8" + +[[package]] +name = "polling" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" +dependencies = [ + "autocfg", + "bitflags 1.3.2", + "cfg-if", + "concurrent-queue", + "libc", + "log", + "pin-project-lite", + "windows-sys 0.48.0", +] + +[[package]] +name = "poly1305" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "048aeb476be11a4b6ca432ca569e375810de9294ae78f4774e78ea98a9246ede" +dependencies = [ + "cpufeatures", + "opaque-debug 0.3.0", + "universal-hash", +] + +[[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 0.3.0", + "universal-hash", +] + +[[package]] +name = "portable-atomic" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b559898e0b4931ed2d3b959ab0c2da4d99cc644c4b0b1a35b4d344027f474023" + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "pretty-hex" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6fa0831dd7cc608c38a5e323422a0077678fa5744aa2be4ad91c4ece8eec8d5" + +[[package]] +name = "primitive-types" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" +dependencies = [ + "fixed-hash", + "impl-codec", + "impl-serde", + "scale-info", + "uint", +] + +[[package]] +name = "proc-macro-crate" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" +dependencies = [ + "toml 0.5.11", +] + +[[package]] +name = "proc-macro-crate" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +dependencies = [ + "once_cell", + "toml_edit 0.19.15", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "psm" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5787f7cda34e3033a72192c018bc5883100330f362ef279a8cbccfce8bb4e874" +dependencies = [ + "cc", +] + +[[package]] +name = "ptr_meta" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1" +dependencies = [ + "ptr_meta_derive", +] + +[[package]] +name = "ptr_meta_derive" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "qstring" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d464fae65fff2680baf48019211ce37aaec0c78e9264c84a3e484717f965104e" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "qualifier_attr" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e2e25ee72f5b24d773cae88422baddefff7714f97aab68d96fe2b6fc4a28fb2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "quinn" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cc2c5017e4b43d5995dcea317bc46c1e09404c0a9664d2908f7f02dfe943d75" +dependencies = [ + "bytes", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "quinn-proto" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c78e758510582acc40acb90458401172d41f1016f8c9dde89e49677afb7eec1" +dependencies = [ + "bytes", + "rand 0.8.5", + "ring", + "rustc-hash", + "rustls", + "rustls-native-certs", + "slab", + "thiserror", + "tinyvec", + "tracing", +] + +[[package]] +name = "quinn-udp" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "055b4e778e8feb9f93c4e439f71dc2156ef13360b432b799e179a8c4cdf0b1d7" +dependencies = [ + "bytes", + "libc", + "socket2 0.5.4", + "tracing", + "windows-sys 0.48.0", +] + +[[package]] +name = "quote" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "rand" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" +dependencies = [ + "fuchsia-cprng", + "libc", + "rand_core 0.3.1", + "rdrand", + "winapi", +] + +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom 0.1.16", + "libc", + "rand_chacha 0.2.2", + "rand_core 0.5.1", + "rand_hc", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core 0.5.1", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_core" +version = "0.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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom 0.1.16", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.10", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core 0.5.1", +] + +[[package]] +name = "rand_xoshiro" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa" +dependencies = [ + "rand_core 0.6.4", +] + +[[package]] +name = "rayon" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "rcgen" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffbe84efe2f38dea12e9bfc1f65377fdf03e53a18cb3b995faedf7934c7e785b" +dependencies = [ + "pem", + "ring", + "time", + "yasna", +] + +[[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.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_syscall" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_users" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +dependencies = [ + "getrandom 0.2.10", + "redox_syscall 0.2.16", + "thiserror", +] + +[[package]] +name = "ref-cast" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acde58d073e9c79da00f2b5b84eed919c8326832648a5b109b3fce1bb1175280" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f7473c2cfcf90008193dd0e3e16599455cb601a9fce322b5bb55de799664925" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "regex" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aaac441002f822bc9705a681810a4dd2963094b9ca0ddc41cb963a4c189189ea" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata 0.4.2", + "regex-syntax 0.8.2", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", +] + +[[package]] +name = "regex-automata" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5011c7e263a695dc8ca064cddb722af1be54e517a280b12a5356f98366899e5d" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.8.2", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "regex-syntax" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" + +[[package]] +name = "rend" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2571463863a6bd50c32f94402933f03457a3fbaf697a707c5be741e459f08fd" +dependencies = [ + "bytecheck", +] + +[[package]] +name = "reqwest" +version = "0.11.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b" +dependencies = [ + "async-compression", + "base64 0.21.4", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "hyper", + "hyper-rustls", + "ipnet", + "js-sys", + "log", + "mime", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls", + "rustls-pemfile", + "serde", + "serde_json", + "serde_urlencoded", + "system-configuration", + "tokio", + "tokio-rustls", + "tokio-util", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "webpki-roots 0.25.2", + "winreg", +] + +[[package]] +name = "ring" +version = "0.16.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +dependencies = [ + "cc", + "libc", + "once_cell", + "spin 0.5.2", + "untrusted", + "web-sys", + "winapi", +] + +[[package]] +name = "rkyv" +version = "0.7.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0200c8230b013893c0b2d6213d6ec64ed2b9be2e0e016682b7224ff82cff5c58" +dependencies = [ + "bitvec", + "bytecheck", + "hashbrown 0.12.3", + "ptr_meta", + "rend", + "rkyv_derive", + "seahash", + "tinyvec", + "uuid", +] + +[[package]] +name = "rkyv_derive" +version = "0.7.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2e06b915b5c230a17d7a736d1e2e63ee753c256a8614ef3f5147b13a4f5541d" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "rlibc" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc874b127765f014d792f16763a81245ab80500e2ad921ed4ee9e82481ee08fe" + +[[package]] +name = "rpassword" +version = "7.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6678cf63ab3491898c0d021b493c94c9b221d91295294a2a5746eacbe5928322" +dependencies = [ + "libc", + "rtoolbox", + "winapi", +] + +[[package]] +name = "rtoolbox" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "034e22c514f5c0cb8a10ff341b9b048b5ceb21591f31c8f44c43b960f9b3524a" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "rust_decimal" +version = "1.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4c4216490d5a413bc6d10fa4742bd7d4955941d062c0ef873141d6b0e7b30fd" +dependencies = [ + "arrayvec 0.7.4", + "borsh 0.10.3", + "bytes", + "num-traits", + "rand 0.8.5", + "rkyv", + "serde", + "serde_json", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc-hex" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + +[[package]] +name = "rusticata-macros" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faf0c4a6ece9950b9abdb62b1cfcf2a68b3b67a10ba445b3bb85be2a293d0632" +dependencies = [ + "nom", +] + +[[package]] +name = "rustix" +version = "0.36.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6da3636faa25820d8648e0e31c5d519bbb01f72fdf57131f0f5f7da5fed36eab" +dependencies = [ + "bitflags 1.3.2", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys 0.1.4", + "windows-sys 0.45.0", +] + +[[package]] +name = "rustix" +version = "0.37.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84f3f8f960ed3b5a59055428714943298bf3fa2d4a1d53135084e0544829d995" +dependencies = [ + "bitflags 1.3.2", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys 0.3.8", + "windows-sys 0.48.0", +] + +[[package]] +name = "rustix" +version = "0.38.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "745ecfa778e66b2b63c88a61cb36e0eea109e803b0b86bf9879fbc77c70e86ed" +dependencies = [ + "bitflags 2.4.1", + "errno", + "libc", + "linux-raw-sys 0.4.10", + "windows-sys 0.48.0", +] + +[[package]] +name = "rustls" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd8d6c9f025a446bc4d18ad9632e69aec8f287aa84499ee335599fabd20c3fd8" +dependencies = [ + "log", + "ring", + "rustls-webpki", + "sct", +] + +[[package]] +name = "rustls-native-certs" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" +dependencies = [ + "openssl-probe", + "rustls-pemfile", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2" +dependencies = [ + "base64 0.21.4", +] + +[[package]] +name = "rustls-webpki" +version = "0.101.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c7d5dece342910d9ba34d259310cae3e0154b873b35408b787b59bce53d34fe" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "rustversion" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" + +[[package]] +name = "ruzstd" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3ffab8f9715a0d455df4bbb9d21e91135aab3cd3ca187af0cd0c3c3f868fdc" +dependencies = [ + "byteorder", + "thiserror-core", + "twox-hash", +] + +[[package]] +name = "ryu" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "scale-bits" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "036575c29af9b6e4866ffb7fa055dbf623fe7a9cc159b33786de6013a6969d89" +dependencies = [ + "parity-scale-codec", + "scale-info", + "serde", +] + +[[package]] +name = "scale-decode" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7789f5728e4e954aaa20cadcc370b99096fb8645fca3c9333ace44bb18f30095" +dependencies = [ + "derive_more", + "parity-scale-codec", + "primitive-types", + "scale-bits", + "scale-decode-derive", + "scale-info", + "smallvec", +] + +[[package]] +name = "scale-decode-derive" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27873eb6005868f8cc72dcfe109fae664cf51223d35387bc2f28be4c28d94c47" +dependencies = [ + "darling 0.14.4", + "proc-macro-crate 1.3.1", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "scale-encode" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d70cb4b29360105483fac1ed567ff95d65224a14dd275b6303ed0a654c78de5" +dependencies = [ + "derive_more", + "parity-scale-codec", + "primitive-types", + "scale-bits", + "scale-encode-derive", + "scale-info", + "smallvec", +] + +[[package]] +name = "scale-encode-derive" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "995491f110efdc6bea96d6a746140e32bfceb4ea47510750a5467295a4707a25" +dependencies = [ + "darling 0.14.4", + "proc-macro-crate 1.3.1", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "scale-info" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f7d66a1128282b7ef025a8ead62a4a9fcf017382ec53b8ffbf4d7bf77bd3c60" +dependencies = [ + "bitvec", + "cfg-if", + "derive_more", + "parity-scale-codec", + "scale-info-derive", + "schemars", + "serde", +] + +[[package]] +name = "scale-info-derive" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abf2c68b89cafb3b8d918dd07b42be0da66ff202cf1155c5739a4e0c1ea0dc19" +dependencies = [ + "proc-macro-crate 1.3.1", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "scale-value" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6538d1cc1af9c0baf401c57da8a6d4730ef582db0d330d2efa56ec946b5b0283" +dependencies = [ + "base58", + "blake2", + "derive_more", + "either", + "frame-metadata 15.1.0", + "parity-scale-codec", + "scale-bits", + "scale-decode", + "scale-encode", + "scale-info", + "serde", + "yap", +] + +[[package]] +name = "schannel" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" +dependencies = [ + "windows-sys 0.48.0", +] + +[[package]] +name = "schemars" +version = "0.8.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f7b0ce13155372a76ee2e1c5ffba1fe61ede73fbea5630d61eee6fac4929c0c" +dependencies = [ + "dyn-clone", + "schemars_derive", + "serde", + "serde_json", +] + +[[package]] +name = "schemars_derive" +version = "0.8.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e85e2a16b12bdb763244c69ab79363d71db2b4b918a2def53f80b02e0574b13c" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn 1.0.109", +] + +[[package]] +name = "schnellru" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "772575a524feeb803e5b0fcbc6dd9f367e579488197c94c6e4023aad2305774d" +dependencies = [ + "ahash 0.8.3", + "cfg-if", + "hashbrown 0.13.2", +] + +[[package]] +name = "schnorrkel" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "021b403afe70d81eea68f6ea12f6b3c9588e5d536a94c3bf80f15e7faa267862" +dependencies = [ + "arrayref", + "arrayvec 0.5.2", + "curve25519-dalek 2.1.3", + "getrandom 0.1.16", + "merlin 2.0.1", + "rand 0.7.3", + "rand_core 0.5.1", + "sha2 0.8.2", + "subtle", + "zeroize", +] + +[[package]] +name = "schnorrkel" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "844b7645371e6ecdf61ff246ba1958c29e802881a749ae3fb1993675d210d28d" +dependencies = [ + "arrayref", + "arrayvec 0.7.4", + "curve25519-dalek-ng", + "merlin 3.0.0", + "rand_core 0.6.4", + "serde_bytes", + "sha2 0.9.9", + "subtle-ng", + "zeroize", +] + +[[package]] +name = "schnorrkel" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da18ffd9f2f5d01bc0b3050b37ce7728665f926b4dd1157fe3221b05737d924f" +dependencies = [ + "arrayref", + "arrayvec 0.7.4", + "curve25519-dalek 4.1.1", + "merlin 3.0.0", + "rand 0.8.5", + "rand_core 0.6.4", + "serde_bytes", + "sha2 0.10.8", + "subtle", + "zeroize", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "scratch" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3cf7c11c38cb994f3d40e8a8cde3bbd1f72a435e4c49e85d6553d8312306152" + +[[package]] +name = "scroll" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04c565b551bafbef4157586fa379538366e4385d42082f255bfd96e4fe8519da" +dependencies = [ + "scroll_derive", +] + +[[package]] +name = "scroll_derive" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1db149f81d46d2deba7cd3c50772474707729550221e69588478ebf9ada425ae" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "sct" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "seahash" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" + +[[package]] +name = "secp256k1" +version = "0.24.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b1629c9c557ef9b293568b338dddfc8208c98a18c59d722a9d53f859d9c9b62" +dependencies = [ + "secp256k1-sys 0.6.1", +] + +[[package]] +name = "secp256k1" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25996b82292a7a57ed3508f052cfff8640d38d32018784acd714758b43da9c8f" +dependencies = [ + "secp256k1-sys 0.8.1", +] + +[[package]] +name = "secp256k1-sys" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83080e2c2fc1006e625be82e5d1eb6a43b7fd9578b617fcc55814daf286bba4b" +dependencies = [ + "cc", +] + +[[package]] +name = "secp256k1-sys" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70a129b9e9efbfb223753b9163c4ab3b13cff7fd9c7f010fbac25ab4099fa07e" +dependencies = [ + "cc", +] + +[[package]] +name = "secrecy" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bd1c54ea06cfd2f6b63219704de0b9b4f72dcc2b8fdef820be6cd799780e91e" +dependencies = [ + "zeroize", +] + +[[package]] +name = "security-framework" +version = "2.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "semver" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" +dependencies = [ + "serde", +] + +[[package]] +name = "serde" +version = "1.0.189" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e422a44e74ad4001bdc8eede9a4570ab52f71190e9c076d14369f38b9200537" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_bytes" +version = "0.11.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab33ec92f677585af6d88c65593ae2375adde54efdbf16d597f2cbc7a6d368ff" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.189" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e48d1f918009ce3145511378cf68d613e3b3d9137d67272562080d68a2b32d5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "serde_derive_internals" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "serde_json" +version = "1.0.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_repr" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8725e1dfadb3a50f7e5ce0b1a540466f6ed3fe7a0fca2ac2b8b831d31316bd00" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "serde_spanned" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12022b835073e5b11e90a14f86838ceb1c8fb0325b72416845c487ac0fa95e80" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_with" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07ff71d2c147a7b57362cead5e22f772cd52f6ab31cfcd9edcd7f6aeb2a0afbe" +dependencies = [ + "serde", + "serde_with_macros", +] + +[[package]] +name = "serde_with" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64cd236ccc1b7a29e7e2739f27c0b2dd199804abc4290e32f59f3b68d6405c23" +dependencies = [ + "base64 0.21.4", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.0.2", + "serde", + "serde_json", + "time", +] + +[[package]] +name = "serde_with_macros" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "881b6f881b17d13214e5d494c939ebab463d01264ce1811e9d4ac3a882e7695f" +dependencies = [ + "darling 0.20.3", + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "serde_yaml" +version = "0.9.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a49e178e4452f45cb61d0cd8cebc1b0fafd3e41929e996cef79aa3aca91f574" +dependencies = [ + "indexmap 2.0.2", + "itoa", + "ryu", + "serde", + "unsafe-libyaml", +] + +[[package]] +name = "sha-1" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures", + "digest 0.9.0", + "opaque-debug 0.3.0", +] + +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + +[[package]] +name = "sha2" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69" +dependencies = [ + "block-buffer 0.7.3", + "digest 0.8.1", + "fake-simd", + "opaque-debug 0.2.3", +] + +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures", + "digest 0.9.0", + "opaque-debug 0.3.0", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + +[[package]] +name = "sha3" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f81199417d4e5de3f04b1e871023acea7389672c4135918f05aa9cbf2f2fa809" +dependencies = [ + "block-buffer 0.9.0", + "digest 0.9.0", + "keccak", + "opaque-debug 0.3.0", +] + +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest 0.10.7", + "keccak", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shared_child" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0d94659ad3c2137fef23ae75b03d5241d633f8acded53d672decfa0e6e0caef" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "shell-words" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" + +[[package]] +name = "signal-hook" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-mio" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af" +dependencies = [ + "libc", + "mio", + "signal-hook", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +dependencies = [ + "libc", +] + +[[package]] +name = "signature" +version = "1.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" + +[[package]] +name = "simdutf8" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a" + +[[package]] +name = "siphasher" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" + +[[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.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" + +[[package]] +name = "smol" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13f2b548cd8447f8de0fdf1c592929f70f4fc7039a05e47404b0d096ec6987a1" +dependencies = [ + "async-channel", + "async-executor", + "async-fs", + "async-io", + "async-lock", + "async-net", + "async-process", + "blocking", + "futures-lite", +] + +[[package]] +name = "smoldot" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cce5e2881b30bad7ef89f383a816ad0b22c45915911f28499026de4a76d20ee" +dependencies = [ + "arrayvec 0.7.4", + "async-lock", + "atomic", + "base64 0.21.4", + "bip39", + "blake2-rfc", + "bs58 0.5.0", + "crossbeam-queue", + "derive_more", + "ed25519-zebra", + "either", + "event-listener 2.5.3", + "fnv", + "futures-channel", + "futures-util", + "hashbrown 0.14.1", + "hex", + "hmac 0.12.1", + "itertools 0.10.5", + "libsecp256k1 0.7.1", + "merlin 3.0.0", + "no-std-net", + "nom", + "num-bigint 0.4.4", + "num-rational 0.4.1", + "num-traits", + "pbkdf2 0.12.2", + "pin-project", + "rand 0.8.5", + "rand_chacha 0.3.1", + "ruzstd", + "schnorrkel 0.10.2", + "serde", + "serde_json", + "sha2 0.10.8", + "siphasher", + "slab", + "smallvec", + "smol", + "snow", + "soketto", + "tiny-keccak", + "twox-hash", + "wasmi", +] + +[[package]] +name = "smoldot-light" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b2f7b4687b83ff244ef6137735ed5716ad37dcdf3ee16c4eb1a32fb9808fa47" +dependencies = [ + "async-lock", + "blake2-rfc", + "derive_more", + "either", + "event-listener 2.5.3", + "fnv", + "futures-channel", + "futures-util", + "hashbrown 0.14.1", + "hex", + "itertools 0.10.5", + "log", + "lru", + "parking_lot", + "rand 0.8.5", + "serde", + "serde_json", + "siphasher", + "slab", + "smol", + "smoldot", +] + +[[package]] +name = "snow" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c9d1425eb528a21de2755c75af4c9b5d57f50a0d4c3b7f1828a4cd03f8ba155" +dependencies = [ + "aes-gcm", + "blake2", + "chacha20poly1305", + "curve25519-dalek 4.1.1", + "rand_core 0.6.4", + "rustc_version", + "sha2 0.10.8", + "subtle", +] + +[[package]] +name = "socket2" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "socket2" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4031e820eb552adee9295814c0ced9e5cf38ddf1e8b7d566d6de8e2538ea989e" +dependencies = [ + "libc", + "windows-sys 0.48.0", +] + +[[package]] +name = "soketto" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d1c5305e39e09653383c2c7244f2f78b3bcae37cf50c64cb4789c9f5096ec2" +dependencies = [ + "base64 0.13.1", + "bytes", + "futures", + "httparse", + "log", + "rand 0.8.5", + "sha-1", +] + +[[package]] +name = "solana-account-decoder" +version = "1.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ec4cebccef07b65c46854b62237a29e7ccc92ef21ef1c90be346f9de0c4e7a4" +dependencies = [ + "Inflector", + "base64 0.21.4", + "bincode", + "bs58 0.4.0", + "bv", + "lazy_static", + "serde", + "serde_derive", + "serde_json", + "solana-config-program", + "solana-sdk", + "spl-token", + "spl-token-2022", + "spl-token-metadata-interface", + "thiserror", + "zstd", +] + +[[package]] +name = "solana-bpf-loader-program" +version = "1.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af5bf2cf0981fc14ccf1044190bd767846b28f381c8e7349a5ca2e000b3821da" +dependencies = [ + "bincode", + "byteorder", + "libsecp256k1 0.6.0", + "log", + "scopeguard", + "solana-measure", + "solana-program-runtime", + "solana-sdk", + "solana-zk-token-sdk", + "solana_rbpf", + "thiserror", +] + +[[package]] +name = "solana-clap-utils" +version = "1.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "089f1edd0e325e5664f33b11df131ff47ed93cd74d75a2d434c8b7f9e976267a" +dependencies = [ + "chrono", + "clap 2.34.0", + "rpassword", + "solana-remote-wallet", + "solana-sdk", + "thiserror", + "tiny-bip39 0.8.2", + "uriparse", + "url", +] + +[[package]] +name = "solana-clap-v3-utils" +version = "1.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f431cda12c6541f44c6502fb52100bc3d661a67ec9b2209b2d9dd2a301385235" +dependencies = [ + "chrono", + "clap 3.2.25", + "rpassword", + "solana-remote-wallet", + "solana-sdk", + "solana-zk-token-sdk", + "thiserror", + "tiny-bip39 0.8.2", + "uriparse", + "url", +] + +[[package]] +name = "solana-cli" +version = "1.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b716f793ee4a33604563e608220d67b88dc6deab934eddda0203c36697d7e166" +dependencies = [ + "bincode", + "bs58 0.4.0", + "clap 2.34.0", + "console", + "const_format", + "criterion-stats", + "crossbeam-channel", + "ctrlc", + "hex", + "humantime", + "log", + "num-traits", + "pretty-hex", + "reqwest", + "semver", + "serde", + "serde_derive", + "serde_json", + "solana-account-decoder", + "solana-bpf-loader-program", + "solana-clap-utils", + "solana-cli-config", + "solana-cli-output", + "solana-client", + "solana-config-program", + "solana-faucet", + "solana-loader-v4-program", + "solana-logger", + "solana-program-runtime", + "solana-pubsub-client", + "solana-remote-wallet", + "solana-rpc-client", + "solana-rpc-client-api", + "solana-rpc-client-nonce-utils", + "solana-sdk", + "solana-tpu-client", + "solana-transaction-status", + "solana-version", + "solana-vote-program", + "solana_rbpf", + "spl-memo", + "thiserror", + "tiny-bip39 0.8.2", +] + +[[package]] +name = "solana-cli-config" +version = "1.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "882d2ad48ea0cbf52006144e0fc545c9992c62a072ac41f0f95f0c57a06a5394" +dependencies = [ + "dirs-next", + "lazy_static", + "serde", + "serde_derive", + "serde_yaml", + "solana-clap-utils", + "solana-sdk", + "url", +] + +[[package]] +name = "solana-cli-output" +version = "1.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f507087d953cd827dfe1255759699b63dfbb00f329bde89d7f2b0ea3c532a191" +dependencies = [ + "Inflector", + "base64 0.21.4", + "chrono", + "clap 2.34.0", + "console", + "humantime", + "indicatif", + "pretty-hex", + "semver", + "serde", + "serde_json", + "solana-account-decoder", + "solana-clap-utils", + "solana-cli-config", + "solana-rpc-client-api", + "solana-sdk", + "solana-transaction-status", + "solana-vote-program", + "spl-memo", +] + +[[package]] +name = "solana-client" +version = "1.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d4eb6c673b6a8768ba687d620d02ec544d86525ce6d7e3858e9730463ed41b4" +dependencies = [ + "async-trait", + "bincode", + "dashmap", + "futures", + "futures-util", + "indexmap 2.0.2", + "indicatif", + "log", + "quinn", + "rayon", + "solana-connection-cache", + "solana-measure", + "solana-metrics", + "solana-pubsub-client", + "solana-quic-client", + "solana-rpc-client", + "solana-rpc-client-api", + "solana-rpc-client-nonce-utils", + "solana-sdk", + "solana-streamer", + "solana-thin-client", + "solana-tpu-client", + "solana-udp-client", + "thiserror", + "tokio", +] + +[[package]] +name = "solana-config-program" +version = "1.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98d262cd78922735637ef0ccf179e43bc0acd430f9004cd7e987e95d04b44f47" +dependencies = [ + "bincode", + "chrono", + "serde", + "serde_derive", + "solana-program-runtime", + "solana-sdk", +] + +[[package]] +name = "solana-connection-cache" +version = "1.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84f1aa4f1d78bdf5f76f4f351d05c0b861025c8b4e46503d8c2aa8d97a7139d4" +dependencies = [ + "async-trait", + "bincode", + "crossbeam-channel", + "futures-util", + "indexmap 2.0.2", + "log", + "rand 0.8.5", + "rayon", + "rcgen", + "solana-measure", + "solana-metrics", + "solana-sdk", + "thiserror", + "tokio", +] + +[[package]] +name = "solana-faucet" +version = "1.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74208ee4f79b808e01a2e098a01d5a72f3d5541293472457aeed3275cb392698" +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.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92dc68e28d42991c6579079f9be29e2e30fb20474cbcd7be1d97e052081c8050" +dependencies = [ + "ahash 0.8.3", + "blake3", + "block-buffer 0.10.4", + "bs58 0.4.0", + "bv", + "byteorder", + "cc", + "either", + "generic-array 0.14.7", + "im", + "lazy_static", + "log", + "memmap2", + "rustc_version", + "serde", + "serde_bytes", + "serde_derive", + "serde_json", + "sha2 0.10.8", + "solana-frozen-abi-macro", + "subtle", + "thiserror", +] + +[[package]] +name = "solana-frozen-abi-macro" +version = "1.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "999084a6d587bc79a059eb4c34c2e1419913612bb6224bb95660567c0f12449d" +dependencies = [ + "proc-macro2", + "quote", + "rustc_version", + "syn 2.0.38", +] + +[[package]] +name = "solana-loader-v4-program" +version = "1.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b53c047467e01a5593461fd6a16587bf04c536627093995a6dffccf7b6253fe" +dependencies = [ + "log", + "solana-measure", + "solana-program-runtime", + "solana-sdk", + "solana_rbpf", +] + +[[package]] +name = "solana-logger" +version = "1.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84a56a1696678acd5237565c3092354c923f84dc1fbcd9b824c91fbfefc10740" +dependencies = [ + "env_logger", + "lazy_static", + "log", +] + +[[package]] +name = "solana-measure" +version = "1.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cad3ae58ed767c409a792b045b4580c96b658b1672f4389f4dca7ca6a124693c" +dependencies = [ + "log", + "solana-sdk", +] + +[[package]] +name = "solana-metrics" +version = "1.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b6764575759cf274c7579df7d3b8c45d4859706c9da4a1964110ab6e622c5e9" +dependencies = [ + "crossbeam-channel", + "gethostname", + "lazy_static", + "log", + "reqwest", + "solana-sdk", + "thiserror", +] + +[[package]] +name = "solana-net-utils" +version = "1.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8570303599bc8c05b66550b919344dfde14dc79b17fa0c1d743a9c6dd7bac040" +dependencies = [ + "bincode", + "clap 3.2.25", + "crossbeam-channel", + "log", + "nix 0.26.4", + "rand 0.8.5", + "serde", + "serde_derive", + "socket2 0.5.4", + "solana-logger", + "solana-sdk", + "solana-version", + "tokio", + "url", +] + +[[package]] +name = "solana-perf" +version = "1.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68c658d1eff3672cb97c3501b9838fe1afdcac65d456c3e74b4c46f5245c8b05" +dependencies = [ + "ahash 0.8.3", + "bincode", + "bv", + "caps", + "curve25519-dalek 3.2.1", + "dlopen2", + "fnv", + "lazy_static", + "libc", + "log", + "nix 0.26.4", + "rand 0.8.5", + "rayon", + "rustc_version", + "serde", + "solana-frozen-abi", + "solana-frozen-abi-macro", + "solana-metrics", + "solana-rayon-threadlimit", + "solana-sdk", + "solana-vote-program", +] + +[[package]] +name = "solana-program" +version = "1.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e9aa19fa728ed701584c398607f26c773ede20e1c38e4a6c3ae79ed56521374" +dependencies = [ + "ark-bn254", + "ark-ec", + "ark-ff", + "ark-serialize", + "base64 0.21.4", + "bincode", + "bitflags 2.4.1", + "blake3", + "borsh 0.10.3", + "borsh 0.9.3", + "bs58 0.4.0", + "bv", + "bytemuck", + "cc", + "console_error_panic_hook", + "console_log", + "curve25519-dalek 3.2.1", + "getrandom 0.2.10", + "itertools 0.10.5", + "js-sys", + "lazy_static", + "libc", + "libsecp256k1 0.6.0", + "light-poseidon", + "log", + "memoffset 0.9.0", + "num-bigint 0.4.4", + "num-derive 0.3.3", + "num-traits", + "parking_lot", + "rand 0.8.5", + "rustc_version", + "rustversion", + "serde", + "serde_bytes", + "serde_derive", + "serde_json", + "sha2 0.10.8", + "sha3 0.10.8", + "solana-frozen-abi", + "solana-frozen-abi-macro", + "solana-sdk-macro", + "thiserror", + "tiny-bip39 0.8.2", + "wasm-bindgen", + "zeroize", +] + +[[package]] +name = "solana-program-runtime" +version = "1.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27f91b73c2c061b3e5f85345879a932460ff946ab363eb25166b751944e6f6dc" +dependencies = [ + "base64 0.21.4", + "bincode", + "eager", + "enum-iterator", + "itertools 0.10.5", + "libc", + "log", + "num-derive 0.3.3", + "num-traits", + "percentage", + "rand 0.8.5", + "rustc_version", + "serde", + "solana-frozen-abi", + "solana-frozen-abi-macro", + "solana-measure", + "solana-metrics", + "solana-sdk", + "solana_rbpf", + "thiserror", +] + +[[package]] +name = "solana-pubsub-client" +version = "1.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3939e4174d01c3bd9ef1385122de065e11fc6d660649388fae61effc2e0fa" +dependencies = [ + "crossbeam-channel", + "futures-util", + "log", + "reqwest", + "semver", + "serde", + "serde_derive", + "serde_json", + "solana-account-decoder", + "solana-rpc-client-api", + "solana-sdk", + "thiserror", + "tokio", + "tokio-stream", + "tokio-tungstenite", + "tungstenite", + "url", +] + +[[package]] +name = "solana-quic-client" +version = "1.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdd2ba399377ec18fe9bd45cb290bb92668df8adba1f884d4b6adab8e0c27ed5" +dependencies = [ + "async-mutex", + "async-trait", + "futures", + "itertools 0.10.5", + "lazy_static", + "log", + "quinn", + "quinn-proto", + "rcgen", + "rustls", + "solana-connection-cache", + "solana-measure", + "solana-metrics", + "solana-net-utils", + "solana-rpc-client-api", + "solana-sdk", + "solana-streamer", + "thiserror", + "tokio", +] + +[[package]] +name = "solana-rayon-threadlimit" +version = "1.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ada8292386cdf61aff5f9d00670abeefa3310b391f1a50c760c34c1ea52ea1a1" +dependencies = [ + "lazy_static", + "num_cpus", +] + +[[package]] +name = "solana-remote-wallet" +version = "1.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad77919e1081817f5b38b29ac74d93348aa653b5f987ee53d281fba206b7bd26" +dependencies = [ + "console", + "dialoguer", + "hidapi", + "log", + "num-derive 0.3.3", + "num-traits", + "parking_lot", + "qstring", + "semver", + "solana-sdk", + "thiserror", + "uriparse", +] + +[[package]] +name = "solana-rpc-client" +version = "1.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f681deb63fe05f365dddb4c3d2f596cf2cc54a81d6fb24746503c284b35266f8" +dependencies = [ + "async-trait", + "base64 0.21.4", + "bincode", + "bs58 0.4.0", + "indicatif", + "log", + "reqwest", + "semver", + "serde", + "serde_derive", + "serde_json", + "solana-account-decoder", + "solana-rpc-client-api", + "solana-sdk", + "solana-transaction-status", + "solana-version", + "solana-vote-program", + "tokio", +] + +[[package]] +name = "solana-rpc-client-api" +version = "1.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be2823b1ffc18604c8f0ef6c6a4da24e4da6f420aea09f5afe57f6594044ebb8" +dependencies = [ + "base64 0.21.4", + "bs58 0.4.0", + "jsonrpc-core", + "reqwest", + "semver", + "serde", + "serde_derive", + "serde_json", + "solana-account-decoder", + "solana-sdk", + "solana-transaction-status", + "solana-version", + "spl-token-2022", + "thiserror", +] + +[[package]] +name = "solana-rpc-client-nonce-utils" +version = "1.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc934849ef622beff13951b9a49a350e9d9d30a80dfa5f98043b516a08dfe64a" +dependencies = [ + "clap 2.34.0", + "solana-clap-utils", + "solana-rpc-client", + "solana-sdk", + "thiserror", +] + +[[package]] +name = "solana-sdk" +version = "1.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "774c2379f8aaa8b5877029410dacd4e663d167cb93b09b2f3c2647c63df4f2eb" +dependencies = [ + "assert_matches", + "base64 0.21.4", + "bincode", + "bitflags 2.4.1", + "borsh 0.10.3", + "bs58 0.4.0", + "bytemuck", + "byteorder", + "chrono", + "derivation-path", + "digest 0.10.7", + "ed25519-dalek", + "ed25519-dalek-bip32", + "generic-array 0.14.7", + "hmac 0.12.1", + "itertools 0.10.5", + "js-sys", + "lazy_static", + "libsecp256k1 0.6.0", + "log", + "memmap2", + "num-derive 0.3.3", + "num-traits", + "num_enum 0.6.1", + "pbkdf2 0.11.0", + "qstring", + "qualifier_attr", + "rand 0.7.3", + "rand 0.8.5", + "rustc_version", + "rustversion", + "serde", + "serde_bytes", + "serde_derive", + "serde_json", + "serde_with 2.3.3", + "sha2 0.10.8", + "sha3 0.10.8", + "solana-frozen-abi", + "solana-frozen-abi-macro", + "solana-logger", + "solana-program", + "solana-sdk-macro", + "thiserror", + "uriparse", + "wasm-bindgen", +] + +[[package]] +name = "solana-sdk-macro" +version = "1.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "015ca49e4cec213f034468b5d1fd2faea554be32e2144c90c409304121d781e6" +dependencies = [ + "bs58 0.4.0", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.38", +] + +[[package]] +name = "solana-streamer" +version = "1.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af376501d990f281b9249c5072ceef73bd5fc10700e877b27c1737b14cf447a2" +dependencies = [ + "async-channel", + "bytes", + "crossbeam-channel", + "futures-util", + "histogram", + "indexmap 2.0.2", + "itertools 0.10.5", + "libc", + "log", + "nix 0.26.4", + "pem", + "percentage", + "pkcs8", + "quinn", + "quinn-proto", + "rand 0.8.5", + "rcgen", + "rustls", + "solana-metrics", + "solana-perf", + "solana-sdk", + "thiserror", + "tokio", + "x509-parser", +] + +[[package]] +name = "solana-thin-client" +version = "1.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "749ba2ec60049a0c855fd971757465b82f5b99962f0c106f3bf83db2e8265637" +dependencies = [ + "bincode", + "log", + "rayon", + "solana-connection-cache", + "solana-rpc-client", + "solana-rpc-client-api", + "solana-sdk", +] + +[[package]] +name = "solana-tpu-client" +version = "1.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8aa49abe807db6f2a4e6ff5e5ade1835940f1ee311bbb94bfd9d05abf959ea62" +dependencies = [ + "async-trait", + "bincode", + "futures-util", + "indexmap 2.0.2", + "indicatif", + "log", + "rayon", + "solana-connection-cache", + "solana-measure", + "solana-metrics", + "solana-pubsub-client", + "solana-rpc-client", + "solana-rpc-client-api", + "solana-sdk", + "thiserror", + "tokio", +] + +[[package]] +name = "solana-transaction-status" +version = "1.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "884c541fae17c7cd3dd851f9e05a5adf3afd1b18122839fb4a3604feb4129386" +dependencies = [ + "Inflector", + "base64 0.21.4", + "bincode", + "borsh 0.10.3", + "bs58 0.4.0", + "lazy_static", + "log", + "serde", + "serde_derive", + "serde_json", + "solana-account-decoder", + "solana-sdk", + "spl-associated-token-account", + "spl-memo", + "spl-token", + "spl-token-2022", + "thiserror", +] + +[[package]] +name = "solana-udp-client" +version = "1.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfa91410ff195d0b7a4e46f4cef9cf3699961ee02654fe0ca590c01958ca59fe" +dependencies = [ + "async-trait", + "solana-connection-cache", + "solana-net-utils", + "solana-sdk", + "solana-streamer", + "thiserror", + "tokio", +] + +[[package]] +name = "solana-version" +version = "1.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45ced655d4e15fe1d52b4ecfb93c656dab933b2fd414a6879981e0ab1c854010" +dependencies = [ + "log", + "rustc_version", + "semver", + "serde", + "serde_derive", + "solana-frozen-abi", + "solana-frozen-abi-macro", + "solana-sdk", +] + +[[package]] +name = "solana-vote-program" +version = "1.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa36601af633b2854b2e38ceb7604f50f7e5739a150d57865ebb6e586ed142f6" +dependencies = [ + "bincode", + "log", + "num-derive 0.3.3", + "num-traits", + "rustc_version", + "serde", + "serde_derive", + "solana-frozen-abi", + "solana-frozen-abi-macro", + "solana-metrics", + "solana-program", + "solana-program-runtime", + "solana-sdk", + "thiserror", +] + +[[package]] +name = "solana-zk-token-sdk" +version = "1.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40f5be2f291d3a1692fc878dc98a841032df7672ba0878bbef43677e705b19cd" +dependencies = [ + "aes-gcm-siv", + "base64 0.21.4", + "bincode", + "bytemuck", + "byteorder", + "curve25519-dalek 3.2.1", + "getrandom 0.1.16", + "itertools 0.10.5", + "lazy_static", + "merlin 3.0.0", + "num-derive 0.3.3", + "num-traits", + "rand 0.7.3", + "serde", + "serde_json", + "sha3 0.9.1", + "solana-program", + "solana-sdk", + "subtle", + "thiserror", + "zeroize", +] + +[[package]] +name = "solana_rbpf" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "103318aa365ff7caa8cf534f2246b5eb7e5b34668736d52b1266b143f7a21196" +dependencies = [ + "byteorder", + "combine", + "goblin", + "hash32", + "libc", + "log", + "rand 0.8.5", + "rustc-demangle", + "scroll", + "thiserror", + "winapi", +] + +[[package]] +name = "sp-application-crypto" +version = "24.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b49d62089ef6fdd52a6f90f670d533ccb365235258cf517dbd5bd571febcfbd" +dependencies = [ + "parity-scale-codec", + "scale-info", + "serde", + "sp-core", + "sp-io", + "sp-std 9.0.0", +] + +[[package]] +name = "sp-arithmetic" +version = "17.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0241327405688cac3fcc29114fd35f99224e321daa37e19920e50e4b2fdd0645" +dependencies = [ + "integer-sqrt", + "num-traits", + "parity-scale-codec", + "scale-info", + "serde", + "sp-std 9.0.0", + "static_assertions", +] + +[[package]] +name = "sp-core" +version = "22.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0de478e02efd547693b33ad02515e09933d5b69b7f3036fa890b92e50fd9dfc" +dependencies = [ + "array-bytes", + "bitflags 1.3.2", + "blake2", + "bounded-collections", + "bs58 0.4.0", + "dyn-clonable", + "ed25519-zebra", + "futures", + "hash-db", + "hash256-std-hasher", + "impl-serde", + "lazy_static", + "libsecp256k1 0.7.1", + "log", + "merlin 2.0.1", + "parity-scale-codec", + "parking_lot", + "paste", + "primitive-types", + "rand 0.8.5", + "regex", + "scale-info", + "schnorrkel 0.9.1", + "secp256k1 0.24.3", + "secrecy", + "serde", + "sp-core-hashing 10.0.0", + "sp-debug-derive", + "sp-externalities", + "sp-runtime-interface", + "sp-std 9.0.0", + "sp-storage", + "ss58-registry", + "substrate-bip39", + "thiserror", + "tiny-bip39 1.0.0", + "tracing", + "zeroize", +] + +[[package]] +name = "sp-core-hashing" +version = "9.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ee599a8399448e65197f9a6cee338ad192e9023e35e31f22382964c3c174c68" +dependencies = [ + "blake2b_simd", + "byteorder", + "digest 0.10.7", + "sha2 0.10.8", + "sha3 0.10.8", + "sp-std 8.0.0", + "twox-hash", +] + +[[package]] +name = "sp-core-hashing" +version = "10.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e360755a2706a76886d58776665cad0db793dece3c7d390455b28e8a1efd6285" +dependencies = [ + "blake2b_simd", + "byteorder", + "digest 0.10.7", + "sha2 0.10.8", + "sha3 0.10.8", + "twox-hash", +] + +[[package]] +name = "sp-debug-derive" +version = "9.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f12dae7cf6c1e825d13ffd4ce16bd9309db7c539929d0302b4443ed451a9f4e5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "sp-externalities" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3313e2c5f2523b06062e541dff9961bde88ad5a28861621dc7b7b47a32bb0f7c" +dependencies = [ + "environmental", + "parity-scale-codec", + "sp-std 9.0.0", + "sp-storage", +] + +[[package]] +name = "sp-io" +version = "24.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff6194309bfe055d93177c6c9d2ed4c7b66040617cf3003a15e509c432cf3b62" +dependencies = [ + "bytes", + "ed25519", + "ed25519-dalek", + "libsecp256k1 0.7.1", + "log", + "parity-scale-codec", + "rustversion", + "secp256k1 0.24.3", + "sp-core", + "sp-externalities", + "sp-keystore", + "sp-runtime-interface", + "sp-state-machine", + "sp-std 9.0.0", + "sp-tracing", + "sp-trie", + "tracing", + "tracing-core", +] + +[[package]] +name = "sp-keystore" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eda1d2572a15340927a9f7db75ffe74366b645eaf9212015b4a96ad8e9d4c46" +dependencies = [ + "parity-scale-codec", + "parking_lot", + "sp-core", + "sp-externalities", + "thiserror", +] + +[[package]] +name = "sp-panic-handler" +version = "9.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c67eb0a0d11d3017ef43c975068ba76c7b0e83aca1ee3d68ba0ce270ecebe7" +dependencies = [ + "backtrace", + "lazy_static", + "regex", +] + +[[package]] +name = "sp-runtime" +version = "25.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d056e4cccf36a45be5d471b47c09e8be91b825f1d8352f20aa01f9f693176e7" +dependencies = [ + "either", + "hash256-std-hasher", + "impl-trait-for-tuples", + "log", + "parity-scale-codec", + "paste", + "rand 0.8.5", + "scale-info", + "serde", + "sp-application-crypto", + "sp-arithmetic", + "sp-core", + "sp-io", + "sp-std 9.0.0", + "sp-weights", +] + +[[package]] +name = "sp-runtime-interface" +version = "18.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf9781c72848efe6750116eb96edaeb105ee7e0bd7f38a4e46371bf810b3db7b" +dependencies = [ + "bytes", + "impl-trait-for-tuples", + "parity-scale-codec", + "primitive-types", + "sp-externalities", + "sp-runtime-interface-proc-macro", + "sp-std 9.0.0", + "sp-storage", + "sp-tracing", + "sp-wasm-interface", + "static_assertions", +] + +[[package]] +name = "sp-runtime-interface-proc-macro" +version = "12.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7402572a08aa1ae421ea5bab10918764b0ae72301b27710913e5d804862f2448" +dependencies = [ + "Inflector", + "proc-macro-crate 1.3.1", + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "sp-state-machine" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2e84d8ed3acc6aed5a3d5cfd500fb5b99c1e299c86086b2fe82c3e4be93178f" +dependencies = [ + "hash-db", + "log", + "parity-scale-codec", + "parking_lot", + "rand 0.8.5", + "smallvec", + "sp-core", + "sp-externalities", + "sp-panic-handler", + "sp-std 9.0.0", + "sp-trie", + "thiserror", + "tracing", + "trie-db", +] + +[[package]] +name = "sp-std" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53458e3c57df53698b3401ec0934bea8e8cfce034816873c0b0abbd83d7bac0d" + +[[package]] +name = "sp-std" +version = "9.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d5bbc9339227d1b6a9b7ccd9b2920c818653d40eef1512f1e2e824d72e7a336" + +[[package]] +name = "sp-storage" +version = "14.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21245c3a7799ff6d3f1f159b496f9ac72eb32cd6fe68c6f73013155289aa9f1" +dependencies = [ + "impl-serde", + "parity-scale-codec", + "ref-cast", + "serde", + "sp-debug-derive", + "sp-std 9.0.0", +] + +[[package]] +name = "sp-tracing" +version = "11.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f5ba26db1f7513d5975970d1ba1f0580d7a1b8da8c86ea3f9f0f8dbe2cfa96e" +dependencies = [ + "parity-scale-codec", + "sp-std 9.0.0", + "tracing", + "tracing-core", + "tracing-subscriber", +] + +[[package]] +name = "sp-trie" +version = "23.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf63ea90ffb5d61048d8fb2fac669114dac198fc2739e913e615f0fd2c36c3e7" +dependencies = [ + "ahash 0.8.3", + "hash-db", + "hashbrown 0.13.2", + "lazy_static", + "memory-db", + "nohash-hasher", + "parity-scale-codec", + "parking_lot", + "scale-info", + "schnellru", + "sp-core", + "sp-std 9.0.0", + "thiserror", + "tracing", + "trie-db", + "trie-root", +] + +[[package]] +name = "sp-wasm-interface" +version = "15.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d07945f592d2792632e6f030108769757e928a0fd78cf8659c9c210a5e341e55" +dependencies = [ + "anyhow", + "impl-trait-for-tuples", + "log", + "parity-scale-codec", + "sp-std 9.0.0", + "wasmtime", +] + +[[package]] +name = "sp-weights" +version = "21.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7699b853471c2eb5dc06ea1d8ea847bfa1415371218ebb4c86325c9d0232bc" +dependencies = [ + "parity-scale-codec", + "scale-info", + "serde", + "smallvec", + "sp-arithmetic", + "sp-core", + "sp-debug-derive", + "sp-std 9.0.0", +] + +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[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 = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "385e31c29981488f2820b2022d8e731aae3b02e6e18e2fd854e4c9a94dc44fc3" +dependencies = [ + "assert_matches", + "borsh 0.10.3", + "num-derive 0.4.1", + "num-traits", + "solana-program", + "spl-token", + "spl-token-2022", + "thiserror", +] + +[[package]] +name = "spl-discriminator" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cce5d563b58ef1bb2cdbbfe0dfb9ffdc24903b10ae6a4df2d8f425ece375033f" +dependencies = [ + "bytemuck", + "solana-program", + "spl-discriminator-derive", +] + +[[package]] +name = "spl-discriminator-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fadbefec4f3c678215ca72bd71862697bb06b41fd77c0088902dd3203354387b" +dependencies = [ + "quote", + "spl-discriminator-syn", + "syn 2.0.38", +] + +[[package]] +name = "spl-discriminator-syn" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e5f2044ca42c8938d54d1255ce599c79a1ffd86b677dfab695caa20f9ffc3f2" +dependencies = [ + "proc-macro2", + "quote", + "sha2 0.10.8", + "syn 2.0.38", + "thiserror", +] + +[[package]] +name = "spl-memo" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f180b03318c3dbab3ef4e1e4d46d5211ae3c780940dd0a28695aba4b59a75a" +dependencies = [ + "solana-program", +] + +[[package]] +name = "spl-pod" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2881dddfca792737c0706fa0175345ab282b1b0879c7d877bad129645737c079" +dependencies = [ + "borsh 0.10.3", + "bytemuck", + "solana-program", + "solana-zk-token-sdk", + "spl-program-error", +] + +[[package]] +name = "spl-program-error" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "249e0318493b6bcf27ae9902600566c689b7dfba9f1bdff5893e92253374e78c" +dependencies = [ + "num-derive 0.4.1", + "num-traits", + "solana-program", + "spl-program-error-derive", + "thiserror", +] + +[[package]] +name = "spl-program-error-derive" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab5269c8e868da17b6552ef35a51355a017bd8e0eae269c201fef830d35fa52c" +dependencies = [ + "proc-macro2", + "quote", + "sha2 0.10.8", + "syn 2.0.38", +] + +[[package]] +name = "spl-tlv-account-resolution" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "062e148d3eab7b165582757453632ffeef490c02c86a48bfdb4988f63eefb3b9" +dependencies = [ + "bytemuck", + "solana-program", + "spl-discriminator", + "spl-pod", + "spl-program-error", + "spl-type-length-value", +] + +[[package]] +name = "spl-token" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08459ba1b8f7c1020b4582c4edf0f5c7511a5e099a7a97570c9698d4f2337060" +dependencies = [ + "arrayref", + "bytemuck", + "num-derive 0.3.3", + "num-traits", + "num_enum 0.6.1", + "solana-program", + "thiserror", +] + +[[package]] +name = "spl-token-2022" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4abf34a65ba420584a0c35f3903f8d727d1f13ababbdc3f714c6b065a686e86" +dependencies = [ + "arrayref", + "bytemuck", + "num-derive 0.4.1", + "num-traits", + "num_enum 0.7.1", + "solana-program", + "solana-zk-token-sdk", + "spl-memo", + "spl-pod", + "spl-token", + "spl-token-metadata-interface", + "spl-transfer-hook-interface", + "spl-type-length-value", + "thiserror", +] + +[[package]] +name = "spl-token-metadata-interface" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c16ce3ba6979645fb7627aa1e435576172dd63088dc7848cb09aa331fa1fe4f" +dependencies = [ + "borsh 0.10.3", + "solana-program", + "spl-discriminator", + "spl-pod", + "spl-program-error", + "spl-type-length-value", +] + +[[package]] +name = "spl-transfer-hook-interface" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "051d31803f873cabe71aec3c1b849f35248beae5d19a347d93a5c9cccc5d5a9b" +dependencies = [ + "arrayref", + "bytemuck", + "solana-program", + "spl-discriminator", + "spl-pod", + "spl-program-error", + "spl-tlv-account-resolution", + "spl-type-length-value", +] + +[[package]] +name = "spl-type-length-value" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a468e6f6371f9c69aae760186ea9f1a01c2908351b06a5e0026d21cfc4d7ecac" +dependencies = [ + "bytemuck", + "solana-program", + "spl-discriminator", + "spl-pod", + "spl-program-error", +] + +[[package]] +name = "ss58-registry" +version = "1.43.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e6915280e2d0db8911e5032a5c275571af6bdded2916abd691a659be25d3439" +dependencies = [ + "Inflector", + "num-format", + "proc-macro2", + "quote", + "serde", + "serde_json", + "unicode-xid", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "static_assertions" +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" + +[[package]] +name = "strum" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" +dependencies = [ + "strum_macros 0.25.3", +] + +[[package]] +name = "strum_macros" +version = "0.24.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" +dependencies = [ + "heck 0.4.1", + "proc-macro2", + "quote", + "rustversion", + "syn 1.0.109", +] + +[[package]] +name = "strum_macros" +version = "0.25.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" +dependencies = [ + "heck 0.4.1", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.38", +] + +[[package]] +name = "substrate-bip39" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49eee6965196b32f882dd2ee85a92b1dbead41b04e53907f269de3b0dc04733c" +dependencies = [ + "hmac 0.11.0", + "pbkdf2 0.8.0", + "schnorrkel 0.9.1", + "sha2 0.9.9", + "zeroize", +] + +[[package]] +name = "subtle" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" + +[[package]] +name = "subtle-ng" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "734676eb262c623cec13c3155096e08d1f8f29adce39ba17948b18dad1e54142" + +[[package]] +name = "subxt" +version = "0.32.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "588b8ce92699eeb06290f4fb02dad4f7e426c4e6db4d53889c6bcbc808cf24ac" +dependencies = [ + "async-trait", + "base58", + "blake2", + "derivative", + "either", + "frame-metadata 16.0.0", + "futures", + "hex", + "impl-serde", + "jsonrpsee", + "parity-scale-codec", + "primitive-types", + "scale-bits", + "scale-decode", + "scale-encode", + "scale-info", + "scale-value", + "serde", + "serde_json", + "sp-core-hashing 9.0.0", + "subxt-lightclient", + "subxt-macro", + "subxt-metadata", + "thiserror", + "tracing", +] + +[[package]] +name = "subxt-codegen" +version = "0.32.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98f5a534c8d475919e9c845d51fc2316da4fcadd04fe17552d932d2106de930e" +dependencies = [ + "frame-metadata 16.0.0", + "heck 0.4.1", + "hex", + "jsonrpsee", + "parity-scale-codec", + "proc-macro2", + "quote", + "scale-info", + "subxt-metadata", + "syn 2.0.38", + "thiserror", + "tokio", +] + +[[package]] +name = "subxt-lightclient" +version = "0.32.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10fd0ac9b091211f962b6ae19e26cd08e0b86efa064dfb7fac69c8f79f122329" +dependencies = [ + "futures", + "futures-util", + "serde", + "serde_json", + "smoldot-light", + "thiserror", + "tokio", + "tokio-stream", + "tracing", +] + +[[package]] +name = "subxt-macro" +version = "0.32.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12e8be9ab6fe88b8c13edbe15911e148482cfb905a8b8d5b8d766a64c54be0bd" +dependencies = [ + "darling 0.20.3", + "proc-macro-error", + "subxt-codegen", + "syn 2.0.38", +] + +[[package]] +name = "subxt-metadata" +version = "0.32.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6898275765d36a37e5ef564358e0341cf41b5f3a91683d7d8b859381b65ac8a" +dependencies = [ + "frame-metadata 16.0.0", + "parity-scale-codec", + "scale-info", + "sp-core-hashing 9.0.0", + "thiserror", +] + +[[package]] +name = "subxt-signer" +version = "0.32.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d82e5abb896d5f5a6581d5b86a5e7f015e318122498d8163211e8f61f83b54d2" +dependencies = [ + "bip39", + "hex", + "hmac 0.12.1", + "parity-scale-codec", + "pbkdf2 0.12.2", + "regex", + "schnorrkel 0.10.2", + "secp256k1 0.27.0", + "secrecy", + "sha2 0.10.8", + "sp-core-hashing 9.0.0", + "subxt", + "thiserror", + "zeroize", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "synstructure" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", + "unicode-xid", +] + +[[package]] +name = "system-configuration" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "target-lexicon" +version = "0.12.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c39fd04924ca3a864207c66fc2cd7d22d7c016007f9ce846cbb9326331930a" + +[[package]] +name = "tempfile" +version = "3.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" +dependencies = [ + "cfg-if", + "fastrand 2.0.1", + "redox_syscall 0.3.5", + "rustix 0.38.19", + "windows-sys 0.48.0", +] + +[[package]] +name = "term_size" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e4129646ca0ed8f45d09b929036bafad5377103edd06e50bf574b353d2b08d9" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "termcolor" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6093bad37da69aab9d123a8091e4be0aa4a03e4d601ec641c327398315f62b64" +dependencies = [ + "winapi-util", +] + +[[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.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" + +[[package]] +name = "thiserror" +version = "1.0.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-core" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d97345f6437bb2004cd58819d8a9ef8e36cdd7661c2abc4bbde0a7c40d9f497" +dependencies = [ + "thiserror-core-impl", +] + +[[package]] +name = "thiserror-core-impl" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10ac1c5050e43014d16b2f94d0d2ce79e65ffdd8b38d8048f9c8f6a8a6da62ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "thread-scoped" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcbb6aa301e5d3b0b5ef639c9a9c7e2f1c944f177b460c04dc24c69b1fa2bd99" + +[[package]] +name = "thread_local" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "time" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5" +dependencies = [ + "deranged", + "itoa", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20" +dependencies = [ + "time-core", +] + +[[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 = "tiny-bip39" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62cc94d358b5a1e84a5cb9109f559aa3c4d634d2b1b4de3d0fa4adc7c78e2861" +dependencies = [ + "anyhow", + "hmac 0.12.1", + "once_cell", + "pbkdf2 0.11.0", + "rand 0.8.5", + "rustc-hash", + "sha2 0.10.8", + "thiserror", + "unicode-normalization", + "wasm-bindgen", + "zeroize", +] + +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f38200e3ef7995e5ef13baec2f432a6da0aa9ac495b2c0e8f3b7eec2c92d653" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "num_cpus", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2 0.5.4", + "tokio-macros", + "windows-sys 0.48.0", +] + +[[package]] +name = "tokio-macros" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "tokio-rustls" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +dependencies = [ + "rustls", + "tokio", +] + +[[package]] +name = "tokio-stream" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-tungstenite" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "212d5dcb2a1ce06d81107c3d0ffa3121fe974b73f068c8282cb1c32328113b6c" +dependencies = [ + "futures-util", + "log", + "rustls", + "tokio", + "tokio-rustls", + "tungstenite", + "webpki-roots 0.25.2", +] + +[[package]] +name = "tokio-util" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d68074620f57a0b21594d9735eb2e98ab38b17f80d3fcb189fca266771ca60d" +dependencies = [ + "bytes", + "futures-core", + "futures-io", + "futures-sink", + "pin-project-lite", + "tokio", + "tracing", +] + +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "serde", +] + +[[package]] +name = "toml" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ff9e3abce27ee2c9a37f9ad37238c1bdd4e789c84ba37df76aa4d528f5072cc" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit 0.20.7", +] + +[[package]] +name = "toml_datetime" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.19.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +dependencies = [ + "indexmap 2.0.2", + "toml_datetime", + "winnow", +] + +[[package]] +name = "toml_edit" +version = "0.20.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" +dependencies = [ + "indexmap 2.0.2", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-layer" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" + +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "log", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" +dependencies = [ + "lazy_static", + "log", + "tracing-core", +] + +[[package]] +name = "tracing-serde" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc6b213177105856957181934e4920de57730fc69bf42c37ee5bb664d406d9e1" +dependencies = [ + "serde", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e0d2eaa99c3c2e41547cfa109e910a68ea03823cccad4a0525dcbc9b01e8c71" +dependencies = [ + "ansi_term", + "chrono", + "lazy_static", + "matchers", + "regex", + "serde", + "serde_json", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", + "tracing-serde", +] + +[[package]] +name = "trie-db" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "767abe6ffed88a1889671a102c2861ae742726f52e0a5a425b92c9fbfa7e9c85" +dependencies = [ + "hash-db", + "hashbrown 0.13.2", + "log", + "rustc-hex", + "smallvec", +] + +[[package]] +name = "trie-root" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4ed310ef5ab98f5fa467900ed906cb9232dd5376597e00fd4cba2a449d06c0b" +dependencies = [ + "hash-db", +] + +[[package]] +name = "try-lock" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" + +[[package]] +name = "tungstenite" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e3dac10fd62eaf6617d3a904ae222845979aec67c615d1c842b4002c7666fb9" +dependencies = [ + "byteorder", + "bytes", + "data-encoding", + "http", + "httparse", + "log", + "rand 0.8.5", + "rustls", + "sha1", + "thiserror", + "url", + "utf-8", + "webpki-roots 0.24.0", +] + +[[package]] +name = "twox-hash" +version = "1.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" +dependencies = [ + "cfg-if", + "digest 0.10.7", + "rand 0.8.5", + "static_assertions", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "uint" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" +dependencies = [ + "byteorder", + "crunchy", + "hex", + "static_assertions", +] + +[[package]] +name = "unicode-bidi" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-segmentation" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" + +[[package]] +name = "unicode-width" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" + +[[package]] +name = "unicode-xid" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" + +[[package]] +name = "universal-hash" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8326b2c654932e3e4f9196e69d08fdf7cfd718e1dc6f66b347e6024a0c961402" +dependencies = [ + "generic-array 0.14.7", + "subtle", +] + +[[package]] +name = "unreachable" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" +dependencies = [ + "void", +] + +[[package]] +name = "unsafe-libyaml" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f28467d3e1d3c6586d8f25fa243f544f5800fec42d97032474e17222c2b75cfa" + +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + +[[package]] +name = "uriparse" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0200d0fc04d809396c2ad43f3c95da3582a2556eba8d453c1087f4120ee352ff" +dependencies = [ + "fnv", + "lazy_static", +] + +[[package]] +name = "url" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + +[[package]] +name = "users" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24cc0f6d6f267b73e5a2cadf007ba8f9bc39c6a6f9666f8cf25ea809a153b032" +dependencies = [ + "libc", + "log", +] + +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + +[[package]] +name = "uuid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ad59a7560b41a70d191093a945f0b87bc1deeda46fb237479708a1d6b6cdfc" + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" + +[[package]] +name = "waker-fn" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3c4517f54858c779bbcbf228f4fca63d121bf85fbecb2dc578cdf4a39395690" + +[[package]] +name = "walkdir" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.38", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" + +[[package]] +name = "wasm-opt" +version = "0.116.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc942673e7684671f0c5708fc18993569d184265fd5223bb51fc8e5b9b6cfd52" +dependencies = [ + "anyhow", + "libc", + "strum 0.24.1", + "strum_macros 0.24.3", + "tempfile", + "thiserror", + "wasm-opt-cxx-sys", + "wasm-opt-sys", +] + +[[package]] +name = "wasm-opt-cxx-sys" +version = "0.116.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c57b28207aa724318fcec6575fe74803c23f6f266fce10cbc9f3f116762f12e" +dependencies = [ + "anyhow", + "cxx", + "cxx-build", + "wasm-opt-sys", +] + +[[package]] +name = "wasm-opt-sys" +version = "0.116.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a1cce564dc768dacbdb718fc29df2dba80bd21cb47d8f77ae7e3d95ceb98cbe" +dependencies = [ + "anyhow", + "cc", + "cxx", + "cxx-build", +] + +[[package]] +name = "wasmi" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51fb5c61993e71158abf5bb863df2674ca3ec39ed6471c64f07aeaf751d67b4" +dependencies = [ + "intx", + "smallvec", + "spin 0.9.8", + "wasmi_arena", + "wasmi_core", + "wasmparser-nostd", +] + +[[package]] +name = "wasmi_arena" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "401c1f35e413fac1846d4843745589d9ec678977ab35a384db8ae7830525d468" + +[[package]] +name = "wasmi_core" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624e6333e861ef49095d2d678b76ebf30b06bf37effca845be7e5b87c90071b7" +dependencies = [ + "downcast-rs", + "libm", + "num-traits", + "paste", +] + +[[package]] +name = "wasmparser" +version = "0.102.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48134de3d7598219ab9eaf6b91b15d8e50d31da76b8519fe4ecfcec2cf35104b" +dependencies = [ + "indexmap 1.9.3", + "url", +] + +[[package]] +name = "wasmparser-nostd" +version = "0.100.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9157cab83003221bfd385833ab587a039f5d6fa7304854042ba358a3b09e0724" +dependencies = [ + "indexmap-nostd", +] + +[[package]] +name = "wasmtime" +version = "8.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f907fdead3153cb9bfb7a93bbd5b62629472dc06dee83605358c64c52ed3dda9" +dependencies = [ + "anyhow", + "bincode", + "cfg-if", + "indexmap 1.9.3", + "libc", + "log", + "object 0.30.4", + "once_cell", + "paste", + "psm", + "serde", + "target-lexicon", + "wasmparser", + "wasmtime-environ", + "wasmtime-jit", + "wasmtime-runtime", + "windows-sys 0.45.0", +] + +[[package]] +name = "wasmtime-asm-macros" +version = "8.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3b9daa7c14cd4fa3edbf69de994408d5f4b7b0959ac13fa69d465f6597f810d" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "wasmtime-environ" +version = "8.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a990198cee4197423045235bf89d3359e69bd2ea031005f4c2d901125955c949" +dependencies = [ + "anyhow", + "cranelift-entity", + "gimli 0.27.3", + "indexmap 1.9.3", + "log", + "object 0.30.4", + "serde", + "target-lexicon", + "thiserror", + "wasmparser", + "wasmtime-types", +] + +[[package]] +name = "wasmtime-jit" +version = "8.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de48df552cfca1c9b750002d3e07b45772dd033b0b206d5c0968496abf31244" +dependencies = [ + "addr2line 0.19.0", + "anyhow", + "bincode", + "cfg-if", + "cpp_demangle", + "gimli 0.27.3", + "log", + "object 0.30.4", + "rustc-demangle", + "serde", + "target-lexicon", + "wasmtime-environ", + "wasmtime-jit-icache-coherence", + "wasmtime-runtime", + "windows-sys 0.45.0", +] + +[[package]] +name = "wasmtime-jit-debug" +version = "8.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e0554b84c15a27d76281d06838aed94e13a77d7bf604bbbaf548aa20eb93846" +dependencies = [ + "once_cell", +] + +[[package]] +name = "wasmtime-jit-icache-coherence" +version = "8.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aecae978b13f7f67efb23bd827373ace4578f2137ec110bbf6a4a7cde4121bbd" +dependencies = [ + "cfg-if", + "libc", + "windows-sys 0.45.0", +] + +[[package]] +name = "wasmtime-runtime" +version = "8.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "658cf6f325232b6760e202e5255d823da5e348fdea827eff0a2a22319000b441" +dependencies = [ + "anyhow", + "cc", + "cfg-if", + "indexmap 1.9.3", + "libc", + "log", + "mach", + "memfd", + "memoffset 0.8.0", + "paste", + "rand 0.8.5", + "rustix 0.36.16", + "wasmtime-asm-macros", + "wasmtime-environ", + "wasmtime-jit-debug", + "windows-sys 0.45.0", +] + +[[package]] +name = "wasmtime-types" +version = "8.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4f6fffd2a1011887d57f07654dd112791e872e3ff4a2e626aee8059ee17f06f" +dependencies = [ + "cranelift-entity", + "serde", + "thiserror", + "wasmparser", +] + +[[package]] +name = "web-sys" +version = "0.3.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki-roots" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b291546d5d9d1eab74f069c77749f2cb8504a12caa20f0f2de93ddbf6f411888" +dependencies = [ + "rustls-webpki", +] + +[[package]] +name = "webpki-roots" +version = "0.25.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14247bb57be4f377dfb94c72830b8ce8fc6beac03cf4bf7b9732eadd414123fc" + +[[package]] +name = "which" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bf3ea8596f3a0dd5980b46430f2058dfe2c36a27ccfbb1845d6fbfcd9ba6e14" +dependencies = [ + "either", + "home", + "once_cell", + "rustix 0.38.19", + "windows-sys 0.48.0", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "winnow" +version = "0.5.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3b801d0e0a6726477cc207f60162da452f3a95adb368399bef20a946e06f65c" +dependencies = [ + "memchr", +] + +[[package]] +name = "winreg" +version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + +[[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.1", + "data-encoding", + "der-parser", + "lazy_static", + "nom", + "oid-registry", + "rusticata-macros", + "thiserror", + "time", +] + +[[package]] +name = "xxhash-rust" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9828b178da53440fa9c766a3d2f73f7cf5d0ac1fe3980c1e5018d899fd19e07b" + +[[package]] +name = "yap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff4524214bc4629eba08d78ceb1d6507070cc0bcbbed23af74e19e6e924a24cf" + +[[package]] +name = "yasna" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e17bb3549cc1321ae1296b9cdc2698e2b6cb1992adfa19a8c72e5b7a738f44cd" +dependencies = [ + "time", +] + +[[package]] +name = "zeroize" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "zip" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261" +dependencies = [ + "byteorder", + "crc32fast", + "crossbeam-utils", +] + +[[package]] +name = "zstd" +version = "0.11.2+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "5.0.2+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db" +dependencies = [ + "libc", + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.9+zstd.1.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e16efa8a874a0481a574084d34cc26fdb3b99627480f785888deb6386506656" +dependencies = [ + "cc", + "pkg-config", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..f3c99df --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,16 @@ +[workspace] +members = ["crates/*"] + +resolver = "2" + +# Patching aes-gcm-siv to be: +# - compatible with solana crates (require aes-gcm-siv v^0.10.3) +# - compatible with contract-extrinsics (require subtle v2) +# This commit includes aes-gcm-siv v0.10.3 and removes pinning to subtle (>=2, <2.5) +[patch.crates-io.aes-gcm-siv] +git = "https://github.com/RustCrypto/AEADs" +rev = "e1e35e0c4f4943da0a99ceb8477c421dcfae2c33" + +[patch.crates-io.curve25519-dalek] +git = "https://github.com/solana-labs/curve25519-dalek.git" +rev = "c14774464c4d38de553c6ef2f48a10982c1b4801" diff --git a/README.md b/README.md new file mode 100644 index 0000000..d007a8a --- /dev/null +++ b/README.md @@ -0,0 +1,61 @@ +# Solang Aqd - Smart Contract CLI Tool + +
+ Solang Logo + + [![Discord](https://img.shields.io/discord/905194001349627914?logo=Hyperledger&style=plastic)](https://discord.gg/hyperledger) + [![CI](https://img.shields.io/github/workflow/status/hyperledger/solang-aqd/CI?label=CI&logo=GitHub)](https://github.com/hyperledger/solang-aqd/actions) + [![License](https://img.shields.io/github/license/hyperledger/solang.svg)](LICENSE) +
+ +`Aqd`(عَقد - meaning a contract in Arabic) is a versatile CLI tool for interacting with smart contracts on the Solana and Polkadot blockchains. +It provides a user-friendly interface with commands for deploying smart contracts and calling specific functions on the deployed contracts. + +Whether you're developing on Solana or Polkadot, `Aqd` simplifies your smart contract interactions. + +## Usage +### Installation +You can install Aqd using `cargo` : +```bash +cargo install --force --locked aqd +``` + +### Polkadot Interactions +To upload a contract to Polkadot: +```bash +aqd polkadot upload --suri //Alice -x flipper.contract +``` + +To instantiate a contract on Polkadot: +```bash +aqd polkadot instantiate --suri //Alice --args true -x flipper.contract +``` + +To call a specific function on Polkadot: +```bash +aqd polkadot call --contract --message get --suri //Alice flipper.contract +``` +### Solana Interactions + +To deploy a contract to Solana: +```bash +aqd solana deploy flipper.so +``` + +To call a specific function on Solana: +```bash +aqd solana call --idl flipper.json --program --instruction new --data true --accounts new self system +``` + +For more information, refer to [`Solang Aqd` documentation](https://solang.readthedocs.io/en/v0.3.3/running.html) + + +## Packages + +| Package | Description | Version | +| ------------------ | ---------------------------------- | ------- | +| `aqd-core` | The CLI tool core crate | pre-release | +| `aqd-polkadot` | Smart contract interactions for Polkadot | pre-release | +| `aqd-solana` | Smart contract interactions for Solana | pre-release | +| `aqd-utils` | Utility functions and common code | pre-release | +| `aqd-solana-contracts` | Rust crate for Solana smart contract interactions | pre-release | diff --git a/crates/aqd-core/Cargo.toml b/crates/aqd-core/Cargo.toml new file mode 100644 index 0000000..fc3dc02 --- /dev/null +++ b/crates/aqd-core/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "aqd" +version = "0.1.0" +edition = "2021" + + +[dependencies] +clap = { version = "4.4.7", features = ["derive"] } + +# tokio is only needed for polkadot target +tokio = { version = "1.33.0", optional = true } +aqd-polkadot = { path = "../aqd-polkadot", optional = true } + +aqd-solana = { path = "../aqd-solana", optional = true } + + +[features] +default = ["polkadot", "solana"] +polkadot = ["aqd-polkadot", "tokio"] +solana = ["aqd-solana"] diff --git a/crates/aqd-core/src/cli.rs b/crates/aqd-core/src/cli.rs new file mode 100644 index 0000000..f658a3f --- /dev/null +++ b/crates/aqd-core/src/cli.rs @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: Apache-2.0 + +use clap::{Parser, Subcommand}; + +#[cfg(feature = "solana")] +use aqd_solana::SolanaAction; + +#[cfg(feature = "polkadot")] +use aqd_polkadot::PolkadotAction; + +#[derive(Parser)] +#[command( author = env!("CARGO_PKG_AUTHORS"), + about = "Aqd is a versatile CLI tool for interacting with contracts on Solana and Polkadot blockchains.", + subcommand_required = true)] +pub struct Cli { + #[command(subcommand)] + pub command: Commands, +} + +#[allow(clippy::large_enum_variant)] +#[derive(Subcommand)] +pub enum Commands { + #[cfg(feature = "solana")] + #[command(about = "Interact with Solana contracts on chain")] + Solana { + #[clap(subcommand)] + action: SolanaAction, + }, + #[cfg(feature = "polkadot")] + #[command(about = "Interact with Polkadot contracts on chain")] + Polkadot { + #[clap(subcommand)] + action: PolkadotAction, + }, +} diff --git a/crates/aqd-core/src/main.rs b/crates/aqd-core/src/main.rs new file mode 100644 index 0000000..cd21343 --- /dev/null +++ b/crates/aqd-core/src/main.rs @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: Apache-2.0 + +mod cli; +use { + crate::cli::{Cli, Commands::*}, + clap::{CommandFactory, FromArgMatches}, + std::process::exit, +}; + +#[cfg(feature = "solana")] +use aqd_solana::SolanaAction; + +#[cfg(feature = "polkadot")] +use {aqd_polkadot::PolkadotAction, tokio::runtime::Runtime}; + +/// The main entry point for `aqd` command-line application. +fn main() { + // Parse command-line arguments. + let matches = Cli::command().get_matches(); + let cli = Cli::from_arg_matches(&matches).unwrap(); + + #[cfg(feature = "polkadot")] + let runtime = Runtime::new().expect("Failed to create Tokio runtime"); + + match cli.command { + #[cfg(feature = "solana")] + Solana { action } => match action { + SolanaAction::Deploy(deploy_args) => { + if let Err(err) = deploy_args.handle() { + eprintln!("{}", err); + exit(1); + } + } + SolanaAction::Call(call_args) => { + if let Err(err) = call_args.handle() { + eprintln!("{}", err); + exit(1); + } + } + SolanaAction::Show(show_args) => { + if let Err(err) = show_args.handle() { + eprintln!("{}", err); + exit(1); + } + } + }, + #[cfg(feature = "polkadot")] + Polkadot { action } => match action { + PolkadotAction::Upload(upload_args) => runtime.block_on(async { + if let Err(err) = upload_args.handle().await { + eprintln!("{}", err); + exit(1); + } + }), + PolkadotAction::Instantiate(instantiate_args) => runtime.block_on(async { + if let Err(err) = instantiate_args.handle().await { + eprintln!("{}", err); + exit(1); + } + }), + PolkadotAction::Call(call_args) => runtime.block_on(async { + if let Err(err) = call_args.handle().await { + eprintln!("{}", err); + exit(1); + } + }), + PolkadotAction::Remove(remove_args) => runtime.block_on(async { + if let Err(err) = remove_args.handle().await { + eprintln!("{}", err); + exit(1); + } + }), + }, + } +} diff --git a/crates/aqd-polkadot/Cargo.toml b/crates/aqd-polkadot/Cargo.toml new file mode 100644 index 0000000..c4f4448 --- /dev/null +++ b/crates/aqd-polkadot/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "aqd-polkadot" +version = "0.1.0" +edition = "2021" + +[dependencies] +anyhow = "1.0.75" +serde_json = "1.0.107" +clap = { version = "4.4.6", features = ["derive"] } +url = { version = "2.4.1", features = ["serde"] } +colored = "2.0.4" +hex = "0.4.3" +serde = "1.0.189" + +sp-core = "22.0.0" +subxt = "0.32.1" +contract-extrinsics = { git = "https://github.com/paritytech/cargo-contract", rev = "dfdc768bc430ba6e2967a482cb3016dba3785726" } +contract-build = { git = "https://github.com/paritytech/cargo-contract", rev = "dfdc768bc430ba6e2967a482cb3016dba3785726" } +aqd-utils = { path = "../aqd-utils" } diff --git a/crates/aqd-polkadot/src/commands/call.rs b/crates/aqd-polkadot/src/commands/call.rs new file mode 100644 index 0000000..af0bf4f --- /dev/null +++ b/crates/aqd-polkadot/src/commands/call.rs @@ -0,0 +1,150 @@ +// SPDX-License-Identifier: Apache-2.0 + +use { + anyhow::{anyhow, Context, Result}, + colored::Colorize, + serde_json::{json, to_string_pretty}, + std::{fmt::Debug, process::exit}, +}; + +use { + super::CLIExtrinsicOpts, + aqd_utils::{ + check_target_match, print_key_value, print_title, print_warning, prompt_confirm_transaction, + }, + contract_build::Verbosity, + contract_extrinsics::{ + BalanceVariant, CallCommandBuilder, DefaultConfig, ExtrinsicOptsBuilder, StorageDeposit, + }, + subxt::Config, +}; + +#[derive(Debug, clap::Args)] +#[clap(name = "call", about = "Call a contract on Polkadot")] +pub struct PolkadotCallCommand { + #[clap( + name = "contract", + long, + help = "Specifies the address of the contract to call." + )] + contract: ::AccountId, + #[clap( + long, + short, + help = "Specifies the name of the contract message to call." + )] + message: String, + #[clap(long, num_args = 0.., help = "Specifies the arguments of the contract message to call.")] + args: Vec, + #[clap(flatten)] + extrinsic_cli_opts: CLIExtrinsicOpts, + #[clap( + name = "value", + long, + default_value = "0", + help = "Specifies the value to be transferred as part of the call." + )] + value: BalanceVariant, + #[clap( + name = "gas", + long, + help = "Specifies the maximum amount of gas to be used for this command." + )] + gas_limit: Option, + #[clap(long, help = "Specifies the maximum proof size for this call.")] + proof_size: Option, + #[clap( + short('y'), + long, + help = "Specifies whether to skip the confirmation prompt." + )] + skip_confirm: bool, +} + +impl PolkadotCallCommand { + /// Returns whether to export the call output in JSON format. + pub fn output_json(&self) -> bool { + self.extrinsic_cli_opts.output_json + } + + /// Handles the calling of a contract on the Polkadot network. + /// + /// If the `execute` flag is set to `false`, it performs a dry run of the call and displays + /// the results. If the `output_json` flag is set to `true`, the output is in JSON format. + /// Otherwise, it prompts for a transaction confirmation and then submits the transaction for execution. + pub async fn handle(&self) -> Result<()> { + // Make sure the command is run in the correct directory + // Fails if the command is run in a Solang Solana project directory + let target_match = check_target_match("polkadot", None) + .map_err(|e| anyhow!("Failed to check current directory: {}", e))?; + if !target_match { + exit(1); + } + + // Initialize the extrinsic options + let cli_options = ExtrinsicOptsBuilder::default() + .file(Some(self.extrinsic_cli_opts.file.clone())) + .url(self.extrinsic_cli_opts.url().clone()) + .suri(self.extrinsic_cli_opts.suri.clone()) + .storage_deposit_limit(self.extrinsic_cli_opts.storage_deposit_limit.clone()) + .done(); + let exec = CallCommandBuilder::default() + .contract(self.contract.clone()) + .message(self.message.clone()) + .args(self.args.clone()) + .extrinsic_opts(cli_options) + .gas_limit(self.gas_limit) + .proof_size(self.proof_size) + .value(self.value.clone()) + .done() + .await?; + + if !self.extrinsic_cli_opts.execute { + let result = exec.call_dry_run().await?; + let ret_val = &result + .result + .map_err(|err| anyhow!("Error calling the contract: {:?}", err))?; + let value = exec + .transcoder() + .decode_message_return(exec.message(), &mut &ret_val.data[..]) + .context(format!("Failed to decode return value {:?}", &ret_val))?; + if self.output_json() { + let json_object = json!({ + "reverted": ret_val.did_revert(), + "data": value, + "gas_consumed": result.gas_consumed, + "gas_required": result.gas_required, + "storage_deposit": StorageDeposit::from(&result.storage_deposit), + }); + println!("{}", to_string_pretty(&json_object)?); + } else { + print_title!("Call Dry Run Result"); + print_key_value!("Status", format!("{}", value)); + print_key_value!("Reverted", format!("{:?}", ret_val.did_revert())); + print_warning!("Execution of your call has NOT been completed. To submit the transaction and execute the call on chain, please include -x/--execute flag."); + }; + } else { + let gas_limit = exec.estimate_gas().await?; + if !self.skip_confirm { + prompt_confirm_transaction(|| { + println!("Call Summary:"); + print_key_value!("Message", exec.message()); + print_key_value!("Args", exec.args().join(" ")); + print_key_value!("Gas limit", gas_limit.to_string()); + })?; + } + let token_metadata = exec.token_metadata(); + let display_events = exec + .call(Some(gas_limit)) + .await + .map_err(|err| anyhow!("Error calling the contract: {:?}", err))?; + let output = if self.output_json() { + display_events.to_json()? + } else { + display_events.display_events(Verbosity::Default, token_metadata)? + }; + println!("{output}"); + } + Ok(()) + } +} diff --git a/crates/aqd-polkadot/src/commands/instantiate.rs b/crates/aqd-polkadot/src/commands/instantiate.rs new file mode 100644 index 0000000..8b08236 --- /dev/null +++ b/crates/aqd-polkadot/src/commands/instantiate.rs @@ -0,0 +1,179 @@ +// SPDX-License-Identifier: Apache-2.0 + +use { + anyhow::{anyhow, Result}, + colored::Colorize, + std::fmt::Debug, + std::process::exit, +}; + +use { + super::CLIExtrinsicOpts, + aqd_utils::{ + check_target_match, print_key_value, print_title, print_warning, prompt_confirm_transaction, + }, + contract_build::{util::decode_hex, Verbosity}, + contract_extrinsics::{ + BalanceVariant, DisplayEvents, ExtrinsicOptsBuilder, InstantiateCommandBuilder, + }, + sp_core::Bytes, +}; + +#[derive(Debug, clap::Args)] +#[clap(name = "instantiate", about = "Instantiate a contract on Polkadot")] +pub struct PolkadotInstantiateCommand { + #[clap( + name = "constructor", + long, + default_value = "new", + help = "Specifies the name of the contract constructor to call." + )] + constructor: String, + #[clap(long, num_args = 0.., help = "Specifies the arguments of the contract constructor to call.")] + args: Vec, + #[clap(flatten)] + extrinsic_cli_opts: CLIExtrinsicOpts, + #[clap( + name = "value", + long, + default_value = "0", + help = "Specifies the value to be transferred as part of the call." + )] + value: BalanceVariant, + #[clap( + name = "gas", + long, + help = "Specifies the maximum amount of gas to be used for this command." + )] + gas_limit: Option, + #[clap( + long, + help = "Specifies the maximum proof size for this instantiation." + )] + proof_size: Option, + #[clap(long, value_parser = parse_hex_bytes, help = "Specifies a salt used in the address derivation of the new contract.")] + salt: Option, + #[clap( + short('y'), + long, + help = "Specifies whether to skip the confirmation prompt." + )] + skip_confirm: bool, +} + +/// Parse hex encoded bytes. +fn parse_hex_bytes(input: &str) -> Result { + let bytes = decode_hex(input)?; + Ok(bytes.into()) +} + +impl PolkadotInstantiateCommand { + /// Returns whether to export the call output in JSON format. + pub fn output_json(&self) -> bool { + self.extrinsic_cli_opts.output_json + } + + /// Handles the instantiation of a contract on the Polkadot network. + /// + /// If the `execute` flag is set to `false`, it performs a dry run of the instantiation and displays + /// the results. If the `output_json` flag is set to `true`, the output is in JSON format. + /// Otherwise, it prompts for a transaction confirmation and then submits the transaction for execution. + pub async fn handle(&self) -> Result<()> { + // Make sure the command is run in the correct directory + // Fails if the command is run in a Solang Solana project directory + let target_match = check_target_match("polkadot", None) + .map_err(|e| anyhow!("Failed to check current directory: {}", e))?; + if !target_match { + exit(1); + } + + // Initialize the extrinsic options + let cli_options = ExtrinsicOptsBuilder::default() + .file(Some(self.extrinsic_cli_opts.file.clone())) + .url(self.extrinsic_cli_opts.url().clone()) + .suri(self.extrinsic_cli_opts.suri.clone()) + .storage_deposit_limit(self.extrinsic_cli_opts.storage_deposit_limit.clone()) + .done(); + let exec = InstantiateCommandBuilder::default() + .constructor(self.constructor.clone()) + .args(self.args.clone()) + .extrinsic_opts(cli_options) + .value(self.value.clone()) + .gas_limit(self.gas_limit) + .proof_size(self.proof_size) + .salt(self.salt.clone()) + .done() + .await?; + + if !self.extrinsic_cli_opts.execute { + let result = exec.instantiate_dry_run().await?; + let dry_run_result = exec + .decode_instantiate_dry_run(&result) + .await + .map_err(|e| anyhow!("Failed to decode instantiate dry run result: {}", e))?; + if self.output_json() { + println!("{}", dry_run_result.to_json()?); + } else { + print_title!("Instantiate dry run result"); + print_key_value!("Status", format!("{}", &dry_run_result.result)); + print_key_value!("Reverted", format!("{:?}", &dry_run_result.reverted)); + print_key_value!("Contract", &dry_run_result.contract); + print_key_value!("Gas consumed", &dry_run_result.gas_consumed.to_string()); + print_warning!("Execution of your instantiate call has NOT been completed. To submit the transaction and execute the call on chain, please include -x/--execute flag."); + } + } else { + let gas_limit = exec.estimate_gas().await?; + if !self.skip_confirm { + prompt_confirm_transaction(|| { + println!("Instantiation Summary:"); + print_key_value!("Constructor", exec.args().constructor()); + print_key_value!("Args", exec.args().raw_args().join(" ")); + print_key_value!("Gas limit", gas_limit.to_string()); + })?; + } + let instantiate_result = exec + .instantiate(Some(gas_limit)) + .await + .map_err(|err| anyhow!("Error instantiating the contract: {:?}", err))?; + let events = DisplayEvents::from_events( + &instantiate_result.result, + Some(exec.transcoder()), + &exec.client().metadata(), + )?; + let contract_address = instantiate_result.contract_address.to_string(); + if self.output_json() { + let display_instantiate_result = InstantiateResult { + code_hash: instantiate_result.code_hash.map(|ch| format!("{ch:?}")), + contract: contract_address, + events, + }; + println!("{}", display_instantiate_result.to_json()?) + } else { + println!( + "{}", + events + .display_events(Verbosity::Default, &instantiate_result.token_metadata)? + ); + if let Some(code_hash) = instantiate_result.code_hash { + print_key_value!("Code hash", format!("{code_hash:?}")); + } + print_key_value!("Contract", contract_address); + }; + } + Ok(()) + } +} + +#[derive(serde::Serialize)] +pub struct InstantiateResult { + pub contract: String, + #[serde(skip_serializing_if = "Option::is_none")] + pub code_hash: Option, + pub events: DisplayEvents, +} + +impl InstantiateResult { + pub fn to_json(&self) -> Result { + Ok(serde_json::to_string_pretty(self)?) + } +} diff --git a/crates/aqd-polkadot/src/commands/mod.rs b/crates/aqd-polkadot/src/commands/mod.rs new file mode 100644 index 0000000..9abe2a5 --- /dev/null +++ b/crates/aqd-polkadot/src/commands/mod.rs @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: Apache-2.0 + +mod call; +mod instantiate; +mod remove; +mod upload; + +pub use self::{ + call::PolkadotCallCommand, instantiate::PolkadotInstantiateCommand, + remove::PolkadotRemoveCommand, upload::PolkadotUploadCommand, +}; + +use {std::path::PathBuf, url::Url}; + +pub use contract_extrinsics::BalanceVariant; + +/// Common CLI options for executing extrinsics on a Polkadot node. +/// +/// These options allow you to specify the contract or metadata file, the node's URL, +/// network, secret key URI, whether to execute the extrinsic, the storage deposit limit, +/// and whether to export the output in JSON format. +#[derive(Clone, Debug, clap::Args)] +pub struct CLIExtrinsicOpts { + #[clap( + value_parser, + help = "Specifies the path to a contract wasm file, .contract bundle, or .json metadata file." + )] + file: PathBuf, + #[clap( + name = "url", + long, + value_parser, + default_value = "ws://localhost:9944", + help = "Specifies the websockets URL for the substrate node directly." + )] + url: Url, + #[clap( + value_enum, + name = "network", + long, + conflicts_with = "url", + help = "Specifies the network name." + )] + network: Option, + #[clap( + name = "suri", + long, + short, + help = "Specifies the secret key URI used for deploying the contract. For example:\n + For a development account: //Alice\n + With a password: //Alice///SECRET_PASSWORD" + )] + suri: String, + #[clap( + short('x'), + long, + help = "Specifies whether to submit the extrinsic for execution." + )] + execute: bool, + #[clap( + long, + help = "Specifies the maximum amount of balance that can be charged from the caller to pay for the storage consumed." + )] + storage_deposit_limit: Option, + #[clap(long, help = "Specifies whether to export the call output in JSON.")] + output_json: bool, +} + +/// Available networks. +#[derive(clap::ValueEnum, Clone, Debug)] +enum Network { + Rococo, + PhalaPoC5, + AstarShiden, + AstarShibuya, + Astar, + AlephZeroTestnet, + AlephZero, + T3RNT0RN, + PendulumTestnet, +} + +impl CLIExtrinsicOpts { + /// Returns the URL for the Polkadot node based on the specified network or user input. + /// + /// If a specific network is chosen, the function returns the URL associated with that network. + /// Otherwise, it returns the URL provided by the user in the CLI options. + pub fn url(&self) -> Url { + if let Some(net) = &self.network { + return Url::parse(match net { + Network::Rococo => "wss://rococo-contracts-rpc.polkadot.io", + Network::PhalaPoC5 => "wss://poc5.phala.network/ws", + Network::AstarShiden => "wss://rpc.shiden.astar.network", + Network::AstarShibuya => "wss://rpc.shibuya.astar.network", + Network::Astar => "wss://rpc.astar.network", + Network::AlephZeroTestnet => "wss://ws.test.azero.dev", + Network::AlephZero => "wss://ws.azero.dev", + Network::T3RNT0RN => "wss://ws.t0rn.io", + Network::PendulumTestnet => "wss://rpc-foucoco.pendulumchain.tech", + }) + .unwrap(); + } + self.url.clone() + } +} diff --git a/crates/aqd-polkadot/src/commands/remove.rs b/crates/aqd-polkadot/src/commands/remove.rs new file mode 100644 index 0000000..85a7ee0 --- /dev/null +++ b/crates/aqd-polkadot/src/commands/remove.rs @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: Apache-2.0 + +use { + anyhow::{anyhow, Result}, + colored::Colorize, + serde_json::{from_str, json, to_string_pretty, Value}, + std::fmt::Debug, + std::process::exit, +}; + +use { + super::CLIExtrinsicOpts, + aqd_utils::{check_target_match, print_key_value}, + contract_build::Verbosity, + contract_extrinsics::{ + parse_code_hash, DefaultConfig, ExtrinsicOptsBuilder, RemoveCommandBuilder, + }, + subxt::Config, +}; + +#[derive(Debug, clap::Args)] +#[clap(name = "remove", about = "Remove a contract on Polkadot")] +pub struct PolkadotRemoveCommand { + #[clap(long, value_parser = parse_code_hash, help = "Specifies the code hash to remove.")] + code_hash: Option<::Hash>, + #[clap(flatten)] + extrinsic_cli_opts: CLIExtrinsicOpts, +} + +impl PolkadotRemoveCommand { + /// Returns whether to export the call output in JSON format. + pub fn output_json(&self) -> bool { + self.extrinsic_cli_opts.output_json + } + + /// Handles the removal of a contract from the Polkadot network. + /// + /// Removes a contract with the specified code hash. If successful, it returns information about the + /// removal, including the events generated. The `output_json` flag controls the output format. + pub async fn handle(&self) -> Result<()> { + // Make sure the command is run in the correct directory + // Fails if the command is run in a Solang Solana project directory + let target_match = check_target_match("polkadot", None) + .map_err(|e| anyhow!("Failed to check current directory: {}", e))?; + if !target_match { + exit(1); + } + + // Initialize the extrinsic options + let cli_options = ExtrinsicOptsBuilder::default() + .file(Some(self.extrinsic_cli_opts.file.clone())) + .url(self.extrinsic_cli_opts.url().clone()) + .suri(self.extrinsic_cli_opts.suri.clone()) + .storage_deposit_limit(self.extrinsic_cli_opts.storage_deposit_limit.clone()) + .done(); + let exec = RemoveCommandBuilder::default() + .code_hash(self.code_hash) + .extrinsic_opts(cli_options) + .done() + .await?; + + let remove_result = exec + .remove_code() + .await + .map_err(|err| anyhow!("Error removing the code: {}", err.to_string()))?; + let display_events = remove_result.display_events; + let events = if self.output_json() { + display_events.to_json()? + } else { + display_events.display_events(Verbosity::Default, exec.token_metadata())? + }; + let code_removed = remove_result.code_removed.ok_or_else(|| { + anyhow!( + "Error removing the code: {}", + hex::encode(exec.final_code_hash()) + ) + })?; + let remove_result = code_removed.code_hash; + if self.output_json() { + let json_object = json!({ + "events": from_str::(&events)?, + "removed_code_hash": remove_result, + }); + let json_object = to_string_pretty(&json_object)?; + println!("{}", json_object); + } else { + println!("{events}"); + print_key_value!("Code hash", format!("{remove_result:?}")); + } + Ok(()) + } +} diff --git a/crates/aqd-polkadot/src/commands/upload.rs b/crates/aqd-polkadot/src/commands/upload.rs new file mode 100644 index 0000000..171d641 --- /dev/null +++ b/crates/aqd-polkadot/src/commands/upload.rs @@ -0,0 +1,114 @@ +// SPDX-License-Identifier: Apache-2.0 + +use { + anyhow::{anyhow, Result}, + colored::Colorize, + serde_json::{from_str, json, to_string_pretty, Value}, + std::fmt::Debug, + std::process::exit, +}; + +use { + super::CLIExtrinsicOpts, + aqd_utils::{check_target_match, print_key_value, print_title, print_warning}, + contract_build::Verbosity, + contract_extrinsics::{ExtrinsicOptsBuilder, UploadCommandBuilder}, +}; + +#[derive(Debug, clap::Args)] +#[clap(name = "upload", about = "Upload a contract on Polkadot")] +pub struct PolkadotUploadCommand { + #[clap(flatten)] + extrinsic_cli_opts: CLIExtrinsicOpts, +} + +impl PolkadotUploadCommand { + /// Returns whether to export the call output in JSON format. + pub fn output_json(&self) -> bool { + self.extrinsic_cli_opts.output_json + } + + /// Handles the Polkadot upload command, allowing users to upload contracts to the Polkadot network. + /// + /// This function performs the following steps: + /// + /// 1. Verifies that the command is being run in the correct directory, failing if it's in a Solang Solana project directory. + /// 2. Builds command-line options for executing the upload. + /// 3. Creates and executes the upload command. + /// 4. Processes the result based on whether execution is required or not. + /// 5. Prints the outcome, including any generated events or output JSON if requested. + pub async fn handle(&self) -> Result<()> { + // Make sure the command is run in the correct directory + // Fails if the command is run in a Solang Solana project directory + let target_match = check_target_match("polkadot", None) + .map_err(|e| anyhow!("Failed to check current directory: {}", e))?; + if !target_match { + exit(1); + } + + // Initialize the extrinsic options + let cli_options = ExtrinsicOptsBuilder::default() + .file(Some(self.extrinsic_cli_opts.file.clone())) + .url(self.extrinsic_cli_opts.url().clone()) + .suri(self.extrinsic_cli_opts.suri.clone()) + .storage_deposit_limit(self.extrinsic_cli_opts.storage_deposit_limit.clone()) + .done(); + let exec = UploadCommandBuilder::default() + .extrinsic_opts(cli_options) + .done() + .await?; + + // Obtain the code hash + // This is used to check if the contract has already been uploaded + let code_hash = exec.code().code_hash(); + + if !self.extrinsic_cli_opts.execute { + let result = exec + .upload_code_rpc() + .await? + .map_err(|err| anyhow!("Error uploading the code: {:?}", err))?; + if self.output_json() { + let json_object = json!({ + "result": "Success", + "code_hash": result.code_hash, + "deposit": result.deposit + }); + println!("{}", to_string_pretty(&json_object)?); + } else { + print_title!("Upload Dry Run Result"); + print_key_value!("Status", "Success"); + print_key_value!("Code hash", format!("{:?}", result.code_hash)); + print_key_value!("Deposit", format!("{:?}", result.deposit)); + print_warning!("Execution of your upload call has NOT been completed. To submit the transaction and execute the call on chain, please include -x/--execute flag."); + } + } else { + let result = exec + .upload_code() + .await + .map_err(|err| anyhow!("Error uploading the code: {}", err.to_string()))?; + let events = result.display_events; + let events = if self.output_json() { + events.to_json()? + } else { + events.display_events(Verbosity::Default, exec.token_metadata())? + }; + let code_stored = result.code_stored.ok_or_else(|| { + anyhow!( + "This contract has already been uploaded. Code hash: 0x{}", + hex::encode(code_hash) + ) + })?; + if self.output_json() { + let json_object = json!({ + "events": from_str::(&events)?, + "code_hash": code_stored.code_hash, + }); + println!("{}", to_string_pretty(&json_object)?); + } else { + println!("{}", events); + print_key_value!("Code hash", format!("{:?}", code_stored.code_hash)); + } + } + Ok(()) + } +} diff --git a/crates/aqd-polkadot/src/lib.rs b/crates/aqd-polkadot/src/lib.rs new file mode 100644 index 0000000..9a2eb0b --- /dev/null +++ b/crates/aqd-polkadot/src/lib.rs @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: Apache-2.0 + +mod commands; +mod polkadot_action; + +pub use commands::{ + PolkadotCallCommand, PolkadotInstantiateCommand, PolkadotRemoveCommand, PolkadotUploadCommand, +}; + +pub use polkadot_action::PolkadotAction; diff --git a/crates/aqd-polkadot/src/polkadot_action.rs b/crates/aqd-polkadot/src/polkadot_action.rs new file mode 100644 index 0000000..92ff7c0 --- /dev/null +++ b/crates/aqd-polkadot/src/polkadot_action.rs @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: Apache-2.0 + +use { + crate::{ + PolkadotCallCommand, PolkadotInstantiateCommand, PolkadotRemoveCommand, + PolkadotUploadCommand, + }, + clap::Subcommand, +}; + +/// Available subcommands for the `polkadot` subcommand. +#[derive(Debug, Subcommand)] +pub enum PolkadotAction { + Upload(PolkadotUploadCommand), + Instantiate(PolkadotInstantiateCommand), + Call(PolkadotCallCommand), + Remove(PolkadotRemoveCommand), +} diff --git a/crates/aqd-solana-contracts/Cargo.toml b/crates/aqd-solana-contracts/Cargo.toml new file mode 100644 index 0000000..f2bdeae --- /dev/null +++ b/crates/aqd-solana-contracts/Cargo.toml @@ -0,0 +1,36 @@ +[package] +name = "aqd-solana-contracts" +version = "0.1.0" +edition = "2021" + + +[dependencies] +serde_json = "1.0.107" +serde = "1.0.188" +tokio = { version = "1", features = ["full"] } +anyhow = "1.0.75" +colored = "2.0.4" + +# Solana and Anchor Dependencies +solana-clap-v3-utils = "1.17.2" +solana-cli-config = "1.17.2" +solana-client = "1.17.2" +solana-transaction-status = "1.17.2" +solana-sdk = "1.17.2" +solana-cli = "1.17.2" +solana-cli-output = "1.17.2" +solana-rpc-client-api = "1.17.2" +anchor-syn = { version = "0.28.0", features = ["idl"] } + +# Numeric Types and Encoding +num-bigint = { version = "0.4", features = ["rand", "serde"] } +base64 = "0.21.4" +base58 = "0.2.0" +hex = "0.4.3" +convert_case = "0.6.0" +byte-slice-cast = "1.2.2" +sha2 = "0.10.8" +num-traits = "0.2" + +# For Printing macros +aqd-utils = { path = "../aqd-utils" } diff --git a/crates/aqd-solana-contracts/README.md b/crates/aqd-solana-contracts/README.md new file mode 100644 index 0000000..11942ab --- /dev/null +++ b/crates/aqd-solana-contracts/README.md @@ -0,0 +1,93 @@ +# Solana Contracts + +`aqd-solana-contracts` is a Rust crate designed to simplify interaction with smart contracts on the Solana blockchain. +This crate provides a set of utilities and abstractions to make it easier to deploy smart contracts and to call specific functions on Solana smart contracts, leveraging the contract's Instruction Description Language (IDL). + + +## Example usage +The following example demonstrates how to use `aqd-solana-contracts` to deploy a smart contract to the Solana blockchain. +```rust +use { + anyhow::Result, + aqd_solana_contracts::deploy_program, +}; + +fn main() -> Result<()> { + // Define the contract to call + let program_path = "flipper.so".to_string(); + + // Deploy the contract (This returns the program ID) + let program_id = deploy_program(program_path)?; + + Ok(()) +} +``` + + + +The following example demonstrates how to use `aqd-solana-contracts` to call a method of a deployed smart contract on the Solana blockchain. +```rust +use { + anyhow::Result, + solana_clap_v3_utils::input_validators::normalize_to_url_if_moniker, + solana_cli_config::{Config, CONFIG_FILE}, + aqd_solana_contracts::{print_transaction_information, SolanaTransaction}, +}; + +fn main() -> Result<()> { + // Parse the config file to get the RPC URL and payer keypair. + let config_file = CONFIG_FILE + .as_ref() + .ok_or_else(|| anyhow::anyhow!("Error loading config file"))?; + let cli_config = Config::load(config_file).unwrap_or_default(); + let rpc_url = normalize_to_url_if_moniker(&cli_config.json_rpc_url); + let keypair = cli_config.keypair_path.to_string(); + + // Define the path to the IDL JSON file, the program ID, and whether to output JSON. + let idl_json = "crates/aqd-solana-contracts/examples/contracts/flipper.json"; + // The program ID is the address of the deployed program on the Solana blockchain. + // Replace this with the address of the deployed flipper program. + let program_id = "71gxeC5D6bGAUznocUWyXdhWQozhDc72qKL7oZ8zn4kR"; + let output_json = false; + + // Call the `new` method of the flipper program. + + // Define the instruction name, data arguments, and accounts arguments. + let instruction_name = "new"; + let data_args: Vec = vec!["true".to_string()]; + let accounts_args: Vec = + vec!["new".to_string(), "self".to_string(), "system".to_string()]; + + // Create a `SolanaTransaction` object with the necessary parameters. + let flipper_new = SolanaTransaction::new() + .rpc_url(rpc_url.clone()) + .idl(idl_json.to_string()) + .program_id(program_id.to_string()) + .instruction(instruction_name.to_string()) + .call_data(data_args) + .accounts(accounts_args) + .payer(keypair.clone()) + .done()?; + + // Submit the transaction. + let signature = flipper_new.submit_transaction()?; + + // Print the transaction information. + match print_transaction_information( + flipper_new.rpc_client(), + &signature, + flipper_new.instruction(), + flipper_new.idl().types.as_slice(), + flipper_new.new_accounts(), + output_json, + ) { + Ok(_) => (), + Err(err) => eprintln!("{}", err), + } + + Ok(()) +} +``` +In this example, `aqd-solana-contracts` streamlines the process of interacting with a Solana smart contract. It takes care of data encoding and prepares the necessary accounts, allowing you to focus on defining the specifics of the transaction and easily submit it to the Solana blockchain. + +> For more examples, see the [examples](examples) directory. diff --git a/crates/aqd-solana-contracts/examples/contracts/flipper.json b/crates/aqd-solana-contracts/examples/contracts/flipper.json new file mode 100644 index 0000000..c84aaf4 --- /dev/null +++ b/crates/aqd-solana-contracts/examples/contracts/flipper.json @@ -0,0 +1,69 @@ +{ + "version": "0.0.1", + "name": "flipper", + "instructions": [ + { + "name": "new", + "docs": [ + "notice: Constructor that initializes the `bool` value to the given `init_value`." + ], + "accounts": [ + { + "name": "dataAccount", + "isMut": true, + "isSigner": true, + "isOptional": false + }, + { + "name": "payer", + "isMut": true, + "isSigner": true, + "isOptional": false + }, + { + "name": "systemProgram", + "isMut": false, + "isSigner": false, + "isOptional": false + } + ], + "args": [ + { + "name": "initvalue", + "type": "bool" + } + ] + }, + { + "name": "flip", + "docs": [ + "notice: A message that can be called on instantiated contracts.\nThis one flips the value of the stored `bool` from `true`\nto `false` and vice versa." + ], + "accounts": [ + { + "name": "dataAccount", + "isMut": true, + "isSigner": false, + "isOptional": false + } + ], + "args": [] + }, + { + "name": "get", + "docs": [ + "notice: Simply returns the current value of our `bool`." + ], + "accounts": [ + { + "name": "dataAccount", + "isMut": false, + "isSigner": false, + "isOptional": false + } + ], + "args": [], + "returns": "bool" + } + ] +} \ No newline at end of file diff --git a/crates/aqd-solana-contracts/examples/contracts/flipper.so b/crates/aqd-solana-contracts/examples/contracts/flipper.so new file mode 100644 index 0000000..8284d51 Binary files /dev/null and b/crates/aqd-solana-contracts/examples/contracts/flipper.so differ diff --git a/crates/aqd-solana-contracts/examples/contracts/flipper.sol b/crates/aqd-solana-contracts/examples/contracts/flipper.sol new file mode 100644 index 0000000..ec1e2f6 --- /dev/null +++ b/crates/aqd-solana-contracts/examples/contracts/flipper.sol @@ -0,0 +1,21 @@ +contract flipper { + bool private value; + + /// Constructor that initializes the `bool` value to the given `init_value`. + @payer(payer) + constructor(bool initvalue) { + value = initvalue; + } + + /// A message that can be called on instantiated contracts. + /// This one flips the value of the stored `bool` from `true` + /// to `false` and vice versa. + function flip() public { + value = !value; + } + + /// Simply returns the current value of our `bool`. + function get() public view returns (bool) { + return value; + } +} diff --git a/crates/aqd-solana-contracts/examples/flipper_call.rs b/crates/aqd-solana-contracts/examples/flipper_call.rs new file mode 100644 index 0000000..3bc3f5b --- /dev/null +++ b/crates/aqd-solana-contracts/examples/flipper_call.rs @@ -0,0 +1,169 @@ +// SPDX-License-Identifier: Apache-2.0 + +use { + anyhow::Result, + aqd_solana_contracts::{deploy_program, print_transaction_information, SolanaTransaction}, + solana_clap_v3_utils::input_validators::normalize_to_url_if_moniker, + solana_cli_config::{Config, CONFIG_FILE}, +}; + +/// Example of interacting with Solana programs. +/// +/// This example demonstrates how to use the `aqd_solana_contracts` crate to interact +/// with Solana programs. It sets up the necessary parameters, including the IDL JSON file, program ID, +/// instruction names, arguments, and submits transactions to the Solana blockchain. The example includes +/// calls to the "new," "get," and "flip" methods of a deployed Flipper smart contract. +/// +/// This example demonstrates a sequence of interactions with a Solana program, making it useful +/// for understanding how to work with the `aqd_solana_contracts` crate. +/// +/// The flipper contract is assumed to be deployed. The contract is defined in the +/// `examples/contracts/flipper.sol` file. The contract is compiled using the Solang compiler +/// and deployed using the Solana CLI. +/// +/// To run the example, make sure the Solana CLI is installed and the Solana test validator is running. +fn main() -> Result<()> { + // Parse the config file to get the RPC URL and payer keypair. + let config_file = CONFIG_FILE + .as_ref() + .ok_or_else(|| anyhow::anyhow!("Error loading config file"))?; + let cli_config = Config::load(config_file).unwrap_or_default(); + let rpc_url = normalize_to_url_if_moniker(&cli_config.json_rpc_url); + let keypair = cli_config.keypair_path.to_string(); + + // Define the path to the IDL JSON file, the program ID, and whether to output JSON. + let idl_json = "crates/aqd-solana-contracts/examples/contracts/flipper.json"; + let output_json = false; + + // The compiled program is assumed to be in the same directory as the IDL JSON file. + let program_location = "crates/aqd-solana-contracts/examples/contracts/flipper.so".to_string(); + + // Deploy the flipper program. + let program_id = deploy_program(program_location)?; + + // Wait for 3 seconds for the program to be deployed. + std::thread::sleep(std::time::Duration::from_secs(3)); + + // Call the `new` method of the flipper program. + + // Define the instruction name, data arguments, and accounts arguments. + let instruction_name = "new"; + let data_args: Vec = vec!["true".to_string()]; + let accounts_args: Vec = + vec!["new".to_string(), "self".to_string(), "system".to_string()]; + + // Create a `SolanaTransaction` object with the necessary parameters. + let flipper_new = SolanaTransaction::new() + .rpc_url(rpc_url.clone()) + .idl(idl_json.to_string()) + .program_id(program_id.to_string()) + .instruction(instruction_name.to_string()) + .call_data(data_args) + .accounts(accounts_args) + .payer(keypair.clone()) + .done()?; + + // Submit the transaction. + let _signature = flipper_new.submit_transaction()?; + // The `new` method does not return any data, so no need to print. + // It also creates a new account because "new" was given as an account argument. + // This is needed for other methods. + let (data_account_pubkey, _data_account_path) = &flipper_new.new_accounts()[0]; + let data_account_pubkey = data_account_pubkey.to_string(); + + // Call the `get` method of the flipper program. + + // Define the instruction name, data arguments, and accounts arguments. + let instruction_name = "get"; + let data_args: Vec = vec![]; + // `get` method requires only one account, the data account. + let accounts_args: Vec = vec![data_account_pubkey.clone()]; + + // Create a `SolanaTransaction` object with the necessary parameters. + let call_cmd = SolanaTransaction::new() + .rpc_url(rpc_url.clone()) + .idl(idl_json.to_string()) + .program_id(program_id.to_string()) + .instruction(instruction_name.to_string()) + .call_data(data_args) + .accounts(accounts_args) + .payer(keypair.clone()) + .done()?; + + // Submit the transaction. + let signature = call_cmd.submit_transaction()?; + + // Print the transaction information. + match print_transaction_information( + call_cmd.rpc_client(), + &signature, + call_cmd.instruction(), + call_cmd.idl().types.as_slice(), + call_cmd.new_accounts(), + output_json, + ) { + Ok(_) => (), + Err(err) => eprintln!("{}", err), + } + + // Call the `flip` method of the flipper program. + + // Define the instruction name, data arguments, and accounts arguments. + let instruction_name = "flip"; + let data_args: Vec = vec![]; + // `flip` method requires only one account, the data account. + let accounts_args: Vec = vec![data_account_pubkey.clone()]; + + // Create a `SolanaTransaction` object with the necessary parameters. + let call_cmd = SolanaTransaction::new() + .rpc_url(rpc_url.clone()) + .idl(idl_json.to_string()) + .program_id(program_id.to_string()) + .instruction(instruction_name.to_string()) + .call_data(data_args) + .accounts(accounts_args) + .payer(keypair.clone()) + .done()?; + + // Submit the transaction. + let _signature = call_cmd.submit_transaction()?; + + // Call the `get` method of the flipper program. + // Define the instruction name, data arguments, and accounts arguments. + let instruction_name = "get"; + let data_args: Vec = vec![]; + // `get` method requires only one account, the data account. + let accounts_args: Vec = vec![data_account_pubkey.clone()]; + + // Create a `SolanaTransaction` object with the necessary parameters. + let call_cmd = SolanaTransaction::new() + .rpc_url(rpc_url.clone()) + .idl(idl_json.to_string()) + .program_id(program_id.to_string()) + .instruction(instruction_name.to_string()) + .call_data(data_args) + .accounts(accounts_args) + .payer(keypair.clone()) + .done()?; + + // Submit the transaction. + let signature = call_cmd.submit_transaction()?; + + // Print a separator. + println!("------------------------------------------"); + + // Print the transaction information. + match print_transaction_information( + call_cmd.rpc_client(), + &signature, + call_cmd.instruction(), + call_cmd.idl().types.as_slice(), + call_cmd.new_accounts(), + output_json, + ) { + Ok(_) => (), + Err(err) => eprintln!("{}", err), + } + + Ok(()) +} diff --git a/crates/aqd-solana-contracts/src/borsh_encoding.rs b/crates/aqd-solana-contracts/src/borsh_encoding.rs new file mode 100644 index 0000000..278d4ec --- /dev/null +++ b/crates/aqd-solana-contracts/src/borsh_encoding.rs @@ -0,0 +1,497 @@ +// SPDX-License-Identifier: Apache-2.0 + +use anchor_syn::idl::{IdlType, IdlTypeDefinition, IdlTypeDefinitionTy}; +use base58::ToBase58; +use byte_slice_cast::AsByteSlice; +use convert_case::{Boundary, Case, Casing}; +use num_bigint::{BigInt, Sign}; +use num_traits::ToPrimitive; +use serde::Deserialize; +use sha2::{Digest, Sha256}; +use std::cmp::Ordering; + +/// Generate discriminator based on the name of the function. This is the 8 byte +/// value anchor uses to dispatch function calls on. This should match +/// anchor's behaviour - we need to match the discriminator exactly +pub fn discriminator(namespace: &'static str, name: &str) -> Vec { + let mut hasher = Sha256::new(); + // must match snake-case npm library, see + // https://github.com/coral-xyz/anchor/blob/master/ts/packages/anchor/src/coder/borsh/instruction.ts#L389 + let normalized = name + .from_case(Case::Camel) + .without_boundaries(&[Boundary::LowerDigit]) + .to_case(Case::Snake); + hasher.update(format!("{namespace}:{normalized}")); + hasher.finalize()[..8].to_vec() +} + +/// This is the token that should be used for each function call in Solana runtime tests +#[derive(Debug, PartialEq, Clone, Deserialize)] +pub enum BorshToken { + Address([u8; 32]), + Int { width: u16, value: BigInt }, + Uint { width: u16, value: BigInt }, + FixedBytes(Vec), + Bytes(Vec), + Bool(bool), + String(String), + FixedArray(Vec), + Array(Vec), + Tuple(Vec), +} + +impl std::fmt::Display for BorshToken { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + BorshToken::Address(data) => { + write!(f, "{}", data.to_base58()) + } + BorshToken::Int { width: _, value } => { + write!(f, "{}", value) + } + BorshToken::Uint { width: _, value } => { + write!(f, "{}", value) + } + BorshToken::FixedBytes(data) => { + write!(f, "{}", hex::encode(data)) + } + BorshToken::Bytes(data) => { + write!(f, "{}", hex::encode(data)) + } + BorshToken::Bool(value) => { + write!(f, "{}", value) + } + BorshToken::String(data) => { + write!(f, "{}", data) + } + BorshToken::FixedArray(data) => { + let response = data + .iter() + .map(|item| item.to_string()) + .collect::>() + .join(", "); + write!(f, "{}", response) + } + BorshToken::Array(data) => { + let response = data + .iter() + .map(|item| item.to_string()) + .collect::>() + .join(", "); + write!(f, "{}", response) + } + BorshToken::Tuple(data) => { + let response = data + .iter() + .map(|item| item.to_string()) + .collect::>() + .join(", "); + write!(f, "{}", response) + } + } + } +} + +impl BorshToken { + /// Encode the parameter into the buffer + pub fn encode(&self, buffer: &mut Vec) { + match self { + BorshToken::Address(data) => { + buffer.extend_from_slice(data); + } + BorshToken::Uint { width, value } => { + encode_uint(*width, value, buffer); + } + BorshToken::Int { width, value } => { + encode_int(*width, value, buffer); + } + BorshToken::FixedBytes(data) => { + buffer.extend_from_slice(data); + } + BorshToken::Bytes(data) => { + let len = data.len() as u32; + buffer.extend_from_slice(&len.to_le_bytes()); + buffer.extend_from_slice(data); + } + BorshToken::Bool(value) => { + buffer.push(*value as u8); + } + BorshToken::String(data) => { + let len = data.len() as u32; + buffer.extend_from_slice(&len.to_le_bytes()); + buffer.extend_from_slice(data.as_byte_slice()); + } + BorshToken::Tuple(data) | BorshToken::FixedArray(data) => { + for item in data { + item.encode(buffer); + } + } + BorshToken::Array(arr) => { + let len = arr.len() as u32; + buffer.extend_from_slice(&len.to_le_bytes()); + for item in arr { + item.encode(buffer); + } + } + } + } + + pub fn into_string(self) -> Option { + match self { + BorshToken::String(value) => Some(value), + _ => None, + } + } + + pub fn into_array(self) -> Option> { + match self { + BorshToken::Array(value) => Some(value), + _ => None, + } + } + + pub fn into_fixed_bytes(self) -> Option> { + match self { + BorshToken::FixedBytes(value) => Some(value), + BorshToken::FixedArray(vec) => { + let mut response: Vec = Vec::with_capacity(vec.len()); + for elem in vec { + match elem { + BorshToken::Uint { width, value } => { + assert_eq!(width, 8); + response.push(value.to_u8().unwrap()); + } + _ => unreachable!("Array cannot be converted to fixed bytes"), + } + } + Some(response) + } + BorshToken::Address(value) => Some(value.to_vec()), + _ => None, + } + } + + pub fn into_bytes(self) -> Option> { + match self { + BorshToken::Bytes(value) => Some(value), + _ => None, + } + } + + pub fn into_bigint(self) -> Option { + match self { + BorshToken::Uint { value, .. } => Some(value), + BorshToken::Int { value, .. } => Some(value), + _ => None, + } + } + + pub fn unwrap_tuple(self) -> Vec { + match self { + BorshToken::Tuple(vec) => vec, + _ => panic!("This is not a tuple"), + } + } + + pub fn uint8_fixed_array(vec: Vec) -> BorshToken { + let mut array: Vec = Vec::with_capacity(vec.len()); + for item in &vec { + array.push(BorshToken::Uint { + width: 8, + value: BigInt::from(*item), + }); + } + + BorshToken::FixedArray(array) + } +} + +/// Encode a signed integer +fn encode_int(width: u16, value: &BigInt, buffer: &mut Vec) { + match width { + 1..=8 => { + let val = value.to_i8().unwrap(); + buffer.extend_from_slice(&val.to_le_bytes()); + } + 9..=16 => { + let val = value.to_i16().unwrap(); + buffer.extend_from_slice(&val.to_le_bytes()); + } + 17..=32 => { + let val = value.to_i32().unwrap(); + buffer.extend_from_slice(&val.to_le_bytes()); + } + 33..=64 => { + let val = value.to_i64().unwrap(); + buffer.extend_from_slice(&val.to_le_bytes()); + } + 65..=128 => { + let val = value.to_i128().unwrap(); + buffer.extend_from_slice(&val.to_le_bytes()); + } + 129..=256 => { + let mut val = value.to_signed_bytes_le(); + let byte_width = 32; + match val.len().cmp(&byte_width) { + Ordering::Greater => { + while val.len() > byte_width { + val.pop(); + } + } + Ordering::Less => { + if value.sign() == Sign::Minus { + val.extend(vec![255; byte_width - val.len()]); + } else { + val.extend(vec![0; byte_width - val.len()]); + } + } + + Ordering::Equal => (), + } + + buffer.extend_from_slice(&val); + } + _ => unreachable!("bit width not supported"), + } +} + +/// Encode an unsigned integer +fn encode_uint(width: u16, value: &BigInt, buffer: &mut Vec) { + match width { + 1..=8 => { + let val = value.to_u8().unwrap(); + buffer.push(val); + } + 9..=16 => { + let val = value.to_u16().unwrap(); + buffer.extend_from_slice(&val.to_le_bytes()); + } + 17..=32 => { + let val = value.to_u32().unwrap(); + buffer.extend_from_slice(&val.to_le_bytes()); + } + 33..=64 => { + let val = value.to_u64().unwrap(); + buffer.extend_from_slice(&val.to_le_bytes()); + } + 65..=128 => { + let val = value.to_u128().unwrap(); + buffer.extend_from_slice(&val.to_le_bytes()); + } + 129..=256 => { + let mut val = value.to_signed_bytes_le(); + let bytes_width = 32; + match val.len().cmp(&bytes_width) { + Ordering::Greater => { + while val.len() > bytes_width { + val.pop(); + } + } + Ordering::Less => { + val.extend(vec![0; bytes_width - val.len()]); + } + + Ordering::Equal => (), + } + + buffer.extend_from_slice(&val); + } + + _ => unreachable!("bit width not supported"), + } +} + +/// Encode the arguments of a function +pub fn encode_arguments(args: &[BorshToken]) -> Vec { + let mut encoded: Vec = Vec::new(); + for item in args { + item.encode(&mut encoded); + } + + encoded +} + +/// Decode a parameter at a given offset +pub fn decode_at_offset( + data: &[u8], + offset: &mut usize, + ty: &IdlType, + custom_types: &[IdlTypeDefinition], +) -> BorshToken { + match ty { + IdlType::PublicKey => { + let read = &data[*offset..(*offset + 32)]; + (*offset) += 32; + BorshToken::Address(<[u8; 32]>::try_from(read).unwrap()) + } + + IdlType::U8 + | IdlType::U16 + | IdlType::U32 + | IdlType::U64 + | IdlType::U128 + | IdlType::U256 => { + let decoding_width = integer_byte_width(ty); + let bigint = + BigInt::from_bytes_le(Sign::Plus, &data[*offset..(*offset + decoding_width)]); + (*offset) += decoding_width; + BorshToken::Uint { + width: (decoding_width * 8) as u16, + value: bigint, + } + } + + IdlType::I8 + | IdlType::I16 + | IdlType::I32 + | IdlType::I64 + | IdlType::I128 + | IdlType::I256 => { + let decoding_width = integer_byte_width(ty); + let bigint = BigInt::from_signed_bytes_le(&data[*offset..(*offset + decoding_width)]); + (*offset) += decoding_width; + BorshToken::Int { + width: (decoding_width * 8) as u16, + value: bigint, + } + } + + IdlType::Bool => { + let val = data[*offset] == 1; + (*offset) += 1; + BorshToken::Bool(val) + } + IdlType::String => { + let mut int_data: [u8; 4] = Default::default(); + int_data.copy_from_slice(&data[*offset..(*offset + 4)]); + let len = u32::from_le_bytes(int_data) as usize; + (*offset) += 4; + let read_string = std::str::from_utf8(&data[*offset..(*offset + len)]).unwrap(); + (*offset) += len; + BorshToken::String(read_string.to_string()) + } + IdlType::Array(ty, len) => { + let mut read_items: Vec = Vec::with_capacity(*len); + for _ in 0..*len { + read_items.push(decode_at_offset(data, offset, ty, custom_types)); + } + BorshToken::FixedArray(read_items) + } + IdlType::Vec(ty) => { + let mut int_data: [u8; 4] = Default::default(); + int_data.copy_from_slice(&data[*offset..(*offset + 4)]); + let len = u32::from_le_bytes(int_data); + (*offset) += 4; + let mut read_items: Vec = Vec::with_capacity(len as usize); + for _ in 0..len { + read_items.push(decode_at_offset(data, offset, ty, custom_types)); + } + BorshToken::Array(read_items) + } + IdlType::Defined(value) => { + let current_ty = custom_types + .iter() + .find(|item| &item.name == value) + .unwrap(); + + match ¤t_ty.ty { + IdlTypeDefinitionTy::Enum { .. } => { + let value = data[*offset]; + (*offset) += 1; + BorshToken::Uint { + width: 8, + value: BigInt::from(value), + } + } + IdlTypeDefinitionTy::Struct { fields } => { + let mut read_items: Vec = Vec::with_capacity(fields.len()); + for item in fields { + read_items.push(decode_at_offset(data, offset, &item.ty, custom_types)); + } + + BorshToken::Tuple(read_items) + } + } + } + IdlType::Bytes => { + let mut int_data: [u8; 4] = Default::default(); + int_data.copy_from_slice(&data[*offset..(*offset + 4)]); + let len = u32::from_le_bytes(int_data) as usize; + (*offset) += 4; + let read_data = &data[*offset..(*offset + len)]; + (*offset) += len; + BorshToken::Bytes(read_data.to_vec()) + } + + IdlType::Option(_) | IdlType::F32 | IdlType::F64 => { + unreachable!("Type not available in Solidity") + } + } +} + +fn integer_byte_width(ty: &IdlType) -> usize { + match ty { + IdlType::U8 | IdlType::I8 => 1, + IdlType::U16 | IdlType::I16 => 2, + IdlType::U32 | IdlType::I32 => 4, + IdlType::U64 | IdlType::I64 => 8, + IdlType::U128 | IdlType::I128 => 16, + IdlType::U256 | IdlType::I256 => 32, + _ => unreachable!("Not an integer"), + } +} + +pub trait VisitorMut { + fn visit_address(&mut self, _a: &mut [u8; 32]) {} + fn visit_int(&mut self, _width: &mut u16, _value: &mut BigInt) {} + fn visit_uint(&mut self, _width: &mut u16, _value: &mut BigInt) {} + fn visit_fixed_bytes(&mut self, _v: &mut Vec) {} + fn visit_bytes(&mut self, _v: &mut Vec) {} + fn visit_bool(&mut self, _b: &mut bool) {} + fn visit_string(&mut self, _s: &mut String) {} + fn visit_fixed_array(&mut self, v: &mut Vec) { + visit_fixed_array(self, v) + } + fn visit_array(&mut self, v: &mut Vec) { + visit_array(self, v) + } + fn visit_tuple(&mut self, v: &mut Vec) { + visit_tuple(self, v) + } +} + +pub fn visit_mut(visitor: &mut T, token: &mut BorshToken) { + match token { + BorshToken::Address(a) => visitor.visit_address(a), + BorshToken::Int { width, value } => visitor.visit_int(width, value), + BorshToken::Uint { width, value } => visitor.visit_uint(width, value), + BorshToken::FixedBytes(v) => visitor.visit_fixed_bytes(v), + BorshToken::Bytes(v) => visitor.visit_bytes(v), + BorshToken::Bool(b) => visitor.visit_bool(b), + BorshToken::String(s) => visitor.visit_string(s), + BorshToken::FixedArray(v) => visitor.visit_fixed_array(v), + BorshToken::Array(v) => visitor.visit_array(v), + BorshToken::Tuple(v) => visitor.visit_tuple(v), + } +} + +#[allow(clippy::ptr_arg)] +pub fn visit_fixed_array(visitor: &mut T, v: &mut Vec) { + for token in v.iter_mut() { + visit_mut(visitor, token); + } +} + +#[allow(clippy::ptr_arg)] +pub fn visit_array(visitor: &mut T, v: &mut Vec) { + for token in v.iter_mut() { + visit_mut(visitor, token); + } +} + +#[allow(clippy::ptr_arg)] +pub fn visit_tuple(visitor: &mut T, v: &mut Vec) { + for token in v.iter_mut() { + visit_mut(visitor, token); + } +} diff --git a/crates/aqd-solana-contracts/src/lib.rs b/crates/aqd-solana-contracts/src/lib.rs new file mode 100644 index 0000000..3880b59 --- /dev/null +++ b/crates/aqd-solana-contracts/src/lib.rs @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: Apache-2.0 + +pub mod borsh_encoding; +mod printing_utils; +mod solana_deploy; +mod solana_transaction; +mod utils; + +pub use { + printing_utils::{ + decode_instruction_return_data, print_idl_instruction_info, print_transaction_information, + }, + solana_deploy::deploy_program, + solana_transaction::SolanaTransaction, + utils::{construct_instruction_accounts, construct_instruction_data, idl_from_json}, +}; diff --git a/crates/aqd-solana-contracts/src/printing_utils.rs b/crates/aqd-solana-contracts/src/printing_utils.rs new file mode 100644 index 0000000..3461032 --- /dev/null +++ b/crates/aqd-solana-contracts/src/printing_utils.rs @@ -0,0 +1,418 @@ +// SPDX-License-Identifier: Apache-2.0 + +// To be able to use (base64::decode) in `decode_transaction_return_data` function +#![allow(deprecated)] + +use { + crate::borsh_encoding::decode_at_offset, + anchor_syn::idl::{Idl, IdlAccountItem, IdlInstruction, IdlTypeDefinition}, + anyhow::{anyhow, Result}, + aqd_utils::{print_key_value, print_subtitle, print_title, print_value}, + colored::Colorize, + serde_json::{json, Map, Value}, + solana_client::{rpc_client::RpcClient, rpc_config::RpcTransactionConfig}, + solana_sdk::{ + commitment_config::CommitmentConfig, pubkey::Pubkey, signature::Signature, + transaction::TransactionVersion::Legacy, transaction::TransactionVersion::Number, + }, + solana_transaction_status::{option_serializer::OptionSerializer, UiTransactionEncoding}, +}; + +/// Prints information about instructions in an Instruction Description Language (IDL) definition. +/// +/// This function takes an [`Idl`] structure, an optional instruction name, and a flag for output format. +/// It provides information about instructions defined in the [`Idl`]. If an instruction name is provided, +/// it will print details about that specific instruction. Otherwise, it can print information about all +/// instructions in the [`Idl`]. The information includes the instruction name, documentation, +/// associated accounts, and arguments. The output format can be either JSON or human-readable. +/// +/// The function will print information about the instruction, its associated accounts, and arguments based on the +/// specified output format. +/// +/// # Arguments +/// +/// * `idl`: A reference to an [`Idl`] structure that defines the instructions. +/// * `instruction_name`: An optional reference to a specific instruction name to print details for. +/// * `output_json`: A boolean flag indicating whether to output the information in JSON format. +pub fn print_idl_instruction_info(idl: &Idl, instruction_name: Option, output_json: bool) { + // If the instruction name is provided, print only that instruction + if let Some(instruction_name) = instruction_name { + // Find the instruction with the specified name + if let Some(instruction) = idl + .instructions + .iter() + .find(|i| i.name == *instruction_name) + { + print_single_instruction_info(instruction, output_json); + } else { + eprintln!("Instruction {} not found", instruction_name); + } + } else { + // Print all instructions' information + if output_json { + // This is to ensure that we print only 1 JSON + let val = match serde_json::to_string_pretty(&idl.instructions) { + Ok(val) => val, + Err(e) => { + eprintln!("Error: {}", e); + return; + } + }; + println!("{}", val); + } else { + for instruction in idl.instructions.iter() { + print_single_instruction_info(instruction, output_json); + } + } + } +} + +/// Print detailed information about an instruction. +/// +/// This function takes an instruction and an output format flag. It prints comprehensive details +/// about the given instruction, including its name, documentation, associated accounts, and arguments. +/// The output format can be either JSON or human-readable. +fn print_single_instruction_info(instruction: &IdlInstruction, output_json: bool) { + if output_json { + match serde_json::to_string_pretty(&instruction) { + Ok(val) => println!("{}", val), + Err(e) => { + eprintln!("Error: {}", e); + } + }; + } else { + // Print the instruction name + print_title!("Instruction name"); + print_value!(instruction.name); + + // Print the instruction documentation + print_title!("Instruction docs"); + let docs = match &instruction.docs { + Some(docs) => docs.join("\n"), + None => "No documentation".to_string(), + }; + print_value!(docs); + + // Print the associated accounts + print_title!("Accounts"); + // If there are no accounts, print a message + if instruction.accounts.is_empty() { + print_value!("No accounts"); + } + // Loop through the accounts and print their details + for (i, account) in instruction.accounts.iter().enumerate() { + let key: String = format!("Account {}", i + 1); + print_subtitle!(key); + match account { + IdlAccountItem::IdlAccount(account) => { + print_key_value!("Account Name: ", format!("{}", account.name)); + print_key_value!("Is signer: ", format!("{}", account.is_signer)); + print_key_value!("Is mutable: ", format!("{}", account.is_mut)); + print_key_value!("Is optional: ", format!("{:?}", account.is_optional)); + print_key_value!("Account docs: ", format!("{:?}", account.docs)); + print_key_value!("Account PDA: ", format!("{:?}", account.pda)); + } + IdlAccountItem::IdlAccounts(accounts) => { + // Print a warning that this is a nested account + println!("{}", "Nested accounts are not supported".red()); + let accounts_str = format!("{:?}", accounts); + print_key_value!(key, accounts_str); + } + } + } + + // Print the instruction arguments + print_title!("Args"); + // If there are no arguments, print a message + if instruction.args.is_empty() { + print_value!("No arguments"); + } + // Loop through the arguments and print their details + for (i, arg) in instruction.args.iter().enumerate() { + let key = format!("Arg {}", i + 1); + print_subtitle!(key); + print_key_value!("Arg name: ", format!("{}", arg.name)); + print_key_value!("Arg type: ", format!("{:?}", arg.ty)); + print_key_value!("Arg docs: ", format!("{:?}", arg.docs)); + } + } +} + +/// Print transaction information given a transaction signature. +/// +/// The function prints detailed information about the transaction, including the instruction name, associated accounts, +/// and arguments. The output format can be either JSON or human-readable. +/// +/// # Arguments +/// +/// * `rpc_client`: A reference to the [`RpcClient`] used to communicate with the Solana cluster. +/// * `signature`: A reference to the transaction [`Signature`] to retrieve transaction details. +/// * `instruction`: A reference to the [`IdlInstruction`] representing the instruction in the transaction. +/// * `custom_types`: An array of custom [`IdlTypeDefinition`]s used in the IDL definition. +/// * `new_accounts`: A reference to a list of new accounts as tuples containing the [`Pubkey`] and keypair file path. +/// * `output_json`: A boolean flag indicating whether to output the information in JSON format. +/// +/// The function will print information about the transaction, the associated instruction, its accounts, and arguments +/// based on the specified output format. +pub fn print_transaction_information( + rpc_client: &RpcClient, + signature: &Signature, + instruction: &IdlInstruction, + custom_types: &[IdlTypeDefinition], + new_accounts: &Vec<(Pubkey, String)>, + output_json: bool, +) -> Result<()> { + // If the instruction has a return value, we need to decode it using the IDL definition + let decoded_return_data = + decode_instruction_return_data(rpc_client, signature, instruction, custom_types)? + .unwrap_or("None".to_string()); + + if output_json { + // For the JSON output, we need to fetch the transaction details using the RpcTransactionConfig + // with the encoding set to JSON or JSONParsed + let config = RpcTransactionConfig { + encoding: Some(UiTransactionEncoding::Json), + commitment: Some(CommitmentConfig::confirmed()), + max_supported_transaction_version: Some(0), + }; + let transaction = rpc_client.get_transaction_with_config(signature, config)?; + let transaction_info = transaction.transaction; + + // Deserialize the transaction to a JSON object + let mut transaction_json: Map = + serde_json::from_str(&serde_json::to_string(&transaction_info)?)?; + + // If new accounts were created, add them to the JSON transaction + // instead of printing them separately. + // This is to ensure that we print only 1 JSON. + if !new_accounts.is_empty() { + // Create a JSON array of new accounts + let new_accounts_json: Vec = new_accounts + .iter() + .map(|(pubkey, name)| { + json!({ + "pubkey": pubkey.to_string(), + "file_name": name, + }) + }) + .collect(); + + // Add new_accounts field to the JSON transaction + transaction_json.insert("new_accounts".to_string(), Value::Array(new_accounts_json)); + } + + transaction_json.insert( + "decoded_return_data".to_string(), + Value::String(decoded_return_data), + ); + + // Serialize the modified transaction back to a string + let modified_pretty_trans = serde_json::to_string_pretty(&Value::Object(transaction_json))?; + println!("{}", modified_pretty_trans); + } else { + let config = RpcTransactionConfig { + encoding: Some(UiTransactionEncoding::Base64), + commitment: Some(CommitmentConfig::confirmed()), + max_supported_transaction_version: None, + }; + let transaction = rpc_client.get_transaction_with_config(signature, config)?; + let transaction_info = transaction.transaction; + + if let Some(trans) = transaction_info.transaction.decode() { + // Print the transaction version + let version = trans.version(); + let version = match version { + Legacy(_) => "Legacy".to_string(), + Number(val) => format!("Number: {}", val), + }; + print_title!("Transaction version"); + print_value!(version); + + // Print the signatures + let signatures = trans.signatures; + print_title!("Signatures"); + for (i, signature) in signatures.iter().enumerate() { + let key = format!("Signature {}", i + 1); + print_key_value!(key, signature); + } + + // Print the message + let message = trans.message; + + // Print the message header + let message_header = message.header(); + print_title!("Message header"); + print_key_value!( + "Number of required signatures", + message_header.num_required_signatures + ); + print_key_value!( + "Number of readonly signed accounts", + message_header.num_readonly_signed_accounts + ); + print_key_value!( + "Number of readonly unsigned accounts", + message_header.num_readonly_unsigned_accounts + ); + + // Print the message account keys + let account_keys = message.static_account_keys(); + print_title!("Account keys"); + for (i, account_key) in account_keys.iter().enumerate() { + let key = format!("Account key {}", i + 1); + print_key_value!(key, account_key); + } + + // Print the message recent block hash + let recent_block_hash = message.recent_blockhash(); + print_title!("Recent block hash"); + print_value!(recent_block_hash); + + // Print the message instructions + let instructions = message.instructions(); + print_title!("Instructions"); + for (i, instruction) in instructions.iter().enumerate() { + let program_id_index = instruction.program_id_index; + let accounts = &instruction.accounts; + let data = &instruction.data; + print_subtitle!(format!("Instruction {}", i + 1)); + print_key_value!("Program ID index", program_id_index); + let accounts = format!("{:?}", accounts); + print_key_value!("Accounts", accounts); + let data = format!("{:?}", data); + print_key_value!("Data", data); + } + // Print the new accounts (if any) + if !new_accounts.is_empty() { + print_title!("New accounts"); + for (i, (pubkey, name)) in new_accounts.iter().enumerate() { + print_subtitle!(format!("New account {}", i + 1)); + print_key_value!("Pubkey", pubkey); + print_key_value!("File name", name); + } + } + } else { + return Err(anyhow!("Error decoding transaction")); + } + + // Print transaction return data + if let Some(transaction_status) = transaction_info.meta { + // Print the transaction status + let status = match transaction_status.status { + Ok(_) => "Ok".to_string(), + Err(_) => "Error".to_string(), + }; + let err = transaction_status.err; + print_title!("Transaction status"); + print_key_value!("Status", status); + if let Some(err) = err { + print_key_value!("Error", err); + } + + // Print the transaction return data + print_title!("Transaction return data"); + print_value!(decoded_return_data); + + // Print the transaction logs + let logs = transaction_status.log_messages; + match logs { + OptionSerializer::Some(val) => { + print_subtitle!("Logs"); + for log in val { + print_value!(log); + } + } + OptionSerializer::None | OptionSerializer::Skip => {} + } + } + } + Ok(()) +} + +/// Decode the return data from a Solana instruction. +/// +/// Given the `rpc_client`, `signature` of the transaction containing the instruction, the +/// `instruction` description, and a vector of custom `custom_types`, this function attempts to +/// decode the return data of the instruction. If the instruction has no return value, it returns +/// `None`. +/// +/// The return data is extracted from the transaction logs, where it's identified as "Program +/// return." The encoded data is Base64 encoded, and this function decodes it and attempts to +/// deserialize it according to the provided `instruction` and `custom_types`. +/// +/// If successful, it returns the decoded data as a string wrapped in an `Ok` variant. If any error +/// occurs during the decoding process, it returns an `Err` variant containing an error message. +/// +/// # Parameters +/// +/// - `rpc_client`: A reference to the Solana RPC client of type [`RpcClient`]. +/// - `signature`: The transaction signature containing the instruction of type [`Signature`]. +/// - `instruction`: A reference to the instruction description of type [`IdlInstruction`]. +/// - `custom_types`: A vector of custom IDL type definitions used for deserialization of type [`IdlTypeDefinition`]. +/// +/// # Returns +/// +/// - `Ok(Some(result))`: The decoded return data as a string if successful. +/// - `Ok(None)`: If the instruction has no return value. +/// - `Err(error)`: If an error occurs during the decoding process. +pub fn decode_instruction_return_data( + rpc_client: &RpcClient, + signature: &Signature, + instruction: &IdlInstruction, + custom_types: &[IdlTypeDefinition], +) -> Result> { + // If the instruction has no return value, return None + let ty = instruction.returns.as_ref(); + if ty.is_none() { + return Ok(None); + } + // This can be unwrapped safely because we checked that it's not None + let ty = ty.unwrap(); + + // Fetch the transaction details using the RpcTransactionConfig + let config = RpcTransactionConfig { + encoding: Some(UiTransactionEncoding::Base64), + commitment: Some(CommitmentConfig::confirmed()), + max_supported_transaction_version: None, + }; + let transaction = rpc_client.get_transaction_with_config(signature, config)?; + let transaction_meta = transaction + .transaction + .meta + .ok_or_else(|| anyhow!("Error fetching transaction return data from transaction meta"))?; + + // We need to extract the return data from the logs. + // can't use the return data from the `EncodedTransactionWithStatusMeta` directly + // because of an issue fixed in this PR: + // https://github.com/solana-labs/solana/pull/33639 + // This is a workaround until a new version of the solana crate is released + // with the fix. + + let logs = transaction_meta.log_messages; + + let mut response = String::new(); + match logs { + OptionSerializer::Some(val) => { + for log in val { + if log.contains("Program return") { + // A sample log message containing return data: + // "Program return: FiyfwwVZjuC2GE15X68fpKdA9SukqB7bk472FageXVGv AQ==" + // We need to extract the base64 encoded data + let data = log.split_whitespace().last().ok_or_else(|| { + anyhow!("Error extracting transaction return data from log") + })?; + // Deserialize the data from base64 + let data = base64::decode(data) + .map_err(|e| anyhow!("Error decoding transaction return data: {}", e))?; + let data = data.as_slice(); + let mut offset = 0; + let data = decode_at_offset(data, &mut offset, ty, custom_types).to_string(); + response.push_str(&data); + } + } + } + OptionSerializer::None | OptionSerializer::Skip => {} + } + + Ok(Some(response)) +} diff --git a/crates/aqd-solana-contracts/src/solana_deploy.rs b/crates/aqd-solana-contracts/src/solana_deploy.rs new file mode 100644 index 0000000..2f745f4 --- /dev/null +++ b/crates/aqd-solana-contracts/src/solana_deploy.rs @@ -0,0 +1,126 @@ +// SPDX-License-Identifier: Apache-2.0 + +use { + anyhow::Result, + solana_cli::{ + cli::{ + process_command, CliCommand, CliCommandInfo, CliConfig, + DEFAULT_CONFIRM_TX_TIMEOUT_SECONDS, DEFAULT_RPC_TIMEOUT_SECONDS, + }, + program::ProgramCliCommand, + }, + solana_cli_config::{Config, CONFIG_FILE}, + solana_cli_output::OutputFormat, + solana_rpc_client_api::config::RpcSendTransactionConfig, + solana_sdk::{commitment_config::CommitmentConfig, signer::keypair::read_keypair_file}, + std::{str::FromStr, time::Duration}, +}; + +/// Deploy a Solana program to the blockchain. +/// +/// This function facilitates the deployment of a Solana program to the blockchain. It reads +/// the default Solana configuration file on disk to obtain necessary configuration settings. +/// +/// # Arguments +/// +/// * `program_location`: A string representing the location of the program to be deployed. +/// +/// # Returns +/// +/// A `Result` containing a string that represents the result of the deployment operation. +pub fn deploy_program(program_location: S) -> Result +where + S: Into, +{ + // Convert the program location to a string + let program_location: String = program_location.into(); + + // Get the path to the configuration file (default location) + let config_file = CONFIG_FILE + .as_ref() + .ok_or_else(|| anyhow::anyhow!("Failed to get configuration file path"))?; + + // Load configuration settings from a file or use defaults if the file is not found + let config = Config::load(config_file).unwrap_or_default(); + + // Create a CLI command for program deployment and define signers + let CliCommandInfo { command, signers } = CliCommandInfo { + command: CliCommand::Program(ProgramCliCommand::Deploy { + program_location: Some(program_location.to_string()), + program_signer_index: None, + program_pubkey: None, + buffer_signer_index: None, + buffer_pubkey: None, + upgrade_authority_signer_index: 0, + is_final: false, + max_len: None, + allow_excessive_balance: false, + skip_fee_check: false, + }), + // Load signer keypair from the file specified in the configuration + signers: vec![read_keypair_file(&config.keypair_path) + .map_err(|e| { + anyhow::anyhow!( + "Failed to read keypair file '{}': {}", + config.keypair_path, + e + ) + })? + .into()], + }; + + // Parse the commitment level from the configuration file + let commitment = CommitmentConfig::from_str(&config.commitment) + .ok() + .ok_or_else(|| { + anyhow::anyhow!("Failed to parse commitment level from configuration file") + })?; + + // Determine the output format (JSON or Display) + let output_format = OutputFormat::Display; + + let rpc_timeout = Duration::from_secs( + DEFAULT_RPC_TIMEOUT_SECONDS + .parse::() + .map_err(|e| anyhow::anyhow!("Failed to parse RPC timeout: {}", e))?, + ); + let confirm_transaction_initial_timeout = Duration::from_secs( + DEFAULT_CONFIRM_TX_TIMEOUT_SECONDS + .parse::() + .map_err(|e| anyhow::anyhow!("Failed to parse confirm transaction timeout: {}", e))?, + ); + + // Create a new configuration with modified settings + let cmd_config = CliConfig { + command, + json_rpc_url: config.json_rpc_url, + websocket_url: config.websocket_url, + signers: signers.iter().map(|s| s.as_ref()).collect(), + keypair_path: config.keypair_path, + rpc_client: None, + rpc_timeout, + verbose: false, + output_format, + commitment, + send_transaction_config: RpcSendTransactionConfig { + preflight_commitment: Some(commitment.commitment), + ..RpcSendTransactionConfig::default() + }, + confirm_transaction_initial_timeout, + address_labels: config.address_labels, + use_quic: true, + }; + + // Process the deployment command with the updated configuration + let result = process_command(&cmd_config) + .map_err(|e| anyhow::anyhow!("Failed to process deployment command: {}", e))?; + + // Extract the program ID from the result + // Sample result = "Program Id: 71gxeC5D6bGAUznocUWyXdhWQozhDc72qKL7oZ8zn4kR" + let program_id = result + .split_whitespace() + .nth(2) + .ok_or_else(|| anyhow::anyhow!("Failed to get program ID from result"))?; + + Ok(program_id.to_string()) +} diff --git a/crates/aqd-solana-contracts/src/solana_transaction.rs b/crates/aqd-solana-contracts/src/solana_transaction.rs new file mode 100644 index 0000000..0f63b82 --- /dev/null +++ b/crates/aqd-solana-contracts/src/solana_transaction.rs @@ -0,0 +1,581 @@ +// SPDX-License-Identifier: Apache-2.0 + +use { + crate::utils::{construct_instruction_accounts, construct_instruction_data, idl_from_json}, + anchor_syn::idl::{Idl, IdlInstruction}, + anyhow::{format_err, Result}, + solana_client::rpc_client::RpcClient, + solana_sdk::{ + commitment_config::CommitmentConfig, + instruction::{AccountMeta, Instruction}, + message::Message, + pubkey::Pubkey, + signature::Keypair, + signature::Signature, + signature::Signer, + signer::keypair::read_keypair_file, + transaction::Transaction, + }, + std::{ffi::OsStr, marker::PhantomData, str::FromStr}, +}; + +/// Represents a Solana program call configuration and execution context. +/// +/// This struct encapsulates the necessary data and parameters required to configure and execute a +/// call to a Solana program. It includes information such as the Solana RPC client, the Idl (Interface +/// Definition Language) for the program, the program's ID, the specific instruction to call, call data, +/// accounts involved, signers, new accounts to be created, and the payer's keypair. +pub struct SolanaTransaction { + rpc_client: RpcClient, + idl: Idl, + program_id: Pubkey, + instruction: IdlInstruction, + call_data: Vec, + accounts: Vec, + signers: Vec, + new_accounts: Vec<(Pubkey, String)>, + payer: Keypair, +} + +/// Type state for the call command to tell that some mandatory state has not yet +/// been set yet or to fail upon setting the same state multiple times. +pub struct Missing(PhantomData S>); + +pub mod state { + //! Type states that tell what state of the command has not + //! yet been set properly for a valid construction. + + /// Type state for the RPC client. + pub struct RpcClient; + /// Type state for the Idl. + pub struct Idl; + /// Type state for the program ID. + pub struct ProgramID; + /// Type state for the instruction. + pub struct Instruction; + /// Type state for the instruction data. + pub struct CallData; + /// Type state for the accounts. + pub struct Accounts; + /// Type state for the payer. + pub struct Payer; +} + +/// Represents options for configuring a Solana program call. +/// +/// This struct is designed to be used with the [`SolanaTransactionBuilder`] to collect user-provided +/// configuration options for setting up a Solana program call. The options are stored as strings, +/// making it convenient for users to specify their desired parameters. +struct SolanaTransactionOpts { + rpc_url: String, + idl: String, + program_id: String, + instruction: String, + call_data: Vec, + accounts: Vec, + payer: String, +} + +/// A builder for configuring and constructing Solana program calls. +/// +/// The [`SolanaTransactionBuilder`] allows you to fluently specify various configuration options for +/// setting up a Solana program call. These options include the Solana RPC client, Idl (Interface +/// Definition Language), program ID, instruction, call data, accounts, and payer. Once all +/// necessary parameters are set, you can use this builder to build a [`SolanaTransaction`] instance for +/// executing the program call. +#[allow(clippy::type_complexity)] +pub struct SolanaTransactionBuilder< + RpcClient, + Idl, + ProgramID, + Instruction, + CallData, + Accounts, + Payer, +> { + opts: SolanaTransactionOpts, + marker: PhantomData< + fn() -> ( + RpcClient, + Idl, + ProgramID, + Instruction, + CallData, + Accounts, + Payer, + ), + >, +} + +impl Default + for SolanaTransactionBuilder< + Missing, + Missing, + Missing, + Missing, + Missing, + Missing, + Missing, + > +{ + fn default() -> Self { + Self::new() + } +} + +impl + SolanaTransactionBuilder< + Missing, + Missing, + Missing, + Missing, + Missing, + Missing, + Missing, + > +{ + /// Create a new builder + pub fn new() -> Self { + Self { + opts: SolanaTransactionOpts { + rpc_url: "".to_string(), + idl: "".to_string(), + program_id: "".to_string(), + instruction: "".to_string(), + call_data: vec![], + accounts: vec![], + payer: "".to_string(), + }, + marker: PhantomData, + } + } +} + +impl + SolanaTransactionBuilder, Id, Pi, In, C, A, Py> +{ + /// Sets the Solana Remote Procedure Call (RPC) URL for connecting to a Solana network. + /// + /// The RPC URL is crucial for establishing a connection to a Solana cluster. It defines the + /// endpoint through which the Solana program call will interact with the network. By specifying + /// the RPC URL, you ensure that the program call is directed to the desired Solana cluster. + /// + /// # Parameters + /// + /// - `rpc_url`: A `String` representing the URL of the Solana RPC endpoint. + /// + /// # Returns + /// + /// Returns a new [`SolanaTransactionBuilder`] instance with the RPC URL option set. + pub fn rpc_url>( + self, + rpc_url: T, + ) -> SolanaTransactionBuilder { + SolanaTransactionBuilder { + opts: SolanaTransactionOpts { + rpc_url: rpc_url.into(), + ..self.opts + }, + marker: PhantomData, + } + } +} + +impl SolanaTransactionBuilder, Pi, In, C, A, Py> { + /// Sets the Interface Definition Language (Idl) by providing the path to the Idl JSON file + /// generated by the Solang compiler. + /// + /// The Idl JSON file is essential for defining the structure and interface of the Solana + /// program being called. By specifying the path to this file, you ensure that the program call + /// is configured with the correct Idl. + /// + /// # Parameters + /// + /// - `idl`: A `String` representing the path to the Idl JSON file. + /// + /// # Returns + /// + /// Returns a new [`SolanaTransactionBuilder`] instance with the Idl option set. + pub fn idl>( + self, + idl: T, + ) -> SolanaTransactionBuilder { + SolanaTransactionBuilder { + opts: SolanaTransactionOpts { + idl: idl.into(), + ..self.opts + }, + marker: PhantomData, + } + } +} + +impl + SolanaTransactionBuilder, In, C, A, Py> +{ + /// Sets the program ID for the Solana program call. + /// + /// The program ID is a unique identifier for a Solana program on the Solana blockchain. It + /// specifies which program should be invoked when the Solana transaction is processed. + /// + /// # Parameters + /// + /// - `program_id`: A `String` representing the program ID for the Solana program. + /// + /// # Returns + /// + /// Returns a new [`SolanaTransactionBuilder`] instance with the program ID option set. + pub fn program_id>( + self, + program_id: T, + ) -> SolanaTransactionBuilder { + SolanaTransactionBuilder { + opts: SolanaTransactionOpts { + program_id: program_id.into(), + ..self.opts + }, + marker: PhantomData, + } + } +} + +impl + SolanaTransactionBuilder, C, A, Py> +{ + /// Sets the Solana program instruction to be called. + /// + /// An instruction represents a specific action or operation that a Solana program can perform. + /// + /// # Parameters + /// + /// - `instruction`: A `String` representing the name of the Solana program instruction. + /// + /// # Returns + /// + /// Returns a new [`SolanaTransactionBuilder`] instance with the specified instruction set. + pub fn instruction>( + self, + instruction: T, + ) -> SolanaTransactionBuilder { + SolanaTransactionBuilder { + opts: SolanaTransactionOpts { + instruction: instruction.into(), + ..self.opts + }, + marker: PhantomData, + } + } +} + +impl + SolanaTransactionBuilder, A, Py> +{ + /// Sets the call data for the Solana program instruction. + /// + /// Call data is essential for providing input parameters to the Solana program instruction. + /// For each argument in the instruction's Idl (Interface Definition Language), there should be a corresponding string + /// in the `call_data` vector. The format of these strings depends on the argument type: + /// + /// - For primitive types, such as integers or strings, a single string should be provided. + /// - For structs, the string should be a JSON representation of the struct. + /// - For arrays and vectors, the string should contain a comma-separated list of values. + /// + /// These data values will be compared to the Idl instruction's argument types and encoded accordingly + /// when invoking the Solana program. + /// + /// # Parameters + /// + /// - `call_data`: A `Vec` containing the call data for the Solana program instruction. + /// + /// # Returns + /// + /// Returns a new [`SolanaTransactionBuilder`] instance with the specified call data set. + pub fn call_data>( + self, + call_data: Vec, + ) -> SolanaTransactionBuilder { + SolanaTransactionBuilder { + opts: SolanaTransactionOpts { + call_data: call_data.into_iter().map(|s| s.into()).collect(), + ..self.opts + }, + marker: PhantomData, + } + } +} + +impl + SolanaTransactionBuilder, Py> +{ + /// Sets the accounts for the Solana program instruction. + /// + /// Accounts represent the addresses associated with the Solana program instruction and can include + /// user-defined accounts, system accounts, and special keywords. The provided `accounts` vector + /// should contain strings corresponding to these accounts. + /// + /// You can use special keywords for some accounts: + /// + /// - `"new"`: Creates a new account and writes the keypair to a file. Information about the new account + /// will be stored in the `new_accounts` field and can be accessed later. + /// + /// - `"self"`: Reads the default keypair from the local configuration file. This is useful for accessing + /// the current user's account without specifying a keypair. + /// + /// - `"system"`: Represents the system program account. + /// + /// Whether an account is signable and mutable will be determined based on the account's definition in the + /// Idl (Interface Definition Language). Accounts marked as signable in the Idl will be treated as signers, + /// and mutable accounts will be set as mutable. + /// + /// # Parameters + /// + /// - `accounts`: A `Vec` containing the account names or keywords. + /// + /// # Returns + /// + /// Returns a new [`SolanaTransactionBuilder`] instance with the specified accounts set. + pub fn accounts>( + self, + accounts: Vec, + ) -> SolanaTransactionBuilder { + SolanaTransactionBuilder { + opts: SolanaTransactionOpts { + accounts: accounts.into_iter().map(|s| s.into()).collect(), + ..self.opts + }, + marker: PhantomData, + } + } +} + +impl SolanaTransactionBuilder> { + /// Sets the payer for the Solana program instruction. + /// + /// The payer is the account responsible for covering the transaction fees associated with + /// executing the Solana program instruction. It should be specified as the path to a keypair file. + /// + /// # Parameters + /// + /// - `payer`: A `String` containing the path to the keypair file for the payer account. + /// + /// # Returns + /// + /// Returns a new [`SolanaTransactionBuilder`] instance with the specified payer set. + pub fn payer>( + self, + payer: T, + ) -> SolanaTransactionBuilder { + SolanaTransactionBuilder { + opts: SolanaTransactionOpts { + payer: payer.into(), + ..self.opts + }, + marker: PhantomData, + } + } +} + +impl + SolanaTransactionBuilder< + state::RpcClient, + state::Idl, + state::ProgramID, + state::Instruction, + state::CallData, + state::Accounts, + state::Payer, + > +{ + /// Finalizes the configuration and prepares the [`SolanaTransaction`] instance for execution. + /// + /// This method initializes the [`SolanaTransaction`] instance with the provided configuration, + /// including the RPC client, Idl, program ID, instruction, call data, accounts, signers, + /// new accounts, and payer. If any errors occur during the configuration process, + /// they will be returned as an `Err` variant of the `Result`. + /// + /// # Errors + /// + /// This method returns an error if any of the following conditions are met: + /// + /// - The Idl cannot be obtained from the specified JSON file. + /// - The program ID cannot be parsed from the provided string. + /// - The specified instruction is not found in the Idl. + /// - There is an error constructing the call data. + /// - There is an error constructing the accounts. + /// - The payer keypair cannot be read from the specified file. + /// + /// # Returns + /// + /// Returns a `Result` containing the configured [`SolanaTransaction`] instance if the configuration + pub fn done(self) -> Result { + // Get the RPC client + let rpc_client = RpcClient::new_with_commitment( + self.opts.rpc_url.clone(), + CommitmentConfig::confirmed(), + ); + + // Get the Idl + let idl = idl_from_json(OsStr::new(&self.opts.idl)) + .map_err(|e| format_err!("Error getting Idl from JSON file: {}", e))?; + + // Get the program ID + let program_id = Pubkey::from_str(&self.opts.program_id) + .map_err(|e| format_err!("Error getting program ID: {}", e))?; + + // Find the instruction with the specified name + let instruction = idl + .instructions + .iter() + .find(|i| i.name == self.opts.instruction) + .ok_or_else(|| format_err!("Instruction {} not found", self.opts.instruction))? + .clone(); + + // Prepare the call data + let idl_defined_types = idl.types.clone(); + let call_data = + construct_instruction_data(&instruction, &self.opts.call_data, &idl_defined_types) + .map_err(|e| format_err!("Error constructing call data: {}", e))?; + + // Prepare the accounts + let (accounts, signers, new_accounts) = + construct_instruction_accounts(&instruction, &self.opts.accounts) + .map_err(|e| format_err!("Error constructing accounts: {}", e))?; + + // Get the payer + let payer = read_keypair_file(&self.opts.payer) + .map_err(|e| format_err!("Error getting payer: {}", e))?; + + Ok(SolanaTransaction { + rpc_client, + idl, + program_id, + instruction, + call_data, + accounts, + signers, + new_accounts, + payer, + }) + } +} + +#[allow(clippy::new_ret_no_self)] +impl SolanaTransaction { + /// Returns a clean builder for [`SolanaTransaction`] + #[allow(clippy::type_complexity)] + pub fn new() -> SolanaTransactionBuilder< + Missing, + Missing, + Missing, + Missing, + Missing, + Missing, + Missing, + > { + SolanaTransactionBuilder::new() + } + + /// Get the Rpc client + pub fn rpc_client(&self) -> &RpcClient { + &self.rpc_client + } + + /// Get the Idl + pub fn idl(&self) -> &Idl { + &self.idl + } + + /// Get the program ID + pub fn program_id(&self) -> &Pubkey { + &self.program_id + } + + /// Get the instruction + pub fn instruction(&self) -> &IdlInstruction { + &self.instruction + } + + /// Get the call data + pub fn call_data(&self) -> &Vec { + &self.call_data + } + + /// Get the accounts + pub fn accounts(&self) -> &Vec { + &self.accounts + } + + /// Get the signers + pub fn signers(&self) -> &Vec { + &self.signers + } + + /// Get the new accounts + pub fn new_accounts(&self) -> &Vec<(Pubkey, String)> { + &self.new_accounts + } + + /// Get the payer + pub fn payer(&self) -> &Keypair { + &self.payer + } + + /// Submits a transaction to the Solana network using the configured parameters. + /// + /// This method prepares and submits a transaction to the Solana network based on the + /// previously configured parameters, such as the program ID, instruction, call data, + /// accounts, signers, and payer. It handles the construction and signing of the transaction, + /// retrieves the latest blockhash from the RPC server, and sends the transaction to the network. + /// + /// # Errors + /// + /// This method returns an error if any of the following conditions are met: + /// + /// - The RPC client encounters an error when fetching the latest blockhash. + /// - Signing the transaction with the payer or other signers fails. + /// - Sending and confirming the transaction on the Solana network fails. + /// + /// # Returns + /// + /// Returns a `Result` containing the transaction's [`Signature`] if the submission process succeeds. + pub fn submit_transaction(&self) -> Result { + // Create the instruction + let instruction = Instruction { + program_id: self.program_id, + accounts: self.accounts.clone(), + data: self.call_data.clone(), + }; + + // Create the message + let payer_keypair = &self.payer; + let message = Message::new(&[instruction], Some(&payer_keypair.pubkey())); + let mut transaction = Transaction::new_unsigned(message); + + let rpc_client = &self.rpc_client; + let recent_blockhash = rpc_client + .get_latest_blockhash() + .map_err(|err| format_err!("error: unable to get latest blockhash: {}", err))?; + + // The payer needs to sign the transaction. + // This method does not require all keypairs to be provided. + // Note: It is permitted to sign a transaction with the same keypair multiple times. + transaction.partial_sign(&[payer_keypair], recent_blockhash); + + let signers = self + .signers + .iter() + .map(|keypair| keypair as &dyn Signer) + .collect::>(); + + // Sign the transaction + transaction + .try_sign(&signers, recent_blockhash) + .map_err(|err| format_err!("error: failed to sign transaction: {}", err))?; + + let signature = rpc_client + .send_and_confirm_transaction_with_spinner(&transaction) + .map_err(|err| format_err!("Error: {}", err,))?; + + Ok(signature) + } +} diff --git a/crates/aqd-solana-contracts/src/utils.rs b/crates/aqd-solana-contracts/src/utils.rs new file mode 100644 index 0000000..47ffca2 --- /dev/null +++ b/crates/aqd-solana-contracts/src/utils.rs @@ -0,0 +1,542 @@ +// SPDX-License-Identifier: Apache-2.0 + +use { + crate::borsh_encoding::{discriminator, encode_arguments, BorshToken}, + anchor_syn::idl::{ + Idl, IdlAccountItem, IdlInstruction, IdlType, IdlTypeDefinition, IdlTypeDefinitionTy::Enum, + IdlTypeDefinitionTy::Struct, + }, + anyhow::{anyhow, bail, Result}, + base58::FromBase58, + num_bigint::BigInt, + solana_cli_config::{Config, CONFIG_FILE}, + solana_sdk::{ + instruction::AccountMeta, + pubkey::Pubkey, + signature::{write_keypair_file, Keypair, Signer}, + signer::keypair::read_keypair_file, + system_program, + }, + std::{ffi::OsStr, fs::File, str::FromStr}, +}; + +/// Parses an IDL (Interface Description Language) definition from a JSON file. +/// +/// Given a file path provided as an [`OsStr`], this function attempts to open the file and +/// parse its content into an [`Idl`] struct. If successful, +/// it returns the parsed [`Idl`] struct. +/// +/// # Arguments +/// +/// * `file` - The path to the JSON file containing the IDL instruction definition. +/// +/// # Errors +/// +/// This function can return errors if the provided file path is invalid, the file cannot be +/// opened, or there are issues with parsing the JSON content. +pub fn idl_from_json(file: &OsStr) -> Result { + let f = match File::open(file) { + Ok(s) => s, + Err(e) => { + bail!("{}: error: {}", file.to_string_lossy(), e); + } + }; + + // Parse the JSON into an IDL + match serde_json::from_reader(f) { + Ok(idl) => Ok(idl), + Err(e) => { + bail!("{}: error: {}", file.to_string_lossy(), e); + } + } +} + +/// Constructs accounts, keypairs, and new accounts information for an IDL instruction. +/// +/// Given an [`IdlInstruction`] and a vector of raw account arguments, this function processes +/// the arguments, creates the necessary [`AccountMeta`] instances, and determines which accounts +/// should be treated as signers. If the raw account argument is one of the following keywords, +/// special actions are taken: +/// +/// - `new`: Create a new account and generate a keypair for it. The account's public key and +/// keypair path are recorded for reference. +/// +/// - `self`: Use the keypair specified in the local solana configuration file. +/// +/// - `system`: Use the system program ID for the account. This is equivalent to passing in the +/// system program ID as a public key. +/// +/// For other raw account arguments, the function checks if it's a valid keypair path or a valid +/// public key. If it's a valid keypair path, the keypair is loaded and used for the account. If +/// it's a valid public key, the public key is used for the account. Otherwise, an error is +/// returned. +/// +/// # Arguments +/// +/// * `instr` - The IDL instruction of type [`IdlInstruction`] for which to construct accounts. +/// +/// * `raw_args` - A vector of raw account arguments. Each argument can be one of the keywords +/// mentioned above, a keypair path, or a public key. +/// +/// # Returns +/// +/// Returns a `Result` containing a tuple of three vectors: +/// +/// 1. A vector of [`AccountMeta`] instances representing the accounts required for the instruction. +/// +/// 2. A vector of [`Keypair`] instances representing signers among the accounts. +/// +/// 3. A vector of `(Pubkey, String)` pairs representing new accounts created during the process. +/// +/// # Errors +/// +/// This function can return an error in the following cases: +/// +/// - If a raw account argument is missing or invalid. +/// +/// - If an account type is a nested account (e.g., `IdlAccounts`). +/// +/// - If the provided argument for an account is not a valid keyword, keypair path, or public key. +#[allow(clippy::type_complexity)] +pub fn construct_instruction_accounts( + instr: &IdlInstruction, + raw_args: &[String], +) -> Result<(Vec, Vec, Vec<(Pubkey, String)>)> { + // Initialize the return values + let mut accounts: Vec = vec![]; + let mut signers: Vec = vec![]; + let mut new_accounts: Vec<(Pubkey, String)> = vec![]; + + // Loop through the accounts and create the account meta + // given the raw arguments + for (i, account) in instr.accounts.iter().enumerate() { + let (account_name, is_signer, is_writable) = match account { + IdlAccountItem::IdlAccount(account) => { + (account.name.clone(), account.is_signer, account.is_mut) + } + IdlAccountItem::IdlAccounts(_) => return Err(anyhow!("Nested accounts not supported")), + }; + let raw_pubkey = raw_args + .get(i) + .ok_or_else(|| anyhow!("Missing account: {}", account_name))?; + let (key_pair, pubkey) = match raw_pubkey.as_str() { + "new" => { + // "new" is a special keyword that creates a new account + let keypair = Keypair::new(); + let pubkey = keypair.pubkey(); + // Write the keypair to a file + let keypair_path = format!("{}-{}.json", account_name, pubkey); + write_keypair_file(&keypair, &keypair_path) + .map_err(|_| anyhow!("Couldn't write keypair file to disk"))?; + new_accounts.push((pubkey, keypair_path.clone())); + + (Some(keypair), pubkey) + } + "self" => { + // "self" is a special keyword that uses the keypair from the config file + let config_file = CONFIG_FILE.as_ref().unwrap(); + let cli_config = Config::load(config_file).unwrap_or_default(); + let keypair = read_keypair_file(&cli_config.keypair_path).unwrap(); + let pubkey = keypair.pubkey(); + (Some(keypair), pubkey) + } + "system" => ( + // "system" is a special keyword that uses the system program ID + None, + system_program::id(), + ), + // There are 2 cases here: + // 1. The user passes in a keypair path + // 2. The user passes in a public key + _ => { + // First, check if the user passed in a keypair path + let keypair = read_keypair_file(raw_pubkey); + match keypair { + Ok(keypair) => { + let pubkey = keypair.pubkey(); + (Some(keypair), pubkey) + } + Err(_) => { + // The user passed in a public key + let pubkey = Pubkey::from_str(raw_pubkey).map_err(|_e| { + anyhow!("The provided argument for account: {} is not a valid keyword, keypair path or public key. \nProvided argument: {}", account_name , raw_pubkey) + })?; + (None, pubkey) + } + } + } + }; + + // Add the keypair to the list of signers if the account is a signer + if is_signer { + let key_pair = key_pair.ok_or_else( + || anyhow!("The provided argument for account: {} is not a valid keyword, keypair path or public key. \nProvided argument: {}", account_name , raw_pubkey), + )?; // This should never fail + signers.push(key_pair); + } + accounts.push(AccountMeta { + pubkey, + is_signer, + is_writable, + }); + } + + Ok((accounts, signers, new_accounts)) +} + +/// Constructs binary data for an instruction based on the provided IDL instruction and raw arguments. +/// +/// Given an [`IdlInstruction`], a vector of raw arguments, and a list of IDL type definitions, this +/// function encodes the arguments into binary data following the instruction's layout and type +/// definitions. The resulting binary data can be used as an instruction to invoke a smart contract +/// on a blockchain. +/// +/// # Arguments +/// +/// * `instr` - The IDL instruction of type [`IdlInstruction`] for which to construct binary data. +/// +/// * `raw_args` - A vector of raw argument values represented as strings. +/// +/// * `custom_types` - A vector of IDL type definitions used for encoding arguments. +/// +/// # Returns +/// +/// Returns a [`Result`] containing the encoded binary data as a [`Vec`]. +/// +/// # Errors +/// +/// This function can return an error in the following cases: +/// +/// - If any argument is missing or if the provided raw arguments do not match the expected +/// arguments defined by the IDL instruction. +/// +/// - If the IDL-defined types cannot be found or if there is an issue with encoding the arguments +/// based on these types. +pub fn construct_instruction_data( + instr: &IdlInstruction, + raw_args: &[String], + custom_types: &Vec, +) -> Result> { + // Construct the discriminator (the first 8 bytes of the instruction data) + // The namespace is always "global" + let mut data = discriminator("global", &instr.name); + let mut args: Vec = vec![]; + + // Loop through the arguments and encode them given the IDL instruction + for (i, arg) in instr.args.iter().enumerate() { + let arg_name = arg.name.clone(); + let arg_type = arg.ty.clone(); + let arg_val = raw_args + .get(i) + .ok_or_else(|| anyhow!("Missing argument {}", arg_name))?; + + // Encode the argument based on the IDL type + let mut borsh_args = get_borsh_token_vector(arg_val.to_string(), &arg_type, custom_types)?; + args.append(&mut borsh_args); + } + + let mut encoded_data = encode_arguments(&args); + data.append(&mut encoded_data); + + Ok(data) +} + +/// Converts a raw argument value into a vector of Borsh tokens based on the provided IDL type. +/// +/// This function takes a raw argument value as a string, an IDL type definition, and a list of +/// IDL type definitions for reference. It then converts the raw argument value into a vector of +/// Borsh tokens, considering the specified IDL type and nested types if applicable. +/// +/// # Arguments +/// +/// * `arg_value` - The raw argument value to be converted. The expected input format depends on +/// the IDL type: +/// +/// - For structs, provide a JSON string representing the data structure. +/// - For arrays and vectors, provide a comma-separated string of values. +/// +/// * `arg_type` - The IDL type definition specifying the expected type of the argument. +/// +/// * `custom_types` - A vector of IDL type definitions used for resolving nested types. +/// +/// # Returns +/// +/// Returns a [`Result`] containing the vector of Borsh tokens ([`Vec`]) representing +/// the converted argument value. +/// +/// # Errors +/// +/// This function can return an error if there is an issue with converting the raw argument value +/// to the specified Borsh tokens based on the given IDL type. +fn get_borsh_token_vector( + arg_value: String, + arg_type: &IdlType, + custom_types: &Vec, +) -> Result> { + let mut args: Vec = vec![]; + match arg_type { + IdlType::Bool => { + let val = arg_value.parse::().map_err(|_e| { + anyhow!("The provided argument for bool is not a valid boolean. \nProvided argument: {}\n", arg_value) + })?; + args.push(BorshToken::Bool(val)); + } + IdlType::U8 => { + let val = arg_value.parse::().map_err(|_e| { + anyhow!("The provided argument for u8 is not a valid unsigned integer. \nProvided argument: {}\n", arg_value) + })?; + args.push(BorshToken::Uint { + width: 8, + value: BigInt::from(val), + }); + } + IdlType::I8 => { + let val = arg_value.parse::().map_err(|_e| { + anyhow!("The provided argument for i8 is not a valid signed integer. \nProvided argument: {}\n", arg_value) + })?; + args.push(BorshToken::Int { + width: 8, + value: BigInt::from(val), + }); + } + IdlType::U16 => { + let val = arg_value.parse::().map_err(|_e| { + anyhow!("The provided argument for u16 is not a valid unsigned integer. \nProvided argument: {}\n", arg_value) + })?; + args.push(BorshToken::Uint { + width: 16, + value: BigInt::from(val), + }); + } + IdlType::I16 => { + let val = arg_value.parse::().map_err(|_e| { + anyhow!("The provided argument for i16 is not a valid signed integer. \nProvided argument: {}\n", arg_value) + })?; + args.push(BorshToken::Int { + width: 16, + value: BigInt::from(val), + }); + } + IdlType::U32 => { + let val = arg_value.parse::().map_err( + |_e| anyhow!("The provided argument for u32 is not a valid unsigned integer. \nProvided argument: {}\n", arg_value), + )?; + args.push(BorshToken::Uint { + width: 32, + value: BigInt::from(val), + }); + } + IdlType::I32 => { + let val = arg_value.parse::().map_err( + |_e| anyhow!("The provided argument for i32 is not a valid signed integer. \nProvided argument: {}\n", arg_value), + )?; + args.push(BorshToken::Int { + width: 32, + value: BigInt::from(val), + }); + } + IdlType::F32 => { + return Err(anyhow!("Float is not supported")); + } + IdlType::U64 => { + let val = arg_value.parse::().map_err( + |_e| anyhow!("The provided argument for u64 is not a valid unsigned integer. \nProvided argument: {}\n", arg_value), + )?; + args.push(BorshToken::Uint { + width: 64, + value: BigInt::from(val), + }); + } + IdlType::I64 => { + let val = arg_value.parse::().map_err( + |_e| anyhow!("The provided argument for i64 is not a valid signed integer. \nProvided argument: {}\n", arg_value), + )?; + args.push(BorshToken::Int { + width: 64, + value: BigInt::from(val), + }); + } + IdlType::F64 => { + return Err(anyhow!("Float is not supported")); + } + IdlType::U128 => { + let val = arg_value.parse::().map_err( + |_e| anyhow!("The provided argument for u128 is not a valid unsigned integer. \nProvided argument: {}\n", arg_value), + )?; + args.push(BorshToken::Uint { + width: 128, + value: BigInt::from(val), + }); + } + IdlType::I128 => { + let val = arg_value.parse::().map_err( + |_e| anyhow!("The provided argument for i128 is not a valid signed integer. \nProvided argument: {}\n", arg_value), + )?; + args.push(BorshToken::Int { + width: 128, + value: BigInt::from(val), + }); + } + IdlType::U256 => { + let val = BigInt::parse_bytes(arg_value.as_bytes(), 10).ok_or_else( + || anyhow!("The provided argument for u256 is not a valid unsigned integer. \nProvided argument: {}\n", arg_value), + )?; + args.push(BorshToken::Uint { + width: 256, + value: val, + }); + } + IdlType::I256 => { + let val = BigInt::parse_bytes(arg_value.as_bytes(), 10).ok_or_else( + || anyhow!("The provided argument for i256 is not a valid unsigned integer. \nProvided argument: {}\n", arg_value), + )?; + args.push(BorshToken::Int { + width: 256, + value: val, + }); + } + IdlType::Bytes => { + let val = match hex::decode(&arg_value) { + Ok(val) => val, + Err(_) => { + return Err(anyhow!("The provided argument for Bytes is not a valid hex string. \nProvided argument: {}\n", arg_value)) + } + }; + args.push(BorshToken::Bytes(val)); + } + IdlType::String => { + args.push(BorshToken::String(arg_value.to_string())); + } + IdlType::PublicKey => { + let val = arg_value.from_base58().map_err(|_e| { + anyhow!("The provided argument for PublicKey is not a valid base58 string. \nProvided argument: {}\n", arg_value) + })?; + let val = <[u8; 32]>::try_from(val).map_err(|_e| { + anyhow!("The provided argument for PublicKey is not a valid base58 string. \nProvided argument: {}\n", arg_value) + })?; + args.push(BorshToken::Address(val)); + } + IdlType::Defined(ty) => { + let defined_type = custom_types + .iter() + .find(|t| t.name == *ty) + .ok_or_else(|| anyhow!("Type definition with name {} not found", ty))?; + let mut borsh_args_for_defined_type = + encode_id_defined_type(arg_value.to_string(), defined_type, custom_types)?; + args.append(&mut borsh_args_for_defined_type); + } + IdlType::Option(_) => { + return Err(anyhow!("Option is not supported")); + } + IdlType::Vec(elem_type) => { + // Split the string into a vector of strings + let val: Vec = arg_value.split(',').map(|s| s.to_string()).collect(); + let mut borsh_args: Vec = vec![]; + for arg in val { + let mut borsh_arg = get_borsh_token_vector(arg, elem_type, custom_types)?; + borsh_args.append(&mut borsh_arg); + } + args.push(BorshToken::Array(borsh_args)); + } + IdlType::Array(elem_type, size) => { + // Split the string into a vector of strings + let val: Vec = arg_value.split(',').map(|s| s.to_string()).collect(); + // Make sure the number of elements matches the size of the array + if val.len() != *size { + return Err(anyhow!( + "The number of elements in the array does not match the size of the array. \nProvided argument: {}\n", + arg_value + )); + } + let mut borsh_args: Vec = vec![]; + for arg in val { + let mut borsh_arg = get_borsh_token_vector(arg, elem_type, custom_types)?; + borsh_args.append(&mut borsh_arg); + } + args.push(BorshToken::FixedArray(borsh_args)); + } + } + Ok(args) +} + +/// Converts a raw argument value into a vector of Borsh tokens for a custom IDL-defined type. +/// +/// This function takes a raw argument value as a string, a custom IDL type definition, and a list +/// of IDL type definitions for reference. It then converts the raw argument value into a vector of +/// Borsh tokens based on the specified custom IDL type, including handling structs and enums as per +/// the IDL definition. +/// +/// # Arguments +/// +/// * `arg_value` - The raw argument value as a string to be converted. +/// +/// * `defined_type` - The custom IDL type definition specifying the expected type of the argument. +/// +/// * `custom_types` - A vector of IDL type definitions used for resolving nested types. +/// +/// # Returns +/// +/// Returns a [`Result`] containing the vector of Borsh tokens ([`Vec`]) representing +/// the converted argument value. +fn encode_id_defined_type( + arg_value: String, + defined_type: &IdlTypeDefinition, + custom_types: &Vec, +) -> Result> { + let mut response: Vec = vec![]; + let ty = &defined_type.ty; + match ty { + Struct { fields } => { + // The user could either pass a JSON object or a path to a JSON file + // If the user passes a path to a JSON file, we need to read the file first + let arg_value = match std::fs::read_to_string(&arg_value) { + Ok(s) => s, + Err(_) => arg_value, + }; + + // The user should pass a json object + // for example: {"a": 1, "b": 2} + // we need to parse the json object and then encode it + let json_object: serde_json::Value = serde_json::from_str(&arg_value).map_err( + |_e| anyhow!("The provided argument for Struct is not a valid JSON object. \nProvided argument: {}\n", arg_value), + )?; + for field in fields { + let field_name = &field.name; + let field_ty = &field.ty; + let field_value = json_object + .get(field_name) + .ok_or_else(|| anyhow!("Field {} not found", field_name))?; + let mut borsh_args = + get_borsh_token_vector(field_value.to_string(), field_ty, custom_types)?; + response.append(&mut borsh_args); + } + } + Enum { variants } => { + // If the variant is a string, we need to remove the quotes + let arg_value = arg_value.replace('\"', ""); + // The user passes a String of the variant name + // for example: "A" + // we need to find index of the variant and then encode it + let variant_index = variants + .iter() + .position(|v| v.name == arg_value) + .ok_or_else(|| { + anyhow!( + "Variant {} not found. \nAvailable variants of {}: {:?}", + arg_value, + defined_type.name, + variants + .iter() + .map(|v| v.clone().name) + .collect::>() + ) + })?; + + let mut borsh_args = + get_borsh_token_vector(variant_index.to_string(), &IdlType::U8, custom_types)?; + response.append(&mut borsh_args); + } + } + + Ok(response) +} diff --git a/crates/aqd-solana-contracts/tests/contracts/AddressTest.json b/crates/aqd-solana-contracts/tests/contracts/AddressTest.json new file mode 100644 index 0000000..ad711d4 --- /dev/null +++ b/crates/aqd-solana-contracts/tests/contracts/AddressTest.json @@ -0,0 +1,61 @@ +{ + "version": "0.0.1", + "name": "AddressTest", + "instructions": [ + { + "name": "addressData", + "accounts": [ + { + "name": "dataAccount", + "isMut": false, + "isSigner": false, + "isOptional": false + } + ], + "args": [], + "returns": "publicKey" + }, + { + "name": "new", + "accounts": [ + { + "name": "dataAccount", + "isMut": true, + "isSigner": true, + "isOptional": false + }, + { + "name": "payer", + "isMut": true, + "isSigner": true, + "isOptional": false + }, + { + "name": "systemProgram", + "isMut": false, + "isSigner": false, + "isOptional": false + } + ], + "args": [ + { + "name": "initaddress", + "type": "publicKey" + } + ] + }, + { + "name": "getAddressData", + "accounts": [ + { + "name": "dataAccount", + "isMut": false, + "isSigner": false, + "isOptional": false + } + ], + "args": [], + "returns": "publicKey" + } + ] +} \ No newline at end of file diff --git a/crates/aqd-solana-contracts/tests/contracts/DefinedTypes.json b/crates/aqd-solana-contracts/tests/contracts/DefinedTypes.json new file mode 100644 index 0000000..d2c1fda --- /dev/null +++ b/crates/aqd-solana-contracts/tests/contracts/DefinedTypes.json @@ -0,0 +1,182 @@ +{ + "version": "0.0.1", + "name": "DefinedTypes", + "instructions": [ + { + "name": "personData", + "accounts": [ + { + "name": "dataAccount", + "isMut": false, + "isSigner": false, + "isOptional": false + } + ], + "args": [], + "returns": { + "defined": "personData_returns" + } + }, + { + "name": "colorData", + "accounts": [ + { + "name": "dataAccount", + "isMut": false, + "isSigner": false, + "isOptional": false + } + ], + "args": [], + "returns": { + "defined": "Color" + } + }, + { + "name": "new", + "accounts": [ + { + "name": "dataAccount", + "isMut": true, + "isSigner": true, + "isOptional": false + }, + { + "name": "payer", + "isMut": true, + "isSigner": true, + "isOptional": false + }, + { + "name": "systemProgram", + "isMut": false, + "isSigner": false, + "isOptional": false + } + ], + "args": [ + { + "name": "person", + "type": { + "defined": "Person" + } + } + ] + }, + { + "name": "setColor", + "accounts": [ + { + "name": "dataAccount", + "isMut": true, + "isSigner": false, + "isOptional": false + } + ], + "args": [ + { + "name": "color", + "type": { + "defined": "Color" + } + } + ] + }, + { + "name": "getPerson", + "accounts": [ + { + "name": "dataAccount", + "isMut": false, + "isSigner": false, + "isOptional": false + } + ], + "args": [], + "returns": { + "defined": "Person" + } + }, + { + "name": "getColor", + "accounts": [ + { + "name": "dataAccount", + "isMut": false, + "isSigner": false, + "isOptional": false + } + ], + "args": [], + "returns": { + "defined": "Color" + } + } + ], + "types": [ + { + "name": "Color", + "type": { + "kind": "enum", + "variants": [ + { + "name": "Red" + }, + { + "name": "Green" + }, + { + "name": "Blue" + } + ] + } + }, + { + "name": "Person", + "type": { + "kind": "struct", + "fields": [ + { + "name": "name", + "type": "string" + }, + { + "name": "age", + "type": "u8" + }, + { + "name": "favoriteColor", + "type": { + "defined": "Color" + } + } + ] + } + }, + { + "name": "personData_returns", + "docs": [ + "Data structure to hold the multiple returns of function personData" + ], + "type": { + "kind": "struct", + "fields": [ + { + "name": "name", + "type": "string" + }, + { + "name": "age", + "type": "u8" + }, + { + "name": "favoriteColor", + "type": { + "defined": "Color" + } + } + ] + } + } + ] +} \ No newline at end of file diff --git a/crates/aqd-solana-contracts/tests/contracts/VectorTest.json b/crates/aqd-solana-contracts/tests/contracts/VectorTest.json new file mode 100644 index 0000000..7469491 --- /dev/null +++ b/crates/aqd-solana-contracts/tests/contracts/VectorTest.json @@ -0,0 +1,70 @@ +{ + "version": "0.0.1", + "name": "VectorTest", + "instructions": [ + { + "name": "intArray", + "accounts": [ + { + "name": "dataAccount", + "isMut": false, + "isSigner": false, + "isOptional": false + } + ], + "args": [ + { + "name": "arg0", + "type": "u256" + } + ], + "returns": "u8" + }, + { + "name": "new", + "accounts": [ + { + "name": "dataAccount", + "isMut": true, + "isSigner": true, + "isOptional": false + }, + { + "name": "payer", + "isMut": true, + "isSigner": true, + "isOptional": false + }, + { + "name": "systemProgram", + "isMut": false, + "isSigner": false, + "isOptional": false + } + ], + "args": [ + { + "name": "initintarray", + "type": { + "vec": "u8" + } + } + ] + }, + { + "name": "getIntArray", + "accounts": [ + { + "name": "dataAccount", + "isMut": false, + "isSigner": false, + "isOptional": false + } + ], + "args": [], + "returns": { + "vec": "u8" + } + } + ] +} \ No newline at end of file diff --git a/crates/aqd-solana-contracts/tests/contracts/address.sol b/crates/aqd-solana-contracts/tests/contracts/address.sol new file mode 100644 index 0000000..048b74b --- /dev/null +++ b/crates/aqd-solana-contracts/tests/contracts/address.sol @@ -0,0 +1,12 @@ +contract AddressTest { + address public addressData; + + @payer(payer) + constructor(address initAddress) { + addressData = initAddress; + } + + function getAddressData() public view returns (address) { + return addressData; + } +} diff --git a/crates/aqd-solana-contracts/tests/contracts/array.json b/crates/aqd-solana-contracts/tests/contracts/array.json new file mode 100644 index 0000000..389c3a9 --- /dev/null +++ b/crates/aqd-solana-contracts/tests/contracts/array.json @@ -0,0 +1,76 @@ +{ + "version": "0.0.1", + "name": "array", + "instructions": [ + { + "name": "intArray", + "accounts": [ + { + "name": "dataAccount", + "isMut": false, + "isSigner": false, + "isOptional": false + } + ], + "args": [ + { + "name": "arg0", + "type": "u256" + } + ], + "returns": "u8" + }, + { + "name": "new", + "accounts": [ + { + "name": "dataAccount", + "isMut": true, + "isSigner": true, + "isOptional": false + }, + { + "name": "payer", + "isMut": true, + "isSigner": true, + "isOptional": false + }, + { + "name": "systemProgram", + "isMut": false, + "isSigner": false, + "isOptional": false + } + ], + "args": [ + { + "name": "initintarray", + "type": { + "array": [ + "u8", + 4 + ] + } + } + ] + }, + { + "name": "getIntArray", + "accounts": [ + { + "name": "dataAccount", + "isMut": false, + "isSigner": false, + "isOptional": false + } + ], + "args": [], + "returns": { + "array": [ + "u8", + 4 + ] + } + } + ] +} \ No newline at end of file diff --git a/crates/aqd-solana-contracts/tests/contracts/array.sol b/crates/aqd-solana-contracts/tests/contracts/array.sol new file mode 100644 index 0000000..684d6e7 --- /dev/null +++ b/crates/aqd-solana-contracts/tests/contracts/array.sol @@ -0,0 +1,14 @@ +contract array { + uint8[4] public intArray; + + @payer(payer) + constructor( + uint8[4] initIntArray + ) { + intArray = initIntArray; + } + + function getIntArray() public view returns (uint8[4]) { + return intArray; + } +} diff --git a/crates/aqd-solana-contracts/tests/contracts/byte_test.json b/crates/aqd-solana-contracts/tests/contracts/byte_test.json new file mode 100644 index 0000000..e78745e --- /dev/null +++ b/crates/aqd-solana-contracts/tests/contracts/byte_test.json @@ -0,0 +1,61 @@ +{ + "version": "0.0.1", + "name": "byte_test", + "instructions": [ + { + "name": "byteVal", + "accounts": [ + { + "name": "dataAccount", + "isMut": false, + "isSigner": false, + "isOptional": false + } + ], + "args": [], + "returns": "bytes" + }, + { + "name": "new", + "accounts": [ + { + "name": "dataAccount", + "isMut": true, + "isSigner": true, + "isOptional": false + }, + { + "name": "payer", + "isMut": true, + "isSigner": true, + "isOptional": false + }, + { + "name": "systemProgram", + "isMut": false, + "isSigner": false, + "isOptional": false + } + ], + "args": [ + { + "name": "initbyteval", + "type": "bytes" + } + ] + }, + { + "name": "getbyteVal", + "accounts": [ + { + "name": "dataAccount", + "isMut": false, + "isSigner": false, + "isOptional": false + } + ], + "args": [], + "returns": "bytes" + } + ] +} \ No newline at end of file diff --git a/crates/aqd-solana-contracts/tests/contracts/bytes.sol b/crates/aqd-solana-contracts/tests/contracts/bytes.sol new file mode 100644 index 0000000..c353a97 --- /dev/null +++ b/crates/aqd-solana-contracts/tests/contracts/bytes.sol @@ -0,0 +1,13 @@ +contract byte_test { + bytes public byteVal; + + @payer(payer) + @space(1024) + constructor(bytes initbyteVal) { + byteVal = initbyteVal; + } + + function getbyteVal() public view returns (bytes) { + return byteVal; + } +} \ No newline at end of file diff --git a/crates/aqd-solana-contracts/tests/contracts/defined_types.sol b/crates/aqd-solana-contracts/tests/contracts/defined_types.sol new file mode 100644 index 0000000..5c6e080 --- /dev/null +++ b/crates/aqd-solana-contracts/tests/contracts/defined_types.sol @@ -0,0 +1,34 @@ +contract DefinedTypes { + // Enum definition + enum Color { Red, Green, Blue } + + // Struct definition + struct Person { + string name; + uint8 age; + Color favoriteColor; + } + + // State variables + Person public personData; + Color public colorData; + + @payer(payer) + @space(1024) + constructor(Person person) { + personData = person; + } + + function setColor(Color color) public { + colorData = color; + } + + // Getters + function getPerson() public view returns (Person person) { + return personData; + } + + function getColor() public view returns (Color) { + return colorData; + } +} diff --git a/crates/aqd-solana-contracts/tests/contracts/flipper.json b/crates/aqd-solana-contracts/tests/contracts/flipper.json new file mode 100644 index 0000000..c84aaf4 --- /dev/null +++ b/crates/aqd-solana-contracts/tests/contracts/flipper.json @@ -0,0 +1,69 @@ +{ + "version": "0.0.1", + "name": "flipper", + "instructions": [ + { + "name": "new", + "docs": [ + "notice: Constructor that initializes the `bool` value to the given `init_value`." + ], + "accounts": [ + { + "name": "dataAccount", + "isMut": true, + "isSigner": true, + "isOptional": false + }, + { + "name": "payer", + "isMut": true, + "isSigner": true, + "isOptional": false + }, + { + "name": "systemProgram", + "isMut": false, + "isSigner": false, + "isOptional": false + } + ], + "args": [ + { + "name": "initvalue", + "type": "bool" + } + ] + }, + { + "name": "flip", + "docs": [ + "notice: A message that can be called on instantiated contracts.\nThis one flips the value of the stored `bool` from `true`\nto `false` and vice versa." + ], + "accounts": [ + { + "name": "dataAccount", + "isMut": true, + "isSigner": false, + "isOptional": false + } + ], + "args": [] + }, + { + "name": "get", + "docs": [ + "notice: Simply returns the current value of our `bool`." + ], + "accounts": [ + { + "name": "dataAccount", + "isMut": false, + "isSigner": false, + "isOptional": false + } + ], + "args": [], + "returns": "bool" + } + ] +} \ No newline at end of file diff --git a/crates/aqd-solana-contracts/tests/contracts/flipper.sol b/crates/aqd-solana-contracts/tests/contracts/flipper.sol new file mode 100644 index 0000000..ec1e2f6 --- /dev/null +++ b/crates/aqd-solana-contracts/tests/contracts/flipper.sol @@ -0,0 +1,21 @@ +contract flipper { + bool private value; + + /// Constructor that initializes the `bool` value to the given `init_value`. + @payer(payer) + constructor(bool initvalue) { + value = initvalue; + } + + /// A message that can be called on instantiated contracts. + /// This one flips the value of the stored `bool` from `true` + /// to `false` and vice versa. + function flip() public { + value = !value; + } + + /// Simply returns the current value of our `bool`. + function get() public view returns (bool) { + return value; + } +} diff --git a/crates/aqd-solana-contracts/tests/contracts/signed_int.json b/crates/aqd-solana-contracts/tests/contracts/signed_int.json new file mode 100644 index 0000000..9ca0479 --- /dev/null +++ b/crates/aqd-solana-contracts/tests/contracts/signed_int.json @@ -0,0 +1,211 @@ +{ + "version": "0.0.1", + "name": "signed_int", + "instructions": [ + { + "name": "i8Value", + "accounts": [ + { + "name": "dataAccount", + "isMut": false, + "isSigner": false, + "isOptional": false + } + ], + "args": [], + "returns": "i8" + }, + { + "name": "i16Value", + "accounts": [ + { + "name": "dataAccount", + "isMut": false, + "isSigner": false, + "isOptional": false + } + ], + "args": [], + "returns": "i16" + }, + { + "name": "i32Value", + "accounts": [ + { + "name": "dataAccount", + "isMut": false, + "isSigner": false, + "isOptional": false + } + ], + "args": [], + "returns": "i32" + }, + { + "name": "i64Value", + "accounts": [ + { + "name": "dataAccount", + "isMut": false, + "isSigner": false, + "isOptional": false + } + ], + "args": [], + "returns": "i64" + }, + { + "name": "i128Value", + "accounts": [ + { + "name": "dataAccount", + "isMut": false, + "isSigner": false, + "isOptional": false + } + ], + "args": [], + "returns": "i128" + }, + { + "name": "i256Value", + "accounts": [ + { + "name": "dataAccount", + "isMut": false, + "isSigner": false, + "isOptional": false + } + ], + "args": [], + "returns": "i256" + }, + { + "name": "new", + "accounts": [ + { + "name": "dataAccount", + "isMut": true, + "isSigner": true, + "isOptional": false + }, + { + "name": "payer", + "isMut": true, + "isSigner": true, + "isOptional": false + }, + { + "name": "systemProgram", + "isMut": false, + "isSigner": false, + "isOptional": false + } + ], + "args": [ + { + "name": "initi8value", + "type": "i8" + }, + { + "name": "initi16value", + "type": "i16" + }, + { + "name": "initi32value", + "type": "i32" + }, + { + "name": "initi64value", + "type": "i64" + }, + { + "name": "initi128value", + "type": "i128" + }, + { + "name": "initi256value", + "type": "i256" + } + ] + }, + { + "name": "getI8Value", + "accounts": [ + { + "name": "dataAccount", + "isMut": false, + "isSigner": false, + "isOptional": false + } + ], + "args": [], + "returns": "i8" + }, + { + "name": "getI16Value", + "accounts": [ + { + "name": "dataAccount", + "isMut": false, + "isSigner": false, + "isOptional": false + } + ], + "args": [], + "returns": "i16" + }, + { + "name": "getI32Value", + "accounts": [ + { + "name": "dataAccount", + "isMut": false, + "isSigner": false, + "isOptional": false + } + ], + "args": [], + "returns": "i32" + }, + { + "name": "getI64Value", + "accounts": [ + { + "name": "dataAccount", + "isMut": false, + "isSigner": false, + "isOptional": false + } + ], + "args": [], + "returns": "i64" + }, + { + "name": "getI128Value", + "accounts": [ + { + "name": "dataAccount", + "isMut": false, + "isSigner": false, + "isOptional": false + } + ], + "args": [], + "returns": "i128" + }, + { + "name": "getI256Value", + "accounts": [ + { + "name": "dataAccount", + "isMut": false, + "isSigner": false, + "isOptional": false + } + ], + "args": [], + "returns": "i256" + } + ] +} \ No newline at end of file diff --git a/crates/aqd-solana-contracts/tests/contracts/signed_int.sol b/crates/aqd-solana-contracts/tests/contracts/signed_int.sol new file mode 100644 index 0000000..b7d5c81 --- /dev/null +++ b/crates/aqd-solana-contracts/tests/contracts/signed_int.sol @@ -0,0 +1,49 @@ +contract signed_int { + int8 public i8Value; + int16 public i16Value; + int32 public i32Value; + int64 public i64Value; + int128 public i128Value; + int256 public i256Value; + + @payer(payer) + constructor( + int8 initi8Value, + int16 initi16Value, + int32 initi32Value, + int64 initi64Value, + int128 initi128Value, + int256 initi256Value + ) { + i8Value = initi8Value; + i16Value = initi16Value; + i32Value = initi32Value; + i64Value = initi64Value; + i128Value = initi128Value; + i256Value = initi256Value; + } + + function getI8Value() public view returns (int8) { + return i8Value; + } + + function getI16Value() public view returns (int16) { + return i16Value; + } + + function getI32Value() public view returns (int32) { + return i32Value; + } + + function getI64Value() public view returns (int64) { + return i64Value; + } + + function getI128Value() public view returns (int128) { + return i128Value; + } + + function getI256Value() public view returns (int256) { + return i256Value; + } +} diff --git a/crates/aqd-solana-contracts/tests/contracts/unsigned_int.json b/crates/aqd-solana-contracts/tests/contracts/unsigned_int.json new file mode 100644 index 0000000..730fee1 --- /dev/null +++ b/crates/aqd-solana-contracts/tests/contracts/unsigned_int.json @@ -0,0 +1,211 @@ +{ + "version": "0.0.1", + "name": "unsigned_int", + "instructions": [ + { + "name": "uint8Value", + "accounts": [ + { + "name": "dataAccount", + "isMut": false, + "isSigner": false, + "isOptional": false + } + ], + "args": [], + "returns": "u8" + }, + { + "name": "uint16Value", + "accounts": [ + { + "name": "dataAccount", + "isMut": false, + "isSigner": false, + "isOptional": false + } + ], + "args": [], + "returns": "u16" + }, + { + "name": "uint32Value", + "accounts": [ + { + "name": "dataAccount", + "isMut": false, + "isSigner": false, + "isOptional": false + } + ], + "args": [], + "returns": "u32" + }, + { + "name": "uint64Value", + "accounts": [ + { + "name": "dataAccount", + "isMut": false, + "isSigner": false, + "isOptional": false + } + ], + "args": [], + "returns": "u64" + }, + { + "name": "uint128Value", + "accounts": [ + { + "name": "dataAccount", + "isMut": false, + "isSigner": false, + "isOptional": false + } + ], + "args": [], + "returns": "u128" + }, + { + "name": "uint256Value", + "accounts": [ + { + "name": "dataAccount", + "isMut": false, + "isSigner": false, + "isOptional": false + } + ], + "args": [], + "returns": "u256" + }, + { + "name": "new", + "accounts": [ + { + "name": "dataAccount", + "isMut": true, + "isSigner": true, + "isOptional": false + }, + { + "name": "payer", + "isMut": true, + "isSigner": true, + "isOptional": false + }, + { + "name": "systemProgram", + "isMut": false, + "isSigner": false, + "isOptional": false + } + ], + "args": [ + { + "name": "inituint8value", + "type": "u8" + }, + { + "name": "inituint16value", + "type": "u16" + }, + { + "name": "inituint32value", + "type": "u32" + }, + { + "name": "inituint64value", + "type": "u64" + }, + { + "name": "inituint128value", + "type": "u128" + }, + { + "name": "inituint256value", + "type": "u256" + } + ] + }, + { + "name": "getUint8Value", + "accounts": [ + { + "name": "dataAccount", + "isMut": false, + "isSigner": false, + "isOptional": false + } + ], + "args": [], + "returns": "u8" + }, + { + "name": "getUint16Value", + "accounts": [ + { + "name": "dataAccount", + "isMut": false, + "isSigner": false, + "isOptional": false + } + ], + "args": [], + "returns": "u16" + }, + { + "name": "getUint32Value", + "accounts": [ + { + "name": "dataAccount", + "isMut": false, + "isSigner": false, + "isOptional": false + } + ], + "args": [], + "returns": "u32" + }, + { + "name": "getUint64Value", + "accounts": [ + { + "name": "dataAccount", + "isMut": false, + "isSigner": false, + "isOptional": false + } + ], + "args": [], + "returns": "u64" + }, + { + "name": "getUint128Value", + "accounts": [ + { + "name": "dataAccount", + "isMut": false, + "isSigner": false, + "isOptional": false + } + ], + "args": [], + "returns": "u128" + }, + { + "name": "getUint256Value", + "accounts": [ + { + "name": "dataAccount", + "isMut": false, + "isSigner": false, + "isOptional": false + } + ], + "args": [], + "returns": "u256" + } + ] +} \ No newline at end of file diff --git a/crates/aqd-solana-contracts/tests/contracts/unsigned_int.sol b/crates/aqd-solana-contracts/tests/contracts/unsigned_int.sol new file mode 100644 index 0000000..73e8932 --- /dev/null +++ b/crates/aqd-solana-contracts/tests/contracts/unsigned_int.sol @@ -0,0 +1,49 @@ +contract unsigned_int { + uint8 public uint8Value; + uint16 public uint16Value; + uint32 public uint32Value; + uint64 public uint64Value; + uint128 public uint128Value; + uint256 public uint256Value; + + @payer(payer) + constructor( + uint8 initUint8Value, + uint16 initUint16Value, + uint32 initUint32Value, + uint64 initUint64Value, + uint128 initUint128Value, + uint256 initUint256Value + ) { + uint8Value = initUint8Value; + uint16Value = initUint16Value; + uint32Value = initUint32Value; + uint64Value = initUint64Value; + uint128Value = initUint128Value; + uint256Value = initUint256Value; + } + + function getUint8Value() public view returns (uint8) { + return uint8Value; + } + + function getUint16Value() public view returns (uint16) { + return uint16Value; + } + + function getUint32Value() public view returns (uint32) { + return uint32Value; + } + + function getUint64Value() public view returns (uint64) { + return uint64Value; + } + + function getUint128Value() public view returns (uint128) { + return uint128Value; + } + + function getUint256Value() public view returns (uint256) { + return uint256Value; + } +} diff --git a/crates/aqd-solana-contracts/tests/contracts/vector.sol b/crates/aqd-solana-contracts/tests/contracts/vector.sol new file mode 100644 index 0000000..7e5b5f3 --- /dev/null +++ b/crates/aqd-solana-contracts/tests/contracts/vector.sol @@ -0,0 +1,13 @@ +contract VectorTest { + uint8[] public intArray; + + @payer(payer) + @space(1024) + constructor(uint8[] memory initIntArray) { + intArray = initIntArray; + } + + function getIntArray() public view returns (uint8[] memory) { + return intArray; + } +} diff --git a/crates/aqd-solana-contracts/tests/test_address.rs b/crates/aqd-solana-contracts/tests/test_address.rs new file mode 100644 index 0000000..f8a832d --- /dev/null +++ b/crates/aqd-solana-contracts/tests/test_address.rs @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: Apache-2.0 + +use { + anyhow::Result, + aqd_solana_contracts::{construct_instruction_data, idl_from_json}, + std::ffi::OsStr, +}; + +/// Purpose: This test checks the instruction data for the "new" function of the address program. +/// +/// Note: The "address" program is a custom program that was created for this test. +/// The program's IDL is defined in tests/contracts/AddressTest.json. +/// The purpose of this program is to test address type. +#[tokio::test] +pub async fn test_address_new_data() -> Result<()> { + // Define the address program's IDL and the instruction we want to test. + let idl_json = "tests/contracts/AddressTest.json"; + let instruction_name = "new"; + let data = vec!["1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM".to_string()]; + + // Load the address program's IDL and find the instruction we want to test. + let idl = idl_from_json(OsStr::new(idl_json))?; + let idl_instruction = + if let Some(instruction) = idl.instructions.iter().find(|i| i.name == instruction_name) { + instruction.clone() + } else { + return Err(anyhow::anyhow!( + "Instruction not found: {}", + instruction_name + )); + }; + let custom_types = idl.types.clone(); + + // Construct the instruction data. + let data = construct_instruction_data(&idl_instruction, &data, &custom_types)?; + + // Verify the instruction data is correct. + assert_eq!( + data, + vec![ + 135, 44, 205, 198, 25, 1, 72, 188, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + ] + ); + + Ok(()) +} diff --git a/crates/aqd-solana-contracts/tests/test_arrays.rs b/crates/aqd-solana-contracts/tests/test_arrays.rs new file mode 100644 index 0000000..b6fa4c0 --- /dev/null +++ b/crates/aqd-solana-contracts/tests/test_arrays.rs @@ -0,0 +1,115 @@ +// SPDX-License-Identifier: Apache-2.0 + +use { + anyhow::Result, + aqd_solana_contracts::{construct_instruction_data, idl_from_json}, + std::ffi::OsStr, +}; + +/// Purpose: This test checks the instruction data for the "new" function of the "array" program. +/// +/// Note: The "array" program is a custom program that was created for this test. +/// The program's IDL is defined in tests/contracts/array.json. +/// The purpose of this program is to test fixed array type. +#[tokio::test] +pub async fn test_array_data() -> Result<()> { + // Define the program's IDL and the instruction we want to test. + let idl_json = "tests/contracts/array.json"; + let instruction_name = "new"; + let data: Vec = vec!["1,2,3,4".to_string()]; + + // Load the program's IDL and find the instruction we want to test. + let idl = idl_from_json(OsStr::new(idl_json))?; + let idl_instruction = + if let Some(instruction) = idl.instructions.iter().find(|i| i.name == instruction_name) { + instruction.clone() + } else { + return Err(anyhow::anyhow!( + "Instruction not found: {}", + instruction_name + )); + }; + let custom_types = idl.types.clone(); + + // Construct the instruction data. + let data = construct_instruction_data(&idl_instruction, &data, &custom_types)?; + + // Verify the instruction data is correct. + assert_eq!(data, vec![135, 44, 205, 198, 25, 1, 72, 188, 1, 2, 3, 4]); + + Ok(()) +} + +/// Purpose: This test checks the instruction data for the "new" function of the "vector" program. +/// +/// Note: The "VectorTest" program is a custom program that was created for this test. +/// The program's IDL is defined in tests/contracts/VectorTest.json. +/// The purpose of this program is to test fixed array type. +#[tokio::test] +pub async fn test_vector_data() -> Result<()> { + // Define the program's IDL and the instruction we want to test. + let idl_json = "tests/contracts/VectorTest.json"; + let instruction_name = "new"; + let data: Vec = vec!["1,2,3".to_string()]; + + // Load the program's IDL and find the instruction we want to test. + let idl = idl_from_json(OsStr::new(idl_json))?; + let idl_instruction = + if let Some(instruction) = idl.instructions.iter().find(|i| i.name == instruction_name) { + instruction.clone() + } else { + return Err(anyhow::anyhow!( + "Instruction not found: {}", + instruction_name + )); + }; + let custom_types = idl.types.clone(); + + // Construct the instruction data. + let data = construct_instruction_data(&idl_instruction, &data, &custom_types)?; + + // Verify the instruction data is correct. + assert_eq!( + data, + vec![135, 44, 205, 198, 25, 1, 72, 188, 3, 0, 0, 0, 1, 2, 3] + ); + + Ok(()) +} + +/// Purpose: This test checks the instruction data for the "new" function of the "byte_test" program. +/// +/// Note: The "byte_test" program is a custom program that was created for this test. +/// The program's IDL is defined in tests/contracts/byte_test.json. +/// The purpose of this program is to test bytes type. +#[tokio::test] +pub async fn test_bytes_data() -> Result<()> { + // Define the program's IDL and the instruction we want to test. + let idl_json = "tests/contracts/byte_test.json"; + let instruction_name = "new"; + let data: Vec = vec!["123456".to_string()]; + + // Load the program's IDL and find the instruction we want to test. + let idl = idl_from_json(OsStr::new(idl_json))?; + let idl_instruction = + if let Some(instruction) = idl.instructions.iter().find(|i| i.name == instruction_name) { + instruction.clone() + } else { + return Err(anyhow::anyhow!( + "Instruction not found: {}", + instruction_name + )); + }; + let custom_types = idl.types.clone(); + + // Construct the instruction data. + let data = construct_instruction_data(&idl_instruction, &data, &custom_types)?; + + // Verify the instruction data is correct. + assert_eq!( + data, + vec![135, 44, 205, 198, 25, 1, 72, 188, 3, 0, 0, 0, 18, 52, 86] + ); + + Ok(()) +} diff --git a/crates/aqd-solana-contracts/tests/test_defined_types.rs b/crates/aqd-solana-contracts/tests/test_defined_types.rs new file mode 100644 index 0000000..4f353ee --- /dev/null +++ b/crates/aqd-solana-contracts/tests/test_defined_types.rs @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: Apache-2.0 + +use { + anyhow::Result, + aqd_solana_contracts::{construct_instruction_data, idl_from_json}, + std::ffi::OsStr, +}; + +/// Purpose: This test checks the instruction data for the "new" function of the defined_types program. + +/// Note: The "DefinedTypes" program is a custom program that was created for this test. +/// The program's IDL is defined in tests/contracts/DefinedTypes.json. +/// The purpose of this program is to test struct and Enum types. +#[tokio::test] +pub async fn test_defined_types_new_data() -> Result<()> { + // Define the defined_types program's IDL and the instruction we want to test. + let idl_json = "tests/contracts/DefinedTypes.json"; + let instruction_name = "new"; + let person = r#" + { + "name": "Alice", + "age": 30, + "favoriteColor": "Red" + }"# + .to_string(); + let data = vec![person]; + + // Load the defined_types program's IDL and find the instruction we want to test. + let idl = idl_from_json(OsStr::new(idl_json))?; + let idl_instruction = + if let Some(instruction) = idl.instructions.iter().find(|i| i.name == instruction_name) { + instruction.clone() + } else { + return Err(anyhow::anyhow!( + "Instruction not found: {}", + instruction_name + )); + }; + let custom_types = idl.types.clone(); + + // Construct the instruction data. + let data = construct_instruction_data(&idl_instruction, &data, &custom_types)?; + + // Verify the instruction data is correct. + assert_eq!( + data, + vec![135, 44, 205, 198, 25, 1, 72, 188, 7, 0, 0, 0, 34, 65, 108, 105, 99, 101, 34, 30, 0] + ); + + Ok(()) +} diff --git a/crates/aqd-solana-contracts/tests/test_flipper.rs b/crates/aqd-solana-contracts/tests/test_flipper.rs new file mode 100644 index 0000000..0a9731f --- /dev/null +++ b/crates/aqd-solana-contracts/tests/test_flipper.rs @@ -0,0 +1,156 @@ +// SPDX-License-Identifier: Apache-2.0 + +use { + anyhow::Result, + aqd_solana_contracts::{ + construct_instruction_accounts, construct_instruction_data, idl_from_json, + }, + solana_sdk::pubkey::Pubkey, + std::ffi::OsStr, +}; + +/// Purpose: This test checks the instruction data for the "new" function of the flipper program. +#[tokio::test] +pub async fn test_flipper_new_data() -> Result<()> { + // Define the flipper program's IDL and the instruction we want to test. + let idl_json = "tests/contracts/flipper.json"; + let instruction_name = "new"; + let data = vec!["true".to_string()]; + + // Load the flipper program's IDL and find the instruction we want to test. + let idl = idl_from_json(OsStr::new(idl_json))?; + let idl_instruction = + if let Some(instruction) = idl.instructions.iter().find(|i| i.name == instruction_name) { + instruction.clone() + } else { + return Err(anyhow::anyhow!( + "Instruction not found: {}", + instruction_name + )); + }; + let custom_types = idl.types.clone(); + + // Construct the instruction data. + let data = construct_instruction_data(&idl_instruction, &data, &custom_types)?; + + // Verify the instruction data is correct. + assert_eq!(data, vec![135, 44, 205, 198, 25, 1, 72, 188, 1]); + + Ok(()) +} + +/// Purpose: This test checks the instruction data for the "get" function of the flipper program. +#[tokio::test] +pub async fn test_flipper_get_data() -> Result<()> { + // Define the flipper program's IDL and the instruction we want to test. + let idl_json = "tests/contracts/flipper.json"; + let instruction_name = "get"; + let data = vec![]; + + // Load the flipper program's IDL and find the instruction we want to test. + let idl = idl_from_json(OsStr::new(idl_json))?; + let idl_instruction = + if let Some(instruction) = idl.instructions.iter().find(|i| i.name == instruction_name) { + instruction.clone() + } else { + return Err(anyhow::anyhow!( + "Instruction not found: {}", + instruction_name + )); + }; + let custom_types = idl.types.clone(); + + // Construct the instruction data. + let data = construct_instruction_data(&idl_instruction, &data, &custom_types)?; + + // Verify the instruction data is correct. + assert_eq!(data, vec![161, 224, 50, 61, 5, 210, 122, 216]); + + Ok(()) +} + +/// Purpose: This test checks the instruction accounts for the "get" function of the flipper program. +#[tokio::test] +pub async fn test_flipper_get_accounts() -> Result<()> { + // Define the flipper program's IDL and the instruction we want to test. + let idl_json = "tests/contracts/flipper.json"; + let instruction_name = "get"; + + // Define the accounts. + // For "get", the only account is the data account. + let new_account = Pubkey::new_unique().to_string(); + let accounts = vec![new_account]; + + // Load the flipper program's IDL and find the instruction we want to test. + let idl = idl_from_json(OsStr::new(idl_json))?; + let idl_instruction = + if let Some(instruction) = idl.instructions.iter().find(|i| i.name == instruction_name) { + instruction.clone() + } else { + return Err(anyhow::anyhow!( + "Instruction not found: {}", + instruction_name + )); + }; + + // Construct the instruction accounts. + let (accounts, signers, new_accounts) = + construct_instruction_accounts(&idl_instruction, &accounts)?; + + // Verify the instruction accounts are correct. + + // Only one account is returned, the data account. + assert_eq!(accounts.len(), 1); + // No signers are returned. + assert_eq!(signers.len(), 0); + // No new accounts are created. + assert_eq!(new_accounts.len(), 0); + // The data account is not signable nor mutable. + assert!(!accounts[0].is_signer); + assert!(!accounts[0].is_writable); + + Ok(()) +} + +/// Purpose: This test checks the instruction accounts for the "flip" function of the flipper program. +#[tokio::test] +pub async fn test_flipper_flip_accounts() -> Result<()> { + // Define the flipper program's IDL and the instruction we want to test. + let idl_json = "tests/contracts/flipper.json"; + let instruction_name = "flip"; + + // Define the accounts. + // For "flip", the only account is the data account. + let new_account = Pubkey::new_unique().to_string(); + let accounts = vec![new_account]; + + // Load the flipper program's IDL and find the instruction we want to test. + let idl = idl_from_json(OsStr::new(idl_json))?; + let idl_instruction = + if let Some(instruction) = idl.instructions.iter().find(|i| i.name == instruction_name) { + instruction.clone() + } else { + return Err(anyhow::anyhow!( + "Instruction not found: {}", + instruction_name + )); + }; + + // Construct the instruction accounts. + let (accounts, signers, new_accounts) = + construct_instruction_accounts(&idl_instruction, &accounts)?; + + // Verify the instruction accounts are correct. + + // Only one account is returned, the data account. + assert_eq!(accounts.len(), 1); + // No signers are returned. + assert_eq!(signers.len(), 0); + // No new accounts are created. + assert_eq!(new_accounts.len(), 0); + // The data account is not signable but mutable. + assert!(!accounts[0].is_signer); + assert!(accounts[0].is_writable); + + Ok(()) +} diff --git a/crates/aqd-solana-contracts/tests/test_int.rs b/crates/aqd-solana-contracts/tests/test_int.rs new file mode 100644 index 0000000..ed06b70 --- /dev/null +++ b/crates/aqd-solana-contracts/tests/test_int.rs @@ -0,0 +1,117 @@ +// SPDX-License-Identifier: Apache-2.0 + +use { + anyhow::Result, + aqd_solana_contracts::{construct_instruction_data, idl_from_json}, + std::ffi::OsStr, +}; + +/// Purpose: This test checks the instruction data for the "new" function of the "unsigned_int" program. +/// +/// Note: The "unsigned_int" program is a custom program that was created for this test. +/// The program's IDL is defined in tests/contracts/unsigned_int.json. +/// The purpose of this program is to test unsigned integer types. +#[tokio::test] +pub async fn test_unsigned_int_data() -> Result<()> { + // Define the program's IDL and the instruction we want to test. + let idl_json = "tests/contracts/unsigned_int.json"; + let instruction_name = "new"; + let data: Vec = vec![ + // u8 + "12".to_string(), + // u16 + "1234".to_string(), + // u32 + "12345678".to_string(), + // u64 + "123456789012345".to_string(), + // u128 + "123456789012345678901234".to_string(), + // u256 + "1234567890123456789012345678901234567890".to_string(), + ]; + + // Load the program's IDL and find the instruction we want to test. + let idl = idl_from_json(OsStr::new(idl_json))?; + let idl_instruction = + if let Some(instruction) = idl.instructions.iter().find(|i| i.name == instruction_name) { + instruction.clone() + } else { + return Err(anyhow::anyhow!( + "Instruction not found: {}", + instruction_name + )); + }; + let custom_types = idl.types.clone(); + + // Construct the instruction data. + let data = construct_instruction_data(&idl_instruction, &data, &custom_types)?; + + // Verify the instruction data is correct. + assert_eq!( + data, + vec![ + 135, 44, 205, 198, 25, 1, 72, 188, 12, 210, 4, 78, 97, 188, 0, 121, 223, 13, 134, 72, + 112, 0, 0, 242, 175, 150, 108, 160, 16, 31, 155, 36, 26, 0, 0, 0, 0, 0, 0, 210, 10, 63, + 206, 150, 95, 188, 172, 184, 243, 219, 192, 117, 32, 201, 160, 3, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 + ] + ); + + Ok(()) +} + +/// Purpose: This test checks the instruction data for the "new" function of the "signed_int" program. +/// +/// Note: The "signed_int" program is a custom program that was created for this test. +/// The program's IDL is defined in tests/contracts/signed_int.json. +/// The purpose of this program is to test signed integer types. +#[tokio::test] +pub async fn test_signed_int_data() -> Result<()> { + // Define the program's IDL and the instruction we want to test. + let idl_json = "tests/contracts/signed_int.json"; + let instruction_name = "new"; + let data: Vec = vec![ + // i8 + "12".to_string(), + // i16 + "-1234".to_string(), + // i32 + "12345678".to_string(), + // i64 + "-123456789012345".to_string(), + // i128 + "123456789012345678901234".to_string(), + // i256 + "-1234567890123456789012345678901234567890".to_string(), + ]; + + // Load the program's IDL and find the instruction we want to test. + let idl = idl_from_json(OsStr::new(idl_json))?; + let idl_instruction = + if let Some(instruction) = idl.instructions.iter().find(|i| i.name == instruction_name) { + instruction.clone() + } else { + return Err(anyhow::anyhow!( + "Instruction not found: {}", + instruction_name + )); + }; + let custom_types = idl.types.clone(); + + // Construct the instruction data. + let data = construct_instruction_data(&idl_instruction, &data, &custom_types)?; + + // Verify the instruction data is correct. + assert_eq!( + data, + vec![ + 135, 44, 205, 198, 25, 1, 72, 188, 12, 46, 251, 78, 97, 188, 0, 135, 32, 242, 121, 183, + 143, 255, 255, 242, 175, 150, 108, 160, 16, 31, 155, 36, 26, 0, 0, 0, 0, 0, 0, 46, 245, + 192, 49, 105, 160, 67, 83, 71, 12, 36, 63, 138, 223, 54, 95, 252, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 + ] + ); + + Ok(()) +} diff --git a/crates/aqd-solana/Cargo.toml b/crates/aqd-solana/Cargo.toml new file mode 100644 index 0000000..7ff00b1 --- /dev/null +++ b/crates/aqd-solana/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "aqd-solana" +version = "0.1.0" +edition = "2021" + +[dependencies] +clap = { version = "4.4.6", features = ["derive"] } +anyhow = "1.0.75" +serde_json = "1.0.107" + +solana-cli-config = "1.17.2" +solana-clap-v3-utils = "1.17.2" + +aqd-solana-contracts = { path = "../aqd-solana-contracts" } +aqd-utils = { path = "../aqd-utils" } diff --git a/crates/aqd-solana/src/commands/call.rs b/crates/aqd-solana/src/commands/call.rs new file mode 100644 index 0000000..aec49c7 --- /dev/null +++ b/crates/aqd-solana/src/commands/call.rs @@ -0,0 +1,109 @@ +// SPDX-License-Identifier: Apache-2.0 + +use { + anyhow::Result, + solana_clap_v3_utils::input_validators::normalize_to_url_if_moniker, + solana_cli_config::{Config, CONFIG_FILE}, + std::process::exit, +}; +use { + aqd_solana_contracts::{print_transaction_information, SolanaTransaction}, + aqd_utils::check_target_match, +}; + +#[derive(Clone, Debug, clap::Args)] +#[clap(name = "call", about = "Send a custom transaction to a Solana program")] +pub struct SolanaCall { + #[clap(long, help = "Specifies the path of the IDL JSON file")] + idl: String, + #[clap(long, help = "Specifies the program ID of the deployed program")] + program: String, + #[clap(long, help = "Specifies the name of the instruction to call")] + instruction: String, + #[clap( + long, + help = "Specifies the data arguments to pass to the instruction. + For arrays and vectors, pass a comma-separated list of values. (e.g. 1,2,3,4) + For structs, pass a JSON string of the struct. (can be a path to a JSON file)", + // The number of data arguments is variable (Can be 0 or more) + num_args = 0.., + )] + data: Vec, + #[clap( + long, + help = "Specifies the accounts arguments to pass to the instruction\ + Keywords: + - new: create a new account + - self: reads the default keypair from the local configuration file. + - system: use the system program ID as the account", + // The number of accounts arguments is variable (Can be 0 or more) + num_args = 0.., + )] + accounts: Vec, + #[clap(long, help = "Specifies the payer keypair to use for the transaction")] + payer: Option, + #[clap(long, help = "Specifies whether to export the output in JSON format")] + output_json: bool, +} + +impl SolanaCall { + /// Handle the Solana transaction command. + /// + /// This function handles the processing of a Solana transaction command. It checks if the command + /// is being run in the correct directory, parses the command-line arguments, retrieves the RPC URL + /// and payer keypair from the configuration file, creates a [`SolanaTransaction`] object, submits + /// the transaction, and prints transaction information. + pub fn handle(&self) -> Result<()> { + // Make sure the command is run in the correct directory + // Fails if the command is run in a Solang Polkadot project directory + let target_match = check_target_match("solana", None) + .map_err(|e| anyhow::anyhow!("Failed to check current directory: {}", e))?; + if !target_match { + exit(1); + } + + // Parse command-line arguments + let idl_json = self.idl.clone(); + let program_id = self.program.clone(); + let instruction = self.instruction.clone(); + let data_args = self.data.clone(); + let accounts_args = self.accounts.clone(); + let payer = self.payer.clone(); + let output_json = self.output_json; + + // Get the RPC URL from the config file + // Parse the config file to get the RPC URL and payer keypair. + let config_file = CONFIG_FILE + .as_ref() + .ok_or_else(|| anyhow::anyhow!("Error loading config file"))?; + let cli_config = Config::load(config_file).unwrap_or_default(); + let rpc_url = normalize_to_url_if_moniker(&cli_config.json_rpc_url); + let keypair = cli_config.keypair_path.to_string(); + + let payer = payer.unwrap_or(keypair); + + // Create a `SolanaTransaction` object with the necessary parameters. + let transaction = SolanaTransaction::new() + .rpc_url(rpc_url.clone()) + .idl(idl_json.to_string()) + .program_id(program_id.to_string()) + .instruction(instruction.to_string()) + .call_data(data_args) + .accounts(accounts_args) + .payer(payer.clone()) + .done()?; + + // Submit the transaction. + let signature = transaction.submit_transaction()?; + + // Print the transaction information. + print_transaction_information( + transaction.rpc_client(), + &signature, + transaction.instruction(), + transaction.idl().types.as_slice(), + transaction.new_accounts(), + output_json, + ) + } +} diff --git a/crates/aqd-solana/src/commands/deploy.rs b/crates/aqd-solana/src/commands/deploy.rs new file mode 100644 index 0000000..73fcb89 --- /dev/null +++ b/crates/aqd-solana/src/commands/deploy.rs @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: Apache-2.0 + +use {anyhow::Result, serde_json::json, std::process::exit}; +use {aqd_solana_contracts::deploy_program, aqd_utils::check_target_match}; + +#[derive(Clone, Debug, clap::Args)] +#[clap(name = "deploy", about = "Deploy a program to Solana")] +pub struct SolanaDeploy { + #[clap(help = "Specifies the path to the program file to deploy (.so)")] + program_location: String, + #[clap(long, help = "Specifies whether to export the output in JSON format")] + output_json: bool, +} + +impl SolanaDeploy { + /// Handle the deployment of a Solana program + /// + /// This function is responsible for managing the deployment process, + /// including checking the current directory, parsing command-line arguments, + /// configuring settings, and executing the deployment command. It also handles + /// loading the necessary configuration and signers, defining output formats, + /// and processing the deployment command using the provided configuration. + pub fn handle(&self) -> Result<()> { + // Make sure the command is run in the correct directory + // Fails if the command is run in a Solang Polkadot project directory + let target_match = check_target_match("solana", None) + .map_err(|e| anyhow::anyhow!("Failed to check current directory: {}", e))?; + if !target_match { + exit(1); + } + + // Parse command-line arguments + let program_location = self.program_location.clone(); + let output_json = self.output_json; + + // Deploy the program + let program_id = deploy_program(program_location)?; + + // If the output is JSON, print the program ID in JSON format + // Else, print the program ID as a string + if output_json { + let program_id = json!({ "program_id": program_id }); + println!("{}", program_id); + } else { + println!("Program ID: {}", program_id); + } + + Ok(()) + } +} diff --git a/crates/aqd-solana/src/commands/mod.rs b/crates/aqd-solana/src/commands/mod.rs new file mode 100644 index 0000000..3e094f7 --- /dev/null +++ b/crates/aqd-solana/src/commands/mod.rs @@ -0,0 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 + +pub mod call; +pub mod deploy; +pub mod show; diff --git a/crates/aqd-solana/src/commands/show.rs b/crates/aqd-solana/src/commands/show.rs new file mode 100644 index 0000000..1436baa --- /dev/null +++ b/crates/aqd-solana/src/commands/show.rs @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: Apache-2.0 + +use {anyhow::Result, std::ffi::OsStr, std::process::exit}; +use { + aqd_solana_contracts::{idl_from_json, print_idl_instruction_info}, + aqd_utils::check_target_match, +}; + +#[derive(Clone, Debug, clap::Args)] +#[clap( + name = "show", + about = "Show information about a Solana program's instructions given an IDL JSON file" +)] +pub struct SolanaShow { + #[clap(long, help = "Specifies the path of the IDL JSON file")] + idl: String, + #[clap( + long, + help = "Specifies the name of the instruction to show information about\n + If not specified, information about all instructions is shown" + )] + instruction: Option, + #[clap(long, help = "Specifies whether to export the output in JSON format")] + output_json: bool, +} + +impl SolanaShow { + /// Handle the Solana show command. + /// + /// This function handles the processing of a Solana show command. It checks if the command + /// is being run in the correct directory, parses the command-line arguments, retrieves the IDL + /// from a JSON file, and prints information about the instruction. + pub fn handle(&self) -> Result<()> { + // Make sure the command is run in the correct directory + // Fails if the command is run in a Solang Polkadot project directory + let target_match = check_target_match("solana", None) + .map_err(|e| anyhow::anyhow!("Failed to check current directory: {}", e))?; + if !target_match { + exit(1); + } + + // Parse command-line arguments + let idl_json = self.idl.clone(); + let instruction = self.instruction.clone(); + let output_json = self.output_json; + + // Get the IDL from the JSON file + let idl = idl_from_json(OsStr::new(&idl_json))?; + + // Print information about the instruction + print_idl_instruction_info(&idl, instruction, output_json); + + Ok(()) + } +} diff --git a/crates/aqd-solana/src/lib.rs b/crates/aqd-solana/src/lib.rs new file mode 100644 index 0000000..b245acf --- /dev/null +++ b/crates/aqd-solana/src/lib.rs @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: Apache-2.0 + +mod commands; +mod solana_action; + +pub use commands::{call::SolanaCall, deploy::SolanaDeploy, show::SolanaShow}; +pub use solana_action::SolanaAction; diff --git a/crates/aqd-solana/src/solana_action.rs b/crates/aqd-solana/src/solana_action.rs new file mode 100644 index 0000000..b1b2823 --- /dev/null +++ b/crates/aqd-solana/src/solana_action.rs @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: Apache-2.0 + +use { + crate::{SolanaCall, SolanaDeploy, SolanaShow}, + clap::Subcommand, +}; + +/// Available subcommands for the `solana` subcommand. +#[derive(Debug, Subcommand)] +pub enum SolanaAction { + Deploy(SolanaDeploy), + Call(SolanaCall), + Show(SolanaShow), +} diff --git a/crates/aqd-utils/Cargo.toml b/crates/aqd-utils/Cargo.toml new file mode 100644 index 0000000..ca5f945 --- /dev/null +++ b/crates/aqd-utils/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "aqd-utils" +version = "0.1.0" +edition = "2021" + +[dependencies] +anyhow = "1.0.75" +toml = "0.8.2" diff --git a/crates/aqd-utils/solang_config_examples/polkadot_config.toml b/crates/aqd-utils/solang_config_examples/polkadot_config.toml new file mode 100644 index 0000000..52449bb --- /dev/null +++ b/crates/aqd-utils/solang_config_examples/polkadot_config.toml @@ -0,0 +1,63 @@ +[package] +authors = ["Your Name "] +version = "0.1.0" + +# Source files to be compiled. +input_files = ["flipper.sol"] + +# Contracts to be compiled. +# If no contracts are specified, solang will compile all non-virtual contracts. +contracts = ["flipper"] + +# Specify required import paths. +import_path = [] + +# Define any importmaps. +# import_map = { "@openzeppelin" = "/home/user/libraries/openzeppelin-contracts/" } +import_map = {} + + +[target] +name = "polkadot" +address_length = 32 +value_length = 16 + + +[debug-features] +# Log debug prints to the environment. +prints = true + +# Log runtime errors to the environment. +log-runtime-errors = true + +# Add debug info to the generated llvm IR. +generate-debug-info = false + +[optimizations] +dead-storage = true +constant-folding = true +strength-reduce = true +vector-to-slice = true +common-subexpression-elimination = true + + +# Valid wasm-opt passes are: Zero, One, Two, Three, Four, S, (focusing on code size) or Z (super-focusing on code size) +wasm-opt = "Z" + +# Valid LLVM optimization levels are: none, less, default, aggressive +llvm-IR-optimization-level = "aggressive" + +[compiler-output] +verbose = false + +# Emit compiler state at early stages. Valid options are: ast-dot, cfg, llvm-ir, llvm-bc, object, asm +# emit = "llvm-ir" + +# Output directory for binary artifacts. +# output_directory = "path/to/dir" + +# Output directory for the metadata. +# output_meta = "path/to/dir" + +# Output everything in a JSON format on STDOUT instead of writing output files. +std_json_output = false diff --git a/crates/aqd-utils/solang_config_examples/solana_config.toml b/crates/aqd-utils/solang_config_examples/solana_config.toml new file mode 100644 index 0000000..cef3b5f --- /dev/null +++ b/crates/aqd-utils/solang_config_examples/solana_config.toml @@ -0,0 +1,55 @@ +[package] +version = "0.1.0" + +# Source files to be compiled. +input_files = ["flipper.sol"] + +# Contracts to be compiled. +# If no contracts are specified, solang will compile all non-virtual contracts. +contracts = ["flipper"] + +# Specify required import paths. +import_path = [] + +# Define any importmaps. +# import_map = { "@openzeppelin" = "/home/user/libraries/openzeppelin-contracts/" } +import_map = {} + + +[target] +name = "solana" + +[debug-features] +# Log debug prints to the environment. +prints = true + +# Log runtime errors to the environment. +log-runtime-errors = true + +# Add debug info to the generated llvm IR. +generate-debug-info = false + +[optimizations] +dead-storage = true +constant-folding = true +strength-reduce = true +vector-to-slice = true +common-subexpression-elimination = true + +# Valid LLVM optimization levels are: none, less, default, aggressive +llvm-IR-optimization-level = "aggressive" + +[compiler-output] +verbose = false + +# Emit compiler state at early stages. Valid options are: ast-dot, cfg, llvm-ir, llvm-bc, object, asm +# emit = "llvm-ir" + +# Output directory for binary artifacts. +# output_directory = "path/to/dir" + +# Output directory for the metadata. +# output_meta = "path/to/dir" + +# Output everything in a JSON format on STDOUT instead of writing output files. +std_json_output = false diff --git a/crates/aqd-utils/src/lib.rs b/crates/aqd-utils/src/lib.rs new file mode 100644 index 0000000..51c2489 --- /dev/null +++ b/crates/aqd-utils/src/lib.rs @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: Apache-2.0 + +pub mod printing_macros; +mod utils; + +pub use utils::{check_target_match, prompt_confirm_transaction}; diff --git a/crates/aqd-utils/src/printing_macros.rs b/crates/aqd-utils/src/printing_macros.rs new file mode 100644 index 0000000..b837a2d --- /dev/null +++ b/crates/aqd-utils/src/printing_macros.rs @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: Apache-2.0 + +/// macro to print a title (cyan and bold) +#[macro_export] +macro_rules! print_title { + ($title:expr) => { + println!("{}", format!("\n{}", $title.bold().cyan(),)); + }; +} + +/// macro to print a subtitle (cyan and bold) indented with 2 spaces +#[macro_export] +macro_rules! print_subtitle { + ($title:expr) => { + println!("{}", format!("\n {}", $title.bold().cyan(),)); + }; +} + +/// macro to print a key and value (green and bold) indented with 4 spaces +#[macro_export] +macro_rules! print_key_value { + ($key:expr, $value:expr) => { + println!(" {}: {}", format!("{:<15}", $key.bold().green()), $value); + }; +} + +/// macro to print a value (indented with 4 spaces) +#[macro_export] +macro_rules! print_value { + ($val:expr) => { + println!(" {}", $val); + }; +} + +/// macro to print a warning (yellow and bold) +#[macro_export] +macro_rules! print_warning { + ($warning:expr) => { + println!( + "{}", + format!("\n{} {}", "Warning:".bold().yellow(), $warning.yellow()) + ); + }; +} diff --git a/crates/aqd-utils/src/utils.rs b/crates/aqd-utils/src/utils.rs new file mode 100644 index 0000000..35927ab --- /dev/null +++ b/crates/aqd-utils/src/utils.rs @@ -0,0 +1,114 @@ +// SPDX-License-Identifier: Apache-2.0 + +use { + anyhow::{anyhow, Result}, + std::{ + fs::File, + io, + io::{Read, Write}, + path::PathBuf, + }, +}; + +/// Prompt the user to confirm transaction. +pub fn prompt_confirm_transaction(summary: F) -> Result<()> { + summary(); + println!("Are you sure you want to submit this transaction? (Y/n): "); + + let mut choice = String::new(); + io::stdout().flush()?; + io::stdin().read_line(&mut choice)?; + match choice.trim().to_lowercase().as_str() { + "y" | "" => Ok(()), + "n" => Err(anyhow!("Transaction not submitted")), + _ => Err(anyhow!("Invalid choice")), + } +} + +/// A helper function to check if the target name provided by the user matches the target name in solang.toml +/// +/// If no configuration file content is provided, then the function will read the content of the +/// solang.toml file in the current directory. +/// +/// If the target names match, then the function will return true. else, it will return false. +/// +/// Returns an error if the solang.toml file does not exist, or if the file cannot be read or parsed. +pub fn check_target_match(target_name: &str, config_file_content: Option) -> Result { + // Get the content of the configuration file + // If the content is provided as an argument, then use it + // Otherwise, read the content from the solang.toml file in the current directory + let content = if let Some(content) = config_file_content { + content + } else { + // Get the manifest path from the current directory + let manifest_path = PathBuf::from("solang.toml"); + + // Check if the manifest file exists + // If it doesn't, then we don't need to check the target name + if !manifest_path.exists() { + return Ok(true); + } + + // Read the content of the solang.toml file + let mut file = File::open(&manifest_path).map_err(|err| { + anyhow!( + "Failed to open solang.toml file in the current directory: {}", + err + ) + })?; + let mut content = String::new(); + file.read_to_string(&mut content).map_err(|err| { + anyhow!( + "Failed to read solang.toml file in the current directory: {}", + err + ) + })?; + + content + }; + + // Parse the TOML content and extract the target name + let parsed_toml: toml::Value = toml::from_str(&content).map_err(|err| { + anyhow::anyhow!( + "Failed to parse solang.toml file in the current directory: {}", + err + ) + })?; + let config_target = parsed_toml["target"]["name"] + .as_str() + .ok_or_else(|| anyhow::anyhow!("Failed to get target name from solang.toml"))? + .to_string(); + + // Compare the target name with the provided argument + if config_target != target_name { + eprintln!( + "Error: The specified target '{}' does not match the target '{}' in solang.toml", + target_name, config_target + ); + return Ok(false); + } + + Ok(true) +} + +/// A test for the `check_target_match` function +#[test] +fn test_check_target_match() { + // Test that the function returns true if the target names match + let target_name = "solana"; + // Load the content of the solang.toml file from the Solana examples directory + let config_file_content = + include_str!("../solang_config_examples/solana_config.toml").to_string(); + let result = check_target_match(target_name, Some(config_file_content)); + assert!(result.is_ok(), "Error: {:?}", result); + assert!(result.unwrap()); + + // Test that the function returns false if the target names do not match + let target_name = "solana"; + // Load the content of the solang.toml file from the Polkadot examples directory + let config_file_content = + include_str!("../solang_config_examples/polkadot_config.toml").to_string(); + let result = check_target_match(target_name, Some(config_file_content)); + assert!(result.is_ok(), "Error: {:?}", result); + assert!(!result.unwrap()); +} diff --git a/integration/polkadot/flipper.contract b/integration/polkadot/flipper.contract new file mode 100644 index 0000000..767392d --- /dev/null +++ b/integration/polkadot/flipper.contract @@ -0,0 +1 @@ +{"source":{"hash":"0xe62b681614e6b7dbe892796b43e8d09eaf687d768d71bbb91d385b9a89277258","language":"ink! 5.0.0-alpha","compiler":"rustc 1.73.0","wasm":"0x0061736d0100000001240760027f7f0060000060047f7f7f7f017f60037f7f7f006000017f60017f017f60017f00027406057365616c310b6765745f73746f726167650002057365616c301176616c75655f7472616e736665727265640000057365616c3005696e7075740000057365616c320b7365745f73746f726167650002057365616c300b7365616c5f72657475726e000303656e76066d656d6f727902010210030b0a000304050001060001010608017f01418080040b0711020463616c6c000d066465706c6f79000e0a99090a2601017f230041106b22022400200220003a000f20012002410f6a41011006200241106a24000b6f01037f024002402000280208220320026a22042003490d00200420002802044b0d00200420036b2002470d01200028020020036a210541002103037f2002200346047f200505200320056a200120036a2d00003a0000200341016a21030c010b0b1a200020043602080f0b000b000b4d02017f027e230041206b2200240020004200370308200042003703002000411036021c20002000411c6a10012000290308210120002903002102200041206a2400410541042001200284501b0b3f01017f2000280204220145044041020f0b2000200141016b36020420002000280200220041016a3602004101410220002d000022004101461b410020001b0b3c01027f027f200145044041808004210141010c010b410121024180800441013a000041818004210141020b2103200120023a000020002003100c000b12004180800441003b010041004102100c000b950101057f230041106b2201240020014280800137020820014180800436020420014100360200200141046a2204200141041006024020012802082205200128020c2202490d00200128020421032001410036020c2001200520026b3602082001200220036a360204200020041005200128020c220020012802084b0d00200320022001280204200010031a200141106a24000f0b000b0d0020004180800420011004000b970301067f230041106b22002400024002400240100741ff01714105470d00200041808001360200418080042000100220002802002201418180014f0d0020014104490d02418380042d00002101418280042d00002102418180042d000021030240418080042d00002204412f470440200441e300472003413a4772200241a50147720d0441012105200141d100460d010c040b200341860147200241db004772200141d90147720d030b2000428080013702042000418080043602002000410036020c20002000410c6a410410062000280204220320002802082201490d00200028020021022000200320016b220336020020022001200120026a22012000100020032000280200220249720d00200020023602042000200136020020001008220141ff01714102460d0020050d01230041106b220024002000418080043602044180800441003a00002000428080818010370208200141ff0171410047200041046a1005200028020c2200418180014f0440000b41002000100c000b000b200141ff017145100b410041001009000b410141011009000be30101057f230041106b2200240002400240100741ff01714105470d0020004180800136020c418080042000410c6a1002200028020c2201418180014f0d00024020014104490d002000418480043602042000200141046b360208418380042d00002101418280042d00002102418180042d00002103418080042d0000220441ed014704402004419b0147200341ae0147722002419d0147200141de004772720d01200041046a1008220041ff01714102460d012000100b100a000b200341cb00472002419d0147720d002001411b460d020b410141011009000b000b4100100b100a000b","build_info":{"build_mode":"Release","cargo_contract_version":"4.0.0-alpha","rust_toolchain":"stable-aarch64-apple-darwin","wasm_opt_settings":{"keep_debug_symbols":false,"optimization_passes":"Z"}}},"contract":{"name":"flipper","version":"0.1.0","authors":["[your_name] <[your_email]>"]},"image":null,"spec":{"constructors":[{"args":[{"label":"init_value","type":{"displayName":["bool"],"type":0}}],"default":false,"docs":["Constructor that initializes the `bool` value to the given `init_value`."],"label":"new","payable":false,"returnType":{"displayName":["ink_primitives","ConstructorResult"],"type":2},"selector":"0x9bae9d5e"},{"args":[],"default":false,"docs":["Constructor that initializes the `bool` value to `false`.","","Constructors can delegate to other constructors."],"label":"default","payable":false,"returnType":{"displayName":["ink_primitives","ConstructorResult"],"type":2},"selector":"0xed4b9d1b"}],"docs":[],"environment":{"accountId":{"displayName":["AccountId"],"type":6},"balance":{"displayName":["Balance"],"type":9},"blockNumber":{"displayName":["BlockNumber"],"type":12},"chainExtension":{"displayName":["ChainExtension"],"type":13},"hash":{"displayName":["Hash"],"type":10},"maxEventTopics":4,"staticBufferSize":16384,"timestamp":{"displayName":["Timestamp"],"type":11}},"events":[],"lang_error":{"displayName":["ink","LangError"],"type":4},"messages":[{"args":[],"default":false,"docs":[" A message that can be called on instantiated contracts."," This one flips the value of the stored `bool` from `true`"," to `false` and vice versa."],"label":"flip","mutates":true,"payable":false,"returnType":{"displayName":["ink","MessageResult"],"type":2},"selector":"0x633aa551"},{"args":[],"default":false,"docs":[" Simply returns the current value of our `bool`."],"label":"get","mutates":false,"payable":false,"returnType":{"displayName":["ink","MessageResult"],"type":5},"selector":"0x2f865bd9"}]},"storage":{"root":{"layout":{"struct":{"fields":[{"layout":{"leaf":{"key":"0x00000000","ty":0}},"name":"value"}],"name":"Flipper"}},"root_key":"0x00000000","ty":1}},"types":[{"id":0,"type":{"def":{"primitive":"bool"}}},{"id":1,"type":{"def":{"composite":{"fields":[{"name":"value","type":0,"typeName":",>>::Type"}]}},"path":["flipper","flipper","Flipper"]}},{"id":2,"type":{"def":{"variant":{"variants":[{"fields":[{"type":3}],"index":0,"name":"Ok"},{"fields":[{"type":4}],"index":1,"name":"Err"}]}},"params":[{"name":"T","type":3},{"name":"E","type":4}],"path":["Result"]}},{"id":3,"type":{"def":{"tuple":[]}}},{"id":4,"type":{"def":{"variant":{"variants":[{"index":1,"name":"CouldNotReadInput"}]}},"path":["ink_primitives","LangError"]}},{"id":5,"type":{"def":{"variant":{"variants":[{"fields":[{"type":0}],"index":0,"name":"Ok"},{"fields":[{"type":4}],"index":1,"name":"Err"}]}},"params":[{"name":"T","type":0},{"name":"E","type":4}],"path":["Result"]}},{"id":6,"type":{"def":{"composite":{"fields":[{"type":7,"typeName":"[u8; 32]"}]}},"path":["ink_primitives","types","AccountId"]}},{"id":7,"type":{"def":{"array":{"len":32,"type":8}}}},{"id":8,"type":{"def":{"primitive":"u8"}}},{"id":9,"type":{"def":{"primitive":"u128"}}},{"id":10,"type":{"def":{"composite":{"fields":[{"type":7,"typeName":"[u8; 32]"}]}},"path":["ink_primitives","types","Hash"]}},{"id":11,"type":{"def":{"primitive":"u64"}}},{"id":12,"type":{"def":{"primitive":"u32"}}},{"id":13,"type":{"def":{"variant":{}},"path":["ink_env","types","NoChainExtension"]}}],"version":"4"} \ No newline at end of file diff --git a/integration/polkadot/flipper.wasm b/integration/polkadot/flipper.wasm new file mode 100644 index 0000000..c4c5ebf Binary files /dev/null and b/integration/polkadot/flipper.wasm differ diff --git a/integration/polkadot/incrementer.contract b/integration/polkadot/incrementer.contract new file mode 100644 index 0000000..fbfd19b --- /dev/null +++ b/integration/polkadot/incrementer.contract @@ -0,0 +1 @@ +{"source":{"hash":"0x0cac9f6c156ce7cbc0bbd7ba4f1369aff039eee6d7e55a60855b63962780133d","language":"ink! 5.0.0-alpha","compiler":"rustc 1.73.0","wasm":"0x0061736d01000000011f0660027f7f0060000060047f7f7f7f017f60037f7f7f006000017f60017f00027406057365616c310b6765745f73746f726167650002057365616c301176616c75655f7472616e736665727265640000057365616c3005696e7075740000057365616c320b7365745f73746f726167650002057365616c300b7365616c5f72657475726e000303656e76066d656d6f72790201021003090804010005000001010608017f01418080040b0711020463616c6c000b066465706c6f79000c0ae807084d02017f027e230041206b2200240020004200370308200042003703002000411036021c20002000411c6a10012000290308210120002903002102200041206a2400410541042001200284501b0b12004180800441003b010041004102100a000b3c01027f027f200145044041808004210141010c010b410121024180800441013a000041818004210141020b2103200120023a000020002003100a000b8c0101057f230041106b22012400200142808001370208200141808004360204200141046a220441001009024020012802082205200128020c2202490d00200128020421032001410036020c2001200520026b3602082001200220036a360204200420001009200128020c220020012802084b0d00200320022001280204200010031a200141106a24000f0b000b4a01037f024002402000280208220241046a22032002490d00200320002802044b0d00200320026b4104470d012000280200210420002003360208200220046a20013600000f0b000b000b0d0020004180800420011004000b920301077f230041106b2200240002400240100541ff01714105470d0020004180800136020441808004200041046a100220002802042201418180014f0d00024020014104490d00418380042d00002102418280042d00002104418180042d000021050240418080042d00002203412f4704402001417c714104462003411d47722005413247200441ff017141e1004772722002419f0147720d02418480042802002104410121060c010b200541860147200441ff017141db004772200241d90147720d010b200042808001370208200041808004360204200041046a22054100100920002802082203200028020c2201490d01200028020421022000200320016b220336020420022001200120026a22012005100020032000280204220049722000410449720d012001280000210120060d02230041106b220024002000418080043602044180800441003a00002000428080818010370208200041046a20011009200028020c2200418180014f0440000b41002000100a000b410141011007000b000b200120046a1008410041001007000bcc0101057f230041106b2200240002400240100541ff01714105470d0020004180800136020c418080042000410c6a1002200028020c2200418180014f0d00024020004104490d00418380042d00002101418280042d00002102418180042d00002103418080042d0000220441e1004704402000417c714104462004419b014772200341ae01472002419d01477272200141de0047720d014184800428020010081006000b200341ef0147200241fe0047720d002001413e460d020b410141011007000b000b410010081006000b","build_info":{"build_mode":"Release","cargo_contract_version":"4.0.0-alpha","rust_toolchain":"stable-aarch64-apple-darwin","wasm_opt_settings":{"keep_debug_symbols":false,"optimization_passes":"Z"}}},"contract":{"name":"incrementer","version":"0.1.0","authors":["[your_name] <[your_email]>"]},"image":null,"spec":{"constructors":[{"args":[{"label":"init_value","type":{"displayName":["i32"],"type":0}}],"default":false,"docs":[],"label":"new","payable":false,"returnType":{"displayName":["ink_primitives","ConstructorResult"],"type":2},"selector":"0x9bae9d5e"},{"args":[],"default":false,"docs":[],"label":"new_default","payable":false,"returnType":{"displayName":["ink_primitives","ConstructorResult"],"type":2},"selector":"0x61ef7e3e"}],"docs":[],"environment":{"accountId":{"displayName":["AccountId"],"type":6},"balance":{"displayName":["Balance"],"type":9},"blockNumber":{"displayName":["BlockNumber"],"type":12},"chainExtension":{"displayName":["ChainExtension"],"type":13},"hash":{"displayName":["Hash"],"type":10},"maxEventTopics":4,"staticBufferSize":16384,"timestamp":{"displayName":["Timestamp"],"type":11}},"events":[],"lang_error":{"displayName":["ink","LangError"],"type":4},"messages":[{"args":[{"label":"by","type":{"displayName":["i32"],"type":0}}],"default":false,"docs":[],"label":"inc","mutates":true,"payable":false,"returnType":{"displayName":["ink","MessageResult"],"type":2},"selector":"0x1d32619f"},{"args":[],"default":false,"docs":[],"label":"get","mutates":false,"payable":false,"returnType":{"displayName":["ink","MessageResult"],"type":5},"selector":"0x2f865bd9"}]},"storage":{"root":{"layout":{"struct":{"fields":[{"layout":{"leaf":{"key":"0x00000000","ty":0}},"name":"value"}],"name":"Incrementer"}},"root_key":"0x00000000","ty":1}},"types":[{"id":0,"type":{"def":{"primitive":"i32"}}},{"id":1,"type":{"def":{"composite":{"fields":[{"name":"value","type":0,"typeName":",>>::Type"}]}},"path":["incrementer","incrementer","Incrementer"]}},{"id":2,"type":{"def":{"variant":{"variants":[{"fields":[{"type":3}],"index":0,"name":"Ok"},{"fields":[{"type":4}],"index":1,"name":"Err"}]}},"params":[{"name":"T","type":3},{"name":"E","type":4}],"path":["Result"]}},{"id":3,"type":{"def":{"tuple":[]}}},{"id":4,"type":{"def":{"variant":{"variants":[{"index":1,"name":"CouldNotReadInput"}]}},"path":["ink_primitives","LangError"]}},{"id":5,"type":{"def":{"variant":{"variants":[{"fields":[{"type":0}],"index":0,"name":"Ok"},{"fields":[{"type":4}],"index":1,"name":"Err"}]}},"params":[{"name":"T","type":0},{"name":"E","type":4}],"path":["Result"]}},{"id":6,"type":{"def":{"composite":{"fields":[{"type":7,"typeName":"[u8; 32]"}]}},"path":["ink_primitives","types","AccountId"]}},{"id":7,"type":{"def":{"array":{"len":32,"type":8}}}},{"id":8,"type":{"def":{"primitive":"u8"}}},{"id":9,"type":{"def":{"primitive":"u128"}}},{"id":10,"type":{"def":{"composite":{"fields":[{"type":7,"typeName":"[u8; 32]"}]}},"path":["ink_primitives","types","Hash"]}},{"id":11,"type":{"def":{"primitive":"u64"}}},{"id":12,"type":{"def":{"primitive":"u32"}}},{"id":13,"type":{"def":{"variant":{}},"path":["ink_env","types","NoChainExtension"]}}],"version":"4"} \ No newline at end of file diff --git a/integration/polkadot/incrementer.wasm b/integration/polkadot/incrementer.wasm new file mode 100644 index 0000000..e6706aa Binary files /dev/null and b/integration/polkadot/incrementer.wasm differ diff --git a/integration/polkadot/polkadot_cli.sh b/integration/polkadot/polkadot_cli.sh new file mode 100755 index 0000000..60ec112 --- /dev/null +++ b/integration/polkadot/polkadot_cli.sh @@ -0,0 +1,79 @@ +#!/bin/bash +set -e + +# Add Aqd to PATH (assumes aqd is built) +# pwd is integration/polkadot, so ../../target/release +export PATH="$PATH:$(pwd)/../../target/release" + + +# Test case 1: +# 1. Upload "flipper" contract +# 2. Instantiate contract +# 3. Call get contract (should return true) +# 4. Call flip contract +# 5. Call get contract (should return false) + +# Upload the contract to a substrate node +upload_result=$(aqd polkadot upload --suri //Alice -x flipper.contract --output-json) + +# Instantiate the contract +instantiate_result=$(aqd polkadot instantiate --suri //Alice --args true -x flipper.contract --output-json --skip-confirm) + +# Extract the contract address from the instantiate result +contract_address=$(echo "$instantiate_result" | jq -r '.contract') + +# Call the contract +call_result=$(aqd polkadot call --contract "$contract_address" --message get --suri //Alice flipper.contract --output-json --skip-confirm) + +# Extract the "value" field from the "data" object +value=$(echo "$call_result" | jq -r '.data.Tuple.values[0].Bool') + +# Step 5: Assert that "value" is true +if [ "$value" == "true" ]; then + echo "Contract call succeeded." +else + echo "Contract call reverted." + exit 1 +fi + +# Call the flip function on the contract +call_flip_result=$(aqd polkadot call --contract "$contract_address" --message flip --suri //Alice -x flipper.contract --output-json --skip-confirm) + +# Check that "value" is now false +call_result=$(aqd polkadot call --contract "$contract_address" --message get --suri //Alice flipper.contract --output-json --skip-confirm) + +# Extract the "value" field from the "data" object +value=$(echo "$call_result" | jq -r '.data.Tuple.values[0].Bool') + +# Assert that "value" is false +if [ "$value" == "false" ]; then + echo "Contract call flipped as expected." +else + echo "Contract call did not flip the value." + exit 1 +fi + + +# Test case 2: +# 1. Upload "incrementer" contract +# 2. Remove contract using the code hash + +# Upload the contract to a substrate node +upload_result=$(aqd polkadot upload --suri //Alice -x incrementer.contract --output-json) + +# Extract the "code_hash" value directly from the JSON object +code_hash=$(echo "$upload_result" | jq -r '.code_hash') + +# Remove the contract using the code hash +remove_result=$(aqd polkadot remove --suri //Alice --output-json --code-hash "$code_hash" incrementer.contract) + +# Get "removed_code_hash" value from the JSON object +removed_code_hash=$(echo "$remove_result" | jq -r '.removed_code_hash') + +# In case of success, the removed_code_hash should be equal to the code_hash +if [ "$removed_code_hash" == "$code_hash" ]; then + echo "Contract removed successfully." +else + echo "Contract removal failed." + exit 1 +fi diff --git a/integration/solana/flipper.json b/integration/solana/flipper.json new file mode 100644 index 0000000..c84aaf4 --- /dev/null +++ b/integration/solana/flipper.json @@ -0,0 +1,69 @@ +{ + "version": "0.0.1", + "name": "flipper", + "instructions": [ + { + "name": "new", + "docs": [ + "notice: Constructor that initializes the `bool` value to the given `init_value`." + ], + "accounts": [ + { + "name": "dataAccount", + "isMut": true, + "isSigner": true, + "isOptional": false + }, + { + "name": "payer", + "isMut": true, + "isSigner": true, + "isOptional": false + }, + { + "name": "systemProgram", + "isMut": false, + "isSigner": false, + "isOptional": false + } + ], + "args": [ + { + "name": "initvalue", + "type": "bool" + } + ] + }, + { + "name": "flip", + "docs": [ + "notice: A message that can be called on instantiated contracts.\nThis one flips the value of the stored `bool` from `true`\nto `false` and vice versa." + ], + "accounts": [ + { + "name": "dataAccount", + "isMut": true, + "isSigner": false, + "isOptional": false + } + ], + "args": [] + }, + { + "name": "get", + "docs": [ + "notice: Simply returns the current value of our `bool`." + ], + "accounts": [ + { + "name": "dataAccount", + "isMut": false, + "isSigner": false, + "isOptional": false + } + ], + "args": [], + "returns": "bool" + } + ] +} \ No newline at end of file diff --git a/integration/solana/flipper.so b/integration/solana/flipper.so new file mode 100644 index 0000000..8284d51 Binary files /dev/null and b/integration/solana/flipper.so differ diff --git a/integration/solana/setup_solana.sh b/integration/solana/setup_solana.sh new file mode 100755 index 0000000..da4996d --- /dev/null +++ b/integration/solana/setup_solana.sh @@ -0,0 +1,25 @@ +#!/bin/bash +set -e + +# Install Solana +sh -c "$(curl -sSfL https://release.solana.com/v1.17.1/install)" + +# Add Solana CLI to PATH +export PATH="$PATH:$HOME/.local/share/solana/install/active_release/bin" + +# Ensure nohup writes output to a file, not the terminal. +# If we don't, solana-test-validator might not be able to write its +# output and exit +nohup solana-test-validator -q > validator.out & + +# Wait for the validator to start up +sleep 10 + +# Generate a new keypair +solana-keygen new --no-bip39-passphrase + +# Set Solana URL to localhost +solana config set --url localhost + +# Air drop 50 SOL (required to send transactions) +solana airdrop 50 diff --git a/integration/solana/solana_cli.sh b/integration/solana/solana_cli.sh new file mode 100755 index 0000000..42d2ae4 --- /dev/null +++ b/integration/solana/solana_cli.sh @@ -0,0 +1,63 @@ +#!/bin/bash +set -e + +# Add Aqd to PATH (assumes aqd is built) +# pwd is integration/solana, so ../../target/release +export PATH="$PATH:$(pwd)/../../target/release" + +# Deploy the program (assumes a localnet cluster is running) +deploy_result=$(aqd solana deploy --output-json flipper.so) + +# Extract the program id from the deploy result +program_id=$(echo $deploy_result | jq -r .program_id) + +# Assert the program is deployed successfully +# (the program id is not null) +if [ "$program_id" == "null" ]; then + echo "Error: Solana program deployment failed" + exit 1 +fi + +# Wait for the program to be available +sleep 3 + +# Call the "new" instruction on the flipper program +flipper_new=$(aqd solana call --output-json --idl flipper.json --program "$program_id" --instruction new --data true --accounts new self system) + +# Extract the newly created data account pubkey from the call result +data_account_pubkey=$(echo $flipper_new | jq -r '.new_accounts[0].pubkey') + +# Assert the data account pubkey is not null +if [ "$data_account_pubkey" == "null" ]; then + echo "Error: Solana program call failed" + exit 1 +fi + +# Call the "get" instruction on the flipper program +flipper_get=$(aqd solana call --output-json --idl flipper.json --program "$program_id" --instruction get --accounts "$data_account_pubkey") + +# Extract the decoded return value from the call result +decoded_return_value=$(echo $flipper_get | jq -r .decoded_return_data) + +# Assert that the decoded return value is "true" +if [ "$decoded_return_value" != "true" ]; then + echo "Error: Solana program call failed" + exit 1 +fi + +# Call the "flip" instruction on the flipper program +flipper_flip=$(aqd solana call --output-json --idl flipper.json --program "$program_id" --instruction flip --accounts "$data_account_pubkey") + +# Call the "get" instruction on the flipper program +flipper_get=$(aqd solana call --output-json --idl flipper.json --program "$program_id" --instruction get --accounts "$data_account_pubkey") + +# Extract the decoded return value from the call result +decoded_return_value=$(echo $flipper_get | jq -r .decoded_return_data) + +# Assert that the decoded return value is "false" +if [ "$decoded_return_value" != "false" ]; then + echo "Error: Solana program call failed" + exit 1 +fi + +exit 0