feat: Add methods to fetch state from Tycho RPC

This commit is contained in:
Thales Lima
2025-03-13 10:56:18 -03:00
committed by Tamara
parent 160523a888
commit 2c8e349280
6 changed files with 268 additions and 24 deletions

View File

@@ -1,8 +1,9 @@
mod config;
mod rpc;
mod test_runner;
mod utils;
mod tycho_runner;
mod utils;
mod tycho_rpc;
use clap::Parser;
use tracing_subscriber::EnvFilter;

View File

@@ -1,20 +1,19 @@
use std::{
path::{Path, PathBuf},
thread::sleep,
time::Duration,
};
use std::{collections::HashMap, path::PathBuf};
use figment::{
providers::{Format, Yaml},
Figment,
};
use postgres::{Client, Error, NoTls};
use tracing::{debug, field::debug, info};
use tokio::runtime::Runtime;
use tracing::{debug, info};
use tycho_core::dto::{Chain, ProtocolComponent};
use crate::{
config::{IntegrationTest, IntegrationTestsConfig},
tycho_rpc::TychoClient,
tycho_runner::TychoRunner,
utils::{build_spkg, modify_initial_block},
utils::build_spkg,
};
pub struct TestRunner {
@@ -92,7 +91,7 @@ impl TestRunner {
)
.expect("Failed to run Tycho");
tycho_runner.run_with_rpc_server(validate_state)
tycho_runner.run_with_rpc_server(validate_state);
}
fn empty_database(&self) -> Result<(), Error> {
@@ -113,7 +112,33 @@ impl TestRunner {
}
}
pub fn validate_state() {
// TODO: Implement
fn validate_state() {
let rt = Runtime::new().unwrap();
// Create Tycho client for the RPC server
let tycho_client =
TychoClient::new("http://localhost:4242").expect("Failed to create Tycho client");
let chain = Chain::Ethereum;
let protocol_system = "test_protocol";
let protocol_components = rt
.block_on(tycho_client.get_protocol_components(protocol_system, chain))
.expect("Failed to get protocol components");
let protocol_states = rt
.block_on(tycho_client.get_protocol_state(protocol_system, chain))
.expect("Failed to get protocol state");
// Create a map of component IDs to components for easy lookup
let components_by_id: HashMap<String, ProtocolComponent> = protocol_components
.into_iter()
.map(|c| (c.id.clone(), c))
.collect();
info!("Found {} protocol components", components_by_id.len());
info!("Found {} protocol states", protocol_states.len());
// TODO: Implement complete validation logic similar to Python code
info!("Validating state...");
}

View File

@@ -0,0 +1,126 @@
use std::{error::Error as StdError, fmt};
use tycho_client::{rpc::RPCClient, HttpRPCClient};
use tycho_core::{
dto::{
Chain, ProtocolComponent, ProtocolComponentsRequestBody, ResponseAccount,
ResponseProtocolState, VersionParam,
},
models::Address,
};
/// Custom error type for RPC operations
#[derive(Debug)]
pub enum RpcError {
ClientError(String),
ResponseError(String),
}
impl fmt::Display for RpcError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
RpcError::ClientError(msg) => write!(f, "RPC client error: {}", msg),
RpcError::ResponseError(msg) => write!(f, "RPC response error: {}", msg),
}
}
}
impl StdError for RpcError {}
impl From<Box<dyn StdError>> for RpcError {
fn from(error: Box<dyn StdError>) -> Self {
RpcError::ClientError(error.to_string())
}
}
impl From<tycho_client::RPCError> for RpcError {
fn from(error: tycho_client::RPCError) -> Self {
RpcError::ClientError(error.to_string())
}
}
/// Client for interacting with the Tycho RPC server
pub struct TychoClient {
http_client: HttpRPCClient,
}
impl TychoClient {
pub fn new(host: &str) -> Result<Self, RpcError> {
let http_client =
HttpRPCClient::new(host, None).map_err(|e| RpcError::ClientError(e.to_string()))?;
Ok(Self { http_client })
}
/// Gets protocol components from the RPC server
pub async fn get_protocol_components(
&self,
protocol_system: &str,
chain: Chain,
) -> Result<Vec<ProtocolComponent>, RpcError> {
let request = ProtocolComponentsRequestBody::system_filtered(protocol_system, None, chain);
let chunk_size = 100;
let concurrency = 1;
let response = self
.http_client
.get_protocol_components_paginated(&request, chunk_size, concurrency)
.await?;
Ok(response.protocol_components)
}
/// Gets protocol state from the RPC server
pub async fn get_protocol_state(
&self,
protocol_system: &str,
chain: Chain,
) -> Result<Vec<ResponseProtocolState>, RpcError> {
let chunk_size = 100;
let concurrency = 1;
let ids: &[String] = &[];
let version: tycho_core::dto::VersionParam = VersionParam::default();
let protocol_states = self
.http_client
.get_protocol_states_paginated(
chain,
ids,
protocol_system,
true,
&version,
chunk_size,
concurrency,
)
.await?;
Ok(protocol_states.states)
}
/// Gets contract state from the RPC server
pub async fn get_contract_state(
&self,
contract_ids: Vec<Address>,
protocol_system: &str,
chain: Chain,
) -> Result<Vec<ResponseAccount>, RpcError> {
// Pagination parameters
let chunk_size = 100;
let concurrency = 1;
let version: tycho_core::dto::VersionParam = VersionParam::default();
let contract_states = self
.http_client
.get_contract_state_paginated(
chain,
&contract_ids,
protocol_system,
&version,
chunk_size,
concurrency,
)
.await?;
Ok(contract_states.accounts)
}
}

View File

@@ -1,12 +1,7 @@
use std::{
env,
io::{BufRead, BufReader},
path::Path,
process::{Child, Command, Stdio},
sync::{
mpsc::{self, Receiver, Sender},
Arc, Mutex,
},
sync::mpsc::{self, Receiver, Sender},
thread,
time::Duration,
};
@@ -110,7 +105,7 @@ impl TychoRunner {
let binary_path = "tycho-indexer";
let mut cmd = Command::new(binary_path)
.args(&["--database-url", db_url.as_str(), "rpc"])
.args(["--database-url", db_url.as_str(), "rpc"])
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.env("RUST_LOG", "info")