This reverts commit d14374bc9f
.
This commit is contained in:
@ -24,7 +24,6 @@ use {
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub type StringAmount = String;
|
pub type StringAmount = String;
|
||||||
pub type StringDecimals = String;
|
|
||||||
|
|
||||||
/// A duplicate representation of an Account for pretty JSON serialization
|
/// A duplicate representation of an Account for pretty JSON serialization
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
parse_account_data::{ParsableAccount, ParseAccountError},
|
parse_account_data::{ParsableAccount, ParseAccountError},
|
||||||
StringAmount, StringDecimals,
|
StringAmount,
|
||||||
};
|
};
|
||||||
use solana_sdk::pubkey::Pubkey;
|
use solana_sdk::pubkey::Pubkey;
|
||||||
use spl_token_v2_0::{
|
use spl_token_v2_0::{
|
||||||
@ -158,37 +158,44 @@ impl From<AccountState> for UiAccountState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn real_number_string(amount: u64, decimals: u8) -> StringDecimals {
|
|
||||||
let decimals = decimals as usize;
|
|
||||||
if decimals > 0 {
|
|
||||||
// Left-pad zeros to decimals + 1, so we at least have an integer zero
|
|
||||||
let mut s = format!("{:01$}", amount, decimals + 1);
|
|
||||||
// Add the decimal point (Sorry, "," locales!)
|
|
||||||
s.insert(s.len() - decimals, '.');
|
|
||||||
s
|
|
||||||
} else {
|
|
||||||
amount.to_string()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn real_number_string_trimmed(amount: u64, decimals: u8) -> StringDecimals {
|
|
||||||
let s = real_number_string(amount, decimals);
|
|
||||||
let zeros_trimmed = s.trim_end_matches('0');
|
|
||||||
let decimal_trimmed = zeros_trimmed.trim_end_matches('.');
|
|
||||||
decimal_trimmed.to_string()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
|
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct UiTokenAmount {
|
pub struct UiTokenAmount {
|
||||||
pub ui_amount: StringDecimals,
|
pub ui_amount: f64,
|
||||||
pub decimals: u8,
|
pub decimals: u8,
|
||||||
pub amount: StringAmount,
|
pub amount: StringAmount,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl UiTokenAmount {
|
||||||
|
pub fn real_number_string(&self) -> String {
|
||||||
|
let decimals = self.decimals as usize;
|
||||||
|
if decimals > 0 {
|
||||||
|
let amount = u64::from_str(&self.amount).unwrap_or(0);
|
||||||
|
|
||||||
|
// Left-pad zeros to decimals + 1, so we at least have an integer zero
|
||||||
|
let mut s = format!("{:01$}", amount, decimals + 1);
|
||||||
|
|
||||||
|
// Add the decimal point (Sorry, "," locales!)
|
||||||
|
s.insert(s.len() - decimals, '.');
|
||||||
|
s
|
||||||
|
} else {
|
||||||
|
self.amount.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn real_number_string_trimmed(&self) -> String {
|
||||||
|
let s = self.real_number_string();
|
||||||
|
let zeros_trimmed = s.trim_end_matches('0');
|
||||||
|
let decimal_trimmed = zeros_trimmed.trim_end_matches('.');
|
||||||
|
decimal_trimmed.to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn token_amount_to_ui_amount(amount: u64, decimals: u8) -> UiTokenAmount {
|
pub fn token_amount_to_ui_amount(amount: u64, decimals: u8) -> UiTokenAmount {
|
||||||
|
// Use `amount_to_ui_amount()` once spl_token is bumped to a version that supports it: https://github.com/solana-labs/solana-program-library/pull/211
|
||||||
|
let amount_decimals = amount as f64 / 10_usize.pow(decimals as u32) as f64;
|
||||||
UiTokenAmount {
|
UiTokenAmount {
|
||||||
ui_amount: real_number_string_trimmed(amount, decimals),
|
ui_amount: amount_decimals,
|
||||||
decimals,
|
decimals,
|
||||||
amount: amount.to_string(),
|
amount: amount.to_string(),
|
||||||
}
|
}
|
||||||
@ -246,7 +253,7 @@ mod test {
|
|||||||
mint: mint_pubkey.to_string(),
|
mint: mint_pubkey.to_string(),
|
||||||
owner: owner_pubkey.to_string(),
|
owner: owner_pubkey.to_string(),
|
||||||
token_amount: UiTokenAmount {
|
token_amount: UiTokenAmount {
|
||||||
ui_amount: "0.42".to_string(),
|
ui_amount: 0.42,
|
||||||
decimals: 2,
|
decimals: 2,
|
||||||
amount: "42".to_string()
|
amount: "42".to_string()
|
||||||
},
|
},
|
||||||
@ -329,40 +336,17 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_ui_token_amount_real_string() {
|
fn test_ui_token_amount_real_string() {
|
||||||
assert_eq!(&real_number_string(1, 0), "1");
|
|
||||||
assert_eq!(&real_number_string_trimmed(1, 0), "1");
|
|
||||||
let token_amount = token_amount_to_ui_amount(1, 0);
|
let token_amount = token_amount_to_ui_amount(1, 0);
|
||||||
assert_eq!(token_amount.ui_amount, real_number_string_trimmed(1, 0));
|
assert_eq!(&token_amount.real_number_string(), "1");
|
||||||
assert_eq!(&real_number_string(1, 9), "0.000000001");
|
assert_eq!(&token_amount.real_number_string_trimmed(), "1");
|
||||||
assert_eq!(&real_number_string_trimmed(1, 9), "0.000000001");
|
|
||||||
let token_amount = token_amount_to_ui_amount(1, 9);
|
let token_amount = token_amount_to_ui_amount(1, 9);
|
||||||
assert_eq!(token_amount.ui_amount, real_number_string_trimmed(1, 9));
|
assert_eq!(&token_amount.real_number_string(), "0.000000001");
|
||||||
assert_eq!(&real_number_string(1_000_000_000, 9), "1.000000000");
|
assert_eq!(&token_amount.real_number_string_trimmed(), "0.000000001");
|
||||||
assert_eq!(&real_number_string_trimmed(1_000_000_000, 9), "1");
|
|
||||||
let token_amount = token_amount_to_ui_amount(1_000_000_000, 9);
|
let token_amount = token_amount_to_ui_amount(1_000_000_000, 9);
|
||||||
assert_eq!(
|
assert_eq!(&token_amount.real_number_string(), "1.000000000");
|
||||||
token_amount.ui_amount,
|
assert_eq!(&token_amount.real_number_string_trimmed(), "1");
|
||||||
real_number_string_trimmed(1_000_000_000, 9)
|
|
||||||
);
|
|
||||||
assert_eq!(&real_number_string(1_234_567_890, 3), "1234567.890");
|
|
||||||
assert_eq!(&real_number_string_trimmed(1_234_567_890, 3), "1234567.89");
|
|
||||||
let token_amount = token_amount_to_ui_amount(1_234_567_890, 3);
|
let token_amount = token_amount_to_ui_amount(1_234_567_890, 3);
|
||||||
assert_eq!(
|
assert_eq!(&token_amount.real_number_string(), "1234567.890");
|
||||||
token_amount.ui_amount,
|
assert_eq!(&token_amount.real_number_string_trimmed(), "1234567.89");
|
||||||
real_number_string_trimmed(1_234_567_890, 3)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
&real_number_string(1_234_567_890, 25),
|
|
||||||
"0.0000000000000001234567890"
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
&real_number_string_trimmed(1_234_567_890, 25),
|
|
||||||
"0.000000000000000123456789"
|
|
||||||
);
|
|
||||||
let token_amount = token_amount_to_ui_amount(1_234_567_890, 20);
|
|
||||||
assert_eq!(
|
|
||||||
token_amount.ui_amount,
|
|
||||||
real_number_string_trimmed(1_234_567_890, 20)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1496,7 +1496,11 @@ impl fmt::Display for CliTokenAccount {
|
|||||||
writeln!(f)?;
|
writeln!(f)?;
|
||||||
writeln_name_value(f, "Address:", &self.address)?;
|
writeln_name_value(f, "Address:", &self.address)?;
|
||||||
let account = &self.token_account;
|
let account = &self.token_account;
|
||||||
writeln_name_value(f, "Balance:", &account.token_amount.ui_amount)?;
|
writeln_name_value(
|
||||||
|
f,
|
||||||
|
"Balance:",
|
||||||
|
&account.token_amount.real_number_string_trimmed(),
|
||||||
|
)?;
|
||||||
let mint = format!(
|
let mint = format!(
|
||||||
"{}{}",
|
"{}{}",
|
||||||
account.mint,
|
account.mint,
|
||||||
@ -1509,7 +1513,7 @@ impl fmt::Display for CliTokenAccount {
|
|||||||
writeln!(f, "Delegation:")?;
|
writeln!(f, "Delegation:")?;
|
||||||
writeln_name_value(f, " Delegate:", delegate)?;
|
writeln_name_value(f, " Delegate:", delegate)?;
|
||||||
let allowance = account.delegated_amount.as_ref().unwrap();
|
let allowance = account.delegated_amount.as_ref().unwrap();
|
||||||
writeln_name_value(f, " Allowance:", &allowance.ui_amount)?;
|
writeln_name_value(f, " Allowance:", &allowance.real_number_string_trimmed())?;
|
||||||
}
|
}
|
||||||
writeln_name_value(
|
writeln_name_value(
|
||||||
f,
|
f,
|
||||||
|
@ -5701,7 +5701,7 @@ pub mod tests {
|
|||||||
let balance: UiTokenAmount =
|
let balance: UiTokenAmount =
|
||||||
serde_json::from_value(result["result"]["value"].clone()).unwrap();
|
serde_json::from_value(result["result"]["value"].clone()).unwrap();
|
||||||
let error = f64::EPSILON;
|
let error = f64::EPSILON;
|
||||||
assert!((f64::from_str(&balance.ui_amount).unwrap() - 4.2).abs() < error);
|
assert!((balance.ui_amount - 4.2).abs() < error);
|
||||||
assert_eq!(balance.amount, 420.to_string());
|
assert_eq!(balance.amount, 420.to_string());
|
||||||
assert_eq!(balance.decimals, 2);
|
assert_eq!(balance.decimals, 2);
|
||||||
|
|
||||||
@ -5726,7 +5726,7 @@ pub mod tests {
|
|||||||
let supply: UiTokenAmount =
|
let supply: UiTokenAmount =
|
||||||
serde_json::from_value(result["result"]["value"].clone()).unwrap();
|
serde_json::from_value(result["result"]["value"].clone()).unwrap();
|
||||||
let error = f64::EPSILON;
|
let error = f64::EPSILON;
|
||||||
assert!((f64::from_str(&supply.ui_amount).unwrap() - 5.0).abs() < error);
|
assert!((supply.ui_amount - 5.0).abs() < error);
|
||||||
assert_eq!(supply.amount, 500.to_string());
|
assert_eq!(supply.amount, 500.to_string());
|
||||||
assert_eq!(supply.decimals, 2);
|
assert_eq!(supply.decimals, 2);
|
||||||
|
|
||||||
@ -6024,7 +6024,7 @@ pub mod tests {
|
|||||||
RpcTokenAccountBalance {
|
RpcTokenAccountBalance {
|
||||||
address: token_with_different_mint_pubkey.to_string(),
|
address: token_with_different_mint_pubkey.to_string(),
|
||||||
amount: UiTokenAmount {
|
amount: UiTokenAmount {
|
||||||
ui_amount: "0.42".to_string(),
|
ui_amount: 0.42,
|
||||||
decimals: 2,
|
decimals: 2,
|
||||||
amount: "42".to_string(),
|
amount: "42".to_string(),
|
||||||
}
|
}
|
||||||
@ -6032,7 +6032,7 @@ pub mod tests {
|
|||||||
RpcTokenAccountBalance {
|
RpcTokenAccountBalance {
|
||||||
address: token_with_smaller_balance.to_string(),
|
address: token_with_smaller_balance.to_string(),
|
||||||
amount: UiTokenAmount {
|
amount: UiTokenAmount {
|
||||||
ui_amount: "0.1".to_string(),
|
ui_amount: 0.1,
|
||||||
decimals: 2,
|
decimals: 2,
|
||||||
amount: "10".to_string(),
|
amount: "10".to_string(),
|
||||||
}
|
}
|
||||||
@ -6106,7 +6106,7 @@ pub mod tests {
|
|||||||
"mint": mint.to_string(),
|
"mint": mint.to_string(),
|
||||||
"owner": owner.to_string(),
|
"owner": owner.to_string(),
|
||||||
"tokenAmount": {
|
"tokenAmount": {
|
||||||
"uiAmount": "4.2".to_string(),
|
"uiAmount": 4.2,
|
||||||
"decimals": 2,
|
"decimals": 2,
|
||||||
"amount": "420",
|
"amount": "420",
|
||||||
},
|
},
|
||||||
@ -6114,12 +6114,12 @@ pub mod tests {
|
|||||||
"state": "initialized",
|
"state": "initialized",
|
||||||
"isNative": true,
|
"isNative": true,
|
||||||
"rentExemptReserve": {
|
"rentExemptReserve": {
|
||||||
"uiAmount": "0.1".to_string(),
|
"uiAmount": 0.1,
|
||||||
"decimals": 2,
|
"decimals": 2,
|
||||||
"amount": "10",
|
"amount": "10",
|
||||||
},
|
},
|
||||||
"delegatedAmount": {
|
"delegatedAmount": {
|
||||||
"uiAmount": "0.3".to_string(),
|
"uiAmount": 0.3,
|
||||||
"decimals": 2,
|
"decimals": 2,
|
||||||
"amount": "30",
|
"amount": "30",
|
||||||
},
|
},
|
||||||
|
@ -105,5 +105,5 @@ EOF
|
|||||||
|
|
||||||
|
|
||||||
_ example_helloworld
|
_ example_helloworld
|
||||||
# _ spl
|
_ spl
|
||||||
_ serum_dex
|
_ serum_dex
|
||||||
|
@ -104,8 +104,6 @@ pub struct UiTokenAmount {
|
|||||||
pub decimals: u32,
|
pub decimals: u32,
|
||||||
#[prost(string, tag = "3")]
|
#[prost(string, tag = "3")]
|
||||||
pub amount: ::prost::alloc::string::String,
|
pub amount: ::prost::alloc::string::String,
|
||||||
#[prost(string, tag = "4")]
|
|
||||||
pub ui_amount_string: ::prost::alloc::string::String,
|
|
||||||
}
|
}
|
||||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||||
pub struct Reward {
|
pub struct Reward {
|
||||||
|
@ -70,7 +70,6 @@ message UiTokenAmount {
|
|||||||
double ui_amount = 1;
|
double ui_amount = 1;
|
||||||
uint32 decimals = 2;
|
uint32 decimals = 2;
|
||||||
string amount = 3;
|
string amount = 3;
|
||||||
string ui_amount_string = 4;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum RewardType {
|
enum RewardType {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::StoredExtendedRewards;
|
use crate::StoredExtendedRewards;
|
||||||
use solana_account_decoder::parse_token::{real_number_string_trimmed, UiTokenAmount};
|
use solana_account_decoder::parse_token::UiTokenAmount;
|
||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
hash::Hash,
|
hash::Hash,
|
||||||
instruction::CompiledInstruction,
|
instruction::CompiledInstruction,
|
||||||
@ -14,10 +14,7 @@ use solana_transaction_status::{
|
|||||||
ConfirmedBlock, InnerInstructions, Reward, RewardType, TransactionByAddrInfo,
|
ConfirmedBlock, InnerInstructions, Reward, RewardType, TransactionByAddrInfo,
|
||||||
TransactionStatusMeta, TransactionTokenBalance, TransactionWithStatusMeta,
|
TransactionStatusMeta, TransactionTokenBalance, TransactionWithStatusMeta,
|
||||||
};
|
};
|
||||||
use std::{
|
use std::convert::{TryFrom, TryInto};
|
||||||
convert::{TryFrom, TryInto},
|
|
||||||
str::FromStr,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub mod generated {
|
pub mod generated {
|
||||||
include!(concat!(
|
include!(concat!(
|
||||||
@ -386,10 +383,9 @@ impl From<TransactionTokenBalance> for generated::TokenBalance {
|
|||||||
account_index: value.account_index as u32,
|
account_index: value.account_index as u32,
|
||||||
mint: value.mint,
|
mint: value.mint,
|
||||||
ui_token_amount: Some(generated::UiTokenAmount {
|
ui_token_amount: Some(generated::UiTokenAmount {
|
||||||
|
ui_amount: value.ui_token_amount.ui_amount,
|
||||||
decimals: value.ui_token_amount.decimals as u32,
|
decimals: value.ui_token_amount.decimals as u32,
|
||||||
amount: value.ui_token_amount.amount,
|
amount: value.ui_token_amount.amount,
|
||||||
ui_amount_string: value.ui_token_amount.ui_amount,
|
|
||||||
..generated::UiTokenAmount::default()
|
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -402,14 +398,7 @@ impl From<generated::TokenBalance> for TransactionTokenBalance {
|
|||||||
account_index: value.account_index as u8,
|
account_index: value.account_index as u8,
|
||||||
mint: value.mint,
|
mint: value.mint,
|
||||||
ui_token_amount: UiTokenAmount {
|
ui_token_amount: UiTokenAmount {
|
||||||
ui_amount: if !ui_token_amount.ui_amount_string.is_empty() {
|
ui_amount: ui_token_amount.ui_amount,
|
||||||
ui_token_amount.ui_amount_string
|
|
||||||
} else {
|
|
||||||
real_number_string_trimmed(
|
|
||||||
u64::from_str(&ui_token_amount.amount).unwrap_or(0),
|
|
||||||
ui_token_amount.decimals as u8,
|
|
||||||
)
|
|
||||||
},
|
|
||||||
decimals: ui_token_amount.decimals as u8,
|
decimals: ui_token_amount.decimals as u8,
|
||||||
amount: ui_token_amount.amount,
|
amount: ui_token_amount.amount,
|
||||||
},
|
},
|
||||||
|
@ -12,7 +12,7 @@ use indicatif::{ProgressBar, ProgressStyle};
|
|||||||
use pickledb::PickleDb;
|
use pickledb::PickleDb;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use solana_account_decoder::parse_token::{
|
use solana_account_decoder::parse_token::{
|
||||||
pubkey_from_spl_token_v2_0, real_number_string, spl_token_v2_0_pubkey,
|
pubkey_from_spl_token_v2_0, spl_token_v2_0_pubkey, token_amount_to_ui_amount,
|
||||||
};
|
};
|
||||||
use solana_client::{
|
use solana_client::{
|
||||||
client_error::{ClientError, Result as ClientResult},
|
client_error::{ClientError, Result as ClientResult},
|
||||||
@ -103,14 +103,12 @@ pub enum Error {
|
|||||||
ClientError(#[from] ClientError),
|
ClientError(#[from] ClientError),
|
||||||
#[error("Missing lockup authority")]
|
#[error("Missing lockup authority")]
|
||||||
MissingLockupAuthority,
|
MissingLockupAuthority,
|
||||||
#[error("insufficient funds in {0:?}, requires {1}")]
|
#[error("insufficient funds in {0:?}, requires {1} SOL")]
|
||||||
InsufficientFunds(FundingSources, String),
|
InsufficientFunds(FundingSources, f64),
|
||||||
#[error("Program error")]
|
#[error("Program error")]
|
||||||
ProgramError(#[from] ProgramError),
|
ProgramError(#[from] ProgramError),
|
||||||
#[error("Exit signal received")]
|
#[error("Exit signal received")]
|
||||||
ExitSignal,
|
ExitSignal,
|
||||||
#[error("Cannot support mint decimals that would overflow")]
|
|
||||||
InvalidMintDecimals,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn merge_allocations(allocations: &[Allocation]) -> Vec<Allocation> {
|
fn merge_allocations(allocations: &[Allocation]) -> Vec<Allocation> {
|
||||||
@ -275,34 +273,33 @@ fn build_messages(
|
|||||||
Some(allocation.lockup_date.parse::<DateTime<Utc>>().unwrap())
|
Some(allocation.lockup_date.parse::<DateTime<Utc>>().unwrap())
|
||||||
};
|
};
|
||||||
|
|
||||||
let do_create_associated_token_account = if let Some(spl_token_args) = &args.spl_token_args
|
let (display_amount, decimals, do_create_associated_token_account) =
|
||||||
{
|
if let Some(spl_token_args) = &args.spl_token_args {
|
||||||
let wallet_address = allocation.recipient.parse().unwrap();
|
let wallet_address = allocation.recipient.parse().unwrap();
|
||||||
let associated_token_address = get_associated_token_address(
|
let associated_token_address = get_associated_token_address(
|
||||||
&wallet_address,
|
&wallet_address,
|
||||||
&spl_token_v2_0_pubkey(&spl_token_args.mint),
|
&spl_token_v2_0_pubkey(&spl_token_args.mint),
|
||||||
);
|
);
|
||||||
let do_create_associated_token_account = client
|
let do_create_associated_token_account =
|
||||||
.get_multiple_accounts(&[pubkey_from_spl_token_v2_0(&associated_token_address)])?
|
client.get_multiple_accounts(&[pubkey_from_spl_token_v2_0(
|
||||||
[0]
|
&associated_token_address,
|
||||||
|
)])?[0]
|
||||||
.is_none();
|
.is_none();
|
||||||
if do_create_associated_token_account {
|
if do_create_associated_token_account {
|
||||||
*created_accounts += 1;
|
*created_accounts += 1;
|
||||||
}
|
}
|
||||||
println!(
|
(
|
||||||
"{:<44} {:>24}",
|
token_amount_to_ui_amount(allocation.amount, spl_token_args.decimals).ui_amount,
|
||||||
allocation.recipient,
|
spl_token_args.decimals as usize,
|
||||||
real_number_string(allocation.amount, spl_token_args.decimals)
|
do_create_associated_token_account,
|
||||||
);
|
)
|
||||||
do_create_associated_token_account
|
|
||||||
} else {
|
} else {
|
||||||
println!(
|
(lamports_to_sol(allocation.amount), 9, false)
|
||||||
"{:<44} {:>24.9}",
|
|
||||||
allocation.recipient,
|
|
||||||
lamports_to_sol(allocation.amount)
|
|
||||||
);
|
|
||||||
false
|
|
||||||
};
|
};
|
||||||
|
println!(
|
||||||
|
"{:<44} {:>24.2$}",
|
||||||
|
allocation.recipient, display_amount, decimals
|
||||||
|
);
|
||||||
let instructions = distribution_instructions(
|
let instructions = distribution_instructions(
|
||||||
allocation,
|
allocation,
|
||||||
&new_stake_account_keypair.pubkey(),
|
&new_stake_account_keypair.pubkey(),
|
||||||
@ -722,7 +719,7 @@ fn check_payer_balances(
|
|||||||
if staker_balance < undistributed_tokens {
|
if staker_balance < undistributed_tokens {
|
||||||
return Err(Error::InsufficientFunds(
|
return Err(Error::InsufficientFunds(
|
||||||
vec![FundingSource::StakeAccount].into(),
|
vec![FundingSource::StakeAccount].into(),
|
||||||
lamports_to_sol(undistributed_tokens).to_string(),
|
lamports_to_sol(undistributed_tokens),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
if args.fee_payer.pubkey() == unlocked_sol_source {
|
if args.fee_payer.pubkey() == unlocked_sol_source {
|
||||||
@ -730,7 +727,7 @@ fn check_payer_balances(
|
|||||||
if balance < fees + total_unlocked_sol {
|
if balance < fees + total_unlocked_sol {
|
||||||
return Err(Error::InsufficientFunds(
|
return Err(Error::InsufficientFunds(
|
||||||
vec![FundingSource::SystemAccount, FundingSource::FeePayer].into(),
|
vec![FundingSource::SystemAccount, FundingSource::FeePayer].into(),
|
||||||
lamports_to_sol(fees + total_unlocked_sol).to_string(),
|
lamports_to_sol(fees + total_unlocked_sol),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -738,14 +735,14 @@ fn check_payer_balances(
|
|||||||
if fee_payer_balance < fees {
|
if fee_payer_balance < fees {
|
||||||
return Err(Error::InsufficientFunds(
|
return Err(Error::InsufficientFunds(
|
||||||
vec![FundingSource::FeePayer].into(),
|
vec![FundingSource::FeePayer].into(),
|
||||||
lamports_to_sol(fees).to_string(),
|
lamports_to_sol(fees),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
let unlocked_sol_balance = client.get_balance(&unlocked_sol_source)?;
|
let unlocked_sol_balance = client.get_balance(&unlocked_sol_source)?;
|
||||||
if unlocked_sol_balance < total_unlocked_sol {
|
if unlocked_sol_balance < total_unlocked_sol {
|
||||||
return Err(Error::InsufficientFunds(
|
return Err(Error::InsufficientFunds(
|
||||||
vec![FundingSource::SystemAccount].into(),
|
vec![FundingSource::SystemAccount].into(),
|
||||||
lamports_to_sol(total_unlocked_sol).to_string(),
|
lamports_to_sol(total_unlocked_sol),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -754,7 +751,7 @@ fn check_payer_balances(
|
|||||||
if balance < fees + undistributed_tokens {
|
if balance < fees + undistributed_tokens {
|
||||||
return Err(Error::InsufficientFunds(
|
return Err(Error::InsufficientFunds(
|
||||||
vec![FundingSource::SystemAccount, FundingSource::FeePayer].into(),
|
vec![FundingSource::SystemAccount, FundingSource::FeePayer].into(),
|
||||||
lamports_to_sol(fees + undistributed_tokens).to_string(),
|
lamports_to_sol(fees + undistributed_tokens),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -762,14 +759,14 @@ fn check_payer_balances(
|
|||||||
if fee_payer_balance < fees {
|
if fee_payer_balance < fees {
|
||||||
return Err(Error::InsufficientFunds(
|
return Err(Error::InsufficientFunds(
|
||||||
vec![FundingSource::FeePayer].into(),
|
vec![FundingSource::FeePayer].into(),
|
||||||
lamports_to_sol(fees).to_string(),
|
lamports_to_sol(fees),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
let sender_balance = client.get_balance(&distribution_source)?;
|
let sender_balance = client.get_balance(&distribution_source)?;
|
||||||
if sender_balance < undistributed_tokens {
|
if sender_balance < undistributed_tokens {
|
||||||
return Err(Error::InsufficientFunds(
|
return Err(Error::InsufficientFunds(
|
||||||
vec![FundingSource::SystemAccount].into(),
|
vec![FundingSource::SystemAccount].into(),
|
||||||
lamports_to_sol(undistributed_tokens).to_string(),
|
lamports_to_sol(undistributed_tokens),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1418,7 +1415,7 @@ mod tests {
|
|||||||
sources,
|
sources,
|
||||||
vec![FundingSource::SystemAccount, FundingSource::FeePayer].into()
|
vec![FundingSource::SystemAccount, FundingSource::FeePayer].into()
|
||||||
);
|
);
|
||||||
assert_eq!(amount, (allocation_amount + fees_in_sol).to_string());
|
assert!((amount - (allocation_amount + fees_in_sol)).abs() < f64::EPSILON);
|
||||||
} else {
|
} else {
|
||||||
panic!("check_payer_balances should have errored");
|
panic!("check_payer_balances should have errored");
|
||||||
}
|
}
|
||||||
@ -1455,7 +1452,7 @@ mod tests {
|
|||||||
sources,
|
sources,
|
||||||
vec![FundingSource::SystemAccount, FundingSource::FeePayer].into()
|
vec![FundingSource::SystemAccount, FundingSource::FeePayer].into()
|
||||||
);
|
);
|
||||||
assert_eq!(amount, (allocation_amount + fees_in_sol).to_string());
|
assert!((amount - (allocation_amount + fees_in_sol)).abs() < f64::EPSILON);
|
||||||
} else {
|
} else {
|
||||||
panic!("check_payer_balances should have errored");
|
panic!("check_payer_balances should have errored");
|
||||||
}
|
}
|
||||||
@ -1511,7 +1508,7 @@ mod tests {
|
|||||||
let err_result = check_payer_balances(1, &allocations, &client, &args).unwrap_err();
|
let err_result = check_payer_balances(1, &allocations, &client, &args).unwrap_err();
|
||||||
if let Error::InsufficientFunds(sources, amount) = err_result {
|
if let Error::InsufficientFunds(sources, amount) = err_result {
|
||||||
assert_eq!(sources, vec![FundingSource::SystemAccount].into());
|
assert_eq!(sources, vec![FundingSource::SystemAccount].into());
|
||||||
assert_eq!(amount, allocation_amount.to_string());
|
assert!((amount - allocation_amount).abs() < f64::EPSILON);
|
||||||
} else {
|
} else {
|
||||||
panic!("check_payer_balances should have errored");
|
panic!("check_payer_balances should have errored");
|
||||||
}
|
}
|
||||||
@ -1525,7 +1522,7 @@ mod tests {
|
|||||||
let err_result = check_payer_balances(1, &allocations, &client, &args).unwrap_err();
|
let err_result = check_payer_balances(1, &allocations, &client, &args).unwrap_err();
|
||||||
if let Error::InsufficientFunds(sources, amount) = err_result {
|
if let Error::InsufficientFunds(sources, amount) = err_result {
|
||||||
assert_eq!(sources, vec![FundingSource::FeePayer].into());
|
assert_eq!(sources, vec![FundingSource::FeePayer].into());
|
||||||
assert_eq!(amount, fees_in_sol.to_string());
|
assert!((amount - fees_in_sol).abs() < f64::EPSILON);
|
||||||
} else {
|
} else {
|
||||||
panic!("check_payer_balances should have errored");
|
panic!("check_payer_balances should have errored");
|
||||||
}
|
}
|
||||||
@ -1612,10 +1609,7 @@ mod tests {
|
|||||||
check_payer_balances(1, &expensive_allocations, &client, &args).unwrap_err();
|
check_payer_balances(1, &expensive_allocations, &client, &args).unwrap_err();
|
||||||
if let Error::InsufficientFunds(sources, amount) = err_result {
|
if let Error::InsufficientFunds(sources, amount) = err_result {
|
||||||
assert_eq!(sources, vec![FundingSource::StakeAccount].into());
|
assert_eq!(sources, vec![FundingSource::StakeAccount].into());
|
||||||
assert_eq!(
|
assert!((amount - (expensive_allocation_amount - unlocked_sol)).abs() < f64::EPSILON);
|
||||||
amount,
|
|
||||||
(expensive_allocation_amount - unlocked_sol).to_string()
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
panic!("check_payer_balances should have errored");
|
panic!("check_payer_balances should have errored");
|
||||||
}
|
}
|
||||||
@ -1637,7 +1631,7 @@ mod tests {
|
|||||||
sources,
|
sources,
|
||||||
vec![FundingSource::SystemAccount, FundingSource::FeePayer].into()
|
vec![FundingSource::SystemAccount, FundingSource::FeePayer].into()
|
||||||
);
|
);
|
||||||
assert_eq!(amount, (unlocked_sol + fees_in_sol).to_string());
|
assert!((amount - (unlocked_sol + fees_in_sol)).abs() < f64::EPSILON);
|
||||||
} else {
|
} else {
|
||||||
panic!("check_payer_balances should have errored");
|
panic!("check_payer_balances should have errored");
|
||||||
}
|
}
|
||||||
@ -1674,7 +1668,7 @@ mod tests {
|
|||||||
sources,
|
sources,
|
||||||
vec![FundingSource::SystemAccount, FundingSource::FeePayer].into()
|
vec![FundingSource::SystemAccount, FundingSource::FeePayer].into()
|
||||||
);
|
);
|
||||||
assert_eq!(amount, (unlocked_sol + fees_in_sol).to_string());
|
assert!((amount - (unlocked_sol + fees_in_sol)).abs() < f64::EPSILON);
|
||||||
} else {
|
} else {
|
||||||
panic!("check_payer_balances should have errored");
|
panic!("check_payer_balances should have errored");
|
||||||
}
|
}
|
||||||
@ -1737,7 +1731,7 @@ mod tests {
|
|||||||
let err_result = check_payer_balances(1, &allocations, &client, &args).unwrap_err();
|
let err_result = check_payer_balances(1, &allocations, &client, &args).unwrap_err();
|
||||||
if let Error::InsufficientFunds(sources, amount) = err_result {
|
if let Error::InsufficientFunds(sources, amount) = err_result {
|
||||||
assert_eq!(sources, vec![FundingSource::SystemAccount].into());
|
assert_eq!(sources, vec![FundingSource::SystemAccount].into());
|
||||||
assert_eq!(amount, unlocked_sol.to_string());
|
assert!((amount - unlocked_sol).abs() < f64::EPSILON);
|
||||||
} else {
|
} else {
|
||||||
panic!("check_payer_balances should have errored");
|
panic!("check_payer_balances should have errored");
|
||||||
}
|
}
|
||||||
@ -1751,7 +1745,7 @@ mod tests {
|
|||||||
let err_result = check_payer_balances(1, &allocations, &client, &args).unwrap_err();
|
let err_result = check_payer_balances(1, &allocations, &client, &args).unwrap_err();
|
||||||
if let Error::InsufficientFunds(sources, amount) = err_result {
|
if let Error::InsufficientFunds(sources, amount) = err_result {
|
||||||
assert_eq!(sources, vec![FundingSource::FeePayer].into());
|
assert_eq!(sources, vec![FundingSource::FeePayer].into());
|
||||||
assert_eq!(amount, fees_in_sol.to_string());
|
assert!((amount - fees_in_sol).abs() < f64::EPSILON);
|
||||||
} else {
|
} else {
|
||||||
panic!("check_payer_balances should have errored");
|
panic!("check_payer_balances should have errored");
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use console::style;
|
use console::style;
|
||||||
use solana_account_decoder::parse_token::{
|
use solana_account_decoder::parse_token::{
|
||||||
pubkey_from_spl_token_v2_0, real_number_string, spl_token_v2_0_pubkey,
|
pubkey_from_spl_token_v2_0, spl_token_v2_0_pubkey, token_amount_to_ui_amount,
|
||||||
token_amount_to_ui_amount,
|
|
||||||
};
|
};
|
||||||
use solana_client::rpc_client::RpcClient;
|
use solana_client::rpc_client::RpcClient;
|
||||||
use solana_sdk::{instruction::Instruction, native_token::lamports_to_sol};
|
use solana_sdk::{instruction::Instruction, native_token::lamports_to_sol};
|
||||||
@ -110,7 +109,7 @@ pub fn check_spl_token_balances(
|
|||||||
if fee_payer_balance < fees + account_creation_amount {
|
if fee_payer_balance < fees + account_creation_amount {
|
||||||
return Err(Error::InsufficientFunds(
|
return Err(Error::InsufficientFunds(
|
||||||
vec![FundingSource::FeePayer].into(),
|
vec![FundingSource::FeePayer].into(),
|
||||||
lamports_to_sol(fees + account_creation_amount).to_string(),
|
lamports_to_sol(fees + account_creation_amount),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
let source_token_account = client
|
let source_token_account = client
|
||||||
@ -143,12 +142,20 @@ pub fn print_token_balances(
|
|||||||
let (actual, difference) = if let Ok(recipient_token) =
|
let (actual, difference) = if let Ok(recipient_token) =
|
||||||
SplTokenAccount::unpack(&recipient_account.data)
|
SplTokenAccount::unpack(&recipient_account.data)
|
||||||
{
|
{
|
||||||
let actual_ui_amount = real_number_string(recipient_token.amount, spl_token_args.decimals);
|
let actual_ui_amount =
|
||||||
let delta_string =
|
token_amount_to_ui_amount(recipient_token.amount, spl_token_args.decimals).ui_amount;
|
||||||
real_number_string(recipient_token.amount - expected, spl_token_args.decimals);
|
let expected_ui_amount =
|
||||||
|
token_amount_to_ui_amount(expected, spl_token_args.decimals).ui_amount;
|
||||||
(
|
(
|
||||||
style(format!("{:>24}", actual_ui_amount)),
|
style(format!(
|
||||||
format!("{:>24}", delta_string),
|
"{:>24.1$}",
|
||||||
|
actual_ui_amount, spl_token_args.decimals as usize
|
||||||
|
)),
|
||||||
|
format!(
|
||||||
|
"{:>24.1$}",
|
||||||
|
actual_ui_amount - expected_ui_amount,
|
||||||
|
spl_token_args.decimals as usize
|
||||||
|
),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
(
|
(
|
||||||
@ -157,11 +164,12 @@ pub fn print_token_balances(
|
|||||||
)
|
)
|
||||||
};
|
};
|
||||||
println!(
|
println!(
|
||||||
"{:<44} {:>24} {:>24} {:>24}",
|
"{:<44} {:>24.4$} {:>24} {:>24}",
|
||||||
allocation.recipient,
|
allocation.recipient,
|
||||||
real_number_string(expected, spl_token_args.decimals),
|
token_amount_to_ui_amount(expected, spl_token_args.decimals).ui_amount,
|
||||||
actual,
|
actual,
|
||||||
difference,
|
difference,
|
||||||
|
spl_token_args.decimals as usize
|
||||||
);
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -888,7 +888,7 @@ mod test {
|
|||||||
"mint": keys[3].to_string(),
|
"mint": keys[3].to_string(),
|
||||||
"authority": keys[0].to_string(),
|
"authority": keys[0].to_string(),
|
||||||
"tokenAmount": {
|
"tokenAmount": {
|
||||||
"uiAmount": "0.42",
|
"uiAmount": 0.42,
|
||||||
"decimals": 2,
|
"decimals": 2,
|
||||||
"amount": "42"
|
"amount": "42"
|
||||||
}
|
}
|
||||||
@ -920,7 +920,7 @@ mod test {
|
|||||||
"multisigAuthority": keys[5].to_string(),
|
"multisigAuthority": keys[5].to_string(),
|
||||||
"signers": keys[0..2].iter().map(|key| key.to_string()).collect::<Vec<String>>(),
|
"signers": keys[0..2].iter().map(|key| key.to_string()).collect::<Vec<String>>(),
|
||||||
"tokenAmount": {
|
"tokenAmount": {
|
||||||
"uiAmount": "0.42",
|
"uiAmount": 0.42,
|
||||||
"decimals": 2,
|
"decimals": 2,
|
||||||
"amount": "42"
|
"amount": "42"
|
||||||
}
|
}
|
||||||
@ -952,7 +952,7 @@ mod test {
|
|||||||
"delegate": keys[3].to_string(),
|
"delegate": keys[3].to_string(),
|
||||||
"owner": keys[0].to_string(),
|
"owner": keys[0].to_string(),
|
||||||
"tokenAmount": {
|
"tokenAmount": {
|
||||||
"uiAmount": "0.42",
|
"uiAmount": 0.42,
|
||||||
"decimals": 2,
|
"decimals": 2,
|
||||||
"amount": "42"
|
"amount": "42"
|
||||||
}
|
}
|
||||||
@ -984,7 +984,7 @@ mod test {
|
|||||||
"multisigOwner": keys[5].to_string(),
|
"multisigOwner": keys[5].to_string(),
|
||||||
"signers": keys[0..2].iter().map(|key| key.to_string()).collect::<Vec<String>>(),
|
"signers": keys[0..2].iter().map(|key| key.to_string()).collect::<Vec<String>>(),
|
||||||
"tokenAmount": {
|
"tokenAmount": {
|
||||||
"uiAmount": "0.42",
|
"uiAmount": 0.42,
|
||||||
"decimals": 2,
|
"decimals": 2,
|
||||||
"amount": "42"
|
"amount": "42"
|
||||||
}
|
}
|
||||||
@ -1014,7 +1014,7 @@ mod test {
|
|||||||
"account": keys[2].to_string(),
|
"account": keys[2].to_string(),
|
||||||
"mintAuthority": keys[0].to_string(),
|
"mintAuthority": keys[0].to_string(),
|
||||||
"tokenAmount": {
|
"tokenAmount": {
|
||||||
"uiAmount": "0.42",
|
"uiAmount": 0.42,
|
||||||
"decimals": 2,
|
"decimals": 2,
|
||||||
"amount": "42"
|
"amount": "42"
|
||||||
}
|
}
|
||||||
@ -1044,7 +1044,7 @@ mod test {
|
|||||||
"mint": keys[2].to_string(),
|
"mint": keys[2].to_string(),
|
||||||
"authority": keys[0].to_string(),
|
"authority": keys[0].to_string(),
|
||||||
"tokenAmount": {
|
"tokenAmount": {
|
||||||
"uiAmount": "0.42",
|
"uiAmount": 0.42,
|
||||||
"decimals": 2,
|
"decimals": 2,
|
||||||
"amount": "42"
|
"amount": "42"
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user