Skip to content
This repository was archived by the owner on Jun 1, 2026. It is now read-only.

Commit eff0e83

Browse files
committed
Migrate Sui to gRPC
#1126
1 parent eac4e73 commit eff0e83

70 files changed

Lines changed: 1531 additions & 2053 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Cargo.lock

Lines changed: 11 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,14 @@ curve25519-dalek = { version = "4.1.3" }
110110
ed25519-dalek = { version = "2", features = ["std"] }
111111
borsh = { version = "1.6.0", features = ["derive"] }
112112
bcs = { version = "0.2.1" }
113+
sui-rpc = { version = "0.3.1" }
114+
prost = { version = "0.14.3" }
115+
prost-types = { version = "0.14.3" }
116+
tonic = { version = "0.14.5", default-features = false, features = [
117+
"channel",
118+
"tls-ring",
119+
"tls-webpki-roots",
120+
] }
113121
pem-rfc7468 = { version = "1.0.0", features = ["std"] }
114122
sui-types = { package = "sui-sdk-types", version = "0.3.0", features = [
115123
"serde",

Settings.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ name:
7777
did:
7878
url: https://indexer-basic.did.id
7979
suins:
80-
url: https://suins-rpc.mainnet.sui.io
80+
url: https://fullnode.mainnet.sui.io
8181
aptos:
8282
url: https://aptosnames.com
8383
injective:
@@ -132,7 +132,7 @@ chains:
132132
aptos:
133133
url: https://fullnode.mainnet.aptoslabs.com
134134
sui:
135-
url: https://suins-rpc.mainnet.sui.io
135+
url: https://fullnode.mainnet.sui.io
136136
celestia:
137137
url: https://celestia-api.polkachu.com
138138
injective:

apps/dynode/chains.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ chains:
5959
# Sui
6060
- chain: sui
6161
urls:
62-
- url: https://sui-mainnet-endpoint.blockvision.org
62+
- url: https://fullnode.mainnet.sui.io
6363

6464
# XRP
6565
- chain: xrp

apps/dynode/config.yml

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,11 @@ request:
2424

2525
headers:
2626
forward:
27+
- accept
2728
- content-type
2829
- content-encoding
2930
- content-length
31+
- te
3032
domains:
3133
public-eth.nownodes.io:
3234
- user-agent
@@ -67,11 +69,6 @@ cache:
6769
solana:
6870
- rpc_method: getVoteAccounts
6971
ttl: 1h
70-
sui:
71-
- rpc_method: suix_getValidatorsApy
72-
ttl: 1h
73-
- rpc_method: suix_getLatestSuiSystemState
74-
ttl: 1m
7572
cosmos:
7673
- path: /cosmos/staking/v1beta1/validators
7774
method: GET

apps/dynode/src/metrics/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ mod tests {
262262
let m = create_test_metrics();
263263

264264
assert_eq!(m.truncate_method("eth_getBlockByNumber"), "eth_getBlockByNumber");
265-
assert_eq!(m.truncate_method("suix_getLatestSuiSystemState"), "suix_getLatestSuiSystemState");
265+
assert_eq!(m.truncate_method("eth_getBalance"), "eth_getBalance");
266266
assert_eq!(m.truncate_method("/api/v1/blocks/by_height/12345"), "/api/v1/blocks/by_height/:number");
267267
assert_eq!(m.truncate_method("/v1/verylongsegmentthatisgreaterthan20characters"), "/v1/:value");
268268
}

apps/dynode/src/webhook.rs

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,7 @@ impl DynodeBroadcastWebhookClient {
4848
}
4949

5050
fn extract_payload(&self, request: &ProxyRequest, response_body: &[u8], broadcast_providers: &BroadcastProviders) -> Option<TransactionId> {
51-
let response = parse_response_body(request, response_body)?;
52-
let identifier = broadcast_providers.decode_transaction_broadcast(request.chain, response)?;
51+
let identifier = broadcast_providers.decode_transaction_broadcast(request.chain, response_body)?;
5352
Some(TransactionId::new(request.chain, identifier))
5453
}
5554

@@ -92,16 +91,6 @@ fn is_success_status(status: u16) -> bool {
9291
(200..300).contains(&status)
9392
}
9493

95-
fn parse_response_body<'a>(request: &ProxyRequest, response_body: &'a [u8]) -> Option<&'a str> {
96-
match std::str::from_utf8(response_body) {
97-
Ok(response) => Some(response),
98-
Err(err) => {
99-
error_with_fields!("broadcast webhook decode failed", &err, chain = request.chain.as_ref(), request_id = request.id.as_str(),);
100-
None
101-
}
102-
}
103-
}
104-
10594
fn is_broadcast_request(request: &ProxyRequest, broadcast_providers: &BroadcastProviders) -> bool {
10695
let chain_request = match request.request_type() {
10796
RequestType::JsonRpc(JsonRpcRequest::Single(call)) => ChainRequest::new(ChainRequestProtocol::JsonRpc, call.method.as_str(), request.path.as_str(), &request.body),

crates/chain_traits/src/lib.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::error::Error;
1+
use std::{error::Error, str};
22

33
use async_trait::async_trait;
44
use primitives::chart::ChartCandleStick;
@@ -111,6 +111,10 @@ pub trait ChainTransactionDecode: Send + Sync {
111111
fn decode_transaction_broadcast(&self, _response: &str) -> Option<String> {
112112
None
113113
}
114+
115+
fn decode_transaction_broadcast_bytes(&self, response: &[u8]) -> Option<String> {
116+
str::from_utf8(response).ok().and_then(|response| self.decode_transaction_broadcast(response))
117+
}
114118
}
115119

116120
#[async_trait]

crates/gem_jsonrpc/src/grpc.rs

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
use async_trait::async_trait;
2+
use std::{collections::HashMap, error::Error, fmt, sync::Arc};
3+
4+
use crate::{
5+
alien,
6+
rpc::{HttpMethod, Target},
7+
};
8+
9+
#[async_trait]
10+
pub trait GrpcTransport: Send + Sync + fmt::Debug {
11+
async fn unary(&self, endpoint: &str, path: &str, body: Vec<u8>) -> Result<Vec<u8>, Box<dyn Error + Send + Sync>>;
12+
}
13+
14+
fn unary_target(endpoint: &str, path: &str, body: Vec<u8>) -> Target {
15+
Target {
16+
url: format!("{}{}", endpoint.trim_end_matches('/'), path),
17+
method: HttpMethod::Post,
18+
headers: Some(grpc_headers()),
19+
body: Some(body),
20+
}
21+
}
22+
23+
fn ensure_success_status(status: Option<u16>) -> Result<(), Box<dyn Error + Send + Sync>> {
24+
if let Some(status) = status
25+
&& !(200..300).contains(&status)
26+
{
27+
return Err(format!("gRPC HTTP error: status {status}").into());
28+
}
29+
Ok(())
30+
}
31+
32+
fn grpc_headers() -> HashMap<String, String> {
33+
HashMap::from([
34+
("Content-Type".into(), "application/grpc+proto".into()),
35+
("Accept".into(), "application/grpc+proto".into()),
36+
("TE".into(), "trailers".into()),
37+
])
38+
}
39+
40+
#[derive(Clone)]
41+
pub struct AlienGrpcTransport {
42+
provider: Arc<dyn alien::RpcProvider>,
43+
}
44+
45+
impl AlienGrpcTransport {
46+
pub fn new(provider: Arc<dyn alien::RpcProvider>) -> Self {
47+
Self { provider }
48+
}
49+
}
50+
51+
impl fmt::Debug for AlienGrpcTransport {
52+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
53+
f.debug_struct("AlienGrpcTransport").finish_non_exhaustive()
54+
}
55+
}
56+
57+
#[async_trait]
58+
impl GrpcTransport for AlienGrpcTransport {
59+
async fn unary(&self, endpoint: &str, path: &str, body: Vec<u8>) -> Result<Vec<u8>, Box<dyn Error + Send + Sync>> {
60+
let response = self.provider.request(unary_target(endpoint, path, body)).await?;
61+
ensure_success_status(response.status)?;
62+
Ok(response.data)
63+
}
64+
}

crates/gem_jsonrpc/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ pub mod alien;
55
#[cfg(feature = "client")]
66
pub mod client;
77
#[cfg(feature = "client")]
8+
pub mod grpc;
9+
#[cfg(feature = "client")]
810
pub use client::*;
911
#[cfg(feature = "testkit")]
1012
pub mod testkit;

0 commit comments

Comments
 (0)