Skip to content

Commit dc67f83

Browse files
committed
refactor: split into library and cli
1 parent f70c56e commit dc67f83

File tree

7 files changed

+145
-71
lines changed

7 files changed

+145
-71
lines changed

Cargo.toml

+2-38
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,2 @@
1-
[package]
2-
name = "bech32-utils"
3-
version = "0.2.0"
4-
edition = "2021"
5-
description = "A CLI tool for converting Bech32 addresses with different prefixes."
6-
license = "MIT OR Apache-2.0"
7-
repository = "https://github.com/mbbrainz/bech32-utils"
8-
readme = "README.md"
9-
keywords = ["bech32", "cli", "address-conversion"]
10-
categories = ["command-line-utilities", "cryptography", "utilities"]
11-
12-
[dependencies]
13-
bech32 = "0.9.1"
14-
clap = { version = "4.4.7", features = ["derive"] }
15-
cosmwasm-std = "1.3.0"
16-
csv = "1.3.0"
17-
18-
[[bin]]
19-
name = "bech32-utils"
20-
path = "src/main.rs"
21-
22-
[profile.release]
23-
# Optimize for maximum performance
24-
opt-level = 3
25-
26-
# Use link time optimization
27-
lto = true
28-
29-
# Strip symbols for a smaller binary
30-
strip = true
31-
32-
# More aggressive inlining
33-
codegen-units = 1
34-
35-
# Disable debug information
36-
debug = false
37-
38-
panic = "abort"
1+
[workspace]
2+
members = ["bech32-addr-converter", "bech32-addr-converter-cli"]

bech32-addr-converter-cli/Cargo.toml

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
[package]
2+
name = "bech32-addr-converter-cli"
3+
version = "0.1.0"
4+
edition = "2021"
5+
description = "A CLI tool for converting Bech32 addresses with different prefixes."
6+
license = "MIT OR Apache-2.0"
7+
repository = "https://github.com/mbbrainz/bech32-utils"
8+
readme = "README.md"
9+
keywords = ["bech32", "cli", "address-conversion"]
10+
categories = ["command-line-utilities", "cryptography", "utilities"]
11+
12+
[dependencies]
13+
bech32 = "0.9.1"
14+
clap = { version = "4.4.7", features = ["derive"] }
15+
cosmwasm-std = "1.3.0"
16+
csv = "1.3.0"
17+
bech32-addr-converter = { path = "../bech32-addr-converter" }
18+
19+
[[bin]]
20+
name = "bech32-addr-converter"
21+
path = "src/main.rs"
22+
23+
[profile.release]
24+
# Optimize for maximum performance
25+
opt-level = 3
26+
27+
# Use link time optimization
28+
lto = true
29+
30+
# Strip symbols for a smaller binary
31+
strip = true
32+
33+
# More aggressive inlining
34+
codegen-units = 1
35+
36+
# Disable debug information
37+
debug = false
38+
39+
panic = "abort"

src/main.rs bech32-addr-converter-cli/src/main.rs

+15-19
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
use bech32_utils::converter;
1+
use bech32_addr_converter::converter;
22
use clap::{error::ErrorKind, Parser};
33
use std::path::PathBuf;
44

5-
use clap::{Args, Subcommand};
5+
use clap::{Args, Subcommand};
66

77
#[derive(Parser)]
88
#[command(
@@ -29,7 +29,7 @@ enum Commands {
2929
struct ConvertCsv {
3030
/// The input csv file
3131
#[arg(required = true, index = 1)]
32-
input_dir: PathBuf,
32+
input_dir: PathBuf,
3333

3434
/// The prefix one wants to convert it into
3535
#[arg(required = true, index = 2)]
@@ -55,17 +55,15 @@ struct SingleConvert {
5555
derivation_path: Option<PathBuf>,
5656
}
5757

58-
5958
fn single_convert(single: SingleConvert) {
6059
let address = single.address;
6160
let prefix = single.prefix;
6261
let _derivation_path = single.derivation_path;
6362

64-
6563
match converter::any_addr_to_prefix_addr(address, &prefix) {
6664
Ok(transformed_address) => println!("{}", transformed_address),
6765
Err(e) => {
68-
eprintln!("Error transforming address: {}", e);
66+
eprintln!("Error transforming address: {:?}", e);
6967
clap::Error::new(ErrorKind::ValueValidation);
7068
}
7169
}
@@ -75,9 +73,9 @@ fn convert_csv(convert_csv: ConvertCsv) {
7573
let input_dir = convert_csv.input_dir;
7674

7775
// output_dir is optional, if not provided, the output will be written to the input file with the postfix "_converted"
78-
let output_dir = convert_csv.output_dir.unwrap_or_else(|| {
79-
add_converted_postfix(&input_dir)
80-
});
76+
let output_dir = convert_csv
77+
.output_dir
78+
.unwrap_or_else(|| add_converted_postfix(&input_dir));
8179

8280
let prefix = convert_csv.prefix;
8381

@@ -89,17 +87,18 @@ fn convert_csv(convert_csv: ConvertCsv) {
8987
let address = record.get(0).unwrap();
9088

9189
// iterate over the rest of the record to get the rest of the record
92-
let rest = (1..record.len()).map(|i| record.get(i).unwrap())
93-
.map(|s| s.to_string())
94-
.collect::<Vec<String>>();
95-
90+
let rest = (1..record.len())
91+
.map(|i| record.get(i).unwrap())
92+
.map(|s| s.to_string())
93+
.collect::<Vec<String>>();
9694

9795
match converter::any_addr_to_prefix_addr(address.to_string(), &prefix) {
9896
Ok(transformed_address) => {
99-
wtr.write_record(&[transformed_address, rest.join(",")]).unwrap();
97+
wtr.write_record(&[transformed_address, rest.join(",")])
98+
.unwrap();
10099
}
101100
Err(e) => {
102-
eprintln!("Error transforming address: {}", e);
101+
eprintln!("Error transforming address: {:?}", e);
103102
clap::Error::new(ErrorKind::ValueValidation);
104103
}
105104
}
@@ -110,13 +109,12 @@ fn convert_csv(convert_csv: ConvertCsv) {
110109
fn add_converted_postfix(input_dir: &PathBuf) -> PathBuf {
111110
let mut output_dir = input_dir.clone();
112111
let file_name = output_dir.file_name().unwrap();
113-
let file_name = file_name.to_str().unwrap();
112+
let file_name = file_name.to_str().unwrap().split(".").next().unwrap();
114113
let file_name = format!("{}_converted.csv", file_name);
115114
output_dir.set_file_name(file_name);
116115
output_dir
117116
}
118117

119-
120118
fn main() {
121119
let cli = Cli::parse();
122120
match cli.command {
@@ -125,7 +123,6 @@ fn main() {
125123
}
126124
}
127125

128-
129126
#[cfg(test)]
130127
mod tests {
131128
use super::*;
@@ -143,5 +140,4 @@ mod tests {
143140
let output_dir = add_converted_postfix(&input_dir);
144141
assert_eq!(output_dir, PathBuf::from("test/test_converted.csv"));
145142
}
146-
147143
}

bech32-addr-converter/Cargo.toml

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
[package]
2+
name = "bech32-addr-converter"
3+
version = "0.2.0"
4+
edition = "2021"
5+
description = "A CLI tool for converting Bech32 addresses with different prefixes."
6+
license = "MIT OR Apache-2.0"
7+
repository = "https://github.com/mbbrainz/bech32-utils"
8+
readme = "README.md"
9+
keywords = [
10+
"bech32",
11+
"address-conversion",
12+
"cosmos-sdk",
13+
"blockchain",
14+
"cryptocurrency",
15+
"utilities",
16+
]
17+
categories = ["cryptography", "utilities"]
18+
19+
[lib]
20+
21+
[dependencies]
22+
bech32 = "0.11"
23+
24+
25+
[profile.release]
26+
# Optimize for maximum performance
27+
opt-level = 3
28+
29+
# Use link time optimization
30+
lto = true
31+
32+
# Strip symbols for a smaller binary
33+
strip = true
34+
35+
# More aggressive inlining
36+
codegen-units = 1
37+
38+
# Disable debug information
39+
debug = false
40+
41+
panic = "abort"
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,34 @@
1+
use bech32::Bech32;
2+
3+
#[derive(std::fmt::Debug)]
4+
pub enum Bech32Error {
5+
EncodeError(bech32::EncodeError),
6+
DecodeError(bech32::DecodeError),
7+
HrpError(bech32::primitives::hrp::Error),
8+
}
9+
10+
impl From<bech32::EncodeError> for Bech32Error {
11+
fn from(error: bech32::EncodeError) -> Self {
12+
Bech32Error::EncodeError(error)
13+
}
14+
}
15+
16+
impl From<bech32::DecodeError> for Bech32Error {
17+
fn from(error: bech32::DecodeError) -> Self {
18+
Bech32Error::DecodeError(error)
19+
}
20+
}
21+
22+
impl From<bech32::primitives::hrp::Error> for Bech32Error {
23+
fn from(error: bech32::primitives::hrp::Error) -> Self {
24+
Bech32Error::HrpError(error)
25+
}
26+
}
127
/// This function transfer the addr to a local neutron addr
228
3-
pub fn any_addr_to_prefix_addr(addr: String, prefix: &str) -> Result<String, bech32::Error> {
4-
// TODO, test this snippet
5-
let (_hrp, data, _variant) = bech32::decode(&addr)?;
6-
let neutron_addr = bech32::encode(prefix, data, bech32::Variant::Bech32)?;
29+
pub fn any_addr_to_prefix_addr(addr: String, prefix: &str) -> Result<String, Bech32Error> {
30+
let (_hrp, data) = bech32::decode(&addr)?;
31+
let neutron_addr = bech32::encode::<Bech32>(bech32::Hrp::parse(prefix)?, &data)?;
732
Ok(neutron_addr)
833
}
934

@@ -18,49 +43,51 @@ mod tests {
1843
const KUJIRA_BECH32_PREFIX: &str = "kujira";
1944

2045
#[test]
21-
fn test_any_addr_to_neutron() {
46+
fn test_any_addr_to_neutron() -> Result<(), Bech32Error> {
2247
let juno_addr_dan = "juno14wd9r77c2rlau7r8lta6mh8nqsvqq00rxha3fl";
2348
let juno_addr_eliseo = "juno1e7faq9nlpms0hfddd8vqqgval478shukpj8c50";
2449
let cosmos_addr_alecp = "cosmos1e4qv3j8lr6xuxsd9fy9yr9xx4hdcwnp4usgg4w";
2550

2651
let neutron_addr_alecp =
27-
any_addr_to_prefix_addr(cosmos_addr_alecp.to_string(), NEUTRON_BECH32_PREFIX).unwrap();
52+
any_addr_to_prefix_addr(cosmos_addr_alecp.to_string(), NEUTRON_BECH32_PREFIX)?;
2853
println!("neutron_addr_alecp: {}", neutron_addr_alecp);
2954

3055
// test juno to neutron and print the result
3156
let juno_addr_dan_neutron =
32-
any_addr_to_prefix_addr(juno_addr_dan.to_string(), NEUTRON_BECH32_PREFIX).unwrap();
57+
any_addr_to_prefix_addr(juno_addr_dan.to_string(), NEUTRON_BECH32_PREFIX)?;
3358
let juno_addr_eliseo_neutron =
34-
any_addr_to_prefix_addr(juno_addr_eliseo.to_string(), NEUTRON_BECH32_PREFIX).unwrap();
59+
any_addr_to_prefix_addr(juno_addr_eliseo.to_string(), NEUTRON_BECH32_PREFIX)?;
3560
println!("juno_addr_dan_neutron: \t{}", juno_addr_dan_neutron);
3661
println!("juno_addr_eliseo_neutron: {}", juno_addr_eliseo_neutron);
3762
print!("\n");
3863

3964
// test juno to osmosis and print the result
4065
let juno_addr_dan_osmosis =
41-
any_addr_to_prefix_addr(juno_addr_dan.to_string(), OSMOSIS_BECH32_PREFIX).unwrap();
66+
any_addr_to_prefix_addr(juno_addr_dan.to_string(), OSMOSIS_BECH32_PREFIX)?;
4267
let juno_addr_eliseo_osmosis =
43-
any_addr_to_prefix_addr(juno_addr_eliseo.to_string(), OSMOSIS_BECH32_PREFIX).unwrap();
68+
any_addr_to_prefix_addr(juno_addr_eliseo.to_string(), OSMOSIS_BECH32_PREFIX)?;
4469
println!("juno_addr_dan_osmosis:\t {}", juno_addr_dan_osmosis);
4570
println!("juno_addr_eliseo_osmosis: {}", juno_addr_eliseo_osmosis);
4671
print!("\n");
4772

4873
// test juno to terra and print the result
4974
let juno_addr_dan_terra =
50-
any_addr_to_prefix_addr(juno_addr_dan.to_string(), TERRA_BECH32_PREFIX).unwrap();
75+
any_addr_to_prefix_addr(juno_addr_dan.to_string(), TERRA_BECH32_PREFIX)?;
5176
let juno_addr_eliseo_terra =
52-
any_addr_to_prefix_addr(juno_addr_eliseo.to_string(), TERRA_BECH32_PREFIX).unwrap();
77+
any_addr_to_prefix_addr(juno_addr_eliseo.to_string(), TERRA_BECH32_PREFIX)?;
5378
println!("juno_addr_dan_terra:\t {}", juno_addr_dan_terra);
5479
println!("juno_addr_eliseo_terra: {}", juno_addr_eliseo_terra);
5580
print!("\n");
5681

5782
// test juno to kujira and print the result
5883
let juno_addr_dan_kujira =
59-
any_addr_to_prefix_addr(juno_addr_dan.to_string(), KUJIRA_BECH32_PREFIX).unwrap();
84+
any_addr_to_prefix_addr(juno_addr_dan.to_string(), KUJIRA_BECH32_PREFIX)?;
6085
let juno_addr_eliseo_kujira =
61-
any_addr_to_prefix_addr(juno_addr_eliseo.to_string(), KUJIRA_BECH32_PREFIX).unwrap();
86+
any_addr_to_prefix_addr(juno_addr_eliseo.to_string(), KUJIRA_BECH32_PREFIX)?;
6287
println!("juno_addr_dan_kujira:\t {}", juno_addr_dan_kujira);
6388
println!("juno_addr_eliseo_kujira: {}", juno_addr_eliseo_kujira);
6489
print!("\n");
90+
91+
Ok(())
6592
}
6693
}
File renamed without changes.

bech32-utils.code-workspace

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"folders": [
3+
{
4+
"path": "."
5+
}
6+
]
7+
}

0 commit comments

Comments
 (0)