Billetera
El módulo Wallet gestiona pares de claves ed25519, firma mensajes y opcionalmente se conecta a un nodo RPC para consultas en cadena.
Gestión de Claves
Crear una Nueva Billetera
use savitri_sdk::Wallet;
// Par de claves aleatorio (criptográficamente seguro)
let wallet = Wallet::new();
println!("Address: {}", wallet.address()); // 64 hex chars (clave pública de 32 bytes)
Importar desde Clave Privada
// Desde bytes sin procesar
let private_key: [u8; 32] = [/* your key */];
let wallet = Wallet::from_private_key(&private_key)?;
// Desde string hexadecimal
let wallet = Wallet::from_private_key_hex("aabbccdd...64hexchars")?;
// Con prefijo 0x
let wallet = Wallet::from_private_key_hex("0xaabbccdd...64hexchars")?;
Exportar Claves
// Clave pública (segura para compartir)
let pubkey = wallet.public_key();
println!("Public key: {}", hex::encode(pubkey.as_bytes()));
// Dirección (derivada de la clave pública)
println!("Address: {}", wallet.address());
// Clave privada (NUNCA compartir ni registrar)
let privkey: [u8; 32] = wallet.private_key();
Firma
Firmar un Mensaje
let message = b"Hello, Savitri!";
let signature: [u8; 64] = wallet.sign_message(message);
Verificar una Firma
wallet.verify_signature(message, &signature)?;
// Devuelve Ok(()) si es válida, Err si es inválida
El esquema de firma usa Ed25519 (ed25519-dalek). Para la firma de transacciones, el mensaje primero se aplica SHA-256:
message = from_hex || to_hex || amount_le_u64 || nonce_le_u64 || fee_le_u128
hash = SHA-256(message)
sig = Ed25519_sign(hash)
Integración con RPC
Conecta una billetera a un nodo para consultas en cadena:
// Crear con conexión RPC
let wallet = Wallet::with_rpc("http://localhost:8545")?;
// O conectar más tarde
let mut wallet = Wallet::new();
wallet.connect_rpc("http://localhost:8545")?;
// Consultar saldo (requiere RPC)
let balance: String = wallet.get_balance().await?;
println!("Balance: {}", balance);
// Consultar nonce (requiere RPC)
let nonce: u64 = wallet.get_nonce().await?;
println!("Nonce: {}", nonce);
// Acceder al cliente RPC subyacente
if let Some(rpc) = wallet.rpc() {
let height = rpc.get_block_number().await?;
println!("Height: {}", height);
}
Seguridad
- Puesta a cero: El material de la clave privada se pone a cero cuando la billetera se descarta (trait
Dropmediante el cratezeroize). - Comportamiento al clonar: Las billeteras clonadas NO heredan la conexión RPC (comienzan desconectadas).
- Sin persistencia: La billetera no guarda claves en disco. Usa tu propio almacenamiento seguro.
{
let wallet = Wallet::new();
// ... usar billetera ...
} // la billetera se descarta aquí — los bytes de la clave privada se ponen a cero en memoria