use common::{HashType, transaction::NSSATransaction}; use keycard_wallet::KeycardWallet; use nssa::{ AccountId, PublicTransaction, program::Program, public_transaction::{Message, WitnessSet}, }; use sequencer_service_rpc::RpcClient as _; use super::NativeTokenTransfer; use crate::{ExecutionFailureKind, WalletCore}; impl NativeTokenTransfer<'_> { pub async fn send_public_transfer( &self, from: AccountId, to: AccountId, balance_to_move: u128, pin: &Option, key_path: &Option, ) -> Result { let balance = self .0 .get_account_balance(from) .await .map_err(ExecutionFailureKind::SequencerError)?; if balance < balance_to_move { return Err(ExecutionFailureKind::InsufficientFundsError); } let account_ids = vec![from, to]; let program_id = Program::authenticated_transfer_program().id(); // Fetch nonces for both accounts unconditionally let nonces = self .0 .get_accounts_nonces(account_ids.clone()) .await .map_err(ExecutionFailureKind::SequencerError)?; let message = Message::try_new(program_id, account_ids, nonces, balance_to_move).unwrap(); let witness_set = pin.as_ref().map_or_else(|| { let sign_ids = self.0.filter_owned_accounts(&[from, to]); WalletCore::sign_public_message(self.0, &message, &sign_ids) .expect("`WalletCore::sign_public_message() failed to produce a signature for a NativeTokenTransfer.") }, |pin| { let key_path = key_path.as_ref().expect("`NativeTokenTransfer::send_public_transfer() expected a String for `key_path`."); let pub_key = KeycardWallet::get_public_key_for_path_with_connect( pin, key_path, ); let signature = KeycardWallet::sign_message_for_path_with_connect( pin, key_path, &message.hash_message(), ) .expect("`NativeTokenTransfer::send_public_transfer() failed to produce a Signature for the given `pin` and `key_path`."); WitnessSet::from_list(&[signature], &[pub_key]) }); let tx = PublicTransaction::new(message, witness_set); Ok(self .0 .sequencer_client .send_transaction(NSSATransaction::Public(tx)) .await?) } pub async fn register_account( &self, from: AccountId, pin: &Option, // Used by Keycard. key_path: &Option, // Used by Keycard. ) -> Result { let nonces = self .0 .get_accounts_nonces(vec![from]) .await .map_err(ExecutionFailureKind::SequencerError)?; let instruction: u128 = 0; let account_ids = vec![from]; let program_id = Program::authenticated_transfer_program().id(); let message = Message::try_new(program_id, account_ids, nonces, instruction) .expect("Expect a valid Message"); let witness_set = if pin.is_none() { let signing_key = self.0.storage.user_data.get_pub_account_signing_key(from); let Some(signing_key) = signing_key else { return Err(ExecutionFailureKind::KeyNotFoundError); }; WitnessSet::for_message(&message, &[signing_key]) } else { let pub_key = KeycardWallet::get_public_key_for_path_with_connect( pin.as_ref().expect("Expect a pin as a String."), key_path.as_ref().expect("Expect a key path String."), ); let signature = KeycardWallet::sign_message_for_path_with_connect( pin.as_ref().as_ref().expect("Expect a pin as a String."), key_path.as_ref().expect("Expect a key path String."), &message.hash_message(), ) .expect("Expect a valid Signature."); WitnessSet::from_list(&[signature], &[pub_key]) }; let tx = PublicTransaction::new(message, witness_set); Ok(self .0 .sequencer_client .send_transaction(NSSATransaction::Public(tx)) .await?) } }