1use crate::error::CosmosClient;
2use cosmrs::bip32::{Language, Mnemonic, XPrv};
3use cosmrs::crypto::secp256k1::SigningKey;
4use cosmrs::crypto::PublicKey;
5use cosmrs::AccountId;
6use hex::decode;
7use rand_core::OsRng;
8
9pub struct Signer {
10 pub mnemonic: Option<String>,
11 pub denom: String,
12 pub public_address: AccountId,
13 pub private_key: SigningKey,
14 pub public_key: PublicKey,
15 pub gas_adjustment_percent: u8,
16 pub gas_price: u128,
17}
18
19impl Signer {
20 fn load_from_mnemonic(
21 phrase: &str,
22 prefix: &str,
23 derivation: Option<&str>,
24 ) -> Result<(SigningKey, PublicKey, AccountId), CosmosClient> {
25 let derivation = if let Some(derivation) = derivation {
26 derivation
27 } else {
28 "m/44'/118'/0'/0/0"
29 };
30
31 let mnemonic = Mnemonic::new(phrase, Language::English)?;
32 let pri = XPrv::derive_from_path(&mnemonic.to_seed(""), &derivation.parse()?)?;
33 let private_key = SigningKey::from(pri);
34 let public_key = private_key.public_key();
35 let public_address = public_key.account_id(prefix)?;
36
37 Ok((private_key, public_key, public_address))
38 }
39
40 pub fn generate(
46 prefix: &str,
47 denom: &str,
48 derivation: Option<&str>,
49 gas_adjustment_percent: u8,
50 gas_price: u128,
51 ) -> Result<Self, CosmosClient> {
52 let mnemonic = Mnemonic::random(OsRng, Language::English);
53 let (private_key, public_key, public_address) =
54 Signer::load_from_mnemonic(mnemonic.phrase(), prefix, derivation)?;
55
56 Ok(Signer {
57 mnemonic: Some(mnemonic.phrase().to_string()),
58 public_address,
59 gas_adjustment_percent,
60 gas_price,
61 denom: denom.to_string(),
62 private_key,
63 public_key,
64 })
65 }
66
67 pub fn from_pkey(
74 private_key: &str,
75 prefix: &str,
76 denom: &str,
77 gas_adjustment_percent: u8,
78 gas_price: u128,
79 ) -> Result<Self, CosmosClient> {
80 let private_key = SigningKey::from_slice(decode(private_key)?.as_slice())?;
81 let public_key = private_key.public_key();
82 let public_address = public_key.account_id(prefix)?;
83
84 Ok(Signer {
85 mnemonic: None,
86 public_address,
87 gas_adjustment_percent,
88 gas_price,
89 denom: denom.to_string(),
90 private_key,
91 public_key,
92 })
93 }
94
95 pub fn from_mnemonic(
102 phrase: &str,
103 prefix: &str,
104 denom: &str,
105 derivation: Option<&str>,
106 gas_adjustment_percent: u8,
107 gas_price: u128,
108 ) -> Result<Self, CosmosClient> {
109 let (private_key, public_key, public_address) =
110 Signer::load_from_mnemonic(phrase, prefix, derivation)?;
111
112 Ok(Signer {
113 mnemonic: Some(phrase.to_string()),
114 public_address,
115 gas_adjustment_percent,
116 gas_price,
117 denom: denom.to_string(),
118 private_key,
119 public_key,
120 })
121 }
122}