Skip to content
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

feat(multichain): update token-info client #1208

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
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
3 changes: 3 additions & 0 deletions multichain-aggregator/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ tokio = { version = "1", features = ["rt-multi-thread", "macros"] }
tonic = "0.8"
tonic-build = "0.8"

# clients
contracts-info-proto = { path = "../contracts-info-proto", features = ["http-client"] }
Comment on lines +33 to +34
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix the dependency path to resolve build failure.

The pipeline is failing because the contracts-info-proto dependency cannot be found at the specified path ../contracts-info-proto. This indicates that either:

  1. The repository structure is different from what's expected
  2. The dependency path needs to be adjusted

To resolve this, we need to verify the correct path to the dependency. Please run this script to check the repository structure:

#!/bin/bash
# Description: Check repository structure and find the contracts-info-proto directory

echo "Searching for contracts-info-proto directory..."
fd -t d "contracts-info-proto$"

echo -e "\nChecking if the directory exists at ../contracts-info-proto..."
if [ -d "../contracts-info-proto" ]; then
    echo "Directory exists at ../contracts-info-proto"
    if [ -f "../contracts-info-proto/Cargo.toml" ]; then
        echo "Cargo.toml exists in the directory"
    else
        echo "Cargo.toml is missing"
    fi
else
    echo "Directory does not exist at ../contracts-info-proto"
fi
🧰 Tools
🪛 GitHub Actions: Test, lint and docker (multichain-aggregator)

[error] Failed to load manifest for workspace member. Dependency 'contracts-info-proto' could not be found because its Cargo.toml file is missing at '/home/runner/work/blockscout-rs/blockscout-rs/contracts-info-proto/Cargo.toml'


# db
sea-orm = { version = "1", features = [
"sqlx-postgres",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ tonic = { workspace = true }
tokio = { workspace = true }
reqwest = { workspace = true }
url = { workspace = true }
contracts-info-proto = { workspace = true }

[dev-dependencies]
blockscout-service-launcher = { workspace = true }
Expand Down
Original file line number Diff line number Diff line change
@@ -1,2 +1,7 @@
pub mod dapp;
pub mod token_info;
pub mod token_info {
pub use contracts_info_proto::{
blockscout::contracts_info::v1 as proto,
http_client::{contracts_info as endpoints, Client, Config},
};
}

This file was deleted.

18 changes: 8 additions & 10 deletions multichain-aggregator/multichain-aggregator-logic/src/search.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::{
clients::{
dapp::{SearchDapps, SearchDappsParams},
token_info::{SearchTokenInfos, SearchTokenInfosParams},
token_info::{endpoints::SearchTokenInfos, proto::SearchTokenInfosRequest, Client},
},
error::ServiceError,
repository::{addresses, block_ranges, hashes},
Expand Down Expand Up @@ -38,7 +38,7 @@ macro_rules! populate_search_results {
pub async fn quick_search(
db: &DatabaseConnection,
dapp_client: &HttpApiClient,
token_info_client: &HttpApiClient,
token_info_client: &Client,
query: String,
chains: &[Chain],
) -> Result<SearchResults, ServiceError> {
Expand All @@ -50,14 +50,12 @@ pub async fn quick_search(
},
};

let token_info_search_endpoint = SearchTokenInfos {
params: SearchTokenInfosParams {
query: raw_query.to_string(),
chain_id: None,
page_size: Some(100),
page_token: None,
},
};
let token_info_search_endpoint = SearchTokenInfos::new(SearchTokenInfosRequest {
query: raw_query.to_string(),
chain_id: None,
page_size: Some(100),
page_token: None,
});

let (hashes, block_numbers, addresses, dapps, token_infos) = join!(
hashes::search_by_query(db, raw_query),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ pub struct Token {
pub chain_id: ChainId,
}

impl TryFrom<clients::token_info::TokenInfo> for Token {
impl TryFrom<clients::token_info::proto::TokenInfo> for Token {
type Error = ParseError;

fn try_from(v: clients::token_info::TokenInfo) -> Result<Self, Self::Error> {
fn try_from(v: clients::token_info::proto::TokenInfo) -> Result<Self, Self::Error> {
Ok(Self {
address: v.token_address.parse().map_err(ParseError::from)?,
icon_url: v.icon_url,
Expand All @@ -23,7 +23,10 @@ impl TryFrom<clients::token_info::TokenInfo> for Token {
symbol: v
.token_symbol
.ok_or_else(|| ParseError::Custom("token symbol is required".to_string()))?,
chain_id: v.chain_id.parse().map_err(ParseError::from)?,
chain_id: v
.chain_id
.try_into()
.map_err(|_| ParseError::Custom(format!("invalid chain id: {}", v.chain_id)))?,
})
}
}
Expand Down
8 changes: 6 additions & 2 deletions multichain-aggregator/multichain-aggregator-server/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,17 @@ config = { workspace = true }
sea-orm = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
serde_with = { workspace = true }
tokio = { workspace = true }
tonic = { workspace = true }
tracing = { workspace = true }
env-collector = { workspace = true }
url = { workspace = true, features = ["serde"] }

[dev-dependencies]
blockscout-service-launcher = { workspace = true, features = [ "test-server","test-database"] }
blockscout-service-launcher = { workspace = true, features = [
"test-server",
"test-database",
] }
pretty_assertions = { workspace = true }
reqwest = { workspace = true, features = ["json"]}
reqwest = { workspace = true, features = ["json"] }
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,11 @@ pub async fn run(settings: Settings) -> Result<(), anyhow::Error> {
repository::chains::upsert_many(&db, blockscout_chains.clone()).await?;

let dapp_client = dapp::new_client(settings.service.dapp_client.url)?;
let token_info_client = token_info::new_client(settings.service.token_info_client.url)?;
let token_info_client = {
let settings = settings.service.token_info_client;
let config = token_info::Config::new(settings.url).http_timeout(settings.timeout);
token_info::Client::new(config).await
};

let multichain_aggregator = Arc::new(MultichainAggregator::new(
db,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use api_client_framework::HttpApiClient;
use multichain_aggregator_logic::{
self as logic,
api_key_manager::ApiKeyManager,
clients::token_info::{SearchTokenInfos, SearchTokenInfosParams},
clients::token_info::{self, endpoints::SearchTokenInfos, proto::SearchTokenInfosRequest},
error::ServiceError,
Chain, Token,
};
Expand All @@ -27,7 +27,7 @@ pub struct MultichainAggregator {
// Cached chains
chains: Vec<Chain>,
dapp_client: HttpApiClient,
token_info_client: HttpApiClient,
token_info_client: token_info::Client,
api_settings: ApiSettings,
}

Expand All @@ -36,7 +36,7 @@ impl MultichainAggregator {
db: DatabaseConnection,
chains: Vec<Chain>,
dapp_client: HttpApiClient,
token_info_client: HttpApiClient,
token_info_client: token_info::Client,
api_settings: ApiSettings,
) -> Self {
Self {
Expand Down Expand Up @@ -123,14 +123,12 @@ impl MultichainAggregatorService for MultichainAggregator {

let chain_id = inner.chain_id.map(parse_query).transpose()?;

let token_info_search_endpoint = SearchTokenInfos {
params: SearchTokenInfosParams {
query: inner.q.to_string(),
chain_id,
page_size: inner.page_size,
page_token: inner.page_token,
},
};
let token_info_search_endpoint = SearchTokenInfos::new(SearchTokenInfosRequest {
query: inner.q.to_string(),
chain_id,
page_size: inner.page_size,
page_token: inner.page_token,
});
Comment on lines +126 to +131
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Implement thorough error handling & boundary checks.

Using SearchTokenInfos::new(...) with user-supplied parameters is good. Ensure validations are performed on inner.q, inner.page_size, etc., to avoid potential large or invalid requests. Consider falling back to default values or returning errors if the user input is out of range.


let res = self
.token_info_client
Expand Down
11 changes: 11 additions & 0 deletions multichain-aggregator/multichain-aggregator-server/src/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ use blockscout_service_launcher::{
tracing::{JaegerSettings, TracingSettings},
};
use serde::{Deserialize, Serialize};
use serde_with::serde_as;
use std::time;
use url::Url;

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
Expand Down Expand Up @@ -55,10 +57,14 @@ pub struct DappClientSettings {
pub url: Url,
}

#[serde_as]
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(deny_unknown_fields)]
pub struct TokenInfoClientSettings {
pub url: Url,
#[serde(default = "default_token_info_timeout")]
#[serde_as(as = "serde_with::DurationSeconds<u64>")]
pub timeout: time::Duration,
}

impl ConfigSettings for Settings {
Expand All @@ -84,6 +90,7 @@ impl Settings {
},
token_info_client: TokenInfoClientSettings {
url: Url::parse("http://localhost:8051").unwrap(),
timeout: default_token_info_timeout(),
},
api: ApiSettings {
default_page_size: default_default_page_size(),
Expand All @@ -101,3 +108,7 @@ fn default_max_page_size() -> u32 {
fn default_default_page_size() -> u32 {
50
}

fn default_token_info_timeout() -> time::Duration {
time::Duration::from_secs(5)
}
Loading