2026-03-13 22:38:23 +03:00
use common ::{ HashType , transaction ::NSSATransaction } ;
2026-04-24 22:10:04 -04:00
use keycard_wallet ::KeycardWallet ;
2025-10-03 15:59:27 -03:00
use nssa ::{
2025-11-24 17:09:30 +03:00
AccountId , PublicTransaction ,
2025-10-03 15:59:27 -03:00
program ::Program ,
public_transaction ::{ Message , WitnessSet } ,
} ;
2026-03-13 22:38:23 +03:00
use sequencer_service_rpc ::RpcClient as _ ;
2025-09-22 16:38:25 +03:00
2025-11-30 01:57:59 +03:00
use super ::NativeTokenTransfer ;
2026-04-24 22:10:04 -04:00
use crate ::{ ExecutionFailureKind , WalletCore } ;
2025-09-22 16:38:25 +03:00
2025-11-30 01:57:59 +03:00
impl NativeTokenTransfer < '_ > {
pub async fn send_public_transfer (
2025-09-22 16:38:25 +03:00
& self ,
2025-11-24 17:09:30 +03:00
from : AccountId ,
to : AccountId ,
2025-09-22 16:38:25 +03:00
balance_to_move : u128 ,
2026-04-23 17:45:43 -04:00
pin : & Option < String > ,
key_path : & Option < String > ,
2026-03-13 22:38:23 +03:00
) -> Result < HashType , ExecutionFailureKind > {
2026-03-04 18:42:33 +03:00
let balance = self
. 0
. get_account_balance ( from )
. await
. map_err ( ExecutionFailureKind ::SequencerError ) ? ;
2025-09-22 16:38:25 +03:00
2026-04-28 14:13:04 -04:00
if balance < balance_to_move {
return Err ( ExecutionFailureKind ::InsufficientFundsError ) ;
}
2026-03-27 21:43:28 +03:00
2026-04-28 14:13:04 -04:00
let account_ids = vec! [ from , to ] ;
let program_id = Program ::authenticated_transfer_program ( ) . id ( ) ;
2026-04-21 13:40:15 -04:00
2026-04-28 14:13:04 -04:00
// Fetch nonces for both accounts unconditionally
2026-04-28 20:45:43 -04:00
let mut nonces = self
2026-04-28 20:48:02 -04:00
. 0
. get_accounts_nonces ( vec! [ from ] )
. await
. map_err ( ExecutionFailureKind ::SequencerError ) ? ;
let to_signing_key = self . 0. storage . user_data . get_pub_account_signing_key ( to ) ;
if let Some ( _to_signing_key ) = to_signing_key {
let to_nonces = self
2026-04-28 20:45:43 -04:00
. 0
2026-04-28 20:48:02 -04:00
. get_accounts_nonces ( vec! [ to ] )
2026-04-28 20:45:43 -04:00
. await
. map_err ( ExecutionFailureKind ::SequencerError ) ? ;
2026-04-28 20:48:02 -04:00
nonces . extend ( to_nonces ) ;
} else {
println! (
" Receiver's account ({to}) private key not found in wallet. Proceeding with only sender's key. "
) ;
}
2026-04-21 13:40:15 -04:00
2026-04-28 14:13:04 -04:00
let message = Message ::try_new ( program_id , account_ids , nonces , balance_to_move ) . unwrap ( ) ;
2025-09-22 16:38:25 +03:00
2026-04-28 16:32:42 -04:00
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 ] )
} ) ;
2025-09-22 16:38:25 +03:00
2026-04-28 14:13:04 -04:00
let tx = PublicTransaction ::new ( message , witness_set ) ;
Ok ( self
. 0
. sequencer_client
. send_transaction ( NSSATransaction ::Public ( tx ) )
. await ? )
2025-09-22 16:38:25 +03:00
}
2025-10-10 17:47:23 -03:00
2025-11-30 01:57:59 +03:00
pub async fn register_account (
2025-10-10 17:47:23 -03:00
& self ,
2025-11-24 17:09:30 +03:00
from : AccountId ,
2026-04-23 17:45:43 -04:00
pin : & Option < String > , // Used by Keycard.
key_path : & Option < String > , // Used by Keycard.
2026-03-13 22:38:23 +03:00
) -> Result < HashType , ExecutionFailureKind > {
2026-03-04 18:42:33 +03:00
let nonces = self
. 0
. get_accounts_nonces ( vec! [ from ] )
. await
. map_err ( ExecutionFailureKind ::SequencerError ) ? ;
2025-10-10 17:47:23 -03:00
let instruction : u128 = 0 ;
2025-11-24 17:09:30 +03:00
let account_ids = vec! [ from ] ;
2025-10-10 17:47:23 -03:00
let program_id = Program ::authenticated_transfer_program ( ) . id ( ) ;
2026-04-26 21:29:54 -04:00
let message = Message ::try_new ( program_id , account_ids , nonces , instruction )
. expect ( " Expect a valid Message " ) ;
2025-10-10 17:47:23 -03:00
2026-04-23 17:45:43 -04:00
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 ) ;
} ;
2025-10-10 17:47:23 -03:00
2026-04-23 17:45:43 -04:00
WitnessSet ::for_message ( & message , & [ signing_key ] )
} else {
2026-04-24 22:10:04 -04:00
let pub_key = KeycardWallet ::get_public_key_for_path_with_connect (
2026-04-28 21:33:12 -04:00
pin . as_ref ( ) . expect ( " `wallet::program_facades::native_token_transfer::public::register_account`: invalid data received for pin for public key " ) ,
key_path . as_ref ( ) . expect ( " `wallet::program_facades::native_token_transfer::public::register_account`: invalid data received for key_path for public_key " ) ,
2026-04-24 22:10:04 -04:00
) ;
let signature = KeycardWallet ::sign_message_for_path_with_connect (
2026-04-28 21:33:12 -04:00
pin . as_ref ( ) . as_ref ( ) . expect ( " `wallet::program_facades::native_token_transfer::public::register_account`: invalid data received for pin for signature " ) ,
key_path . as_ref ( ) . expect ( " `wallet::program_facades::native_token_transfer::public::register_account`: invalid data received for key_path for public_key " ) ,
2026-04-24 22:10:04 -04:00
& message . hash_message ( ) ,
)
. expect ( " Expect a valid Signature. " ) ;
WitnessSet ::from_list ( & [ signature ] , & [ pub_key ] )
2026-04-23 17:45:43 -04:00
} ;
2025-10-10 17:47:23 -03:00
let tx = PublicTransaction ::new ( message , witness_set ) ;
2026-03-13 22:38:23 +03:00
Ok ( self
. 0
. sequencer_client
. send_transaction ( NSSATransaction ::Public ( tx ) )
. await ? )
2025-10-10 17:47:23 -03:00
}
2025-09-22 16:38:25 +03:00
}