Skip to content

Commit

Permalink
refactoring of crate structure and execution of txns
Browse files Browse the repository at this point in the history
  • Loading branch information
ochaloup committed Jun 27, 2023
1 parent efa26d2 commit f085414
Show file tree
Hide file tree
Showing 16 changed files with 206 additions and 337 deletions.
7 changes: 7 additions & 0 deletions libs/dynsigner/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[package]
name = "dynsigner"
version = "0.1.0"
edition = "2021"

[dependencies]
solana-sdk = "1.14.18"
22 changes: 22 additions & 0 deletions libs/dynsigner/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# DynSigner

When using Solana labs CLI utilities
(`solana-clap-utils`, https://github.com/solana-labs/solana/tree/master/clap-utils
-> https://github.com/solana-labs/solana/blob/6b013f46ebd30c82f7fa9c50c5a0e9ae32df3c44/clap-utils/src/keypair.rs#L357)
the loaded signer of type `Box<dyn Signer>` is not aligned to the expected `Client<C>` type of `<C: Clone + Deref<Target = impl Signer>>`.
Using the dyn Signer fails with error:

```
the size for values of type `dyn solana_sdk::signature::Signer` cannot be known at compilation time [E0277] doesn't have a size known at compile-time Help: the trait `Sized` is not implemented for `dyn solana_sdk::signature::Signer` Note: required by a bound in `anchor_client::Client::<C>::new_with_options`
```

Adding the helper DynSigner makes possible to match those types and use the Signer loded from the Solana utils with the Anchor client.

```
let fee_payer: Arc<dyn Signer> = ...
let anchor_client: Client<Arc<DynSigner>> = Client::new_with_options(
anchor_cluster,
Arc::new(DynSigner(fee_payer.clone())),
CommitmentConfig::confirmed(),
);
```
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[package]
name = "marinade-common-rs"
name = "marinade-client-rs"
version = "0.1.0"
edition = "2021"

Expand All @@ -14,5 +14,6 @@ spl-associated-token-account = { version = "1.1.3", features = ["no-entrypoint"
log = "0.4.18"
solana-client = "1.14.18"
marinade-finance = { git = "https://github.com/marinade-finance/liquid-staking-program.git", branch = "anchor-0.27" }
dynsigner = { path = "../dynsigner" }
anchor-lang = "0.27.0"
anchor-client = "0.27.0"
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use crate::marinade::instructions::{
use crate::instructions::{
add_liquidity, add_validator, change_authority, claim, config_lp, config_marinade,
config_validator_system, deactivate_stake, deposit, deposit_stake_account, emergency_unstake,
initialize, liquid_unstake, merge_stakes, order_unstake, partial_unstake, remove_liquidity,
remove_validator, set_validator_score, stake_reserve, update_active, update_deactivated,
};
use crate::marinade::rpc_marinade::RpcMarinade;
use crate::rpc_marinade::RpcMarinade;
use anchor_client::RequestBuilder;
use marinade_finance::instructions::{ChangeAuthorityData, ConfigMarinadeParams};
use marinade_finance::state::Fee;
Expand All @@ -13,8 +13,6 @@ use solana_sdk::signer::Signer;
use std::ops::Deref;
use std::sync::Arc;

/// Utilizing the TransactionBuilder from transaction_builder.rs
/// to work with marinade transactions
pub trait TransactionBuilderMarinade<'a, C> {
fn add_validator(
&'a self,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::marinade::verifiers::{verify_admin_authority, verify_manager_authority};
use crate::verifiers::{verify_admin_authority, verify_manager_authority};
use anchor_client::{Program, RequestBuilder};
use marinade_finance::state::liq_pool::LiqPool;
use marinade_finance::state::stake_system::StakeSystem;
Expand Down
11 changes: 11 additions & 0 deletions libs/marinade-client-rs/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#![cfg_attr(not(debug_assertions), deny(warnings))]

pub mod builder;
pub mod instructions;
pub mod rpc_marinade;
pub mod state;
pub mod verifiers;
pub mod transaction_executors;

pub use solana_sdk;
pub use spl_associated_token_account;
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use solana_client::rpc_client::RpcClient;
use solana_sdk::pubkey::Pubkey;
use solana_sdk::signer::Signer;
use std::ops::Deref;
use crate::marinade::state::{StakeInfo, stakes_info_reversed, stakes_info, validator_list, stake_list};
use crate::state::{StakeInfo, stakes_info_reversed, stakes_info, validator_list, stake_list};

pub struct RpcMarinade<C> {
pub client: RpcClient,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use crate::rpc_client_helpers::RpcClientHelpers;
use anchor_lang::AnchorDeserialize;
use anyhow::bail;
use marinade_finance::state::stake_system::StakeRecord;
Expand Down
132 changes: 132 additions & 0 deletions libs/marinade-client-rs/src/transaction_executors.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
use std::ops::Deref;
use anchor_client::{RequestBuilder};
use anyhow::{anyhow};
use log::{debug, error, warn, info};
use solana_client::client_error::ClientErrorKind;
use solana_client::rpc_client::RpcClient;
use solana_client::rpc_config::RpcSendTransactionConfig;
use solana_client::rpc_request::{RpcError, RpcResponseErrorData};
use solana_client::rpc_response::{RpcResult, RpcSimulateTransactionResult};
use solana_sdk::commitment_config::CommitmentLevel;
use solana_sdk::signature::Signature;
use solana_sdk::signer::Signer;

pub trait TransactionExecutor {
fn execute(self, commitment: CommitmentLevel) -> Result<Signature, anchor_client::ClientError>;
}

impl<'a, C: Deref<Target = impl Signer> + Clone> TransactionExecutor for RequestBuilder<'a, C> {
fn execute(self, commitment: CommitmentLevel) -> Result<Signature, anchor_client::ClientError> {
self.send_with_spinner_and_config(RpcSendTransactionConfig {
skip_preflight: false,
preflight_commitment: Some(commitment),
..RpcSendTransactionConfig::default()
})
}
}

pub fn log_execution(execution_result: Result<Signature, anchor_client::ClientError>) {
match execution_result {
Ok(signature) => debug!("Transaction {}", signature),
Err(err) => {
error!("Transaction error: {}", err);
match &err {
anchor_client::ClientError::SolanaClientError(ce) => {
error!("Transaction error: {}", err);
if let ClientErrorKind::RpcError(RpcError::RpcResponseError {
data:
RpcResponseErrorData::SendTransactionPreflightFailure(
RpcSimulateTransactionResult {
err: _,
logs: Some(logs),
accounts: _,
return_data: _,
units_consumed: _,
},
),
..
}) = ce.kind()
{
for log in logs {
error!("Log: {}", log);
}
error!("Transaction ERR {:?}", err);
}
}
_ => {
error!("Transaction ERR {:?}", err);
}
}
}
}
}

pub trait TransactionSimulator {
fn simulate(self, rpc_client: &RpcClient) -> RpcResult<RpcSimulateTransactionResult>;
}

impl<'a, C: Deref<Target = impl Signer> + Clone> TransactionSimulator for RequestBuilder<'a, C> {
fn simulate(self, rpc_client: &RpcClient) -> RpcResult<RpcSimulateTransactionResult> {
let tx = &self.transaction().map_err(|err| {
RpcError::RpcRequestError(format!("Transaction error: {}", err))
})?;
rpc_client.simulate_transaction(tx)
}
}

pub fn log_simulation(simulation_result: RpcResult<RpcSimulateTransactionResult>) {
match simulation_result {
Ok(result) => {
if let Some(logs) = &result.value.logs {
for log in logs {
debug!("Log: {}", log);
}
}
if result.value.err.is_some() {
error!("Transaction ERR {:?}", result);
} else {
info!("Transaction simulation Ok");
}
}
Err(err) => {
error!("Transaction error: {}", err);
if let ClientErrorKind::RpcError(RpcError::RpcResponseError {
data:
RpcResponseErrorData::SendTransactionPreflightFailure(
RpcSimulateTransactionResult {
err: _,
logs: Some(logs),
accounts: _,
units_consumed: _,
return_data: _,
},
),
..
}) = err.kind()
{
for log in logs {
error!("Log: {}", log);
}
error!("Transaction ERR {:?}", err);
}
}
}
}

pub fn execute<'a, I,C>(anchor_builders: I, rpc_client: &RpcClient, simulate: bool) -> anyhow::Result<()>
where
I: IntoIterator<Item = RequestBuilder<'a, C>>,
C: Deref<Target = dynsigner::DynSigner> + Clone
{
if !simulate {
let commitment_level = rpc_client.commitment().commitment;
anchor_builders.into_iter().for_each(|builder| log_execution(builder.execute(commitment_level)));
} else {
let mut builders_iterator = anchor_builders.into_iter();
log_simulation(builders_iterator.next().ok_or(anyhow!("No transactions to simulate"))?.simulate(rpc_client));
if builders_iterator.next().is_some() {
warn!("Simulation mode: only the first transaction was simulated. The rest are ignored.");
}
}
Ok(())
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,17 @@ pub fn verify_manager_authority(
validator_manager_authority: Pubkey,
) -> anyhow::Result<()> {
if state.validator_system.manager_authority != validator_manager_authority {
bail!("Argument '--validator-manager-authority' {} to sign the transaction mismatches Marinade state system manager authority {}",
bail!("Validator-manager-authority {} to sign the transaction mismatches Marinade state system manager authority {}",
validator_manager_authority,
state.validator_system.manager_authority
);
}
Ok(())
}

pub fn verify_admin_authority(state: &State, admin_authority: Pubkey) -> anyhow::Result<()> {
if state.admin_authority != admin_authority {
bail!("Argument '--admin-authority' {} to sign the transaction mismatches Marinade state admin authority {}",
bail!("Admin-authority {} to sign the transaction mismatches Marinade state admin authority {}",
admin_authority,
state.validator_system.manager_authority
);
Expand All @@ -30,7 +31,7 @@ pub fn verify_rent_payer(rpc_client: &RpcClient, rent_payer: Pubkey) -> anyhow::
let rent_account = rpc_client.get_account(&rent_payer)?;
if rent_account.owner != system_program::ID {
bail!(
"Provided rent payer {} must be a system account",
"Provided rent payer {} address must be a system account",
rent_payer
)
}
Expand Down
2 changes: 1 addition & 1 deletion libs/marinade-common-cli/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#![cfg_attr(not(debug_assertions), deny(warnings))]

pub mod config_args;
pub mod processors;
pub mod matchers;
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ use solana_sdk::pubkey::Pubkey;
use solana_sdk::signer::Signer;
use std::{str::FromStr, sync::Arc};

// Try to get signer from the keypair path argument, or a default signer
pub fn signer_or_default(
// Getting signer from the matched name as the keypair path argument, or returns the default signer
pub fn signer_from_path_or_default(
matches: &ArgMatches<'_>,
name: &str,
default_signer: &Arc<dyn Signer>,
Expand All @@ -24,8 +24,8 @@ pub fn signer_or_default(
}
}

// Try to get pubkey from the string or load it from the signer data
pub fn pubkey_of(
/// Getting pubkey from the matched name or load it from the signer data
pub fn pubkey_or_of_signer(
matches: &ArgMatches<'_>,
name: &str,
wallet_manager: &mut Option<Arc<RemoteWalletManager>>,
Expand All @@ -50,8 +50,24 @@ pub fn pubkey_of(
}
}

// Try to get pubkey from the string or load it from the signer data
pub(crate) fn pubkey_or_from_path(
/// Loooking for a set of pubkeys in the matches, and return them as a vector
pub fn process_multiple_pubkeys(
arg_matches: &ArgMatches,
arg_name: &str,
mut wallet_manager: Option<Arc<RemoteWalletManager>>,
) -> anyhow::Result<Vec<Pubkey>> {
let mut value_pubkeys: Vec<Pubkey> = vec![];
if let Some(values) = arg_matches.values_of(arg_name) {
for (i, value) in values.enumerate() {
let name = format!("{}-{}", arg_name, i.saturating_add(1));
let value_pubkey = pubkey_or_from_path(arg_matches, &name, value, &mut wallet_manager)?;
value_pubkeys.push(value_pubkey);
}
}
Ok(value_pubkeys)
}

fn pubkey_or_from_path(
matches: &ArgMatches<'_>,
name: &str,
value_or_path: &str,
Expand All @@ -71,20 +87,4 @@ pub(crate) fn pubkey_or_from_path(
})?;
Ok(signer.pubkey())
}
}

pub fn process_multiple_pubkeys(
arg_matches: &ArgMatches,
arg_name: &str,
mut wallet_manager: Option<Arc<RemoteWalletManager>>,
) -> anyhow::Result<Vec<Pubkey>> {
let mut value_pubkeys: Vec<Pubkey> = vec![];
if let Some(values) = arg_matches.values_of(arg_name) {
for (i, value) in values.enumerate() {
let name = format!("{}-{}", arg_name, i.saturating_add(1));
let value_pubkey = pubkey_or_from_path(arg_matches, &name, value, &mut wallet_manager)?;
value_pubkeys.push(value_pubkey);
}
}
Ok(value_pubkeys)
}
}
8 changes: 0 additions & 8 deletions libs/marinade-common-rs/src/lib.rs

This file was deleted.

5 changes: 0 additions & 5 deletions libs/marinade-common-rs/src/marinade/mod.rs

This file was deleted.

Loading

0 comments on commit f085414

Please sign in to comment.