Skip to content
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
1f25a5b
Refactor swapper providers to use rpc_provider field
0xh3rman Oct 2, 2025
8853d4b
Refactor swapper clients to use generic HTTP and RPC clients
0xh3rman Oct 2, 2025
5418898
Refactor network and RPC clients; update Sui and Tron integration
0xh3rman Oct 3, 2025
a8696ca
Refactor imports and add Default for HyperCoreBridge
0xh3rman Oct 3, 2025
6eaed59
Merge branch 'main' into swapper-gem-client
0xh3rman Oct 6, 2025
ffb618c
Merge branch 'main' into swapper-gem-client
0xh3rman Oct 7, 2025
39a9745
adding swapper crate
0xh3rman Oct 7, 2025
2c1256d
adding swapper crate
0xh3rman Oct 7, 2025
2cf5141
remove SuiRpcClient
0xh3rman Oct 7, 2025
357a83c
refactor client_factory
0xh3rman Oct 7, 2025
2c7be93
remove Alien prefixes
0xh3rman Oct 7, 2025
a5e76ea
remove swapper code from gemstone
0xh3rman Oct 7, 2025
5a66112
re-add GemSwapper and fix iOS build
0xh3rman Oct 7, 2025
27194f4
Merge branch 'main' into swapper-gem-client
0xh3rman Oct 7, 2025
7f27677
cleanup Cargo.toml, add back test
0xh3rman Oct 7, 2025
874ce6b
Merge branch 'swapper-gem-client' of github.com:gemwalletcom/core int…
0xh3rman Oct 7, 2025
129c616
reuse NativeProvider
0xh3rman Oct 7, 2025
bb8bc2d
refactor AlienClient
0xh3rman Oct 7, 2025
7ac014b
Merge branch 'main' into swapper-gem-client
0xh3rman Oct 7, 2025
5a2ddb4
remove tron_client
0xh3rman Oct 7, 2025
c26f7c1
add missing permit2_data_to_eip712_json export
0xh3rman Oct 7, 2025
f42d75d
add back SwapProviderConfig
0xh3rman Oct 7, 2025
8209e85
Merge branch 'main' into swapper-gem-client
0xh3rman Oct 7, 2025
3cf19b8
Update ci.yml
0xh3rman Oct 7, 2025
331158b
review comments
0xh3rman Oct 8, 2025
eb30300
cleanup
0xh3rman Oct 8, 2025
c053651
Merge branch 'main' into swapper-gem-client
0xh3rman Oct 8, 2025
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
1 change: 0 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ jobs:

- name: Build all integration tests only
run: |
just --unstable gemstone build-integration-tests
just --unstable build-integration-tests

- name: Check gemstone dependencies
Expand Down
69 changes: 56 additions & 13 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ members = [
"crates/number_formatter",
"crates/pricer_dex",
"crates/streamer",
"crates/gem_swapper",
"crates/tracing",
]

Expand Down
3 changes: 2 additions & 1 deletion bin/gas-bench/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ use std::error::Error;
use gem_evm::fee_calculator::FeeCalculator;
use gem_evm::models::fee::EthereumFeeHistory;
use gem_evm::{ether_conv::EtherConv, jsonrpc::EthereumRpc};
use gemstone::network::{alien_provider::NativeProvider, jsonrpc_client_with_chain};
use gemstone::alien::reqwest_provider::NativeProvider;
use gemstone::network::jsonrpc_client_with_chain;
use num_bigint::BigInt;
use primitives::{Chain, PriorityFeeValue, fee::FeePriority};
use std::fmt::Display;
Expand Down
2 changes: 1 addition & 1 deletion bin/gas-bench/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use crate::{
etherscan::EtherscanClient,
gasflow::GasflowClient,
};
use gemstone::network::alien_provider::NativeProvider;
use gemstone::alien::reqwest_provider::NativeProvider;
use primitives::fee::FeePriority;

#[derive(Debug, Clone)]
Expand Down
3 changes: 2 additions & 1 deletion crates/gem_client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ serde_json = { workspace = true }
serde_urlencoded = { workspace = true }
reqwest = { workspace = true, optional = true }
hex = { workspace = true }
tokio = { workspace = true, features = ["time"], optional = true }
tokio = { workspace = true, features = ["time"], optional = true }
primitives = { path = "../primitives" }
3 changes: 3 additions & 0 deletions crates/gem_client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ mod types;
#[cfg(feature = "reqwest")]
mod reqwest_client;

pub mod rpc;

#[cfg(feature = "reqwest")]
pub mod retry;

Expand All @@ -15,6 +17,7 @@ pub mod query;
pub use content_type::{ContentType, CONTENT_TYPE};
pub use query::build_path_with_query;
pub use types::ClientError;
pub use rpc::{HttpMethod, RpcClient, RpcProvider, Target, X_CACHE_TTL};

#[cfg(feature = "reqwest")]
pub use reqwest_client::ReqwestClient;
Expand Down
124 changes: 105 additions & 19 deletions gemstone/src/network/alien_client.rs → crates/gem_client/src/rpc.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,96 @@
use crate::network::{AlienError, AlienProvider, AlienTarget};
use crate::{Client, ClientError, ContentType, Data};
use async_trait::async_trait;
use gem_client::{Client, ClientError, ContentType};
use primitives::Chain;
use serde::{Serialize, de::DeserializeOwned};
use std::{collections::HashMap, str::FromStr, sync::Arc};
use serde_json;
use std::{collections::HashMap, fmt::Debug, str::FromStr, sync::Arc};

pub const X_CACHE_TTL: &str = "x-cache-ttl";

#[derive(Debug, Clone)]
pub struct Target {
pub url: String,
pub method: HttpMethod,
pub headers: Option<HashMap<String, String>>,
pub body: Option<Vec<u8>>,
}

impl Target {
pub fn get(url: &str) -> Self {
Self {
url: url.into(),
method: HttpMethod::Get,
headers: None,
body: None,
}
}

pub fn post_json(url: &str, body: serde_json::Value) -> Self {
Self {
url: url.into(),
method: HttpMethod::Post,
headers: Some(HashMap::from([("Content-Type".into(), "application/json".into())])),
body: Some(serde_json::to_vec(&body).expect("Failed to serialize JSON body")),
}
}

pub fn set_cache_ttl(mut self, ttl: u64) -> Self {
if self.headers.is_none() {
self.headers = Some(HashMap::new());
}
if let Some(headers) = self.headers.as_mut() {
headers.insert(X_CACHE_TTL.into(), ttl.to_string());
}
self
}
}

#[derive(Debug, Clone, Copy, PartialEq)]
pub enum HttpMethod {
Get,
Post,
Put,
Delete,
Head,
Options,
Patch,
}

impl From<HttpMethod> for String {
fn from(value: HttpMethod) -> Self {
match value {
HttpMethod::Get => "GET",
HttpMethod::Post => "POST",
HttpMethod::Put => "PUT",
HttpMethod::Delete => "DELETE",
HttpMethod::Head => "HEAD",
HttpMethod::Options => "OPTIONS",
HttpMethod::Patch => "PATCH",
}
.into()
}
}

#[async_trait]
pub trait RpcProvider: Send + Sync + Debug {
type Error: std::error::Error + Send + Sync + 'static;

async fn request(&self, target: Target) -> Result<Data, Self::Error>;
async fn batch_request(&self, targets: Vec<Target>) -> Result<Vec<Data>, Self::Error>;
fn get_endpoint(&self, chain: Chain) -> Result<String, Self::Error>;
}

#[derive(Debug, Clone)]
pub struct AlienClient {
pub struct RpcClient<E> {
base_url: String,
provider: Arc<dyn AlienProvider>,
provider: Arc<dyn RpcProvider<Error = E>>,
}

impl AlienClient {
pub fn new(base_url: String, provider: Arc<dyn AlienProvider>) -> Self {
impl<E> RpcClient<E>
where
E: std::error::Error + Send + Sync + 'static,
{
pub fn new(base_url: String, provider: Arc<dyn RpcProvider<Error = E>>) -> Self {
Self { base_url, provider }
}

Expand All @@ -22,7 +100,10 @@ impl AlienClient {
}

#[async_trait]
impl Client for AlienClient {
impl<E> Client for RpcClient<E>
where
E: std::error::Error + Send + Sync + 'static + std::fmt::Display,
{
async fn get<R>(&self, path: &str) -> Result<R, ClientError>
where
R: DeserializeOwned,
Expand All @@ -36,21 +117,21 @@ impl Client for AlienClient {
{
let url = self.build_url(path);
let target = if let Some(headers) = headers {
AlienTarget {
Target {
url,
method: crate::network::AlienHttpMethod::Get,
method: HttpMethod::Get,
headers: Some(headers),
body: None,
}
} else {
AlienTarget::get(&url)
Target::get(&url)
};

let response_data = self
.provider
.request(target)
.await
.map_err(|e| ClientError::Network(format!("Alien provider error: {e}")))?;
.map_err(|e| ClientError::Network(format!("RPC provider error: {e}")))?;

serde_json::from_slice(&response_data).map_err(|e| ClientError::Serialization(format!("Failed to deserialize response: {e}")))
}
Expand Down Expand Up @@ -88,9 +169,9 @@ impl Client for AlienClient {
_ => serde_json::to_vec(body)?,
};

let target = AlienTarget {
let target = Target {
url,
method: crate::network::AlienHttpMethod::Post,
method: HttpMethod::Post,
headers: Some(request_headers),
body: Some(data),
};
Expand All @@ -99,23 +180,28 @@ impl Client for AlienClient {
.provider
.request(target)
.await
.map_err(|e| ClientError::Network(format!("Alien provider error: {e}")))?;
.map_err(|e| ClientError::Network(format!("RPC provider error: {e}")))?;

serde_json::from_slice(&response_data).map_err(|e| ClientError::Serialization(format!("Failed to deserialize response: {e}")))
}
}

#[async_trait]
impl AlienProvider for AlienClient {
async fn request(&self, target: AlienTarget) -> Result<Vec<u8>, AlienError> {
impl<E> RpcProvider for RpcClient<E>
where
E: std::error::Error + Send + Sync + 'static,
{
type Error = E;

async fn request(&self, target: Target) -> Result<Data, Self::Error> {
self.provider.request(target).await
}

async fn batch_request(&self, targets: Vec<AlienTarget>) -> Result<Vec<Vec<u8>>, AlienError> {
async fn batch_request(&self, targets: Vec<Target>) -> Result<Vec<Data>, Self::Error> {
self.provider.batch_request(targets).await
}

fn get_endpoint(&self, chain: Chain) -> Result<String, AlienError> {
fn get_endpoint(&self, chain: Chain) -> Result<String, Self::Error> {
self.provider.get_endpoint(chain)
}
}
2 changes: 1 addition & 1 deletion crates/gem_evm/src/rpc/ankr/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use serde_json::json;

use crate::rpc::ankr::model::{TokenBalances, Transactions, ankr_chain};

#[derive(Clone)]
#[derive(Debug, Clone)]
pub struct AnkrClient<C: Client + Clone> {
pub chain: EVMChain,
rpc_client: GenericJsonRpcClient<C>,
Expand Down
Loading
Loading