From a06e0196d6a5937fb07f6b74a0b590873aea7b9e Mon Sep 17 00:00:00 2001 From: Harsh Date: Fri, 19 Apr 2024 03:22:15 +0530 Subject: [PATCH 1/3] Add fee substream --- Cargo.lock | 50 +- Cargo.toml | 3 +- curve-finance/Cargo.toml | 28 + curve-finance/Makefile | 21 + curve-finance/abi/pool_contract.json | 629 ++++++++++++++++++ curve-finance/abi/registry_contract.json | 438 ++++++++++++ curve-finance/build.rs | 10 + curve-finance/proto/contract.proto | 37 ++ curve-finance/rust-toolchain.toml | 4 + curve-finance/src/abi.rs | 10 + curve-finance/src/common/constants.rs | 1 + curve-finance/src/common/mod.rs | 2 + curve-finance/src/lib.rs | 6 + .../src/modules/1_map_pool_created.rs | 37 ++ curve-finance/src/modules/2_store_pools.rs | 12 + curve-finance/src/modules/3_map_pool_fees.rs | 62 ++ curve-finance/src/modules/mod.rs | 12 + curve-finance/src/pb.rs | 29 + curve-finance/substreams.yaml | 51 ++ 19 files changed, 1433 insertions(+), 9 deletions(-) create mode 100644 curve-finance/Cargo.toml create mode 100644 curve-finance/Makefile create mode 100644 curve-finance/abi/pool_contract.json create mode 100644 curve-finance/abi/registry_contract.json create mode 100644 curve-finance/build.rs create mode 100644 curve-finance/proto/contract.proto create mode 100644 curve-finance/rust-toolchain.toml create mode 100644 curve-finance/src/abi.rs create mode 100644 curve-finance/src/common/constants.rs create mode 100644 curve-finance/src/common/mod.rs create mode 100644 curve-finance/src/lib.rs create mode 100644 curve-finance/src/modules/1_map_pool_created.rs create mode 100644 curve-finance/src/modules/2_store_pools.rs create mode 100644 curve-finance/src/modules/3_map_pool_fees.rs create mode 100644 curve-finance/src/modules/mod.rs create mode 100644 curve-finance/src/pb.rs create mode 100644 curve-finance/substreams.yaml diff --git a/Cargo.lock b/Cargo.lock index 53aec903..19ad98d6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -216,6 +216,27 @@ dependencies = [ "typenum", ] +[[package]] +name = "curve_finance_substream" +version = "0.0.1" +dependencies = [ + "anyhow", + "ethabi", + "hex", + "hex-literal", + "num-bigint", + "num-traits", + "prost 0.11.9", + "prost-types 0.11.9", + "regex", + "substreams 0.5.10", + "substreams-common", + "substreams-database-change", + "substreams-entity-change 1.3.0", + "substreams-ethereum", + "substreams-helper", +] + [[package]] name = "digest" version = "0.10.7" @@ -1118,6 +1139,17 @@ dependencies = [ "thiserror", ] +[[package]] +name = "substreams-database-change" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed32ca6fc7fa4b7a684d3abd5bb0545aadd2df82402e7336443cdbb6f8b350c3" +dependencies = [ + "prost 0.11.9", + "prost-types 0.11.9", + "substreams 0.5.10", +] + [[package]] name = "substreams-entity-change" version = "0.3.0" @@ -1172,11 +1204,12 @@ dependencies = [ [[package]] name = "substreams-ethereum" -version = "0.8.0" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03a426822f6032fa28145cb2cb7661e70554da839a40ee08b6348f1479a44e1b" +checksum = "8bd2614efbfe4fc3f9e5bc342d68b6d5a20640b2e3c2258094c7bce59ea29667" dependencies = [ "getrandom", + "num-bigint", "substreams 0.5.10", "substreams-ethereum-abigen", "substreams-ethereum-core", @@ -1185,9 +1218,9 @@ dependencies = [ [[package]] name = "substreams-ethereum-abigen" -version = "0.8.0" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd2ba34bc4d19288e7487aa2b13ee75955222809d2dab48c9dad33230a6f4732" +checksum = "c7e52092b876ccda2087dd08cf769398c3dce591de3a3f46570d5596b8fd6144" dependencies = [ "anyhow", "ethabi", @@ -1202,9 +1235,9 @@ dependencies = [ [[package]] name = "substreams-ethereum-core" -version = "0.8.0" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f680a56fc8df55dfd0b3465af2ed6f0eb471b4a0b5a9e0e56c13377911104b01" +checksum = "06601ff5192dc844f4c48961f196b12104e4cbf47dcfdef78ba77d10358b1109" dependencies = [ "bigdecimal", "ethabi", @@ -1218,13 +1251,14 @@ dependencies = [ [[package]] name = "substreams-ethereum-derive" -version = "0.8.0" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b40d3bcb83759b62c2ed372b582be8ba46fc844362a7f7a35fa0269590066118" +checksum = "01728bb412313d36b376be0aed38a8ca7dfbc28adaa658e3df47530b528b4c64" dependencies = [ "ethabi", "heck", "hex", + "num-bigint", "proc-macro2", "quote", "substreams-ethereum-abigen", diff --git a/Cargo.toml b/Cargo.toml index eedf6a7e..cd05b872 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,12 +15,13 @@ members = [ "eth-supply", "synthetix", "aave-v2", + "curve-finance", ] exclude = ["messari-cli"] [workspace.dependencies] substreams = "0.5.0" -substreams-ethereum = "0.8.0" +substreams-ethereum = "0.9" substreams-solana = "0.1.0" [build] diff --git a/curve-finance/Cargo.toml b/curve-finance/Cargo.toml new file mode 100644 index 00000000..4b80fbcf --- /dev/null +++ b/curve-finance/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "curve_finance_substream" +version = "0.0.1" +edition = "2021" +repository = "https://github.com/messari/substreams/" + +[lib] +crate-type = ["cdylib"] + +[dependencies] +ethabi = "17" +hex = "0.4.3" +hex-literal = "0.3.4" +num-bigint = "0.4" +num-traits = "0.2.15" +prost = "0.11" +prost-types = "0.11" +substreams = "0.5" +substreams-ethereum = "0.9" +substreams-database-change = "1" +substreams-entity-change = "1" +substreams-helper = { path = "../substreams-helper" } + +[build-dependencies] +anyhow = "1" +regex = "1.8" +substreams-ethereum = "0.9" +substreams-common = { path = "../common" } diff --git a/curve-finance/Makefile b/curve-finance/Makefile new file mode 100644 index 00000000..0f72285e --- /dev/null +++ b/curve-finance/Makefile @@ -0,0 +1,21 @@ +.PHONY: build_all +build_all: + $(MAKE) -C ../erc20-price build + $(MAKE) -C ../erc20-price pack + cargo build --target wasm32-unknown-unknown --release + +.PHONY: build +build: + cargo build --target wasm32-unknown-unknown --release + +.PHONY: run +run: + substreams run -e polygon.streamingfast.io:443 substreams.yaml map_pool_fees --debug-modules-initial-snapshot store_pools -s 13991900 -t +10 + +.PHONY: build_csv +build_csv: + substreams-sink-csv -e polygon.substreams.pinax.network:9000 --manifest ./curve-finance-substream-v0.1.0.spkg --module-name map_pool_fees --start-block 13991900 + +.PHONY: pack +pack: + substreams pack ./substreams.yaml diff --git a/curve-finance/abi/pool_contract.json b/curve-finance/abi/pool_contract.json new file mode 100644 index 00000000..33ca7d39 --- /dev/null +++ b/curve-finance/abi/pool_contract.json @@ -0,0 +1,629 @@ +[ + { + "name": "TokenExchange", + "inputs": [ + { "name": "buyer", "type": "address", "indexed": true }, + { "name": "sold_id", "type": "int128", "indexed": false }, + { "name": "tokens_sold", "type": "uint256", "indexed": false }, + { "name": "bought_id", "type": "int128", "indexed": false }, + { "name": "tokens_bought", "type": "uint256", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "TokenExchangeUnderlying", + "inputs": [ + { "name": "buyer", "type": "address", "indexed": true }, + { "name": "sold_id", "type": "int128", "indexed": false }, + { "name": "tokens_sold", "type": "uint256", "indexed": false }, + { "name": "bought_id", "type": "int128", "indexed": false }, + { "name": "tokens_bought", "type": "uint256", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "AddLiquidity", + "inputs": [ + { "name": "provider", "type": "address", "indexed": true }, + { "name": "token_amounts", "type": "uint256[3]", "indexed": false }, + { "name": "fees", "type": "uint256[3]", "indexed": false }, + { "name": "invariant", "type": "uint256", "indexed": false }, + { "name": "token_supply", "type": "uint256", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "RemoveLiquidity", + "inputs": [ + { "name": "provider", "type": "address", "indexed": true }, + { "name": "token_amounts", "type": "uint256[3]", "indexed": false }, + { "name": "fees", "type": "uint256[3]", "indexed": false }, + { "name": "token_supply", "type": "uint256", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "RemoveLiquidityOne", + "inputs": [ + { "name": "provider", "type": "address", "indexed": true }, + { "name": "token_amount", "type": "uint256", "indexed": false }, + { "name": "coin_amount", "type": "uint256", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "RemoveLiquidityImbalance", + "inputs": [ + { "name": "provider", "type": "address", "indexed": true }, + { "name": "token_amounts", "type": "uint256[3]", "indexed": false }, + { "name": "fees", "type": "uint256[3]", "indexed": false }, + { "name": "invariant", "type": "uint256", "indexed": false }, + { "name": "token_supply", "type": "uint256", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "CommitNewAdmin", + "inputs": [ + { "name": "deadline", "type": "uint256", "indexed": true }, + { "name": "admin", "type": "address", "indexed": true } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "NewAdmin", + "inputs": [{ "name": "admin", "type": "address", "indexed": true }], + "anonymous": false, + "type": "event" + }, + { + "name": "CommitNewFee", + "inputs": [ + { "name": "deadline", "type": "uint256", "indexed": true }, + { "name": "fee", "type": "uint256", "indexed": false }, + { "name": "admin_fee", "type": "uint256", "indexed": false }, + { "name": "offpeg_fee_multiplier", "type": "uint256", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "NewFee", + "inputs": [ + { "name": "fee", "type": "uint256", "indexed": false }, + { "name": "admin_fee", "type": "uint256", "indexed": false }, + { "name": "offpeg_fee_multiplier", "type": "uint256", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "RampA", + "inputs": [ + { "name": "old_A", "type": "uint256", "indexed": false }, + { "name": "new_A", "type": "uint256", "indexed": false }, + { "name": "initial_time", "type": "uint256", "indexed": false }, + { "name": "future_time", "type": "uint256", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "StopRampA", + "inputs": [ + { "name": "A", "type": "uint256", "indexed": false }, + { "name": "t", "type": "uint256", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "stateMutability": "nonpayable", + "type": "constructor", + "inputs": [ + { "name": "_coins", "type": "address[3]" }, + { "name": "_underlying_coins", "type": "address[3]" }, + { "name": "_pool_token", "type": "address" }, + { "name": "_A", "type": "uint256" }, + { "name": "_fee", "type": "uint256" }, + { "name": "_admin_fee", "type": "uint256" }, + { "name": "_offpeg_fee_multiplier", "type": "uint256" } + ], + "outputs": [] + }, + { + "stateMutability": "view", + "type": "function", + "name": "A", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 10374 + }, + { + "stateMutability": "view", + "type": "function", + "name": "A_precise", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 10336 + }, + { + "stateMutability": "view", + "type": "function", + "name": "dynamic_fee", + "inputs": [ + { "name": "i", "type": "int128" }, + { "name": "j", "type": "int128" } + ], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 22113 + }, + { + "stateMutability": "view", + "type": "function", + "name": "balances", + "inputs": [{ "name": "i", "type": "uint256" }], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 7358 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_virtual_price", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 2702067 + }, + { + "stateMutability": "view", + "type": "function", + "name": "calc_token_amount", + "inputs": [ + { "name": "_amounts", "type": "uint256[3]" }, + { "name": "is_deposit", "type": "bool" } + ], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 5368162 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "add_liquidity", + "inputs": [ + { "name": "_amounts", "type": "uint256[3]" }, + { "name": "_min_mint_amount", "type": "uint256" } + ], + "outputs": [{ "name": "", "type": "uint256" }] + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "add_liquidity", + "inputs": [ + { "name": "_amounts", "type": "uint256[3]" }, + { "name": "_min_mint_amount", "type": "uint256" }, + { "name": "_use_underlying", "type": "bool" } + ], + "outputs": [{ "name": "", "type": "uint256" }] + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_dy", + "inputs": [ + { "name": "i", "type": "int128" }, + { "name": "j", "type": "int128" }, + { "name": "dx", "type": "uint256" } + ], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 6289374 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_dy_underlying", + "inputs": [ + { "name": "i", "type": "int128" }, + { "name": "j", "type": "int128" }, + { "name": "dx", "type": "uint256" } + ], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 6289404 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "exchange", + "inputs": [ + { "name": "i", "type": "int128" }, + { "name": "j", "type": "int128" }, + { "name": "dx", "type": "uint256" }, + { "name": "min_dy", "type": "uint256" } + ], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 6465508 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "exchange_underlying", + "inputs": [ + { "name": "i", "type": "int128" }, + { "name": "j", "type": "int128" }, + { "name": "dx", "type": "uint256" }, + { "name": "min_dy", "type": "uint256" } + ], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 6484358 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "remove_liquidity", + "inputs": [ + { "name": "_amount", "type": "uint256" }, + { "name": "_min_amounts", "type": "uint256[3]" } + ], + "outputs": [{ "name": "", "type": "uint256[3]" }] + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "remove_liquidity", + "inputs": [ + { "name": "_amount", "type": "uint256" }, + { "name": "_min_amounts", "type": "uint256[3]" }, + { "name": "_use_underlying", "type": "bool" } + ], + "outputs": [{ "name": "", "type": "uint256[3]" }] + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "remove_liquidity_imbalance", + "inputs": [ + { "name": "_amounts", "type": "uint256[3]" }, + { "name": "_max_burn_amount", "type": "uint256" } + ], + "outputs": [{ "name": "", "type": "uint256" }] + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "remove_liquidity_imbalance", + "inputs": [ + { "name": "_amounts", "type": "uint256[3]" }, + { "name": "_max_burn_amount", "type": "uint256" }, + { "name": "_use_underlying", "type": "bool" } + ], + "outputs": [{ "name": "", "type": "uint256" }] + }, + { + "stateMutability": "view", + "type": "function", + "name": "calc_withdraw_one_coin", + "inputs": [ + { "name": "_token_amount", "type": "uint256" }, + { "name": "i", "type": "int128" } + ], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 4491030 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "remove_liquidity_one_coin", + "inputs": [ + { "name": "_token_amount", "type": "uint256" }, + { "name": "i", "type": "int128" }, + { "name": "_min_amount", "type": "uint256" } + ], + "outputs": [{ "name": "", "type": "uint256" }] + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "remove_liquidity_one_coin", + "inputs": [ + { "name": "_token_amount", "type": "uint256" }, + { "name": "i", "type": "int128" }, + { "name": "_min_amount", "type": "uint256" }, + { "name": "_use_underlying", "type": "bool" } + ], + "outputs": [{ "name": "", "type": "uint256" }] + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "ramp_A", + "inputs": [ + { "name": "_future_A", "type": "uint256" }, + { "name": "_future_time", "type": "uint256" } + ], + "outputs": [], + "gas": 159459 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "stop_ramp_A", + "inputs": [], + "outputs": [], + "gas": 154920 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "commit_new_fee", + "inputs": [ + { "name": "new_fee", "type": "uint256" }, + { "name": "new_admin_fee", "type": "uint256" }, + { "name": "new_offpeg_fee_multiplier", "type": "uint256" } + ], + "outputs": [], + "gas": 148809 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "apply_new_fee", + "inputs": [], + "outputs": [], + "gas": 141271 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "revert_new_parameters", + "inputs": [], + "outputs": [], + "gas": 23012 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "commit_transfer_ownership", + "inputs": [{ "name": "_owner", "type": "address" }], + "outputs": [], + "gas": 77050 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "apply_transfer_ownership", + "inputs": [], + "outputs": [], + "gas": 65727 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "revert_transfer_ownership", + "inputs": [], + "outputs": [], + "gas": 23102 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "withdraw_admin_fees", + "inputs": [], + "outputs": [], + "gas": 90981 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "donate_admin_fees", + "inputs": [], + "outputs": [], + "gas": 63303 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "kill_me", + "inputs": [], + "outputs": [], + "gas": 40385 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "unkill_me", + "inputs": [], + "outputs": [], + "gas": 23222 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "set_aave_referral", + "inputs": [{ "name": "referral_code", "type": "uint256" }], + "outputs": [], + "gas": 38352 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "set_reward_receiver", + "inputs": [{ "name": "_reward_receiver", "type": "address" }], + "outputs": [], + "gas": 38385 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "set_admin_fee_receiver", + "inputs": [{ "name": "_admin_fee_receiver", "type": "address" }], + "outputs": [], + "gas": 38415 + }, + { + "stateMutability": "view", + "type": "function", + "name": "coins", + "inputs": [{ "name": "arg0", "type": "uint256" }], + "outputs": [{ "name": "", "type": "address" }], + "gas": 3397 + }, + { + "stateMutability": "view", + "type": "function", + "name": "underlying_coins", + "inputs": [{ "name": "arg0", "type": "uint256" }], + "outputs": [{ "name": "", "type": "address" }], + "gas": 3427 + }, + { + "stateMutability": "view", + "type": "function", + "name": "admin_balances", + "inputs": [{ "name": "arg0", "type": "uint256" }], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3457 + }, + { + "stateMutability": "view", + "type": "function", + "name": "fee", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3378 + }, + { + "stateMutability": "view", + "type": "function", + "name": "offpeg_fee_multiplier", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3408 + }, + { + "stateMutability": "view", + "type": "function", + "name": "admin_fee", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3438 + }, + { + "stateMutability": "view", + "type": "function", + "name": "owner", + "inputs": [], + "outputs": [{ "name": "", "type": "address" }], + "gas": 3468 + }, + { + "stateMutability": "view", + "type": "function", + "name": "lp_token", + "inputs": [], + "outputs": [{ "name": "", "type": "address" }], + "gas": 3498 + }, + { + "stateMutability": "view", + "type": "function", + "name": "initial_A", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3528 + }, + { + "stateMutability": "view", + "type": "function", + "name": "future_A", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3558 + }, + { + "stateMutability": "view", + "type": "function", + "name": "initial_A_time", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3588 + }, + { + "stateMutability": "view", + "type": "function", + "name": "future_A_time", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3618 + }, + { + "stateMutability": "view", + "type": "function", + "name": "admin_actions_deadline", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3648 + }, + { + "stateMutability": "view", + "type": "function", + "name": "transfer_ownership_deadline", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3678 + }, + { + "stateMutability": "view", + "type": "function", + "name": "future_fee", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3708 + }, + { + "stateMutability": "view", + "type": "function", + "name": "future_admin_fee", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3738 + }, + { + "stateMutability": "view", + "type": "function", + "name": "future_offpeg_fee_multiplier", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3768 + }, + { + "stateMutability": "view", + "type": "function", + "name": "future_owner", + "inputs": [], + "outputs": [{ "name": "", "type": "address" }], + "gas": 3798 + }, + { + "stateMutability": "view", + "type": "function", + "name": "reward_receiver", + "inputs": [], + "outputs": [{ "name": "", "type": "address" }], + "gas": 3828 + }, + { + "stateMutability": "view", + "type": "function", + "name": "admin_fee_receiver", + "inputs": [], + "outputs": [{ "name": "", "type": "address" }], + "gas": 3858 + } +] diff --git a/curve-finance/abi/registry_contract.json b/curve-finance/abi/registry_contract.json new file mode 100644 index 00000000..6b8afd31 --- /dev/null +++ b/curve-finance/abi/registry_contract.json @@ -0,0 +1,438 @@ +[ + { + "name": "PoolAdded", + "inputs": [ + { "name": "pool", "type": "address", "indexed": true }, + { "name": "rate_method_id", "type": "bytes", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "PoolRemoved", + "inputs": [{ "name": "pool", "type": "address", "indexed": true }], + "anonymous": false, + "type": "event" + }, + { + "stateMutability": "nonpayable", + "type": "constructor", + "inputs": [{ "name": "_address_provider", "type": "address" }], + "outputs": [] + }, + { + "stateMutability": "view", + "type": "function", + "name": "find_pool_for_coins", + "inputs": [ + { "name": "_from", "type": "address" }, + { "name": "_to", "type": "address" } + ], + "outputs": [{ "name": "", "type": "address" }] + }, + { + "stateMutability": "view", + "type": "function", + "name": "find_pool_for_coins", + "inputs": [ + { "name": "_from", "type": "address" }, + { "name": "_to", "type": "address" }, + { "name": "i", "type": "uint256" } + ], + "outputs": [{ "name": "", "type": "address" }] + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_n_coins", + "inputs": [{ "name": "_pool", "type": "address" }], + "outputs": [{ "name": "", "type": "uint256[2]" }], + "gas": 2836 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_coins", + "inputs": [{ "name": "_pool", "type": "address" }], + "outputs": [{ "name": "", "type": "address[8]" }], + "gas": 23802 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_underlying_coins", + "inputs": [{ "name": "_pool", "type": "address" }], + "outputs": [{ "name": "", "type": "address[8]" }], + "gas": 23894 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_decimals", + "inputs": [{ "name": "_pool", "type": "address" }], + "outputs": [{ "name": "", "type": "uint256[8]" }], + "gas": 10474 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_underlying_decimals", + "inputs": [{ "name": "_pool", "type": "address" }], + "outputs": [{ "name": "", "type": "uint256[8]" }], + "gas": 10566 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_rates", + "inputs": [{ "name": "_pool", "type": "address" }], + "outputs": [{ "name": "", "type": "uint256[8]" }], + "gas": 92272 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_gauges", + "inputs": [{ "name": "_pool", "type": "address" }], + "outputs": [ + { "name": "", "type": "address[10]" }, + { "name": "", "type": "int128[10]" } + ], + "gas": 28534 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_balances", + "inputs": [{ "name": "_pool", "type": "address" }], + "outputs": [{ "name": "", "type": "uint256[8]" }], + "gas": 42130 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_underlying_balances", + "inputs": [{ "name": "_pool", "type": "address" }], + "outputs": [{ "name": "", "type": "uint256[8]" }], + "gas": 379602 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_virtual_price_from_lp_token", + "inputs": [{ "name": "_token", "type": "address" }], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 5287 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_A", + "inputs": [{ "name": "_pool", "type": "address" }], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3105 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_parameters", + "inputs": [{ "name": "_pool", "type": "address" }], + "outputs": [ + { "name": "A", "type": "uint256" }, + { "name": "future_A", "type": "uint256" }, + { "name": "fee", "type": "uint256" }, + { "name": "admin_fee", "type": "uint256" }, + { "name": "future_fee", "type": "uint256" }, + { "name": "future_admin_fee", "type": "uint256" }, + { "name": "future_owner", "type": "address" }, + { "name": "initial_A", "type": "uint256" }, + { "name": "initial_A_time", "type": "uint256" }, + { "name": "future_A_time", "type": "uint256" } + ], + "gas": 25860 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_fees", + "inputs": [{ "name": "_pool", "type": "address" }], + "outputs": [{ "name": "", "type": "uint256[2]" }], + "gas": 5601 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_admin_balances", + "inputs": [{ "name": "_pool", "type": "address" }], + "outputs": [{ "name": "", "type": "uint256[8]" }], + "gas": 87173 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_coin_indices", + "inputs": [ + { "name": "_pool", "type": "address" }, + { "name": "_from", "type": "address" }, + { "name": "_to", "type": "address" } + ], + "outputs": [ + { "name": "", "type": "int128" }, + { "name": "", "type": "int128" }, + { "name": "", "type": "bool" } + ], + "gas": 47931 + }, + { + "stateMutability": "view", + "type": "function", + "name": "estimate_gas_used", + "inputs": [ + { "name": "_pool", "type": "address" }, + { "name": "_from", "type": "address" }, + { "name": "_to", "type": "address" } + ], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 60049 + }, + { + "stateMutability": "view", + "type": "function", + "name": "is_meta", + "inputs": [{ "name": "_pool", "type": "address" }], + "outputs": [{ "name": "", "type": "bool" }], + "gas": 3200 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_pool_name", + "inputs": [{ "name": "_pool", "type": "address" }], + "outputs": [{ "name": "", "type": "string" }], + "gas": 13523 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_coin_swap_count", + "inputs": [{ "name": "_coin", "type": "address" }], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3251 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_coin_swap_complement", + "inputs": [ + { "name": "_coin", "type": "address" }, + { "name": "_index", "type": "uint256" } + ], + "outputs": [{ "name": "", "type": "address" }], + "gas": 3390 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_pool_asset_type", + "inputs": [{ "name": "_pool", "type": "address" }], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3311 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "add_pool", + "inputs": [ + { "name": "_pool", "type": "address" }, + { "name": "_n_coins", "type": "uint256" }, + { "name": "_lp_token", "type": "address" }, + { "name": "_rate_info", "type": "bytes32" }, + { "name": "_decimals", "type": "uint256" }, + { "name": "_underlying_decimals", "type": "uint256" }, + { "name": "_name", "type": "string" } + ], + "outputs": [], + "gas": 63156468 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "add_pool_without_underlying", + "inputs": [ + { "name": "_pool", "type": "address" }, + { "name": "_n_coins", "type": "uint256" }, + { "name": "_lp_token", "type": "address" }, + { "name": "_rate_info", "type": "bytes32" }, + { "name": "_decimals", "type": "uint256" }, + { "name": "_use_rates", "type": "uint256" }, + { "name": "_name", "type": "string" } + ], + "outputs": [], + "gas": 32112470 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "add_metapool", + "inputs": [ + { "name": "_pool", "type": "address" }, + { "name": "_n_coins", "type": "uint256" }, + { "name": "_lp_token", "type": "address" }, + { "name": "_decimals", "type": "uint256" }, + { "name": "_name", "type": "string" } + ], + "outputs": [] + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "add_metapool", + "inputs": [ + { "name": "_pool", "type": "address" }, + { "name": "_n_coins", "type": "uint256" }, + { "name": "_lp_token", "type": "address" }, + { "name": "_decimals", "type": "uint256" }, + { "name": "_name", "type": "string" }, + { "name": "_base_pool", "type": "address" } + ], + "outputs": [] + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "remove_pool", + "inputs": [{ "name": "_pool", "type": "address" }], + "outputs": [], + "gas": 801545294718 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "set_pool_gas_estimates", + "inputs": [ + { "name": "_addr", "type": "address[5]" }, + { "name": "_amount", "type": "uint256[2][5]" } + ], + "outputs": [], + "gas": 393820 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "set_coin_gas_estimates", + "inputs": [ + { "name": "_addr", "type": "address[10]" }, + { "name": "_amount", "type": "uint256[10]" } + ], + "outputs": [], + "gas": 395407 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "set_gas_estimate_contract", + "inputs": [ + { "name": "_pool", "type": "address" }, + { "name": "_estimator", "type": "address" } + ], + "outputs": [], + "gas": 75989 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "set_liquidity_gauges", + "inputs": [ + { "name": "_pool", "type": "address" }, + { "name": "_liquidity_gauges", "type": "address[10]" } + ], + "outputs": [], + "gas": 422130 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "set_pool_asset_type", + "inputs": [ + { "name": "_pool", "type": "address" }, + { "name": "_asset_type", "type": "uint256" } + ], + "outputs": [], + "gas": 76027 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "batch_set_pool_asset_type", + "inputs": [ + { "name": "_pools", "type": "address[32]" }, + { "name": "_asset_types", "type": "uint256[32]" } + ], + "outputs": [], + "gas": 1176807 + }, + { + "stateMutability": "view", + "type": "function", + "name": "address_provider", + "inputs": [], + "outputs": [{ "name": "", "type": "address" }], + "gas": 3348 + }, + { + "stateMutability": "view", + "type": "function", + "name": "pool_list", + "inputs": [{ "name": "arg0", "type": "uint256" }], + "outputs": [{ "name": "", "type": "address" }], + "gas": 3487 + }, + { + "stateMutability": "view", + "type": "function", + "name": "pool_count", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3408 + }, + { + "stateMutability": "view", + "type": "function", + "name": "coin_count", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3438 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_coin", + "inputs": [{ "name": "arg0", "type": "uint256" }], + "outputs": [{ "name": "", "type": "address" }], + "gas": 3577 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_pool_from_lp_token", + "inputs": [{ "name": "arg0", "type": "address" }], + "outputs": [{ "name": "", "type": "address" }], + "gas": 3713 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_lp_token", + "inputs": [{ "name": "arg0", "type": "address" }], + "outputs": [{ "name": "", "type": "address" }], + "gas": 3743 + }, + { + "stateMutability": "view", + "type": "function", + "name": "last_updated", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3558 + } +] diff --git a/curve-finance/build.rs b/curve-finance/build.rs new file mode 100644 index 00000000..fb321d31 --- /dev/null +++ b/curve-finance/build.rs @@ -0,0 +1,10 @@ +use anyhow::{Ok, Result}; +use substreams_common::codegen; + +fn main() -> Result<(), anyhow::Error> { + println!("cargo:rerun-if-changed=proto"); + println!("cargo:rerun-if-changed=abi"); + codegen::generate(None)?; + + Ok(()) +} diff --git a/curve-finance/proto/contract.proto b/curve-finance/proto/contract.proto new file mode 100644 index 00000000..add2764a --- /dev/null +++ b/curve-finance/proto/contract.proto @@ -0,0 +1,37 @@ +syntax = "proto3"; + +import "google/protobuf/timestamp.proto"; +package messari.contract.v1; + +message Pools { + repeated Pool pools = 1; +} + +message Pool { + string address = 1; + + int64 log_index = 2; + int64 block_number = 3; + + google.protobuf.Timestamp block_timestmap = 4; + int64 transaction_index = 5; + string transaction_hash = 6; +} + +message PoolFees { + repeated PoolFee fees = 1; +} + +message PoolFee { + string address = 1; + + optional uint64 fee = 2; + optional uint64 admin_fee = 3; + + int64 log_index = 5; + int64 block_number = 6; + + google.protobuf.Timestamp block_timestmap = 7; + int64 transaction_index = 8; + string transaction_hash = 9; +} \ No newline at end of file diff --git a/curve-finance/rust-toolchain.toml b/curve-finance/rust-toolchain.toml new file mode 100644 index 00000000..0a0b90ae --- /dev/null +++ b/curve-finance/rust-toolchain.toml @@ -0,0 +1,4 @@ +[toolchain] +channel = "1.64.0" +components = [ "rustfmt" ] +targets = [ "wasm32-unknown-unknown" ] diff --git a/curve-finance/src/abi.rs b/curve-finance/src/abi.rs new file mode 100644 index 00000000..84650b31 --- /dev/null +++ b/curve-finance/src/abi.rs @@ -0,0 +1,10 @@ +// DO NOT EDIT - the file is generated by build script +#[rustfmt::skip] +#[allow(unused_imports)] +#[path = "../target/abi/pool_contract.rs"] +pub mod pool_contract; + +#[rustfmt::skip] +#[allow(unused_imports)] +#[path = "../target/abi/registry_contract.rs"] +pub mod registry_contract; diff --git a/curve-finance/src/common/constants.rs b/curve-finance/src/common/constants.rs new file mode 100644 index 00000000..e23af3ec --- /dev/null +++ b/curve-finance/src/common/constants.rs @@ -0,0 +1 @@ +pub const REGISTRY_ADDRESS: &str = "0x094d12e5b541784701fd8d65f11fc0598fbc6332"; \ No newline at end of file diff --git a/curve-finance/src/common/mod.rs b/curve-finance/src/common/mod.rs new file mode 100644 index 00000000..49e80740 --- /dev/null +++ b/curve-finance/src/common/mod.rs @@ -0,0 +1,2 @@ +#[path = "constants.rs"] +pub(crate) mod constants; diff --git a/curve-finance/src/lib.rs b/curve-finance/src/lib.rs new file mode 100644 index 00000000..6470a6dc --- /dev/null +++ b/curve-finance/src/lib.rs @@ -0,0 +1,6 @@ +mod abi; +mod common; +mod modules; +mod pb; + +pub use modules::*; diff --git a/curve-finance/src/modules/1_map_pool_created.rs b/curve-finance/src/modules/1_map_pool_created.rs new file mode 100644 index 00000000..36d5492d --- /dev/null +++ b/curve-finance/src/modules/1_map_pool_created.rs @@ -0,0 +1,37 @@ +use std::str::FromStr; + +use ethabi::ethereum_types::Address; +use substreams_ethereum::pb::eth::v2::{self as eth}; +use substreams_helper::event_handler::EventHandler; +use substreams_helper::hex::Hexable; + +use crate::abi::registry_contract::events::PoolAdded; +use crate::common::constants; +use crate::pb::contract::v1::{Pool, Pools}; + +#[substreams::handlers::map] +pub fn map_pool_created(blk: eth::Block) -> Result { + let mut pools: Vec = vec![]; + + get_pools(&blk, &mut pools); + Ok(Pools { pools }) +} + +fn get_pools(blk: ð::Block, pools: &mut Vec) { + let mut on_pair_created = |event: PoolAdded, tx: ð::TransactionTrace, log: ð::Log| { + pools.push(Pool { + address: event.pool.to_hex(), + log_index: log.index as i64, + block_number: blk.number as i64, + block_timestmap: Some(blk.timestamp().to_owned()), + transaction_index: tx.index as i64, + transaction_hash: tx.hash.to_hex(), + }) + }; + + let mut eh = EventHandler::new(blk); + eh.filter_by_address(vec![Address::from_str(constants::REGISTRY_ADDRESS).unwrap()]); + + eh.on::(&mut on_pair_created); + eh.handle_events(); +} diff --git a/curve-finance/src/modules/2_store_pools.rs b/curve-finance/src/modules/2_store_pools.rs new file mode 100644 index 00000000..6254d781 --- /dev/null +++ b/curve-finance/src/modules/2_store_pools.rs @@ -0,0 +1,12 @@ +use substreams::store::StoreNew; +use substreams::store::StoreSetIfNotExists; +use substreams::store::StoreSetIfNotExistsString; + +use crate::pb::contract::v1::Pools; + +#[substreams::handlers::store] +pub fn store_pools(pools_created: Pools, store: StoreSetIfNotExistsString) { + for pool in pools_created.pools { + store.set_if_not_exists(0, &pool.address, &pool.address); + } +} diff --git a/curve-finance/src/modules/3_map_pool_fees.rs b/curve-finance/src/modules/3_map_pool_fees.rs new file mode 100644 index 00000000..714dfec5 --- /dev/null +++ b/curve-finance/src/modules/3_map_pool_fees.rs @@ -0,0 +1,62 @@ +use substreams::log; +use substreams::scalar::BigInt; +use substreams::store::{StoreGet, StoreGetString}; +use substreams_ethereum::pb::eth::rpc::RpcResponse; +use substreams_ethereum::pb::eth::v2::{self as eth}; +use substreams_ethereum::rpc::RpcBatch; +use substreams_helper::hex::Hexable; + +use crate::abi::pool_contract::functions::{AdminFee, Fee}; +use crate::pb::contract::v1::{PoolFee, PoolFees}; + +#[substreams::handlers::map] +pub fn map_pool_fees( + blk: eth::Block, + pools_store: StoreGetString, +) -> Result { + let mut fees: Vec = vec![]; + + for log in blk.logs() { + if pools_store + .get_last(log.address().to_owned().to_hex()) + .is_none() + { + continue; + } + + let pool_fees = get_pool_fees(log.address().to_vec()); + + fees.push(PoolFee { + address: log.address().to_owned().to_hex(), + + fee: RpcBatch::decode::<_, Fee>(&pool_fees[0]).map(|x| x.to_u64()), + admin_fee: RpcBatch::decode::<_, Fee>(&pool_fees[1]).map(|x| x.to_u64()), + // admin_balances: admin_balances, + + log_index: log.index() as i64, + block_number: blk.number as i64, + block_timestmap: Some(blk.timestamp().to_owned()), + + transaction_index: log.receipt.transaction.index as i64, + transaction_hash: log.receipt.transaction.hash.to_hex(), + }) + } + + Ok(PoolFees { fees }) +} + +fn get_pool_fees(contract: Vec) -> Vec { + let batch = RpcBatch::new(); + + let responses = batch + .add(Fee {}, contract.clone()) + .add(AdminFee {}, contract.clone()) + .execute() + .unwrap() + .responses; + + // let fee = RpcBatch::decode::<_, Fee>(&responses[0]); + // let admin_fee = RpcBatch::decode::<_, AdminFee>(&responses[1]); + + responses +} diff --git a/curve-finance/src/modules/mod.rs b/curve-finance/src/modules/mod.rs new file mode 100644 index 00000000..dab74819 --- /dev/null +++ b/curve-finance/src/modules/mod.rs @@ -0,0 +1,12 @@ +#[path = "1_map_pool_created.rs"] +mod map_pool_created; + +#[path = "2_store_pools.rs"] +mod store_pools; + +#[path = "3_map_pool_fees.rs"] +mod map_pool_fees; + +pub use map_pool_created::map_pool_created; +pub use store_pools::store_pools; +pub use map_pool_fees::map_pool_fees; diff --git a/curve-finance/src/pb.rs b/curve-finance/src/pb.rs new file mode 100644 index 00000000..7d94c4f4 --- /dev/null +++ b/curve-finance/src/pb.rs @@ -0,0 +1,29 @@ +#[rustfmt::skip] +#[path = "../target/pb/messari.common.v1.rs"] +pub(in crate::pb) mod common_v1; + +pub mod common { + pub mod v1 { + pub use super::super::common_v1::*; + } +} + +#[rustfmt::skip] +#[path = "../target/pb/messari.contract.v1.rs"] +pub(in crate::pb) mod contract_v1; + +pub mod contract { + pub mod v1 { + pub use super::super::contract_v1::*; + } +} + +#[rustfmt::skip] +#[path = "../target/pb/messari.erc20.v1.rs"] +pub(in crate::pb) mod erc20_v1; + +pub mod erc20 { + pub mod v1 { + pub use super::super::erc20_v1::*; + } +} diff --git a/curve-finance/substreams.yaml b/curve-finance/substreams.yaml new file mode 100644 index 00000000..20048366 --- /dev/null +++ b/curve-finance/substreams.yaml @@ -0,0 +1,51 @@ +specVersion: v0.1.0 +package: + name: curve_finance_substream + version: v0.1.0 + +imports: + sql: https://github.com/streamingfast/substreams-sink-sql/releases/download/protodefs-v1.0.7/substreams-sink-sql-protodefs-v1.0.7.spkg + graph: https://github.com/streamingfast/substreams-sink-subgraph/releases/download/v0.1.0/substreams-sink-subgraph-protodefs-v0.1.0.spkg + database_change: https://github.com/streamingfast/substreams-sink-database-changes/releases/download/v1.2.1/substreams-database-change-v1.2.1.spkg + entity: https://github.com/streamingfast/substreams-entity-change/releases/download/v1.1.0/substreams-entity-change-v1.1.0.spkg + +protobuf: + files: + - common.proto + - erc20.proto + - contract.proto + importPaths: + - ./proto + - ../common/proto + +binaries: + default: + type: wasm/rust-v1 + file: "../target/wasm32-unknown-unknown/release/curve_finance_substream.wasm" + +modules: + - name: map_pool_created + kind: map + initialBlock: 13991825 + inputs: + - source: sf.ethereum.type.v2.Block + output: + type: proto:messari.contract.v1.Pools + + - name: store_pools + kind: store + updatePolicy: set_if_not_exists + valueType: string + inputs: + - map: map_pool_created + + - name: map_pool_fees + kind: map + initialBlock: 13991825 + inputs: + - source: sf.ethereum.type.v2.Block + - store: store_pools + output: + type: proto:messari.contract.v1.PoolFees + +network: polygon From a343d6350361b77ad78af9556e95415fa7aeb8d5 Mon Sep 17 00:00:00 2001 From: Harsh Date: Sun, 21 Apr 2024 07:32:57 +0530 Subject: [PATCH 2/3] Add admin_balances delta --- .gitignore | 8 + curve-finance/Makefile | 4 +- curve-finance/ecosystem.config.js | 14 + curve-finance/package-lock.json | 623 ++++++++++++++++++ curve-finance/package.json | 5 + curve-finance/proto/contract.proto | 1 + curve-finance/src/common/constants.rs | 7 +- curve-finance/src/lib.rs | 1 + curve-finance/src/modules/2_store_pools.rs | 7 +- curve-finance/src/modules/3_map_pool_fees.rs | 62 -- .../modules/3_store_pool_admin_balances.rs | 98 +++ curve-finance/src/modules/4_map_pool_fees.rs | 106 +++ curve-finance/src/modules/mod.rs | 6 +- curve-finance/src/store_key.rs | 24 + curve-finance/substreams.yaml | 16 +- 15 files changed, 912 insertions(+), 70 deletions(-) create mode 100644 curve-finance/ecosystem.config.js create mode 100644 curve-finance/package-lock.json create mode 100644 curve-finance/package.json delete mode 100644 curve-finance/src/modules/3_map_pool_fees.rs create mode 100644 curve-finance/src/modules/3_store_pool_admin_balances.rs create mode 100644 curve-finance/src/modules/4_map_pool_fees.rs create mode 100644 curve-finance/src/store_key.rs diff --git a/.gitignore b/.gitignore index e12b4ca6..1001f752 100644 --- a/.gitignore +++ b/.gitignore @@ -9,7 +9,15 @@ Reference/ **/target/ **/build/ **/data/ +**/node_modules/ + **/*.spkg +**/*.csv +**/*.clock +**/*.cursor +**/*.session + + **/buf.gen.yaml replay.log Cargo.lock diff --git a/curve-finance/Makefile b/curve-finance/Makefile index 0f72285e..d41f73c0 100644 --- a/curve-finance/Makefile +++ b/curve-finance/Makefile @@ -10,11 +10,11 @@ build: .PHONY: run run: - substreams run -e polygon.streamingfast.io:443 substreams.yaml map_pool_fees --debug-modules-initial-snapshot store_pools -s 13991900 -t +10 + substreams run -e polygon.streamingfast.io:443 substreams.yaml map_pool_fees --debug-modules-initial-snapshot store_pool_admin_balances -s 13521257 .PHONY: build_csv build_csv: - substreams-sink-csv -e polygon.substreams.pinax.network:9000 --manifest ./curve-finance-substream-v0.1.0.spkg --module-name map_pool_fees --start-block 13991900 + substreams-sink-csv -e polygon.substreams.pinax.network --manifest ./curve-finance-substream-v0.1.0.spkg --module-name map_pool_fees --start-block 13479484 .PHONY: pack pack: diff --git a/curve-finance/ecosystem.config.js b/curve-finance/ecosystem.config.js new file mode 100644 index 00000000..e1d90831 --- /dev/null +++ b/curve-finance/ecosystem.config.js @@ -0,0 +1,14 @@ +module.exports = { + apps: [{ + name: "substreams-sink-csv", + script: "./node_modules/substreams-sink-csv/dist/bin/cli.mjs", + env: { + SUBSTREAMS_API_KEY: '62017651ea666fd0a915f8d0a9c31f378712dd0710de394e', + MANIFEST: './curve-finance-substream-v0.1.0.spkg', + MODULE_NAME: 'map_pool_fees', + SUBSTREAMS_ENDPOINT: 'polygon.substreams.pinax.network', + FINAL_BLOCKS_ONLY: 'true', + START_BLOCK: '13479484', + } + }] +} \ No newline at end of file diff --git a/curve-finance/package-lock.json b/curve-finance/package-lock.json new file mode 100644 index 00000000..ad5c104d --- /dev/null +++ b/curve-finance/package-lock.json @@ -0,0 +1,623 @@ +{ + "name": "curve-finance", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "substreams-sink-csv": "^0.3.1" + } + }, + "node_modules/@bufbuild/buf": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/@bufbuild/buf/-/buf-1.30.1.tgz", + "integrity": "sha512-9VVvrXBCWUiH8ToccqDfPRuTiPXSbHmSkL8XPlMpUhpJIlm01m4/Vzbc5FJL1yuk3e1rdBGCF6I9Obs9NsILzg==", + "hasInstallScript": true, + "peer": true, + "bin": { + "buf": "bin/buf", + "protoc-gen-buf-breaking": "bin/protoc-gen-buf-breaking", + "protoc-gen-buf-lint": "bin/protoc-gen-buf-lint" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@bufbuild/buf-darwin-arm64": "1.30.1", + "@bufbuild/buf-darwin-x64": "1.30.1", + "@bufbuild/buf-linux-aarch64": "1.30.1", + "@bufbuild/buf-linux-x64": "1.30.1", + "@bufbuild/buf-win32-arm64": "1.30.1", + "@bufbuild/buf-win32-x64": "1.30.1" + } + }, + "node_modules/@bufbuild/buf-darwin-arm64": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/@bufbuild/buf-darwin-arm64/-/buf-darwin-arm64-1.30.1.tgz", + "integrity": "sha512-FRgf+x4V4s9Z1wH2xHdP8+1AYtil1GCmMjzKf/4AQ+eaUpoLfipSIsVYiBrnpcRxEPe9UMVzwNjKtPak/szwPw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@bufbuild/buf-darwin-x64": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/@bufbuild/buf-darwin-x64/-/buf-darwin-x64-1.30.1.tgz", + "integrity": "sha512-kE0ne45zE7lSdv9WxPVhapwu627WMbWmWCzqSxzYr8sWDLqiAuw+XvO9/mHGdPWcMhV4lMX6tutitd9PPVxK8A==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@bufbuild/buf-linux-aarch64": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/@bufbuild/buf-linux-aarch64/-/buf-linux-aarch64-1.30.1.tgz", + "integrity": "sha512-kVV9Sl0GwZiQkMOXJiuwuU+gIHe6AWcYBMRMmuW55sY0ePZNXBmRGt4k5W4ijy98O6pnY3ao+n9ne0KwiD9MVA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@bufbuild/buf-linux-x64": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/@bufbuild/buf-linux-x64/-/buf-linux-x64-1.30.1.tgz", + "integrity": "sha512-RacDbQJYNwqRlMESa/rLHprfUVa8Wu1/cmcqS29Fyt/cGzs0G8sNcQzQ87HYFIS9cSlSPl6vWL0x8JqQRp68lQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@bufbuild/buf-win32-arm64": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/@bufbuild/buf-win32-arm64/-/buf-win32-arm64-1.30.1.tgz", + "integrity": "sha512-ndp/qb5M6yrSzcnMI0j4jjAuDKa7zHBFc187FwyDb3v63rvyQeYqncHb0leT5ZWqfNggJT4vXIH6QnH82PfDQw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@bufbuild/buf-win32-x64": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/@bufbuild/buf-win32-x64/-/buf-win32-x64-1.30.1.tgz", + "integrity": "sha512-1kmIY6oKLKZ4zIQVNG60GRDp+vKSZdaim7wRejOtgEDuWXhIuErlnGbpstypU8FO+OV3SeFUJNOJ8tLOYd3PvQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@bufbuild/protobuf": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-1.8.0.tgz", + "integrity": "sha512-qR9FwI8QKIveDnUYutvfzbC21UZJJryYrLuZGjeZ/VGz+vXelUkK+xgkOHsvPEdYEdxtgUUq4313N8QtOehJ1Q==" + }, + "node_modules/@connectrpc/connect": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@connectrpc/connect/-/connect-1.4.0.tgz", + "integrity": "sha512-vZeOkKaAjyV4+RH3+rJZIfDFJAfr+7fyYr6sLDKbYX3uuTVszhFe9/YKf5DNqrDb5cKdKVlYkGn6DTDqMitAnA==", + "peerDependencies": { + "@bufbuild/protobuf": "^1.4.2" + } + }, + "node_modules/@connectrpc/connect-node": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@connectrpc/connect-node/-/connect-node-1.4.0.tgz", + "integrity": "sha512-0ANnrr6SvsjevsWEgdzHy7BaHkluZyS6s4xNoVt7RBHFR5V/kT9lPokoIbYUOU9JHzdRgTaS3x5595mwUsu15g==", + "dependencies": { + "undici": "^5.28.3" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@bufbuild/protobuf": "^1.4.2", + "@connectrpc/connect": "1.4.0" + } + }, + "node_modules/@connectrpc/connect-web": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@connectrpc/connect-web/-/connect-web-1.4.0.tgz", + "integrity": "sha512-13aO4psFbbm7rdOFGV0De2Za64DY/acMspgloDlcOKzLPPs0yZkhp1OOzAQeiAIr7BM/VOHIA3p8mF0inxCYTA==", + "peerDependencies": { + "@bufbuild/protobuf": "^1.4.2", + "@connectrpc/connect": "1.4.0" + } + }, + "node_modules/@effect/schema": { + "version": "0.62.9", + "resolved": "https://registry.npmjs.org/@effect/schema/-/schema-0.62.9.tgz", + "integrity": "sha512-u5LJqk3MClXr8DxiN/AGUBUxVnsl8o6glOTfToFECn3I+slVW/vbzLMRyUqbNNp2uBpdP6UGwmp9VVYxd72bBg==", + "peer": true, + "peerDependencies": { + "effect": "^2.3.8", + "fast-check": "^3.13.2" + } + }, + "node_modules/@fastify/busboy": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", + "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/api": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.8.0.tgz", + "integrity": "sha512-I/s6F7yKUDdtMsoBWXJe8Qz40Tui5vsuKCWJEWVL+5q9sSWRzzx6v2KeNsOBEwd94j0eWkpWCH4yB6rZg9Mf0w==", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@sinclair/typebox": { + "version": "0.32.21", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.32.21.tgz", + "integrity": "sha512-mIJHip7dc98j2KAUvwqmkSn02R8dNk7698g5Vb7J58fLLMSEBNi1ps10WzNM5HcKH90SvyFb3Vny6BvBmt5GnQ==" + }, + "node_modules/@substreams/core": { + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/@substreams/core/-/core-0.15.1.tgz", + "integrity": "sha512-zxk/KzSCaR3C+1La9I6tfLp2SJGEARxol8Mwa/wMNOsXUvsZ57Fhm515IYwoUO8HSdi/L+OwOpzjvb4NTJwSKA==", + "peerDependencies": { + "@bufbuild/protobuf": "^1.7.2", + "@connectrpc/connect": "^1.3.0" + } + }, + "node_modules/@substreams/manifest": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/@substreams/manifest/-/manifest-0.14.1.tgz", + "integrity": "sha512-NKxNmiVki41wPGmGewQBkpzDc6HOMkK2JIZR4mPczSA3tRIxwiTcK027X5Na3mpaxJawbzAOHGSuJNbS+IBYJQ==", + "dependencies": { + "@substreams/core": "0.15.1" + }, + "peerDependencies": { + "@bufbuild/buf": "^1.29.0", + "@bufbuild/protobuf": "^1.7.2", + "@effect/schema": "^0.62.0", + "effect": "^2.3.0", + "yaml": "^2.3.4" + } + }, + "node_modules/@substreams/node": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/@substreams/node/-/node-0.6.2.tgz", + "integrity": "sha512-as/LbCOy4YM9UGFZ4eIfNJircDPnm2BYUCk4Fc1U6SakLGBG1Glbnc6c63PIxxonO2zpxu1yYPLu/BXdFCjXWQ==", + "dependencies": { + "@bufbuild/protobuf": "latest", + "@connectrpc/connect": "latest", + "@connectrpc/connect-node": "latest", + "@connectrpc/connect-web": "latest", + "@substreams/core": "latest", + "eventemitter3": "latest" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@substreams/sink-database-changes": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@substreams/sink-database-changes/-/sink-database-changes-0.3.6.tgz", + "integrity": "sha512-GwjoFBY6ODTuxYtlkz0jSJLD+gcWsJP/Cl4i6vRLqbgnE514r6EUFHc6TsrXPKqaxFTGiOedO+hzSai+0RYOrQ==", + "dependencies": { + "@bufbuild/protobuf": "latest", + "@sinclair/typebox": "latest", + "zod": "latest" + } + }, + "node_modules/@substreams/sink-entity-changes": { + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/@substreams/sink-entity-changes/-/sink-entity-changes-0.3.11.tgz", + "integrity": "sha512-flWn/IiZE5luQDloUCoy9MzIoptQPj416GA0V6sowcFy9mgii2y5hCv/Ck3VlZqW0zPWuNml2DI+SZUTCSvJBw==", + "dependencies": { + "@bufbuild/protobuf": "latest", + "@sinclair/typebox": "latest", + "zod": "latest" + } + }, + "node_modules/ansi-escapes": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.1.tgz", + "integrity": "sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig==", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/bintrees": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bintrees/-/bintrees-1.0.2.tgz", + "integrity": "sha512-VOMgTMwjAaUG580SXn3LacVgjurrbMme7ZZNYGSSV7mmtY6QQRh0Eg3pwIcntQ77DErK1L0NxkbetjcoXzVwKw==" + }, + "node_modules/cli-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", + "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", + "dependencies": { + "restore-cursor": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/commander": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.0.0.tgz", + "integrity": "sha512-MwVNWlYjDTtOjX5PiD7o5pK0UrFU/OYgcJfjjK4RaHZETNtjJqrZa9Y9ds88+A+f+d5lv+561eZ+yCKoS3gbAA==", + "engines": { + "node": ">=18" + } + }, + "node_modules/dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/effect": { + "version": "2.4.19", + "resolved": "https://registry.npmjs.org/effect/-/effect-2.4.19.tgz", + "integrity": "sha512-z/rn878Po3n522g/AYUDHD1SsZaZdvRxlTCLQ8xl8H6xA82nBwwooD1mdn/73Uywmp7d84oay3w3528r0Uyd0w==", + "peer": true + }, + "node_modules/emoji-regex": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", + "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==" + }, + "node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==" + }, + "node_modules/fast-check": { + "version": "3.17.1", + "resolved": "https://registry.npmjs.org/fast-check/-/fast-check-3.17.1.tgz", + "integrity": "sha512-jIKXJVe6ZO0SpwEgVtEVujTf8TwjI9wMXFJCjsDHUB3RroUbXBgF4kOSz3A7MW0UR26aqsoB8i9O2mjtjERAiA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "peer": true, + "dependencies": { + "pure-rand": "^6.1.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-east-asian-width": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.2.0.tgz", + "integrity": "sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz", + "integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==", + "dependencies": { + "get-east-asian-width": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.0.0.tgz", + "integrity": "sha512-niTvB4gqvtof056rRIrTZvjNYE4rCUzO6X/X+kYjd7WFxXeJ0NwEFnRxX6ehkvv3jTwrXnNdtAak5XYZuIyPFw==", + "dependencies": { + "ansi-escapes": "^6.2.0", + "cli-cursor": "^4.0.0", + "slice-ansi": "^7.0.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/prom-client": { + "version": "15.1.2", + "resolved": "https://registry.npmjs.org/prom-client/-/prom-client-15.1.2.tgz", + "integrity": "sha512-on3h1iXb04QFLLThrmVYg1SChBQ9N1c+nKAjebBjokBqipddH3uxmOUcEkTnzmJ8Jh/5TSUnUqS40i2QB2dJHQ==", + "dependencies": { + "@opentelemetry/api": "^1.4.0", + "tdigest": "^0.1.1" + }, + "engines": { + "node": "^16 || ^18 || >=20" + } + }, + "node_modules/pure-rand": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "peer": true + }, + "node_modules/restore-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", + "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/slice-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz", + "integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==", + "dependencies": { + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/string-width": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", + "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/substreams-sink": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/substreams-sink/-/substreams-sink-0.16.0.tgz", + "integrity": "sha512-wvkWsu0jyiRyPCKrAl852A0MeUazlGSXMeg7WDRK9fe1vLZopAts3wn2ODuM10R3e8QJxqFQgmNH9+Qipr5rVg==", + "dependencies": { + "@substreams/core": "^0.15.1", + "@substreams/manifest": "^0.14.1", + "@substreams/node": "^0.6.2", + "commander": "latest", + "dotenv": "latest", + "prom-client": "latest", + "tslog": "latest" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/substreams-sink-csv": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/substreams-sink-csv/-/substreams-sink-csv-0.3.1.tgz", + "integrity": "sha512-pj9DS1tuuvxZM1gTG9+vHwzm0OxZPXNgk71nI/RJzjFRqLD+TLPZ6tvF/xAWgb25MZBiY8zcG2jlCK8H8TKa2w==", + "dependencies": { + "@substreams/sink-database-changes": "^0.3.6", + "@substreams/sink-entity-changes": "^0.3.11", + "log-update": "latest", + "substreams-sink": "^0.16.0" + }, + "bin": { + "substreams-sink-csv": "dist/bin/cli.mjs" + } + }, + "node_modules/tdigest": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/tdigest/-/tdigest-0.1.2.tgz", + "integrity": "sha512-+G0LLgjjo9BZX2MfdvPfH+MKLCrxlXSYec5DaPYP1fe6Iyhf0/fSmJ0bFiZ1F8BT6cGXl2LpltQptzjXKWEkKA==", + "dependencies": { + "bintrees": "1.0.2" + } + }, + "node_modules/tslog": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/tslog/-/tslog-4.9.2.tgz", + "integrity": "sha512-wBM+LRJoNl34Bdu8mYEFxpvmOUedpNUwMNQB/NcuPIZKwdDde6xLHUev3bBjXQU7gdurX++X/YE7gLH8eXYsiQ==", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/fullstack-build/tslog?sponsor=1" + } + }, + "node_modules/undici": { + "version": "5.28.4", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz", + "integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==", + "dependencies": { + "@fastify/busboy": "^2.0.0" + }, + "engines": { + "node": ">=14.0" + } + }, + "node_modules/wrap-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/yaml": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.1.tgz", + "integrity": "sha512-pIXzoImaqmfOrL7teGUBt/T7ZDnyeGBWyXQBvOVhLkWLN37GXv8NMLK406UY6dS51JfcQHsmcW5cJ441bHg6Lg==", + "peer": true, + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/zod": { + "version": "3.22.5", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.5.tgz", + "integrity": "sha512-HqnGsCdVZ2xc0qWPLdO25WnseXThh0kEYKIdV5F/hTHO75hNZFp8thxSeHhiPrHZKrFTo1SOgkAj9po5bexZlw==", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + } + } +} diff --git a/curve-finance/package.json b/curve-finance/package.json new file mode 100644 index 00000000..52ea1cc9 --- /dev/null +++ b/curve-finance/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "substreams-sink-csv": "^0.3.1" + } +} diff --git a/curve-finance/proto/contract.proto b/curve-finance/proto/contract.proto index add2764a..4e7e4f74 100644 --- a/curve-finance/proto/contract.proto +++ b/curve-finance/proto/contract.proto @@ -27,6 +27,7 @@ message PoolFee { optional uint64 fee = 2; optional uint64 admin_fee = 3; + repeated string admin_balances = 4; int64 log_index = 5; int64 block_number = 6; diff --git a/curve-finance/src/common/constants.rs b/curve-finance/src/common/constants.rs index e23af3ec..ee3cfc62 100644 --- a/curve-finance/src/common/constants.rs +++ b/curve-finance/src/common/constants.rs @@ -1 +1,6 @@ -pub const REGISTRY_ADDRESS: &str = "0x094d12e5b541784701fd8d65f11fc0598fbc6332"; \ No newline at end of file +pub const REGISTRY_ADDRESS: &str = "0x094d12e5b541784701fd8d65f11fc0598fbc6332"; + +pub const POOLS_DEPLOYED_BEFORE_FACTORIES: [&str; 2] = [ + "0x445fe580ef8d70ff569ab36e80c647af338db351", // 13479484 - amDAI_amUSDC_amUSDT + "0xc2d95eef97ec6c17551d45e77b590dc1f9117c67", // 15601242 - amwbtc_renbtcp +]; \ No newline at end of file diff --git a/curve-finance/src/lib.rs b/curve-finance/src/lib.rs index 6470a6dc..f48ded08 100644 --- a/curve-finance/src/lib.rs +++ b/curve-finance/src/lib.rs @@ -2,5 +2,6 @@ mod abi; mod common; mod modules; mod pb; +mod store_key; pub use modules::*; diff --git a/curve-finance/src/modules/2_store_pools.rs b/curve-finance/src/modules/2_store_pools.rs index 6254d781..32c9bf95 100644 --- a/curve-finance/src/modules/2_store_pools.rs +++ b/curve-finance/src/modules/2_store_pools.rs @@ -2,11 +2,16 @@ use substreams::store::StoreNew; use substreams::store::StoreSetIfNotExists; use substreams::store::StoreSetIfNotExistsString; +use crate::common::constants; use crate::pb::contract::v1::Pools; #[substreams::handlers::store] pub fn store_pools(pools_created: Pools, store: StoreSetIfNotExistsString) { for pool in pools_created.pools { - store.set_if_not_exists(0, &pool.address, &pool.address); + store.set_if_not_exists(0, &pool.address, &"Added".to_string()); + } + + for pool in constants::POOLS_DEPLOYED_BEFORE_FACTORIES { + store.set_if_not_exists(0, pool.to_string(), &"Added".to_string()); } } diff --git a/curve-finance/src/modules/3_map_pool_fees.rs b/curve-finance/src/modules/3_map_pool_fees.rs deleted file mode 100644 index 714dfec5..00000000 --- a/curve-finance/src/modules/3_map_pool_fees.rs +++ /dev/null @@ -1,62 +0,0 @@ -use substreams::log; -use substreams::scalar::BigInt; -use substreams::store::{StoreGet, StoreGetString}; -use substreams_ethereum::pb::eth::rpc::RpcResponse; -use substreams_ethereum::pb::eth::v2::{self as eth}; -use substreams_ethereum::rpc::RpcBatch; -use substreams_helper::hex::Hexable; - -use crate::abi::pool_contract::functions::{AdminFee, Fee}; -use crate::pb::contract::v1::{PoolFee, PoolFees}; - -#[substreams::handlers::map] -pub fn map_pool_fees( - blk: eth::Block, - pools_store: StoreGetString, -) -> Result { - let mut fees: Vec = vec![]; - - for log in blk.logs() { - if pools_store - .get_last(log.address().to_owned().to_hex()) - .is_none() - { - continue; - } - - let pool_fees = get_pool_fees(log.address().to_vec()); - - fees.push(PoolFee { - address: log.address().to_owned().to_hex(), - - fee: RpcBatch::decode::<_, Fee>(&pool_fees[0]).map(|x| x.to_u64()), - admin_fee: RpcBatch::decode::<_, Fee>(&pool_fees[1]).map(|x| x.to_u64()), - // admin_balances: admin_balances, - - log_index: log.index() as i64, - block_number: blk.number as i64, - block_timestmap: Some(blk.timestamp().to_owned()), - - transaction_index: log.receipt.transaction.index as i64, - transaction_hash: log.receipt.transaction.hash.to_hex(), - }) - } - - Ok(PoolFees { fees }) -} - -fn get_pool_fees(contract: Vec) -> Vec { - let batch = RpcBatch::new(); - - let responses = batch - .add(Fee {}, contract.clone()) - .add(AdminFee {}, contract.clone()) - .execute() - .unwrap() - .responses; - - // let fee = RpcBatch::decode::<_, Fee>(&responses[0]); - // let admin_fee = RpcBatch::decode::<_, AdminFee>(&responses[1]); - - responses -} diff --git a/curve-finance/src/modules/3_store_pool_admin_balances.rs b/curve-finance/src/modules/3_store_pool_admin_balances.rs new file mode 100644 index 00000000..71d194db --- /dev/null +++ b/curve-finance/src/modules/3_store_pool_admin_balances.rs @@ -0,0 +1,98 @@ +use substreams::scalar::BigInt; +use substreams::store::StoreGet; +use substreams::store::StoreNew; +use substreams::store::StoreSet; +use substreams::store::{StoreGetString, StoreSetBigInt}; + +use substreams_ethereum::pb::eth::{rpc::RpcResponse, v2 as eth}; +use substreams_ethereum::rpc::RpcBatch; +use substreams_helper::hex::Hexable; + +use crate::abi::pool_contract::functions::AdminBalances; +use crate::store_key::StoreKey; + +#[substreams::handlers::store] +pub fn store_pool_admin_balances( + blk: eth::Block, + pools_store: StoreGetString, + output_store: StoreSetBigInt, +) { + for calls in blk.calls() { + let address = calls.call.address.clone(); + + if pools_store.get_last(&address.to_hex()).is_none() { + continue; + } + + let admin_balances = get_pool_admin_balances(address.clone()); + + output_store.set( + calls.call.end_ordinal, + StoreKey::Pool.get_unique_key(&address.to_hex()), + &BigInt::one(), + ); + output_store.set( + calls.call.end_ordinal, + StoreKey::AdminBalanceToken0.get_unique_key(&address.to_hex()), + RpcBatch::decode::<_, AdminBalances>(&admin_balances[0]) + .unwrap_or(BigInt::zero()) + .as_ref(), + ); + output_store.set( + calls.call.end_ordinal, + StoreKey::AdminBalanceToken1.get_unique_key(&address.to_hex()), + RpcBatch::decode::<_, AdminBalances>(&admin_balances[1]) + .unwrap_or(BigInt::zero()) + .as_ref(), + ); + output_store.set( + calls.call.end_ordinal, + StoreKey::AdminBalanceToken2.get_unique_key(&address.to_hex()), + RpcBatch::decode::<_, AdminBalances>(&admin_balances[2]) + .unwrap_or(BigInt::zero()) + .as_ref(), + ); + output_store.set( + calls.call.end_ordinal, + StoreKey::AdminBalanceToken3.get_unique_key(&address.to_hex()), + RpcBatch::decode::<_, AdminBalances>(&admin_balances[3]) + .unwrap_or(BigInt::zero()) + .as_ref(), + ); + } +} + +fn get_pool_admin_balances(contract: Vec) -> Vec { + let batch = RpcBatch::new(); + + let responses = batch + .add( + AdminBalances { + arg0: BigInt::from(0), + }, + contract.clone(), + ) + .add( + AdminBalances { + arg0: BigInt::from(1), + }, + contract.clone(), + ) + .add( + AdminBalances { + arg0: BigInt::from(2), + }, + contract.clone(), + ) + .add( + AdminBalances { + arg0: BigInt::from(3), + }, + contract.clone(), + ) + .execute() + .unwrap() + .responses; + + responses +} diff --git a/curve-finance/src/modules/4_map_pool_fees.rs b/curve-finance/src/modules/4_map_pool_fees.rs new file mode 100644 index 00000000..66341c0f --- /dev/null +++ b/curve-finance/src/modules/4_map_pool_fees.rs @@ -0,0 +1,106 @@ +use substreams::log; +use substreams::scalar::BigInt; +use substreams::store::{DeltaBigInt, Deltas, StoreGet, StoreGetBigInt}; +use substreams_ethereum::pb::eth::rpc::RpcResponse; +use substreams_ethereum::pb::eth::v2::{self as eth}; +use substreams_ethereum::rpc::RpcBatch; +use substreams_helper::hex::Hexable; + +use crate::abi::pool_contract::functions::{AdminFee, Fee}; +use crate::pb::contract::v1::{PoolFee, PoolFees}; +use crate::store_key::StoreKey; + +#[substreams::handlers::map] +pub fn map_pool_fees( + blk: eth::Block, + admin_balances: StoreGetBigInt, + admin_balance_deltas: Deltas, +) -> Result { + let mut fees: Vec = vec![]; + + for calls in blk.calls() { + let address = calls.call.address.clone(); + + if admin_balances + .get_last(StoreKey::Pool.get_unique_key(&address.to_hex())) + .is_none() + { + continue; + } + + let admin_balances = get_admin_balances( + &admin_balance_deltas, + &address.to_hex(), + calls.call.end_ordinal, + ); + + if admin_balances.iter().any(|x| x < &BigInt::zero()) + || admin_balances.iter().all(|x| x == &BigInt::zero()) + { + log::debug!("Admin Balances unchanged."); + continue; + } + + let pool_fees = get_pool_fees(address.clone()); + + fees.push(PoolFee { + address: address.clone().to_hex(), + + fee: RpcBatch::decode::<_, Fee>(&pool_fees[0]).map(|x| x.to_u64()), + admin_fee: RpcBatch::decode::<_, Fee>(&pool_fees[1]).map(|x| x.to_u64()), + + admin_balances: admin_balances.iter().map(|x| x.to_string()).collect(), + + log_index: 0 as i64, + block_number: blk.number as i64, + block_timestmap: Some(blk.timestamp().to_owned()), + + transaction_index: calls.transaction.index as i64, + transaction_hash: calls.transaction.hash.to_hex(), + }) + } + + Ok(PoolFees { fees }) +} + +fn get_pool_fees(contract: Vec) -> Vec { + let batch = RpcBatch::new(); + + let responses = batch + .add(Fee {}, contract.clone()) + .add(AdminFee {}, contract.clone()) + .execute() + .unwrap() + .responses; + + responses +} + +fn get_admin_balances( + admin_balance_deltas: &Deltas, + address: &String, + ordinal: u64, +) -> Vec { + let mut balances = vec![BigInt::zero(); 4]; + + for delta in admin_balance_deltas.deltas.iter() { + match delta { + ref x if x.key == StoreKey::AdminBalanceToken0.get_unique_key(address) => { + balances[0] = delta.new_value.clone() - delta.old_value.clone(); + } + ref x if x.key == StoreKey::AdminBalanceToken1.get_unique_key(address) => { + balances[1] = delta.new_value.clone() - delta.old_value.clone(); + } + ref x if x.key == StoreKey::AdminBalanceToken2.get_unique_key(address) => { + balances[2] = delta.new_value.clone() - delta.old_value.clone(); + } + ref x if x.key == StoreKey::AdminBalanceToken3.get_unique_key(address) => { + balances[3] = delta.new_value.clone() - delta.old_value.clone(); + } + + _ => {} + } + } + + balances +} diff --git a/curve-finance/src/modules/mod.rs b/curve-finance/src/modules/mod.rs index dab74819..0f6e0b12 100644 --- a/curve-finance/src/modules/mod.rs +++ b/curve-finance/src/modules/mod.rs @@ -4,9 +4,13 @@ mod map_pool_created; #[path = "2_store_pools.rs"] mod store_pools; -#[path = "3_map_pool_fees.rs"] +#[path = "3_store_pool_admin_balances.rs"] +mod store_pool_admin_balances; + +#[path = "4_map_pool_fees.rs"] mod map_pool_fees; pub use map_pool_created::map_pool_created; pub use store_pools::store_pools; +pub use store_pool_admin_balances::store_pool_admin_balances; pub use map_pool_fees::map_pool_fees; diff --git a/curve-finance/src/store_key.rs b/curve-finance/src/store_key.rs new file mode 100644 index 00000000..154870a8 --- /dev/null +++ b/curve-finance/src/store_key.rs @@ -0,0 +1,24 @@ +#[derive(Clone)] +pub enum StoreKey { + Pool, + AdminBalanceToken0, + AdminBalanceToken1, + AdminBalanceToken2, + AdminBalanceToken3, +} + +impl StoreKey { + pub fn get_unique_key(&self, key: &str) -> String { + format!("{}:{}", self.unique_id(), key) + } + + pub fn unique_id(&self) -> String { + match self { + StoreKey::Pool => "Pool".to_string(), + StoreKey::AdminBalanceToken0 => "ABT0".to_string(), + StoreKey::AdminBalanceToken1 => "ABT1".to_string(), + StoreKey::AdminBalanceToken2 => "ABT2".to_string(), + StoreKey::AdminBalanceToken3 => "ABT3".to_string(), + } + } +} diff --git a/curve-finance/substreams.yaml b/curve-finance/substreams.yaml index 20048366..29eaad4c 100644 --- a/curve-finance/substreams.yaml +++ b/curve-finance/substreams.yaml @@ -26,7 +26,7 @@ binaries: modules: - name: map_pool_created kind: map - initialBlock: 13991825 + initialBlock: 13479484 inputs: - source: sf.ethereum.type.v2.Block output: @@ -39,12 +39,22 @@ modules: inputs: - map: map_pool_created + - name: store_pool_admin_balances + kind: store + updatePolicy: set + valueType: bigint + inputs: + - source: sf.ethereum.type.v2.Block + - store: store_pools + - name: map_pool_fees kind: map - initialBlock: 13991825 + initialBlock: 13479484 inputs: - source: sf.ethereum.type.v2.Block - - store: store_pools + - store: store_pool_admin_balances + - store: store_pool_admin_balances + mode: deltas output: type: proto:messari.contract.v1.PoolFees From 44638ab51baa4bec6c2d8c7333d4c0cae0d227bc Mon Sep 17 00:00:00 2001 From: Harsh Date: Thu, 9 May 2024 09:00:30 +0530 Subject: [PATCH 3/3] Add graph_out module and add all events through which pools can be deployed --- curve-finance/Makefile | 4 +- curve-finance/abi/address_provider.json | 159 +++++++++++ curve-finance/abi/erc20.json | 222 +++++++++++++++ curve-finance/abi/pool_contract.json | 8 + curve-finance/abi/registry_contract.json | 94 ++++++ curve-finance/proto/contract.proto | 15 + curve-finance/schema.graphql | 22 ++ curve-finance/src/abi.rs | 10 + curve-finance/src/common/constants.rs | 23 +- .../src/modules/1_map_factory_added.rs | 59 ++++ .../src/modules/1_map_pool_created.rs | 37 --- .../src/modules/2_store_factories.rs | 12 + .../src/modules/3_map_pool_created.rs | 267 ++++++++++++++++++ .../{2_store_pools.rs => 4_store_pools.rs} | 0 ...nces.rs => 5_store_pool_admin_balances.rs} | 0 ..._map_pool_fees.rs => 6_map_fees_entity.rs} | 90 +++--- curve-finance/src/modules/7_graph_out.rs | 10 + curve-finance/src/modules/mod.rs | 25 +- curve-finance/subgraph.yaml | 17 ++ curve-finance/substreams.yaml | 32 ++- substreams-helper/src/common.rs | 6 + 21 files changed, 1013 insertions(+), 99 deletions(-) create mode 100644 curve-finance/abi/address_provider.json create mode 100644 curve-finance/abi/erc20.json create mode 100644 curve-finance/schema.graphql create mode 100644 curve-finance/src/modules/1_map_factory_added.rs delete mode 100644 curve-finance/src/modules/1_map_pool_created.rs create mode 100644 curve-finance/src/modules/2_store_factories.rs create mode 100644 curve-finance/src/modules/3_map_pool_created.rs rename curve-finance/src/modules/{2_store_pools.rs => 4_store_pools.rs} (100%) rename curve-finance/src/modules/{3_store_pool_admin_balances.rs => 5_store_pool_admin_balances.rs} (100%) rename curve-finance/src/modules/{4_map_pool_fees.rs => 6_map_fees_entity.rs} (50%) create mode 100644 curve-finance/src/modules/7_graph_out.rs create mode 100644 curve-finance/subgraph.yaml diff --git a/curve-finance/Makefile b/curve-finance/Makefile index d41f73c0..d9426a1b 100644 --- a/curve-finance/Makefile +++ b/curve-finance/Makefile @@ -10,11 +10,11 @@ build: .PHONY: run run: - substreams run -e polygon.streamingfast.io:443 substreams.yaml map_pool_fees --debug-modules-initial-snapshot store_pool_admin_balances -s 13521257 + substreams run -e polygon.streamingfast.io:443 substreams.yaml map_pool_created -s 11153725 .PHONY: build_csv build_csv: - substreams-sink-csv -e polygon.substreams.pinax.network --manifest ./curve-finance-substream-v0.1.0.spkg --module-name map_pool_fees --start-block 13479484 + substreams-sink-csv -e polygon.substreams.pinax.network --manifest ./curve-finance-substream-v0.1.0.spkg --module-name map_pool_fees --start-block 13479484 --production-mode true .PHONY: pack pack: diff --git a/curve-finance/abi/address_provider.json b/curve-finance/abi/address_provider.json new file mode 100644 index 00000000..f1c3222b --- /dev/null +++ b/curve-finance/abi/address_provider.json @@ -0,0 +1,159 @@ +[ + { + "name": "NewAddressIdentifier", + "inputs": [ + { "type": "uint256", "name": "id", "indexed": true }, + { "type": "address", "name": "addr", "indexed": false }, + { "type": "string", "name": "description", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "AddressModified", + "inputs": [ + { "type": "uint256", "name": "id", "indexed": true }, + { "type": "address", "name": "new_address", "indexed": false }, + { "type": "uint256", "name": "version", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "CommitNewAdmin", + "inputs": [ + { "type": "uint256", "name": "deadline", "indexed": true }, + { "type": "address", "name": "admin", "indexed": true } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "NewAdmin", + "inputs": [{ "type": "address", "name": "admin", "indexed": true }], + "anonymous": false, + "type": "event" + }, + { + "outputs": [], + "inputs": [{ "type": "address", "name": "_admin" }], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "name": "get_registry", + "outputs": [{ "type": "address", "name": "" }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 1061 + }, + { + "name": "max_id", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 1258 + }, + { + "name": "get_address", + "outputs": [{ "type": "address", "name": "" }], + "inputs": [{ "type": "uint256", "name": "_id" }], + "stateMutability": "view", + "type": "function", + "gas": 1308 + }, + { + "name": "add_new_id", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [ + { "type": "address", "name": "_address" }, + { "type": "string", "name": "_description" } + ], + "stateMutability": "nonpayable", + "type": "function", + "gas": 291275 + }, + { + "name": "set_address", + "outputs": [{ "type": "bool", "name": "" }], + "inputs": [ + { "type": "uint256", "name": "_id" }, + { "type": "address", "name": "_address" } + ], + "stateMutability": "nonpayable", + "type": "function", + "gas": 182430 + }, + { + "name": "unset_address", + "outputs": [{ "type": "bool", "name": "" }], + "inputs": [{ "type": "uint256", "name": "_id" }], + "stateMutability": "nonpayable", + "type": "function", + "gas": 101348 + }, + { + "name": "commit_transfer_ownership", + "outputs": [{ "type": "bool", "name": "" }], + "inputs": [{ "type": "address", "name": "_new_admin" }], + "stateMutability": "nonpayable", + "type": "function", + "gas": 74048 + }, + { + "name": "apply_transfer_ownership", + "outputs": [{ "type": "bool", "name": "" }], + "inputs": [], + "stateMutability": "nonpayable", + "type": "function", + "gas": 60125 + }, + { + "name": "revert_transfer_ownership", + "outputs": [{ "type": "bool", "name": "" }], + "inputs": [], + "stateMutability": "nonpayable", + "type": "function", + "gas": 21400 + }, + { + "name": "admin", + "outputs": [{ "type": "address", "name": "" }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 1331 + }, + { + "name": "transfer_ownership_deadline", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 1361 + }, + { + "name": "future_admin", + "outputs": [{ "type": "address", "name": "" }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 1391 + }, + { + "name": "get_id_info", + "outputs": [ + { "type": "address", "name": "addr" }, + { "type": "bool", "name": "is_active" }, + { "type": "uint256", "name": "version" }, + { "type": "uint256", "name": "last_modified" }, + { "type": "string", "name": "description" } + ], + "inputs": [{ "type": "uint256", "name": "arg0" }], + "stateMutability": "view", + "type": "function", + "gas": 12168 + } +] diff --git a/curve-finance/abi/erc20.json b/curve-finance/abi/erc20.json new file mode 100644 index 00000000..3b0ab2f1 --- /dev/null +++ b/curve-finance/abi/erc20.json @@ -0,0 +1,222 @@ +[ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "balance", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "_spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + } +] \ No newline at end of file diff --git a/curve-finance/abi/pool_contract.json b/curve-finance/abi/pool_contract.json index 33ca7d39..161e0365 100644 --- a/curve-finance/abi/pool_contract.json +++ b/curve-finance/abi/pool_contract.json @@ -1,4 +1,12 @@ [ + { + "stateMutability": "view", + "type": "function", + "name": "minter", + "inputs": [], + "outputs": [{ "name": "", "type": "address" }], + "gas": 3000 + }, { "name": "TokenExchange", "inputs": [ diff --git a/curve-finance/abi/registry_contract.json b/curve-finance/abi/registry_contract.json index 6b8afd31..2c35221c 100644 --- a/curve-finance/abi/registry_contract.json +++ b/curve-finance/abi/registry_contract.json @@ -1,4 +1,98 @@ [ + { + "name": "BasePoolAdded", + "inputs": [{ "name": "base_pool", "type": "address", "indexed": false }], + "anonymous": false, + "type": "event" + }, + { + "name": "BasePoolAdded", + "inputs": [ + { "type": "address", "name": "base_pool", "indexed": false }, + { "type": "address", "name": "implementat", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "PlainPoolDeployed", + "inputs": [ + { "name": "coins", "type": "address[4]", "indexed": false }, + { "name": "A", "type": "uint256", "indexed": false }, + { "name": "fee", "type": "uint256", "indexed": false }, + { "name": "deployer", "type": "address", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "PlainPoolDeployed", + "inputs": [ + { "name": "coins", "type": "address[4]", "indexed": false }, + { "name": "A", "type": "uint256", "indexed": false }, + { "name": "fee", "type": "uint256", "indexed": false }, + { "name": "deployer", "type": "address", "indexed": false }, + { "name": "pool", "type": "address", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "MetaPoolDeployed", + "inputs": [ + { "name": "coin", "type": "address", "indexed": false }, + { "name": "base_pool", "type": "address", "indexed": false }, + { "name": "A", "type": "uint256", "indexed": false }, + { "name": "fee", "type": "uint256", "indexed": false }, + { "name": "deployer", "type": "address", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "CryptoPoolDeployed", + "inputs": [ + { "name": "token", "type": "address", "indexed": false }, + { "name": "coins", "type": "address[2]", "indexed": false }, + { "name": "A", "type": "uint256", "indexed": false }, + { "name": "gamma", "type": "uint256", "indexed": false }, + { "name": "mid_fee", "type": "uint256", "indexed": false }, + { "name": "out_fee", "type": "uint256", "indexed": false }, + { "name": "allowed_extra_profit", "type": "uint256", "indexed": false }, + { "name": "fee_gamma", "type": "uint256", "indexed": false }, + { "name": "adjustment_step", "type": "uint256", "indexed": false }, + { "name": "admin_fee", "type": "uint256", "indexed": false }, + { "name": "ma_half_time", "type": "uint256", "indexed": false }, + { "name": "initial_price", "type": "uint256", "indexed": false }, + { "name": "deployer", "type": "address", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "TricryptoPoolDeployed", + "inputs": [ + { "name": "pool", "type": "address", "indexed": false }, + { "name": "name", "type": "string", "indexed": false }, + { "name": "symbol", "type": "string", "indexed": false }, + { "name": "weth", "type": "address", "indexed": false }, + { "name": "coins", "type": "address[3]", "indexed": false }, + { "name": "math", "type": "address", "indexed": false }, + { "name": "salt", "type": "bytes32", "indexed": false }, + { "name": "packed_precisions", "type": "uint256", "indexed": false }, + { "name": "packed_A_gamma", "type": "uint256", "indexed": false }, + { "name": "packed_fee_params", "type": "uint256", "indexed": false }, + { + "name": "packed_rebalancing_params", + "type": "uint256", + "indexed": false + }, + { "name": "packed_prices", "type": "uint256", "indexed": false }, + { "name": "deployer", "type": "address", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, { "name": "PoolAdded", "inputs": [ diff --git a/curve-finance/proto/contract.proto b/curve-finance/proto/contract.proto index 4e7e4f74..b401a8dc 100644 --- a/curve-finance/proto/contract.proto +++ b/curve-finance/proto/contract.proto @@ -3,6 +3,21 @@ syntax = "proto3"; import "google/protobuf/timestamp.proto"; package messari.contract.v1; +message Factories { + repeated Factory factories = 1; +} + +message Factory { + string address = 1; + + int64 log_index = 2; + int64 block_number = 3; + + google.protobuf.Timestamp block_timestmap = 4; + int64 transaction_index = 5; + string transaction_hash = 6; +} + message Pools { repeated Pool pools = 1; } diff --git a/curve-finance/schema.graphql b/curve-finance/schema.graphql new file mode 100644 index 00000000..4872bc9d --- /dev/null +++ b/curve-finance/schema.graphql @@ -0,0 +1,22 @@ +type Fees @entity { + " {Address of the pool}-{block number} " + id: ID! + + " Address of the curve pool " + pool: String! + + " Fee of the curve pool " + fee: BigInt! + + " Admin fee of the curve pool " + adminFee: BigInt! + + " Admin balances of the curve pool " + adminBalances: [BigInt!]! + + " Block number of this event " + blockNumber: BigInt! + + " Timestamp of this event " + timestamp: BigInt! +} diff --git a/curve-finance/src/abi.rs b/curve-finance/src/abi.rs index 84650b31..71d4065b 100644 --- a/curve-finance/src/abi.rs +++ b/curve-finance/src/abi.rs @@ -1,4 +1,14 @@ // DO NOT EDIT - the file is generated by build script +#[rustfmt::skip] +#[allow(unused_imports)] +#[path = "../target/abi/address_provider.rs"] +pub mod address_provider; + +#[rustfmt::skip] +#[allow(unused_imports)] +#[path = "../target/abi/erc20.rs"] +pub mod erc20; + #[rustfmt::skip] #[allow(unused_imports)] #[path = "../target/abi/pool_contract.rs"] diff --git a/curve-finance/src/common/constants.rs b/curve-finance/src/common/constants.rs index ee3cfc62..be66a205 100644 --- a/curve-finance/src/common/constants.rs +++ b/curve-finance/src/common/constants.rs @@ -1,6 +1,21 @@ -pub const REGISTRY_ADDRESS: &str = "0x094d12e5b541784701fd8d65f11fc0598fbc6332"; +pub const ADRRESS_PROVIDER: &str = "0x0000000022d53366457f9d5e68ec105046fc4383"; -pub const POOLS_DEPLOYED_BEFORE_FACTORIES: [&str; 2] = [ - "0x445fe580ef8d70ff569ab36e80c647af338db351", // 13479484 - amDAI_amUSDC_amUSDT - "0xc2d95eef97ec6c17551d45e77b590dc1f9117c67", // 15601242 - amwbtc_renbtcp +// Ethereum missing pools +pub const POOLS_DEPLOYED_BEFORE_FACTORIES: [&str; 16] = [ + "0x42d7025938bec20b69cbae5a77421082407f053a", + "0x7f55dde206dbad629c080068923b36fe9d6bdbef", + "0xd81da8d904b52208541bade1bd6595d8a251f8dd", + "0x8038c01a0390a8c547446a0b2c18fc9aefecc10c", + "0x3e01dd8a5e1fb3481f0f589056b428fc308af0fb", + "0xe7a24ef0c5e95ffb0f6684b813a78f2a3ad7d171", + "0x0f9cb53ebe405d49a0bbdbd291a65ff571bc83e1", + "0x4f062658eaaf2c1ccf8c8e36d6824cdf41167956", + "0x3ef6a01a0f81d6046290f3e2a8c5b843e738e604", + "0x36965b1a6b97c1b33416e5d53fb5621ade1f1e80", + "0x071c661b4deefb59e2a3ddb20db036821eee8f4b", + "0x8474ddbe98f5aa3179b3b3f5942d724afcdec9f6", + "0x890f4e345b1daed0367a877a1612f86a1f86985f", + "0xc18cc39da8b11da8c3541c598ee022258f9744da", + "0x618788357d0ebd8a37e763adab3bc575d54c2c7d", + "0xc25099792e9349c7dd09759744ea681c7de2cb66", ]; \ No newline at end of file diff --git a/curve-finance/src/modules/1_map_factory_added.rs b/curve-finance/src/modules/1_map_factory_added.rs new file mode 100644 index 00000000..e2440d49 --- /dev/null +++ b/curve-finance/src/modules/1_map_factory_added.rs @@ -0,0 +1,59 @@ +use std::str::FromStr; + +use ethabi::ethereum_types::Address; +use substreams_ethereum::pb::eth::v2::{self as eth}; +use substreams_helper::event_handler::EventHandler; +use substreams_helper::hex::Hexable; + +use crate::abi::address_provider::events::{AddressModified, NewAddressIdentifier}; +use crate::common::constants; +use crate::pb::contract::v1::{Factories, Factory}; + +#[substreams::handlers::map] +pub fn map_factory_added(blk: eth::Block) -> Result { + let mut factories: Vec = vec![]; + + get_factory_from_new_address_identified_events(&blk, &mut factories); + get_factory_from_address_modified_events(&blk, &mut factories); + Ok(Factories { factories }) +} + +fn get_factory_from_new_address_identified_events(blk: ð::Block, factories: &mut Vec) { + let mut on_new_address_identified = + |event: NewAddressIdentifier, tx: ð::TransactionTrace, log: ð::Log| { + factories.push(Factory { + address: event.addr.to_hex(), + log_index: log.index as i64, + block_number: blk.number as i64, + block_timestmap: Some(blk.timestamp().to_owned()), + transaction_index: tx.index as i64, + transaction_hash: tx.hash.to_hex(), + }) + }; + + let mut eh = EventHandler::new(blk); + eh.filter_by_address(vec![Address::from_str(constants::ADRRESS_PROVIDER).unwrap()]); + + eh.on::(&mut on_new_address_identified); + eh.handle_events(); +} + +fn get_factory_from_address_modified_events(blk: ð::Block, factories: &mut Vec) { + let mut on_new_address_identified = + |event: AddressModified, tx: ð::TransactionTrace, log: ð::Log| { + factories.push(Factory { + address: event.new_address.to_hex(), + log_index: log.index as i64, + block_number: blk.number as i64, + block_timestmap: Some(blk.timestamp().to_owned()), + transaction_index: tx.index as i64, + transaction_hash: tx.hash.to_hex(), + }) + }; + + let mut eh = EventHandler::new(blk); + eh.filter_by_address(vec![Address::from_str(constants::ADRRESS_PROVIDER).unwrap()]); + + eh.on::(&mut on_new_address_identified); + eh.handle_events(); +} diff --git a/curve-finance/src/modules/1_map_pool_created.rs b/curve-finance/src/modules/1_map_pool_created.rs deleted file mode 100644 index 36d5492d..00000000 --- a/curve-finance/src/modules/1_map_pool_created.rs +++ /dev/null @@ -1,37 +0,0 @@ -use std::str::FromStr; - -use ethabi::ethereum_types::Address; -use substreams_ethereum::pb::eth::v2::{self as eth}; -use substreams_helper::event_handler::EventHandler; -use substreams_helper::hex::Hexable; - -use crate::abi::registry_contract::events::PoolAdded; -use crate::common::constants; -use crate::pb::contract::v1::{Pool, Pools}; - -#[substreams::handlers::map] -pub fn map_pool_created(blk: eth::Block) -> Result { - let mut pools: Vec = vec![]; - - get_pools(&blk, &mut pools); - Ok(Pools { pools }) -} - -fn get_pools(blk: ð::Block, pools: &mut Vec) { - let mut on_pair_created = |event: PoolAdded, tx: ð::TransactionTrace, log: ð::Log| { - pools.push(Pool { - address: event.pool.to_hex(), - log_index: log.index as i64, - block_number: blk.number as i64, - block_timestmap: Some(blk.timestamp().to_owned()), - transaction_index: tx.index as i64, - transaction_hash: tx.hash.to_hex(), - }) - }; - - let mut eh = EventHandler::new(blk); - eh.filter_by_address(vec![Address::from_str(constants::REGISTRY_ADDRESS).unwrap()]); - - eh.on::(&mut on_pair_created); - eh.handle_events(); -} diff --git a/curve-finance/src/modules/2_store_factories.rs b/curve-finance/src/modules/2_store_factories.rs new file mode 100644 index 00000000..094b82f0 --- /dev/null +++ b/curve-finance/src/modules/2_store_factories.rs @@ -0,0 +1,12 @@ +use substreams::store::StoreNew; +use substreams::store::StoreSetIfNotExists; +use substreams::store::StoreSetIfNotExistsString; + +use crate::pb::contract::v1::Factories; + +#[substreams::handlers::store] +pub fn store_factories(factories_added: Factories, store: StoreSetIfNotExistsString) { + for factory in factories_added.factories { + store.set_if_not_exists(0, &factory.address, &"Added".to_string()); + } +} diff --git a/curve-finance/src/modules/3_map_pool_created.rs b/curve-finance/src/modules/3_map_pool_created.rs new file mode 100644 index 00000000..b44abcbd --- /dev/null +++ b/curve-finance/src/modules/3_map_pool_created.rs @@ -0,0 +1,267 @@ +use substreams::store::{StoreGet, StoreGetString}; +use substreams_ethereum::pb::eth::v2::{self as eth}; +use substreams_ethereum::{Event, NULL_ADDRESS}; +use substreams_helper::event_handler::EventHandler; +use substreams_helper::hex::Hexable; + +use crate::abi::erc20::events::Transfer; +use crate::abi::pool_contract::functions::Minter; +use crate::abi::registry_contract::events::{ + BasePoolAdded1 as BasePoolAdded, BasePoolAdded1 as BasePoolAddedWithImplementation, + PlainPoolDeployed1 as PlainPoolDeployed, PlainPoolDeployed2 as PlainPoolDeployedWithPool, +}; +use crate::abi::registry_contract::events::{ + CryptoPoolDeployed, MetaPoolDeployed, PoolAdded, TricryptoPoolDeployed, +}; +use crate::pb::contract::v1::{Pool, Pools}; + +#[substreams::handlers::map] +pub fn map_pool_created( + blk: eth::Block, + factories_store: StoreGetString, +) -> Result { + let mut pools: Vec = vec![]; + + get_pool_from_deploy_crypto_pool_deployed_events(&blk, &factories_store, &mut pools); + get_pool_from_tri_deploy_crypto_pool_deployed_events(&blk, &factories_store, &mut pools); + + get_pool_from_plain_pool_deployed_events(&blk, &factories_store, &mut pools); + get_pool_from_plain_pool_deployed_with_pool_events(&blk, &factories_store, &mut pools); + + get_pool_from_base_pool_added_events(&blk, &factories_store, &mut pools); + get_pool_from_base_pool_added_with_implementation_events(&blk, &factories_store, &mut pools); + + get_pool_from_meta_pool_deployed_events(&blk, &factories_store, &mut pools); + get_pool_pool_addded_events(&blk, &factories_store, &mut pools); + + Ok(Pools { pools }) +} + +fn get_pool_from_deploy_crypto_pool_deployed_events( + blk: ð::Block, + factories: &StoreGetString, + pools: &mut Vec, +) { + let mut on_crypto_pool_deployed = + |event: CryptoPoolDeployed, tx: ð::TransactionTrace, log: ð::Log| { + let lp_address = event.token; + let pool_address_option = Minter {}.call(lp_address); + + let pool_address = match pool_address_option { + Some(x) => x.to_hex(), + None => return, + }; + + pools.push(Pool { + address: pool_address, + log_index: log.index as i64, + block_number: blk.number as i64, + block_timestmap: Some(blk.timestamp().to_owned()), + transaction_index: tx.index as i64, + transaction_hash: tx.hash.to_hex(), + }) + }; + + let mut eh = EventHandler::new(blk); + eh.filter_by_address(factories); + + eh.on::(&mut on_crypto_pool_deployed); + eh.handle_events(); +} + +fn get_pool_from_tri_deploy_crypto_pool_deployed_events( + blk: ð::Block, + factories: &StoreGetString, + pools: &mut Vec, +) { + let mut on_tri_crypto_pool_deployed = + |event: TricryptoPoolDeployed, tx: ð::TransactionTrace, log: ð::Log| { + pools.push(Pool { + address: event.pool.to_hex(), + log_index: log.index as i64, + block_number: blk.number as i64, + block_timestmap: Some(blk.timestamp().to_owned()), + transaction_index: tx.index as i64, + transaction_hash: tx.hash.to_hex(), + }) + }; + + let mut eh = EventHandler::new(blk); + eh.filter_by_address(factories); + + eh.on::(&mut on_tri_crypto_pool_deployed); + eh.handle_events(); +} + +fn find_pool_from_plain_pool_deployed_event( + tx: ð::TransactionTrace, + log: ð::Log, +) -> Option { + tx.calls + .iter() + .filter(|call| !call.state_reverted) + .flat_map(|call| call.logs.iter()) + .find_map(|transfer_log| { + if let Some(transfer) = Transfer::match_and_decode(transfer_log) { + if transfer.from == NULL_ADDRESS + && (transfer.to == transfer_log.address || transfer.to == log.address) + { + return Some(transfer_log.address.to_hex()); + } + } + None + }) +} + +fn get_pool_from_plain_pool_deployed_events( + blk: ð::Block, + factories: &StoreGetString, + pools: &mut Vec, +) { + let mut on_plain_pool_deployed = + |_event: PlainPoolDeployed, tx: ð::TransactionTrace, log: ð::Log| { + let pool_address = match find_pool_from_plain_pool_deployed_event(tx, log) { + Some(x) => x, + None => return, + }; + + pools.push(Pool { + address: pool_address, + log_index: log.index as i64, + block_number: blk.number as i64, + block_timestmap: Some(blk.timestamp().to_owned()), + transaction_index: tx.index as i64, + transaction_hash: tx.hash.to_hex(), + }) + }; + + let mut eh = EventHandler::new(blk); + eh.filter_by_address(factories); + + eh.on::(&mut on_plain_pool_deployed); + eh.handle_events(); +} + +fn get_pool_from_plain_pool_deployed_with_pool_events( + blk: ð::Block, + factories: &StoreGetString, + pools: &mut Vec, +) { + let mut on_plain_pool_deployed = + |event: PlainPoolDeployedWithPool, tx: ð::TransactionTrace, log: ð::Log| { + pools.push(Pool { + address: event.pool.to_hex(), + log_index: log.index as i64, + block_number: blk.number as i64, + block_timestmap: Some(blk.timestamp().to_owned()), + transaction_index: tx.index as i64, + transaction_hash: tx.hash.to_hex(), + }) + }; + + let mut eh = EventHandler::new(blk); + eh.filter_by_address(factories); + + eh.on::(&mut on_plain_pool_deployed); + eh.handle_events(); +} + +fn get_pool_from_base_pool_added_events( + blk: ð::Block, + factories: &StoreGetString, + pools: &mut Vec, +) { + let mut on_base_pool_added = + |event: BasePoolAdded, tx: ð::TransactionTrace, log: ð::Log| { + pools.push(Pool { + address: event.base_pool.to_hex(), + log_index: log.index as i64, + block_number: blk.number as i64, + block_timestmap: Some(blk.timestamp().to_owned()), + transaction_index: tx.index as i64, + transaction_hash: tx.hash.to_hex(), + }) + }; + + let mut eh = EventHandler::new(blk); + eh.filter_by_address(factories); + + eh.on::(&mut on_base_pool_added); + eh.handle_events(); +} + +fn get_pool_from_base_pool_added_with_implementation_events( + blk: ð::Block, + factories: &StoreGetString, + pools: &mut Vec, +) { + let mut on_base_pool_added = + |event: BasePoolAddedWithImplementation, tx: ð::TransactionTrace, log: ð::Log| { + pools.push(Pool { + address: event.base_pool.to_hex(), + log_index: log.index as i64, + block_number: blk.number as i64, + block_timestmap: Some(blk.timestamp().to_owned()), + transaction_index: tx.index as i64, + transaction_hash: tx.hash.to_hex(), + }) + }; + + let mut eh = EventHandler::new(blk); + eh.filter_by_address(factories); + + eh.on::(&mut on_base_pool_added); + eh.handle_events(); +} + +fn get_pool_from_meta_pool_deployed_events( + blk: ð::Block, + factories: &StoreGetString, + pools: &mut Vec, +) { + let mut on_meta_pool_deployed = + |_event: MetaPoolDeployed, tx: ð::TransactionTrace, log: ð::Log| { + let pool_address = match find_pool_from_plain_pool_deployed_event(tx, log) { + Some(x) => x, + None => return, + }; + + pools.push(Pool { + address: pool_address, + log_index: log.index as i64, + block_number: blk.number as i64, + block_timestmap: Some(blk.timestamp().to_owned()), + transaction_index: tx.index as i64, + transaction_hash: tx.hash.to_hex(), + }) + }; + + let mut eh = EventHandler::new(blk); + eh.filter_by_address(factories); + + eh.on::(&mut on_meta_pool_deployed); + eh.handle_events(); +} + +fn get_pool_pool_addded_events( + blk: ð::Block, + factories: &StoreGetString, + pools: &mut Vec, +) { + let mut on_pool_added = |event: PoolAdded, tx: ð::TransactionTrace, log: ð::Log| { + pools.push(Pool { + address: event.pool.to_hex(), + log_index: log.index as i64, + block_number: blk.number as i64, + block_timestmap: Some(blk.timestamp().to_owned()), + transaction_index: tx.index as i64, + transaction_hash: tx.hash.to_hex(), + }) + }; + + let mut eh = EventHandler::new(blk); + eh.filter_by_address(factories); + + eh.on::(&mut on_pool_added); + eh.handle_events(); +} diff --git a/curve-finance/src/modules/2_store_pools.rs b/curve-finance/src/modules/4_store_pools.rs similarity index 100% rename from curve-finance/src/modules/2_store_pools.rs rename to curve-finance/src/modules/4_store_pools.rs diff --git a/curve-finance/src/modules/3_store_pool_admin_balances.rs b/curve-finance/src/modules/5_store_pool_admin_balances.rs similarity index 100% rename from curve-finance/src/modules/3_store_pool_admin_balances.rs rename to curve-finance/src/modules/5_store_pool_admin_balances.rs diff --git a/curve-finance/src/modules/4_map_pool_fees.rs b/curve-finance/src/modules/6_map_fees_entity.rs similarity index 50% rename from curve-finance/src/modules/4_map_pool_fees.rs rename to curve-finance/src/modules/6_map_fees_entity.rs index 66341c0f..b4f3915c 100644 --- a/curve-finance/src/modules/4_map_pool_fees.rs +++ b/curve-finance/src/modules/6_map_fees_entity.rs @@ -1,25 +1,27 @@ -use substreams::log; +use std::collections::HashSet; + use substreams::scalar::BigInt; use substreams::store::{DeltaBigInt, Deltas, StoreGet, StoreGetBigInt}; +use substreams_entity_change::pb::entity::{entity_change, EntityChange, EntityChanges}; use substreams_ethereum::pb::eth::rpc::RpcResponse; use substreams_ethereum::pb::eth::v2::{self as eth}; use substreams_ethereum::rpc::RpcBatch; use substreams_helper::hex::Hexable; use crate::abi::pool_contract::functions::{AdminFee, Fee}; -use crate::pb::contract::v1::{PoolFee, PoolFees}; use crate::store_key::StoreKey; #[substreams::handlers::map] -pub fn map_pool_fees( +pub fn map_fees_entity( blk: eth::Block, admin_balances: StoreGetBigInt, admin_balance_deltas: Deltas, -) -> Result { - let mut fees: Vec = vec![]; +) -> Result { + let mut entity_changes: Vec = vec![]; + let mut unique_pools_set: HashSet> = HashSet::new(); for calls in blk.calls() { - let address = calls.call.address.clone(); + let address: Vec = calls.call.address.clone(); if admin_balances .get_last(StoreKey::Pool.get_unique_key(&address.to_hex())) @@ -28,47 +30,51 @@ pub fn map_pool_fees( continue; } - let admin_balances = get_admin_balances( - &admin_balance_deltas, - &address.to_hex(), - calls.call.end_ordinal, - ); - - if admin_balances.iter().any(|x| x < &BigInt::zero()) - || admin_balances.iter().all(|x| x == &BigInt::zero()) - { - log::debug!("Admin Balances unchanged."); - continue; - } - - let pool_fees = get_pool_fees(address.clone()); - - fees.push(PoolFee { - address: address.clone().to_hex(), - - fee: RpcBatch::decode::<_, Fee>(&pool_fees[0]).map(|x| x.to_u64()), - admin_fee: RpcBatch::decode::<_, Fee>(&pool_fees[1]).map(|x| x.to_u64()), - - admin_balances: admin_balances.iter().map(|x| x.to_string()).collect(), - - log_index: 0 as i64, - block_number: blk.number as i64, - block_timestmap: Some(blk.timestamp().to_owned()), + unique_pools_set.insert(address); + } - transaction_index: calls.transaction.index as i64, - transaction_hash: calls.transaction.hash.to_hex(), - }) + for pool in &unique_pools_set { + let id = [pool.to_hex(), blk.number.to_string()].join("-"); + + let mut fees_entity_change = + EntityChange::new("Fees", id.as_str(), 0, entity_change::Operation::Update); + + let pool_fees = get_pool_fees(pool); + + fees_entity_change + .change("id", id) + .change("pool", pool.to_hex()) + .change( + "fee", + RpcBatch::decode::<_, Fee>(&pool_fees[0]) + .map(|x| x.to_u64()) + .unwrap_or_default(), + ) + .change( + "adminFee", + RpcBatch::decode::<_, Fee>(&pool_fees[1]) + .map(|x| x.to_u64()) + .unwrap_or_default(), + ) + .change( + "adminBalances", + get_admin_balances(&admin_balance_deltas, &pool.to_hex()), + ) + .change("blockNumber", blk.number) + .change("timestamp", blk.timestamp_seconds()); + + entity_changes.push(fees_entity_change); } - Ok(PoolFees { fees }) + Ok(EntityChanges { entity_changes }) } -fn get_pool_fees(contract: Vec) -> Vec { +fn get_pool_fees(contract: &Vec) -> Vec { let batch = RpcBatch::new(); let responses = batch - .add(Fee {}, contract.clone()) - .add(AdminFee {}, contract.clone()) + .add(Fee {}, contract.to_vec()) + .add(AdminFee {}, contract.to_vec()) .execute() .unwrap() .responses; @@ -76,11 +82,7 @@ fn get_pool_fees(contract: Vec) -> Vec { responses } -fn get_admin_balances( - admin_balance_deltas: &Deltas, - address: &String, - ordinal: u64, -) -> Vec { +fn get_admin_balances(admin_balance_deltas: &Deltas, address: &String) -> Vec { let mut balances = vec![BigInt::zero(); 4]; for delta in admin_balance_deltas.deltas.iter() { diff --git a/curve-finance/src/modules/7_graph_out.rs b/curve-finance/src/modules/7_graph_out.rs new file mode 100644 index 00000000..8756e8c5 --- /dev/null +++ b/curve-finance/src/modules/7_graph_out.rs @@ -0,0 +1,10 @@ +use substreams_entity_change::pb::entity::{EntityChange, EntityChanges}; + +#[substreams::handlers::map] +pub fn graph_out(fees_entity_map: EntityChanges) -> Result { + let mut entity_changes: Vec = vec![]; + + entity_changes.extend(fees_entity_map.entity_changes); + + Ok(EntityChanges { entity_changes }) +} diff --git a/curve-finance/src/modules/mod.rs b/curve-finance/src/modules/mod.rs index 0f6e0b12..e04a10e5 100644 --- a/curve-finance/src/modules/mod.rs +++ b/curve-finance/src/modules/mod.rs @@ -1,16 +1,27 @@ -#[path = "1_map_pool_created.rs"] +#[path = "1_map_factory_added.rs"] +mod map_factory_added; + +#[path = "2_store_factories.rs"] +mod store_factories; + +#[path = "3_map_pool_created.rs"] mod map_pool_created; -#[path = "2_store_pools.rs"] +#[path = "4_store_pools.rs"] mod store_pools; -#[path = "3_store_pool_admin_balances.rs"] +#[path = "5_store_pool_admin_balances.rs"] mod store_pool_admin_balances; -#[path = "4_map_pool_fees.rs"] -mod map_pool_fees; +#[path = "6_map_fees_entity.rs"] +mod map_fees_entity; + +#[path = "7_graph_out.rs"] +mod graph_out; +pub use graph_out::graph_out; +pub use map_factory_added::map_factory_added; +pub use map_fees_entity::map_fees_entity; pub use map_pool_created::map_pool_created; -pub use store_pools::store_pools; pub use store_pool_admin_balances::store_pool_admin_balances; -pub use map_pool_fees::map_pool_fees; +pub use store_pools::store_pools; diff --git a/curve-finance/subgraph.yaml b/curve-finance/subgraph.yaml new file mode 100644 index 00000000..ee8dffc5 --- /dev/null +++ b/curve-finance/subgraph.yaml @@ -0,0 +1,17 @@ +specVersion: 0.0.4 +description: Curve Finance Fees powered by substreams +repository: https://github.com/messari/substreams +schema: + file: ./schema.graphql + +dataSources: + - kind: substreams + name: curve_finance_fee + network: mainnet + source: + package: + moduleName: graph_out + file: curve-finance-substream-v0.1.0.spkg + mapping: + kind: substreams/graph-entities + apiVersion: 0.0.5 diff --git a/curve-finance/substreams.yaml b/curve-finance/substreams.yaml index 29eaad4c..d03e58b5 100644 --- a/curve-finance/substreams.yaml +++ b/curve-finance/substreams.yaml @@ -24,11 +24,27 @@ binaries: file: "../target/wasm32-unknown-unknown/release/curve_finance_substream.wasm" modules: + - name: map_factory_added + kind: map + initialBlock: 11153725 + inputs: + - source: sf.ethereum.type.v2.Block + output: + type: proto:messari.contract.v1.Factories + + - name: store_factories + kind: store + updatePolicy: set_if_not_exists + valueType: string + inputs: + - map: map_factory_added + - name: map_pool_created kind: map - initialBlock: 13479484 + initialBlock: 11153725 inputs: - source: sf.ethereum.type.v2.Block + - store: store_factories output: type: proto:messari.contract.v1.Pools @@ -47,15 +63,21 @@ modules: - source: sf.ethereum.type.v2.Block - store: store_pools - - name: map_pool_fees + - name: map_fees_entity kind: map - initialBlock: 13479484 + initialBlock: 11153725 inputs: - source: sf.ethereum.type.v2.Block - store: store_pool_admin_balances - store: store_pool_admin_balances mode: deltas output: - type: proto:messari.contract.v1.PoolFees + type: proto:substreams.entity.v1.EntityChanges -network: polygon + - name: graph_out + kind: map + initialBlock: 11153725 + inputs: + - map: map_fees_entity + output: + type: proto:substreams.entity.v1.EntityChanges diff --git a/substreams-helper/src/common.rs b/substreams-helper/src/common.rs index 7f71dd45..7951880b 100644 --- a/substreams-helper/src/common.rs +++ b/substreams-helper/src/common.rs @@ -32,6 +32,12 @@ impl HasAddresser for StoreGetString { } } +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()