kabu_broadcast_accounts/signers/
initialize_actor.rs

1use alloy_primitives::{hex, Bytes, B256};
2use eyre::eyre;
3use tracing::{error, info};
4
5use kabu_core_actors::{Accessor, Actor, ActorResult, SharedState, WorkerResult};
6use kabu_core_actors_macros::Accessor;
7use kabu_core_blockchain::Blockchain;
8use kabu_types_blockchain::{KabuDataTypes, KabuDataTypesEthereum};
9use kabu_types_entities::{AccountNonceAndBalanceState, KeyStore, LoomTxSigner, TxSigners};
10
11/// The one-shot actor adds a new signer to the signers and monitor list after and stops.
12#[derive(Accessor)]
13pub struct InitializeSignersOneShotBlockingActor<LDT: KabuDataTypes> {
14    key: Option<Vec<u8>>,
15    #[accessor]
16    signers: Option<SharedState<TxSigners<LDT>>>,
17    #[accessor]
18    monitor: Option<SharedState<AccountNonceAndBalanceState>>,
19}
20
21async fn initialize_signers_one_shot_worker(
22    key: Vec<u8>,
23    signers: SharedState<TxSigners<KabuDataTypesEthereum>>,
24    monitor: SharedState<AccountNonceAndBalanceState>,
25) -> WorkerResult {
26    let new_signer = signers.write().await.add_privkey(Bytes::from(key));
27    monitor.write().await.add_account(new_signer.address());
28    info!("New signer added {:?}", new_signer.address());
29    Ok("Signer added".to_string())
30}
31
32impl<LDT: KabuDataTypes> InitializeSignersOneShotBlockingActor<LDT> {
33    pub fn new(key: Option<Vec<u8>>) -> InitializeSignersOneShotBlockingActor<LDT> {
34        let key = key.unwrap_or_else(|| B256::random().to_vec());
35
36        InitializeSignersOneShotBlockingActor { key: Some(key), signers: None, monitor: None }
37    }
38
39    pub fn new_from_encrypted_env() -> InitializeSignersOneShotBlockingActor<LDT> {
40        let key = match std::env::var("DATA") {
41            Ok(priv_key_enc) => {
42                let keystore = KeyStore::new();
43                let key = keystore.encrypt_once(hex::decode(priv_key_enc).unwrap().as_slice()).unwrap();
44                Some(key)
45            }
46            _ => None,
47        };
48
49        InitializeSignersOneShotBlockingActor { key, signers: None, monitor: None }
50    }
51
52    pub fn new_from_encrypted_key(priv_key_enc: Vec<u8>) -> InitializeSignersOneShotBlockingActor<LDT> {
53        let keystore = KeyStore::new();
54        let key = keystore.encrypt_once(priv_key_enc.as_slice()).unwrap();
55
56        InitializeSignersOneShotBlockingActor { key: Some(key), signers: None, monitor: None }
57    }
58
59    pub fn on_bc(self, bc: &Blockchain<LDT>) -> Self {
60        Self { monitor: Some(bc.nonce_and_balance()), ..self }
61    }
62
63    pub fn with_signers(self, signers: SharedState<TxSigners<LDT>>) -> Self {
64        Self { signers: Some(signers), ..self }
65    }
66}
67
68impl Actor for InitializeSignersOneShotBlockingActor<KabuDataTypesEthereum> {
69    fn start_and_wait(&self) -> eyre::Result<()> {
70        let key = match self.key.clone() {
71            Some(key) => key,
72            _ => {
73                error!("No signer keys found");
74                return Err(eyre!("NO_SIGNER_KEY"));
75            }
76        };
77        let (signers, monitor) = match (self.signers.clone(), self.monitor.clone()) {
78            (Some(signers), Some(monitor)) => (signers, monitor),
79            _ => {
80                error!("Signers or monitor not initialized");
81                return Err(eyre!("SIGNERS_OR_MONITOR_NOT_INITIALIZED"));
82            }
83        };
84
85        let rt = tokio::runtime::Runtime::new()?; // we need a different runtime to wait for the result
86        let handle = rt.spawn(async { initialize_signers_one_shot_worker(key, signers, monitor).await });
87
88        self.wait(Ok(vec![handle]))?;
89        rt.shutdown_background();
90
91        Ok(())
92    }
93    fn start(&self) -> ActorResult {
94        Err(eyre!("NEED_TO_BE_WAITED"))
95    }
96
97    fn name(&self) -> &'static str {
98        "InitializeSignersOneShotBlockingActor"
99    }
100}