abis + params

This commit is contained in:
0xMochan
2024-05-02 03:18:58 -05:00
parent a66c9a3965
commit 692579e930
15 changed files with 28819 additions and 146 deletions

View File

@@ -15,6 +15,7 @@ abis = {
"CryptoPoolFactory": "0xF18056Bbd320E96A48e3Fbf8bC061322531aac99",
# pool
"Pool": "0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7",
"3Pool": "0x5F890841f657d90E081bAbdB532A05996Af79Fe6",
}
ABI_ENDPOINT = (

View File

@@ -0,0 +1,895 @@
[
{
"name": "TokenExchange",
"inputs": [
{
"type": "address",
"name": "buyer",
"indexed": true
},
{
"type": "int128",
"name": "sold_id",
"indexed": false
},
{
"type": "uint256",
"name": "tokens_sold",
"indexed": false
},
{
"type": "int128",
"name": "bought_id",
"indexed": false
},
{
"type": "uint256",
"name": "tokens_bought",
"indexed": false
}
],
"anonymous": false,
"type": "event"
},
{
"name": "TokenExchangeUnderlying",
"inputs": [
{
"type": "address",
"name": "buyer",
"indexed": true
},
{
"type": "int128",
"name": "sold_id",
"indexed": false
},
{
"type": "uint256",
"name": "tokens_sold",
"indexed": false
},
{
"type": "int128",
"name": "bought_id",
"indexed": false
},
{
"type": "uint256",
"name": "tokens_bought",
"indexed": false
}
],
"anonymous": false,
"type": "event"
},
{
"name": "AddLiquidity",
"inputs": [
{
"type": "address",
"name": "provider",
"indexed": true
},
{
"type": "uint256[2]",
"name": "token_amounts",
"indexed": false
},
{
"type": "uint256[2]",
"name": "fees",
"indexed": false
},
{
"type": "uint256",
"name": "invariant",
"indexed": false
},
{
"type": "uint256",
"name": "token_supply",
"indexed": false
}
],
"anonymous": false,
"type": "event"
},
{
"name": "RemoveLiquidity",
"inputs": [
{
"type": "address",
"name": "provider",
"indexed": true
},
{
"type": "uint256[2]",
"name": "token_amounts",
"indexed": false
},
{
"type": "uint256[2]",
"name": "fees",
"indexed": false
},
{
"type": "uint256",
"name": "token_supply",
"indexed": false
}
],
"anonymous": false,
"type": "event"
},
{
"name": "RemoveLiquidityOne",
"inputs": [
{
"type": "address",
"name": "provider",
"indexed": true
},
{
"type": "uint256",
"name": "token_amount",
"indexed": false
},
{
"type": "uint256",
"name": "coin_amount",
"indexed": false
}
],
"anonymous": false,
"type": "event"
},
{
"name": "RemoveLiquidityImbalance",
"inputs": [
{
"type": "address",
"name": "provider",
"indexed": true
},
{
"type": "uint256[2]",
"name": "token_amounts",
"indexed": false
},
{
"type": "uint256[2]",
"name": "fees",
"indexed": false
},
{
"type": "uint256",
"name": "invariant",
"indexed": false
},
{
"type": "uint256",
"name": "token_supply",
"indexed": false
}
],
"anonymous": false,
"type": "event"
},
{
"name": "CommitNewAdmin",
"inputs": [
{
"type": "uint256",
"name": "deadline",
"indexed": true
},
{
"type": "address",
"name": "admin",
"indexed": true
}
],
"anonymous": false,
"type": "event"
},
{
"name": "NewAdmin",
"inputs": [
{
"type": "address",
"name": "admin",
"indexed": true
}
],
"anonymous": false,
"type": "event"
},
{
"name": "CommitNewFee",
"inputs": [
{
"type": "uint256",
"name": "deadline",
"indexed": true
},
{
"type": "uint256",
"name": "fee",
"indexed": false
},
{
"type": "uint256",
"name": "admin_fee",
"indexed": false
}
],
"anonymous": false,
"type": "event"
},
{
"name": "NewFee",
"inputs": [
{
"type": "uint256",
"name": "fee",
"indexed": false
},
{
"type": "uint256",
"name": "admin_fee",
"indexed": false
}
],
"anonymous": false,
"type": "event"
},
{
"name": "RampA",
"inputs": [
{
"type": "uint256",
"name": "old_A",
"indexed": false
},
{
"type": "uint256",
"name": "new_A",
"indexed": false
},
{
"type": "uint256",
"name": "initial_time",
"indexed": false
},
{
"type": "uint256",
"name": "future_time",
"indexed": false
}
],
"anonymous": false,
"type": "event"
},
{
"name": "StopRampA",
"inputs": [
{
"type": "uint256",
"name": "A",
"indexed": false
},
{
"type": "uint256",
"name": "t",
"indexed": false
}
],
"anonymous": false,
"type": "event"
},
{
"outputs": [],
"inputs": [
{
"type": "address",
"name": "_owner"
},
{
"type": "address[2]",
"name": "_coins"
},
{
"type": "address",
"name": "_pool_token"
},
{
"type": "uint256",
"name": "_A"
},
{
"type": "uint256",
"name": "_fee"
},
{
"type": "uint256",
"name": "_admin_fee"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"name": "A",
"outputs": [
{
"type": "uint256",
"name": ""
}
],
"inputs": [],
"stateMutability": "view",
"type": "function",
"gas": 5289
},
{
"name": "A_precise",
"outputs": [
{
"type": "uint256",
"name": ""
}
],
"inputs": [],
"stateMutability": "view",
"type": "function",
"gas": 5251
},
{
"name": "balances",
"outputs": [
{
"type": "uint256",
"name": ""
}
],
"inputs": [
{
"type": "uint256",
"name": "i"
}
],
"stateMutability": "view",
"type": "function",
"gas": 5076
},
{
"name": "get_virtual_price",
"outputs": [
{
"type": "uint256",
"name": ""
}
],
"inputs": [],
"stateMutability": "view",
"type": "function",
"gas": 1114301
},
{
"name": "calc_token_amount",
"outputs": [
{
"type": "uint256",
"name": ""
}
],
"inputs": [
{
"type": "uint256[2]",
"name": "amounts"
},
{
"type": "bool",
"name": "is_deposit"
}
],
"stateMutability": "view",
"type": "function",
"gas": 2218181
},
{
"name": "add_liquidity",
"outputs": [
{
"type": "uint256",
"name": ""
}
],
"inputs": [
{
"type": "uint256[2]",
"name": "amounts"
},
{
"type": "uint256",
"name": "min_mint_amount"
}
],
"stateMutability": "payable",
"type": "function",
"gas": 3484118
},
{
"name": "get_dy",
"outputs": [
{
"type": "uint256",
"name": ""
}
],
"inputs": [
{
"type": "int128",
"name": "i"
},
{
"type": "int128",
"name": "j"
},
{
"type": "uint256",
"name": "dx"
}
],
"stateMutability": "view",
"type": "function",
"gas": 2654541
},
{
"name": "exchange",
"outputs": [
{
"type": "uint256",
"name": ""
}
],
"inputs": [
{
"type": "int128",
"name": "i"
},
{
"type": "int128",
"name": "j"
},
{
"type": "uint256",
"name": "dx"
},
{
"type": "uint256",
"name": "min_dy"
}
],
"stateMutability": "payable",
"type": "function",
"gas": 2810134
},
{
"name": "remove_liquidity",
"outputs": [
{
"type": "uint256[2]",
"name": ""
}
],
"inputs": [
{
"type": "uint256",
"name": "_amount"
},
{
"type": "uint256[2]",
"name": "_min_amounts"
}
],
"stateMutability": "nonpayable",
"type": "function",
"gas": 160545
},
{
"name": "remove_liquidity_imbalance",
"outputs": [
{
"type": "uint256",
"name": ""
}
],
"inputs": [
{
"type": "uint256[2]",
"name": "_amounts"
},
{
"type": "uint256",
"name": "_max_burn_amount"
}
],
"stateMutability": "nonpayable",
"type": "function",
"gas": 3519382
},
{
"name": "calc_withdraw_one_coin",
"outputs": [
{
"type": "uint256",
"name": ""
}
],
"inputs": [
{
"type": "uint256",
"name": "_token_amount"
},
{
"type": "int128",
"name": "i"
}
],
"stateMutability": "view",
"type": "function",
"gas": 1435
},
{
"name": "remove_liquidity_one_coin",
"outputs": [
{
"type": "uint256",
"name": ""
}
],
"inputs": [
{
"type": "uint256",
"name": "_token_amount"
},
{
"type": "int128",
"name": "i"
},
{
"type": "uint256",
"name": "_min_amount"
}
],
"stateMutability": "nonpayable",
"type": "function",
"gas": 4113806
},
{
"name": "ramp_A",
"outputs": [],
"inputs": [
{
"type": "uint256",
"name": "_future_A"
},
{
"type": "uint256",
"name": "_future_time"
}
],
"stateMutability": "nonpayable",
"type": "function",
"gas": 151834
},
{
"name": "stop_ramp_A",
"outputs": [],
"inputs": [],
"stateMutability": "nonpayable",
"type": "function",
"gas": 148595
},
{
"name": "commit_new_fee",
"outputs": [],
"inputs": [
{
"type": "uint256",
"name": "new_fee"
},
{
"type": "uint256",
"name": "new_admin_fee"
}
],
"stateMutability": "nonpayable",
"type": "function",
"gas": 110431
},
{
"name": "apply_new_fee",
"outputs": [],
"inputs": [],
"stateMutability": "nonpayable",
"type": "function",
"gas": 153115
},
{
"name": "revert_new_parameters",
"outputs": [],
"inputs": [],
"stateMutability": "nonpayable",
"type": "function",
"gas": 21865
},
{
"name": "commit_transfer_ownership",
"outputs": [],
"inputs": [
{
"type": "address",
"name": "_owner"
}
],
"stateMutability": "nonpayable",
"type": "function",
"gas": 74603
},
{
"name": "apply_transfer_ownership",
"outputs": [],
"inputs": [],
"stateMutability": "nonpayable",
"type": "function",
"gas": 116583
},
{
"name": "revert_transfer_ownership",
"outputs": [],
"inputs": [],
"stateMutability": "nonpayable",
"type": "function",
"gas": 21955
},
{
"name": "withdraw_admin_fees",
"outputs": [],
"inputs": [],
"stateMutability": "nonpayable",
"type": "function",
"gas": 137597
},
{
"name": "donate_admin_fees",
"outputs": [],
"inputs": [],
"stateMutability": "nonpayable",
"type": "function",
"gas": 42144
},
{
"name": "kill_me",
"outputs": [],
"inputs": [],
"stateMutability": "nonpayable",
"type": "function",
"gas": 37938
},
{
"name": "unkill_me",
"outputs": [],
"inputs": [],
"stateMutability": "nonpayable",
"type": "function",
"gas": 22075
},
{
"name": "coins",
"outputs": [
{
"type": "address",
"name": ""
}
],
"inputs": [
{
"type": "uint256",
"name": "arg0"
}
],
"stateMutability": "view",
"type": "function",
"gas": 2160
},
{
"name": "admin_balances",
"outputs": [
{
"type": "uint256",
"name": ""
}
],
"inputs": [
{
"type": "uint256",
"name": "arg0"
}
],
"stateMutability": "view",
"type": "function",
"gas": 2190
},
{
"name": "fee",
"outputs": [
{
"type": "uint256",
"name": ""
}
],
"inputs": [],
"stateMutability": "view",
"type": "function",
"gas": 2111
},
{
"name": "admin_fee",
"outputs": [
{
"type": "uint256",
"name": ""
}
],
"inputs": [],
"stateMutability": "view",
"type": "function",
"gas": 2141
},
{
"name": "owner",
"outputs": [
{
"type": "address",
"name": ""
}
],
"inputs": [],
"stateMutability": "view",
"type": "function",
"gas": 2171
},
{
"name": "lp_token",
"outputs": [
{
"type": "address",
"name": ""
}
],
"inputs": [],
"stateMutability": "view",
"type": "function",
"gas": 2201
},
{
"name": "initial_A",
"outputs": [
{
"type": "uint256",
"name": ""
}
],
"inputs": [],
"stateMutability": "view",
"type": "function",
"gas": 2231
},
{
"name": "future_A",
"outputs": [
{
"type": "uint256",
"name": ""
}
],
"inputs": [],
"stateMutability": "view",
"type": "function",
"gas": 2261
},
{
"name": "initial_A_time",
"outputs": [
{
"type": "uint256",
"name": ""
}
],
"inputs": [],
"stateMutability": "view",
"type": "function",
"gas": 2291
},
{
"name": "future_A_time",
"outputs": [
{
"type": "uint256",
"name": ""
}
],
"inputs": [],
"stateMutability": "view",
"type": "function",
"gas": 2321
},
{
"name": "admin_actions_deadline",
"outputs": [
{
"type": "uint256",
"name": ""
}
],
"inputs": [],
"stateMutability": "view",
"type": "function",
"gas": 2351
},
{
"name": "transfer_ownership_deadline",
"outputs": [
{
"type": "uint256",
"name": ""
}
],
"inputs": [],
"stateMutability": "view",
"type": "function",
"gas": 2381
},
{
"name": "future_fee",
"outputs": [
{
"type": "uint256",
"name": ""
}
],
"inputs": [],
"stateMutability": "view",
"type": "function",
"gas": 2411
},
{
"name": "future_admin_fee",
"outputs": [
{
"type": "uint256",
"name": ""
}
],
"inputs": [],
"stateMutability": "view",
"type": "function",
"gas": 2441
},
{
"name": "future_owner",
"outputs": [
{
"type": "address",
"name": ""
}
],
"inputs": [],
"stateMutability": "view",
"type": "function",
"gas": 2471
}
]

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,12 @@
[
{
"address": "0x5F890841f657d90E081bAbdB532A05996Af79Fe6",
"tx_hash": "0xb71a66c1d93c525a2dd19a8db0da19e65be04f36e733af7f03e3c9dff41aa16a",
"tokens": [
"0x6b175474e89094c44da98b954eedeac495271d0f",
"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
"0xdac17f958d2ee523a2206206994597c13d831ec7"
],
"attributes": {}
}
]

View File

@@ -0,0 +1,48 @@
# This script could theoretically be done in a Makefile or pure bash with a program like `jq`.
import json
from typing import Any
PARAMETERS = "params.json"
def encode_json_to_query_params(params: list[dict[str, Any]]):
encoded_params = []
try:
for i, param in enumerate(params):
address: str = param["address"]
tx_hash: str = param["tx_hash"]
tokens: list[str] = param["tokens"]
attributes: dict[str, str] = param["attributes"]
encoded_address = f"address={address}"
encoded_tx_hash = f"tx_hash={tx_hash}"
encoded_tokens = "&".join([f"tokens[]={token}" for token in tokens])
encoded_attributes = "&".join(
[
f"attribute_keys[]={key}&attribute_vals[]={value}"
for key, value in attributes.items()
]
)
encoded_param = f"{encoded_address}&{encoded_tx_hash}&{encoded_tokens}&{encoded_attributes}"
encoded_param = encoded_param.rstrip("&")
encoded_params.append(encoded_param)
except KeyError as err:
raise KeyError(
f"Missing key in {PARAMETERS}.\n"
f"Index `{i}` object missing parameters.\n\n" + err.args[0]
)
return ",".join(encoded_params)
def main():
with open(PARAMETERS, "r") as f:
params = json.load(f)
print('"', encode_json_to_query_params(params), '"', sep="")
if __name__ == "__main__":
main()

View File

@@ -1,5 +1,8 @@
pub mod crypto_pool_factory;
pub mod pool_tricrypto;
pub mod pool_steth;
pub mod pool;
pub mod main_registry;
pub mod pool_3pool;
pub mod meta_pool_factory;
pub mod crypto_swap_registry;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,5 @@
mod abi;
pub mod modules;
mod pool_changes;
mod pool_factories;
mod pools;

View File

@@ -16,7 +16,7 @@ use substreams_ethereum::{block_view::LogView, pb::eth};
use substreams_ethereum::Event;
use crate::{abi, pool_factories, pools::emit_specific_pools};
use crate::{abi, pool_changes::emit_deltas, pool_factories, pools::emit_specific_pools};
use tycho_substreams::{
balances::store_balance_changes, contract::extract_contract_changes, prelude::*,
};
@@ -32,15 +32,6 @@ impl PartialEq for TransactionWrapper {
}
}
fn tx_from_log(log: &LogView) -> Transaction {
Transaction {
hash: log.receipt.transaction.hash.clone(),
from: log.receipt.transaction.from.clone(),
to: log.receipt.transaction.to.clone(),
index: Into::<u64>::into(log.receipt.transaction.index),
}
}
#[substreams::handlers::map]
pub fn map_components(
params: String,
@@ -132,111 +123,7 @@ pub fn map_relative_balances(
pools_store: StoreGetInt64,
tokens_store: StoreGetString,
) -> Result<BlockBalanceDeltas, anyhow::Error> {
let mut deltas = block
.logs()
.filter_map(|log| {
let event = abi::pool::events::TokenExchange::match_and_decode(log)?;
Some((log, event))
})
.filter(|(log, _)| {
pools_store
.get_last(format!("pool:{0}", hex::encode(&log.address())))
.is_some()
})
.flat_map(|(log, event)| {
let tokens_bought_delta: BigInt = event.tokens_bought * -1;
vec![
BalanceDelta {
ord: log.log.ordinal,
tx: Some(tx_from_log(&log)),
token: event.sold_id.to_signed_bytes_be(),
delta: event.tokens_sold.to_signed_bytes_be(),
component_id: log.address().into(),
},
BalanceDelta {
ord: log.log.ordinal,
tx: Some(tx_from_log(&log)),
token: event.bought_id.to_signed_bytes_be(),
delta: tokens_bought_delta.to_signed_bytes_be(),
component_id: log.address().into(),
},
]
})
.collect::<Vec<_>>();
deltas.extend(
block
.logs()
.filter_map(|log| {
let event = abi::pool::events::AddLiquidity::match_and_decode(log)?;
Some((log, event))
})
.filter_map(|(log, event)| {
let tokens = tokens_store
.get_last(format!("pool:{0}", hex::encode(log.address())))?
.split(":")
.map(|token| token.to_owned()) // Clone the tokens
.collect::<Vec<_>>();
Some((tokens, log, event))
})
.flat_map(|(tokens, log, event)| {
event
.token_amounts
.iter()
.zip(tokens)
.map(move |(token_amount, token_id)| BalanceDelta {
ord: log.log.ordinal,
tx: Some(tx_from_log(&log)),
token: token_id.into(),
delta: token_amount.to_signed_bytes_be(),
component_id: log.address().into(),
})
.collect::<Vec<_>>()
})
.collect::<Vec<_>>(),
);
deltas.extend(
block
.logs()
.filter_map(|log| {
let event = abi::pool::events::RemoveLiquidity::match_and_decode(log)?;
Some((log, event))
})
.filter(|(log, _)| {
pools_store
.get_last(format!("pool:{0}", hex::encode(&log.address())))
.is_none()
})
.flat_map(|(log, event)| {
let tokens = tokens_store
.get_last(format!("pool:{}", hex::encode(log.address())))
.unwrap()
.split(":")
.map(|token| token.to_owned()) // Clone the tokens
.collect::<Vec<_>>();
event
.token_amounts
.iter()
.zip(tokens)
.map(move |(token_amount, token_id)| {
let negative_token_amount: BigInt = token_amount * BigInt::from(-1);
BalanceDelta {
ord: log.log.ordinal,
tx: Some(tx_from_log(&log)),
token: token_id.into(),
delta: negative_token_amount.to_signed_bytes_be(),
component_id: log.address().into(),
}
})
.collect::<Vec<_>>()
})
.collect::<Vec<_>>(),
);
Ok(BlockBalanceDeltas { balance_deltas: deltas })
Ok(BlockBalanceDeltas { balance_deltas: emit_deltas(block, pools_store, tokens_store) })
}
/// It's significant to include both the `pool_id` and the `token_id` for each balance delta as the

View File

@@ -0,0 +1,167 @@
use substreams::{
scalar::BigInt,
store::{StoreGet, StoreGetInt64, StoreGetString},
};
use substreams_ethereum::{block_view::LogView, pb::eth, Event};
use tycho_substreams::prelude::*;
use crate::abi;
fn tx_from_log(log: &LogView) -> Transaction {
Transaction {
hash: log.receipt.transaction.hash.clone(),
from: log.receipt.transaction.from.clone(),
to: log.receipt.transaction.to.clone(),
index: Into::<u64>::into(log.receipt.transaction.index),
}
}
pub fn emit_deltas(
log: LogView,
pools_store: StoreGetInt64,
tokens_store: StoreGetString,
) -> Option<impl Iterator<Item = BalanceDelta>> {
if let Some(event) = abi::pool::events::TokenExchange::match_and_decode(log) {
if pools_store
.get_last(format!("pool:{0}", hex::encode(&log.address())))
.is_none()
{
return None;
}
let tokens_bought_delta: BigInt = event.tokens_bought * -1;
return Some(
vec![
BalanceDelta {
ord: log.log.ordinal,
tx: Some(tx_from_log(&log)),
token: event.sold_id.to_signed_bytes_be(),
delta: event.tokens_sold.to_signed_bytes_be(),
component_id: log.address().into(),
},
BalanceDelta {
ord: log.log.ordinal,
tx: Some(tx_from_log(&log)),
token: event.bought_id.to_signed_bytes_be(),
delta: tokens_bought_delta.to_signed_bytes_be(),
component_id: log.address().into(),
},
]
.into_iter(),
)
} else if let Some(event) = abi::pool::events::AddLiquidity::match_and_decode(log) {
let tokens = tokens_store
.get_last(format!("pool:{0}", hex::encode(log.address())))?
.split(":")
.map(|token| token.to_owned()) // Clone the tokens
.collect::<Vec<_>>();
let deltas: Vec<_> = event
.token_amounts
.iter()
.zip(tokens)
.map(move |(token_amount, token_id)| BalanceDelta {
ord: log.log.ordinal,
tx: Some(tx_from_log(&log)),
token: token_id.into(),
delta: token_amount.to_signed_bytes_be(),
component_id: log.address().into(),
})
.collect();
return Some(deltas.into_iter());
} else if let Some(event) = abi::pool::events::RemoveLiquidity::match_and_decode(log) {
let tokens = tokens_store
.get_last(format!("pool:{0}", hex::encode(log.address())))?
.split(":")
.map(|token| token.to_owned()) // Clone the tokens
.collect::<Vec<_>>();
let deltas: Vec<_> = event
.token_amounts
.iter()
.zip(tokens)
.map(move |(token_amount, token_id)| BalanceDelta {
ord: log.log.ordinal,
tx: Some(tx_from_log(&log)),
token: token_id.into(),
delta: token_amount.to_signed_bytes_be(),
component_id: log.address().into(),
})
.collect();
return Some(deltas.into_iter());
}
deltas.extend(
block
.logs()
.filter_map(|log| {
let event = abi::pool::events::AddLiquidity::match_and_decode(log)?;
Some((log, event))
})
.filter_map(|(log, event)| {
let tokens = tokens_store
.get_last(format!("pool:{0}", hex::encode(log.address())))?
.split(":")
.map(|token| token.to_owned()) // Clone the tokens
.collect::<Vec<_>>();
Some((tokens, log, event))
})
.flat_map(|(tokens, log, event)| {
event
.token_amounts
.iter()
.zip(tokens)
.map(move |(token_amount, token_id)| BalanceDelta {
ord: log.log.ordinal,
tx: Some(tx_from_log(&log)),
token: token_id.into(),
delta: token_amount.to_signed_bytes_be(),
component_id: log.address().into(),
})
.collect::<Vec<_>>()
})
.collect::<Vec<_>>(),
);
deltas.extend(
block
.logs()
.filter_map(|log| {
let event = abi::pool::events::RemoveLiquidity::match_and_decode(log)?;
Some((log, event))
})
.filter(|(log, _)| {
pools_store
.get_last(format!("pool:{0}", hex::encode(&log.address())))
.is_none()
})
.flat_map(|(log, event)| {
let tokens = tokens_store
.get_last(format!("pool:{}", hex::encode(log.address())))
.unwrap()
.split(":")
.map(|token| token.to_owned()) // Clone the tokens
.collect::<Vec<_>>();
event
.token_amounts
.iter()
.zip(tokens)
.map(move |(token_amount, token_id)| {
let negative_token_amount: BigInt = token_amount * BigInt::from(-1);
BalanceDelta {
ord: log.log.ordinal,
tx: Some(tx_from_log(&log)),
token: token_id.into(),
delta: negative_token_amount.to_signed_bytes_be(),
component_id: log.address().into(),
}
})
.collect::<Vec<_>>()
})
.collect::<Vec<_>>(),
);
deltas
}

View File

@@ -1,18 +1,18 @@
use std::collections::HashMap;
use anyhow::{Context, Result};
use serde::Deserialize;
use std::{collections::HashMap, iter::zip};
use substreams_ethereum::pb::eth;
use tycho_substreams::prelude::*;
const PARAMS_SEPERATOR: &str = ",";
#[derive(Debug, Deserialize)]
#[derive(Debug, Deserialize, PartialEq)]
struct PoolQueryParams {
address: String,
tx_hash: String,
tokens: Vec<String>,
attributes: Vec<(String, String)>,
attribute_keys: Vec<String>,
attribute_vals: Vec<String>,
}
/// This function parses the `params` string and extracts the pool query parameters. `params` are
@@ -32,19 +32,15 @@ pub fn emit_specific_pools(
params: &String,
block: &eth::v2::Block,
) -> Result<Vec<ProtocolComponent>> {
let pools: HashMap<String, PoolQueryParams> = params
.split(PARAMS_SEPERATOR)
.map(|param| {
// TODO UNSAFE
let pool: PoolQueryParams = serde_qs::from_str(&param)
.with_context(|| format!("Failed to parse pool query params: {0}", param))?;
Ok((pool.tx_hash.clone(), pool))
})
.collect::<Result<HashMap<_, _>>>()
.with_context(|| "Failed to parse all pool query params")?;
let pools = parse_params(params)?;
create_components(block, pools)
}
fn create_components(
block: &eth::v2::Block,
pools: HashMap<String, PoolQueryParams>,
) -> Result<Vec<ProtocolComponent>, anyhow::Error> {
let mut components: Vec<ProtocolComponent> = vec![];
for tx in block.transactions() {
let encoded_hash = hex::encode(tx.hash.clone());
if let Some(pool) = pools.get(&encoded_hash) {
@@ -63,13 +59,15 @@ pub fn emit_specific_pools(
.map(|token| Result::Ok(hex::decode(token)?))
.collect::<Result<Vec<_>>>()
.with_context(|| "Token addresses were not formatted properly")?,
static_att: pool
.attributes
static_att: zip(
pool.attribute_keys.clone().into_iter(),
pool.attribute_vals.clone().into_iter(),
)
.clone()
.into_iter()
.map(|attr| Attribute {
name: attr.0,
value: attr.1.into(),
.map(|(key, value)| Attribute {
name: key,
value: value.into(),
change: ChangeType::Creation.into(),
})
.collect::<Vec<_>>(),
@@ -88,3 +86,46 @@ pub fn emit_specific_pools(
}
Ok(components)
}
fn parse_params(params: &String) -> Result<HashMap<String, PoolQueryParams>, anyhow::Error> {
let pools: HashMap<String, PoolQueryParams> = params
.split(PARAMS_SEPERATOR)
.map(|param| {
let pool: PoolQueryParams = serde_qs::from_str(&param)
.with_context(|| format!("Failed to parse pool query params: {0}", param))?;
Ok((pool.tx_hash.clone(), pool))
})
.collect::<Result<HashMap<_, _>>>()
.with_context(|| "Failed to parse all pool query params")?;
Ok(pools)
}
mod tests {
use super::*;
#[test]
fn test_parse_params() {
// Existing test case
let params = "address=0x5F890841f657d90E081bAbdB532A05996Af79Fe6&tx_hash=0xb71a66c1d93c525a2dd19a8db0da19e65be04f36e733af7f03e3c9dff41aa16a&tokens[]=0x6b175474e89094c44da98b954eedeac495271d0f&tokens[]=0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48&tokens[]=0xdac17f958d2ee523a2206206994597c13d831ec7&attribute_keys[]=key1&attribute_vals[]=val1".to_string();
let expected_result = {
let mut map = HashMap::new();
map.insert(
"0xb71a66c1d93c525a2dd19a8db0da19e65be04f36e733af7f03e3c9dff41aa16a".to_string(),
PoolQueryParams {
address: "0x5F890841f657d90E081bAbdB532A05996Af79Fe6".to_string(),
tx_hash: "0xb71a66c1d93c525a2dd19a8db0da19e65be04f36e733af7f03e3c9dff41aa16a"
.to_string(),
tokens: vec![
"0x6b175474e89094c44da98b954eedeac495271d0f".to_string(),
"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48".to_string(),
"0xdac17f958d2ee523a2206206994597c13d831ec7".to_string(),
],
attribute_keys: vec!["key1".to_string()],
attribute_vals: vec!["val1".to_string()],
},
);
map
};
assert_eq!(parse_params(&params).unwrap(), expected_result);
}
}

View File

@@ -19,15 +19,16 @@ binaries:
modules:
- name: map_components
kind: map
initialBlock: 18838383
initialBlock: 11942410
inputs:
- params: string
- source: sf.ethereum.type.v2.Block
output:
type: proto:tycho.evm.v1.BlockTransactionProtocolComponents
- name: store_components
kind: store
initialBlock: 18838383
initialBlock: 11942410
updatePolicy: add
valueType: int64
inputs:
@@ -35,7 +36,7 @@ modules:
- name: store_component_tokens
kind: store
initialBlock: 18838383
initialBlock: 11942410
updatePolicy: set
valueType: string
inputs:
@@ -43,7 +44,7 @@ modules:
- name: map_relative_balances
kind: map
initialBlock: 18838383 # An arbitrary block that should change based on your requirements
initialBlock: 11942410 # An arbitrary block that should change based on your requirements
inputs:
- source: sf.ethereum.type.v2.Block
- store: store_components
@@ -53,7 +54,7 @@ modules:
- name: store_balances
kind: store
initialBlock: 18838383
initialBlock: 11942410
updatePolicy: add
valueType: bigint
inputs:
@@ -61,7 +62,7 @@ modules:
- name: map_protocol_changes
kind: map
initialBlock: 18838383
initialBlock: 11942410
inputs:
- source: sf.ethereum.type.v2.Block
- map: map_components