diff --git a/nssa/program_methods/guest/src/bin/authenticated_transfer.rs b/nssa/program_methods/guest/src/bin/authenticated_transfer.rs index 210e3f0..3336ea9 100644 --- a/nssa/program_methods/guest/src/bin/authenticated_transfer.rs +++ b/nssa/program_methods/guest/src/bin/authenticated_transfer.rs @@ -1,4 +1,7 @@ -use nssa_core::program::{ProgramInput, read_nssa_inputs, write_nssa_outputs}; +use nssa_core::{ + account::Account, + program::{ProgramInput, read_nssa_inputs, write_nssa_outputs}, +}; /// A transfer of balance program. /// To be used both in public and private contexts. @@ -10,28 +13,40 @@ fn main() { instruction: balance_to_move, } = read_nssa_inputs(); - // Continue only if input_accounts is an array of two elements - let [sender, receiver] = match pre_states.try_into() { - Ok(array) => array, - Err(_) => return, - }; + if pre_states.len() == 1 { + // Claim account + let account_to_claim = pre_states[0].account.clone(); + let is_authorized = pre_states[0].is_authorized; + if account_to_claim == Account::default() && balance_to_move == 0 && is_authorized { + write_nssa_outputs(pre_states, vec![account_to_claim]); + } else { + panic!("Invalid params"); + } + } else { + // Transfer - // Continue only if the sender has authorized this operation - if !sender.is_authorized { - return; + // Continue only if input_accounts is an array of two elements + let [sender, receiver] = match pre_states.try_into() { + Ok(array) => array, + Err(_) => return, + }; + + // Continue only if the sender has authorized this operation + if !sender.is_authorized { + return; + } + + // Continue only if the sender has enough balance + if sender.account.balance < balance_to_move { + return; + } + + // Create accounts post states, with updated balances + let mut sender_post = sender.account.clone(); + let mut receiver_post = receiver.account.clone(); + sender_post.balance -= balance_to_move; + receiver_post.balance += balance_to_move; + + write_nssa_outputs(vec![sender, receiver], vec![sender_post, receiver_post]); } - - // Continue only if the sender has enough balance - if sender.account.balance < balance_to_move { - return; - } - - // Create accounts post states, with updated balances - let mut sender_post = sender.account.clone(); - let mut receiver_post = receiver.account.clone(); - sender_post.balance -= balance_to_move; - receiver_post.balance += balance_to_move; - - write_nssa_outputs(vec![sender, receiver], vec![sender_post, receiver_post]); } - diff --git a/wallet/src/lib.rs b/wallet/src/lib.rs index 0e8b1cb..f0fcefc 100644 --- a/wallet/src/lib.rs +++ b/wallet/src/lib.rs @@ -377,6 +377,7 @@ pub enum Command { #[arg(long)] solution: u128, }, + RegisterAccountForAuthenticatedTransfer {}, } ///To execute commands, env var NSSA_WALLET_HOME_DIR must be set into directory with config @@ -845,6 +846,25 @@ pub async fn execute_subcommand(command: Command) -> Result { + let addr = wallet_core.create_new_account_public(); + + println!("Generated new account with addr {addr}"); + + let path = wallet_core.store_persistent_accounts()?; + + println!("Stored persistent accounts at {path:#?}"); + + let res = wallet_core + .register_account_under_authenticated_transfers_programs(addr) + .await?; + + println!("Results of tx send is {res:#?}"); + + let _transfer_tx = wallet_core.poll_native_token_transfer(res.tx_hash).await?; + SubcommandReturnValue::Empty } }; diff --git a/wallet/src/token_transfers/public.rs b/wallet/src/token_transfers/public.rs index 22d50eb..80db91d 100644 --- a/wallet/src/token_transfers/public.rs +++ b/wallet/src/token_transfers/public.rs @@ -42,4 +42,30 @@ impl WalletCore { Err(ExecutionFailureKind::InsufficientFundsError) } } + + pub async fn register_account_under_authenticated_transfers_programs( + &self, + from: Address, + ) -> Result { + let Ok(nonces) = self.get_accounts_nonces(vec![from]).await else { + return Err(ExecutionFailureKind::SequencerError); + }; + + let instruction:u128 = 0; + let addresses = vec![from]; + let program_id = Program::authenticated_transfer_program().id(); + let message = Message::try_new(program_id, addresses, nonces, instruction).unwrap(); + + let signing_key = self.storage.user_data.get_pub_account_signing_key(&from); + + let Some(signing_key) = signing_key else { + return Err(ExecutionFailureKind::KeyNotFoundError); + }; + + let witness_set = WitnessSet::for_message(&message, &[signing_key]); + + let tx = PublicTransaction::new(message, witness_set); + + Ok(self.sequencer_client.send_tx_public(tx).await?) + } }