1use sui_crypto::ed25519::Ed25519PrivateKey;
2use sui_sdk_types::Address;
3use std::path::Path;
4use base64ct::Encoding;
5
6pub fn load_keypair(keystore_path: &Path, expected_address: &Address) -> anyhow::Result<Ed25519PrivateKey> {
11 let json_str = std::fs::read_to_string(keystore_path)
12 .map_err(|e| anyhow::anyhow!("Cannot read keystore at {}: {}", keystore_path.display(), e))?;
13 let entries: Vec<String> = serde_json::from_str(&json_str)?;
14
15 for entry in &entries {
16 let raw = base64ct::Base64::decode_vec(entry)
17 .map_err(|_| anyhow::anyhow!("Invalid base64 in keystore entry"))?;
18 if raw.len() != 33 {
19 continue;
20 }
21 let flag = raw[0];
22 if flag != 0x00 {
23 continue;
25 }
26 let key_bytes: [u8; 32] = raw[1..33]
27 .try_into()
28 .map_err(|_| anyhow::anyhow!("Invalid private key length"))?;
29
30 let keypair = Ed25519PrivateKey::new(key_bytes);
31 let derived: Address = keypair.public_key().derive_address();
32
33 if derived == *expected_address {
34 return Ok(keypair);
35 }
36 }
37
38 anyhow::bail!(
39 "No Ed25519 keypair found in keystore matching address: {:?}",
40 expected_address
41 )
42}