turdle_client/
reader.rs

1use anchor_client::solana_sdk::{
2    pubkey::{ParsePubkeyError, Pubkey},
3    signer::keypair::Keypair,
4};
5use ed25519_dalek::SignatureError;
6use fehler::throws;
7use std::{borrow::Cow, io, str::FromStr};
8use thiserror::Error;
9use tokio::fs;
10
11#[derive(Error, Debug)]
12pub enum Error {
13    #[error("cannot read the file")]
14    Io(#[from] io::Error),
15    #[error("deserialization failed")]
16    SerdeJson(#[from] serde_json::Error),
17    #[error("pubkey parsing failed")]
18    Pubkey(#[from] ParsePubkeyError),
19    #[error("keypair parsing failed")]
20    Keypair(#[from] SignatureError),
21}
22
23/// `Reader` allows you to read [Pubkey], [Keypair] and other entities from files.
24pub struct Reader {
25    root: Cow<'static, str>,
26}
27
28impl Reader {
29    /// Creates a new `Reader` instance with the default root `"../../"`.
30    pub fn new() -> Self {
31        Self { root: "../".into() }
32    }
33
34    /// Creates a new `Reader` instance with the provided `root`.
35    pub fn with_root(root: impl Into<Cow<'static, str>>) -> Self {
36        Self { root: root.into() }
37    }
38
39    /// Reads [Pubkey] from `[root]keys/[name]_pub.json`.
40    ///
41    /// # Errors
42    ///
43    /// It fails when:
44    /// - the requested file does not exist or it is not readable.
45    /// - [Pubkey] cannot be parsed from the file content.
46    #[throws]
47    pub async fn pubkey(&self, name: &str) -> Pubkey {
48        let path = format!("{}keys/{}_pub.json", self.root, name);
49        let key: String = serde_json::from_str(&fs::read_to_string(path).await?)?;
50        Pubkey::from_str(&key)?
51    }
52
53    /// Reads [Keypair] from `[root]keys/[name].json`.
54    ///
55    /// # Errors
56    ///
57    /// It fails when:
58    /// - the requested file does not exist or it is not readable.
59    /// - [Keypair] cannot be parsed from the file content.
60    #[throws]
61    pub async fn keypair(&self, name: &str) -> Keypair {
62        let path = format!("{}keys/{}.json", self.root, name);
63        let bytes: Vec<u8> = serde_json::from_str(&fs::read_to_string(path).await?)?;
64        Keypair::from_bytes(&bytes)?
65    }
66
67    /// Reads program data from `[root]target/deploy/[name].so`.
68    ///
69    /// # Errors
70    ///
71    /// It fails when the requested file does not exist or it is not readable.
72    #[throws]
73    pub async fn program_data(&self, name: &str) -> Vec<u8> {
74        fs::read(format!("{}target/deploy/{}.so", self.root, name)).await?
75    }
76}
77
78impl Default for Reader {
79    /// Creates a new `Reader` instance with the default root `"../../"`.
80    fn default() -> Self {
81        Self::new()
82    }
83}