Armani Ferrante преди 4 години
родител
ревизия
e4ef35bb19
променени са 3 файла, в които са добавени 78 реда и са изтрити 10 реда
  1. 2 0
      Cargo.lock
  2. 2 0
      cli/Cargo.toml
  3. 74 10
      cli/src/main.rs

+ 2 - 0
Cargo.lock

@@ -104,6 +104,7 @@ dependencies = [
  "anchor-lang",
  "anchor-syn",
  "anyhow",
+ "bs58",
  "clap 3.0.0-beta.2",
  "dirs",
  "flate2",
@@ -113,6 +114,7 @@ dependencies = [
  "serde_yaml",
  "serum-common",
  "shellexpand",
+ "solana-account-decoder",
  "solana-client",
  "solana-program",
  "solana-sdk",

+ 2 - 0
cli/Cargo.toml

@@ -22,7 +22,9 @@ serde = { version = "1.0", features = ["derive"] }
 solana-sdk = "1.5.0"
 solana-program = "1.5.0"
 solana-client = "1.4.4"
+solana-account-decoder = "1.4.13"
 serum-common = { git = "https://github.com/project-serum/serum-dex", features = ["client"] }
 dirs = "3.0"
 heck = "0.3.1"
 flate2 = "1.0.19"
+bs58 = "0.3.1"

+ 74 - 10
cli/src/main.rs

@@ -8,8 +8,12 @@ use flate2::read::ZlibDecoder;
 use flate2::write::ZlibEncoder;
 use flate2::Compression;
 use serde::{Deserialize, Serialize};
+use solana_account_decoder::UiAccountEncoding;
 use solana_client::rpc_client::RpcClient;
-use solana_client::rpc_config::RpcSendTransactionConfig;
+use solana_client::rpc_config::{
+    RpcAccountInfoConfig, RpcProgramAccountsConfig, RpcSendTransactionConfig,
+};
+use solana_client::rpc_filter::{Memcmp, MemcmpEncodedBytes, RpcFilterType};
 use solana_program::instruction::{AccountMeta, Instruction};
 use solana_sdk::commitment_config::CommitmentConfig;
 use solana_sdk::pubkey::Pubkey;
@@ -34,17 +38,13 @@ pub struct Opts {
 pub enum Command {
     /// Initializes a workspace.
     Init { name: String },
-    /// Builds a Solana program.
-    Build {
-        /// Output directory for the IDL.
-        #[clap(short, long)]
-        idl: Option<String>,
-    },
-    /// Runs integration tests against a localnetwork.
+    /// Builds programs.
+    Build,
+    /// Runs integration tests.
     Test,
     /// Creates a new program.
     New { name: String },
-    /// Commands for interact with interface definitions.
+    /// Commands for interface definitions.
     Idl {
         #[clap(subcommand)]
         subcmd: IdlCommand,
@@ -65,6 +65,10 @@ pub enum Command {
     /// Not yet implemented. Please use `solana program deploy` command to
     /// upgrade your program.
     Upgrade {},
+    Account {
+        #[clap(subcommand)]
+        subcmd: AccountCommand,
+    },
 }
 
 #[derive(Debug, Clap)]
@@ -93,12 +97,25 @@ pub enum IdlCommand {
     },
 }
 
+#[derive(Debug, Clap)]
+pub enum AccountCommand {
+    /// Outputs program owned accounts.
+    List {
+        #[clap(short, long)]
+        program: Pubkey,
+        /// The account kind. Matches the type defined in the program source,
+        /// lowercase.
+        #[clap(short, long)]
+        kind: Option<String>,
+    },
+}
+
 fn main() -> Result<()> {
     let opts = Opts::parse();
 
     match opts.command {
         Command::Init { name } => init(name),
-        Command::Build { idl } => build(idl),
+        Command::Build => build(None),
         Command::Test => test(),
         Command::New { name } => new(name),
         Command::Idl { subcmd } => idl(subcmd),
@@ -108,14 +125,61 @@ fn main() -> Result<()> {
             Ok(())
         }
         Command::Migrate { url } => migrate(&url),
+        Command::Account { subcmd } => account(subcmd),
     }
 }
 
+fn account(cmd: AccountCommand) -> Result<()> {
+    match cmd {
+        AccountCommand::List { program, kind } => account_list(program, kind),
+    }
+}
+
+fn account_list(program: Pubkey, kind: Option<String>) -> Result<()> {
+    let cfg = Config::discover()?.expect("Must be inside a workspace").0;
+    let client = RpcClient::new(cfg.cluster.url().to_string());
+
+    // Filter on the 8 byte account discriminator.
+    let filters = kind.map(|kind| {
+        let filter_bytes = {
+            let discriminator_preimage = format!("account:{}", kind);
+            let mut disc = [0u8; 8];
+            disc.copy_from_slice(
+                &solana_program::hash::hash(discriminator_preimage.as_bytes()).to_bytes()[..8],
+            );
+            bs58::encode(disc).into_string()
+        };
+        let disc_filter = RpcFilterType::Memcmp(Memcmp {
+            offset: 0,
+            bytes: MemcmpEncodedBytes::Binary(filter_bytes),
+            encoding: None,
+        });
+
+        vec![disc_filter]
+    });
+
+    let resp = client.get_program_accounts_with_config(
+        &program,
+        RpcProgramAccountsConfig {
+            filters,
+            account_config: RpcAccountInfoConfig {
+                encoding: Some(UiAccountEncoding::Base64),
+                ..RpcAccountInfoConfig::default()
+            },
+        },
+    )?;
+
+    println!("RESP {:?}", resp);
+
+    Ok(())
+}
+
 fn init(name: String) -> Result<()> {
     let cfg = Config::discover()?;
 
     if cfg.is_some() {
         println!("Anchor workspace already initialized");
+        return Ok(());
     }
 
     fs::create_dir(name.clone())?;