From ee01a0132841e0125329e51521adb042b5c31786 Mon Sep 17 00:00:00 2001 From: Richard Janis Goldschmidt Date: Thu, 7 Nov 2024 15:41:54 +0100 Subject: [PATCH] refactor(cli): separate address command to tool --- .github/workflows/test.yml | 34 +- Cargo.toml | 6 +- crates/astria-cli/CHANGELOG.md | 4 + crates/astria-cli/src/sequencer/address.rs | 55 --- crates/astria-cli/src/sequencer/mod.rs | 4 - tools/astria-address/CHANGELOG.md | 14 + tools/astria-address/Cargo.lock | 478 +++++++++++++++++++++ tools/astria-address/Cargo.toml | 15 + tools/astria-address/README.md | 33 ++ tools/astria-address/src/main.rs | 97 +++++ tools/astria-address/tests/make_address.rs | 52 +++ 11 files changed, 731 insertions(+), 61 deletions(-) delete mode 100644 crates/astria-cli/src/sequencer/address.rs create mode 100644 tools/astria-address/CHANGELOG.md create mode 100644 tools/astria-address/Cargo.lock create mode 100644 tools/astria-address/Cargo.toml create mode 100644 tools/astria-address/README.md create mode 100644 tools/astria-address/src/main.rs create mode 100644 tools/astria-address/tests/make_address.rs diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 0ebe04560b..3f95eb6ca0 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -188,6 +188,38 @@ jobs: run: | cargo nextest run --package astria-bridge-withdrawer -- --include-ignored + # Specifically for tools other than the protobuf and solidity compilers which + # are run as part of other steps. (only `tools/astria-address` for now). + rust-tools: + runs-on: buildjet-8vcpu-ubuntu-2204 + needs: run_checker + if: needs.run_checker.outputs.run_tests == 'true' + steps: + - uses: actions/checkout@v4 + with: + submodules: 'true' + - uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ env.RUSTUP_TOOLCHAIN }} + - uses: Swatinem/rust-cache@v2.7.3 + with: + cache-provider: "buildjet" + - name: Install nextest + uses: taiki-e/install-action@nextest + - name: Build tests + run: | + cargo nextest archive \ + --manifest-path tools/astria-address/Cargo.toml \ + --archive-file=archive.tar.zst \ + --release \ + --all-features \ + --all-targets \ + - name: Run tests + timeout-minutes: 20 + run: | + cargo nextest run --archive-file=archive.tar.zst + + doctest: runs-on: buildjet-8vcpu-ubuntu-2204 needs: run_checker @@ -280,7 +312,7 @@ jobs: test: if: ${{ always() && !cancelled() }} - needs: [compiles, protos-compiled, solidity-contracts-compiled, rust, doctest, clippy, lockfile, custom-lints] + needs: [compiles, protos-compiled, solidity-contracts-compiled, rust, rust-tools, doctest, clippy, lockfile, custom-lints] uses: ./.github/workflows/reusable-success.yml with: success: ${{ !contains(needs.*.result, 'failure') }} diff --git a/Cargo.toml b/Cargo.toml index ed6788f68e..585f0c6b49 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,9 @@ [workspace] -exclude = ["tools/protobuf-compiler", "tools/solidity-compiler"] +exclude = [ + "tools/protobuf-compiler", + "tools/solidity-compiler", + "tools/astria-address", +] members = [ "crates/astria-bridge-contracts", diff --git a/crates/astria-cli/CHANGELOG.md b/crates/astria-cli/CHANGELOG.md index 09bc9674b2..94c45ef2de 100644 --- a/crates/astria-cli/CHANGELOG.md +++ b/crates/astria-cli/CHANGELOG.md @@ -14,6 +14,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed ICS20 withdrawal source when using channel with more than one port/channel combo. [#1768](https://github.com/astriaorg/astria/pull/1768) +### Removed + +- Removed `sequeuncer address` subcommand [#1803](https://github.com/astriaorg/astria/pull/1803) + ## [0.5.1] - 2024-10-23 ### Added diff --git a/crates/astria-cli/src/sequencer/address.rs b/crates/astria-cli/src/sequencer/address.rs deleted file mode 100644 index fa7dcee7cb..0000000000 --- a/crates/astria-cli/src/sequencer/address.rs +++ /dev/null @@ -1,55 +0,0 @@ -use astria_core::primitive::v1::{ - Address, - ADDRESS_LEN, -}; -use color_eyre::eyre::{ - self, - WrapErr as _, -}; - -#[derive(Debug, clap::Args)] -pub(super) struct Command { - #[command(subcommand)] - command: SubCommand, -} - -impl Command { - pub(super) fn run(self) -> eyre::Result<()> { - let SubCommand::Bech32m(bech32m) = self.command; - bech32m.run() - } -} - -#[derive(Debug, clap::Subcommand)] -enum SubCommand { - /// Returns a bech32m sequencer address given a prefix and hex-encoded byte slice - Bech32m(Bech32m), -} - -#[derive(Debug, clap::Args)] -struct Bech32m { - /// The hex formatted byte part of the bech32m address - #[arg(long)] - bytes: String, - /// The human readable prefix (Hrp) of the bech32m adress - #[arg(long, default_value = "astria")] - prefix: String, -} - -impl Bech32m { - fn run(self) -> eyre::Result<()> { - use hex::FromHex as _; - let bytes = <[u8; ADDRESS_LEN]>::from_hex(&self.bytes) - .wrap_err("failed decoding provided hex bytes")?; - let address = Address::::builder() - .array(bytes) - .prefix(&self.prefix) - .try_build() - .wrap_err( - "failed constructing a valid bech32m address from the provided hex bytes and \ - prefix", - )?; - println!("{address}"); - Ok(()) - } -} diff --git a/crates/astria-cli/src/sequencer/mod.rs b/crates/astria-cli/src/sequencer/mod.rs index 6beda8d5ec..def0079456 100644 --- a/crates/astria-cli/src/sequencer/mod.rs +++ b/crates/astria-cli/src/sequencer/mod.rs @@ -2,7 +2,6 @@ use clap::Subcommand; use color_eyre::eyre; mod account; -mod address; mod balance; mod block_height; mod bridge_account; @@ -26,7 +25,6 @@ impl Command { pub(super) async fn run(self) -> eyre::Result<()> { match self.command { SubCommand::Account(account) => account.run().await, - SubCommand::Address(address) => address.run(), SubCommand::Balance(balance) => balance.run().await, SubCommand::BlockHeight(block_height) => block_height.run().await, SubCommand::BridgeLock(bridge_lock) => bridge_lock.run().await, @@ -48,8 +46,6 @@ impl Command { enum SubCommand { /// Commands for interacting with Sequencer accounts Account(account::Command), - /// Utilities for constructing and inspecting sequencer addresses - Address(address::Command), /// Commands for interacting with Sequencer balances Balance(balance::Command), /// Commands for interacting with Sequencer block heights diff --git a/tools/astria-address/CHANGELOG.md b/tools/astria-address/CHANGELOG.md new file mode 100644 index 0000000000..b433965eb6 --- /dev/null +++ b/tools/astria-address/CHANGELOG.md @@ -0,0 +1,14 @@ + + +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +### Added + +- Initial release [#1803](https://github.com/astriaorg/astria/pull/1803) diff --git a/tools/astria-address/Cargo.lock b/tools/astria-address/Cargo.lock new file mode 100644 index 0000000000..58d7ddfa1a --- /dev/null +++ b/tools/astria-address/Cargo.lock @@ -0,0 +1,478 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "anstyle" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" + +[[package]] +name = "assert_cmd" +version = "2.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc1835b7f27878de8525dc71410b5a31cdcc5f230aed5ba5df968e09c201b23d" +dependencies = [ + "anstyle", + "bstr", + "doc-comment", + "libc", + "predicates", + "predicates-core", + "predicates-tree", + "wait-timeout", +] + +[[package]] +name = "astria-address" +version = "0.1.0" +dependencies = [ + "assert_cmd", + "astria-core-address", + "const-hex", + "const_format", + "pico-args", + "predicates", +] + +[[package]] +name = "astria-core-address" +version = "0.1.0" +dependencies = [ + "astria-core-consts", + "bech32", + "thiserror", +] + +[[package]] +name = "astria-core-consts" +version = "0.1.0" + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "bech32" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d965446196e3b7decd44aa7ee49e31d630118f90ef12f97900f262eb915c951d" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "bstr" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40723b8fb387abc38f4f4a37c09073622e41dd12327033091ef8950659e6dc0c" +dependencies = [ + "memchr", + "regex-automata", + "serde", +] + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "const-hex" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0121754e84117e65f9d90648ee6aa4882a6e63110307ab73967a4c5e7e69e586" +dependencies = [ + "cfg-if", + "cpufeatures", + "hex", + "proptest", + "serde", +] + +[[package]] +name = "const_format" +version = "0.2.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50c655d81ff1114fb0dcdea9225ea9f0cc712a6f8d189378e82bdf62a473a64b" +dependencies = [ + "const_format_proc_macros", +] + +[[package]] +name = "const_format_proc_macros" +version = "0.2.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eff1a44b93f47b1bac19a27932f5c591e43d1ba357ee4f61526c8a25603f0eb1" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "cpufeatures" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" +dependencies = [ + "libc", +] + +[[package]] +name = "difflib" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8" + +[[package]] +name = "doc-comment" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" + +[[package]] +name = "float-cmp" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4" +dependencies = [ + "num-traits", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.161" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" + +[[package]] +name = "libm" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "normalize-line-endings" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", + "libm", +] + +[[package]] +name = "pico-args" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315" + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "predicates" +version = "3.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e9086cc7640c29a356d1a29fd134380bee9d8f79a17410aa76e7ad295f42c97" +dependencies = [ + "anstyle", + "difflib", + "float-cmp", + "normalize-line-endings", + "predicates-core", + "regex", +] + +[[package]] +name = "predicates-core" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae8177bee8e75d6846599c6b9ff679ed51e882816914eec639944d7c9aa11931" + +[[package]] +name = "predicates-tree" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41b740d195ed3166cd147c8047ec98db0e22ec019eb8eeb76d343b795304fb13" +dependencies = [ + "predicates-core", + "termtree", +] + +[[package]] +name = "proc-macro2" +version = "1.0.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "proptest" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4c2511913b88df1637da85cc8d96ec8e43a3f8bb8ccb71ee1ac240d6f3df58d" +dependencies = [ + "bitflags", + "lazy_static", + "num-traits", + "rand", + "rand_chacha", + "rand_xorshift", + "regex-syntax", + "unarray", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[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", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_xorshift" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" +dependencies = [ + "rand_core", +] + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "serde" +version = "1.0.214" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.214" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "syn" +version = "2.0.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "termtree" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76" + +[[package]] +name = "thiserror" +version = "1.0.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02dd99dc800bbb97186339685293e1cc5d9df1f8fae2d0aecd9ff1c77efea892" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7c61ec9a6f64d2793d8a45faba21efbe3ced62a886d44c36a009b2b519b4c7e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "unarray" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" + +[[package]] +name = "unicode-ident" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "wait-timeout" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" +dependencies = [ + "libc", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/tools/astria-address/Cargo.toml b/tools/astria-address/Cargo.toml new file mode 100644 index 0000000000..ba910d94d1 --- /dev/null +++ b/tools/astria-address/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "astria-address" +version = "0.1.0" +edition = "2021" +rust-version = "1.81.0" + +[dependencies] +astria-core-address = { path = "../../crates/astria-core-address" } +const-hex = "1.13.1" +const_format = "0.2.33" +pico-args = "0.5.0" + +[dev-dependencies] +assert_cmd = "2.0.16" +predicates = "3.1.2" diff --git a/tools/astria-address/README.md b/tools/astria-address/README.md new file mode 100644 index 0000000000..9071a0ff67 --- /dev/null +++ b/tools/astria-address/README.md @@ -0,0 +1,33 @@ +# Astria Address Tool + +Construct Astria addresses given a 20 hex encoded bytes (usually obtained from +a private/public ed25519 keypair). + +This tool is intended for developers and operators and usually not needed when +interacting with the Astria network. + +## Building and usage + +```console +# From inside the `astria-address` crate +$ cargo build --release +$ target/release/astria-address --help +Astria Address Tool + +Utility to construct astria addresses given an address prefix +and 20 hex-encoded bytes. + +USAGE: + astria-address [OPTIONS] [INPUT] + +FLAGS: + -h, --help Prints help information + -c, --compat Constructs a compat address (primarily IBC communication + with chains that only support bech32 non-m addresses) + +OPTIONS: + -p, --prefix STRING Sets the prefix of the address (default: astria) + +ARGS: + The 20 bytes in hex-format +``` diff --git a/tools/astria-address/src/main.rs b/tools/astria-address/src/main.rs new file mode 100644 index 0000000000..96f38f7e26 --- /dev/null +++ b/tools/astria-address/src/main.rs @@ -0,0 +1,97 @@ +use astria_core_address as address; +use astria_core_address::{ + Address, + ADDRESS_LENGTH, +}; + +const DEFAULT_PREFIX: &str = "astria"; +const HELP: &str = const_format::formatcp!( + r"Astria Address Tool + +Utility to construct astria addresses given an address prefix +and {ADDRESS_LENGTH} hex-encoded bytes. + +USAGE: + astria-address [OPTIONS] [INPUT] + +FLAGS: + -h, --help Prints help information + -c, --compat Constructs a compat address (primarily IBC communication + with chains that only support bech32 non-m addresses) + +OPTIONS: + -p, --prefix STRING Sets the prefix of the address (default: {DEFAULT_PREFIX}) + +ARGS: + The {ADDRESS_LENGTH} bytes in hex-format +" +); + +fn main() -> Result<(), Box> { + let args = Args::parse()?; + args.run()?; + Ok(()) +} + +#[derive(Debug)] +struct Args { + compat: bool, + prefix: Option, + input: [u8; ADDRESS_LENGTH], +} + +impl Args { + fn parse() -> Result { + let mut pargs = pico_args::Arguments::from_env(); + + // XXX: little hack to move the args out of pargs and back in: + let no_args = { + let raw_args = pargs.finish(); + let no_args = raw_args.is_empty(); + pargs = pico_args::Arguments::from_vec(raw_args); + no_args + }; + if pargs.contains(["-h", "--help"]) || no_args { + print!("{}", HELP); + std::process::exit(0); + } + + let args = Self { + compat: pargs.contains(["-c", "--compat"]), + prefix: pargs.opt_value_from_str(["-p", "--prefix"])?, + input: pargs.free_from_fn(|input| const_hex::decode_to_array(input))?, + }; + + // It's up to the caller what to do with the remaining arguments. + let remaining = pargs.finish(); + if !remaining.is_empty() { + return Err(pico_args::Error::ArgumentParsingFailed { + cause: format!("unknown arguments: {remaining:?}"), + }); + } + + Ok(args) + } + + fn run(self) -> Result<(), address::Error> { + use astria_core_address::{ + Bech32, + Bech32m, + }; + let prefix = self.prefix.as_deref().unwrap_or(DEFAULT_PREFIX); + if self.compat { + let address = Address::::builder() + .array(self.input) + .prefix(prefix) + .try_build()?; + println!("{address}"); + } else { + let address = Address::::builder() + .array(self.input) + .prefix(prefix) + .try_build()?; + println!("{address}"); + } + Ok(()) + } +} diff --git a/tools/astria-address/tests/make_address.rs b/tools/astria-address/tests/make_address.rs new file mode 100644 index 0000000000..31e85511a3 --- /dev/null +++ b/tools/astria-address/tests/make_address.rs @@ -0,0 +1,52 @@ +use assert_cmd::Command; +use predicates::prelude::*; + +const INPUT_BYTES: &str = "1234567890abcdef1234567890abcdef12345678"; + +#[test] +fn input_without_options() { + let assert = Command::cargo_bin(env!("CARGO_PKG_NAME")) + .unwrap() + .arg(INPUT_BYTES) + .assert(); + assert.stdout(predicate::eq( + "astria1zg69v7ys40x77y352eufp27daufrg4nc077y64\n", + )); +} + +#[test] +fn input_with_compat() { + let assert = Command::cargo_bin(env!("CARGO_PKG_NAME")) + .unwrap() + .arg("--compat") + .arg(INPUT_BYTES) + .assert(); + assert.stdout(predicate::eq( + "astria1zg69v7ys40x77y352eufp27daufrg4nc6zwglh\n", + )); +} + +#[test] +fn input_with_prefix() { + let assert = Command::cargo_bin(env!("CARGO_PKG_NAME")) + .unwrap() + .args(["--prefix", "astriacompat"]) + .arg(INPUT_BYTES) + .assert(); + assert.stdout(predicate::eq( + "astriacompat1zg69v7ys40x77y352eufp27daufrg4ncd586wu\n", + )); +} + +#[test] +fn input_with_prefix_and_compat() { + let assert = Command::cargo_bin(env!("CARGO_PKG_NAME")) + .unwrap() + .arg("--compat") + .args(["--prefix", "astriacompat"]) + .arg(INPUT_BYTES) + .assert(); + assert.stdout(predicate::eq( + "astriacompat1zg69v7ys40x77y352eufp27daufrg4nccghkt7\n", + )); +}