chore: clean up ambient (#136)
* fix: remove unnecessary tx field in ProtocolComponent * chore: move ambient protobuf files to ambient module * chore: remove dependency on common message types This allows us to isolate the ambient specific messages within the ambient module * feat: update ambient substream with new message structs * chore: update substream configs And remove use of deprecated BlockContractChanges. * feat: implement From for AmbientProtocolComponent to ProtocolComponent
This commit is contained in:
1
buf.yaml
1
buf.yaml
@@ -3,7 +3,6 @@ modules:
|
|||||||
- path: proto
|
- path: proto
|
||||||
excludes:
|
excludes:
|
||||||
- proto/sf
|
- proto/sf
|
||||||
- path: substreams/ethereum-ambient/proto
|
|
||||||
lint:
|
lint:
|
||||||
use:
|
use:
|
||||||
- BASIC
|
- BASIC
|
||||||
|
|||||||
@@ -90,8 +90,6 @@ message ProtocolComponent {
|
|||||||
ChangeType change = 5;
|
ChangeType change = 5;
|
||||||
/// Represents the functionality of the component.
|
/// Represents the functionality of the component.
|
||||||
ProtocolType protocol_type = 6;
|
ProtocolType protocol_type = 6;
|
||||||
// Transaction where this component was created
|
|
||||||
Transaction tx = 7;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// A struct for following the changes of Total Value Locked (TVL) of a protocol component.
|
// A struct for following the changes of Total Value Locked (TVL) of a protocol component.
|
||||||
|
|||||||
20
substreams/Cargo.lock
generated
20
substreams/Cargo.lock
generated
@@ -1,6 +1,6 @@
|
|||||||
# This file is automatically @generated by Cargo.
|
# This file is automatically @generated by Cargo.
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
version = 4
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aho-corasick"
|
name = "aho-corasick"
|
||||||
@@ -1141,7 +1141,7 @@ dependencies = [
|
|||||||
"substreams",
|
"substreams",
|
||||||
"substreams-ethereum",
|
"substreams-ethereum",
|
||||||
"tiny-keccak",
|
"tiny-keccak",
|
||||||
"tycho-substreams 0.2.0 (git+https://github.com/propeller-heads/tycho-protocol-sdk.git?rev=b8aeaa3)",
|
"tycho-substreams 0.2.0 (git+https://github.com/propeller-heads/tycho-protocol-sdk.git?rev=f90c33b)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1369,6 +1369,22 @@ dependencies = [
|
|||||||
"substreams-ethereum",
|
"substreams-ethereum",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tycho-substreams"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "git+https://github.com/propeller-heads/tycho-protocol-sdk.git?rev=f90c33b#f90c33bcc229a1bca1fe86ee6fc4024cbdc25aeb"
|
||||||
|
dependencies = [
|
||||||
|
"ethabi 18.0.0",
|
||||||
|
"hex",
|
||||||
|
"itertools 0.12.1",
|
||||||
|
"num-bigint",
|
||||||
|
"prost 0.11.9",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"substreams",
|
||||||
|
"substreams-ethereum",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "typenum"
|
name = "typenum"
|
||||||
version = "1.17.0"
|
version = "1.17.0"
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use std::collections::{HashMap, HashSet};
|
|||||||
use substreams_ethereum::pb::eth::v2::{self as sf, StorageChange};
|
use substreams_ethereum::pb::eth::v2::{self as sf, StorageChange};
|
||||||
|
|
||||||
// re-export the protobuf types here.
|
// re-export the protobuf types here.
|
||||||
pub use crate::pb::tycho::{ambient::v1::*, evm::v1::*};
|
pub use crate::pb::tycho::evm::v1::*;
|
||||||
|
|
||||||
impl TransactionContractChanges {
|
impl TransactionContractChanges {
|
||||||
/// Creates a new empty `TransactionContractChanges` instance.
|
/// Creates a new empty `TransactionContractChanges` instance.
|
||||||
@@ -213,7 +213,7 @@ impl ProtocolComponent {
|
|||||||
/// ## Parameters
|
/// ## Parameters
|
||||||
/// - `id`: Identifier for the component.
|
/// - `id`: Identifier for the component.
|
||||||
/// - `tx`: Reference to the associated transaction.
|
/// - `tx`: Reference to the associated transaction.
|
||||||
pub fn new(id: &str, tx: &Transaction) -> Self {
|
pub fn new(id: &str) -> Self {
|
||||||
Self {
|
Self {
|
||||||
id: id.to_string(),
|
id: id.to_string(),
|
||||||
tokens: Vec::new(),
|
tokens: Vec::new(),
|
||||||
@@ -221,7 +221,6 @@ impl ProtocolComponent {
|
|||||||
static_att: Vec::new(),
|
static_att: Vec::new(),
|
||||||
change: ChangeType::Creation.into(),
|
change: ChangeType::Creation.into(),
|
||||||
protocol_type: None,
|
protocol_type: None,
|
||||||
tx: Some(tx.clone()),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -233,7 +232,7 @@ impl ProtocolComponent {
|
|||||||
/// ## Parameters
|
/// ## Parameters
|
||||||
/// - `id`: Contract address to be encoded and set as the component's ID.
|
/// - `id`: Contract address to be encoded and set as the component's ID.
|
||||||
/// - `tx`: Reference to the associated transaction.
|
/// - `tx`: Reference to the associated transaction.
|
||||||
pub fn at_contract(id: &[u8], tx: &Transaction) -> Self {
|
pub fn at_contract(id: &[u8]) -> Self {
|
||||||
Self {
|
Self {
|
||||||
id: format!("0x{}", hex::encode(id)),
|
id: format!("0x{}", hex::encode(id)),
|
||||||
tokens: Vec::new(),
|
tokens: Vec::new(),
|
||||||
@@ -241,7 +240,6 @@ impl ProtocolComponent {
|
|||||||
static_att: Vec::new(),
|
static_att: Vec::new(),
|
||||||
change: ChangeType::Creation.into(),
|
change: ChangeType::Creation.into(),
|
||||||
protocol_type: None,
|
protocol_type: None,
|
||||||
tx: Some(tx.clone()),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,5 @@
|
|||||||
// @generated
|
// @generated
|
||||||
pub mod tycho {
|
pub mod tycho {
|
||||||
pub mod ambient {
|
|
||||||
// @@protoc_insertion_point(attribute:tycho.ambient.v1)
|
|
||||||
pub mod v1 {
|
|
||||||
include!("tycho.ambient.v1.rs");
|
|
||||||
// @@protoc_insertion_point(tycho.ambient.v1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub mod evm {
|
pub mod evm {
|
||||||
// @@protoc_insertion_point(attribute:tycho.evm.v1)
|
// @@protoc_insertion_point(attribute:tycho.evm.v1)
|
||||||
pub mod v1 {
|
pub mod v1 {
|
||||||
|
|||||||
@@ -95,9 +95,6 @@ pub struct ProtocolComponent {
|
|||||||
/// / Represents the functionality of the component.
|
/// / Represents the functionality of the component.
|
||||||
#[prost(message, optional, tag="6")]
|
#[prost(message, optional, tag="6")]
|
||||||
pub protocol_type: ::core::option::Option<ProtocolType>,
|
pub protocol_type: ::core::option::Option<ProtocolType>,
|
||||||
/// Transaction where this component was created
|
|
||||||
#[prost(message, optional, tag = "7")]
|
|
||||||
pub tx: ::core::option::Option<Transaction>,
|
|
||||||
}
|
}
|
||||||
/// A struct for following the changes of Total Value Locked (TVL) of a protocol component.
|
/// A struct for following the changes of Total Value Locked (TVL) of a protocol component.
|
||||||
/// Note that if a ProtocolComponent contains multiple contracts, the TVL is tracked for the component as a whole.
|
/// Note that if a ProtocolComponent contains multiple contracts, the TVL is tracked for the component as a whole.
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ name = "substreams_ethereum_ambient"
|
|||||||
crate-type = ["cdylib"]
|
crate-type = ["cdylib"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
tycho-substreams = { git = "https://github.com/propeller-heads/tycho-protocol-sdk.git", rev = "b8aeaa3" }
|
tycho-substreams = { git = "https://github.com/propeller-heads/tycho-protocol-sdk.git", rev = "f90c33b" }
|
||||||
substreams = "0.5.22"
|
substreams = "0.5.22"
|
||||||
substreams-ethereum = "0.9.9"
|
substreams-ethereum = "0.9.9"
|
||||||
prost = "0.11"
|
prost = "0.11"
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ Modules Description
|
|||||||
* **Type**: Map
|
* **Type**: Map
|
||||||
* **Purpose**: This module detects new pools within the Ethereum blockchain and balance changes.
|
* **Purpose**: This module detects new pools within the Ethereum blockchain and balance changes.
|
||||||
* **Inputs**: Ethereum block data (`sf.ethereum.type.v2.Block`).
|
* **Inputs**: Ethereum block data (`sf.ethereum.type.v2.Block`).
|
||||||
* **Output**: Emits data of type `proto:tycho.evm.state.v1.BlockPoolChanges`.
|
* **Output**: Emits data of type `proto:tycho.ambient.v1.BlockPoolChanges`.
|
||||||
|
|
||||||
### `store_pools_balances`
|
### `store_pools_balances`
|
||||||
|
|
||||||
@@ -26,10 +26,10 @@ Modules Description
|
|||||||
### `map_changes`
|
### `map_changes`
|
||||||
|
|
||||||
* **Type**: Map
|
* **Type**: Map
|
||||||
* **Purpose**: This module integrates all the processed information to generate comprehensive `BlockContractChanges`. It considers new pools, balance changes and contract changes.
|
* **Purpose**: This module integrates all the processed information to generate comprehensive `BlockChanges`. It considers new pools, balance changes and contract changes.
|
||||||
* **Inputs**:
|
* **Inputs**:
|
||||||
* Ethereum block data (`sf.ethereum.type.v2.Block`).
|
* Ethereum block data (`sf.ethereum.type.v2.Block`).
|
||||||
* Data from `map_pool_changes`.
|
* Data from `map_pool_changes`.
|
||||||
* Data from `store_pools_balances`.
|
* Data from `store_pools_balances`.
|
||||||
* Data from `store_pools`.
|
* Data from `store_pools`.
|
||||||
* **Output**: Emits `proto:tycho.evm.state.v1.BlockContractChanges`.
|
* **Output**: Emits `proto:tycho.evm.state.v1.BlockChanges`.
|
||||||
|
|||||||
@@ -2,8 +2,6 @@ syntax = "proto3";
|
|||||||
|
|
||||||
package tycho.ambient.v1;
|
package tycho.ambient.v1;
|
||||||
|
|
||||||
import "tycho/evm/v1/common.proto";
|
|
||||||
|
|
||||||
// A change to a pool's balance. Ambient specific.
|
// A change to a pool's balance. Ambient specific.
|
||||||
message AmbientBalanceDelta {
|
message AmbientBalanceDelta {
|
||||||
// The address of the ERC20 token whose balance changed.
|
// The address of the ERC20 token whose balance changed.
|
||||||
@@ -14,14 +12,25 @@ message AmbientBalanceDelta {
|
|||||||
bytes token_delta = 3;
|
bytes token_delta = 3;
|
||||||
// Used to determine the order of the balance changes. Necessary for the balance store.
|
// Used to determine the order of the balance changes. Necessary for the balance store.
|
||||||
uint64 ordinal = 4;
|
uint64 ordinal = 4;
|
||||||
// Transaction where the balance changed.
|
// Transaction index of the balance change
|
||||||
tycho.evm.v1.Transaction tx = 5;
|
uint64 tx_index = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message AmbientProtocolComponent {
|
||||||
|
// A unique identifier for the component within the protocol.
|
||||||
|
string id = 1;
|
||||||
|
// Addresses of the ERC20 tokens used by the component.
|
||||||
|
repeated bytes tokens = 2;
|
||||||
|
// Ambient pool index [static attribute for ambient pools]
|
||||||
|
bytes pool_index = 3;
|
||||||
|
// Transaction index for the component creation
|
||||||
|
uint64 tx_index = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ambient pool changes within a single block
|
// Ambient pool changes within a single block
|
||||||
message BlockPoolChanges {
|
message BlockPoolChanges {
|
||||||
// New protocol components added in this block
|
// New protocol components added in this block
|
||||||
repeated tycho.evm.v1.ProtocolComponent protocol_components = 1;
|
repeated AmbientProtocolComponent new_components = 1;
|
||||||
// Balance changes to pools in this block
|
// Balance changes on this block
|
||||||
repeated AmbientBalanceDelta balance_deltas = 2;
|
repeated AmbientBalanceDelta balance_deltas = 2;
|
||||||
}
|
}
|
||||||
@@ -1,14 +1,17 @@
|
|||||||
use anyhow::{anyhow, bail};
|
use anyhow::{anyhow, bail};
|
||||||
use tycho_substreams::models::{
|
|
||||||
Attribute, ChangeType, FinancialType, ImplementationType, ProtocolComponent, ProtocolType,
|
|
||||||
Transaction,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::utils::{decode_flows_from_output, encode_pool_hash};
|
|
||||||
use ethabi::{decode, ParamType};
|
use ethabi::{decode, ParamType};
|
||||||
use hex_literal::hex;
|
use hex_literal::hex;
|
||||||
use substreams_ethereum::pb::eth::v2::Call;
|
use substreams_ethereum::pb::eth::v2::Call;
|
||||||
|
|
||||||
|
use tycho_substreams::models::{
|
||||||
|
Attribute, ChangeType, FinancialType, ImplementationType, ProtocolComponent, ProtocolType,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
pb::tycho::ambient::v1::AmbientProtocolComponent,
|
||||||
|
utils::{decode_flows_from_output, encode_pool_hash},
|
||||||
|
};
|
||||||
|
|
||||||
pub const AMBIENT_CONTRACT: [u8; 20] = hex!("aaaaaaaaa24eeeb8d57d431224f73832bc34f688");
|
pub const AMBIENT_CONTRACT: [u8; 20] = hex!("aaaaaaaaa24eeeb8d57d431224f73832bc34f688");
|
||||||
pub const USER_CMD_FN_SIG: [u8; 4] = hex!("a15112f9");
|
pub const USER_CMD_FN_SIG: [u8; 4] = hex!("a15112f9");
|
||||||
|
|
||||||
@@ -91,10 +94,11 @@ pub fn decode_direct_swap_call(
|
|||||||
bail!("Failed to decode swap call inputs.".to_string());
|
bail!("Failed to decode swap call inputs.".to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn decode_pool_init(
|
pub fn decode_pool_init(
|
||||||
call: &Call,
|
call: &Call,
|
||||||
tx: Transaction,
|
tx_index: u64,
|
||||||
) -> Result<Option<ProtocolComponent>, anyhow::Error> {
|
) -> Result<Option<AmbientProtocolComponent>, anyhow::Error> {
|
||||||
// Decode external call to UserCmd
|
// Decode external call to UserCmd
|
||||||
if let Ok(external_params) = decode(USER_CMD_EXTERNAL_ABI, &call.input[4..]) {
|
if let Ok(external_params) = decode(USER_CMD_EXTERNAL_ABI, &call.input[4..]) {
|
||||||
let cmd_bytes = external_params[1]
|
let cmd_bytes = external_params[1]
|
||||||
@@ -134,28 +138,14 @@ pub fn decode_pool_init(
|
|||||||
let pool_index = pool_index_buf.to_vec();
|
let pool_index = pool_index_buf.to_vec();
|
||||||
let pool_hash = encode_pool_hash(base.clone(), quote.clone(), pool_index.clone());
|
let pool_hash = encode_pool_hash(base.clone(), quote.clone(), pool_index.clone());
|
||||||
|
|
||||||
let static_attribute = Attribute {
|
|
||||||
name: String::from("pool_index"),
|
|
||||||
value: pool_index,
|
|
||||||
change: ChangeType::Creation.into(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut tokens: Vec<Vec<u8>> = vec![base.clone(), quote.clone()];
|
let mut tokens: Vec<Vec<u8>> = vec![base.clone(), quote.clone()];
|
||||||
tokens.sort();
|
tokens.sort();
|
||||||
|
|
||||||
let new_component = ProtocolComponent {
|
let new_component = AmbientProtocolComponent {
|
||||||
id: hex::encode(pool_hash),
|
id: hex::encode(pool_hash),
|
||||||
tokens,
|
tokens,
|
||||||
contracts: vec![AMBIENT_CONTRACT.to_vec()],
|
pool_index,
|
||||||
static_att: vec![static_attribute],
|
tx_index,
|
||||||
change: ChangeType::Creation.into(),
|
|
||||||
protocol_type: Some(ProtocolType {
|
|
||||||
name: "ambient_pool".to_string(),
|
|
||||||
attribute_schema: vec![],
|
|
||||||
financial_type: FinancialType::Swap.into(),
|
|
||||||
implementation_type: ImplementationType::Vm.into(),
|
|
||||||
}),
|
|
||||||
tx: Some(tx.clone()),
|
|
||||||
};
|
};
|
||||||
Ok(Some(new_component))
|
Ok(Some(new_component))
|
||||||
} else {
|
} else {
|
||||||
@@ -168,3 +158,25 @@ pub fn decode_pool_init(
|
|||||||
bail!("Failed to decode ABI external call.".to_string());
|
bail!("Failed to decode ABI external call.".to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<AmbientProtocolComponent> for ProtocolComponent {
|
||||||
|
fn from(component: AmbientProtocolComponent) -> Self {
|
||||||
|
ProtocolComponent {
|
||||||
|
id: component.id,
|
||||||
|
tokens: component.tokens,
|
||||||
|
contracts: vec![AMBIENT_CONTRACT.to_vec()],
|
||||||
|
static_att: vec![Attribute {
|
||||||
|
name: "pool_index".to_string(),
|
||||||
|
value: component.pool_index,
|
||||||
|
change: ChangeType::Creation.into(),
|
||||||
|
}],
|
||||||
|
change: ChangeType::Creation.into(),
|
||||||
|
protocol_type: Some(ProtocolType {
|
||||||
|
name: "ambient_pool".to_string(),
|
||||||
|
attribute_schema: vec![],
|
||||||
|
financial_type: FinancialType::Swap.into(),
|
||||||
|
implementation_type: ImplementationType::Vm.into(),
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
mod contracts;
|
mod contracts;
|
||||||
|
mod pb;
|
||||||
|
|
||||||
pub use modules::*;
|
pub use modules::*;
|
||||||
mod modules;
|
mod modules;
|
||||||
|
|||||||
@@ -20,24 +20,17 @@ use crate::{
|
|||||||
decode_warm_path_user_cmd_call, AMBIENT_WARMPATH_CONTRACT, USER_CMD_WARMPATH_FN_SIG,
|
decode_warm_path_user_cmd_call, AMBIENT_WARMPATH_CONTRACT, USER_CMD_WARMPATH_FN_SIG,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
pb::tycho::ambient::v1::{AmbientBalanceDelta, BlockPoolChanges},
|
||||||
utils::from_u256_to_vec,
|
utils::from_u256_to_vec,
|
||||||
};
|
};
|
||||||
use tycho_substreams::{
|
|
||||||
models::{AmbientBalanceDelta, BlockPoolChanges},
|
|
||||||
prelude::Transaction,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[substreams::handlers::map]
|
#[substreams::handlers::map]
|
||||||
fn map_pool_changes(block: eth::v2::Block) -> Result<BlockPoolChanges, substreams::errors::Error> {
|
fn map_pool_changes(block: eth::v2::Block) -> Result<BlockPoolChanges, substreams::errors::Error> {
|
||||||
let mut protocol_components = Vec::new();
|
|
||||||
let mut balance_deltas = Vec::new();
|
let mut balance_deltas = Vec::new();
|
||||||
|
let mut protocol_components = Vec::new();
|
||||||
|
|
||||||
for block_tx in block.transactions() {
|
for block_tx in block.transactions() {
|
||||||
let tx = Transaction {
|
let tx_index = block_tx.index as u64;
|
||||||
hash: block_tx.hash.clone(),
|
|
||||||
from: block_tx.from.clone(),
|
|
||||||
to: block_tx.to.clone(),
|
|
||||||
index: block_tx.index as u64,
|
|
||||||
};
|
|
||||||
// extract storage changes
|
// extract storage changes
|
||||||
let mut storage_changes = block_tx
|
let mut storage_changes = block_tx
|
||||||
.calls
|
.calls
|
||||||
@@ -66,7 +59,7 @@ fn map_pool_changes(block: eth::v2::Block) -> Result<BlockPoolChanges, substream
|
|||||||
|
|
||||||
if call.address == AMBIENT_CONTRACT && selector == USER_CMD_FN_SIG {
|
if call.address == AMBIENT_CONTRACT && selector == USER_CMD_FN_SIG {
|
||||||
// Extract pool creations
|
// Extract pool creations
|
||||||
if let Some(protocol_component) = decode_pool_init(call, tx.clone())? {
|
if let Some(protocol_component) = decode_pool_init(call, tx_index)? {
|
||||||
protocol_components.push(protocol_component);
|
protocol_components.push(protocol_component);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -109,19 +102,18 @@ fn map_pool_changes(block: eth::v2::Block) -> Result<BlockPoolChanges, substream
|
|||||||
token_type: "base".to_string(),
|
token_type: "base".to_string(),
|
||||||
token_delta: from_u256_to_vec(base_flow),
|
token_delta: from_u256_to_vec(base_flow),
|
||||||
ordinal: call.index as u64,
|
ordinal: call.index as u64,
|
||||||
tx: Some(tx.clone()),
|
tx_index,
|
||||||
};
|
};
|
||||||
let quote_balance_delta = AmbientBalanceDelta {
|
let quote_balance_delta = AmbientBalanceDelta {
|
||||||
pool_hash: Vec::from(pool_hash),
|
pool_hash: Vec::from(pool_hash),
|
||||||
token_type: "quote".to_string(),
|
token_type: "quote".to_string(),
|
||||||
token_delta: from_u256_to_vec(quote_flow),
|
token_delta: from_u256_to_vec(quote_flow),
|
||||||
ordinal: call.index as u64,
|
ordinal: call.index as u64,
|
||||||
tx: Some(tx.clone()),
|
tx_index,
|
||||||
};
|
};
|
||||||
balance_deltas.extend([base_balance_delta.clone(), quote_balance_delta.clone()]);
|
balance_deltas.extend([base_balance_delta.clone(), quote_balance_delta.clone()]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
balance_deltas.sort_by_key(|delta| (delta.ordinal, delta.token_type.clone()));
|
balance_deltas.sort_by_key(|delta| (delta.ordinal, delta.token_type.clone()));
|
||||||
let pool_changes = BlockPoolChanges { protocol_components, balance_deltas };
|
Ok(BlockPoolChanges { balance_deltas, new_components: protocol_components })
|
||||||
Ok(pool_changes)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,12 +2,12 @@ use substreams::{
|
|||||||
scalar::BigInt,
|
scalar::BigInt,
|
||||||
store::{StoreAdd, StoreAddBigInt, StoreNew},
|
store::{StoreAdd, StoreAddBigInt, StoreNew},
|
||||||
};
|
};
|
||||||
use tycho_substreams::models::BlockPoolChanges;
|
|
||||||
|
use crate::pb::tycho::ambient::v1::BlockPoolChanges;
|
||||||
|
|
||||||
#[substreams::handlers::store]
|
#[substreams::handlers::store]
|
||||||
pub fn store_pool_balances(changes: BlockPoolChanges, balance_store: StoreAddBigInt) {
|
pub fn store_pool_balances(changes: BlockPoolChanges, balance_store: StoreAddBigInt) {
|
||||||
let deltas = changes.balance_deltas.clone();
|
for balance_delta in changes.balance_deltas {
|
||||||
for balance_delta in deltas {
|
|
||||||
let pool_hash_hex = hex::encode(&balance_delta.pool_hash);
|
let pool_hash_hex = hex::encode(&balance_delta.pool_hash);
|
||||||
balance_store.add(
|
balance_store.add(
|
||||||
balance_delta.ordinal,
|
balance_delta.ordinal,
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
use substreams::store::{StoreNew, StoreSet, StoreSetProto};
|
use substreams::store::{StoreNew, StoreSet, StoreSetProto};
|
||||||
use tycho_substreams::models::{BlockPoolChanges, ProtocolComponent};
|
use tycho_substreams::models::ProtocolComponent;
|
||||||
|
|
||||||
|
use crate::pb::tycho::ambient::v1::BlockPoolChanges;
|
||||||
|
|
||||||
#[substreams::handlers::store]
|
#[substreams::handlers::store]
|
||||||
pub fn store_pools(changes: BlockPoolChanges, component_store: StoreSetProto<ProtocolComponent>) {
|
pub fn store_pools(changes: BlockPoolChanges, component_store: StoreSetProto<ProtocolComponent>) {
|
||||||
for component in changes.protocol_components {
|
for component in changes.new_components {
|
||||||
component_store.set(0, component.id.clone(), &component);
|
let protocol_component: ProtocolComponent = component.into();
|
||||||
|
component_store.set(0, protocol_component.id.clone(), &protocol_component);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,14 +3,16 @@ use std::{
|
|||||||
collections::{hash_map::Entry, HashMap},
|
collections::{hash_map::Entry, HashMap},
|
||||||
str::FromStr,
|
str::FromStr,
|
||||||
};
|
};
|
||||||
use substreams::pb::substreams::StoreDeltas;
|
use substreams::{
|
||||||
|
pb::substreams::StoreDeltas,
|
||||||
|
store::{StoreGet, StoreGetProto},
|
||||||
|
};
|
||||||
use substreams_ethereum::pb::eth::{self};
|
use substreams_ethereum::pb::eth::{self};
|
||||||
|
|
||||||
use crate::contracts::main::AMBIENT_CONTRACT;
|
|
||||||
use substreams::store::{StoreGet, StoreGetProto};
|
|
||||||
use tycho_substreams::prelude::*;
|
use tycho_substreams::prelude::*;
|
||||||
|
|
||||||
|
use crate::{contracts::main::AMBIENT_CONTRACT, pb::tycho::ambient::v1::BlockPoolChanges};
|
||||||
|
|
||||||
struct SlotValue {
|
struct SlotValue {
|
||||||
new_value: Vec<u8>,
|
new_value: Vec<u8>,
|
||||||
start_value: Vec<u8>,
|
start_value: Vec<u8>,
|
||||||
@@ -74,10 +76,10 @@ fn map_changes(
|
|||||||
block_pool_changes: BlockPoolChanges,
|
block_pool_changes: BlockPoolChanges,
|
||||||
balance_store: StoreDeltas,
|
balance_store: StoreDeltas,
|
||||||
pool_store: StoreGetProto<ProtocolComponent>,
|
pool_store: StoreGetProto<ProtocolComponent>,
|
||||||
) -> Result<BlockContractChanges, substreams::errors::Error> {
|
) -> Result<BlockChanges, substreams::errors::Error> {
|
||||||
let mut block_changes = BlockContractChanges::default();
|
let mut block_changes = BlockChanges::default();
|
||||||
|
|
||||||
let mut tx_change = TransactionContractChanges::default();
|
let mut transaction_changes = TransactionChanges::default();
|
||||||
|
|
||||||
let mut changed_contracts: HashMap<Vec<u8>, InterimContractChange> = HashMap::new();
|
let mut changed_contracts: HashMap<Vec<u8>, InterimContractChange> = HashMap::new();
|
||||||
|
|
||||||
@@ -93,6 +95,13 @@ fn map_changes(
|
|||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
for block_tx in block.transactions() {
|
for block_tx in block.transactions() {
|
||||||
|
let tx = Transaction {
|
||||||
|
hash: block_tx.hash.clone(),
|
||||||
|
from: block_tx.from.clone(),
|
||||||
|
to: block_tx.to.clone(),
|
||||||
|
index: block_tx.index as u64,
|
||||||
|
};
|
||||||
|
|
||||||
// extract storage changes
|
// extract storage changes
|
||||||
let mut storage_changes = block_tx
|
let mut storage_changes = block_tx
|
||||||
.calls
|
.calls
|
||||||
@@ -244,44 +253,37 @@ fn map_changes(
|
|||||||
|
|
||||||
// if there were any changes, add transaction and push the changes
|
// if there were any changes, add transaction and push the changes
|
||||||
if !storage_changes.is_empty() || !balance_changes.is_empty() || !code_changes.is_empty() {
|
if !storage_changes.is_empty() || !balance_changes.is_empty() || !code_changes.is_empty() {
|
||||||
tx_change.tx = Some(Transaction {
|
transaction_changes.tx = Some(tx.clone());
|
||||||
hash: block_tx.hash.clone(),
|
|
||||||
from: block_tx.from.clone(),
|
|
||||||
to: block_tx.to.clone(),
|
|
||||||
index: block_tx.index as u64,
|
|
||||||
});
|
|
||||||
|
|
||||||
// reuse changed_contracts hash map by draining it, next iteration
|
// reuse changed_contracts hash map by draining it, next iteration
|
||||||
// will start empty. This avoids a costly reallocation
|
// will start empty. This avoids a costly reallocation
|
||||||
for (_, change) in changed_contracts.drain() {
|
for (_, change) in changed_contracts.drain() {
|
||||||
tx_change
|
transaction_changes
|
||||||
.contract_changes
|
.contract_changes
|
||||||
.push(change.into())
|
.push(change.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
block_changes
|
block_changes
|
||||||
.changes
|
.changes
|
||||||
.push(tx_change.clone());
|
.push(transaction_changes.clone());
|
||||||
|
|
||||||
// clear out the interim contract changes after we pushed those.
|
// clear out the interim contract changes after we pushed those.
|
||||||
tx_change.tx = None;
|
transaction_changes.tx = None;
|
||||||
tx_change.contract_changes.clear();
|
transaction_changes
|
||||||
|
.contract_changes
|
||||||
|
.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// extract new protocol components
|
||||||
let mut grouped_components = HashMap::new();
|
let mut grouped_components = HashMap::new();
|
||||||
for component in &block_pool_changes.protocol_components {
|
for component in &block_pool_changes.new_components {
|
||||||
let tx_hash = component
|
|
||||||
.tx
|
|
||||||
.clone()
|
|
||||||
.expect("Transaction is missing")
|
|
||||||
.hash;
|
|
||||||
grouped_components
|
grouped_components
|
||||||
.entry(tx_hash)
|
.entry(component.tx_index)
|
||||||
.or_insert_with(Vec::new)
|
.or_insert_with(Vec::new)
|
||||||
.push(component.clone());
|
.push(component.clone());
|
||||||
}
|
}
|
||||||
|
for (tx_index, components) in grouped_components {
|
||||||
for (tx_hash, components) in grouped_components {
|
|
||||||
if let Some(tx_change) = block_changes
|
if let Some(tx_change) = block_changes
|
||||||
.changes
|
.changes
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
@@ -290,14 +292,20 @@ fn map_changes(
|
|||||||
tx_change
|
tx_change
|
||||||
.tx
|
.tx
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.is_some_and(|tx| tx.hash == tx_hash)
|
.is_some_and(|tx| tx.index == tx_index)
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
|
let new_components = components
|
||||||
|
.into_iter()
|
||||||
|
.map(Into::into)
|
||||||
|
.collect::<Vec<ProtocolComponent>>();
|
||||||
tx_change
|
tx_change
|
||||||
.component_changes
|
.component_changes
|
||||||
.extend(components);
|
.extend(new_components);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// extract component balance changes
|
||||||
let mut balance_changes = HashMap::new();
|
let mut balance_changes = HashMap::new();
|
||||||
balance_store
|
balance_store
|
||||||
.deltas
|
.deltas
|
||||||
@@ -323,17 +331,12 @@ fn map_changes(
|
|||||||
token: pool.tokens[token_index].clone(),
|
token: pool.tokens[token_index].clone(),
|
||||||
balance: big_endian_bytes_balance.to_vec(),
|
balance: big_endian_bytes_balance.to_vec(),
|
||||||
};
|
};
|
||||||
let tx_hash = balance_delta
|
|
||||||
.tx
|
|
||||||
.expect("Transaction is missing")
|
|
||||||
.hash;
|
|
||||||
balance_changes
|
balance_changes
|
||||||
.entry(tx_hash)
|
.entry(balance_delta.tx_index)
|
||||||
.or_insert_with(Vec::new)
|
.or_insert_with(Vec::new)
|
||||||
.push(balance_change);
|
.push(balance_change);
|
||||||
});
|
});
|
||||||
|
for (tx_index, grouped_balance_changes) in balance_changes {
|
||||||
for (tx_hash, grouped_balance_changes) in balance_changes {
|
|
||||||
if let Some(tx_change) = block_changes
|
if let Some(tx_change) = block_changes
|
||||||
.changes
|
.changes
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
@@ -342,7 +345,7 @@ fn map_changes(
|
|||||||
tx_change
|
tx_change
|
||||||
.tx
|
.tx
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.is_some_and(|tx| tx.hash == tx_hash)
|
.is_some_and(|tx| tx.index == tx_index)
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
tx_change
|
tx_change
|
||||||
|
|||||||
10
substreams/ethereum-ambient/src/pb/mod.rs
Normal file
10
substreams/ethereum-ambient/src/pb/mod.rs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
// @generated
|
||||||
|
pub mod tycho {
|
||||||
|
pub mod ambient {
|
||||||
|
// @@protoc_insertion_point(attribute:tycho.ambient.v1)
|
||||||
|
pub mod v1 {
|
||||||
|
include!("tycho.ambient.v1.rs");
|
||||||
|
// @@protoc_insertion_point(tycho.ambient.v1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,9 +15,25 @@ pub struct AmbientBalanceDelta {
|
|||||||
/// Used to determine the order of the balance changes. Necessary for the balance store.
|
/// Used to determine the order of the balance changes. Necessary for the balance store.
|
||||||
#[prost(uint64, tag="4")]
|
#[prost(uint64, tag="4")]
|
||||||
pub ordinal: u64,
|
pub ordinal: u64,
|
||||||
/// Transaction where the balance changed.
|
/// Transaction index of the balance change
|
||||||
#[prost(message, optional, tag="5")]
|
#[prost(uint64, tag="5")]
|
||||||
pub tx: ::core::option::Option<super::super::evm::v1::Transaction>,
|
pub tx_index: u64,
|
||||||
|
}
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||||
|
pub struct AmbientProtocolComponent {
|
||||||
|
/// A unique identifier for the component within the protocol.
|
||||||
|
#[prost(string, tag="1")]
|
||||||
|
pub id: ::prost::alloc::string::String,
|
||||||
|
/// Addresses of the ERC20 tokens used by the component.
|
||||||
|
#[prost(bytes="vec", repeated, tag="2")]
|
||||||
|
pub tokens: ::prost::alloc::vec::Vec<::prost::alloc::vec::Vec<u8>>,
|
||||||
|
/// Ambient pool index [static attribute for ambient pools]
|
||||||
|
#[prost(bytes="vec", tag="3")]
|
||||||
|
pub pool_index: ::prost::alloc::vec::Vec<u8>,
|
||||||
|
/// Transaction index for the component creation
|
||||||
|
#[prost(uint64, tag="4")]
|
||||||
|
pub tx_index: u64,
|
||||||
}
|
}
|
||||||
/// Ambient pool changes within a single block
|
/// Ambient pool changes within a single block
|
||||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
@@ -25,8 +41,8 @@ pub struct AmbientBalanceDelta {
|
|||||||
pub struct BlockPoolChanges {
|
pub struct BlockPoolChanges {
|
||||||
/// New protocol components added in this block
|
/// New protocol components added in this block
|
||||||
#[prost(message, repeated, tag="1")]
|
#[prost(message, repeated, tag="1")]
|
||||||
pub protocol_components: ::prost::alloc::vec::Vec<super::super::evm::v1::ProtocolComponent>,
|
pub new_components: ::prost::alloc::vec::Vec<AmbientProtocolComponent>,
|
||||||
/// Balance changes to pools in this block
|
/// Balance changes on this block
|
||||||
#[prost(message, repeated, tag="2")]
|
#[prost(message, repeated, tag="2")]
|
||||||
pub balance_deltas: ::prost::alloc::vec::Vec<AmbientBalanceDelta>,
|
pub balance_deltas: ::prost::alloc::vec::Vec<AmbientBalanceDelta>,
|
||||||
}
|
}
|
||||||
@@ -1,21 +1,20 @@
|
|||||||
specVersion: v0.1.0
|
specVersion: v0.1.0
|
||||||
package:
|
package:
|
||||||
name: "substreams_ethereum_ambient"
|
name: "substreams_ethereum_ambient"
|
||||||
version: v0.5.1
|
version: v0.6.0
|
||||||
|
|
||||||
protobuf:
|
protobuf:
|
||||||
files:
|
files:
|
||||||
- tycho/evm/v1/common.proto
|
- tycho/evm/v1/common.proto
|
||||||
- tycho/evm/v1/vm.proto
|
|
||||||
- ambient.proto
|
- ambient.proto
|
||||||
importPaths:
|
importPaths:
|
||||||
- ./proto/v1
|
- ./proto
|
||||||
- ../../proto/
|
- ../../proto
|
||||||
|
|
||||||
binaries:
|
binaries:
|
||||||
default:
|
default:
|
||||||
type: wasm/rust-v1
|
type: wasm/rust-v1
|
||||||
file: ../../target/wasm32-unknown-unknown/substreams/substreams_ethereum_ambient.wasm
|
file: ../target/wasm32-unknown-unknown/release/substreams_ethereum_ambient.wasm
|
||||||
|
|
||||||
modules:
|
modules:
|
||||||
- name: map_pool_changes
|
- name: map_pool_changes
|
||||||
@@ -24,7 +23,7 @@ modules:
|
|||||||
inputs:
|
inputs:
|
||||||
- source: sf.ethereum.type.v2.Block
|
- source: sf.ethereum.type.v2.Block
|
||||||
output:
|
output:
|
||||||
type: proto:tycho.evm.v1.BlockPoolChanges
|
type: proto:tycho.ambient.v1.BlockPoolChanges
|
||||||
- name: store_pools
|
- name: store_pools
|
||||||
kind: store
|
kind: store
|
||||||
initialBlock: 17361664
|
initialBlock: 17361664
|
||||||
@@ -49,4 +48,4 @@ modules:
|
|||||||
mode: deltas
|
mode: deltas
|
||||||
- store: store_pools
|
- store: store_pools
|
||||||
output:
|
output:
|
||||||
type: proto:tycho.evm.v1.BlockContractChanges
|
type: proto:tycho.evm.v1.BlockChanges
|
||||||
|
|||||||
Reference in New Issue
Block a user