From d8a6a719db134713a2ccd77d79883e227590c5a6 Mon Sep 17 00:00:00 2001 From: Ikrk Date: Fri, 15 Sep 2023 16:42:03 +0200 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Added=20new=20function=20to=20read?= =?UTF-8?q?=20keypair=20file=20generated=20by=20Anchor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Until now it was necessary to manually change the program ID to some of the keys predefined by Trdelnik. Now the test template automatically uses the the program keypair generated by Anchor and no manual modification of the program and Anchor.toml is necessary. --- README.md | 15 ++------- crates/client/src/keys.rs | 33 +++++++++++++++++++ .../src/templates/trdelnik-tests/test.rs | 3 +- crates/client/src/test_generator.rs | 5 ++- examples/escrow/trdelnik-tests/tests/test.rs | 6 +++- .../turnstile/trdelnik-tests/tests/test.rs | 5 +++ 6 files changed, 51 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index ffb21b92..623b7b9e 100644 --- a/README.md +++ b/README.md @@ -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( @@ -129,15 +129,6 @@ async fn test_happy_path(#[future] init_fixture: Result) { } ``` -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 diff --git a/crates/client/src/keys.rs b/crates/client/src/keys.rs index ca7f5b80..0f024f81 100644 --- a/crates/client/src/keys.rs +++ b/crates/client/src/keys.rs @@ -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> { + 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 { diff --git a/crates/client/src/templates/trdelnik-tests/test.rs b/crates/client/src/templates/trdelnik-tests/test.rs index 30038124..b64b3188 100644 --- a/crates/client/src/templates/trdelnik-tests/test.rs +++ b/crates/client/src/templates/trdelnik-tests/test.rs @@ -1,5 +1,4 @@ use fehler::throws; -use program_client::*; use trdelnik_client::{anyhow::Result, *}; // @todo: create and deploy your fixture @@ -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), } } diff --git a/crates/client/src/test_generator.rs b/crates/client/src/test_generator.rs index 97435ca6..a6a28ceb 100644 --- a/crates/client/src/test_generator.rs +++ b/crates/client/src/test_generator.rs @@ -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); diff --git a/examples/escrow/trdelnik-tests/tests/test.rs b/examples/escrow/trdelnik-tests/tests/test.rs index 8a7cb352..92ad9dfd 100644 --- a/examples/escrow/trdelnik-tests/tests/test.rs +++ b/examples/escrow/trdelnik-tests/tests/test.rs @@ -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), diff --git a/examples/turnstile/trdelnik-tests/tests/test.rs b/examples/turnstile/trdelnik-tests/tests/test.rs index 16fc2a6a..9c14ea7d 100644 --- a/examples/turnstile/trdelnik-tests/tests/test.rs +++ b/examples/turnstile/trdelnik-tests/tests/test.rs @@ -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),