Skip to content

Commit 5275eef

Browse files
authored
Merge pull request #241 from propeller-heads/release/hooks
feat: Hooks
2 parents 950a491 + a9b5c27 commit 5275eef

File tree

21 files changed

+1827
-272
lines changed

21 files changed

+1827
-272
lines changed

Cargo.lock

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

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ unicode-width = "0.1.13"
9797
tracing-appender = "0.2.3"
9898

9999
# tycho execution for quickstart
100-
tycho-execution = "0.118.0"
100+
tycho-execution = "0.121.0"
101101

102102
[features]
103103
default = ["evm", "rfq"]

examples/price_printer/main.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,10 @@ fn register_exchanges(
6464
"uniswap_v4",
6565
tvl_filter.clone(),
6666
Some(uniswap_v4_pool_with_hook_filter),
67-
)
67+
);
6868
// COMING SOON!
69+
// .exchange::<UniswapV4State>("uniswap_v4_hooks", tvl_filter.clone(),
70+
// Some(uniswap_v4_pool_with_euler_hook_filter));
6971
// .exchange::<EVMPoolState<PreCachedDB>>("vm:maverick_v2", tvl_filter.clone(), None)
7072
}
7173
Chain::Base => {

examples/price_printer/ui.rs

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -150,22 +150,28 @@ impl App {
150150
.iter()
151151
.map(|a| a.symbol.clone())
152152
.join("/");
153-
let price = update
154-
.states
155-
.get(id)
156-
.map(|el| el.spot_price(&comp.tokens[0], &comp.tokens[1]))
157-
.unwrap_or(Ok(0.0))
158-
.expect("Expected spot price as f64");
159153

160154
match update.states.get(id) {
161155
Some(state) => {
162-
self.items.push(Data {
163-
component: comp.clone(),
164-
state: state.clone(),
165-
name,
166-
tokens,
167-
price: price.to_string(),
168-
});
156+
// Check if spot_price calculation is successful
157+
match state.spot_price(&comp.tokens[0], &comp.tokens[1]) {
158+
Ok(price) => {
159+
self.items.push(Data {
160+
component: comp.clone(),
161+
state: state.clone(),
162+
name,
163+
tokens,
164+
price: price.to_string(),
165+
});
166+
}
167+
Err(_) => {
168+
// Skip pools with spot_price errors
169+
warn!(
170+
"Skipping pool {comp_id} due to spot_price error",
171+
comp_id = comp.id
172+
);
173+
}
174+
}
169175
}
170176
None => {
171177
warn!("Received update for unknown pool {comp_id}", comp_id = comp.id)
@@ -180,12 +186,20 @@ impl App {
180186
.iter()
181187
.find_position(|e| e.component.id == eth_address);
182188
if let Some((index, _)) = entry {
183-
let row = self.items.get_mut(index).unwrap();
184-
let price = state
185-
.spot_price(&row.component.tokens[0], &row.component.tokens[1])
186-
.expect("Expected spot price as f64");
187-
row.price = price.to_string();
188-
row.state = state.clone();
189+
let row = &self.items[index];
190+
match state.spot_price(&row.component.tokens[0], &row.component.tokens[1]) {
191+
Ok(price) => {
192+
// Update the price and state if calculation is successful
193+
let row = self.items.get_mut(index).unwrap();
194+
row.price = price.to_string();
195+
row.state = state.clone();
196+
}
197+
Err(_) => {
198+
// Remove the pool if spot_price calculation fails
199+
warn!("Removing pool {} due to spot_price error", address);
200+
self.items.remove(index);
201+
}
202+
}
189203
}
190204
}
191205

examples/quickstart/main.rs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,8 @@ async fn main() {
184184
Some(curve_pool_filter),
185185
);
186186
// COMING SOON!
187+
// .exchange::<UniswapV4State>("uniswap_v4_hooks", tvl_filter.clone(),
188+
// Some(uniswap_v4_pool_with_euler_hook_filter));
187189
// .exchange::<EVMPoolState<PreCachedDB>>("vm:maverick_v2", tvl_filter.clone(), None);
188190
}
189191
Chain::Base => {
@@ -316,8 +318,8 @@ async fn main() {
316318
if balance < amount_in {
317319
let required = format_token_amount(&amount_in, &sell_token);
318320
println!("⚠️ Warning: Insufficient balance for swap. You have {formatted_balance} {sell_symbol} but need {required} {sell_symbol}",
319-
formatted_balance = formatted_balance,
320-
sell_symbol = sell_token.symbol,
321+
formatted_balance = formatted_balance,
322+
sell_symbol = sell_token.symbol,
321323
);
322324
return;
323325
}
@@ -541,13 +543,21 @@ fn get_best_swap(
541543
if HashSet::from([&sell_token, &buy_token])
542544
.is_subset(&HashSet::from_iter(tokens.iter()))
543545
{
544-
let amount_out = state
546+
let amount_out_result = state
545547
.get_amount_out(amount_in.clone(), &sell_token, &buy_token)
546548
.map_err(|e| eprintln!("Error calculating amount out for Pool {id:?}: {e:?}"))
547549
.ok();
548-
if let Some(amount_out) = amount_out {
550+
551+
if let Some(amount_out) = amount_out_result {
549552
amounts_out.insert(id.clone(), amount_out.amount);
550553
}
554+
555+
// If you would like to know how much of each token you are able to swap on the
556+
// pool, do
557+
// let limits = state
558+
// .get_limits(sell_token.address.clone(), buy_token.address.clone())
559+
// .unwrap();
560+
551561
// If you would like to save spot prices instead of the amount out, do
552562
// let spot_price = state
553563
// .spot_price(&tokens[0], &tokens[1])

src/evm/protocol/filters.rs

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,33 @@ pub fn balancer_v2_pool_filter(component: &ComponentWithState) -> bool {
1414
balancer_v2_pool_filter_after_dci_update(component)
1515
}
1616

17+
/// Filters out pools that have hooks in Uniswap V4
18+
pub fn uniswap_v4_pool_with_hook_filter(component: &ComponentWithState) -> bool {
19+
if let Some(hooks) = component
20+
.component
21+
.static_attributes
22+
.get("hooks")
23+
{
24+
if hooks.to_vec() != ZERO_ADDRESS_ARR {
25+
debug!("Filtering out UniswapV4 pool {} because it has hooks", component.component.id);
26+
return false;
27+
}
28+
}
29+
true
30+
}
31+
32+
pub fn uniswap_v4_pool_with_euler_hook_filter(component: &ComponentWithState) -> bool {
33+
if let Some(_hooks_data) = component
34+
.component
35+
.static_attributes
36+
.get("hook_identifier")
37+
{
38+
// Only Euler pools have a hook_identifier
39+
return true;
40+
}
41+
false
42+
}
43+
1744
/// Filters out pools that are failing at the moment after DCI update
1845
pub fn balancer_v2_pool_filter_after_dci_update(component: &ComponentWithState) -> bool {
1946
const UNSUPPORTED_COMPONENT_IDS: [&str; 6] = [
@@ -161,7 +188,7 @@ pub fn curve_pool_filter(component: &ComponentWithState) -> bool {
161188
"Filtering out Curve pool {} because it belongs to an unsupported factory",
162189
component.component.id
163190
);
164-
return false
191+
return false;
165192
}
166193
};
167194

@@ -181,27 +208,12 @@ pub fn curve_pool_filter(component: &ComponentWithState) -> bool {
181208
"Filtering out Curve pool {} because it has a rebasing token that is not supported",
182209
component.component.id
183210
);
184-
return false
211+
return false;
185212
}
186213

187214
true
188215
}
189216

190-
/// Filters out pools that have hooks in Uniswap V4
191-
pub fn uniswap_v4_pool_with_hook_filter(component: &ComponentWithState) -> bool {
192-
if let Some(hooks) = component
193-
.component
194-
.static_attributes
195-
.get("hooks")
196-
{
197-
if hooks.to_vec() != ZERO_ADDRESS_ARR {
198-
debug!("Filtering out UniswapV4 pool {} because it has hooks", component.component.id);
199-
return false;
200-
}
201-
}
202-
true
203-
}
204-
205217
/// Filters out pools that rely on ERC4626 in Balancer V3
206218
pub fn balancer_v3_pool_filter(component: &ComponentWithState) -> bool {
207219
if let Some(erc4626) = component
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
#![allow(dead_code)]
1+
#[allow(dead_code)]
22
pub const POOL_MANAGER_BYTECODE: &[u8] = include_bytes!("assets/pool_manager_bytecode.bin");

0 commit comments

Comments
 (0)