From 73d48236ba698c984701bc24798d6bbfbe7c4237 Mon Sep 17 00:00:00 2001
From: zizou <111426680+flopell@users.noreply.github.com>
Date: Fri, 11 Oct 2024 12:57:34 +0200
Subject: [PATCH 1/8] feat(substreams): add substreams for Uniswap v2 and v3
---
substreams/Cargo.lock | 96 +
substreams/Cargo.toml | 12 +-
.../crates/substreams-helper/.gitignore | 1 +
.../crates/substreams-helper/Cargo.toml | 29 +
substreams/crates/substreams-helper/Makefile | 7 +
.../substreams-helper/rust-toolchain.toml | 4 +
.../crates/substreams-helper/src/common.rs | 69 +
.../substreams-helper/src/event_handler.rs | 103 +
.../crates/substreams-helper/src/hex.rs | 20 +
.../crates/substreams-helper/src/lib.rs | 5 +
.../substreams-helper/src/storage_change.rs | 14 +
substreams/ethereum-uniswap-v2/Cargo.toml | 28 +
substreams/ethereum-uniswap-v2/Makefile | 2 +
.../ethereum-uniswap-v2/abi/Factory.json | 125 +
substreams/ethereum-uniswap-v2/abi/Pool.json | 713 +++
.../arbitrum-uniswap-v2.yaml | 49 +
substreams/ethereum-uniswap-v2/build.rs | 12 +
.../ethereum-pancakeswap.yaml | 49 +
.../ethereum-sushiswap.yaml | 49 +
.../ethereum-uniswap-v2.yaml | 49 +
.../proto/v1/uniswap.proto | 61 +
.../ethereum-uniswap-v2/src/abi/factory.rs | 904 +++
substreams/ethereum-uniswap-v2/src/abi/mod.rs | 4 +
.../ethereum-uniswap-v2/src/abi/pool.rs | 3554 ++++++++++++
substreams/ethereum-uniswap-v2/src/lib.rs | 10 +
.../src/modules/1_map_pool_created.rs | 99 +
.../src/modules/2_store_pools.rs | 25 +
.../src/modules/3_map_pool_events.rs | 232 +
.../ethereum-uniswap-v2/src/modules/mod.rs | 11 +
substreams/ethereum-uniswap-v2/src/pb/mod.rs | 17 +
.../src/pb/tycho.evm.uniswap.v2.rs | 99 +
.../src/pb/tycho.evm.v1.rs | 307 +
.../ethereum-uniswap-v2/src/store_key.rs | 16 +
substreams/ethereum-uniswap-v2/src/traits.rs | 51 +
substreams/ethereum-uniswap-v3/Cargo.toml | 28 +
substreams/ethereum-uniswap-v3/Makefile | 2 +
.../ethereum-uniswap-v3/abi/Factory.json | 198 +
substreams/ethereum-uniswap-v3/abi/Pool.json | 988 ++++
.../arbitrum-uniswap-v3.yaml | 67 +
substreams/ethereum-uniswap-v3/build.rs | 12 +
.../ethereum-uniswap-v3.yaml | 67 +
.../proto/v1/uniswap.proto | 29 +
.../ethereum-uniswap-v3/src/abi/factory.rs | 1040 ++++
substreams/ethereum-uniswap-v3/src/abi/mod.rs | 4 +
.../ethereum-uniswap-v3/src/abi/pool.rs | 5153 +++++++++++++++++
.../ethereum-uniswap-v3/src/events/burn.rs | 45 +
.../ethereum-uniswap-v3/src/events/collect.rs | 58 +
.../src/events/collect_fee_protocol.rs | 50 +
.../ethereum-uniswap-v3/src/events/flash.rs | 50 +
.../src/events/initialize.rs | 34 +
.../ethereum-uniswap-v3/src/events/mint.rs | 58 +
.../ethereum-uniswap-v3/src/events/mod.rs | 150 +
.../src/events/set_fee_protocol.rs | 34 +
.../ethereum-uniswap-v3/src/events/swap.rs | 50 +
substreams/ethereum-uniswap-v3/src/lib.rs | 11 +
.../src/modules/1_map_pool_created.rs | 103 +
.../src/modules/2_store_pools.rs | 23 +
.../src/modules/3_map_balance_changes.rs | 40 +
.../src/modules/4_store_pools_balances.rs | 28 +
.../src/modules/5_map_pool_events.rs | 235 +
.../ethereum-uniswap-v3/src/modules/mod.rs | 18 +
substreams/ethereum-uniswap-v3/src/pb/mod.rs | 17 +
.../src/pb/tycho.evm.v1.rs | 307 +
.../src/pb/uniswap.types.v1.rs | 541 ++
.../ethereum-uniswap-v3/src/pb/uniswap.v3.rs | 41 +
.../src/storage/constants.rs | 60 +
.../ethereum-uniswap-v3/src/storage/mod.rs | 4 +
.../src/storage/pool_storage.rs | 132 +
.../ethereum-uniswap-v3/src/storage/utils.rs | 165 +
substreams/ethereum-uniswap-v3/src/traits.rs | 30 +
70 files changed, 16697 insertions(+), 1 deletion(-)
create mode 100644 substreams/crates/substreams-helper/.gitignore
create mode 100644 substreams/crates/substreams-helper/Cargo.toml
create mode 100644 substreams/crates/substreams-helper/Makefile
create mode 100644 substreams/crates/substreams-helper/rust-toolchain.toml
create mode 100644 substreams/crates/substreams-helper/src/common.rs
create mode 100644 substreams/crates/substreams-helper/src/event_handler.rs
create mode 100644 substreams/crates/substreams-helper/src/hex.rs
create mode 100644 substreams/crates/substreams-helper/src/lib.rs
create mode 100644 substreams/crates/substreams-helper/src/storage_change.rs
create mode 100644 substreams/ethereum-uniswap-v2/Cargo.toml
create mode 100644 substreams/ethereum-uniswap-v2/Makefile
create mode 100644 substreams/ethereum-uniswap-v2/abi/Factory.json
create mode 100644 substreams/ethereum-uniswap-v2/abi/Pool.json
create mode 100644 substreams/ethereum-uniswap-v2/arbitrum-uniswap-v2.yaml
create mode 100644 substreams/ethereum-uniswap-v2/build.rs
create mode 100644 substreams/ethereum-uniswap-v2/ethereum-pancakeswap.yaml
create mode 100644 substreams/ethereum-uniswap-v2/ethereum-sushiswap.yaml
create mode 100644 substreams/ethereum-uniswap-v2/ethereum-uniswap-v2.yaml
create mode 100644 substreams/ethereum-uniswap-v2/proto/v1/uniswap.proto
create mode 100644 substreams/ethereum-uniswap-v2/src/abi/factory.rs
create mode 100644 substreams/ethereum-uniswap-v2/src/abi/mod.rs
create mode 100644 substreams/ethereum-uniswap-v2/src/abi/pool.rs
create mode 100644 substreams/ethereum-uniswap-v2/src/lib.rs
create mode 100644 substreams/ethereum-uniswap-v2/src/modules/1_map_pool_created.rs
create mode 100644 substreams/ethereum-uniswap-v2/src/modules/2_store_pools.rs
create mode 100644 substreams/ethereum-uniswap-v2/src/modules/3_map_pool_events.rs
create mode 100644 substreams/ethereum-uniswap-v2/src/modules/mod.rs
create mode 100644 substreams/ethereum-uniswap-v2/src/pb/mod.rs
create mode 100644 substreams/ethereum-uniswap-v2/src/pb/tycho.evm.uniswap.v2.rs
create mode 100644 substreams/ethereum-uniswap-v2/src/pb/tycho.evm.v1.rs
create mode 100644 substreams/ethereum-uniswap-v2/src/store_key.rs
create mode 100644 substreams/ethereum-uniswap-v2/src/traits.rs
create mode 100644 substreams/ethereum-uniswap-v3/Cargo.toml
create mode 100644 substreams/ethereum-uniswap-v3/Makefile
create mode 100644 substreams/ethereum-uniswap-v3/abi/Factory.json
create mode 100644 substreams/ethereum-uniswap-v3/abi/Pool.json
create mode 100644 substreams/ethereum-uniswap-v3/arbitrum-uniswap-v3.yaml
create mode 100644 substreams/ethereum-uniswap-v3/build.rs
create mode 100644 substreams/ethereum-uniswap-v3/ethereum-uniswap-v3.yaml
create mode 100644 substreams/ethereum-uniswap-v3/proto/v1/uniswap.proto
create mode 100644 substreams/ethereum-uniswap-v3/src/abi/factory.rs
create mode 100644 substreams/ethereum-uniswap-v3/src/abi/mod.rs
create mode 100644 substreams/ethereum-uniswap-v3/src/abi/pool.rs
create mode 100644 substreams/ethereum-uniswap-v3/src/events/burn.rs
create mode 100644 substreams/ethereum-uniswap-v3/src/events/collect.rs
create mode 100644 substreams/ethereum-uniswap-v3/src/events/collect_fee_protocol.rs
create mode 100644 substreams/ethereum-uniswap-v3/src/events/flash.rs
create mode 100644 substreams/ethereum-uniswap-v3/src/events/initialize.rs
create mode 100644 substreams/ethereum-uniswap-v3/src/events/mint.rs
create mode 100644 substreams/ethereum-uniswap-v3/src/events/mod.rs
create mode 100644 substreams/ethereum-uniswap-v3/src/events/set_fee_protocol.rs
create mode 100644 substreams/ethereum-uniswap-v3/src/events/swap.rs
create mode 100644 substreams/ethereum-uniswap-v3/src/lib.rs
create mode 100644 substreams/ethereum-uniswap-v3/src/modules/1_map_pool_created.rs
create mode 100644 substreams/ethereum-uniswap-v3/src/modules/2_store_pools.rs
create mode 100644 substreams/ethereum-uniswap-v3/src/modules/3_map_balance_changes.rs
create mode 100644 substreams/ethereum-uniswap-v3/src/modules/4_store_pools_balances.rs
create mode 100644 substreams/ethereum-uniswap-v3/src/modules/5_map_pool_events.rs
create mode 100644 substreams/ethereum-uniswap-v3/src/modules/mod.rs
create mode 100644 substreams/ethereum-uniswap-v3/src/pb/mod.rs
create mode 100644 substreams/ethereum-uniswap-v3/src/pb/tycho.evm.v1.rs
create mode 100644 substreams/ethereum-uniswap-v3/src/pb/uniswap.types.v1.rs
create mode 100644 substreams/ethereum-uniswap-v3/src/pb/uniswap.v3.rs
create mode 100644 substreams/ethereum-uniswap-v3/src/storage/constants.rs
create mode 100644 substreams/ethereum-uniswap-v3/src/storage/mod.rs
create mode 100644 substreams/ethereum-uniswap-v3/src/storage/pool_storage.rs
create mode 100644 substreams/ethereum-uniswap-v3/src/storage/utils.rs
create mode 100644 substreams/ethereum-uniswap-v3/src/traits.rs
diff --git a/substreams/Cargo.lock b/substreams/Cargo.lock
index c3164d5..0654435 100644
--- a/substreams/Cargo.lock
+++ b/substreams/Cargo.lock
@@ -29,6 +29,12 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
+[[package]]
+name = "base64"
+version = "0.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
+
[[package]]
name = "bigdecimal"
version = "0.3.1"
@@ -126,6 +132,12 @@ dependencies = [
"crypto-common",
]
+[[package]]
+name = "downcast-rs"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2"
+
[[package]]
name = "either"
version = "1.10.0"
@@ -934,6 +946,18 @@ dependencies = [
"thiserror",
]
+[[package]]
+name = "substreams-entity-change"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2c7fca123abff659d15ed30da5b605fa954a29e912c94260c488d0d18f9107d"
+dependencies = [
+ "base64",
+ "prost 0.11.9",
+ "prost-types 0.11.9",
+ "substreams",
+]
+
[[package]]
name = "substreams-ethereum"
version = "0.9.9"
@@ -965,6 +989,20 @@ dependencies = [
"syn 1.0.109",
]
+[[package]]
+name = "substreams-ethereum-ambient"
+version = "0.3.0"
+dependencies = [
+ "anyhow",
+ "bytes",
+ "ethabi 18.0.0",
+ "hex",
+ "hex-literal 0.4.1",
+ "prost 0.11.9",
+ "substreams",
+ "substreams-ethereum",
+]
+
[[package]]
name = "substreams-ethereum-core"
version = "0.9.9"
@@ -997,6 +1035,64 @@ dependencies = [
"syn 1.0.109",
]
+[[package]]
+name = "substreams-ethereum-uniswap-v2"
+version = "0.2.0"
+dependencies = [
+ "anyhow",
+ "ethabi 18.0.0",
+ "getrandom",
+ "hex-literal 0.4.1",
+ "itertools 0.12.1",
+ "num-bigint",
+ "prost 0.11.9",
+ "serde",
+ "serde_qs",
+ "substreams",
+ "substreams-ethereum",
+ "substreams-helper",
+]
+
+[[package]]
+name = "substreams-ethereum-uniswap-v3"
+version = "0.2.0"
+dependencies = [
+ "anyhow",
+ "ethabi 18.0.0",
+ "getrandom",
+ "hex",
+ "hex-literal 0.4.1",
+ "num-bigint",
+ "prost 0.11.9",
+ "substreams",
+ "substreams-entity-change",
+ "substreams-ethereum",
+ "substreams-helper",
+ "tiny-keccak",
+]
+
+[[package]]
+name = "substreams-helper"
+version = "0.0.2"
+dependencies = [
+ "anyhow",
+ "base64",
+ "bigdecimal",
+ "downcast-rs",
+ "ethabi 18.0.0",
+ "hex",
+ "hex-literal 0.4.1",
+ "num-bigint",
+ "pad",
+ "prost 0.11.9",
+ "prost-types 0.12.3",
+ "substreams",
+ "substreams-entity-change",
+ "substreams-ethereum",
+ "thiserror",
+ "tiny-keccak",
+]
+
[[package]]
name = "substreams-macro"
version = "0.5.13"
diff --git a/substreams/Cargo.toml b/substreams/Cargo.toml
index 904aedb..720b54e 100644
--- a/substreams/Cargo.toml
+++ b/substreams/Cargo.toml
@@ -1,5 +1,13 @@
[workspace]
-members = ["ethereum-balancer", "ethereum-curve", "crates/tycho-substreams"]
+members = [
+ "ethereum-balancer",
+ "ethereum-curve",
+ "crates/tycho-substreams",
+ "crates/substreams-helper",
+ "ethereum-ambient",
+ "ethereum-uniswap-v2",
+ "ethereum-uniswap-v3",
+]
resolver = "2"
@@ -9,9 +17,11 @@ substreams = "0.5"
prost = "0.11"
prost-types = "0.12.3"
hex-literal = "0.4.1"
+anyhow = "1.0.75"
hex = "0.4.3"
ethabi = "18.0.0"
tycho-substreams = { path = "crates/tycho-substreams" }
+substreams-helper = { path = "crates/substreams-helper" }
serde = "1.0.204"
serde_json = "1.0.120"
diff --git a/substreams/crates/substreams-helper/.gitignore b/substreams/crates/substreams-helper/.gitignore
new file mode 100644
index 0000000..03314f7
--- /dev/null
+++ b/substreams/crates/substreams-helper/.gitignore
@@ -0,0 +1 @@
+Cargo.lock
diff --git a/substreams/crates/substreams-helper/Cargo.toml b/substreams/crates/substreams-helper/Cargo.toml
new file mode 100644
index 0000000..41624d6
--- /dev/null
+++ b/substreams/crates/substreams-helper/Cargo.toml
@@ -0,0 +1,29 @@
+[package]
+name = "substreams-helper"
+description = "Substreams Helper Crate - by Messari"
+version = "0.0.2"
+edition = "2021"
+license = "MIT"
+homepage = "https://messari.io/"
+repository = "https://github.com/messari/substreams/substreams-helper"
+
+[dependencies]
+ethabi.workspace = true
+hex.workspace = true
+hex-literal.workspace = true
+prost.workspace = true
+prost-types.workspace = true
+num-bigint = "0.4"
+bigdecimal = "0.3"
+pad = "0.1"
+tiny-keccak = { version = "2.0", features = ["keccak"] }
+substreams = { workspace = true }
+substreams-ethereum = { workspace = true }
+thiserror = "1.0.37"
+downcast-rs = "1.2.0"
+substreams-entity-change = "1.1.0"
+base64 = "0.13.0"
+
+
+[build-dependencies]
+anyhow.workspace = true
diff --git a/substreams/crates/substreams-helper/Makefile b/substreams/crates/substreams-helper/Makefile
new file mode 100644
index 0000000..f991fe2
--- /dev/null
+++ b/substreams/crates/substreams-helper/Makefile
@@ -0,0 +1,7 @@
+.PHONY: build
+build:
+ cargo build --target wasm32-unknown-unknown --release
+
+.PHONY: publish
+publish:
+ cargo publish --target wasm32-unknown-unknown
diff --git a/substreams/crates/substreams-helper/rust-toolchain.toml b/substreams/crates/substreams-helper/rust-toolchain.toml
new file mode 100644
index 0000000..98d17b4
--- /dev/null
+++ b/substreams/crates/substreams-helper/rust-toolchain.toml
@@ -0,0 +1,4 @@
+[toolchain]
+channel = "1.75.0"
+components = [ "rustfmt" ]
+targets = [ "wasm32-unknown-unknown" ]
diff --git a/substreams/crates/substreams-helper/src/common.rs b/substreams/crates/substreams-helper/src/common.rs
new file mode 100644
index 0000000..cdc12d8
--- /dev/null
+++ b/substreams/crates/substreams-helper/src/common.rs
@@ -0,0 +1,69 @@
+use ethabi::ethereum_types::Address;
+
+use substreams::store::{
+ StoreGet, StoreGetBigDecimal, StoreGetBigInt, StoreGetInt64, StoreGetProto, StoreGetRaw,
+ StoreGetString,
+};
+
+use crate::hex::Hexable;
+
+/// HasAddresser is a trait that a few functionalities in this crate depend on.
+/// Every time we need to filter something by address (events emmited by a set of addresses,
+/// storage changes occurring on certain contracts, etc) you'll likely need
+/// to provide a HasAddresser.
+///
+/// HasAddresser has been implemented already for all substreams::store's for convenience.
+/// So if you know a given store module contains the list of addresses you want to filter by
+/// you can pass it directly as a HasAddresser. In this case, the addresses need to be the store key
+/// hex encoded as a string including the leading 0x. The value of the store is ignored.
+pub trait HasAddresser {
+ fn has_address(&self, key: Address) -> bool;
+}
+
+impl HasAddresser for Vec
{
+ fn has_address(&self, key: Address) -> bool {
+ self.contains(&key)
+ }
+}
+
+impl HasAddresser for StoreGetString {
+ fn has_address(&self, key: Address) -> bool {
+ self.get_last(key.to_hex()).is_some()
+ }
+}
+
+impl HasAddresser for StoreGetProto {
+ fn has_address(&self, key: Address) -> bool {
+ self.get_last(key.to_hex()).is_some()
+ }
+}
+
+impl HasAddresser for StoreGetRaw {
+ fn has_address(&self, key: Address) -> bool {
+ self.get_last(key.to_hex()).is_some()
+ }
+}
+
+impl HasAddresser for StoreGetBigInt {
+ fn has_address(&self, key: Address) -> bool {
+ self.get_last(key.to_hex()).is_some()
+ }
+}
+
+impl HasAddresser for StoreGetBigDecimal {
+ fn has_address(&self, key: Address) -> bool {
+ self.get_last(key.to_hex()).is_some()
+ }
+}
+
+impl HasAddresser for StoreGetInt64 {
+ fn has_address(&self, key: Address) -> bool {
+ self.get_last(key.to_hex()).is_some()
+ }
+}
+
+impl HasAddresser for Address {
+ fn has_address(&self, key: Address) -> bool {
+ key == *self
+ }
+}
diff --git a/substreams/crates/substreams-helper/src/event_handler.rs b/substreams/crates/substreams-helper/src/event_handler.rs
new file mode 100644
index 0000000..8a91342
--- /dev/null
+++ b/substreams/crates/substreams-helper/src/event_handler.rs
@@ -0,0 +1,103 @@
+use std::collections::HashMap;
+
+use ethabi::ethereum_types::Address;
+use substreams_ethereum::{
+ pb::eth::v2::{self as eth},
+ Event,
+};
+
+use crate::common::HasAddresser;
+
+/// Utility struct to easily filter events and assign them handlers.
+///
+/// Usage:
+/// ```
+/// let eh = EventHandler::new(&block);
+/// eh.filter_by_address(store); // This is optional, if omitted it will handle all events that match the type, independently of the emitting contract.
+/// eh.on::(&mut on_transfer);
+/// eh.on::(&mut on_approval);
+/// eh.on::(&mut on_mint);
+/// eh.on::(&mut on_burn);
+/// eh.handle_events(); // this will run all handlers
+/// ```
+///
+/// You'll likely want to mutate some value from the handlers that is in the current scope.
+/// For that, make your handlers be closures, that close over the variable you want to mutate, and
+/// have the whole EventHandler block of code in its own scope (either by wrapping it in an aux
+/// function or by wrapping it in {...})
+///
+/// Like so:
+/// ```
+/// let mut balances : Vec = vec![];
+/// {
+/// let mut on_transfer = |/*...*/| {
+/// // this handler modifies `balances`
+/// balances.push(some_balance);
+/// };
+/// let eh = EventHandler::new(&block);
+/// eh.on::(&mut on_transfer);
+/// eh.handle_events();
+/// }
+///
+/// // do whatever else with `balances` here.
+/// ```
+pub struct EventHandler<'a> {
+ block: &'a eth::Block,
+ #[allow(clippy::type_complexity)]
+ handlers: HashMap<&'static str, Box>,
+ addresses: Option>,
+}
+
+impl<'a> EventHandler<'a> {
+ pub fn new(block: &'a eth::Block) -> Self {
+ Self { block, handlers: HashMap::new(), addresses: None }
+ }
+
+ /// Sets the HasAddresser as a filter for which events to handle.
+ /// Only one at a time can be set. Setting it twice will remove the first one.
+ /// Addresses found in the `HasAddresser` will be the ones we'll handle events from.
+ pub fn filter_by_address(&mut self, addresser: impl HasAddresser + 'a) {
+ self.addresses = Some(Box::new(addresser));
+ }
+
+ /// Registers a handler to be run on a given event. The handler should have the signature:
+ /// `|ev: SomeEvent, tx: &pbeth::v2::TransactionTrace, log: &pbeth::v2::Log|`.
+ /// You can only assign one handler to each Event type.
+ /// Handlers are keyed by the name of the event they are handling, so be careful to not assign
+ /// handlers for 2 different events named equal.
+ pub fn on(&mut self, mut handler: F)
+ where
+ F: FnMut(E, ð::TransactionTrace, ð::Log) + 'a,
+ {
+ self.handlers.insert(
+ E::NAME,
+ Box::new(move |log: ð::Log, tx: ð::TransactionTrace| {
+ if let Some(event) = E::match_and_decode(log) {
+ handler(event, tx, log);
+ }
+ }),
+ );
+ }
+
+ /// Will run all registered handlers for all events present on the block that match the given
+ /// filters. You'll likely want to run this just once.
+ pub fn handle_events(&mut self) {
+ // Here we don't need to filter out failed transactions because logs only exist for
+ // successful ones.
+ for log in self.block.logs() {
+ if self.addresses.is_some() &&
+ !&self
+ .addresses
+ .as_ref()
+ .unwrap()
+ .has_address(Address::from_slice(log.log.address.as_slice()))
+ {
+ continue;
+ }
+
+ for handler in self.handlers.values_mut() {
+ handler(log.log, log.receipt.transaction);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/substreams/crates/substreams-helper/src/hex.rs b/substreams/crates/substreams-helper/src/hex.rs
new file mode 100644
index 0000000..c056ba7
--- /dev/null
+++ b/substreams/crates/substreams-helper/src/hex.rs
@@ -0,0 +1,20 @@
+use ethabi::ethereum_types::Address;
+use substreams::Hex;
+
+pub trait Hexable {
+ fn to_hex(&self) -> String;
+}
+
+impl Hexable for Vec {
+ fn to_hex(&self) -> String {
+ let mut str = Hex::encode(self);
+ str.insert_str(0, "0x");
+ str
+ }
+}
+
+impl Hexable for Address {
+ fn to_hex(&self) -> String {
+ self.as_bytes().to_vec().to_hex()
+ }
+}
diff --git a/substreams/crates/substreams-helper/src/lib.rs b/substreams/crates/substreams-helper/src/lib.rs
new file mode 100644
index 0000000..8e66ac5
--- /dev/null
+++ b/substreams/crates/substreams-helper/src/lib.rs
@@ -0,0 +1,5 @@
+pub mod common;
+
+pub mod event_handler;
+pub mod hex;
+pub mod storage_change;
diff --git a/substreams/crates/substreams-helper/src/storage_change.rs b/substreams/crates/substreams-helper/src/storage_change.rs
new file mode 100644
index 0000000..0fe484e
--- /dev/null
+++ b/substreams/crates/substreams-helper/src/storage_change.rs
@@ -0,0 +1,14 @@
+use substreams_ethereum::pb::eth::v2::StorageChange;
+
+pub trait StorageChangesFilter {
+ fn filter_by_address(&self, contract_addr: &[u8; 20]) -> Vec<&StorageChange>;
+}
+
+impl StorageChangesFilter for Vec {
+ fn filter_by_address(&self, contract_addr: &[u8; 20]) -> Vec<&StorageChange> {
+ return self
+ .iter()
+ .filter(|change| change.address == contract_addr)
+ .collect();
+ }
+}
diff --git a/substreams/ethereum-uniswap-v2/Cargo.toml b/substreams/ethereum-uniswap-v2/Cargo.toml
new file mode 100644
index 0000000..ab2e76a
--- /dev/null
+++ b/substreams/ethereum-uniswap-v2/Cargo.toml
@@ -0,0 +1,28 @@
+[package]
+name = "substreams-ethereum-uniswap-v2"
+version = "0.2.0"
+edition = "2021"
+
+[lib]
+name = "ethereum_uniswap_v2"
+crate-type = ["cdylib"]
+
+[dependencies]
+substreams.workspace = true
+substreams-ethereum.workspace = true
+prost.workspace = true
+ethabi.workspace = true
+anyhow = { workspace = true, features = [] }
+hex-literal.workspace = true
+substreams-helper.workspace = true
+num-bigint = "0.4.4"
+itertools = "0.12.1"
+serde_qs = "0.13.0"
+serde.workspace = true
+
+[target.wasm32-unknown-unknown.dependencies]
+getrandom = { version = "0.2", features = ["custom"] }
+
+[build-dependencies]
+anyhow.workspace = true
+substreams-ethereum.workspace = true
diff --git a/substreams/ethereum-uniswap-v2/Makefile b/substreams/ethereum-uniswap-v2/Makefile
new file mode 100644
index 0000000..d9be557
--- /dev/null
+++ b/substreams/ethereum-uniswap-v2/Makefile
@@ -0,0 +1,2 @@
+build:
+ cargo build --target wasm32-unknown-unknown --release
\ No newline at end of file
diff --git a/substreams/ethereum-uniswap-v2/abi/Factory.json b/substreams/ethereum-uniswap-v2/abi/Factory.json
new file mode 100644
index 0000000..1b14599
--- /dev/null
+++ b/substreams/ethereum-uniswap-v2/abi/Factory.json
@@ -0,0 +1,125 @@
+[
+ {
+ "inputs": [
+ { "internalType": "address", "name": "_feeToSetter", "type": "address" }
+ ],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "constructor"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "token0",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "token1",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "pair",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "name": "PairCreated",
+ "type": "event"
+ },
+ {
+ "constant": true,
+ "inputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
+ "name": "allPairs",
+ "outputs": [{ "internalType": "address", "name": "", "type": "address" }],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "allPairsLength",
+ "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ { "internalType": "address", "name": "tokenA", "type": "address" },
+ { "internalType": "address", "name": "tokenB", "type": "address" }
+ ],
+ "name": "createPair",
+ "outputs": [
+ { "internalType": "address", "name": "pair", "type": "address" }
+ ],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "feeTo",
+ "outputs": [{ "internalType": "address", "name": "", "type": "address" }],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "feeToSetter",
+ "outputs": [{ "internalType": "address", "name": "", "type": "address" }],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [
+ { "internalType": "address", "name": "", "type": "address" },
+ { "internalType": "address", "name": "", "type": "address" }
+ ],
+ "name": "getPair",
+ "outputs": [{ "internalType": "address", "name": "", "type": "address" }],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ { "internalType": "address", "name": "_feeTo", "type": "address" }
+ ],
+ "name": "setFeeTo",
+ "outputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ { "internalType": "address", "name": "_feeToSetter", "type": "address" }
+ ],
+ "name": "setFeeToSetter",
+ "outputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ }
+]
diff --git a/substreams/ethereum-uniswap-v2/abi/Pool.json b/substreams/ethereum-uniswap-v2/abi/Pool.json
new file mode 100644
index 0000000..53582c1
--- /dev/null
+++ b/substreams/ethereum-uniswap-v2/abi/Pool.json
@@ -0,0 +1,713 @@
+[
+ {
+ "inputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "constructor"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "owner",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "spender",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "value",
+ "type": "uint256"
+ }
+ ],
+ "name": "Approval",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount0",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount1",
+ "type": "uint256"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "to",
+ "type": "address"
+ }
+ ],
+ "name": "Burn",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount0",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount1",
+ "type": "uint256"
+ }
+ ],
+ "name": "Mint",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount0In",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount1In",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount0Out",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount1Out",
+ "type": "uint256"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "to",
+ "type": "address"
+ }
+ ],
+ "name": "Swap",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "internalType": "uint112",
+ "name": "reserve0",
+ "type": "uint112"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint112",
+ "name": "reserve1",
+ "type": "uint112"
+ }
+ ],
+ "name": "Sync",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "from",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "to",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "value",
+ "type": "uint256"
+ }
+ ],
+ "name": "Transfer",
+ "type": "event"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "DOMAIN_SEPARATOR",
+ "outputs": [
+ {
+ "internalType": "bytes32",
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "MINIMUM_LIQUIDITY",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "PERMIT_TYPEHASH",
+ "outputs": [
+ {
+ "internalType": "bytes32",
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "name": "allowance",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "spender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "value",
+ "type": "uint256"
+ }
+ ],
+ "name": "approve",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "name": "balanceOf",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "to",
+ "type": "address"
+ }
+ ],
+ "name": "burn",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "amount0",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount1",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "decimals",
+ "outputs": [
+ {
+ "internalType": "uint8",
+ "name": "",
+ "type": "uint8"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "factory",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "getReserves",
+ "outputs": [
+ {
+ "internalType": "uint112",
+ "name": "_reserve0",
+ "type": "uint112"
+ },
+ {
+ "internalType": "uint112",
+ "name": "_reserve1",
+ "type": "uint112"
+ },
+ {
+ "internalType": "uint32",
+ "name": "_blockTimestampLast",
+ "type": "uint32"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "_token0",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "_token1",
+ "type": "address"
+ }
+ ],
+ "name": "initialize",
+ "outputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "kLast",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "to",
+ "type": "address"
+ }
+ ],
+ "name": "mint",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "liquidity",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "name",
+ "outputs": [
+ {
+ "internalType": "string",
+ "name": "",
+ "type": "string"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "name": "nonces",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "owner",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "spender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "value",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "deadline",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint8",
+ "name": "v",
+ "type": "uint8"
+ },
+ {
+ "internalType": "bytes32",
+ "name": "r",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "bytes32",
+ "name": "s",
+ "type": "bytes32"
+ }
+ ],
+ "name": "permit",
+ "outputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "price0CumulativeLast",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "price1CumulativeLast",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "to",
+ "type": "address"
+ }
+ ],
+ "name": "skim",
+ "outputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "amount0Out",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount1Out",
+ "type": "uint256"
+ },
+ {
+ "internalType": "address",
+ "name": "to",
+ "type": "address"
+ },
+ {
+ "internalType": "bytes",
+ "name": "data",
+ "type": "bytes"
+ }
+ ],
+ "name": "swap",
+ "outputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "symbol",
+ "outputs": [
+ {
+ "internalType": "string",
+ "name": "",
+ "type": "string"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [],
+ "name": "sync",
+ "outputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "token0",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "token1",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "totalSupply",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "to",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "value",
+ "type": "uint256"
+ }
+ ],
+ "name": "transfer",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "from",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "to",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "value",
+ "type": "uint256"
+ }
+ ],
+ "name": "transferFrom",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ }
+]
diff --git a/substreams/ethereum-uniswap-v2/arbitrum-uniswap-v2.yaml b/substreams/ethereum-uniswap-v2/arbitrum-uniswap-v2.yaml
new file mode 100644
index 0000000..7f287bc
--- /dev/null
+++ b/substreams/ethereum-uniswap-v2/arbitrum-uniswap-v2.yaml
@@ -0,0 +1,49 @@
+specVersion: v0.1.0
+package:
+ name: "arbitrum_uniswap_v2"
+ version: v0.2.0
+
+protobuf:
+ files:
+ - tycho/evm/v1/common.proto
+ - tycho/evm/v1/entity.proto
+ - uniswap.proto
+ importPaths:
+ - ./proto/v1
+ - ../../proto/
+
+binaries:
+ default:
+ type: wasm/rust-v1
+ file: ../../target/wasm32-unknown-unknown/substreams/ethereum_uniswap_v2.wasm
+
+modules:
+ - name: map_pools_created
+ kind: map
+ initialBlock: 150442611
+ inputs:
+ - params: string
+ - source: sf.ethereum.type.v2.Block
+ output:
+ type: proto:tycho.evm.v1.BlockChanges
+
+ - name: store_pools
+ kind: store
+ initialBlock: 150442611
+ updatePolicy: set_if_not_exists
+ valueType: proto:tycho.evm.uniswap.v2.Pool
+ inputs:
+ - map: map_pools_created
+
+ - name: map_pool_events
+ kind: map
+ initialBlock: 150442611
+ inputs:
+ - source: sf.ethereum.type.v2.Block
+ - map: map_pools_created
+ - store: store_pools
+ output:
+ type: proto:tycho.evm.v1.BlockChanges
+
+params:
+ map_pools_created: factory_address=f1D7CC64Fb4452F05c498126312eBE29f30Fbcf9&protocol_type_name=uniswap_v2_pool
diff --git a/substreams/ethereum-uniswap-v2/build.rs b/substreams/ethereum-uniswap-v2/build.rs
new file mode 100644
index 0000000..7992bb0
--- /dev/null
+++ b/substreams/ethereum-uniswap-v2/build.rs
@@ -0,0 +1,12 @@
+use anyhow::{Ok, Result};
+use substreams_ethereum::Abigen;
+
+fn main() -> Result<(), anyhow::Error> {
+ Abigen::new("Factory", "abi/Factory.json")?
+ .generate()?
+ .write_to_file("src/abi/factory.rs")?;
+ Abigen::new("Pool", "abi/Pool.json")?
+ .generate()?
+ .write_to_file("src/abi/pool.rs")?;
+ Ok(())
+}
diff --git a/substreams/ethereum-uniswap-v2/ethereum-pancakeswap.yaml b/substreams/ethereum-uniswap-v2/ethereum-pancakeswap.yaml
new file mode 100644
index 0000000..7424d6c
--- /dev/null
+++ b/substreams/ethereum-uniswap-v2/ethereum-pancakeswap.yaml
@@ -0,0 +1,49 @@
+specVersion: v0.1.0
+package:
+ name: "ethereum_pancakeswap"
+ version: v0.2.0
+
+protobuf:
+ files:
+ - tycho/evm/v1/common.proto
+ - tycho/evm/v1/entity.proto
+ - uniswap.proto
+ importPaths:
+ - ./proto/v1
+ - ../../proto/
+
+binaries:
+ default:
+ type: wasm/rust-v1
+ file: ../../target/wasm32-unknown-unknown/substreams/ethereum_uniswap_v2.wasm
+
+modules:
+ - name: map_pools_created
+ kind: map
+ initialBlock: 15614590
+ inputs:
+ - params: string
+ - source: sf.ethereum.type.v2.Block
+ output:
+ type: proto:tycho.evm.v1.BlockChanges
+
+ - name: store_pools
+ kind: store
+ initialBlock: 15614590
+ updatePolicy: set_if_not_exists
+ valueType: proto:tycho.evm.v1.ProtocolComponent
+ inputs:
+ - map: map_pools_created
+
+ - name: map_pool_events
+ kind: map
+ initialBlock: 15614590
+ inputs:
+ - source: sf.ethereum.type.v2.Block
+ - map: map_pools_created
+ - store: store_pools
+ output:
+ type: proto:tycho.evm.v1.BlockChanges
+
+params:
+ map_pools_created: factory_address=1097053fd2ea711dad45caccc45eff7548fcb362&protocol_type_name=pancakeswap_pool
diff --git a/substreams/ethereum-uniswap-v2/ethereum-sushiswap.yaml b/substreams/ethereum-uniswap-v2/ethereum-sushiswap.yaml
new file mode 100644
index 0000000..e5334d1
--- /dev/null
+++ b/substreams/ethereum-uniswap-v2/ethereum-sushiswap.yaml
@@ -0,0 +1,49 @@
+specVersion: v0.1.0
+package:
+ name: "ethereum_sushiswap_v2"
+ version: v0.2.0
+
+protobuf:
+ files:
+ - tycho/evm/v1/common.proto
+ - tycho/evm/v1/entity.proto
+ - uniswap.proto
+ importPaths:
+ - ./proto/v1
+ - ../../proto/
+
+binaries:
+ default:
+ type: wasm/rust-v1
+ file: ../../target/wasm32-unknown-unknown/substreams/ethereum_uniswap_v2.wasm
+
+modules:
+ - name: map_pools_created
+ kind: map
+ initialBlock: 10794229
+ inputs:
+ - params: string
+ - source: sf.ethereum.type.v2.Block
+ output:
+ type: proto:tycho.evm.v1.BlockChanges
+
+ - name: store_pools
+ kind: store
+ initialBlock: 10794229
+ updatePolicy: set_if_not_exists
+ valueType: proto:tycho.evm.uniswap.v2.Pool
+ inputs:
+ - map: map_pools_created
+
+ - name: map_pool_events
+ kind: map
+ initialBlock: 10794229
+ inputs:
+ - source: sf.ethereum.type.v2.Block
+ - map: map_pools_created
+ - store: store_pools
+ output:
+ type: proto:tycho.evm.v1.BlockChanges
+
+params:
+ map_pools_created: factory_address=c0aee478e3658e2610c5f7a4a2e1777ce9e4f2ac&protocol_type_name=sushiswap_v2_pool
diff --git a/substreams/ethereum-uniswap-v2/ethereum-uniswap-v2.yaml b/substreams/ethereum-uniswap-v2/ethereum-uniswap-v2.yaml
new file mode 100644
index 0000000..1ed8f63
--- /dev/null
+++ b/substreams/ethereum-uniswap-v2/ethereum-uniswap-v2.yaml
@@ -0,0 +1,49 @@
+specVersion: v0.1.0
+package:
+ name: "ethereum_uniswap_v2"
+ version: v0.2.0
+
+protobuf:
+ files:
+ - tycho/evm/v1/common.proto
+ - tycho/evm/v1/entity.proto
+ - uniswap.proto
+ importPaths:
+ - ./proto/v1
+ - ../../proto/
+
+binaries:
+ default:
+ type: wasm/rust-v1
+ file: ../../target/wasm32-unknown-unknown/substreams/ethereum_uniswap_v2.wasm
+
+modules:
+ - name: map_pools_created
+ kind: map
+ initialBlock: 10008300
+ inputs:
+ - params: string
+ - source: sf.ethereum.type.v2.Block
+ output:
+ type: proto:tycho.evm.v1.BlockChanges
+
+ - name: store_pools
+ kind: store
+ initialBlock: 10008300
+ updatePolicy: set_if_not_exists
+ valueType: proto:tycho.evm.uniswap.v2.Pool
+ inputs:
+ - map: map_pools_created
+
+ - name: map_pool_events
+ kind: map
+ initialBlock: 10008300
+ inputs:
+ - source: sf.ethereum.type.v2.Block
+ - map: map_pools_created
+ - store: store_pools
+ output:
+ type: proto:tycho.evm.v1.BlockChanges
+
+params:
+ map_pools_created: factory_address=5c69bee701ef814a2b6a3edd4b1652cb9cc5aa6f&protocol_type_name=uniswap_v2_pool
diff --git a/substreams/ethereum-uniswap-v2/proto/v1/uniswap.proto b/substreams/ethereum-uniswap-v2/proto/v1/uniswap.proto
new file mode 100644
index 0000000..3f26fd1
--- /dev/null
+++ b/substreams/ethereum-uniswap-v2/proto/v1/uniswap.proto
@@ -0,0 +1,61 @@
+syntax = "proto3";
+
+package tycho.evm.uniswap.v2;
+
+message Pools {
+ repeated Pool pools = 1;
+}
+
+message Pool {
+ bytes address = 1;
+
+ bytes token0 = 2;
+ bytes token1 = 3;
+
+ bytes created_tx_hash = 4;
+}
+
+message Events {
+ repeated Event events = 1;
+}
+
+message Event {
+ oneof type {
+ DepositEvent deposit_type = 10;
+ WithdrawEvent withdraw_type = 20;
+ SyncEvent sync_type = 30;
+ SwapEvent swap_type = 40;
+ }
+
+ string hash = 100;
+ uint32 log_index = 101;
+ uint64 log_ordinal = 102;
+ string to = 103;
+ string from = 104;
+ uint64 block_number = 105;
+ uint64 timestamp = 106;
+ string pool = 107;
+}
+
+message DepositEvent {
+ repeated string input_token_amounts = 1;
+ optional string output_token_amount = 2;
+}
+
+message WithdrawEvent {
+ repeated string input_token_amounts = 1;
+ optional string output_token_amount = 2;
+}
+
+message SyncEvent {
+ string reserve0 = 1;
+ string reserve1 = 2;
+}
+
+message SwapEvent {
+ string token_in = 1;
+ string amount_in = 2;
+
+ string token_out = 3;
+ string amount_out = 4;
+}
diff --git a/substreams/ethereum-uniswap-v2/src/abi/factory.rs b/substreams/ethereum-uniswap-v2/src/abi/factory.rs
new file mode 100644
index 0000000..2a92a8f
--- /dev/null
+++ b/substreams/ethereum-uniswap-v2/src/abi/factory.rs
@@ -0,0 +1,904 @@
+ const INTERNAL_ERR: &'static str = "`ethabi_derive` internal error";
+ /// Contract's functions.
+ #[allow(dead_code, unused_imports, unused_variables)]
+ pub mod functions {
+ use super::INTERNAL_ERR;
+ #[derive(Debug, Clone, PartialEq)]
+ pub struct AllPairs {
+ pub param0: substreams::scalar::BigInt,
+ }
+ impl AllPairs {
+ const METHOD_ID: [u8; 4] = [30u8, 61u8, 209u8, 139u8];
+ pub fn decode(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ let maybe_data = call.input.get(4..);
+ if maybe_data.is_none() {
+ return Err("no data to decode".to_string());
+ }
+ let mut values = ethabi::decode(
+ &[ethabi::ParamType::Uint(256usize)],
+ maybe_data.unwrap(),
+ )
+ .map_err(|e| format!("unable to decode call.input: {:?}", e))?;
+ values.reverse();
+ Ok(Self {
+ param0: {
+ let mut v = [0 as u8; 32];
+ values
+ .pop()
+ .expect(INTERNAL_ERR)
+ .into_uint()
+ .expect(INTERNAL_ERR)
+ .to_big_endian(v.as_mut_slice());
+ substreams::scalar::BigInt::from_unsigned_bytes_be(&v)
+ },
+ })
+ }
+ pub fn encode(&self) -> Vec {
+ let data = ethabi::encode(
+ &[
+ ethabi::Token::Uint(
+ ethabi::Uint::from_big_endian(
+ match self.param0.clone().to_bytes_be() {
+ (num_bigint::Sign::Plus, bytes) => bytes,
+ (num_bigint::Sign::NoSign, bytes) => bytes,
+ (num_bigint::Sign::Minus, _) => {
+ panic!("negative numbers are not supported")
+ }
+ }
+ .as_slice(),
+ ),
+ ),
+ ],
+ );
+ let mut encoded = Vec::with_capacity(4 + data.len());
+ encoded.extend(Self::METHOD_ID);
+ encoded.extend(data);
+ encoded
+ }
+ pub fn output_call(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result, String> {
+ Self::output(call.return_data.as_ref())
+ }
+ pub fn output(data: &[u8]) -> Result, String> {
+ let mut values = ethabi::decode(
+ &[ethabi::ParamType::Address],
+ data.as_ref(),
+ )
+ .map_err(|e| format!("unable to decode output data: {:?}", e))?;
+ Ok(
+ values
+ .pop()
+ .expect("one output data should have existed")
+ .into_address()
+ .expect(INTERNAL_ERR)
+ .as_bytes()
+ .to_vec(),
+ )
+ }
+ pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool {
+ match call.input.get(0..4) {
+ Some(signature) => Self::METHOD_ID == signature,
+ None => false,
+ }
+ }
+ pub fn call(&self, address: Vec) -> Option> {
+ use substreams_ethereum::pb::eth::rpc;
+ let rpc_calls = rpc::RpcCalls {
+ calls: vec![
+ rpc::RpcCall { to_addr : address, data : self.encode(), }
+ ],
+ };
+ let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses;
+ let response = responses
+ .get(0)
+ .expect("one response should have existed");
+ if response.failed {
+ return None;
+ }
+ match Self::output(response.raw.as_ref()) {
+ Ok(data) => Some(data),
+ Err(err) => {
+ use substreams_ethereum::Function;
+ substreams::log::info!(
+ "Call output for function `{}` failed to decode with error: {}",
+ Self::NAME, err
+ );
+ None
+ }
+ }
+ }
+ }
+ impl substreams_ethereum::Function for AllPairs {
+ const NAME: &'static str = "allPairs";
+ fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool {
+ Self::match_call(call)
+ }
+ fn decode(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ Self::decode(call)
+ }
+ fn encode(&self) -> Vec {
+ self.encode()
+ }
+ }
+ impl substreams_ethereum::rpc::RPCDecodable> for AllPairs {
+ fn output(data: &[u8]) -> Result, String> {
+ Self::output(data)
+ }
+ }
+ #[derive(Debug, Clone, PartialEq)]
+ pub struct AllPairsLength {}
+ impl AllPairsLength {
+ const METHOD_ID: [u8; 4] = [87u8, 79u8, 43u8, 163u8];
+ pub fn decode(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ Ok(Self {})
+ }
+ pub fn encode(&self) -> Vec {
+ let data = ethabi::encode(&[]);
+ let mut encoded = Vec::with_capacity(4 + data.len());
+ encoded.extend(Self::METHOD_ID);
+ encoded.extend(data);
+ encoded
+ }
+ pub fn output_call(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ Self::output(call.return_data.as_ref())
+ }
+ pub fn output(data: &[u8]) -> Result {
+ let mut values = ethabi::decode(
+ &[ethabi::ParamType::Uint(256usize)],
+ data.as_ref(),
+ )
+ .map_err(|e| format!("unable to decode output data: {:?}", e))?;
+ Ok({
+ let mut v = [0 as u8; 32];
+ values
+ .pop()
+ .expect("one output data should have existed")
+ .into_uint()
+ .expect(INTERNAL_ERR)
+ .to_big_endian(v.as_mut_slice());
+ substreams::scalar::BigInt::from_unsigned_bytes_be(&v)
+ })
+ }
+ pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool {
+ match call.input.get(0..4) {
+ Some(signature) => Self::METHOD_ID == signature,
+ None => false,
+ }
+ }
+ pub fn call(&self, address: Vec) -> Option {
+ use substreams_ethereum::pb::eth::rpc;
+ let rpc_calls = rpc::RpcCalls {
+ calls: vec![
+ rpc::RpcCall { to_addr : address, data : self.encode(), }
+ ],
+ };
+ let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses;
+ let response = responses
+ .get(0)
+ .expect("one response should have existed");
+ if response.failed {
+ return None;
+ }
+ match Self::output(response.raw.as_ref()) {
+ Ok(data) => Some(data),
+ Err(err) => {
+ use substreams_ethereum::Function;
+ substreams::log::info!(
+ "Call output for function `{}` failed to decode with error: {}",
+ Self::NAME, err
+ );
+ None
+ }
+ }
+ }
+ }
+ impl substreams_ethereum::Function for AllPairsLength {
+ const NAME: &'static str = "allPairsLength";
+ fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool {
+ Self::match_call(call)
+ }
+ fn decode(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ Self::decode(call)
+ }
+ fn encode(&self) -> Vec {
+ self.encode()
+ }
+ }
+ impl substreams_ethereum::rpc::RPCDecodable
+ for AllPairsLength {
+ fn output(data: &[u8]) -> Result {
+ Self::output(data)
+ }
+ }
+ #[derive(Debug, Clone, PartialEq)]
+ pub struct CreatePair {
+ pub token_a: Vec,
+ pub token_b: Vec,
+ }
+ impl CreatePair {
+ const METHOD_ID: [u8; 4] = [201u8, 198u8, 83u8, 150u8];
+ pub fn decode(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ let maybe_data = call.input.get(4..);
+ if maybe_data.is_none() {
+ return Err("no data to decode".to_string());
+ }
+ let mut values = ethabi::decode(
+ &[ethabi::ParamType::Address, ethabi::ParamType::Address],
+ maybe_data.unwrap(),
+ )
+ .map_err(|e| format!("unable to decode call.input: {:?}", e))?;
+ values.reverse();
+ Ok(Self {
+ token_a: values
+ .pop()
+ .expect(INTERNAL_ERR)
+ .into_address()
+ .expect(INTERNAL_ERR)
+ .as_bytes()
+ .to_vec(),
+ token_b: values
+ .pop()
+ .expect(INTERNAL_ERR)
+ .into_address()
+ .expect(INTERNAL_ERR)
+ .as_bytes()
+ .to_vec(),
+ })
+ }
+ pub fn encode(&self) -> Vec {
+ let data = ethabi::encode(
+ &[
+ ethabi::Token::Address(
+ ethabi::Address::from_slice(&self.token_a),
+ ),
+ ethabi::Token::Address(
+ ethabi::Address::from_slice(&self.token_b),
+ ),
+ ],
+ );
+ let mut encoded = Vec::with_capacity(4 + data.len());
+ encoded.extend(Self::METHOD_ID);
+ encoded.extend(data);
+ encoded
+ }
+ pub fn output_call(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result, String> {
+ Self::output(call.return_data.as_ref())
+ }
+ pub fn output(data: &[u8]) -> Result, String> {
+ let mut values = ethabi::decode(
+ &[ethabi::ParamType::Address],
+ data.as_ref(),
+ )
+ .map_err(|e| format!("unable to decode output data: {:?}", e))?;
+ Ok(
+ values
+ .pop()
+ .expect("one output data should have existed")
+ .into_address()
+ .expect(INTERNAL_ERR)
+ .as_bytes()
+ .to_vec(),
+ )
+ }
+ pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool {
+ match call.input.get(0..4) {
+ Some(signature) => Self::METHOD_ID == signature,
+ None => false,
+ }
+ }
+ pub fn call(&self, address: Vec) -> Option> {
+ use substreams_ethereum::pb::eth::rpc;
+ let rpc_calls = rpc::RpcCalls {
+ calls: vec![
+ rpc::RpcCall { to_addr : address, data : self.encode(), }
+ ],
+ };
+ let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses;
+ let response = responses
+ .get(0)
+ .expect("one response should have existed");
+ if response.failed {
+ return None;
+ }
+ match Self::output(response.raw.as_ref()) {
+ Ok(data) => Some(data),
+ Err(err) => {
+ use substreams_ethereum::Function;
+ substreams::log::info!(
+ "Call output for function `{}` failed to decode with error: {}",
+ Self::NAME, err
+ );
+ None
+ }
+ }
+ }
+ }
+ impl substreams_ethereum::Function for CreatePair {
+ const NAME: &'static str = "createPair";
+ fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool {
+ Self::match_call(call)
+ }
+ fn decode(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ Self::decode(call)
+ }
+ fn encode(&self) -> Vec {
+ self.encode()
+ }
+ }
+ impl substreams_ethereum::rpc::RPCDecodable> for CreatePair {
+ fn output(data: &[u8]) -> Result, String> {
+ Self::output(data)
+ }
+ }
+ #[derive(Debug, Clone, PartialEq)]
+ pub struct FeeTo {}
+ impl FeeTo {
+ const METHOD_ID: [u8; 4] = [1u8, 126u8, 126u8, 88u8];
+ pub fn decode(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ Ok(Self {})
+ }
+ pub fn encode(&self) -> Vec {
+ let data = ethabi::encode(&[]);
+ let mut encoded = Vec::with_capacity(4 + data.len());
+ encoded.extend(Self::METHOD_ID);
+ encoded.extend(data);
+ encoded
+ }
+ pub fn output_call(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result, String> {
+ Self::output(call.return_data.as_ref())
+ }
+ pub fn output(data: &[u8]) -> Result, String> {
+ let mut values = ethabi::decode(
+ &[ethabi::ParamType::Address],
+ data.as_ref(),
+ )
+ .map_err(|e| format!("unable to decode output data: {:?}", e))?;
+ Ok(
+ values
+ .pop()
+ .expect("one output data should have existed")
+ .into_address()
+ .expect(INTERNAL_ERR)
+ .as_bytes()
+ .to_vec(),
+ )
+ }
+ pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool {
+ match call.input.get(0..4) {
+ Some(signature) => Self::METHOD_ID == signature,
+ None => false,
+ }
+ }
+ pub fn call(&self, address: Vec) -> Option> {
+ use substreams_ethereum::pb::eth::rpc;
+ let rpc_calls = rpc::RpcCalls {
+ calls: vec![
+ rpc::RpcCall { to_addr : address, data : self.encode(), }
+ ],
+ };
+ let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses;
+ let response = responses
+ .get(0)
+ .expect("one response should have existed");
+ if response.failed {
+ return None;
+ }
+ match Self::output(response.raw.as_ref()) {
+ Ok(data) => Some(data),
+ Err(err) => {
+ use substreams_ethereum::Function;
+ substreams::log::info!(
+ "Call output for function `{}` failed to decode with error: {}",
+ Self::NAME, err
+ );
+ None
+ }
+ }
+ }
+ }
+ impl substreams_ethereum::Function for FeeTo {
+ const NAME: &'static str = "feeTo";
+ fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool {
+ Self::match_call(call)
+ }
+ fn decode(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ Self::decode(call)
+ }
+ fn encode(&self) -> Vec {
+ self.encode()
+ }
+ }
+ impl substreams_ethereum::rpc::RPCDecodable> for FeeTo {
+ fn output(data: &[u8]) -> Result, String> {
+ Self::output(data)
+ }
+ }
+ #[derive(Debug, Clone, PartialEq)]
+ pub struct FeeToSetter {}
+ impl FeeToSetter {
+ const METHOD_ID: [u8; 4] = [9u8, 75u8, 116u8, 21u8];
+ pub fn decode(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ Ok(Self {})
+ }
+ pub fn encode(&self) -> Vec {
+ let data = ethabi::encode(&[]);
+ let mut encoded = Vec::with_capacity(4 + data.len());
+ encoded.extend(Self::METHOD_ID);
+ encoded.extend(data);
+ encoded
+ }
+ pub fn output_call(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result, String> {
+ Self::output(call.return_data.as_ref())
+ }
+ pub fn output(data: &[u8]) -> Result, String> {
+ let mut values = ethabi::decode(
+ &[ethabi::ParamType::Address],
+ data.as_ref(),
+ )
+ .map_err(|e| format!("unable to decode output data: {:?}", e))?;
+ Ok(
+ values
+ .pop()
+ .expect("one output data should have existed")
+ .into_address()
+ .expect(INTERNAL_ERR)
+ .as_bytes()
+ .to_vec(),
+ )
+ }
+ pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool {
+ match call.input.get(0..4) {
+ Some(signature) => Self::METHOD_ID == signature,
+ None => false,
+ }
+ }
+ pub fn call(&self, address: Vec) -> Option> {
+ use substreams_ethereum::pb::eth::rpc;
+ let rpc_calls = rpc::RpcCalls {
+ calls: vec![
+ rpc::RpcCall { to_addr : address, data : self.encode(), }
+ ],
+ };
+ let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses;
+ let response = responses
+ .get(0)
+ .expect("one response should have existed");
+ if response.failed {
+ return None;
+ }
+ match Self::output(response.raw.as_ref()) {
+ Ok(data) => Some(data),
+ Err(err) => {
+ use substreams_ethereum::Function;
+ substreams::log::info!(
+ "Call output for function `{}` failed to decode with error: {}",
+ Self::NAME, err
+ );
+ None
+ }
+ }
+ }
+ }
+ impl substreams_ethereum::Function for FeeToSetter {
+ const NAME: &'static str = "feeToSetter";
+ fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool {
+ Self::match_call(call)
+ }
+ fn decode(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ Self::decode(call)
+ }
+ fn encode(&self) -> Vec {
+ self.encode()
+ }
+ }
+ impl substreams_ethereum::rpc::RPCDecodable> for FeeToSetter {
+ fn output(data: &[u8]) -> Result, String> {
+ Self::output(data)
+ }
+ }
+ #[derive(Debug, Clone, PartialEq)]
+ pub struct GetPair {
+ pub param0: Vec,
+ pub param1: Vec,
+ }
+ impl GetPair {
+ const METHOD_ID: [u8; 4] = [230u8, 164u8, 57u8, 5u8];
+ pub fn decode(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ let maybe_data = call.input.get(4..);
+ if maybe_data.is_none() {
+ return Err("no data to decode".to_string());
+ }
+ let mut values = ethabi::decode(
+ &[ethabi::ParamType::Address, ethabi::ParamType::Address],
+ maybe_data.unwrap(),
+ )
+ .map_err(|e| format!("unable to decode call.input: {:?}", e))?;
+ values.reverse();
+ Ok(Self {
+ param0: values
+ .pop()
+ .expect(INTERNAL_ERR)
+ .into_address()
+ .expect(INTERNAL_ERR)
+ .as_bytes()
+ .to_vec(),
+ param1: values
+ .pop()
+ .expect(INTERNAL_ERR)
+ .into_address()
+ .expect(INTERNAL_ERR)
+ .as_bytes()
+ .to_vec(),
+ })
+ }
+ pub fn encode(&self) -> Vec {
+ let data = ethabi::encode(
+ &[
+ ethabi::Token::Address(
+ ethabi::Address::from_slice(&self.param0),
+ ),
+ ethabi::Token::Address(ethabi::Address::from_slice(&self.param1)),
+ ],
+ );
+ let mut encoded = Vec::with_capacity(4 + data.len());
+ encoded.extend(Self::METHOD_ID);
+ encoded.extend(data);
+ encoded
+ }
+ pub fn output_call(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result, String> {
+ Self::output(call.return_data.as_ref())
+ }
+ pub fn output(data: &[u8]) -> Result, String> {
+ let mut values = ethabi::decode(
+ &[ethabi::ParamType::Address],
+ data.as_ref(),
+ )
+ .map_err(|e| format!("unable to decode output data: {:?}", e))?;
+ Ok(
+ values
+ .pop()
+ .expect("one output data should have existed")
+ .into_address()
+ .expect(INTERNAL_ERR)
+ .as_bytes()
+ .to_vec(),
+ )
+ }
+ pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool {
+ match call.input.get(0..4) {
+ Some(signature) => Self::METHOD_ID == signature,
+ None => false,
+ }
+ }
+ pub fn call(&self, address: Vec) -> Option> {
+ use substreams_ethereum::pb::eth::rpc;
+ let rpc_calls = rpc::RpcCalls {
+ calls: vec![
+ rpc::RpcCall { to_addr : address, data : self.encode(), }
+ ],
+ };
+ let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses;
+ let response = responses
+ .get(0)
+ .expect("one response should have existed");
+ if response.failed {
+ return None;
+ }
+ match Self::output(response.raw.as_ref()) {
+ Ok(data) => Some(data),
+ Err(err) => {
+ use substreams_ethereum::Function;
+ substreams::log::info!(
+ "Call output for function `{}` failed to decode with error: {}",
+ Self::NAME, err
+ );
+ None
+ }
+ }
+ }
+ }
+ impl substreams_ethereum::Function for GetPair {
+ const NAME: &'static str = "getPair";
+ fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool {
+ Self::match_call(call)
+ }
+ fn decode(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ Self::decode(call)
+ }
+ fn encode(&self) -> Vec {
+ self.encode()
+ }
+ }
+ impl substreams_ethereum::rpc::RPCDecodable> for GetPair {
+ fn output(data: &[u8]) -> Result, String> {
+ Self::output(data)
+ }
+ }
+ #[derive(Debug, Clone, PartialEq)]
+ pub struct SetFeeTo {
+ pub fee_to: Vec,
+ }
+ impl SetFeeTo {
+ const METHOD_ID: [u8; 4] = [244u8, 105u8, 1u8, 237u8];
+ pub fn decode(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ let maybe_data = call.input.get(4..);
+ if maybe_data.is_none() {
+ return Err("no data to decode".to_string());
+ }
+ let mut values = ethabi::decode(
+ &[ethabi::ParamType::Address],
+ maybe_data.unwrap(),
+ )
+ .map_err(|e| format!("unable to decode call.input: {:?}", e))?;
+ values.reverse();
+ Ok(Self {
+ fee_to: values
+ .pop()
+ .expect(INTERNAL_ERR)
+ .into_address()
+ .expect(INTERNAL_ERR)
+ .as_bytes()
+ .to_vec(),
+ })
+ }
+ pub fn encode(&self) -> Vec {
+ let data = ethabi::encode(
+ &[ethabi::Token::Address(ethabi::Address::from_slice(&self.fee_to))],
+ );
+ let mut encoded = Vec::with_capacity(4 + data.len());
+ encoded.extend(Self::METHOD_ID);
+ encoded.extend(data);
+ encoded
+ }
+ pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool {
+ match call.input.get(0..4) {
+ Some(signature) => Self::METHOD_ID == signature,
+ None => false,
+ }
+ }
+ }
+ impl substreams_ethereum::Function for SetFeeTo {
+ const NAME: &'static str = "setFeeTo";
+ fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool {
+ Self::match_call(call)
+ }
+ fn decode(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ Self::decode(call)
+ }
+ fn encode(&self) -> Vec {
+ self.encode()
+ }
+ }
+ #[derive(Debug, Clone, PartialEq)]
+ pub struct SetFeeToSetter {
+ pub fee_to_setter: Vec,
+ }
+ impl SetFeeToSetter {
+ const METHOD_ID: [u8; 4] = [162u8, 231u8, 74u8, 246u8];
+ pub fn decode(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ let maybe_data = call.input.get(4..);
+ if maybe_data.is_none() {
+ return Err("no data to decode".to_string());
+ }
+ let mut values = ethabi::decode(
+ &[ethabi::ParamType::Address],
+ maybe_data.unwrap(),
+ )
+ .map_err(|e| format!("unable to decode call.input: {:?}", e))?;
+ values.reverse();
+ Ok(Self {
+ fee_to_setter: values
+ .pop()
+ .expect(INTERNAL_ERR)
+ .into_address()
+ .expect(INTERNAL_ERR)
+ .as_bytes()
+ .to_vec(),
+ })
+ }
+ pub fn encode(&self) -> Vec {
+ let data = ethabi::encode(
+ &[
+ ethabi::Token::Address(
+ ethabi::Address::from_slice(&self.fee_to_setter),
+ ),
+ ],
+ );
+ let mut encoded = Vec::with_capacity(4 + data.len());
+ encoded.extend(Self::METHOD_ID);
+ encoded.extend(data);
+ encoded
+ }
+ pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool {
+ match call.input.get(0..4) {
+ Some(signature) => Self::METHOD_ID == signature,
+ None => false,
+ }
+ }
+ }
+ impl substreams_ethereum::Function for SetFeeToSetter {
+ const NAME: &'static str = "setFeeToSetter";
+ fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool {
+ Self::match_call(call)
+ }
+ fn decode(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ Self::decode(call)
+ }
+ fn encode(&self) -> Vec {
+ self.encode()
+ }
+ }
+ }
+ /// Contract's events.
+ #[allow(dead_code, unused_imports, unused_variables)]
+ pub mod events {
+ use super::INTERNAL_ERR;
+ #[derive(Debug, Clone, PartialEq)]
+ pub struct PairCreated {
+ pub token0: Vec,
+ pub token1: Vec,
+ pub pair: Vec,
+ pub param3: substreams::scalar::BigInt,
+ }
+ impl PairCreated {
+ const TOPIC_ID: [u8; 32] = [
+ 13u8,
+ 54u8,
+ 72u8,
+ 189u8,
+ 15u8,
+ 107u8,
+ 168u8,
+ 1u8,
+ 52u8,
+ 163u8,
+ 59u8,
+ 169u8,
+ 39u8,
+ 90u8,
+ 197u8,
+ 133u8,
+ 217u8,
+ 211u8,
+ 21u8,
+ 240u8,
+ 173u8,
+ 131u8,
+ 85u8,
+ 205u8,
+ 222u8,
+ 253u8,
+ 227u8,
+ 26u8,
+ 250u8,
+ 40u8,
+ 208u8,
+ 233u8,
+ ];
+ pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool {
+ if log.topics.len() != 3usize {
+ return false;
+ }
+ if log.data.len() != 64usize {
+ return false;
+ }
+ return log.topics.get(0).expect("bounds already checked").as_ref()
+ == Self::TOPIC_ID;
+ }
+ pub fn decode(
+ log: &substreams_ethereum::pb::eth::v2::Log,
+ ) -> Result {
+ let mut values = ethabi::decode(
+ &[ethabi::ParamType::Address, ethabi::ParamType::Uint(256usize)],
+ log.data.as_ref(),
+ )
+ .map_err(|e| format!("unable to decode log.data: {:?}", e))?;
+ values.reverse();
+ Ok(Self {
+ token0: ethabi::decode(
+ &[ethabi::ParamType::Address],
+ log.topics[1usize].as_ref(),
+ )
+ .map_err(|e| {
+ format!(
+ "unable to decode param 'token0' from topic of type 'address': {:?}",
+ e
+ )
+ })?
+ .pop()
+ .expect(INTERNAL_ERR)
+ .into_address()
+ .expect(INTERNAL_ERR)
+ .as_bytes()
+ .to_vec(),
+ token1: ethabi::decode(
+ &[ethabi::ParamType::Address],
+ log.topics[2usize].as_ref(),
+ )
+ .map_err(|e| {
+ format!(
+ "unable to decode param 'token1' from topic of type 'address': {:?}",
+ e
+ )
+ })?
+ .pop()
+ .expect(INTERNAL_ERR)
+ .into_address()
+ .expect(INTERNAL_ERR)
+ .as_bytes()
+ .to_vec(),
+ pair: values
+ .pop()
+ .expect(INTERNAL_ERR)
+ .into_address()
+ .expect(INTERNAL_ERR)
+ .as_bytes()
+ .to_vec(),
+ param3: {
+ let mut v = [0 as u8; 32];
+ values
+ .pop()
+ .expect(INTERNAL_ERR)
+ .into_uint()
+ .expect(INTERNAL_ERR)
+ .to_big_endian(v.as_mut_slice());
+ substreams::scalar::BigInt::from_unsigned_bytes_be(&v)
+ },
+ })
+ }
+ }
+ impl substreams_ethereum::Event for PairCreated {
+ const NAME: &'static str = "PairCreated";
+ fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool {
+ Self::match_log(log)
+ }
+ fn decode(
+ log: &substreams_ethereum::pb::eth::v2::Log,
+ ) -> Result {
+ Self::decode(log)
+ }
+ }
+ }
\ No newline at end of file
diff --git a/substreams/ethereum-uniswap-v2/src/abi/mod.rs b/substreams/ethereum-uniswap-v2/src/abi/mod.rs
new file mode 100644
index 0000000..f743394
--- /dev/null
+++ b/substreams/ethereum-uniswap-v2/src/abi/mod.rs
@@ -0,0 +1,4 @@
+#![allow(clippy::all, clippy::pedantic, clippy::nursery)]
+
+pub mod factory;
+pub mod pool;
diff --git a/substreams/ethereum-uniswap-v2/src/abi/pool.rs b/substreams/ethereum-uniswap-v2/src/abi/pool.rs
new file mode 100644
index 0000000..4590901
--- /dev/null
+++ b/substreams/ethereum-uniswap-v2/src/abi/pool.rs
@@ -0,0 +1,3554 @@
+ const INTERNAL_ERR: &'static str = "`ethabi_derive` internal error";
+ /// Contract's functions.
+ #[allow(dead_code, unused_imports, unused_variables)]
+ pub mod functions {
+ use super::INTERNAL_ERR;
+ #[derive(Debug, Clone, PartialEq)]
+ pub struct DomainSeparator {}
+ impl DomainSeparator {
+ const METHOD_ID: [u8; 4] = [54u8, 68u8, 229u8, 21u8];
+ pub fn decode(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ Ok(Self {})
+ }
+ pub fn encode(&self) -> Vec {
+ let data = ethabi::encode(&[]);
+ let mut encoded = Vec::with_capacity(4 + data.len());
+ encoded.extend(Self::METHOD_ID);
+ encoded.extend(data);
+ encoded
+ }
+ pub fn output_call(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result<[u8; 32usize], String> {
+ Self::output(call.return_data.as_ref())
+ }
+ pub fn output(data: &[u8]) -> Result<[u8; 32usize], String> {
+ let mut values = ethabi::decode(
+ &[ethabi::ParamType::FixedBytes(32usize)],
+ data.as_ref(),
+ )
+ .map_err(|e| format!("unable to decode output data: {:?}", e))?;
+ Ok({
+ let mut result = [0u8; 32];
+ let v = values
+ .pop()
+ .expect("one output data should have existed")
+ .into_fixed_bytes()
+ .expect(INTERNAL_ERR);
+ result.copy_from_slice(&v);
+ result
+ })
+ }
+ pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool {
+ match call.input.get(0..4) {
+ Some(signature) => Self::METHOD_ID == signature,
+ None => false,
+ }
+ }
+ pub fn call(&self, address: Vec) -> Option<[u8; 32usize]> {
+ use substreams_ethereum::pb::eth::rpc;
+ let rpc_calls = rpc::RpcCalls {
+ calls: vec![
+ rpc::RpcCall { to_addr : address, data : self.encode(), }
+ ],
+ };
+ let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses;
+ let response = responses
+ .get(0)
+ .expect("one response should have existed");
+ if response.failed {
+ return None;
+ }
+ match Self::output(response.raw.as_ref()) {
+ Ok(data) => Some(data),
+ Err(err) => {
+ use substreams_ethereum::Function;
+ substreams::log::info!(
+ "Call output for function `{}` failed to decode with error: {}",
+ Self::NAME, err
+ );
+ None
+ }
+ }
+ }
+ }
+ impl substreams_ethereum::Function for DomainSeparator {
+ const NAME: &'static str = "DOMAIN_SEPARATOR";
+ fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool {
+ Self::match_call(call)
+ }
+ fn decode(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ Self::decode(call)
+ }
+ fn encode(&self) -> Vec {
+ self.encode()
+ }
+ }
+ impl substreams_ethereum::rpc::RPCDecodable<[u8; 32usize]> for DomainSeparator {
+ fn output(data: &[u8]) -> Result<[u8; 32usize], String> {
+ Self::output(data)
+ }
+ }
+ #[derive(Debug, Clone, PartialEq)]
+ pub struct MinimumLiquidity {}
+ impl MinimumLiquidity {
+ const METHOD_ID: [u8; 4] = [186u8, 154u8, 122u8, 86u8];
+ pub fn decode(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ Ok(Self {})
+ }
+ pub fn encode(&self) -> Vec {
+ let data = ethabi::encode(&[]);
+ let mut encoded = Vec::with_capacity(4 + data.len());
+ encoded.extend(Self::METHOD_ID);
+ encoded.extend(data);
+ encoded
+ }
+ pub fn output_call(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ Self::output(call.return_data.as_ref())
+ }
+ pub fn output(data: &[u8]) -> Result {
+ let mut values = ethabi::decode(
+ &[ethabi::ParamType::Uint(256usize)],
+ data.as_ref(),
+ )
+ .map_err(|e| format!("unable to decode output data: {:?}", e))?;
+ Ok({
+ let mut v = [0 as u8; 32];
+ values
+ .pop()
+ .expect("one output data should have existed")
+ .into_uint()
+ .expect(INTERNAL_ERR)
+ .to_big_endian(v.as_mut_slice());
+ substreams::scalar::BigInt::from_unsigned_bytes_be(&v)
+ })
+ }
+ pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool {
+ match call.input.get(0..4) {
+ Some(signature) => Self::METHOD_ID == signature,
+ None => false,
+ }
+ }
+ pub fn call(&self, address: Vec) -> Option {
+ use substreams_ethereum::pb::eth::rpc;
+ let rpc_calls = rpc::RpcCalls {
+ calls: vec![
+ rpc::RpcCall { to_addr : address, data : self.encode(), }
+ ],
+ };
+ let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses;
+ let response = responses
+ .get(0)
+ .expect("one response should have existed");
+ if response.failed {
+ return None;
+ }
+ match Self::output(response.raw.as_ref()) {
+ Ok(data) => Some(data),
+ Err(err) => {
+ use substreams_ethereum::Function;
+ substreams::log::info!(
+ "Call output for function `{}` failed to decode with error: {}",
+ Self::NAME, err
+ );
+ None
+ }
+ }
+ }
+ }
+ impl substreams_ethereum::Function for MinimumLiquidity {
+ const NAME: &'static str = "MINIMUM_LIQUIDITY";
+ fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool {
+ Self::match_call(call)
+ }
+ fn decode(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ Self::decode(call)
+ }
+ fn encode(&self) -> Vec {
+ self.encode()
+ }
+ }
+ impl substreams_ethereum::rpc::RPCDecodable
+ for MinimumLiquidity {
+ fn output(data: &[u8]) -> Result {
+ Self::output(data)
+ }
+ }
+ #[derive(Debug, Clone, PartialEq)]
+ pub struct PermitTypehash {}
+ impl PermitTypehash {
+ const METHOD_ID: [u8; 4] = [48u8, 173u8, 248u8, 31u8];
+ pub fn decode(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ Ok(Self {})
+ }
+ pub fn encode(&self) -> Vec {
+ let data = ethabi::encode(&[]);
+ let mut encoded = Vec::with_capacity(4 + data.len());
+ encoded.extend(Self::METHOD_ID);
+ encoded.extend(data);
+ encoded
+ }
+ pub fn output_call(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result<[u8; 32usize], String> {
+ Self::output(call.return_data.as_ref())
+ }
+ pub fn output(data: &[u8]) -> Result<[u8; 32usize], String> {
+ let mut values = ethabi::decode(
+ &[ethabi::ParamType::FixedBytes(32usize)],
+ data.as_ref(),
+ )
+ .map_err(|e| format!("unable to decode output data: {:?}", e))?;
+ Ok({
+ let mut result = [0u8; 32];
+ let v = values
+ .pop()
+ .expect("one output data should have existed")
+ .into_fixed_bytes()
+ .expect(INTERNAL_ERR);
+ result.copy_from_slice(&v);
+ result
+ })
+ }
+ pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool {
+ match call.input.get(0..4) {
+ Some(signature) => Self::METHOD_ID == signature,
+ None => false,
+ }
+ }
+ pub fn call(&self, address: Vec) -> Option<[u8; 32usize]> {
+ use substreams_ethereum::pb::eth::rpc;
+ let rpc_calls = rpc::RpcCalls {
+ calls: vec![
+ rpc::RpcCall { to_addr : address, data : self.encode(), }
+ ],
+ };
+ let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses;
+ let response = responses
+ .get(0)
+ .expect("one response should have existed");
+ if response.failed {
+ return None;
+ }
+ match Self::output(response.raw.as_ref()) {
+ Ok(data) => Some(data),
+ Err(err) => {
+ use substreams_ethereum::Function;
+ substreams::log::info!(
+ "Call output for function `{}` failed to decode with error: {}",
+ Self::NAME, err
+ );
+ None
+ }
+ }
+ }
+ }
+ impl substreams_ethereum::Function for PermitTypehash {
+ const NAME: &'static str = "PERMIT_TYPEHASH";
+ fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool {
+ Self::match_call(call)
+ }
+ fn decode(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ Self::decode(call)
+ }
+ fn encode(&self) -> Vec {
+ self.encode()
+ }
+ }
+ impl substreams_ethereum::rpc::RPCDecodable<[u8; 32usize]> for PermitTypehash {
+ fn output(data: &[u8]) -> Result<[u8; 32usize], String> {
+ Self::output(data)
+ }
+ }
+ #[derive(Debug, Clone, PartialEq)]
+ pub struct Allowance {
+ pub param0: Vec,
+ pub param1: Vec,
+ }
+ impl Allowance {
+ const METHOD_ID: [u8; 4] = [221u8, 98u8, 237u8, 62u8];
+ pub fn decode(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ let maybe_data = call.input.get(4..);
+ if maybe_data.is_none() {
+ return Err("no data to decode".to_string());
+ }
+ let mut values = ethabi::decode(
+ &[ethabi::ParamType::Address, ethabi::ParamType::Address],
+ maybe_data.unwrap(),
+ )
+ .map_err(|e| format!("unable to decode call.input: {:?}", e))?;
+ values.reverse();
+ Ok(Self {
+ param0: values
+ .pop()
+ .expect(INTERNAL_ERR)
+ .into_address()
+ .expect(INTERNAL_ERR)
+ .as_bytes()
+ .to_vec(),
+ param1: values
+ .pop()
+ .expect(INTERNAL_ERR)
+ .into_address()
+ .expect(INTERNAL_ERR)
+ .as_bytes()
+ .to_vec(),
+ })
+ }
+ pub fn encode(&self) -> Vec {
+ let data = ethabi::encode(
+ &[
+ ethabi::Token::Address(
+ ethabi::Address::from_slice(&self.param0),
+ ),
+ ethabi::Token::Address(ethabi::Address::from_slice(&self.param1)),
+ ],
+ );
+ let mut encoded = Vec::with_capacity(4 + data.len());
+ encoded.extend(Self::METHOD_ID);
+ encoded.extend(data);
+ encoded
+ }
+ pub fn output_call(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ Self::output(call.return_data.as_ref())
+ }
+ pub fn output(data: &[u8]) -> Result {
+ let mut values = ethabi::decode(
+ &[ethabi::ParamType::Uint(256usize)],
+ data.as_ref(),
+ )
+ .map_err(|e| format!("unable to decode output data: {:?}", e))?;
+ Ok({
+ let mut v = [0 as u8; 32];
+ values
+ .pop()
+ .expect("one output data should have existed")
+ .into_uint()
+ .expect(INTERNAL_ERR)
+ .to_big_endian(v.as_mut_slice());
+ substreams::scalar::BigInt::from_unsigned_bytes_be(&v)
+ })
+ }
+ pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool {
+ match call.input.get(0..4) {
+ Some(signature) => Self::METHOD_ID == signature,
+ None => false,
+ }
+ }
+ pub fn call(&self, address: Vec) -> Option {
+ use substreams_ethereum::pb::eth::rpc;
+ let rpc_calls = rpc::RpcCalls {
+ calls: vec![
+ rpc::RpcCall { to_addr : address, data : self.encode(), }
+ ],
+ };
+ let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses;
+ let response = responses
+ .get(0)
+ .expect("one response should have existed");
+ if response.failed {
+ return None;
+ }
+ match Self::output(response.raw.as_ref()) {
+ Ok(data) => Some(data),
+ Err(err) => {
+ use substreams_ethereum::Function;
+ substreams::log::info!(
+ "Call output for function `{}` failed to decode with error: {}",
+ Self::NAME, err
+ );
+ None
+ }
+ }
+ }
+ }
+ impl substreams_ethereum::Function for Allowance {
+ const NAME: &'static str = "allowance";
+ fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool {
+ Self::match_call(call)
+ }
+ fn decode(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ Self::decode(call)
+ }
+ fn encode(&self) -> Vec {
+ self.encode()
+ }
+ }
+ impl substreams_ethereum::rpc::RPCDecodable
+ for Allowance {
+ fn output(data: &[u8]) -> Result {
+ Self::output(data)
+ }
+ }
+ #[derive(Debug, Clone, PartialEq)]
+ pub struct Approve {
+ pub spender: Vec,
+ pub value: substreams::scalar::BigInt,
+ }
+ impl Approve {
+ const METHOD_ID: [u8; 4] = [9u8, 94u8, 167u8, 179u8];
+ pub fn decode(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ let maybe_data = call.input.get(4..);
+ if maybe_data.is_none() {
+ return Err("no data to decode".to_string());
+ }
+ let mut values = ethabi::decode(
+ &[ethabi::ParamType::Address, ethabi::ParamType::Uint(256usize)],
+ maybe_data.unwrap(),
+ )
+ .map_err(|e| format!("unable to decode call.input: {:?}", e))?;
+ values.reverse();
+ Ok(Self {
+ spender: values
+ .pop()
+ .expect(INTERNAL_ERR)
+ .into_address()
+ .expect(INTERNAL_ERR)
+ .as_bytes()
+ .to_vec(),
+ value: {
+ let mut v = [0 as u8; 32];
+ values
+ .pop()
+ .expect(INTERNAL_ERR)
+ .into_uint()
+ .expect(INTERNAL_ERR)
+ .to_big_endian(v.as_mut_slice());
+ substreams::scalar::BigInt::from_unsigned_bytes_be(&v)
+ },
+ })
+ }
+ pub fn encode(&self) -> Vec {
+ let data = ethabi::encode(
+ &[
+ ethabi::Token::Address(
+ ethabi::Address::from_slice(&self.spender),
+ ),
+ ethabi::Token::Uint(
+ ethabi::Uint::from_big_endian(
+ match self.value.clone().to_bytes_be() {
+ (num_bigint::Sign::Plus, bytes) => bytes,
+ (num_bigint::Sign::NoSign, bytes) => bytes,
+ (num_bigint::Sign::Minus, _) => {
+ panic!("negative numbers are not supported")
+ }
+ }
+ .as_slice(),
+ ),
+ ),
+ ],
+ );
+ let mut encoded = Vec::with_capacity(4 + data.len());
+ encoded.extend(Self::METHOD_ID);
+ encoded.extend(data);
+ encoded
+ }
+ pub fn output_call(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ Self::output(call.return_data.as_ref())
+ }
+ pub fn output(data: &[u8]) -> Result {
+ let mut values = ethabi::decode(
+ &[ethabi::ParamType::Bool],
+ data.as_ref(),
+ )
+ .map_err(|e| format!("unable to decode output data: {:?}", e))?;
+ Ok(
+ values
+ .pop()
+ .expect("one output data should have existed")
+ .into_bool()
+ .expect(INTERNAL_ERR),
+ )
+ }
+ pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool {
+ match call.input.get(0..4) {
+ Some(signature) => Self::METHOD_ID == signature,
+ None => false,
+ }
+ }
+ pub fn call(&self, address: Vec) -> Option {
+ use substreams_ethereum::pb::eth::rpc;
+ let rpc_calls = rpc::RpcCalls {
+ calls: vec![
+ rpc::RpcCall { to_addr : address, data : self.encode(), }
+ ],
+ };
+ let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses;
+ let response = responses
+ .get(0)
+ .expect("one response should have existed");
+ if response.failed {
+ return None;
+ }
+ match Self::output(response.raw.as_ref()) {
+ Ok(data) => Some(data),
+ Err(err) => {
+ use substreams_ethereum::Function;
+ substreams::log::info!(
+ "Call output for function `{}` failed to decode with error: {}",
+ Self::NAME, err
+ );
+ None
+ }
+ }
+ }
+ }
+ impl substreams_ethereum::Function for Approve {
+ const NAME: &'static str = "approve";
+ fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool {
+ Self::match_call(call)
+ }
+ fn decode(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ Self::decode(call)
+ }
+ fn encode(&self) -> Vec {
+ self.encode()
+ }
+ }
+ impl substreams_ethereum::rpc::RPCDecodable for Approve {
+ fn output(data: &[u8]) -> Result {
+ Self::output(data)
+ }
+ }
+ #[derive(Debug, Clone, PartialEq)]
+ pub struct BalanceOf {
+ pub param0: Vec,
+ }
+ impl BalanceOf {
+ const METHOD_ID: [u8; 4] = [112u8, 160u8, 130u8, 49u8];
+ pub fn decode(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ let maybe_data = call.input.get(4..);
+ if maybe_data.is_none() {
+ return Err("no data to decode".to_string());
+ }
+ let mut values = ethabi::decode(
+ &[ethabi::ParamType::Address],
+ maybe_data.unwrap(),
+ )
+ .map_err(|e| format!("unable to decode call.input: {:?}", e))?;
+ values.reverse();
+ Ok(Self {
+ param0: values
+ .pop()
+ .expect(INTERNAL_ERR)
+ .into_address()
+ .expect(INTERNAL_ERR)
+ .as_bytes()
+ .to_vec(),
+ })
+ }
+ pub fn encode(&self) -> Vec {
+ let data = ethabi::encode(
+ &[ethabi::Token::Address(ethabi::Address::from_slice(&self.param0))],
+ );
+ let mut encoded = Vec::with_capacity(4 + data.len());
+ encoded.extend(Self::METHOD_ID);
+ encoded.extend(data);
+ encoded
+ }
+ pub fn output_call(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ Self::output(call.return_data.as_ref())
+ }
+ pub fn output(data: &[u8]) -> Result {
+ let mut values = ethabi::decode(
+ &[ethabi::ParamType::Uint(256usize)],
+ data.as_ref(),
+ )
+ .map_err(|e| format!("unable to decode output data: {:?}", e))?;
+ Ok({
+ let mut v = [0 as u8; 32];
+ values
+ .pop()
+ .expect("one output data should have existed")
+ .into_uint()
+ .expect(INTERNAL_ERR)
+ .to_big_endian(v.as_mut_slice());
+ substreams::scalar::BigInt::from_unsigned_bytes_be(&v)
+ })
+ }
+ pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool {
+ match call.input.get(0..4) {
+ Some(signature) => Self::METHOD_ID == signature,
+ None => false,
+ }
+ }
+ pub fn call(&self, address: Vec) -> Option {
+ use substreams_ethereum::pb::eth::rpc;
+ let rpc_calls = rpc::RpcCalls {
+ calls: vec![
+ rpc::RpcCall { to_addr : address, data : self.encode(), }
+ ],
+ };
+ let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses;
+ let response = responses
+ .get(0)
+ .expect("one response should have existed");
+ if response.failed {
+ return None;
+ }
+ match Self::output(response.raw.as_ref()) {
+ Ok(data) => Some(data),
+ Err(err) => {
+ use substreams_ethereum::Function;
+ substreams::log::info!(
+ "Call output for function `{}` failed to decode with error: {}",
+ Self::NAME, err
+ );
+ None
+ }
+ }
+ }
+ }
+ impl substreams_ethereum::Function for BalanceOf {
+ const NAME: &'static str = "balanceOf";
+ fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool {
+ Self::match_call(call)
+ }
+ fn decode(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ Self::decode(call)
+ }
+ fn encode(&self) -> Vec {
+ self.encode()
+ }
+ }
+ impl substreams_ethereum::rpc::RPCDecodable
+ for BalanceOf {
+ fn output(data: &[u8]) -> Result {
+ Self::output(data)
+ }
+ }
+ #[derive(Debug, Clone, PartialEq)]
+ pub struct Burn {
+ pub to: Vec,
+ }
+ impl Burn {
+ const METHOD_ID: [u8; 4] = [137u8, 175u8, 203u8, 68u8];
+ pub fn decode(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ let maybe_data = call.input.get(4..);
+ if maybe_data.is_none() {
+ return Err("no data to decode".to_string());
+ }
+ let mut values = ethabi::decode(
+ &[ethabi::ParamType::Address],
+ maybe_data.unwrap(),
+ )
+ .map_err(|e| format!("unable to decode call.input: {:?}", e))?;
+ values.reverse();
+ Ok(Self {
+ to: values
+ .pop()
+ .expect(INTERNAL_ERR)
+ .into_address()
+ .expect(INTERNAL_ERR)
+ .as_bytes()
+ .to_vec(),
+ })
+ }
+ pub fn encode(&self) -> Vec {
+ let data = ethabi::encode(
+ &[ethabi::Token::Address(ethabi::Address::from_slice(&self.to))],
+ );
+ let mut encoded = Vec::with_capacity(4 + data.len());
+ encoded.extend(Self::METHOD_ID);
+ encoded.extend(data);
+ encoded
+ }
+ pub fn output_call(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result<
+ (substreams::scalar::BigInt, substreams::scalar::BigInt),
+ String,
+ > {
+ Self::output(call.return_data.as_ref())
+ }
+ pub fn output(
+ data: &[u8],
+ ) -> Result<
+ (substreams::scalar::BigInt, substreams::scalar::BigInt),
+ String,
+ > {
+ let mut values = ethabi::decode(
+ &[
+ ethabi::ParamType::Uint(256usize),
+ ethabi::ParamType::Uint(256usize),
+ ],
+ data.as_ref(),
+ )
+ .map_err(|e| format!("unable to decode output data: {:?}", e))?;
+ values.reverse();
+ Ok((
+ {
+ let mut v = [0 as u8; 32];
+ values
+ .pop()
+ .expect(INTERNAL_ERR)
+ .into_uint()
+ .expect(INTERNAL_ERR)
+ .to_big_endian(v.as_mut_slice());
+ substreams::scalar::BigInt::from_unsigned_bytes_be(&v)
+ },
+ {
+ let mut v = [0 as u8; 32];
+ values
+ .pop()
+ .expect(INTERNAL_ERR)
+ .into_uint()
+ .expect(INTERNAL_ERR)
+ .to_big_endian(v.as_mut_slice());
+ substreams::scalar::BigInt::from_unsigned_bytes_be(&v)
+ },
+ ))
+ }
+ pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool {
+ match call.input.get(0..4) {
+ Some(signature) => Self::METHOD_ID == signature,
+ None => false,
+ }
+ }
+ pub fn call(
+ &self,
+ address: Vec,
+ ) -> Option<(substreams::scalar::BigInt, substreams::scalar::BigInt)> {
+ use substreams_ethereum::pb::eth::rpc;
+ let rpc_calls = rpc::RpcCalls {
+ calls: vec![
+ rpc::RpcCall { to_addr : address, data : self.encode(), }
+ ],
+ };
+ let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses;
+ let response = responses
+ .get(0)
+ .expect("one response should have existed");
+ if response.failed {
+ return None;
+ }
+ match Self::output(response.raw.as_ref()) {
+ Ok(data) => Some(data),
+ Err(err) => {
+ use substreams_ethereum::Function;
+ substreams::log::info!(
+ "Call output for function `{}` failed to decode with error: {}",
+ Self::NAME, err
+ );
+ None
+ }
+ }
+ }
+ }
+ impl substreams_ethereum::Function for Burn {
+ const NAME: &'static str = "burn";
+ fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool {
+ Self::match_call(call)
+ }
+ fn decode(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ Self::decode(call)
+ }
+ fn encode(&self) -> Vec {
+ self.encode()
+ }
+ }
+ impl substreams_ethereum::rpc::RPCDecodable<
+ (substreams::scalar::BigInt, substreams::scalar::BigInt),
+ > for Burn {
+ fn output(
+ data: &[u8],
+ ) -> Result<
+ (substreams::scalar::BigInt, substreams::scalar::BigInt),
+ String,
+ > {
+ Self::output(data)
+ }
+ }
+ #[derive(Debug, Clone, PartialEq)]
+ pub struct Decimals {}
+ impl Decimals {
+ const METHOD_ID: [u8; 4] = [49u8, 60u8, 229u8, 103u8];
+ pub fn decode(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ Ok(Self {})
+ }
+ pub fn encode(&self) -> Vec {
+ let data = ethabi::encode(&[]);
+ let mut encoded = Vec::with_capacity(4 + data.len());
+ encoded.extend(Self::METHOD_ID);
+ encoded.extend(data);
+ encoded
+ }
+ pub fn output_call(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ Self::output(call.return_data.as_ref())
+ }
+ pub fn output(data: &[u8]) -> Result {
+ let mut values = ethabi::decode(
+ &[ethabi::ParamType::Uint(8usize)],
+ data.as_ref(),
+ )
+ .map_err(|e| format!("unable to decode output data: {:?}", e))?;
+ Ok({
+ let mut v = [0 as u8; 32];
+ values
+ .pop()
+ .expect("one output data should have existed")
+ .into_uint()
+ .expect(INTERNAL_ERR)
+ .to_big_endian(v.as_mut_slice());
+ substreams::scalar::BigInt::from_unsigned_bytes_be(&v)
+ })
+ }
+ pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool {
+ match call.input.get(0..4) {
+ Some(signature) => Self::METHOD_ID == signature,
+ None => false,
+ }
+ }
+ pub fn call(&self, address: Vec) -> Option {
+ use substreams_ethereum::pb::eth::rpc;
+ let rpc_calls = rpc::RpcCalls {
+ calls: vec![
+ rpc::RpcCall { to_addr : address, data : self.encode(), }
+ ],
+ };
+ let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses;
+ let response = responses
+ .get(0)
+ .expect("one response should have existed");
+ if response.failed {
+ return None;
+ }
+ match Self::output(response.raw.as_ref()) {
+ Ok(data) => Some(data),
+ Err(err) => {
+ use substreams_ethereum::Function;
+ substreams::log::info!(
+ "Call output for function `{}` failed to decode with error: {}",
+ Self::NAME, err
+ );
+ None
+ }
+ }
+ }
+ }
+ impl substreams_ethereum::Function for Decimals {
+ const NAME: &'static str = "decimals";
+ fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool {
+ Self::match_call(call)
+ }
+ fn decode(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ Self::decode(call)
+ }
+ fn encode(&self) -> Vec {
+ self.encode()
+ }
+ }
+ impl substreams_ethereum::rpc::RPCDecodable
+ for Decimals {
+ fn output(data: &[u8]) -> Result {
+ Self::output(data)
+ }
+ }
+ #[derive(Debug, Clone, PartialEq)]
+ pub struct Factory {}
+ impl Factory {
+ const METHOD_ID: [u8; 4] = [196u8, 90u8, 1u8, 85u8];
+ pub fn decode(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ Ok(Self {})
+ }
+ pub fn encode(&self) -> Vec {
+ let data = ethabi::encode(&[]);
+ let mut encoded = Vec::with_capacity(4 + data.len());
+ encoded.extend(Self::METHOD_ID);
+ encoded.extend(data);
+ encoded
+ }
+ pub fn output_call(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result, String> {
+ Self::output(call.return_data.as_ref())
+ }
+ pub fn output(data: &[u8]) -> Result, String> {
+ let mut values = ethabi::decode(
+ &[ethabi::ParamType::Address],
+ data.as_ref(),
+ )
+ .map_err(|e| format!("unable to decode output data: {:?}", e))?;
+ Ok(
+ values
+ .pop()
+ .expect("one output data should have existed")
+ .into_address()
+ .expect(INTERNAL_ERR)
+ .as_bytes()
+ .to_vec(),
+ )
+ }
+ pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool {
+ match call.input.get(0..4) {
+ Some(signature) => Self::METHOD_ID == signature,
+ None => false,
+ }
+ }
+ pub fn call(&self, address: Vec) -> Option> {
+ use substreams_ethereum::pb::eth::rpc;
+ let rpc_calls = rpc::RpcCalls {
+ calls: vec![
+ rpc::RpcCall { to_addr : address, data : self.encode(), }
+ ],
+ };
+ let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses;
+ let response = responses
+ .get(0)
+ .expect("one response should have existed");
+ if response.failed {
+ return None;
+ }
+ match Self::output(response.raw.as_ref()) {
+ Ok(data) => Some(data),
+ Err(err) => {
+ use substreams_ethereum::Function;
+ substreams::log::info!(
+ "Call output for function `{}` failed to decode with error: {}",
+ Self::NAME, err
+ );
+ None
+ }
+ }
+ }
+ }
+ impl substreams_ethereum::Function for Factory {
+ const NAME: &'static str = "factory";
+ fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool {
+ Self::match_call(call)
+ }
+ fn decode(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ Self::decode(call)
+ }
+ fn encode(&self) -> Vec {
+ self.encode()
+ }
+ }
+ impl substreams_ethereum::rpc::RPCDecodable> for Factory {
+ fn output(data: &[u8]) -> Result, String> {
+ Self::output(data)
+ }
+ }
+ #[derive(Debug, Clone, PartialEq)]
+ pub struct GetReserves {}
+ impl GetReserves {
+ const METHOD_ID: [u8; 4] = [9u8, 2u8, 241u8, 172u8];
+ pub fn decode(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ Ok(Self {})
+ }
+ pub fn encode(&self) -> Vec {
+ let data = ethabi::encode(&[]);
+ let mut encoded = Vec::with_capacity(4 + data.len());
+ encoded.extend(Self::METHOD_ID);
+ encoded.extend(data);
+ encoded
+ }
+ pub fn output_call(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result<
+ (
+ substreams::scalar::BigInt,
+ substreams::scalar::BigInt,
+ substreams::scalar::BigInt,
+ ),
+ String,
+ > {
+ Self::output(call.return_data.as_ref())
+ }
+ pub fn output(
+ data: &[u8],
+ ) -> Result<
+ (
+ substreams::scalar::BigInt,
+ substreams::scalar::BigInt,
+ substreams::scalar::BigInt,
+ ),
+ String,
+ > {
+ let mut values = ethabi::decode(
+ &[
+ ethabi::ParamType::Uint(112usize),
+ ethabi::ParamType::Uint(112usize),
+ ethabi::ParamType::Uint(32usize),
+ ],
+ data.as_ref(),
+ )
+ .map_err(|e| format!("unable to decode output data: {:?}", e))?;
+ values.reverse();
+ Ok((
+ {
+ let mut v = [0 as u8; 32];
+ values
+ .pop()
+ .expect(INTERNAL_ERR)
+ .into_uint()
+ .expect(INTERNAL_ERR)
+ .to_big_endian(v.as_mut_slice());
+ substreams::scalar::BigInt::from_unsigned_bytes_be(&v)
+ },
+ {
+ let mut v = [0 as u8; 32];
+ values
+ .pop()
+ .expect(INTERNAL_ERR)
+ .into_uint()
+ .expect(INTERNAL_ERR)
+ .to_big_endian(v.as_mut_slice());
+ substreams::scalar::BigInt::from_unsigned_bytes_be(&v)
+ },
+ {
+ let mut v = [0 as u8; 32];
+ values
+ .pop()
+ .expect(INTERNAL_ERR)
+ .into_uint()
+ .expect(INTERNAL_ERR)
+ .to_big_endian(v.as_mut_slice());
+ substreams::scalar::BigInt::from_unsigned_bytes_be(&v)
+ },
+ ))
+ }
+ pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool {
+ match call.input.get(0..4) {
+ Some(signature) => Self::METHOD_ID == signature,
+ None => false,
+ }
+ }
+ pub fn call(
+ &self,
+ address: Vec,
+ ) -> Option<
+ (
+ substreams::scalar::BigInt,
+ substreams::scalar::BigInt,
+ substreams::scalar::BigInt,
+ ),
+ > {
+ use substreams_ethereum::pb::eth::rpc;
+ let rpc_calls = rpc::RpcCalls {
+ calls: vec![
+ rpc::RpcCall { to_addr : address, data : self.encode(), }
+ ],
+ };
+ let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses;
+ let response = responses
+ .get(0)
+ .expect("one response should have existed");
+ if response.failed {
+ return None;
+ }
+ match Self::output(response.raw.as_ref()) {
+ Ok(data) => Some(data),
+ Err(err) => {
+ use substreams_ethereum::Function;
+ substreams::log::info!(
+ "Call output for function `{}` failed to decode with error: {}",
+ Self::NAME, err
+ );
+ None
+ }
+ }
+ }
+ }
+ impl substreams_ethereum::Function for GetReserves {
+ const NAME: &'static str = "getReserves";
+ fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool {
+ Self::match_call(call)
+ }
+ fn decode(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ Self::decode(call)
+ }
+ fn encode(&self) -> Vec {
+ self.encode()
+ }
+ }
+ impl substreams_ethereum::rpc::RPCDecodable<
+ (
+ substreams::scalar::BigInt,
+ substreams::scalar::BigInt,
+ substreams::scalar::BigInt,
+ ),
+ > for GetReserves {
+ fn output(
+ data: &[u8],
+ ) -> Result<
+ (
+ substreams::scalar::BigInt,
+ substreams::scalar::BigInt,
+ substreams::scalar::BigInt,
+ ),
+ String,
+ > {
+ Self::output(data)
+ }
+ }
+ #[derive(Debug, Clone, PartialEq)]
+ pub struct Initialize {
+ pub token0: Vec,
+ pub token1: Vec,
+ }
+ impl Initialize {
+ const METHOD_ID: [u8; 4] = [72u8, 92u8, 201u8, 85u8];
+ pub fn decode(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ let maybe_data = call.input.get(4..);
+ if maybe_data.is_none() {
+ return Err("no data to decode".to_string());
+ }
+ let mut values = ethabi::decode(
+ &[ethabi::ParamType::Address, ethabi::ParamType::Address],
+ maybe_data.unwrap(),
+ )
+ .map_err(|e| format!("unable to decode call.input: {:?}", e))?;
+ values.reverse();
+ Ok(Self {
+ token0: values
+ .pop()
+ .expect(INTERNAL_ERR)
+ .into_address()
+ .expect(INTERNAL_ERR)
+ .as_bytes()
+ .to_vec(),
+ token1: values
+ .pop()
+ .expect(INTERNAL_ERR)
+ .into_address()
+ .expect(INTERNAL_ERR)
+ .as_bytes()
+ .to_vec(),
+ })
+ }
+ pub fn encode(&self) -> Vec {
+ let data = ethabi::encode(
+ &[
+ ethabi::Token::Address(
+ ethabi::Address::from_slice(&self.token0),
+ ),
+ ethabi::Token::Address(ethabi::Address::from_slice(&self.token1)),
+ ],
+ );
+ let mut encoded = Vec::with_capacity(4 + data.len());
+ encoded.extend(Self::METHOD_ID);
+ encoded.extend(data);
+ encoded
+ }
+ pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool {
+ match call.input.get(0..4) {
+ Some(signature) => Self::METHOD_ID == signature,
+ None => false,
+ }
+ }
+ }
+ impl substreams_ethereum::Function for Initialize {
+ const NAME: &'static str = "initialize";
+ fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool {
+ Self::match_call(call)
+ }
+ fn decode(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ Self::decode(call)
+ }
+ fn encode(&self) -> Vec {
+ self.encode()
+ }
+ }
+ #[derive(Debug, Clone, PartialEq)]
+ pub struct KLast {}
+ impl KLast {
+ const METHOD_ID: [u8; 4] = [116u8, 100u8, 252u8, 61u8];
+ pub fn decode(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ Ok(Self {})
+ }
+ pub fn encode(&self) -> Vec {
+ let data = ethabi::encode(&[]);
+ let mut encoded = Vec::with_capacity(4 + data.len());
+ encoded.extend(Self::METHOD_ID);
+ encoded.extend(data);
+ encoded
+ }
+ pub fn output_call(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ Self::output(call.return_data.as_ref())
+ }
+ pub fn output(data: &[u8]) -> Result {
+ let mut values = ethabi::decode(
+ &[ethabi::ParamType::Uint(256usize)],
+ data.as_ref(),
+ )
+ .map_err(|e| format!("unable to decode output data: {:?}", e))?;
+ Ok({
+ let mut v = [0 as u8; 32];
+ values
+ .pop()
+ .expect("one output data should have existed")
+ .into_uint()
+ .expect(INTERNAL_ERR)
+ .to_big_endian(v.as_mut_slice());
+ substreams::scalar::BigInt::from_unsigned_bytes_be(&v)
+ })
+ }
+ pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool {
+ match call.input.get(0..4) {
+ Some(signature) => Self::METHOD_ID == signature,
+ None => false,
+ }
+ }
+ pub fn call(&self, address: Vec) -> Option {
+ use substreams_ethereum::pb::eth::rpc;
+ let rpc_calls = rpc::RpcCalls {
+ calls: vec![
+ rpc::RpcCall { to_addr : address, data : self.encode(), }
+ ],
+ };
+ let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses;
+ let response = responses
+ .get(0)
+ .expect("one response should have existed");
+ if response.failed {
+ return None;
+ }
+ match Self::output(response.raw.as_ref()) {
+ Ok(data) => Some(data),
+ Err(err) => {
+ use substreams_ethereum::Function;
+ substreams::log::info!(
+ "Call output for function `{}` failed to decode with error: {}",
+ Self::NAME, err
+ );
+ None
+ }
+ }
+ }
+ }
+ impl substreams_ethereum::Function for KLast {
+ const NAME: &'static str = "kLast";
+ fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool {
+ Self::match_call(call)
+ }
+ fn decode(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ Self::decode(call)
+ }
+ fn encode(&self) -> Vec {
+ self.encode()
+ }
+ }
+ impl substreams_ethereum::rpc::RPCDecodable
+ for KLast {
+ fn output(data: &[u8]) -> Result {
+ Self::output(data)
+ }
+ }
+ #[derive(Debug, Clone, PartialEq)]
+ pub struct Mint {
+ pub to: Vec,
+ }
+ impl Mint {
+ const METHOD_ID: [u8; 4] = [106u8, 98u8, 120u8, 66u8];
+ pub fn decode(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ let maybe_data = call.input.get(4..);
+ if maybe_data.is_none() {
+ return Err("no data to decode".to_string());
+ }
+ let mut values = ethabi::decode(
+ &[ethabi::ParamType::Address],
+ maybe_data.unwrap(),
+ )
+ .map_err(|e| format!("unable to decode call.input: {:?}", e))?;
+ values.reverse();
+ Ok(Self {
+ to: values
+ .pop()
+ .expect(INTERNAL_ERR)
+ .into_address()
+ .expect(INTERNAL_ERR)
+ .as_bytes()
+ .to_vec(),
+ })
+ }
+ pub fn encode(&self) -> Vec {
+ let data = ethabi::encode(
+ &[ethabi::Token::Address(ethabi::Address::from_slice(&self.to))],
+ );
+ let mut encoded = Vec::with_capacity(4 + data.len());
+ encoded.extend(Self::METHOD_ID);
+ encoded.extend(data);
+ encoded
+ }
+ pub fn output_call(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ Self::output(call.return_data.as_ref())
+ }
+ pub fn output(data: &[u8]) -> Result {
+ let mut values = ethabi::decode(
+ &[ethabi::ParamType::Uint(256usize)],
+ data.as_ref(),
+ )
+ .map_err(|e| format!("unable to decode output data: {:?}", e))?;
+ Ok({
+ let mut v = [0 as u8; 32];
+ values
+ .pop()
+ .expect("one output data should have existed")
+ .into_uint()
+ .expect(INTERNAL_ERR)
+ .to_big_endian(v.as_mut_slice());
+ substreams::scalar::BigInt::from_unsigned_bytes_be(&v)
+ })
+ }
+ pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool {
+ match call.input.get(0..4) {
+ Some(signature) => Self::METHOD_ID == signature,
+ None => false,
+ }
+ }
+ pub fn call(&self, address: Vec) -> Option {
+ use substreams_ethereum::pb::eth::rpc;
+ let rpc_calls = rpc::RpcCalls {
+ calls: vec![
+ rpc::RpcCall { to_addr : address, data : self.encode(), }
+ ],
+ };
+ let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses;
+ let response = responses
+ .get(0)
+ .expect("one response should have existed");
+ if response.failed {
+ return None;
+ }
+ match Self::output(response.raw.as_ref()) {
+ Ok(data) => Some(data),
+ Err(err) => {
+ use substreams_ethereum::Function;
+ substreams::log::info!(
+ "Call output for function `{}` failed to decode with error: {}",
+ Self::NAME, err
+ );
+ None
+ }
+ }
+ }
+ }
+ impl substreams_ethereum::Function for Mint {
+ const NAME: &'static str = "mint";
+ fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool {
+ Self::match_call(call)
+ }
+ fn decode(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ Self::decode(call)
+ }
+ fn encode(&self) -> Vec {
+ self.encode()
+ }
+ }
+ impl substreams_ethereum::rpc::RPCDecodable
+ for Mint {
+ fn output(data: &[u8]) -> Result {
+ Self::output(data)
+ }
+ }
+ #[derive(Debug, Clone, PartialEq)]
+ pub struct Name {}
+ impl Name {
+ const METHOD_ID: [u8; 4] = [6u8, 253u8, 222u8, 3u8];
+ pub fn decode(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ Ok(Self {})
+ }
+ pub fn encode(&self) -> Vec {
+ let data = ethabi::encode(&[]);
+ let mut encoded = Vec::with_capacity(4 + data.len());
+ encoded.extend(Self::METHOD_ID);
+ encoded.extend(data);
+ encoded
+ }
+ pub fn output_call(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ Self::output(call.return_data.as_ref())
+ }
+ pub fn output(data: &[u8]) -> Result {
+ let mut values = ethabi::decode(
+ &[ethabi::ParamType::String],
+ data.as_ref(),
+ )
+ .map_err(|e| format!("unable to decode output data: {:?}", e))?;
+ Ok(
+ values
+ .pop()
+ .expect("one output data should have existed")
+ .into_string()
+ .expect(INTERNAL_ERR),
+ )
+ }
+ pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool {
+ match call.input.get(0..4) {
+ Some(signature) => Self::METHOD_ID == signature,
+ None => false,
+ }
+ }
+ pub fn call(&self, address: Vec) -> Option {
+ use substreams_ethereum::pb::eth::rpc;
+ let rpc_calls = rpc::RpcCalls {
+ calls: vec![
+ rpc::RpcCall { to_addr : address, data : self.encode(), }
+ ],
+ };
+ let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses;
+ let response = responses
+ .get(0)
+ .expect("one response should have existed");
+ if response.failed {
+ return None;
+ }
+ match Self::output(response.raw.as_ref()) {
+ Ok(data) => Some(data),
+ Err(err) => {
+ use substreams_ethereum::Function;
+ substreams::log::info!(
+ "Call output for function `{}` failed to decode with error: {}",
+ Self::NAME, err
+ );
+ None
+ }
+ }
+ }
+ }
+ impl substreams_ethereum::Function for Name {
+ const NAME: &'static str = "name";
+ fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool {
+ Self::match_call(call)
+ }
+ fn decode(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ Self::decode(call)
+ }
+ fn encode(&self) -> Vec {
+ self.encode()
+ }
+ }
+ impl substreams_ethereum::rpc::RPCDecodable for Name {
+ fn output(data: &[u8]) -> Result {
+ Self::output(data)
+ }
+ }
+ #[derive(Debug, Clone, PartialEq)]
+ pub struct Nonces {
+ pub param0: Vec,
+ }
+ impl Nonces {
+ const METHOD_ID: [u8; 4] = [126u8, 206u8, 190u8, 0u8];
+ pub fn decode(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ let maybe_data = call.input.get(4..);
+ if maybe_data.is_none() {
+ return Err("no data to decode".to_string());
+ }
+ let mut values = ethabi::decode(
+ &[ethabi::ParamType::Address],
+ maybe_data.unwrap(),
+ )
+ .map_err(|e| format!("unable to decode call.input: {:?}", e))?;
+ values.reverse();
+ Ok(Self {
+ param0: values
+ .pop()
+ .expect(INTERNAL_ERR)
+ .into_address()
+ .expect(INTERNAL_ERR)
+ .as_bytes()
+ .to_vec(),
+ })
+ }
+ pub fn encode(&self) -> Vec {
+ let data = ethabi::encode(
+ &[ethabi::Token::Address(ethabi::Address::from_slice(&self.param0))],
+ );
+ let mut encoded = Vec::with_capacity(4 + data.len());
+ encoded.extend(Self::METHOD_ID);
+ encoded.extend(data);
+ encoded
+ }
+ pub fn output_call(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ Self::output(call.return_data.as_ref())
+ }
+ pub fn output(data: &[u8]) -> Result {
+ let mut values = ethabi::decode(
+ &[ethabi::ParamType::Uint(256usize)],
+ data.as_ref(),
+ )
+ .map_err(|e| format!("unable to decode output data: {:?}", e))?;
+ Ok({
+ let mut v = [0 as u8; 32];
+ values
+ .pop()
+ .expect("one output data should have existed")
+ .into_uint()
+ .expect(INTERNAL_ERR)
+ .to_big_endian(v.as_mut_slice());
+ substreams::scalar::BigInt::from_unsigned_bytes_be(&v)
+ })
+ }
+ pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool {
+ match call.input.get(0..4) {
+ Some(signature) => Self::METHOD_ID == signature,
+ None => false,
+ }
+ }
+ pub fn call(&self, address: Vec) -> Option {
+ use substreams_ethereum::pb::eth::rpc;
+ let rpc_calls = rpc::RpcCalls {
+ calls: vec![
+ rpc::RpcCall { to_addr : address, data : self.encode(), }
+ ],
+ };
+ let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses;
+ let response = responses
+ .get(0)
+ .expect("one response should have existed");
+ if response.failed {
+ return None;
+ }
+ match Self::output(response.raw.as_ref()) {
+ Ok(data) => Some(data),
+ Err(err) => {
+ use substreams_ethereum::Function;
+ substreams::log::info!(
+ "Call output for function `{}` failed to decode with error: {}",
+ Self::NAME, err
+ );
+ None
+ }
+ }
+ }
+ }
+ impl substreams_ethereum::Function for Nonces {
+ const NAME: &'static str = "nonces";
+ fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool {
+ Self::match_call(call)
+ }
+ fn decode(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ Self::decode(call)
+ }
+ fn encode(&self) -> Vec {
+ self.encode()
+ }
+ }
+ impl substreams_ethereum::rpc::RPCDecodable
+ for Nonces {
+ fn output(data: &[u8]) -> Result {
+ Self::output(data)
+ }
+ }
+ #[derive(Debug, Clone, PartialEq)]
+ pub struct Permit {
+ pub owner: Vec,
+ pub spender: Vec,
+ pub value: substreams::scalar::BigInt,
+ pub deadline: substreams::scalar::BigInt,
+ pub v: substreams::scalar::BigInt,
+ pub r: [u8; 32usize],
+ pub s: [u8; 32usize],
+ }
+ impl Permit {
+ const METHOD_ID: [u8; 4] = [213u8, 5u8, 172u8, 207u8];
+ pub fn decode(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ let maybe_data = call.input.get(4..);
+ if maybe_data.is_none() {
+ return Err("no data to decode".to_string());
+ }
+ let mut values = ethabi::decode(
+ &[
+ ethabi::ParamType::Address,
+ ethabi::ParamType::Address,
+ ethabi::ParamType::Uint(256usize),
+ ethabi::ParamType::Uint(256usize),
+ ethabi::ParamType::Uint(8usize),
+ ethabi::ParamType::FixedBytes(32usize),
+ ethabi::ParamType::FixedBytes(32usize),
+ ],
+ maybe_data.unwrap(),
+ )
+ .map_err(|e| format!("unable to decode call.input: {:?}", e))?;
+ values.reverse();
+ Ok(Self {
+ owner: values
+ .pop()
+ .expect(INTERNAL_ERR)
+ .into_address()
+ .expect(INTERNAL_ERR)
+ .as_bytes()
+ .to_vec(),
+ spender: values
+ .pop()
+ .expect(INTERNAL_ERR)
+ .into_address()
+ .expect(INTERNAL_ERR)
+ .as_bytes()
+ .to_vec(),
+ value: {
+ let mut v = [0 as u8; 32];
+ values
+ .pop()
+ .expect(INTERNAL_ERR)
+ .into_uint()
+ .expect(INTERNAL_ERR)
+ .to_big_endian(v.as_mut_slice());
+ substreams::scalar::BigInt::from_unsigned_bytes_be(&v)
+ },
+ deadline: {
+ let mut v = [0 as u8; 32];
+ values
+ .pop()
+ .expect(INTERNAL_ERR)
+ .into_uint()
+ .expect(INTERNAL_ERR)
+ .to_big_endian(v.as_mut_slice());
+ substreams::scalar::BigInt::from_unsigned_bytes_be(&v)
+ },
+ v: {
+ let mut v = [0 as u8; 32];
+ values
+ .pop()
+ .expect(INTERNAL_ERR)
+ .into_uint()
+ .expect(INTERNAL_ERR)
+ .to_big_endian(v.as_mut_slice());
+ substreams::scalar::BigInt::from_unsigned_bytes_be(&v)
+ },
+ r: {
+ let mut result = [0u8; 32];
+ let v = values
+ .pop()
+ .expect(INTERNAL_ERR)
+ .into_fixed_bytes()
+ .expect(INTERNAL_ERR);
+ result.copy_from_slice(&v);
+ result
+ },
+ s: {
+ let mut result = [0u8; 32];
+ let v = values
+ .pop()
+ .expect(INTERNAL_ERR)
+ .into_fixed_bytes()
+ .expect(INTERNAL_ERR);
+ result.copy_from_slice(&v);
+ result
+ },
+ })
+ }
+ pub fn encode(&self) -> Vec {
+ let data = ethabi::encode(
+ &[
+ ethabi::Token::Address(ethabi::Address::from_slice(&self.owner)),
+ ethabi::Token::Address(
+ ethabi::Address::from_slice(&self.spender),
+ ),
+ ethabi::Token::Uint(
+ ethabi::Uint::from_big_endian(
+ match self.value.clone().to_bytes_be() {
+ (num_bigint::Sign::Plus, bytes) => bytes,
+ (num_bigint::Sign::NoSign, bytes) => bytes,
+ (num_bigint::Sign::Minus, _) => {
+ panic!("negative numbers are not supported")
+ }
+ }
+ .as_slice(),
+ ),
+ ),
+ ethabi::Token::Uint(
+ ethabi::Uint::from_big_endian(
+ match self.deadline.clone().to_bytes_be() {
+ (num_bigint::Sign::Plus, bytes) => bytes,
+ (num_bigint::Sign::NoSign, bytes) => bytes,
+ (num_bigint::Sign::Minus, _) => {
+ panic!("negative numbers are not supported")
+ }
+ }
+ .as_slice(),
+ ),
+ ),
+ ethabi::Token::Uint(
+ ethabi::Uint::from_big_endian(
+ match self.v.clone().to_bytes_be() {
+ (num_bigint::Sign::Plus, bytes) => bytes,
+ (num_bigint::Sign::NoSign, bytes) => bytes,
+ (num_bigint::Sign::Minus, _) => {
+ panic!("negative numbers are not supported")
+ }
+ }
+ .as_slice(),
+ ),
+ ),
+ ethabi::Token::FixedBytes(self.r.as_ref().to_vec()),
+ ethabi::Token::FixedBytes(self.s.as_ref().to_vec()),
+ ],
+ );
+ let mut encoded = Vec::with_capacity(4 + data.len());
+ encoded.extend(Self::METHOD_ID);
+ encoded.extend(data);
+ encoded
+ }
+ pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool {
+ match call.input.get(0..4) {
+ Some(signature) => Self::METHOD_ID == signature,
+ None => false,
+ }
+ }
+ }
+ impl substreams_ethereum::Function for Permit {
+ const NAME: &'static str = "permit";
+ fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool {
+ Self::match_call(call)
+ }
+ fn decode(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ Self::decode(call)
+ }
+ fn encode(&self) -> Vec {
+ self.encode()
+ }
+ }
+ #[derive(Debug, Clone, PartialEq)]
+ pub struct Price0CumulativeLast {}
+ impl Price0CumulativeLast {
+ const METHOD_ID: [u8; 4] = [89u8, 9u8, 192u8, 213u8];
+ pub fn decode(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ Ok(Self {})
+ }
+ pub fn encode(&self) -> Vec {
+ let data = ethabi::encode(&[]);
+ let mut encoded = Vec::with_capacity(4 + data.len());
+ encoded.extend(Self::METHOD_ID);
+ encoded.extend(data);
+ encoded
+ }
+ pub fn output_call(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ Self::output(call.return_data.as_ref())
+ }
+ pub fn output(data: &[u8]) -> Result {
+ let mut values = ethabi::decode(
+ &[ethabi::ParamType::Uint(256usize)],
+ data.as_ref(),
+ )
+ .map_err(|e| format!("unable to decode output data: {:?}", e))?;
+ Ok({
+ let mut v = [0 as u8; 32];
+ values
+ .pop()
+ .expect("one output data should have existed")
+ .into_uint()
+ .expect(INTERNAL_ERR)
+ .to_big_endian(v.as_mut_slice());
+ substreams::scalar::BigInt::from_unsigned_bytes_be(&v)
+ })
+ }
+ pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool {
+ match call.input.get(0..4) {
+ Some(signature) => Self::METHOD_ID == signature,
+ None => false,
+ }
+ }
+ pub fn call(&self, address: Vec) -> Option {
+ use substreams_ethereum::pb::eth::rpc;
+ let rpc_calls = rpc::RpcCalls {
+ calls: vec![
+ rpc::RpcCall { to_addr : address, data : self.encode(), }
+ ],
+ };
+ let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses;
+ let response = responses
+ .get(0)
+ .expect("one response should have existed");
+ if response.failed {
+ return None;
+ }
+ match Self::output(response.raw.as_ref()) {
+ Ok(data) => Some(data),
+ Err(err) => {
+ use substreams_ethereum::Function;
+ substreams::log::info!(
+ "Call output for function `{}` failed to decode with error: {}",
+ Self::NAME, err
+ );
+ None
+ }
+ }
+ }
+ }
+ impl substreams_ethereum::Function for Price0CumulativeLast {
+ const NAME: &'static str = "price0CumulativeLast";
+ fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool {
+ Self::match_call(call)
+ }
+ fn decode(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ Self::decode(call)
+ }
+ fn encode(&self) -> Vec {
+ self.encode()
+ }
+ }
+ impl substreams_ethereum::rpc::RPCDecodable
+ for Price0CumulativeLast {
+ fn output(data: &[u8]) -> Result {
+ Self::output(data)
+ }
+ }
+ #[derive(Debug, Clone, PartialEq)]
+ pub struct Price1CumulativeLast {}
+ impl Price1CumulativeLast {
+ const METHOD_ID: [u8; 4] = [90u8, 61u8, 84u8, 147u8];
+ pub fn decode(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ Ok(Self {})
+ }
+ pub fn encode(&self) -> Vec {
+ let data = ethabi::encode(&[]);
+ let mut encoded = Vec::with_capacity(4 + data.len());
+ encoded.extend(Self::METHOD_ID);
+ encoded.extend(data);
+ encoded
+ }
+ pub fn output_call(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ Self::output(call.return_data.as_ref())
+ }
+ pub fn output(data: &[u8]) -> Result {
+ let mut values = ethabi::decode(
+ &[ethabi::ParamType::Uint(256usize)],
+ data.as_ref(),
+ )
+ .map_err(|e| format!("unable to decode output data: {:?}", e))?;
+ Ok({
+ let mut v = [0 as u8; 32];
+ values
+ .pop()
+ .expect("one output data should have existed")
+ .into_uint()
+ .expect(INTERNAL_ERR)
+ .to_big_endian(v.as_mut_slice());
+ substreams::scalar::BigInt::from_unsigned_bytes_be(&v)
+ })
+ }
+ pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool {
+ match call.input.get(0..4) {
+ Some(signature) => Self::METHOD_ID == signature,
+ None => false,
+ }
+ }
+ pub fn call(&self, address: Vec) -> Option {
+ use substreams_ethereum::pb::eth::rpc;
+ let rpc_calls = rpc::RpcCalls {
+ calls: vec![
+ rpc::RpcCall { to_addr : address, data : self.encode(), }
+ ],
+ };
+ let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses;
+ let response = responses
+ .get(0)
+ .expect("one response should have existed");
+ if response.failed {
+ return None;
+ }
+ match Self::output(response.raw.as_ref()) {
+ Ok(data) => Some(data),
+ Err(err) => {
+ use substreams_ethereum::Function;
+ substreams::log::info!(
+ "Call output for function `{}` failed to decode with error: {}",
+ Self::NAME, err
+ );
+ None
+ }
+ }
+ }
+ }
+ impl substreams_ethereum::Function for Price1CumulativeLast {
+ const NAME: &'static str = "price1CumulativeLast";
+ fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool {
+ Self::match_call(call)
+ }
+ fn decode(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result {
+ Self::decode(call)
+ }
+ fn encode(&self) -> Vec {
+ self.encode()
+ }
+ }
+ impl substreams_ethereum::rpc::RPCDecodable
+ for Price1CumulativeLast {
+ fn output(data: &[u8]) -> Result {
+ Self::output(data)
+ }
+ }
+ #[derive(Debug, Clone, PartialEq)]
+ pub struct Skim {
+ pub to: Vec,
+ }
+ impl Skim {
+ const METHOD_ID: [u8; 4] = [188u8, 37u8, 207u8, 119u8];
+ pub fn decode(
+ call: &substreams_ethereum::pb::eth::v2::Call,
+ ) -> Result