use crate::chainsig::get_network_by_account_id; use crate::helpers::decoder::{ parse_and_validate_transaction, parse_near_transaction, parse_transaction, validate_input, Action, }; use crate::permission::types::*; use crate::*; use near_sdk::{env, Gas, NearToken, Promise}; impl Contract { /// Execute chain signature transaction via proposal system /// Signs and executes cross-chain transactions using NEAR's chain signatures pub fn internal_execute_sign_chain_sig( &mut self, function_args: &serde_json::Value, policy_details: ChainSigTransactionConfig, ) -> Promise { let encoded_tx = function_args.as_str().unwrap(); let near_native_transaction_config = NearNativeTransactionConfig { restrictions: policy_details.restrictions, chain_environment: policy_details.chain_environment.clone(), }; let transaction_runnable = parse_and_validate_transaction( &encoded_tx.to_owned(), &near_native_transaction_config, env::current_account_id(), ); if transaction_runnable == false { panic!("Transaction is not runnable."); }; self.sign_transaction( encoded_tx.to_owned(), policy_details.chain_environment, &get_network_by_account_id(&env::current_account_id()), policy_details.derivation_path, ) } /// Execute chain signature message signing via proposal system /// Signs messages for cross-chain verification (e.g., NEP-413 intents) pub fn internal_execute_sign_message( &mut self, function_args: &serde_json::Value, policy_details: ChainSigMessageConfig, ) -> Promise { match policy_details.sign_method { ChainSigSignMethod::NearIntentsSwap => { let nep_413: NEP413 = serde_json::from_str(function_args.as_str().unwrap()).unwrap(); let swap_intent_msg: SwapIntentMessage = serde_json::from_str(&nep_413.message) .expect("Unable to parse message as intent message"); swap_intent_msg.intents.iter().for_each(|intent| { if intent.intent != "token_diff" { panic!("Intent must be token_diff, not {}", intent.intent); } }); self.sign_near_nep413_message( policy_details.derivation_path, &get_network_by_account_id(&env::current_account_id()), nep_413.message, nep_413.recipient, nep_413.nonce.try_into().unwrap(), nep_413.callback_url, ) } } } /// Execute NEAR native transaction via proposal system /// Executes function calls on NEAR contracts with policy-based restrictions pub fn internal_execute_near_native_transaction( &mut self, function_args: &serde_json::Value, policy_details: NearNativeTransactionConfig, ) -> Promise { let encoded_tx = function_args.as_str().unwrap(); let tx = parse_near_transaction(&encoded_tx.to_owned()); let transaction_inputs = parse_transaction(&encoded_tx.to_owned(), &policy_details); let transaction_runnable_result = validate_input( &transaction_inputs, &policy_details.restrictions, env::current_account_id(), ); if transaction_runnable_result.as_ref().is_err() == true { panic!("{}", transaction_runnable_result.as_ref().unwrap_err()); } let transaction_runnable = transaction_runnable_result.unwrap(); if transaction_runnable == false { panic!("Transaction is not runnable."); }; let mut promises: Vec = vec![]; tx.actions().iter().for_each(|action| match action { Action::FunctionCall(function_call_action) => { promises.push(Promise::new(tx.receiver_id().clone()).function_call( function_call_action.method_name.clone(), function_call_action.args.clone(), NearToken::from_yoctonear(function_call_action.deposit), Gas::from_gas(function_call_action.gas), )) } _ => { panic!("Expect function call only"); } }); promises .into_iter() .reduce(|prev, cur| prev.and(cur)) .unwrap() } }