1use crate::crypto::{
2 address::Address,
3 bip32::{DerivedPublicKey, DerivedSecretKey},
4 bip39::Mnemonic,
5 bip44::ChildNumber,
6 Algorithm,
7};
8use crate::types::{AccountIdentifier, CurveType, PublicKey};
9use anyhow::Result;
10
11pub struct Signer {
13 secp256k1: DerivedSecretKey,
14 secp256k1_recoverable: DerivedSecretKey,
15 secp256r1: DerivedSecretKey,
16 ed25519: DerivedSecretKey,
17 sr25519: DerivedSecretKey,
18}
19
20impl Signer {
21 pub fn new(mnemonic: &Mnemonic, password: &str) -> Result<Self> {
23 let secp256k1 = DerivedSecretKey::new(mnemonic, password, Algorithm::EcdsaSecp256k1)?;
24 let secp256k1_recoverable =
25 DerivedSecretKey::new(mnemonic, password, Algorithm::EcdsaRecoverableSecp256k1)?;
26 let secp256r1 = DerivedSecretKey::new(mnemonic, password, Algorithm::EcdsaSecp256r1)?;
27 let ed25519 = DerivedSecretKey::new(mnemonic, password, Algorithm::Ed25519)?;
28 let sr25519 = DerivedSecretKey::new(mnemonic, password, Algorithm::Sr25519)?;
29 Ok(Self {
30 secp256k1,
31 secp256k1_recoverable,
32 secp256r1,
33 ed25519,
34 sr25519,
35 })
36 }
37
38 pub fn generate() -> Result<Self> {
40 let mnemonic = crate::mnemonic::generate_mnemonic()?;
41 Self::new(&mnemonic, "")
42 }
43
44 pub fn master_key(&self, algorithm: Algorithm) -> Result<&DerivedSecretKey> {
46 Ok(match algorithm {
47 Algorithm::EcdsaSecp256k1 => &self.secp256k1,
48 Algorithm::EcdsaRecoverableSecp256k1 => &self.secp256k1_recoverable,
49 Algorithm::EcdsaSecp256r1 => &self.secp256r1,
50 Algorithm::Ed25519 => &self.ed25519,
51 Algorithm::Sr25519 => &self.sr25519,
52 })
53 }
54
55 pub fn bip44_account(
57 &self,
58 algorithm: Algorithm,
59 coin: u32,
60 account: u32,
61 ) -> Result<DerivedSecretKey> {
62 self.master_key(algorithm)?
63 .derive(ChildNumber::hardened_from_u32(44))?
64 .derive(ChildNumber::hardened_from_u32(coin))?
65 .derive(ChildNumber::hardened_from_u32(account))?
66 .derive(ChildNumber::non_hardened_from_u32(0))
67 }
68}
69
70pub trait RosettaPublicKey {
72 fn to_rosetta(&self) -> PublicKey;
74}
75
76impl RosettaPublicKey for DerivedPublicKey {
77 fn to_rosetta(&self) -> PublicKey {
78 PublicKey {
79 curve_type: match self.public_key().algorithm() {
80 Algorithm::EcdsaSecp256k1 => CurveType::Secp256k1,
81 Algorithm::EcdsaRecoverableSecp256k1 => CurveType::Secp256k1,
82 Algorithm::EcdsaSecp256r1 => CurveType::Secp256r1,
83 Algorithm::Ed25519 => CurveType::Edwards25519,
84 Algorithm::Sr25519 => CurveType::Schnorrkel,
85 },
86 hex_bytes: hex::encode(self.public_key().to_bytes()),
87 }
88 }
89}
90
91pub trait RosettaAccount {
93 fn to_rosetta(&self) -> AccountIdentifier;
95}
96
97impl RosettaAccount for Address {
98 fn to_rosetta(&self) -> AccountIdentifier {
99 AccountIdentifier {
100 address: self.address().into(),
101 sub_account: None,
102 metadata: None,
103 }
104 }
105}