pub mod exceptions;
#[cfg(feature = "helpers")]
pub mod faucet_generation;
use crate::constants::CryptoAlgorithm;
use crate::core::addresscodec::classic_address_to_xaddress;
use crate::core::keypairs::derive_classic_address;
use crate::core::keypairs::derive_keypair;
use crate::core::keypairs::generate_seed;
use alloc::string::String;
use core::fmt::{Debug, Display};
use exceptions::XRPLWalletResult;
use zeroize::Zeroize;
pub struct Wallet {
pub seed: String,
pub public_key: String,
pub private_key: String,
pub classic_address: String,
pub sequence: u64,
}
impl Drop for Wallet {
fn drop(&mut self) {
self.seed.zeroize();
self.public_key.zeroize();
self.private_key.zeroize();
self.classic_address.zeroize();
self.sequence.zeroize();
}
}
impl Debug for Wallet {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("Wallet")
.field("seed", &"***REDACTED***")
.field("public_key", &self.public_key)
.field("private_key", &"***REDACTED***")
.field("classic_address", &self.classic_address)
.field("sequence", &self.sequence)
.finish()
}
}
impl Wallet {
pub fn new(seed: &str, sequence: u64) -> XRPLWalletResult<Self> {
let (public_key, private_key) = derive_keypair(seed, false)?;
let classic_address = derive_classic_address(&public_key)?;
Ok(Wallet {
seed: seed.into(),
public_key,
private_key,
classic_address,
sequence,
})
}
pub fn create(crypto_algorithm: Option<CryptoAlgorithm>) -> XRPLWalletResult<Self> {
Self::new(&generate_seed(None, crypto_algorithm)?, 0)
}
pub fn get_xaddress(
&self,
tag: Option<u64>,
is_test_network: bool,
) -> XRPLWalletResult<String> {
Ok(classic_address_to_xaddress(
&self.classic_address,
tag,
is_test_network,
)?)
}
}
#[cfg(all(test, feature = "wallet"))]
mod tests {
use super::*;
const GENESIS_SEED: &str = "snoPBrXtMeMyMHUVTgbuqAfg1SUTb";
#[test]
fn test_debug_redacts_secrets_and_shows_public_key() {
let wallet = Wallet::new(GENESIS_SEED, 0).expect("genesis wallet");
let debug_output = alloc::format!("{:?}", wallet);
assert!(
debug_output.contains(&wallet.public_key),
"public_key should appear in Debug output"
);
assert!(
debug_output.contains(&wallet.classic_address),
"classic_address should appear in Debug output"
);
assert!(
!debug_output.contains(&wallet.seed),
"seed must not appear in Debug output"
);
assert!(
!debug_output.contains(&wallet.private_key),
"private_key must not appear in Debug output"
);
}
}
impl Display for Wallet {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
write!(
f,
"Wallet {{ public_key: {}, private_key: -HIDDEN-, classic_address: {} }}",
self.public_key, self.classic_address
)
}
}