diff --git a/programs/budget/src/budget_processor.rs b/programs/budget/src/budget_processor.rs index d3a2a9b4da..feb0f227f9 100644 --- a/programs/budget/src/budget_processor.rs +++ b/programs/budget/src/budget_processor.rs @@ -144,6 +144,7 @@ pub fn process_instruction( mod test { use super::*; use solana_budget_api::budget_instruction::BudgetInstruction; + use solana_budget_api::budget_script::BudgetScript; use solana_budget_api::id; use solana_runtime::bank::Bank; use solana_runtime::bank_client::BankClient; @@ -164,7 +165,7 @@ mod test { let alice_client = BankClient::new(&bank, mint_keypair); let alice_pubkey = alice_client.pubkey(); let bob_pubkey = Keypair::new().pubkey(); - let script = BudgetInstruction::new_payment_script(&alice_pubkey, &bob_pubkey, 100); + let script = BudgetScript::pay(&alice_pubkey, &bob_pubkey, 100); alice_client.process_script(script).unwrap(); assert_eq!(bank.get_balance(&bob_pubkey), 100); } @@ -179,7 +180,7 @@ mod test { let budget_pubkey = Keypair::new().pubkey(); let bob_pubkey = Keypair::new().pubkey(); let witness = Keypair::new().pubkey(); - let script = BudgetInstruction::new_when_signed_script( + let script = BudgetScript::pay_on_signature( &alice_pubkey, &bob_pubkey, &budget_pubkey, @@ -221,7 +222,7 @@ mod test { let budget_pubkey = Keypair::new().pubkey(); let bob_pubkey = Keypair::new().pubkey(); let dt = Utc::now(); - let script = BudgetInstruction::new_on_date_script( + let script = BudgetScript::pay_on_date( &alice_pubkey, &bob_pubkey, &budget_pubkey, @@ -259,7 +260,7 @@ mod test { } #[test] - fn test_transfer_on_date() { + fn test_pay_on_date() { let (bank, mint_keypair) = create_bank(2); let alice_client = BankClient::new(&bank, mint_keypair); let alice_pubkey = alice_client.pubkey(); @@ -267,7 +268,7 @@ mod test { let bob_pubkey = Keypair::new().pubkey(); let mallory_pubkey = Keypair::new().pubkey(); let dt = Utc::now(); - let script = BudgetInstruction::new_on_date_script( + let script = BudgetScript::pay_on_date( &alice_pubkey, &bob_pubkey, &budget_pubkey, @@ -320,7 +321,7 @@ mod test { } #[test] - fn test_cancel_transfer() { + fn test_cancel_payment() { let (bank, mint_keypair) = create_bank(3); let alice_client = BankClient::new(&bank, mint_keypair); let alice_pubkey = alice_client.pubkey(); @@ -328,7 +329,7 @@ mod test { let bob_pubkey = Keypair::new().pubkey(); let dt = Utc::now(); - let script = BudgetInstruction::new_on_date_script( + let script = BudgetScript::pay_on_date( &alice_pubkey, &bob_pubkey, &budget_pubkey, diff --git a/programs/budget_api/src/budget_instruction.rs b/programs/budget_api/src/budget_instruction.rs index 42a950af59..71be56c6dd 100644 --- a/programs/budget_api/src/budget_instruction.rs +++ b/programs/budget_api/src/budget_instruction.rs @@ -1,13 +1,8 @@ -use crate::budget_expr::{BudgetExpr, Condition}; -use crate::budget_state::BudgetState; +use crate::budget_expr::BudgetExpr; use crate::id; -use bincode::serialized_size; use chrono::prelude::{DateTime, Utc}; use serde_derive::{Deserialize, Serialize}; use solana_sdk::pubkey::Pubkey; -use solana_sdk::script::Script; -use solana_sdk::signature::{Keypair, KeypairUtil}; -use solana_sdk::system_instruction::SystemInstruction; use solana_sdk::transaction::Instruction; /// A smart contract. @@ -42,87 +37,6 @@ impl BudgetInstruction { Instruction::new(id(), &BudgetInstruction::InitializeAccount(expr), keys) } - pub fn new_initialize_account_script( - from: &Pubkey, - contract: &Pubkey, - lamports: u64, - expr: BudgetExpr, - ) -> Script { - let space = serialized_size(&BudgetState::new(expr.clone())).unwrap(); - Script::new(vec![ - SystemInstruction::new_program_account(&from, contract, lamports, space, &id()), - Self::new_initialize_account(contract, expr), - ]) - } - - /// Create a new payment script. - pub fn new_payment_script(from: &Pubkey, to: &Pubkey, lamports: u64) -> Script { - let contract = Keypair::new().pubkey(); - let expr = BudgetExpr::new_payment(lamports, to); - Self::new_initialize_account_script(from, &contract, lamports, expr) - } - - /// Create a postdated payment script. - pub fn new_on_date_script( - from: &Pubkey, - to: &Pubkey, - contract: &Pubkey, - dt: DateTime, - dt_pubkey: &Pubkey, - cancelable: Option, - lamports: u64, - ) -> Script { - let expr = if let Some(from) = cancelable { - BudgetExpr::Or( - ( - Condition::Timestamp(dt, *dt_pubkey), - Box::new(BudgetExpr::new_payment(lamports, to)), - ), - ( - Condition::Signature(from), - Box::new(BudgetExpr::new_payment(lamports, &from)), - ), - ) - } else { - BudgetExpr::After( - Condition::Timestamp(dt, *dt_pubkey), - Box::new(BudgetExpr::new_payment(lamports, to)), - ) - }; - - Self::new_initialize_account_script(from, contract, lamports, expr) - } - - /// Create a multisig payment script. - pub fn new_when_signed_script( - from: &Pubkey, - to: &Pubkey, - contract: &Pubkey, - witness: &Pubkey, - cancelable: Option, - lamports: u64, - ) -> Script { - let expr = if let Some(from) = cancelable { - BudgetExpr::Or( - ( - Condition::Signature(*witness), - Box::new(BudgetExpr::new_payment(lamports, to)), - ), - ( - Condition::Signature(from), - Box::new(BudgetExpr::new_payment(lamports, &from)), - ), - ) - } else { - BudgetExpr::After( - Condition::Signature(*witness), - Box::new(BudgetExpr::new_payment(lamports, to)), - ) - }; - - Self::new_initialize_account_script(from, contract, lamports, expr) - } - pub fn new_apply_timestamp( from: &Pubkey, contract: &Pubkey, diff --git a/programs/budget_api/src/budget_script.rs b/programs/budget_api/src/budget_script.rs new file mode 100644 index 0000000000..ce6321d13f --- /dev/null +++ b/programs/budget_api/src/budget_script.rs @@ -0,0 +1,96 @@ +use crate::budget_expr::{BudgetExpr, Condition}; +use crate::budget_instruction::BudgetInstruction; +use crate::budget_state::BudgetState; +use crate::id; +use bincode::serialized_size; +use chrono::prelude::{DateTime, Utc}; +use solana_sdk::pubkey::Pubkey; +use solana_sdk::script::Script; +use solana_sdk::signature::{Keypair, KeypairUtil}; +use solana_sdk::system_instruction::SystemInstruction; + +pub struct BudgetScript {} + +impl BudgetScript { + pub fn new_account( + from: &Pubkey, + contract: &Pubkey, + lamports: u64, + expr: BudgetExpr, + ) -> Script { + let space = serialized_size(&BudgetState::new(expr.clone())).unwrap(); + let instructions = vec![ + SystemInstruction::new_program_account(&from, contract, lamports, space, &id()), + BudgetInstruction::new_initialize_account(contract, expr), + ]; + Script::new(instructions) + } + + /// Create a new payment script. + pub fn pay(from: &Pubkey, to: &Pubkey, lamports: u64) -> Script { + let contract = Keypair::new().pubkey(); + let expr = BudgetExpr::new_payment(lamports, to); + Self::new_account(from, &contract, lamports, expr) + } + + /// Create a future payment script. + pub fn pay_on_date( + from: &Pubkey, + to: &Pubkey, + contract: &Pubkey, + dt: DateTime, + dt_pubkey: &Pubkey, + cancelable: Option, + lamports: u64, + ) -> Script { + let expr = if let Some(from) = cancelable { + BudgetExpr::Or( + ( + Condition::Timestamp(dt, *dt_pubkey), + Box::new(BudgetExpr::new_payment(lamports, to)), + ), + ( + Condition::Signature(from), + Box::new(BudgetExpr::new_payment(lamports, &from)), + ), + ) + } else { + BudgetExpr::After( + Condition::Timestamp(dt, *dt_pubkey), + Box::new(BudgetExpr::new_payment(lamports, to)), + ) + }; + + Self::new_account(from, contract, lamports, expr) + } + + /// Create a multisig payment script. + pub fn pay_on_signature( + from: &Pubkey, + to: &Pubkey, + contract: &Pubkey, + witness: &Pubkey, + cancelable: Option, + lamports: u64, + ) -> Script { + let expr = if let Some(from) = cancelable { + BudgetExpr::Or( + ( + Condition::Signature(*witness), + Box::new(BudgetExpr::new_payment(lamports, to)), + ), + ( + Condition::Signature(from), + Box::new(BudgetExpr::new_payment(lamports, &from)), + ), + ) + } else { + BudgetExpr::After( + Condition::Signature(*witness), + Box::new(BudgetExpr::new_payment(lamports, to)), + ) + }; + + Self::new_account(from, contract, lamports, expr) + } +} diff --git a/programs/budget_api/src/budget_transaction.rs b/programs/budget_api/src/budget_transaction.rs index 0f3a1c43e5..3162ef700c 100644 --- a/programs/budget_api/src/budget_transaction.rs +++ b/programs/budget_api/src/budget_transaction.rs @@ -1,6 +1,7 @@ //! The `budget_transaction` module provides functionality for creating Budget transactions. use crate::budget_instruction::BudgetInstruction; +use crate::budget_script::BudgetScript; use bincode::deserialize; use chrono::prelude::*; use solana_sdk::hash::Hash; @@ -33,7 +34,7 @@ impl BudgetTransaction { recent_blockhash: Hash, fee: u64, ) -> Transaction { - let script = BudgetInstruction::new_payment_script(&from_keypair.pubkey(), to, lamports); + let script = BudgetScript::pay(&from_keypair.pubkey(), to, lamports); Self::new_signed(from_keypair, script, recent_blockhash, fee) } @@ -77,7 +78,7 @@ impl BudgetTransaction { lamports: u64, recent_blockhash: Hash, ) -> Transaction { - let script = BudgetInstruction::new_on_date_script( + let script = BudgetScript::pay_on_date( &from_keypair.pubkey(), to, contract, @@ -99,7 +100,7 @@ impl BudgetTransaction { lamports: u64, recent_blockhash: Hash, ) -> Transaction { - let script = BudgetInstruction::new_when_signed_script( + let script = BudgetScript::pay_on_signature( &from_keypair.pubkey(), to, contract, diff --git a/programs/budget_api/src/lib.rs b/programs/budget_api/src/lib.rs index df03126e5c..73c3f88f10 100644 --- a/programs/budget_api/src/lib.rs +++ b/programs/budget_api/src/lib.rs @@ -1,5 +1,6 @@ pub mod budget_expr; pub mod budget_instruction; +pub mod budget_script; pub mod budget_state; pub mod budget_transaction; pub mod payment_plan;