Skip to content
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
12 changes: 2 additions & 10 deletions core/crates/chain_providers/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use gem_jsonrpc::grpc::ReqwestGrpcTransport;
use gem_monad::MonadStakingClient;
use gem_near::rpc::{NearClient, NearIndexer, NearProvider};
use gem_polkadot::rpc::{PolkadotClient, PolkadotIndexer, PolkadotProvider};
use gem_solana::rpc::{SolanaClient, SolanaIndexer, SolanaProvider};
use gem_solana::rpc::{SolanaClient, SolanaProvider};
use gem_stellar::rpc::client::StellarClient;
use gem_sui::rpc::{SuiClient, SuiIndexer, SuiProvider};
use gem_tempo::TempoProvider;
Expand Down Expand Up @@ -139,15 +139,7 @@ impl ProviderFactory {
.with_default_headers(HashMap::from([("x-api-key".to_string(), config.indexers.subscan.key)])),
)),
)),
ChainType::Solana => Box::new(SolanaProvider::new(
SolanaClient::new(JsonRpcClient::new(gem_client.clone())),
Box::new(SolanaIndexer::new(JsonRpcClient::new(gem_client.with_base_url(alchemy_url(
chain,
&config.indexers.alchemy.url,
AlchemyApi::JsonRpc,
&config.indexers.alchemy.key,
))))),
)),
ChainType::Solana => Box::new(SolanaProvider::new(SolanaClient::new(JsonRpcClient::new(gem_client)))),
ChainType::Ton => Box::new(TonClient::new(gem_client)),
ChainType::Tron => {
let trongrid = TronGridClient::new(config.indexers.trongrid.configure_client(gem_client.clone()), config.indexers.trongrid.key);
Expand Down
12 changes: 12 additions & 0 deletions core/crates/gem_solana/src/jsonrpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ pub enum SolanaRpc {
GetProgramAccounts(String, Vec<SolanaProgramAccountsFilter>),
GetProgramAccountsSlice(String, Vec<SolanaProgramAccountsFilter>, SolanaDataSlice),
GetRecentPrioritizationFees(Vec<String>),
GetSignaturesForAddress { address: String, limit: usize },
GetSlot(SolanaRpcConfig),
GetSupply,
GetTokenAccountsByOwner(String, SolanaTokenAccountsFilter),
Expand All @@ -102,6 +103,7 @@ impl ToJsonRpcRequest for SolanaRpc {
Self::GetMultipleAccounts(_) | Self::GetMultipleAccountsSlice(_, _) => method::GET_MULTIPLE_ACCOUNTS,
Self::GetProgramAccounts(_, _) | Self::GetProgramAccountsSlice(_, _, _) => method::GET_PROGRAM_ACCOUNTS,
Self::GetRecentPrioritizationFees(_) => method::GET_RECENT_PRIORITIZATION_FEES,
Self::GetSignaturesForAddress { .. } => method::GET_SIGNATURES_FOR_ADDRESS,
Self::GetSlot(_) => method::GET_SLOT,
Self::GetSupply => method::GET_SUPPLY,
Self::GetTokenAccountsByOwner(_, _) => method::GET_TOKEN_ACCOUNTS_BY_OWNER,
Expand Down Expand Up @@ -157,6 +159,7 @@ impl ToJsonRpcRequest for SolanaRpc {
json!([addresses])
}
}
Self::GetSignaturesForAddress { address, limit } => json!([address, confirmed_config(json!({ "limit": limit }))]),
Self::GetSupply => json!([confirmed_config(json!({
"excludeNonCirculatingAccountsList": true,
}))]),
Expand Down Expand Up @@ -241,6 +244,15 @@ mod tests {
);
}

#[test]
fn builds_signatures_for_address_request() {
assert_request(
SolanaRpc::GetSignaturesForAddress { address: "address".into(), limit: 2 },
method::GET_SIGNATURES_FOR_ADDRESS,
json!(["address", {"commitment": "confirmed", "limit": 2}]),
);
}

#[test]
fn builds_configured_account_request() {
assert_request(
Expand Down
1 change: 1 addition & 0 deletions core/crates/gem_solana/src/method.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ pub const GET_LATEST_BLOCKHASH: &str = "getLatestBlockhash";
pub const GET_MULTIPLE_ACCOUNTS: &str = "getMultipleAccounts";
pub const GET_PROGRAM_ACCOUNTS: &str = "getProgramAccounts";
pub const GET_RECENT_PRIORITIZATION_FEES: &str = "getRecentPrioritizationFees";
pub const GET_SIGNATURES_FOR_ADDRESS: &str = "getSignaturesForAddress";
pub const GET_SLOT: &str = "getSlot";
pub const GET_SUPPLY: &str = "getSupply";
pub const GET_TOKEN_ACCOUNTS_BY_OWNER: &str = "getTokenAccountsByOwner";
Expand Down
5 changes: 5 additions & 0 deletions core/crates/gem_solana/src/models/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ use std::collections::{HashMap, HashSet};

use crate::models::token::{BigInt, TokenBalance, TokenBalanceChange};

#[derive(Debug, Deserialize)]
pub struct TransactionSignature {
pub signature: String,
}

#[derive(Deserialize)]
pub struct SolanaTransaction {
pub meta: SolanaTransactionMeta,
Expand Down
8 changes: 2 additions & 6 deletions core/crates/gem_solana/src/provider/testkit.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#[cfg(feature = "chain_integration_tests")]
use crate::rpc::{SolanaClient, SolanaIndexer, SolanaProvider};
use crate::rpc::{SolanaClient, SolanaProvider};
#[cfg(feature = "chain_integration_tests")]
use gem_client::ReqwestClient;
#[cfg(feature = "chain_integration_tests")]
Expand All @@ -15,9 +15,5 @@ pub const TEST_TRANSACTION_ID: &str = "4dHnggcXjvmMJY2J6iGqse12PeCYQzuTySgwJa36K
#[cfg(feature = "chain_integration_tests")]
pub fn create_solana_test_client() -> SolanaProvider<ReqwestClient> {
let settings = get_test_settings();
let alchemy_url = format!("{}/v2/{}", settings.indexer.alchemy.url.replace("{network}", "solana-mainnet"), settings.indexer.alchemy.key.secret);
SolanaProvider::new(
SolanaClient::new(JsonRpcClient::new(ReqwestClient::new_test_client(settings.chains.solana.url))),
Box::new(SolanaIndexer::new(JsonRpcClient::new(ReqwestClient::new_test_client(alchemy_url)))),
)
SolanaProvider::new(SolanaClient::new(JsonRpcClient::new(ReqwestClient::new_test_client(settings.chains.solana.url))))
}
7 changes: 6 additions & 1 deletion core/crates/gem_solana/src/provider/transaction_mapper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ use num_bigint::{BigUint, Sign};
use crate::{
COMPUTE_BUDGET_PROGRAM_ID, JUPITER_PROGRAM_ID, MEMO_PROGRAM_ID, METAPLEX_CORE_PROGRAM, METAPLEX_PROGRAM, METEORA_DAMM_V2_PROGRAM_ID, METEORA_DLMM_PROGRAM_ID, OKX_DEX_V2_PROGRAM_ID, ORCA_WHIRLPOOL_PROGRAM_ID, PUMP_AMM_PROGRAM_ID,
RAYDIUM_AMM_PROGRAM_ID, RAYDIUM_CLMM_PROGRAM_ID, RAYDIUM_CPMM_PROGRAM_ID, SYSTEM_PROGRAM_ID, SYSTEM_PROGRAMS, TOKEN_PROGRAM, TOKEN_PROGRAM_2022, WSOL_TOKEN_ADDRESS,
models::{BlockTransaction, BlockTransactions, Instruction, SingleTransaction, TokenBalanceChange},
models::{BlockTransaction, BlockTransactions, Instruction, SingleTransaction, TokenBalanceChange, TransactionSignature},
};
use primitives::{
AssetId, Chain, NFTAssetId, OptionStringExt, SwapProvider, Transaction, TransactionNFTTransferMetadata, TransactionState, TransactionSwapMetadata, TransactionSwapReferralFee, TransactionType, swap::SOLANA_REFERRAL_ADDRESS,
};

use super::parsers::ProtocolParsers;
use chain_traits::{TransactionIdRequest, TransactionsResult};

const CHAIN: Chain = Chain::Solana;
const SWAP_PROGRAMS: &[(SwapProvider, &str)] = &[
Expand Down Expand Up @@ -174,6 +175,10 @@ fn map_referral_fee(transaction: &BlockTransaction, owner: &str) -> Option<Trans
})
}

pub fn map_transaction_requests(signatures: Vec<TransactionSignature>) -> TransactionsResult {
TransactionsResult::TransactionRequests(signatures.into_iter().map(|signature| TransactionIdRequest::new(CHAIN, signature.signature, None)).collect())
}

pub fn map_block_transactions(transactions: &BlockTransactions) -> Vec<primitives::Transaction> {
transactions.transactions.iter().filter_map(|transaction| map_transaction(transaction, transactions.block_time)).collect()
}
Expand Down
11 changes: 4 additions & 7 deletions core/crates/gem_solana/src/provider/transactions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ use primitives::Transaction;

use crate::{
models::SingleTransaction,
provider::transaction_mapper::{map_block_transactions, map_single_transaction},
rpc::{SolanaIndexer, SolanaProvider, constants::MISSING_BLOCKS_ERRORS},
provider::transaction_mapper::{map_block_transactions, map_single_transaction, map_transaction_requests},
rpc::{SolanaProvider, constants::MISSING_BLOCKS_ERRORS},
};

#[async_trait]
Expand All @@ -35,13 +35,10 @@ impl<C: Client + Clone> ChainTransaction for SolanaProvider<C> {
}

#[async_trait]
impl<C: Client + Clone> ChainTransactions for SolanaIndexer<C> {
impl<C: Client + Clone> ChainTransactions for SolanaProvider<C> {
async fn get_transactions_by_address(&self, request: TransactionsRequest) -> Result<TransactionsResult, Box<dyn Error + Sync + Send>> {
let TransactionsRequest { address, limit, .. } = request;
let transaction_ids = self.get_transaction_ids_by_address(&address, limit).await?;
Ok(TransactionsResult::TransactionRequests(
transaction_ids.into_iter().map(|transaction_id| TransactionIdRequest::new(primitives::Chain::Solana, transaction_id, None)).collect(),
))
Ok(map_transaction_requests(self.get_signatures_for_address(&address, limit).await?))
}
}

Expand Down
12 changes: 10 additions & 2 deletions core/crates/gem_solana/src/rpc/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,12 @@ use crate::{
jsonrpc::{SolanaAccountEncoding, SolanaProgramAccountsFilter, SolanaRpc, SolanaRpcConfig, SolanaTokenAccountsFilter},
metaplex::{decode_metadata, metadata::Metadata},
models::{
AccountData, EpochInfo, InflationRate, ResultTokenInfo, SupplyResult, TokenAccountInfo, ValueResult, VoteAccounts, balances::SolanaBalance, blockhash::SolanaBlockhashResult, prioritization_fee::SolanaPrioritizationFee,
simulation::SimulateTransactionResult, transaction::BlockTransactions,
AccountData, EpochInfo, InflationRate, ResultTokenInfo, SupplyResult, TokenAccountInfo, ValueResult, VoteAccounts,
balances::SolanaBalance,
blockhash::SolanaBlockhashResult,
prioritization_fee::SolanaPrioritizationFee,
simulation::SimulateTransactionResult,
transaction::{BlockTransactions, TransactionSignature},
},
};
#[cfg(feature = "rpc")]
Expand Down Expand Up @@ -52,6 +56,10 @@ impl<C: Client + Clone> SolanaClient<C> {
self.client.request(SolanaRpc::GetTransaction(signature.to_string())).await
}

pub async fn get_signatures_for_address(&self, address: &str, limit: usize) -> Result<Vec<TransactionSignature>, JsonRpcError> {
self.client.request(SolanaRpc::GetSignaturesForAddress { address: address.to_string(), limit }).await
}

pub async fn get_genesis_hash(&self) -> Result<String, JsonRpcError> {
self.client.request(SolanaRpc::GetGenesisHash).await
}
Expand Down
29 changes: 0 additions & 29 deletions core/crates/gem_solana/src/rpc/indexer/jsonrpc.rs

This file was deleted.

68 changes: 0 additions & 68 deletions core/crates/gem_solana/src/rpc/indexer/mod.rs

This file was deleted.

4 changes: 0 additions & 4 deletions core/crates/gem_solana/src/rpc/mod.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
pub mod client;
pub mod constants;
#[cfg(feature = "rpc")]
mod indexer;
#[cfg(feature = "rpc")]
mod provider;

pub use client::SolanaClient;
pub use constants::*;
#[cfg(feature = "rpc")]
pub use indexer::SolanaIndexer;
#[cfg(feature = "rpc")]
pub use provider::SolanaProvider;
21 changes: 4 additions & 17 deletions core/crates/gem_solana/src/rpc/provider.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,18 @@
use std::{error::Error, ops::Deref};
use std::ops::Deref;

use async_trait::async_trait;
use chain_traits::{ChainAccount, ChainPerpetual, ChainProvider, ChainTransactions, EmptyTransactionsProvider, TransactionsRequest, TransactionsResult};
use chain_traits::{ChainAccount, ChainPerpetual, ChainProvider};
use gem_client::Client;
use primitives::Chain;

use super::SolanaClient;

pub struct SolanaProvider<C: Client + Clone> {
client: SolanaClient<C>,
indexer: Box<dyn ChainTransactions>,
}

impl<C: Client + Clone> SolanaProvider<C> {
pub fn new(client: SolanaClient<C>, indexer: Box<dyn ChainTransactions>) -> Self {
Self { client, indexer }
}

pub fn new_rpc_only(client: SolanaClient<C>) -> Self {
Self::new(client, Box::new(EmptyTransactionsProvider))
pub fn new(client: SolanaClient<C>) -> Self {
Self { client }
}
}

Expand All @@ -30,13 +24,6 @@ impl<C: Client + Clone> Deref for SolanaProvider<C> {
}
}

#[async_trait]
impl<C: Client + Clone> ChainTransactions for SolanaProvider<C> {
async fn get_transactions_by_address(&self, request: TransactionsRequest) -> Result<TransactionsResult, Box<dyn Error + Sync + Send>> {
self.indexer.get_transactions_by_address(request).await
}
}

impl<C: Client + Clone> ChainProvider for SolanaProvider<C> {
fn get_chain(&self) -> Chain {
Chain::Solana
Expand Down

This file was deleted.

2 changes: 1 addition & 1 deletion core/gemstone/src/gateway/chain_factory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ impl ChainClientFactory {
ChainType::Polkadot => Ok(Arc::new(PolkadotProvider::new_rpc_only(PolkadotClient::new(alien_client)))),
ChainType::Solana => {
let client = JsonRpcClient::new(alien_client);
Ok(Arc::new(SolanaProvider::new_rpc_only(SolanaClient::new(client))))
Ok(Arc::new(SolanaProvider::new(SolanaClient::new(client))))
}
ChainType::Ethereum => {
let evm_chain = EVMChain::from_chain(chain).unwrap();
Expand Down
2 changes: 1 addition & 1 deletion core/gemstone/src/services/simulation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ impl GemSimulationService {
let url = self.nodes.node_url(chain);
let new_client = || new_alien_client(url.clone(), self.provider.clone());
match chain {
Chain::Solana => Ok(Box::new(SolanaProvider::new_rpc_only(SolanaClient::new(JsonRpcClient::new(new_client()))))),
Chain::Solana => Ok(Box::new(SolanaProvider::new(SolanaClient::new(JsonRpcClient::new(new_client()))))),
Chain::Sui => {
let transport = AlienGrpcTransport::new(Arc::new(AlienProviderWrapper::new(self.provider.clone())));
Ok(Box::new(SuiProvider::new_rpc_only(SuiClient::new_with_transport(url, Arc::new(transport)))))
Expand Down
Loading
Loading