Skip to content

Commit

Permalink
Merge pull request #105 from propeller-heads/dc/add-quickstart
Browse files Browse the repository at this point in the history
feat: Add Quickstart
  • Loading branch information
dianacarvalho1 authored Dec 17, 2024
2 parents 953b282 + 5567bc8 commit 1bc9e39
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 9 deletions.
2 changes: 1 addition & 1 deletion examples/explorer/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ async fn main() {
let cli = Cli::parse();

let tycho_url =
env::var("TYCHO_URL").unwrap_or_else(|_| "tycho-dev.propellerheads.xyz".to_string());
env::var("TYCHO_URL").unwrap_or_else(|_| "tycho-beta.propellerheads.xyz".to_string());
let tycho_api_key: String =
env::var("TYCHO_API_KEY").unwrap_or_else(|_| "sampletoken".to_string());

Expand Down
15 changes: 15 additions & 0 deletions examples/quickstart/Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# QuickStart

This quickstart guide enables you to:

1. Retrieve data from the Tycho Indexer.
2. Leverage Tycho Simulation to:
1. Calculate spot prices.
2. Simulate token swaps.

## How to run

```bash
export RPC_URL=<your-eth-rpc-url>
cargo run --release --example quickstart
```
95 changes: 95 additions & 0 deletions examples/quickstart/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
use std::{collections::HashMap, env};

use futures::StreamExt;
use num_bigint::BigUint;
use tracing_subscriber::EnvFilter;
use tycho_simulation::{
evm::{
engine_db::tycho_db::PreCachedDB,
protocol::{
filters::balancer_pool_filter, uniswap_v2::state::UniswapV2State,
vm::state::EVMPoolState,
},
stream::ProtocolStreamBuilder,
},
models::Token,
protocol::models::BlockUpdate,
tycho_client::feed::component_tracker::ComponentFilter,
tycho_core::dto::Chain,
utils::load_all_tokens,
};

#[tokio::main]
async fn main() {
tracing_subscriber::fmt()
.with_env_filter(EnvFilter::from_default_env())
.with_target(false)
.init();

let tycho_url =
env::var("TYCHO_URL").unwrap_or_else(|_| "tycho-beta.propellerheads.xyz".to_string());
let tycho_api_key: String =
env::var("TYCHO_API_KEY").unwrap_or_else(|_| "sampletoken".to_string());

let tvl_threshold = 10_000.0;
let tvl_filter = ComponentFilter::with_tvl_range(tvl_threshold, tvl_threshold);

let all_tokens = load_all_tokens(tycho_url.as_str(), Some(tycho_api_key.as_str())).await;
let mut pairs: HashMap<String, Vec<Token>> = HashMap::new();

let mut protocol_stream = ProtocolStreamBuilder::new(&tycho_url, Chain::Ethereum)
.exchange::<UniswapV2State>("uniswap_v2", tvl_filter.clone(), None)
.exchange::<EVMPoolState<PreCachedDB>>(
"vm:balancer_v2",
tvl_filter.clone(),
Some(balancer_pool_filter),
)
.auth_key(Some(tycho_api_key.clone()))
.set_tokens(all_tokens.clone())
.await
.build()
.await
.expect("Failed building protocol stream");

while let Some(message) = protocol_stream.next().await {
let message = message.expect("Could not receive message");
print_calculations(message, &mut pairs);
}
}

fn print_calculations(message: BlockUpdate, pairs: &mut HashMap<String, Vec<Token>>) {
println!("==================== Received block {:?} ====================", message.block_number);
for (id, comp) in message.new_pairs.iter() {
pairs
.entry(id.clone())
.or_insert_with(|| comp.tokens.clone());
}
if message.states.is_empty() {
println!("No pools were updated this block");
return
}
println!("Using only pools that were updated this block...");
for (id, state) in message.states.iter().take(10) {
if let Some(tokens) = pairs.get(id) {
let formatted_token_str = format!("{:}/{:}", &tokens[0].symbol, &tokens[1].symbol);
println!("Calculations for pool {:?} with tokens {:?}", id, formatted_token_str);
state
.spot_price(&tokens[0], &tokens[1])
.map(|price| println!("Spot price {:?}: {:?}", formatted_token_str, price))
.map_err(|e| eprintln!("Error calculating spot price for Pool {:?}: {:?}", id, e))
.ok();
let amount_in =
BigUint::from(1u32) * BigUint::from(10u32).pow(tokens[0].decimals as u32);
state
.get_amount_out(amount_in, &tokens[0], &tokens[1])
.map(|result| {
println!(
"Amount out for trading 1 {:?} -> {:?}: {:?} (takes {:?} gas)",
&tokens[0].symbol, &tokens[1].symbol, result.amount, result.gas
)
})
.map_err(|e| eprintln!("Error calculating amount out for Pool {:?}: {:?}", id, e))
.ok();
}
}
}
11 changes: 5 additions & 6 deletions src/models.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
//! Basic data structures
//!
//! This module contains basic models that are shared across many
//! components of the crate, including Token, Swap and SwapSequence.
//! components of the crate.
//!
//! Tokens provide instructions on how to handle prices and amounts,
//! while Swap and SwapSequence are usually used as results types.
//! Tokens provide instructions on how to handle prices and amounts.
use std::{
convert::TryFrom,
hash::{Hash, Hasher},
Expand All @@ -29,9 +28,9 @@ pub struct Token {
}

impl Token {
/// Constructor for ERC20Token
/// Constructor for Token
///
/// Creates a new ERC20 token struct
/// Creates a new Token struct
///
/// ## Parameters
/// - `address`: token address as string
Expand All @@ -40,7 +39,7 @@ impl Token {
/// - `gas`: token gas as U256
///
/// ## Return
/// Return a new ERC20 token struct
/// Return a new Token struct
///
/// ## Panic
/// - Panics if the token address string is not in valid format
Expand Down
4 changes: 2 additions & 2 deletions src/protocol/models.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
//! `ProtocolState` into a single struct.
//!
//! # Note:
//! It's worth emphasizin that although the term "pair" used in this
//! It's worth emphasizing that although the term "pair" used in this
//! module refers to a trading pair, it does not necessarily imply two
//! tokens only. Some pairs might have more than two tokens.
use std::{collections::HashMap, future::Future};
Expand Down Expand Up @@ -95,7 +95,7 @@ impl GetAmountOutResult {
#[derive(Debug)]
pub struct BlockUpdate {
pub block_number: u64,
/// The current state of all pools
/// The new and updated states of this block
pub states: HashMap<String, Box<dyn ProtocolSim>>,
/// The new pairs that were added in this block
pub new_pairs: HashMap<String, ProtocolComponent>,
Expand Down
1 change: 1 addition & 0 deletions src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ pub fn hexstring_to_vec(hexstring: &str) -> Result<Vec<u8>, SimulationError> {
Ok(bytes)
}

/// Loads all tokens from Tycho and returns them as a Hashmap of address->Token.
pub async fn load_all_tokens(tycho_url: &str, auth_key: Option<&str>) -> HashMap<Bytes, Token> {
let rpc_url = format!("https://{tycho_url}");
let rpc_client = HttpRPCClient::new(rpc_url.as_str(), auth_key).unwrap();
Expand Down

0 comments on commit 1bc9e39

Please sign in to comment.