Skip to content
Open
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
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Generated by Cargo
# will have compiled files and executables
/target/
target/

# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
Expand All @@ -14,3 +14,6 @@ Cargo.lock
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json

.idea
.anchor
32 changes: 16 additions & 16 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,26 +11,26 @@ anchor = ["anchor-lang"]
pyth = ["pyth-sdk-solana"]

[dependencies]
solana-program-test = "1.18"
solana-sdk = "1.18"
solana-program ="1.18"
solana-banks-client = "1.18"
solana-program-runtime = "1.18"
solana-client = "1.18"
spl-token = "4.0.0"
spl-associated-token-account = "1.1.2"
anchor-lang = { version = "0.30.0", optional = true }
async-trait = "0.1.52"
solana-program-test = "=1.18"
solana-sdk = "=1.18"
solana-program = "=1.18"
solana-banks-client = "=1.18"
solana-program-runtime = "=1.18"
solana-client = "=1.18"
spl-token = "=4.0.0"
spl-associated-token-account = "=2.3.0"
anchor-lang = { version = "0.30.1", optional = true }
async-trait = "0.1.81"
futures = "0.3"
borsh = "0.9"
borsh = "0.10.3"
bincode = "1.3.3"
log = "0.4"
chrono-humanize = "0.2"
pyth-sdk-solana = { version = "0.10.1", optional = true }
serde = { version = "1.0.152"}
serde_json = { version = "1.0.91", optional = true }
thiserror = "1.0.38"
serde = { version = "1.0.207" }
serde_json = { version = "1.0.124", optional = true }
thiserror = "1.0.63"

[dev-dependencies]
program-for-tests = {path="tests/artifacts/program_for_tests"}
solana-test-validator = "1.18"
program-for-tests = { path = "tests/testsuite/artifacts/program_for_tests" }
solana-test-validator = "=1.18"
13 changes: 0 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,19 +134,6 @@ async fn create_associated_token_account(

 

Deploy a final program

```rust
async fn deploy_program(
&mut self,
path_to_program: &str,
program_keypair: &Keypair,
payer: &Keypair,
) -> Result<(), Box<dyn std::error::Error>>
```

&nbsp;

Deploy an upgradeable program

```rust
Expand Down
109 changes: 23 additions & 86 deletions src/extensions/client/banks_client.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use super::*;

#[cfg(feature = "pyth")]
use pyth_sdk_solana::state::PriceAccount;
use pyth_sdk_solana::state::SolanaPriceAccount;

#[async_trait]
impl ClientExtensions for BanksClient {
Expand All @@ -26,35 +26,37 @@ impl ClientExtensions for BanksClient {
&mut self,
address: Pubkey,
) -> Result<T, Box<dyn std::error::Error>> {
self.get_account(address)
.map(|result| {
let account = result?.ok_or(BanksClientError::ClientError("Account not found"))?;
T::try_deserialize(&mut account.data.as_ref())
.map_err(|_| BanksClientError::ClientError("Failed to deserialize account"))
})
.await
.map_err(Into::into)
let account = self
.get_account(address)
.await?
.ok_or(BanksClientError::ClientError("Account not found"))?;
T::try_deserialize(&mut account.data.as_ref()).map_err(|_| {
Into::into(BanksClientError::ClientError(
"Failed to deserialize account",
))
})
}

async fn get_account_with_borsh<T: BorshDeserialize>(
&mut self,
address: Pubkey,
) -> Result<T, Box<dyn std::error::Error>> {
self.get_account(address)
.map(|result| {
let account = result?.ok_or(BanksClientError::ClientError("Account not found"))?;
T::deserialize(&mut account.data.as_ref())
.map_err(|_| BanksClientError::ClientError("Failed to deserialize account"))
})
.await
.map_err(Into::into)
let account = self
.get_account(address)
.await?
.ok_or(BanksClientError::ClientError("Account not found"))?;
T::deserialize(&mut account.data.as_ref()).map_err(|_| {
Into::into(BanksClientError::ClientError(
"Failed to deserialize account",
))
})
}

#[cfg(feature = "pyth")]
async fn get_pyth_price_account(
&mut self,
address: Pubkey,
) -> Result<PriceAccount, Box<dyn std::error::Error>> {
) -> Result<SolanaPriceAccount, Box<dyn std::error::Error>> {
let account = self.get_account(address).await?.unwrap();

let price_account = pyth_sdk_solana::state::load_price_account(account.data.as_ref())
Expand Down Expand Up @@ -168,7 +170,8 @@ impl ClientExtensions for BanksClient {
token_program_id: &Pubkey,
) -> Result<Pubkey, Box<dyn std::error::Error>> {
let latest_blockhash = self.get_latest_blockhash().await?;
let associated_token_account = get_associated_token_address(account, mint);
let associated_token_account =
get_associated_token_address_with_program_id(account, mint, token_program_id);
let ix =
create_associated_token_account_ix(&payer.pubkey(), account, mint, token_program_id);

Expand All @@ -183,71 +186,6 @@ impl ClientExtensions for BanksClient {
return Ok(associated_token_account);
}

async fn deploy_program(
&mut self,
path_to_program: &str,
program_keypair: &Keypair,
payer: &Keypair,
) -> Result<(), Box<dyn std::error::Error>> {
let (buffer, buffer_len) = util::load_file_to_bytes(path_to_program);

let program_data = buffer;

// multiply by 2 so program can be updated later on
let program_len = buffer_len;
let minimum_balance = Rent::default().minimum_balance(
bpf_loader_upgradeable::UpgradeableLoaderState::programdata_len(program_len)
.expect("Cannot get program len"),
);
let latest_blockhash = self.get_latest_blockhash().await?;

// 1 Create account
self.process_transaction(system_transaction::create_account(
payer,
program_keypair,
latest_blockhash,
minimum_balance,
program_len as u64,
&bpf_loader::id(),
))
.await
.unwrap();

// 2. Write to buffer
let deploy_ix = |offset: u32, bytes: Vec<u8>| {
loader_instruction::write(&program_keypair.pubkey(), &bpf_loader::id(), offset, bytes)
};

let chunk_size = util::calculate_chunk_size(deploy_ix, &vec![payer, program_keypair]);

for (chunk, i) in program_data.chunks(chunk_size).zip(0..) {
let ix = deploy_ix(i * chunk_size as u32, chunk.to_vec());
let tx = self
.transaction_from_instructions(&[ix], payer, vec![payer, program_keypair])
.await
.unwrap();

self.process_transaction(tx).await?;
}

// 3. Finalize
let finalize_tx = self
.transaction_from_instructions(
&[loader_instruction::finalize(
&program_keypair.pubkey(),
&bpf_loader::id(),
)],
payer,
vec![payer, program_keypair],
)
.await
.unwrap();

self.process_transaction(finalize_tx).await?;

return Ok(());
}

async fn deploy_upgradable_program(
&mut self,
path_to_program: &str,
Expand All @@ -263,8 +201,7 @@ impl ClientExtensions for BanksClient {
// multiply by 2 so program can be updated later on
let program_len = buffer_len * 2;
let minimum_balance = Rent::default().minimum_balance(
bpf_loader_upgradeable::UpgradeableLoaderState::programdata_len(program_len)
.expect("Cannot get program len"),
bpf_loader_upgradeable::UpgradeableLoaderState::size_of_programdata(program_len),
);

// 1 Create buffer
Expand Down
32 changes: 9 additions & 23 deletions src/extensions/client/mod.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,17 @@
use async_trait::async_trait;
use borsh::BorshDeserialize;
use futures::FutureExt;
use solana_program::{
bpf_loader_upgradeable,
program_pack::Pack
};
use solana_program::{bpf_loader_upgradeable, program_pack::Pack};
use solana_sdk::{
bpf_loader,
instruction::Instruction,
loader_instruction,
pubkey::Pubkey,
signature::{Keypair, Signer},
system_transaction,
sysvar::rent::Rent,
transaction::Transaction
transaction::Transaction,
};
use spl_associated_token_account::{
get_associated_token_address, instruction::create_associated_token_account as create_associated_token_account_ix,
get_associated_token_address_with_program_id,
instruction::create_associated_token_account as create_associated_token_account_ix,
};

#[cfg(feature = "anchor")]
Expand All @@ -27,13 +22,15 @@ pub use solana_banks_client::{BanksClient, BanksClientError};
mod banks_client;
mod rpc_client;

#[allow(unused_imports)]
pub use banks_client::*;
#[allow(unused_imports)]
pub use rpc_client::*;

use crate::util;

#[cfg(feature = "pyth")]
use pyth_sdk_solana::state::PriceAccount;
use pyth_sdk_solana::state::SolanaPriceAccount;

/// Convenience functions for clients
#[async_trait]
Expand Down Expand Up @@ -68,12 +65,11 @@ pub trait ClientExtensions {
unimplemented!();
}


#[cfg(feature = "pyth")]
async fn get_pyth_price_account(
&mut self,
_address: Pubkey,
) -> Result<PriceAccount, Box<dyn std::error::Error>> {
) -> Result<SolanaPriceAccount, Box<dyn std::error::Error>> {
unimplemented!();
}

Expand Down Expand Up @@ -123,16 +119,6 @@ pub trait ClientExtensions {
unimplemented!();
}

/// Deploy a program
async fn deploy_program(
&mut self,
_path_to_program: &str,
_program_keypair: &Keypair,
_payer: &Keypair,
) -> Result<(), Box<dyn std::error::Error>> {
unimplemented!();
}

/// Deploy an upgradable program
async fn deploy_upgradable_program(
&mut self,
Expand All @@ -144,4 +130,4 @@ pub trait ClientExtensions {
) -> Result<(), Box<dyn std::error::Error>> {
unimplemented!();
}
}
}
Loading