cli: add airdrop call

This commit is contained in:
Hendrik Hofstadt 2020-08-21 18:55:59 +02:00
parent a8d2f36a12
commit 5f253415d5
2 changed files with 97 additions and 0 deletions

73
solana/cli/src/faucet.rs Normal file
View File

@ -0,0 +1,73 @@
use crate::CommmandResult;
use solana_client::rpc_client::RpcClient;
use solana_faucet::faucet::request_airdrop_transaction;
use solana_sdk::hash::Hash;
use solana_sdk::pubkey::Pubkey;
use solana_sdk::signature::{Signature, Signer, SignerError};
use solana_sdk::transaction::Transaction;
use std::error;
use std::net::SocketAddr;
use std::thread::sleep;
use std::time::Duration;
// Quick and dirty Keypair that assumes the client will do retries but not update the
// blockhash. If the client updates the blockhash, the signature will be invalid.
struct FaucetKeypair {
transaction: Transaction,
}
impl FaucetKeypair {
fn new_keypair(
faucet_addr: &SocketAddr,
to_pubkey: &Pubkey,
lamports: u64,
blockhash: Hash,
) -> Result<Self, Box<dyn error::Error>> {
let transaction = request_airdrop_transaction(faucet_addr, to_pubkey, lamports, blockhash)?;
Ok(Self { transaction })
}
fn airdrop_transaction(&self) -> Transaction {
self.transaction.clone()
}
}
impl Signer for FaucetKeypair {
/// Return the public key of the keypair used to sign votes
fn pubkey(&self) -> Pubkey {
self.transaction.message().account_keys[0]
}
fn try_pubkey(&self) -> Result<Pubkey, SignerError> {
Ok(self.pubkey())
}
fn sign_message(&self, _msg: &[u8]) -> Signature {
self.transaction.signatures[0]
}
fn try_sign_message(&self, message: &[u8]) -> Result<Signature, SignerError> {
Ok(self.sign_message(message))
}
}
pub fn request_and_confirm_airdrop(
rpc_client: &RpcClient,
faucet_addr: &SocketAddr,
to_pubkey: &Pubkey,
lamports: u64,
) -> CommmandResult {
let (blockhash, _fee_calculator) = rpc_client.get_recent_blockhash()?;
let keypair = {
let mut retries = 5;
loop {
let result = FaucetKeypair::new_keypair(faucet_addr, to_pubkey, lamports, blockhash);
if result.is_ok() || retries == 0 {
break result;
}
retries -= 1;
sleep(Duration::from_secs(1));
}
}?;
Ok(Some(keypair.airdrop_transaction()))
}

View File

@ -1,4 +1,5 @@
use std::fmt::Display;
use std::net::{SocketAddr, ToSocketAddrs};
use std::str::FromStr;
use std::{mem::size_of, process::exit};
@ -36,6 +37,10 @@ use spl_token::{
use spl_bridge::instruction::*;
use spl_bridge::state::*;
use crate::faucet::request_and_confirm_airdrop;
mod faucet;
struct Config {
rpc_client: RpcClient,
owner: Keypair,
@ -842,6 +847,16 @@ fn main() {
.help("The address of the token account to unwrap"),
),
)
.subcommand(SubCommand::with_name("airdrop")
.arg(
Arg::with_name("faucet_url")
.value_name("FAUCET_URL")
.takes_value(true)
.index(1)
.required(true)
.help("The address of the faucet"),
)
.about("Request an airdrop of 100 SOL"))
.subcommand(SubCommand::with_name("create-bridge")
.about("Create a new bridge")
.arg(
@ -1101,6 +1116,15 @@ fn main() {
let token = pubkey_of(arg_matches, "token");
command_accounts(&config, token)
}
("airdrop", Some(arg_matches)) => {
let faucet_addr = value_t_or_exit!(arg_matches, "faucet_url", String);
request_and_confirm_airdrop(
&config.rpc_client,
&faucet_addr.to_socket_addrs().unwrap().next().unwrap(),
&config.owner.pubkey(),
100 * LAMPORTS_PER_SOL,
)
}
("create-bridge", Some(arg_matches)) => {
let bridge = pubkey_of(arg_matches, "bridge").unwrap();
let initial_guardian: String = value_of(arg_matches, "guardian").unwrap();