From b61aed7250cab5955f748bef7c54e0b90c0dd42f Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Mon, 25 Mar 2019 20:57:25 -0600 Subject: [PATCH] Minor cleanup --- programs/budget_api/src/budget_instruction.rs | 56 ++-- .../exchange_api/src/exchange_instruction.rs | 8 + programs/token_api/src/token_state.rs | 269 ++++++++---------- programs/vote_api/src/vote_instruction.rs | 17 +- sdk/src/system_instruction.rs | 6 + 5 files changed, 171 insertions(+), 185 deletions(-) diff --git a/programs/budget_api/src/budget_instruction.rs b/programs/budget_api/src/budget_instruction.rs index 562c61b50..371308f51 100644 --- a/programs/budget_api/src/budget_instruction.rs +++ b/programs/budget_api/src/budget_instruction.rs @@ -32,7 +32,7 @@ pub enum BudgetInstruction { } impl BudgetInstruction { - pub fn new_initialize_account(contract: &Pubkey, expr: BudgetExpr) -> Instruction { + fn new_initialize_account(contract: &Pubkey, expr: BudgetExpr) -> Instruction { let mut keys = vec![]; if let BudgetExpr::Pay(payment) = &expr { keys.push(AccountMeta::new(payment.to, false)); @@ -41,33 +41,6 @@ impl BudgetInstruction { Instruction::new(id(), &BudgetInstruction::InitializeAccount(expr), keys) } - pub fn new_apply_timestamp( - from: &Pubkey, - contract: &Pubkey, - to: &Pubkey, - dt: DateTime, - ) -> Instruction { - let mut account_metas = vec![ - AccountMeta::new(*from, true), - AccountMeta::new(*contract, false), - ]; - if from != to { - account_metas.push(AccountMeta::new(*to, false)); - } - Instruction::new(id(), &BudgetInstruction::ApplyTimestamp(dt), account_metas) - } - - pub fn new_apply_signature(from: &Pubkey, contract: &Pubkey, to: &Pubkey) -> Instruction { - let mut account_metas = vec![ - AccountMeta::new(*from, true), - AccountMeta::new(*contract, false), - ]; - if from != to { - account_metas.push(AccountMeta::new(*to, false)); - } - Instruction::new(id(), &BudgetInstruction::ApplySignature, account_metas) - } - pub fn new_account( from: &Pubkey, contract: &Pubkey, @@ -118,6 +91,33 @@ impl BudgetInstruction { let expr = BudgetExpr::new_cancelable_authorized_payment(witness, lamports, to, cancelable); Self::new_account(from, contract, lamports, expr) } + + pub fn new_apply_timestamp( + from: &Pubkey, + contract: &Pubkey, + to: &Pubkey, + dt: DateTime, + ) -> Instruction { + let mut account_metas = vec![ + AccountMeta::new(*from, true), + AccountMeta::new(*contract, false), + ]; + if from != to { + account_metas.push(AccountMeta::new(*to, false)); + } + Instruction::new(id(), &BudgetInstruction::ApplyTimestamp(dt), account_metas) + } + + pub fn new_apply_signature(from: &Pubkey, contract: &Pubkey, to: &Pubkey) -> Instruction { + let mut account_metas = vec![ + AccountMeta::new(*from, true), + AccountMeta::new(*contract, false), + ]; + if from != to { + account_metas.push(AccountMeta::new(*to, false)); + } + Instruction::new(id(), &BudgetInstruction::ApplySignature, account_metas) + } } #[cfg(test)] diff --git a/programs/exchange_api/src/exchange_instruction.rs b/programs/exchange_api/src/exchange_instruction.rs index 9040781e3..4d9efd30a 100644 --- a/programs/exchange_api/src/exchange_instruction.rs +++ b/programs/exchange_api/src/exchange_instruction.rs @@ -10,13 +10,17 @@ use solana_sdk::pubkey::Pubkey; pub struct TradeRequestInfo { /// Direction of trade pub direction: Direction, + /// Token pair to trade pub pair: TokenPair, + /// Number of tokens to exchange; refers to the primary or the secondary depending on the direction pub tokens: u64, + /// The price ratio the primary price over the secondary price. The primary price is fixed /// and equal to the variable `SCALER`. pub price: u64, + /// Token account to deposit tokens on successful swap pub dst_account: Pubkey, } @@ -27,20 +31,24 @@ pub enum ExchangeInstruction { /// key 0 - Signer /// key 1 - New token account AccountRequest, + /// Transfer tokens between two accounts /// key 0 - Account to transfer tokens to /// key 1 - Account to transfer tokens from. This can be the exchange program itself, /// the exchange has a limitless number of tokens it can transfer. TransferRequest(Token, u64), + /// Trade request /// key 0 - Signer /// key 1 - Account in which to record the swap /// key 2 - Token account associated with this trade TradeRequest(TradeRequestInfo), + /// Trade cancellation /// key 0 - Signer /// key 1 -Ttrade order to cancel TradeCancellation, + /// Trade swap request /// key 0 - Signer /// key 1 - Account in which to record the swap diff --git a/programs/token_api/src/token_state.rs b/programs/token_api/src/token_state.rs index cbf7a82bb..7a205c27c 100644 --- a/programs/token_api/src/token_state.rs +++ b/programs/token_api/src/token_state.rs @@ -1,89 +1,67 @@ -use bincode; use log::*; use serde_derive::{Deserialize, Serialize}; use solana_sdk::account::KeyedAccount; use solana_sdk::pubkey::Pubkey; -use std; #[derive(Serialize, Debug, PartialEq)] -pub enum Error { +pub enum TokenError { InvalidArgument, InsufficentFunds, NotOwner, } -impl std::fmt::Display for Error { +impl std::fmt::Display for TokenError { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!(f, "error") } } -impl std::error::Error for Error {} +impl std::error::Error for TokenError {} -pub type Result = std::result::Result; +pub type Result = std::result::Result; #[derive(Debug, Default, Serialize, Deserialize, PartialEq)] pub struct TokenInfo { - /** - * Total supply of tokens - */ + /// Total supply of tokens supply: u64, - /** - * Number of base 10 digits to the right of the decimal place in the total supply - */ + /// Number of base 10 digits to the right of the decimal place in the total supply decimals: u8, - /** - * Descriptive name of this token - */ + /// Descriptive name of this token name: String, - /** - * Symbol for this token - */ + /// Symbol for this token symbol: String, } #[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq)] pub struct TokenAccountDelegateInfo { - /** - * The source account for the tokens - */ + /// The source account for the tokens source: Pubkey, - /** - * The original amount that this delegate account was authorized to spend up to - */ + /// The original amount that this delegate account was authorized to spend up to original_amount: u64, } #[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq)] pub struct TokenAccountInfo { - /** - * The kind of token this account holds - */ + /// The kind of token this account holds token: Pubkey, - /** - * Owner of this account - */ + /// Owner of this account owner: Pubkey, - /** - * Amount of tokens this account holds - */ + /// Amount of tokens this account holds amount: u64, - /** - * If `delegate` None, `amount` belongs to this account. - * If `delegate` is Option<_>, `amount` represents the remaining allowance - * of tokens that may be transferred from the `source` account. - */ + /// If `delegate` None, `amount` belongs to this account. + /// If `delegate` is Option<_>, `amount` represents the remaining allowance + /// of tokens that may be transferred from the `source` account. delegate: Option, } #[derive(Debug, Serialize, Deserialize, PartialEq)] -enum Command { +enum TokenInstruction { NewToken(TokenInfo), NewTokenAccount, Transfer(u64), @@ -106,14 +84,14 @@ impl Default for TokenState { impl TokenState { #[allow(clippy::needless_pass_by_value)] - fn map_to_invalid_args(err: std::boxed::Box) -> Error { + fn map_to_invalid_args(err: std::boxed::Box) -> TokenError { warn!("invalid argument: {:?}", err); - Error::InvalidArgument + TokenError::InvalidArgument } pub fn deserialize(input: &[u8]) -> Result { if input.is_empty() { - Err(Error::InvalidArgument)?; + Err(TokenError::InvalidArgument)?; } match input[0] { 0 => Ok(TokenState::Unallocated), @@ -123,17 +101,17 @@ impl TokenState { 2 => Ok(TokenState::Account( bincode::deserialize(&input[1..]).map_err(Self::map_to_invalid_args)?, )), - _ => Err(Error::InvalidArgument), + _ => Err(TokenError::InvalidArgument), } } fn serialize(self: &TokenState, output: &mut [u8]) -> Result<()> { if output.is_empty() { warn!("serialize fail: ouput.len is 0"); - Err(Error::InvalidArgument)?; + Err(TokenError::InvalidArgument)?; } match self { - TokenState::Unallocated | TokenState::Invalid => Err(Error::InvalidArgument), + TokenState::Unallocated | TokenState::Invalid => Err(TokenError::InvalidArgument), TokenState::Token(token_info) => { output[0] = 1; let writer = std::io::BufWriter::new(&mut output[1..]); @@ -152,7 +130,7 @@ impl TokenState { if let TokenState::Account(account_info) = self { Ok(account_info.amount) } else { - Err(Error::InvalidArgument) + Err(TokenError::InvalidArgument) } } @@ -166,63 +144,63 @@ impl TokenState { } } warn!("TokenState: non-owner rejected"); - Err(Error::NotOwner) + Err(TokenError::NotOwner) } - pub fn process_command_newtoken( + pub fn process_newtoken( info: &mut [KeyedAccount], token_info: TokenInfo, - input_program_accounts: &[TokenState], - output_program_accounts: &mut Vec<(usize, TokenState)>, + input_accounts: &[TokenState], + output_accounts: &mut Vec<(usize, TokenState)>, ) -> Result<()> { - if input_program_accounts.len() != 2 { + if input_accounts.len() != 2 { error!("Expected 2 accounts"); - Err(Error::InvalidArgument)?; + Err(TokenError::InvalidArgument)?; } - if let TokenState::Account(dest_account) = &input_program_accounts[1] { + if let TokenState::Account(dest_account) = &input_accounts[1] { if info[0].signer_key().unwrap() != &dest_account.token { error!("account 1 token mismatch"); - Err(Error::InvalidArgument)?; + Err(TokenError::InvalidArgument)?; } if dest_account.delegate.is_some() { error!("account 1 is a delegate and cannot accept tokens"); - Err(Error::InvalidArgument)?; + Err(TokenError::InvalidArgument)?; } let mut output_dest_account = dest_account.clone(); output_dest_account.amount = token_info.supply; - output_program_accounts.push((1, TokenState::Account(output_dest_account))); + output_accounts.push((1, TokenState::Account(output_dest_account))); } else { error!("account 1 invalid"); - Err(Error::InvalidArgument)?; + Err(TokenError::InvalidArgument)?; } - if input_program_accounts[0] != TokenState::Unallocated { + if input_accounts[0] != TokenState::Unallocated { error!("account 0 not available"); - Err(Error::InvalidArgument)?; + Err(TokenError::InvalidArgument)?; } - output_program_accounts.push((0, TokenState::Token(token_info))); + output_accounts.push((0, TokenState::Token(token_info))); Ok(()) } - pub fn process_command_newaccount( + pub fn process_newaccount( info: &mut [KeyedAccount], - input_program_accounts: &[TokenState], - output_program_accounts: &mut Vec<(usize, TokenState)>, + input_accounts: &[TokenState], + output_accounts: &mut Vec<(usize, TokenState)>, ) -> Result<()> { // key 0 - Destination new token account // key 1 - Owner of the account // key 2 - Token this account is associated with // key 3 - Source account that this account is a delegate for (optional) - if input_program_accounts.len() < 3 { + if input_accounts.len() < 3 { error!("Expected 3 accounts"); - Err(Error::InvalidArgument)?; + Err(TokenError::InvalidArgument)?; } - if input_program_accounts[0] != TokenState::Unallocated { + if input_accounts[0] != TokenState::Unallocated { error!("account 0 is already allocated"); - Err(Error::InvalidArgument)?; + Err(TokenError::InvalidArgument)?; } let mut token_account_info = TokenAccountInfo { token: *info[2].unsigned_key(), @@ -230,131 +208,131 @@ impl TokenState { amount: 0, delegate: None, }; - if input_program_accounts.len() >= 4 { + if input_accounts.len() >= 4 { token_account_info.delegate = Some(TokenAccountDelegateInfo { source: *info[3].unsigned_key(), original_amount: 0, }); } - output_program_accounts.push((0, TokenState::Account(token_account_info))); + output_accounts.push((0, TokenState::Account(token_account_info))); Ok(()) } - pub fn process_command_transfer( + pub fn process_transfer( info: &mut [KeyedAccount], amount: u64, - input_program_accounts: &[TokenState], - output_program_accounts: &mut Vec<(usize, TokenState)>, + input_accounts: &[TokenState], + output_accounts: &mut Vec<(usize, TokenState)>, ) -> Result<()> { - if input_program_accounts.len() < 3 { + if input_accounts.len() < 3 { error!("Expected 3 accounts"); - Err(Error::InvalidArgument)?; + Err(TokenError::InvalidArgument)?; } if let (TokenState::Account(source_account), TokenState::Account(dest_account)) = - (&input_program_accounts[1], &input_program_accounts[2]) + (&input_accounts[1], &input_accounts[2]) { if source_account.token != dest_account.token { error!("account 1/2 token mismatch"); - Err(Error::InvalidArgument)?; + Err(TokenError::InvalidArgument)?; } if dest_account.delegate.is_some() { error!("account 2 is a delegate and cannot accept tokens"); - Err(Error::InvalidArgument)?; + Err(TokenError::InvalidArgument)?; } if info[0].signer_key().unwrap() != &source_account.owner { error!("owner of account 1 not present"); - Err(Error::InvalidArgument)?; + Err(TokenError::InvalidArgument)?; } if source_account.amount < amount { - Err(Error::InsufficentFunds)?; + Err(TokenError::InsufficentFunds)?; } let mut output_source_account = source_account.clone(); output_source_account.amount -= amount; - output_program_accounts.push((1, TokenState::Account(output_source_account))); + output_accounts.push((1, TokenState::Account(output_source_account))); if let Some(ref delegate_info) = source_account.delegate { - if input_program_accounts.len() != 4 { + if input_accounts.len() != 4 { error!("Expected 4 accounts"); - Err(Error::InvalidArgument)?; + Err(TokenError::InvalidArgument)?; } let delegate_account = source_account; - if let TokenState::Account(source_account) = &input_program_accounts[3] { + if let TokenState::Account(source_account) = &input_accounts[3] { if source_account.token != delegate_account.token { error!("account 1/3 token mismatch"); - Err(Error::InvalidArgument)?; + Err(TokenError::InvalidArgument)?; } if info[3].unsigned_key() != &delegate_info.source { error!("Account 1 is not a delegate of account 3"); - Err(Error::InvalidArgument)?; + Err(TokenError::InvalidArgument)?; } if source_account.amount < amount { - Err(Error::InsufficentFunds)?; + Err(TokenError::InsufficentFunds)?; } let mut output_source_account = source_account.clone(); output_source_account.amount -= amount; - output_program_accounts.push((3, TokenState::Account(output_source_account))); + output_accounts.push((3, TokenState::Account(output_source_account))); } else { error!("account 3 is an invalid account"); - Err(Error::InvalidArgument)?; + Err(TokenError::InvalidArgument)?; } } let mut output_dest_account = dest_account.clone(); output_dest_account.amount += amount; - output_program_accounts.push((2, TokenState::Account(output_dest_account))); + output_accounts.push((2, TokenState::Account(output_dest_account))); } else { error!("account 1 and/or 2 are invalid accounts"); - Err(Error::InvalidArgument)?; + Err(TokenError::InvalidArgument)?; } Ok(()) } - pub fn process_command_approve( + pub fn process_approve( info: &mut [KeyedAccount], amount: u64, - input_program_accounts: &[TokenState], - output_program_accounts: &mut Vec<(usize, TokenState)>, + input_accounts: &[TokenState], + output_accounts: &mut Vec<(usize, TokenState)>, ) -> Result<()> { - if input_program_accounts.len() != 3 { + if input_accounts.len() != 3 { error!("Expected 3 accounts"); - Err(Error::InvalidArgument)?; + Err(TokenError::InvalidArgument)?; } if let (TokenState::Account(source_account), TokenState::Account(delegate_account)) = - (&input_program_accounts[1], &input_program_accounts[2]) + (&input_accounts[1], &input_accounts[2]) { if source_account.token != delegate_account.token { error!("account 1/2 token mismatch"); - Err(Error::InvalidArgument)?; + Err(TokenError::InvalidArgument)?; } if info[0].signer_key().unwrap() != &source_account.owner { error!("owner of account 1 not present"); - Err(Error::InvalidArgument)?; + Err(TokenError::InvalidArgument)?; } if source_account.delegate.is_some() { error!("account 1 is a delegate"); - Err(Error::InvalidArgument)?; + Err(TokenError::InvalidArgument)?; } match &delegate_account.delegate { None => { error!("account 2 is not a delegate"); - Err(Error::InvalidArgument)?; + Err(TokenError::InvalidArgument)?; } Some(delegate_info) => { if info[1].unsigned_key() != &delegate_info.source { error!("account 2 is not a delegate of account 1"); - Err(Error::InvalidArgument)?; + Err(TokenError::InvalidArgument)?; } let mut output_delegate_account = delegate_account.clone(); @@ -363,57 +341,58 @@ impl TokenState { source: delegate_info.source, original_amount: amount, }); - output_program_accounts.push((2, TokenState::Account(output_delegate_account))); + output_accounts.push((2, TokenState::Account(output_delegate_account))); } } } else { error!("account 1 and/or 2 are invalid accounts"); - Err(Error::InvalidArgument)?; + Err(TokenError::InvalidArgument)?; } Ok(()) } - pub fn process_command_setowner( + pub fn process_setowner( info: &mut [KeyedAccount], - input_program_accounts: &[TokenState], - output_program_accounts: &mut Vec<(usize, TokenState)>, + input_accounts: &[TokenState], + output_accounts: &mut Vec<(usize, TokenState)>, ) -> Result<()> { - if input_program_accounts.len() < 3 { + if input_accounts.len() < 3 { error!("Expected 3 accounts"); - Err(Error::InvalidArgument)?; + Err(TokenError::InvalidArgument)?; } - if let TokenState::Account(source_account) = &input_program_accounts[1] { + if let TokenState::Account(source_account) = &input_accounts[1] { if info[0].signer_key().unwrap() != &source_account.owner { info!("owner of account 1 not present"); - Err(Error::InvalidArgument)?; + Err(TokenError::InvalidArgument)?; } let mut output_source_account = source_account.clone(); output_source_account.owner = *info[2].unsigned_key(); - output_program_accounts.push((1, TokenState::Account(output_source_account))); + output_accounts.push((1, TokenState::Account(output_source_account))); } else { info!("account 1 is invalid"); - Err(Error::InvalidArgument)?; + Err(TokenError::InvalidArgument)?; } Ok(()) } pub fn process(program_id: &Pubkey, info: &mut [KeyedAccount], input: &[u8]) -> Result<()> { - let command = bincode::deserialize::(input).map_err(Self::map_to_invalid_args)?; + let command = + bincode::deserialize::(input).map_err(Self::map_to_invalid_args)?; info!("process_transaction: command={:?}", command); if info[0].signer_key().is_none() { - Err(Error::InvalidArgument)?; + Err(TokenError::InvalidArgument)?; } - let input_program_accounts: Vec = info + let input_accounts: Vec = info .iter() .map(|keyed_account| { let account = &keyed_account.account; if account.owner == *program_id { match Self::deserialize(&account.data) { - Ok(token_program) => token_program, + Ok(token_state) => token_state, Err(err) => { error!("deserialize failed: {:?}", err); TokenState::Invalid @@ -425,52 +404,36 @@ impl TokenState { }) .collect(); - for program_account in &input_program_accounts { - info!("input_program_account: data={:?}", program_account); + for account in &input_accounts { + info!("input_account: data={:?}", account); } - let mut output_program_accounts: Vec<(_, _)> = vec![]; + let mut output_accounts: Vec<(_, _)> = vec![]; match command { - Command::NewToken(token_info) => Self::process_command_newtoken( - info, - token_info, - &input_program_accounts, - &mut output_program_accounts, - )?, - Command::NewTokenAccount => Self::process_command_newaccount( - info, - &input_program_accounts, - &mut output_program_accounts, - )?, + TokenInstruction::NewToken(token_info) => { + Self::process_newtoken(info, token_info, &input_accounts, &mut output_accounts)? + } + TokenInstruction::NewTokenAccount => { + Self::process_newaccount(info, &input_accounts, &mut output_accounts)? + } - Command::Transfer(amount) => Self::process_command_transfer( - info, - amount, - &input_program_accounts, - &mut output_program_accounts, - )?, + TokenInstruction::Transfer(amount) => { + Self::process_transfer(info, amount, &input_accounts, &mut output_accounts)? + } - Command::Approve(amount) => Self::process_command_approve( - info, - amount, - &input_program_accounts, - &mut output_program_accounts, - )?, + TokenInstruction::Approve(amount) => { + Self::process_approve(info, amount, &input_accounts, &mut output_accounts)? + } - Command::SetOwner => Self::process_command_setowner( - info, - &input_program_accounts, - &mut output_program_accounts, - )?, + TokenInstruction::SetOwner => { + Self::process_setowner(info, &input_accounts, &mut output_accounts)? + } } - for (index, program_account) in &output_program_accounts { - info!( - "output_program_account: index={} data={:?}", - index, program_account - ); - Self::serialize(program_account, &mut info[*index].account.data)?; + for (index, account) in &output_accounts { + info!("output_account: index={} data={:?}", index, account); + Self::serialize(account, &mut info[*index].account.data)?; } Ok(()) } diff --git a/programs/vote_api/src/vote_instruction.rs b/programs/vote_api/src/vote_instruction.rs index 610701aab..8f3f11d28 100644 --- a/programs/vote_api/src/vote_instruction.rs +++ b/programs/vote_api/src/vote_instruction.rs @@ -23,17 +23,26 @@ pub enum VoteInstruction { /// Initialize the VoteState for this `vote account` /// * Instruction::keys[0] - the new "vote account" to be associated with the delegate InitializeAccount, + /// `Delegate` or `Assign` a vote account to a particular node DelegateStake(Pubkey), + /// Authorize a voter to send signed votes. AuthorizeVoter(Pubkey), + Vote(Vote), + /// Clear the credits in the vote account /// * Transaction::keys[0] - the "vote account" ClearCredits, } impl VoteInstruction { + fn new_initialize_account(vote_id: &Pubkey) -> Instruction { + let account_metas = vec![AccountMeta::new(*vote_id, false)]; + Instruction::new(id(), &VoteInstruction::InitializeAccount, account_metas) + } + pub fn new_account(from_id: &Pubkey, staker_id: &Pubkey, lamports: u64) -> Vec { let space = VoteState::max_size() as u64; let create_ix = @@ -41,10 +50,12 @@ impl VoteInstruction { let init_ix = VoteInstruction::new_initialize_account(staker_id); vec![create_ix, init_ix] } + pub fn new_clear_credits(vote_id: &Pubkey) -> Instruction { let account_metas = vec![AccountMeta::new(*vote_id, true)]; Instruction::new(id(), &VoteInstruction::ClearCredits, account_metas) } + pub fn new_delegate_stake(vote_id: &Pubkey, delegate_id: &Pubkey) -> Instruction { let account_metas = vec![AccountMeta::new(*vote_id, true)]; Instruction::new( @@ -53,6 +64,7 @@ impl VoteInstruction { account_metas, ) } + pub fn new_authorize_voter(vote_id: &Pubkey, authorized_voter_id: &Pubkey) -> Instruction { let account_metas = vec![AccountMeta::new(*vote_id, true)]; Instruction::new( @@ -61,10 +73,7 @@ impl VoteInstruction { account_metas, ) } - pub fn new_initialize_account(vote_id: &Pubkey) -> Instruction { - let account_metas = vec![AccountMeta::new(*vote_id, false)]; - Instruction::new(id(), &VoteInstruction::InitializeAccount, account_metas) - } + pub fn new_vote(vote_id: &Pubkey, vote: Vote) -> Instruction { let account_metas = vec![AccountMeta::new(*vote_id, true)]; Instruction::new(id(), &VoteInstruction::Vote(vote), account_metas) diff --git a/sdk/src/system_instruction.rs b/sdk/src/system_instruction.rs index ea25aafc3..995fc5a5d 100644 --- a/sdk/src/system_instruction.rs +++ b/sdk/src/system_instruction.rs @@ -54,6 +54,12 @@ impl SystemInstruction { ) } + /// Create and sign a transaction to create a system account + pub fn new_account(from_id: &Pubkey, to_id: &Pubkey, lamports: u64) -> Instruction { + let program_id = system_program::id(); + Self::new_program_account(from_id, to_id, lamports, 0, &program_id) + } + pub fn new_assign(from_id: &Pubkey, program_id: &Pubkey) -> Instruction { let account_metas = vec![AccountMeta::new(*from_id, true)]; Instruction::new(