use std::path::Path;
use tape_api::program::tapedrive::stake_pda;
use tape_crypto::address::Address;
use tape_crypto::ed25519::{Keypair, Pubkey};
use crate::keys::helpers::{load_ed25519_keypair, HelperError};
pub struct StakeKey {
keypair: Keypair,
}
impl StakeKey {
pub fn generate() -> Self {
let mut rng = rand::thread_rng();
Self {
keypair: Keypair::new(&mut rng),
}
}
pub fn load(path: impl AsRef<Path>) -> Result<Self, HelperError> {
let keypair = load_ed25519_keypair(path.as_ref())?;
Ok(Self { keypair })
}
pub fn save(&self, path: impl AsRef<Path>) -> Result<(), std::io::Error> {
let path = path.as_ref();
if let Some(parent) = path.parent() {
if !parent.as_os_str().is_empty() {
std::fs::create_dir_all(parent)?;
}
}
let file = std::fs::File::create(path)?;
serde_json::to_writer(file, &self.keypair.to_keypair_bytes().to_vec())
.map_err(std::io::Error::other)
}
pub fn address(&self) -> Address {
stake_pda(self.keypair.address()).0
}
pub fn pubkey(&self) -> Pubkey {
self.keypair.pubkey()
}
pub fn keypair(&self) -> &Keypair {
&self.keypair
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn generate() {
let key = StakeKey::generate();
assert_eq!(key.address(), stake_pda(key.pubkey().into()).0);
}
#[test]
fn save_and_load() {
let dir = std::env::temp_dir().join("stake_key_test");
let path = dir.join("test.json");
let original = StakeKey::generate();
original.save(&path).unwrap();
let loaded = StakeKey::load(&path).unwrap();
assert_eq!(original.pubkey(), loaded.pubkey());
assert_eq!(original.address(), loaded.address());
std::fs::remove_dir_all(dir).ok();
}
}