-
Notifications
You must be signed in to change notification settings - Fork 122
Feat/675 on chain ouis devaddrs #431
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
Changes from all commits
6060787
8cae4db
58cf64b
d2bf60c
b1734cc
c755093
bd87fdd
db7f998
2031f39
b2f4780
7a67eed
e827eeb
dc47049
040fc93
0e750c9
9ee2bb8
3b38d76
74c9d34
381423a
1e6ee06
3f245d4
3b7f815
1ea9ba3
02d5791
3abf8a9
e14d61a
174b779
3d10078
3b2249d
0a36e98
b5ababb
7d558b4
0623a99
c8a587f
d4ef2c9
ca0308c
c9431ea
e79b802
7557c35
9c907a8
4642b8f
8fde91e
fbdf4d3
25147f3
d46f7e9
2527773
0dd0e45
16239b5
fb7c2c4
4d8ea0f
a62acdb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,15 +3,22 @@ use crate::{ | |
| asset, | ||
| error::{DecodeError, Error}, | ||
| is_zero, | ||
| keypair::{self, Pubkey}, | ||
| keypair::{self, Keypair, Pubkey}, | ||
| priority_fee::auto_compute_limit_and_price, | ||
| solana_client, | ||
| solana_sdk::{commitment_config::CommitmentConfig, signer::Signer}, | ||
| }; | ||
|
|
||
| use anchor_client::solana_client::send_and_confirm_transactions_in_parallel; | ||
| use futures::{stream, StreamExt, TryStreamExt}; | ||
| use itertools::Itertools; | ||
| use jsonrpc_client::{JsonRpcError, SendRequest}; | ||
| use solana_sdk::{instruction::Instruction, message::Message, transaction::Transaction}; | ||
| use std::{marker::Send, sync::Arc}; | ||
| use tracing::instrument; | ||
|
|
||
| pub use solana_client::nonblocking::rpc_client::RpcClient as SolanaRpcClient; | ||
|
|
||
| pub static ONBOARDING_URL_MAINNET: &str = "https://onboarding.dewi.org/api/v3"; | ||
| pub static ONBOARDING_URL_DEVNET: &str = "https://onboarding.web.test-helium.com/api/v3"; | ||
|
|
||
|
|
@@ -23,17 +30,153 @@ pub static SOLANA_URL_DEVNET: &str = "https://solana-rpc.web.test-helium.com?ses | |
| pub static SOLANA_URL_MAINNET_ENV: &str = "SOLANA_MAINNET_URL"; | ||
| pub static SOLANA_URL_DEVNET_ENV: &str = "SOLANA_DEVNET_URL"; | ||
|
|
||
| pub use solana_client::nonblocking::rpc_client::RpcClient as SolanaRpcClient; | ||
| static USER_AGENT: &str = concat!(env!("CARGO_PKG_NAME"), "/", env!("CARGO_PKG_VERSION"),); | ||
|
|
||
| #[derive(Clone)] | ||
| pub struct SolanaClient { | ||
| pub inner: Arc<SolanaRpcClient>, | ||
| pub base_url: String, | ||
| pub keypair: Option<Arc<Keypair>>, | ||
| } | ||
|
|
||
| impl Default for SolanaClient { | ||
| fn default() -> Self { | ||
| // safe to unwrap | ||
| Self::new(SOLANA_URL_MAINNET, None).unwrap() | ||
| } | ||
| } | ||
|
|
||
| impl SolanaClient { | ||
| pub fn new(url: &str, keypair: Option<Arc<Keypair>>) -> Result<Self, Error> { | ||
| let client = Arc::new( | ||
| solana_client::nonblocking::rpc_client::RpcClient::new_with_commitment( | ||
| url.to_string(), | ||
| CommitmentConfig::finalized(), | ||
| ), | ||
| ); | ||
|
|
||
| // Add debug print for keypair | ||
| if let Some(kp) = &keypair { | ||
| println!("Initializing SolanaClient with keypair: {:?}", kp.pubkey()); | ||
| } else { | ||
| println!("Initializing SolanaClient without keypair"); | ||
| } | ||
|
|
||
| Ok(Self { | ||
| inner: client, | ||
| base_url: url.to_string(), | ||
| keypair, | ||
| }) | ||
| } | ||
|
|
||
| pub fn ws_url(&self) -> String { | ||
| self.base_url | ||
| .replace("https", "wss") | ||
| .replace("http", "ws") | ||
| .replace("127.0.0.1:8899", "127.0.0.1:8900") | ||
| } | ||
|
|
||
| pub fn pubkey(&self) -> Result<Pubkey, Error> { | ||
| self.keypair | ||
| .as_ref() | ||
| .map(|keypair| keypair.pubkey()) | ||
| .ok_or_else(|| Error::KeypairUnconfigured) | ||
| } | ||
|
|
||
| pub async fn send_instructions( | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Curiously, where is this function actuallly used?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. used in multiple places on this pr helium/helium-config-service-cli#67
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. right which really doesn't need to use instructions but can use the transaction form constructor functions, since they're all just passing in a single or fixed number of ixs
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Im not following? Is it bad to just pass the instructions to |
||
| &self, | ||
| ixs: &[Instruction], | ||
| extra_signers: &[Keypair], | ||
| ) -> Result<(), Error> { | ||
| let keypair = self | ||
| .keypair | ||
| .as_ref() | ||
| .ok_or_else(|| Error::KeypairUnconfigured)?; | ||
|
|
||
| if ixs.is_empty() { | ||
| return Ok(()); | ||
| } | ||
|
|
||
| let signers: Vec<&dyn Signer> = std::iter::once(keypair.as_ref() as &dyn Signer) | ||
| .chain(extra_signers.iter().map(|k| k as &dyn Signer)) | ||
| .collect(); | ||
|
|
||
| let (recent_blockhash, _) = self | ||
| .inner | ||
| .get_latest_blockhash_with_commitment(CommitmentConfig::finalized()) | ||
| .await?; | ||
|
|
||
| let optimized_ixs = auto_compute_limit_and_price( | ||
| &self.inner, | ||
| ixs, | ||
| &signers, | ||
| 1.2, | ||
| Some(&keypair.pubkey()), | ||
| Some(recent_blockhash), | ||
| ) | ||
| .await?; | ||
|
|
||
| let message = Message::new(&optimized_ixs, Some(&keypair.pubkey())); | ||
| let transaction = Transaction::new(&signers, message, recent_blockhash); | ||
| self.inner | ||
| .send_and_confirm_transaction_with_spinner(&transaction) | ||
| .await?; | ||
|
|
||
| Ok(()) | ||
| } | ||
| } | ||
|
|
||
| #[derive(Clone)] | ||
| pub struct Client { | ||
| pub solana_client: Arc<SolanaRpcClient>, | ||
| pub solana_client: Arc<SolanaClient>, | ||
| pub das_client: Arc<DasClient>, | ||
| } | ||
|
|
||
| impl TryFrom<&str> for Client { | ||
| type Error = Error; | ||
| fn try_from(value: &str) -> Result<Self, Self::Error> { | ||
| fn env_or(key: &str, default: &str) -> String { | ||
| std::env::var(key).unwrap_or_else(|_| default.to_string()) | ||
| } | ||
| let url = match value { | ||
| "m" | "mainnet-beta" => &env_or(SOLANA_URL_MAINNET_ENV, SOLANA_URL_MAINNET), | ||
| "d" | "devnet" => &env_or(SOLANA_URL_DEVNET_ENV, SOLANA_URL_DEVNET), | ||
| url => url, | ||
| }; | ||
| let das_client = Arc::new(DasClient::with_base_url(url)?); | ||
| let solana_client = Arc::new(SolanaClient::new(url, None)?); | ||
|
|
||
| Ok(Self { | ||
| solana_client, | ||
| das_client, | ||
| }) | ||
| } | ||
| } | ||
|
|
||
| impl AsRef<SolanaRpcClient> for SolanaClient { | ||
| fn as_ref(&self) -> &SolanaRpcClient { | ||
| &self.inner | ||
| } | ||
| } | ||
|
|
||
| impl AsRef<SolanaRpcClient> for Client { | ||
| fn as_ref(&self) -> &SolanaRpcClient { | ||
| &self.solana_client.inner | ||
| } | ||
| } | ||
|
|
||
| impl AsRef<DasClient> for Client { | ||
| fn as_ref(&self) -> &DasClient { | ||
| &self.das_client | ||
| } | ||
| } | ||
|
|
||
| #[async_trait::async_trait] | ||
| pub trait GetAnchorAccount { | ||
| async fn anchor_account<T: AccountDeserialize>(&self, pubkey: &Pubkey) -> Result<T, Error>; | ||
| async fn anchor_account<T: AccountDeserialize>( | ||
| &self, | ||
| pubkey: &Pubkey, | ||
| ) -> Result<Option<T>, Error>; | ||
| async fn anchor_accounts<T: AccountDeserialize + Send>( | ||
| &self, | ||
| pubkeys: &[Pubkey], | ||
|
|
@@ -42,18 +185,21 @@ pub trait GetAnchorAccount { | |
|
|
||
| #[async_trait::async_trait] | ||
| impl GetAnchorAccount for SolanaRpcClient { | ||
| async fn anchor_account<T: AccountDeserialize>(&self, pubkey: &Pubkey) -> Result<T, Error> { | ||
| async fn anchor_account<T: AccountDeserialize>( | ||
| &self, | ||
| pubkey: &Pubkey, | ||
| ) -> Result<Option<T>, Error> { | ||
| let account = self.get_account(pubkey).await?; | ||
| let decoded = T::try_deserialize(&mut account.data.as_ref())?; | ||
| Ok(decoded) | ||
| Ok(Some(decoded)) | ||
| } | ||
|
|
||
| async fn anchor_accounts<T: AccountDeserialize + Send>( | ||
| &self, | ||
| pubkeys: &[Pubkey], | ||
| ) -> Result<Vec<Option<T>>, Error> { | ||
| async fn get_accounts<A: AccountDeserialize + Send>( | ||
| client: &SolanaRpcClient, | ||
| client: &solana_client::nonblocking::rpc_client::RpcClient, | ||
| pubkeys: &[Pubkey], | ||
| ) -> Result<Vec<Option<A>>, Error> { | ||
| let accounts = client.get_multiple_accounts(pubkeys).await?; | ||
|
|
@@ -86,46 +232,14 @@ impl GetAnchorAccount for Client { | |
| async fn anchor_account<T: AccountDeserialize>( | ||
| &self, | ||
| pubkey: &keypair::Pubkey, | ||
| ) -> Result<T, Error> { | ||
| self.solana_client.anchor_account(pubkey).await | ||
| ) -> Result<Option<T>, Error> { | ||
| self.solana_client.inner.anchor_account(pubkey).await | ||
| } | ||
| async fn anchor_accounts<T: AccountDeserialize + Send>( | ||
| &self, | ||
| pubkeys: &[Pubkey], | ||
| ) -> Result<Vec<Option<T>>, Error> { | ||
| self.solana_client.anchor_accounts(pubkeys).await | ||
| } | ||
| } | ||
|
|
||
| impl TryFrom<&str> for Client { | ||
| type Error = Error; | ||
| fn try_from(value: &str) -> Result<Self, Self::Error> { | ||
| fn env_or(key: &str, default: &str) -> String { | ||
| std::env::var(key).unwrap_or_else(|_| default.to_string()) | ||
| } | ||
| let url = match value { | ||
| "m" | "mainnet-beta" => &env_or(SOLANA_URL_MAINNET_ENV, SOLANA_URL_MAINNET), | ||
| "d" | "devnet" => &env_or(SOLANA_URL_DEVNET_ENV, SOLANA_URL_DEVNET), | ||
| url => url, | ||
| }; | ||
| let das_client = Arc::new(DasClient::with_base_url(url)?); | ||
| let solana_client = Arc::new(SolanaRpcClient::new(url.to_string())); | ||
| Ok(Self { | ||
| solana_client, | ||
| das_client, | ||
| }) | ||
| } | ||
| } | ||
|
|
||
| impl AsRef<SolanaRpcClient> for Client { | ||
| fn as_ref(&self) -> &SolanaRpcClient { | ||
| &self.solana_client | ||
| } | ||
| } | ||
|
|
||
| impl AsRef<DasClient> for Client { | ||
| fn as_ref(&self) -> &DasClient { | ||
| &self.das_client | ||
| self.solana_client.inner.anchor_accounts(pubkeys).await | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -199,8 +313,6 @@ impl DasClientError { | |
| #[jsonrpc_client::api] | ||
| pub trait DAS {} | ||
|
|
||
| static USER_AGENT: &str = concat!(env!("CARGO_PKG_NAME"), "/", env!("CARGO_PKG_VERSION"),); | ||
|
|
||
| #[jsonrpc_client::implement(DAS)] | ||
| #[derive(Debug, Clone)] | ||
| pub struct DasClient { | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.