Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ Added new function to read keypair file generated by Anchor #102

Merged
merged 1 commit into from
Sep 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 3 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,11 @@ async fn init_fixture() -> Fixture {
// create a test fixture
let mut fixture = Fixture {
client: Client::new(system_keypair(0)),
// make sure your program is using a correct program ID
program: program_keypair(1),
// make sure to pass the correct name of your program
program: anchor_keypair("my_program_name").unwrap(),
state: keypair(42),
};
// deploy a tested program
// deploy the program to test
fixture.deploy().await?;
// call instruction init
my_instruction::initialize(
Expand Down Expand Up @@ -129,15 +129,6 @@ async fn test_happy_path(#[future] init_fixture: Result<Fixture>) {
}
```

Make sure your program is using a correct program ID in the `derive_id!(...)` macro and inside `Anchor.toml`.
If not, obtain the public key of a key pair you're using and replace it in these two places.
To get the program ID of a key pair (key pair's public key) the `trdelnik key-pair` command can be used.
For example
```
$ trdelnik key-pair program 7
```
will print information about the key pair received from `program_keypair(7)`.

#### Instructions with custom structures

- If you want to test an instruction which has custom structure as an argument
Expand Down
33 changes: 33 additions & 0 deletions crates/client/src/keys.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,37 @@
use std::error::Error;

use anchor_client::solana_sdk::signer::keypair::Keypair;
use heck::ToSnakeCase;
use solana_sdk::signer::EncodableKey;

use crate::config::Config;
use thiserror::Error;

#[derive(Error, Debug)]
pub enum KeyPairError {
#[error("Cannot find the Anchor.toml file to locate the root folder")]
BadWorkspace,
#[error("Cannot the program keypair JSON file generated by Anchor")]
AnchorKeypairNotFound,
}

/// Reads program keypair JSON file generated by Anchor based on `program_name`. Returns error if not found.
pub fn anchor_keypair(program_name: &str) -> Result<Keypair, Box<dyn Error>> {
let root = match Config::discover_root() {
Ok(root) => root,
Err(_) => return Err(KeyPairError::BadWorkspace.into()),
};
let keypair_path = root
.join("target")
.join("deploy")
.join(format!("{}-keypair.json", program_name.to_snake_case()));

if !keypair_path.exists() {
return Err(KeyPairError::AnchorKeypairNotFound.into());
}

Keypair::read_from_file(keypair_path)
}

/// Generate a random keypair.
pub fn random_keypair() -> Keypair {
Expand Down
3 changes: 1 addition & 2 deletions crates/client/src/templates/trdelnik-tests/test.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use fehler::throws;
use program_client::*;
use trdelnik_client::{anyhow::Result, *};

// @todo: create and deploy your fixture
Expand Down Expand Up @@ -30,7 +29,7 @@ impl Fixture {
fn new() -> Self {
Fixture {
client: Client::new(system_keypair(0)),
program: program_keypair(1),
program: anchor_keypair("###PROGRAM_NAME###").unwrap(),
state: keypair(42),
}
}
Expand Down
5 changes: 4 additions & 1 deletion crates/client/src/test_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,10 @@ impl TestGenerator {
throw!(Error::NoProgramsFound)
};
let test_content = test_content.replace("###PROGRAM_NAME###", program_name);
self.create_file(&test_path, TESTS_FILE_NAME, &test_content)
let use_instructions = format!("use program_client::{}_instruction::*;\n", program_name);
let template = format!("{use_instructions}{test_content}");

self.create_file(&test_path, TESTS_FILE_NAME, &template)
.await?;

let cargo_toml_path = workspace_path.join(CARGO_TOML);
Expand Down
6 changes: 5 additions & 1 deletion examples/escrow/trdelnik-tests/tests/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,8 +200,12 @@ impl Fixture {
fn new() -> Self {
Fixture {
client: Client::new(system_keypair(0)),
program: program_keypair(1),

// We use the hardcoded program_keypair(1) to ensure users can run these tests without the
// need to modify the program ID in the program's lib.rs source file and in Anchor.toml configuraiton file.
// However the default option in the test template is now to use the keypair generated by Anchor
// located in target/deploy folder using the function anchor_keypair("name_of_your_program").
program: program_keypair(1),
mint_a: keypair(1),
mint_b: keypair(2),
mint_authority: system_keypair(1),
Expand Down
5 changes: 5 additions & 0 deletions examples/turnstile/trdelnik-tests/tests/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ async fn init_fixture() -> Fixture {
// create a test fixture
let fixture = Fixture {
client: Client::new(system_keypair(0)),

// We use the hardcoded program_keypair(1) to ensure users can run these tests without the
// need to modify the program ID in the program's lib.rs source file and in Anchor.toml configuraiton file.
// However the default option in the test template is now to use the keypair generated by Anchor
// located in target/deploy folder using the function anchor_keypair("name_of_your_program").
program: program_keypair(1),
state: keypair(42),
user_initializer: keypair(45),
Expand Down
Loading