Boot BudgetTransaction
This commit is contained in:
parent
b53cbdd9e6
commit
33972ef89e
|
@ -8,7 +8,7 @@ use crate::result::Result;
|
||||||
use bincode::{deserialize, serialized_size};
|
use bincode::{deserialize, serialized_size};
|
||||||
use chrono::prelude::Utc;
|
use chrono::prelude::Utc;
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
use solana_budget_api::budget_transaction::BudgetTransaction;
|
use solana_budget_api::budget_instruction::BudgetInstruction;
|
||||||
use solana_sdk::hash::Hash;
|
use solana_sdk::hash::Hash;
|
||||||
use solana_sdk::pubkey::Pubkey;
|
use solana_sdk::pubkey::Pubkey;
|
||||||
use solana_sdk::signature::{Keypair, KeypairUtil};
|
use solana_sdk::signature::{Keypair, KeypairUtil};
|
||||||
|
@ -378,22 +378,15 @@ pub fn create_ticks(num_ticks: u64, mut hash: Hash) -> Vec<Entry> {
|
||||||
|
|
||||||
pub fn make_tiny_test_entries_from_hash(start: &Hash, num: usize) -> Vec<Entry> {
|
pub fn make_tiny_test_entries_from_hash(start: &Hash, num: usize) -> Vec<Entry> {
|
||||||
let keypair = Keypair::new();
|
let keypair = Keypair::new();
|
||||||
|
let pubkey = keypair.pubkey();
|
||||||
|
|
||||||
let mut hash = *start;
|
let mut hash = *start;
|
||||||
let mut num_hashes = 0;
|
let mut num_hashes = 0;
|
||||||
(0..num)
|
(0..num)
|
||||||
.map(|_| {
|
.map(|_| {
|
||||||
Entry::new_mut(
|
let ix = BudgetInstruction::new_apply_timestamp(&pubkey, &pubkey, &pubkey, Utc::now());
|
||||||
&mut hash,
|
let tx = Transaction::new_signed_instructions(&[&keypair], vec![ix], *start, 0);
|
||||||
&mut num_hashes,
|
Entry::new_mut(&mut hash, &mut num_hashes, vec![tx])
|
||||||
vec![BudgetTransaction::new_timestamp(
|
|
||||||
&keypair,
|
|
||||||
&keypair.pubkey(),
|
|
||||||
&keypair.pubkey(),
|
|
||||||
Utc::now(),
|
|
||||||
*start,
|
|
||||||
)],
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
@ -408,14 +401,10 @@ pub fn make_large_test_entries(num_entries: usize) -> Vec<Entry> {
|
||||||
let zero = Hash::default();
|
let zero = Hash::default();
|
||||||
let one = solana_sdk::hash::hash(&zero.as_ref());
|
let one = solana_sdk::hash::hash(&zero.as_ref());
|
||||||
let keypair = Keypair::new();
|
let keypair = Keypair::new();
|
||||||
|
let pubkey = keypair.pubkey();
|
||||||
|
|
||||||
let tx = BudgetTransaction::new_timestamp(
|
let ix = BudgetInstruction::new_apply_timestamp(&pubkey, &pubkey, &pubkey, Utc::now());
|
||||||
&keypair,
|
let tx = Transaction::new_signed_instructions(&[&keypair], vec![ix], one, 0);
|
||||||
&keypair.pubkey(),
|
|
||||||
&keypair.pubkey(),
|
|
||||||
Utc::now(),
|
|
||||||
one,
|
|
||||||
);
|
|
||||||
|
|
||||||
let serialized_size = tx.serialized_size().unwrap();
|
let serialized_size = tx.serialized_size().unwrap();
|
||||||
let num_txs = BLOB_DATA_SIZE / serialized_size as usize;
|
let num_txs = BLOB_DATA_SIZE / serialized_size as usize;
|
||||||
|
@ -468,6 +457,24 @@ mod tests {
|
||||||
use solana_sdk::system_transaction::SystemTransaction;
|
use solana_sdk::system_transaction::SystemTransaction;
|
||||||
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
||||||
|
|
||||||
|
fn create_sample_payment(keypair: &Keypair, hash: Hash) -> Transaction {
|
||||||
|
let pubkey = keypair.pubkey();
|
||||||
|
let ixs = BudgetInstruction::new_payment(&pubkey, &pubkey, 1);
|
||||||
|
Transaction::new_signed_instructions(&[keypair], ixs, hash, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_sample_timestamp(keypair: &Keypair, hash: Hash) -> Transaction {
|
||||||
|
let pubkey = keypair.pubkey();
|
||||||
|
let ix = BudgetInstruction::new_apply_timestamp(&pubkey, &pubkey, &pubkey, Utc::now());
|
||||||
|
Transaction::new_signed_instructions(&[keypair], vec![ix], hash, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_sample_signature(keypair: &Keypair, hash: Hash) -> Transaction {
|
||||||
|
let pubkey = keypair.pubkey();
|
||||||
|
let ix = BudgetInstruction::new_apply_signature(&pubkey, &pubkey, &pubkey);
|
||||||
|
Transaction::new_signed_instructions(&[keypair], vec![ix], hash, 0)
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_entry_verify() {
|
fn test_entry_verify() {
|
||||||
let zero = Hash::default();
|
let zero = Hash::default();
|
||||||
|
@ -501,15 +508,8 @@ mod tests {
|
||||||
|
|
||||||
// First, verify entries
|
// First, verify entries
|
||||||
let keypair = Keypair::new();
|
let keypair = Keypair::new();
|
||||||
let tx0 = BudgetTransaction::new_timestamp(
|
let tx0 = create_sample_timestamp(&keypair, zero);
|
||||||
&keypair,
|
let tx1 = create_sample_signature(&keypair, zero);
|
||||||
&keypair.pubkey(),
|
|
||||||
&keypair.pubkey(),
|
|
||||||
Utc::now(),
|
|
||||||
zero,
|
|
||||||
);
|
|
||||||
let tx1 =
|
|
||||||
BudgetTransaction::new_signature(&keypair, &keypair.pubkey(), &keypair.pubkey(), zero);
|
|
||||||
let mut e0 = Entry::new(&zero, 0, vec![tx0.clone(), tx1.clone()]);
|
let mut e0 = Entry::new(&zero, 0, vec![tx0.clone(), tx1.clone()]);
|
||||||
assert!(e0.verify(&zero));
|
assert!(e0.verify(&zero));
|
||||||
|
|
||||||
|
@ -531,13 +531,7 @@ mod tests {
|
||||||
assert_eq!(tick.hash, zero);
|
assert_eq!(tick.hash, zero);
|
||||||
|
|
||||||
let keypair = Keypair::new();
|
let keypair = Keypair::new();
|
||||||
let tx0 = BudgetTransaction::new_timestamp(
|
let tx0 = create_sample_timestamp(&keypair, zero);
|
||||||
&keypair,
|
|
||||||
&keypair.pubkey(),
|
|
||||||
&keypair.pubkey(),
|
|
||||||
Utc::now(),
|
|
||||||
zero,
|
|
||||||
);
|
|
||||||
let entry0 = next_entry(&zero, 1, vec![tx0.clone()]);
|
let entry0 = next_entry(&zero, 1, vec![tx0.clone()]);
|
||||||
assert_eq!(entry0.num_hashes, 1);
|
assert_eq!(entry0.num_hashes, 1);
|
||||||
assert_eq!(entry0.hash, next_hash(&zero, 1, &vec![tx0]));
|
assert_eq!(entry0.hash, next_hash(&zero, 1, &vec![tx0]));
|
||||||
|
@ -585,13 +579,7 @@ mod tests {
|
||||||
let keypair = Keypair::new();
|
let keypair = Keypair::new();
|
||||||
let vote_account = Keypair::new();
|
let vote_account = Keypair::new();
|
||||||
let tx0 = VoteTransaction::new_vote(&vote_account.pubkey(), &vote_account, 1, one, 1);
|
let tx0 = VoteTransaction::new_vote(&vote_account.pubkey(), &vote_account, 1, one, 1);
|
||||||
let tx1 = BudgetTransaction::new_timestamp(
|
let tx1 = create_sample_timestamp(&keypair, one);
|
||||||
&keypair,
|
|
||||||
&keypair.pubkey(),
|
|
||||||
&keypair.pubkey(),
|
|
||||||
Utc::now(),
|
|
||||||
one,
|
|
||||||
);
|
|
||||||
//
|
//
|
||||||
// TODO: this magic number and the mix of transaction types
|
// TODO: this magic number and the mix of transaction types
|
||||||
// is designed to fill up a Blob more or less exactly,
|
// is designed to fill up a Blob more or less exactly,
|
||||||
|
@ -651,7 +639,7 @@ mod tests {
|
||||||
let vote_account = Keypair::new();
|
let vote_account = Keypair::new();
|
||||||
let tx_small =
|
let tx_small =
|
||||||
VoteTransaction::new_vote(&vote_account.pubkey(), &vote_account, 1, next_hash, 2);
|
VoteTransaction::new_vote(&vote_account.pubkey(), &vote_account, 1, next_hash, 2);
|
||||||
let tx_large = BudgetTransaction::new_payment(&keypair, &keypair.pubkey(), 1, next_hash, 0);
|
let tx_large = create_sample_payment(&keypair, next_hash);
|
||||||
|
|
||||||
let tx_small_size = tx_small.serialized_size().unwrap() as usize;
|
let tx_small_size = tx_small.serialized_size().unwrap() as usize;
|
||||||
let tx_large_size = tx_large.serialized_size().unwrap() as usize;
|
let tx_large_size = tx_large.serialized_size().unwrap() as usize;
|
||||||
|
|
|
@ -227,7 +227,7 @@ mod tests {
|
||||||
use jsonrpc_core::Response;
|
use jsonrpc_core::Response;
|
||||||
use jsonrpc_pubsub::{PubSubHandler, Session};
|
use jsonrpc_pubsub::{PubSubHandler, Session};
|
||||||
use solana_budget_api;
|
use solana_budget_api;
|
||||||
use solana_budget_api::budget_transaction::BudgetTransaction;
|
use solana_budget_api::budget_instruction::BudgetInstruction;
|
||||||
use solana_runtime::bank::{self, Bank};
|
use solana_runtime::bank::{self, Bank};
|
||||||
use solana_sdk::genesis_block::GenesisBlock;
|
use solana_sdk::genesis_block::GenesisBlock;
|
||||||
use solana_sdk::pubkey::Pubkey;
|
use solana_sdk::pubkey::Pubkey;
|
||||||
|
@ -357,15 +357,15 @@ mod tests {
|
||||||
let tx = SystemTransaction::new_account(&alice, &contract_funds.pubkey(), 51, blockhash, 0);
|
let tx = SystemTransaction::new_account(&alice, &contract_funds.pubkey(), 51, blockhash, 0);
|
||||||
let arc_bank = process_transaction_and_notify(&arc_bank, &tx, &rpc.subscriptions).unwrap();
|
let arc_bank = process_transaction_and_notify(&arc_bank, &tx, &rpc.subscriptions).unwrap();
|
||||||
|
|
||||||
let tx = BudgetTransaction::new_when_signed(
|
let ixs = BudgetInstruction::new_when_signed(
|
||||||
&contract_funds,
|
&contract_funds.pubkey(),
|
||||||
&bob_pubkey,
|
&bob_pubkey,
|
||||||
&contract_state.pubkey(),
|
&contract_state.pubkey(),
|
||||||
&witness.pubkey(),
|
&witness.pubkey(),
|
||||||
None,
|
None,
|
||||||
51,
|
51,
|
||||||
blockhash,
|
|
||||||
);
|
);
|
||||||
|
let tx = Transaction::new_signed_instructions(&[&contract_funds], ixs, blockhash, 0);
|
||||||
let arc_bank = process_transaction_and_notify(&arc_bank, &tx, &rpc.subscriptions).unwrap();
|
let arc_bank = process_transaction_and_notify(&arc_bank, &tx, &rpc.subscriptions).unwrap();
|
||||||
sleep(Duration::from_millis(200));
|
sleep(Duration::from_millis(200));
|
||||||
|
|
||||||
|
@ -393,12 +393,12 @@ mod tests {
|
||||||
let tx = SystemTransaction::new_account(&alice, &witness.pubkey(), 1, blockhash, 0);
|
let tx = SystemTransaction::new_account(&alice, &witness.pubkey(), 1, blockhash, 0);
|
||||||
let arc_bank = process_transaction_and_notify(&arc_bank, &tx, &rpc.subscriptions).unwrap();
|
let arc_bank = process_transaction_and_notify(&arc_bank, &tx, &rpc.subscriptions).unwrap();
|
||||||
sleep(Duration::from_millis(200));
|
sleep(Duration::from_millis(200));
|
||||||
let tx = BudgetTransaction::new_signature(
|
let ix = BudgetInstruction::new_apply_signature(
|
||||||
&witness,
|
&witness.pubkey(),
|
||||||
&contract_state.pubkey(),
|
&contract_state.pubkey(),
|
||||||
&bob_pubkey,
|
&bob_pubkey,
|
||||||
blockhash,
|
|
||||||
);
|
);
|
||||||
|
let tx = Transaction::new_signed_instructions(&[&witness], vec![ix], blockhash, 0);
|
||||||
let arc_bank = process_transaction_and_notify(&arc_bank, &tx, &rpc.subscriptions).unwrap();
|
let arc_bank = process_transaction_and_notify(&arc_bank, &tx, &rpc.subscriptions).unwrap();
|
||||||
sleep(Duration::from_millis(200));
|
sleep(Duration::from_millis(200));
|
||||||
|
|
||||||
|
|
|
@ -1,93 +0,0 @@
|
||||||
//! The `budget_transaction` module provides functionality for creating Budget transactions.
|
|
||||||
|
|
||||||
use crate::budget_instruction::BudgetInstruction;
|
|
||||||
use chrono::prelude::*;
|
|
||||||
use solana_sdk::hash::Hash;
|
|
||||||
use solana_sdk::pubkey::Pubkey;
|
|
||||||
use solana_sdk::signature::{Keypair, KeypairUtil};
|
|
||||||
use solana_sdk::transaction::Transaction;
|
|
||||||
|
|
||||||
pub struct BudgetTransaction {}
|
|
||||||
|
|
||||||
impl BudgetTransaction {
|
|
||||||
/// Create and sign a new Transaction. Used for unit-testing.
|
|
||||||
pub fn new_payment(
|
|
||||||
from_keypair: &Keypair,
|
|
||||||
to: &Pubkey,
|
|
||||||
lamports: u64,
|
|
||||||
recent_blockhash: Hash,
|
|
||||||
fee: u64,
|
|
||||||
) -> Transaction {
|
|
||||||
let ixs = BudgetInstruction::new_payment(&from_keypair.pubkey(), to, lamports);
|
|
||||||
Transaction::new_signed_instructions(&[from_keypair], ixs, recent_blockhash, fee)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create and sign a new Witness Timestamp. Used for unit-testing.
|
|
||||||
pub fn new_timestamp(
|
|
||||||
from_keypair: &Keypair,
|
|
||||||
contract: &Pubkey,
|
|
||||||
to: &Pubkey,
|
|
||||||
dt: DateTime<Utc>,
|
|
||||||
recent_blockhash: Hash,
|
|
||||||
) -> Transaction {
|
|
||||||
let from = from_keypair.pubkey();
|
|
||||||
let ix = BudgetInstruction::new_apply_timestamp(&from, contract, to, dt);
|
|
||||||
Transaction::new_signed_instructions(&[from_keypair], vec![ix], recent_blockhash, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create and sign a new Witness Signature. Used for unit-testing.
|
|
||||||
pub fn new_signature(
|
|
||||||
from_keypair: &Keypair,
|
|
||||||
contract: &Pubkey,
|
|
||||||
to: &Pubkey,
|
|
||||||
recent_blockhash: Hash,
|
|
||||||
) -> Transaction {
|
|
||||||
let from = from_keypair.pubkey();
|
|
||||||
let ix = BudgetInstruction::new_apply_signature(&from, contract, to);
|
|
||||||
Transaction::new_signed_instructions(&[from_keypair], vec![ix], recent_blockhash, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create and sign a postdated Transaction. Used for unit-testing.
|
|
||||||
pub fn new_on_date(
|
|
||||||
from_keypair: &Keypair,
|
|
||||||
to: &Pubkey,
|
|
||||||
contract: &Pubkey,
|
|
||||||
dt: DateTime<Utc>,
|
|
||||||
dt_pubkey: &Pubkey,
|
|
||||||
cancelable: Option<Pubkey>,
|
|
||||||
lamports: u64,
|
|
||||||
recent_blockhash: Hash,
|
|
||||||
) -> Transaction {
|
|
||||||
let ixs = BudgetInstruction::new_on_date(
|
|
||||||
&from_keypair.pubkey(),
|
|
||||||
to,
|
|
||||||
contract,
|
|
||||||
dt,
|
|
||||||
dt_pubkey,
|
|
||||||
cancelable,
|
|
||||||
lamports,
|
|
||||||
);
|
|
||||||
Transaction::new_signed_instructions(&[from_keypair], ixs, recent_blockhash, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create and sign a multisig Transaction.
|
|
||||||
pub fn new_when_signed(
|
|
||||||
from_keypair: &Keypair,
|
|
||||||
to: &Pubkey,
|
|
||||||
contract: &Pubkey,
|
|
||||||
witness: &Pubkey,
|
|
||||||
cancelable: Option<Pubkey>,
|
|
||||||
lamports: u64,
|
|
||||||
recent_blockhash: Hash,
|
|
||||||
) -> Transaction {
|
|
||||||
let ixs = BudgetInstruction::new_when_signed(
|
|
||||||
&from_keypair.pubkey(),
|
|
||||||
to,
|
|
||||||
contract,
|
|
||||||
witness,
|
|
||||||
cancelable,
|
|
||||||
lamports,
|
|
||||||
);
|
|
||||||
Transaction::new_signed_instructions(&[from_keypair], ixs, recent_blockhash, 0)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -2,7 +2,6 @@ pub mod budget_expr;
|
||||||
pub mod budget_instruction;
|
pub mod budget_instruction;
|
||||||
pub mod budget_processor;
|
pub mod budget_processor;
|
||||||
pub mod budget_state;
|
pub mod budget_state;
|
||||||
pub mod budget_transaction;
|
|
||||||
pub mod payment_plan;
|
pub mod payment_plan;
|
||||||
|
|
||||||
use solana_sdk::pubkey::Pubkey;
|
use solana_sdk::pubkey::Pubkey;
|
||||||
|
|
|
@ -5,7 +5,7 @@ use log::*;
|
||||||
use serde_json;
|
use serde_json;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use solana_budget_api;
|
use solana_budget_api;
|
||||||
use solana_budget_api::budget_transaction::BudgetTransaction;
|
use solana_budget_api::budget_instruction::BudgetInstruction;
|
||||||
use solana_client::rpc_client::{get_rpc_request_str, RpcClient};
|
use solana_client::rpc_client::{get_rpc_request_str, RpcClient};
|
||||||
#[cfg(not(test))]
|
#[cfg(not(test))]
|
||||||
use solana_drone::drone::request_airdrop_transaction;
|
use solana_drone::drone::request_airdrop_transaction;
|
||||||
|
@ -466,16 +466,16 @@ fn process_pay(
|
||||||
let contract_state = Keypair::new();
|
let contract_state = Keypair::new();
|
||||||
|
|
||||||
// Initializing contract
|
// Initializing contract
|
||||||
let mut tx = BudgetTransaction::new_on_date(
|
let ixs = BudgetInstruction::new_on_date(
|
||||||
&config.id,
|
&config.id.pubkey(),
|
||||||
to,
|
to,
|
||||||
&contract_state.pubkey(),
|
&contract_state.pubkey(),
|
||||||
dt,
|
dt,
|
||||||
&dt_pubkey,
|
&dt_pubkey,
|
||||||
cancelable,
|
cancelable,
|
||||||
lamports,
|
lamports,
|
||||||
blockhash,
|
|
||||||
);
|
);
|
||||||
|
let mut tx = Transaction::new_signed_instructions(&[&config.id], ixs, blockhash, 0);
|
||||||
let signature_str = rpc_client.send_and_confirm_transaction(&mut tx, &config.id)?;
|
let signature_str = rpc_client.send_and_confirm_transaction(&mut tx, &config.id)?;
|
||||||
|
|
||||||
Ok(json!({
|
Ok(json!({
|
||||||
|
@ -497,15 +497,15 @@ fn process_pay(
|
||||||
let contract_state = Keypair::new();
|
let contract_state = Keypair::new();
|
||||||
|
|
||||||
// Initializing contract
|
// Initializing contract
|
||||||
let mut tx = BudgetTransaction::new_when_signed(
|
let ixs = BudgetInstruction::new_when_signed(
|
||||||
&config.id,
|
&config.id.pubkey(),
|
||||||
to,
|
to,
|
||||||
&contract_state.pubkey(),
|
&contract_state.pubkey(),
|
||||||
&witness,
|
&witness,
|
||||||
cancelable,
|
cancelable,
|
||||||
lamports,
|
lamports,
|
||||||
blockhash,
|
|
||||||
);
|
);
|
||||||
|
let mut tx = Transaction::new_signed_instructions(&[&config.id], ixs, blockhash, 0);
|
||||||
let signature_str = rpc_client.send_and_confirm_transaction(&mut tx, &config.id)?;
|
let signature_str = rpc_client.send_and_confirm_transaction(&mut tx, &config.id)?;
|
||||||
|
|
||||||
Ok(json!({
|
Ok(json!({
|
||||||
|
@ -520,8 +520,9 @@ fn process_pay(
|
||||||
|
|
||||||
fn process_cancel(rpc_client: &RpcClient, config: &WalletConfig, pubkey: &Pubkey) -> ProcessResult {
|
fn process_cancel(rpc_client: &RpcClient, config: &WalletConfig, pubkey: &Pubkey) -> ProcessResult {
|
||||||
let blockhash = rpc_client.get_recent_blockhash()?;
|
let blockhash = rpc_client.get_recent_blockhash()?;
|
||||||
let mut tx =
|
let ix =
|
||||||
BudgetTransaction::new_signature(&config.id, pubkey, &config.id.pubkey(), blockhash);
|
BudgetInstruction::new_apply_signature(&config.id.pubkey(), pubkey, &config.id.pubkey());
|
||||||
|
let mut tx = Transaction::new_signed_instructions(&[&config.id], vec![ix], blockhash, 0);
|
||||||
let signature_str = rpc_client.send_and_confirm_transaction(&mut tx, &config.id)?;
|
let signature_str = rpc_client.send_and_confirm_transaction(&mut tx, &config.id)?;
|
||||||
Ok(signature_str.to_string())
|
Ok(signature_str.to_string())
|
||||||
}
|
}
|
||||||
|
@ -547,7 +548,8 @@ fn process_time_elapsed(
|
||||||
|
|
||||||
let blockhash = rpc_client.get_recent_blockhash()?;
|
let blockhash = rpc_client.get_recent_blockhash()?;
|
||||||
|
|
||||||
let mut tx = BudgetTransaction::new_timestamp(&config.id, pubkey, to, dt, blockhash);
|
let ix = BudgetInstruction::new_apply_timestamp(&config.id.pubkey(), pubkey, to, dt);
|
||||||
|
let mut tx = Transaction::new_signed_instructions(&[&config.id], vec![ix], blockhash, 0);
|
||||||
let signature_str = rpc_client.send_and_confirm_transaction(&mut tx, &config.id)?;
|
let signature_str = rpc_client.send_and_confirm_transaction(&mut tx, &config.id)?;
|
||||||
|
|
||||||
Ok(signature_str.to_string())
|
Ok(signature_str.to_string())
|
||||||
|
@ -567,7 +569,8 @@ fn process_witness(
|
||||||
}
|
}
|
||||||
|
|
||||||
let blockhash = rpc_client.get_recent_blockhash()?;
|
let blockhash = rpc_client.get_recent_blockhash()?;
|
||||||
let mut tx = BudgetTransaction::new_signature(&config.id, pubkey, to, blockhash);
|
let ix = BudgetInstruction::new_apply_signature(&config.id.pubkey(), pubkey, to);
|
||||||
|
let mut tx = Transaction::new_signed_instructions(&[&config.id], vec![ix], blockhash, 0);
|
||||||
let signature_str = rpc_client.send_and_confirm_transaction(&mut tx, &config.id)?;
|
let signature_str = rpc_client.send_and_confirm_transaction(&mut tx, &config.id)?;
|
||||||
|
|
||||||
Ok(signature_str.to_string())
|
Ok(signature_str.to_string())
|
||||||
|
|
Loading…
Reference in New Issue