@ -1,11 +1,13 @@
|
|||||||
use clap::{App, Arg, ArgMatches};
|
use clap::{App, Arg, ArgMatches};
|
||||||
|
use serde_json::Value;
|
||||||
use solana_clap_utils::{
|
use solana_clap_utils::{
|
||||||
input_parsers::value_of,
|
input_parsers::value_of,
|
||||||
input_validators::{is_hash, is_pubkey_sig},
|
input_validators::{is_hash, is_pubkey_sig},
|
||||||
ArgConstant,
|
ArgConstant,
|
||||||
};
|
};
|
||||||
use solana_client::rpc_client::RpcClient;
|
use solana_client::rpc_client::RpcClient;
|
||||||
use solana_sdk::{fee_calculator::FeeCalculator, hash::Hash};
|
use solana_sdk::{fee_calculator::FeeCalculator, hash::Hash, pubkey::Pubkey, signature::Signature};
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
pub const BLOCKHASH_ARG: ArgConstant<'static> = ArgConstant {
|
pub const BLOCKHASH_ARG: ArgConstant<'static> = ArgConstant {
|
||||||
name: "blockhash",
|
name: "blockhash",
|
||||||
@ -112,6 +114,23 @@ impl OfflineArgs for App<'_, '_> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn parse_sign_only_reply_string(reply: &str) -> (Hash, Vec<(Pubkey, Signature)>) {
|
||||||
|
let object: Value = serde_json::from_str(&reply).unwrap();
|
||||||
|
let blockhash_str = object.get("blockhash").unwrap().as_str().unwrap();
|
||||||
|
let blockhash = blockhash_str.parse::<Hash>().unwrap();
|
||||||
|
let signer_strings = object.get("signers").unwrap().as_array().unwrap();
|
||||||
|
let signers = signer_strings
|
||||||
|
.iter()
|
||||||
|
.map(|signer_string| {
|
||||||
|
let mut signer = signer_string.as_str().unwrap().split('=');
|
||||||
|
let key = Pubkey::from_str(signer.next().unwrap()).unwrap();
|
||||||
|
let sig = Signature::from_str(signer.next().unwrap()).unwrap();
|
||||||
|
(key, sig)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
(blockhash, signers)
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -2,20 +2,18 @@ use chrono::prelude::*;
|
|||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use solana_cli::{
|
use solana_cli::{
|
||||||
cli::{process_command, request_and_confirm_airdrop, CliCommand, CliConfig, PayCommand},
|
cli::{process_command, request_and_confirm_airdrop, CliCommand, CliConfig, PayCommand},
|
||||||
offline::BlockhashQuery,
|
offline::{parse_sign_only_reply_string, BlockhashQuery},
|
||||||
};
|
};
|
||||||
use solana_client::rpc_client::RpcClient;
|
use solana_client::rpc_client::RpcClient;
|
||||||
use solana_faucet::faucet::run_local_faucet;
|
use solana_faucet::faucet::run_local_faucet;
|
||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
account_utils::StateMut,
|
account_utils::StateMut,
|
||||||
fee_calculator::FeeCalculator,
|
fee_calculator::FeeCalculator,
|
||||||
hash::Hash,
|
|
||||||
nonce_state::NonceState,
|
nonce_state::NonceState,
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
signature::{read_keypair_file, write_keypair, Keypair, KeypairUtil, Signature},
|
signature::{read_keypair_file, write_keypair, Keypair, KeypairUtil},
|
||||||
};
|
};
|
||||||
use std::fs::remove_dir_all;
|
use std::fs::remove_dir_all;
|
||||||
use std::str::FromStr;
|
|
||||||
use std::sync::mpsc::channel;
|
use std::sync::mpsc::channel;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@ -305,24 +303,12 @@ fn test_offline_pay_tx() {
|
|||||||
check_balance(50, &rpc_client, &config_online.keypair.pubkey());
|
check_balance(50, &rpc_client, &config_online.keypair.pubkey());
|
||||||
check_balance(0, &rpc_client, &bob_pubkey);
|
check_balance(0, &rpc_client, &bob_pubkey);
|
||||||
|
|
||||||
let object: Value = serde_json::from_str(&sig_response).unwrap();
|
let (blockhash, signers) = parse_sign_only_reply_string(&sig_response);
|
||||||
let blockhash_str = object.get("blockhash").unwrap().as_str().unwrap();
|
|
||||||
let signer_strings = object.get("signers").unwrap().as_array().unwrap();
|
|
||||||
let signers: Vec<_> = signer_strings
|
|
||||||
.iter()
|
|
||||||
.map(|signer_string| {
|
|
||||||
let mut signer = signer_string.as_str().unwrap().split('=');
|
|
||||||
let key = Pubkey::from_str(signer.next().unwrap()).unwrap();
|
|
||||||
let sig = Signature::from_str(signer.next().unwrap()).unwrap();
|
|
||||||
(key, sig)
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
config_online.command = CliCommand::Pay(PayCommand {
|
config_online.command = CliCommand::Pay(PayCommand {
|
||||||
lamports: 10,
|
lamports: 10,
|
||||||
to: bob_pubkey,
|
to: bob_pubkey,
|
||||||
signers: Some(signers),
|
signers: Some(signers),
|
||||||
blockhash_query: BlockhashQuery::FeeCalculator(blockhash_str.parse::<Hash>().unwrap()),
|
blockhash_query: BlockhashQuery::FeeCalculator(blockhash),
|
||||||
..PayCommand::default()
|
..PayCommand::default()
|
||||||
});
|
});
|
||||||
process_command(&config_online).unwrap();
|
process_command(&config_online).unwrap();
|
||||||
|
@ -1,22 +1,19 @@
|
|||||||
use serde_json::Value;
|
|
||||||
use solana_cli::{
|
use solana_cli::{
|
||||||
cli::{process_command, request_and_confirm_airdrop, CliCommand, CliConfig},
|
cli::{process_command, request_and_confirm_airdrop, CliCommand, CliConfig},
|
||||||
offline::BlockhashQuery,
|
offline::{parse_sign_only_reply_string, BlockhashQuery},
|
||||||
};
|
};
|
||||||
use solana_client::rpc_client::RpcClient;
|
use solana_client::rpc_client::RpcClient;
|
||||||
use solana_faucet::faucet::run_local_faucet;
|
use solana_faucet::faucet::run_local_faucet;
|
||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
account_utils::StateMut,
|
account_utils::StateMut,
|
||||||
fee_calculator::FeeCalculator,
|
fee_calculator::FeeCalculator,
|
||||||
hash::Hash,
|
|
||||||
nonce_state::NonceState,
|
nonce_state::NonceState,
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
signature::{read_keypair_file, write_keypair, Keypair, KeypairUtil, Signature},
|
signature::{read_keypair_file, write_keypair, Keypair, KeypairUtil},
|
||||||
system_instruction::create_address_with_seed,
|
system_instruction::create_address_with_seed,
|
||||||
};
|
};
|
||||||
use solana_stake_program::stake_state::{Lockup, StakeAuthorize, StakeState};
|
use solana_stake_program::stake_state::{Lockup, StakeAuthorize, StakeState};
|
||||||
use std::fs::remove_dir_all;
|
use std::fs::remove_dir_all;
|
||||||
use std::str::FromStr;
|
|
||||||
use std::sync::mpsc::channel;
|
use std::sync::mpsc::channel;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@ -44,23 +41,6 @@ fn check_balance(expected_balance: u64, client: &RpcClient, pubkey: &Pubkey) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_sign_only_reply_string(reply: &str) -> (Hash, Vec<(Pubkey, Signature)>) {
|
|
||||||
let object: Value = serde_json::from_str(&reply).unwrap();
|
|
||||||
let blockhash_str = object.get("blockhash").unwrap().as_str().unwrap();
|
|
||||||
let blockhash = blockhash_str.parse::<Hash>().unwrap();
|
|
||||||
let signer_strings = object.get("signers").unwrap().as_array().unwrap();
|
|
||||||
let signers = signer_strings
|
|
||||||
.iter()
|
|
||||||
.map(|signer_string| {
|
|
||||||
let mut signer = signer_string.as_str().unwrap().split('=');
|
|
||||||
let key = Pubkey::from_str(signer.next().unwrap()).unwrap();
|
|
||||||
let sig = Signature::from_str(signer.next().unwrap()).unwrap();
|
|
||||||
(key, sig)
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
(blockhash, signers)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_seed_stake_delegation_and_deactivation() {
|
fn test_seed_stake_delegation_and_deactivation() {
|
||||||
solana_logger::setup();
|
solana_logger::setup();
|
||||||
|
Reference in New Issue
Block a user