cli: Accounts subcmd

This commit is contained in:
Armani Ferrante 2021-01-30 20:13:07 -08:00
parent 1fcea7cf01
commit e4ef35bb19
No known key found for this signature in database
GPG Key ID: D597A80BCF8E12B7
3 changed files with 78 additions and 10 deletions

2
Cargo.lock generated
View File

@ -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",

View File

@ -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"

View File

@ -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())?;