From fa7149437a1d0e4d9522cf6d7ceac203b8171ed7 Mon Sep 17 00:00:00 2001 From: FJ-Riveros Date: Tue, 19 Nov 2024 09:13:22 +0100 Subject: [PATCH 01/16] feat: add CI --- .github/workflows/main-push-and-pr.yml | 45 ++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 .github/workflows/main-push-and-pr.yml diff --git a/.github/workflows/main-push-and-pr.yml b/.github/workflows/main-push-and-pr.yml new file mode 100644 index 0000000..0c6b255 --- /dev/null +++ b/.github/workflows/main-push-and-pr.yml @@ -0,0 +1,45 @@ +# This workflow will install Python dependencies, run tests and lint with a single version of Python +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python + +name: Python application + +on: + push: + branches: ["main"] + pull_request: + branches: ["main"] + +permissions: + contents: read + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Set up Python 3.10 + uses: actions/setup-python@v3 + with: + python-version: "3.10" + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install flake8 mypy + if [ -f requirements.txt ]; then pip install -r requirements.txt; fi + if [ -f requirements-dev.txt ]; then pip install -r requirements-dev.txt; fi + + - name: Lint with flake8 + run: | + # stop the build if there are Python syntax errors or undefined names + flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics + # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide + flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics + + - name: Type check with mypy + run: mypy . --explicit-package-bases --pretty --check-untyped-defs + + - name: Set PYTHONPATH + run: echo "PYTHONPATH=$GITHUB_WORKSPACE" >> $GITHUB_ENV \ No newline at end of file From 0cfb43f4ed6bb6a0c3b90ce15733d06283f795f6 Mon Sep 17 00:00:00 2001 From: FJ-Riveros Date: Tue, 19 Nov 2024 09:36:08 +0100 Subject: [PATCH 02/16] chore: move integration ids to the integrations folder --- constants/allstake.py | 23 +- constants/balancer.py | 2 +- constants/curve.py | 2 +- constants/integration_ids.py | 158 -------- constants/lyra.py | 39 +- constants/radiant.py | 17 +- integrations/allstake_susde.py | 2 +- integrations/allstake_usde.py | 2 +- integrations/ambient_scroll.py | 2 +- integrations/balancer_integration.py | 2 +- integrations/beefy_arbitrum_usde.py | 6 +- integrations/beefy_fraxtal_usde.py | 6 +- integrations/beefy_mantle_usde.py | 6 +- integrations/beefy_optimism_usde.py | 6 +- integrations/equilibria_karak_susde_sept.py | 17 +- integrations/equilibria_karak_usde_sept.py | 17 +- integrations/equilibria_rusde_sept.py | 11 +- integrations/equilibria_susde_apr_expiry.py | 17 +- integrations/equilibria_susde_sept.py | 11 +- integrations/equilibria_usde_expiry.py | 16 +- integrations/equilibria_zircuit_usde_aug.py | 17 +- integrations/euler_susde.py | 2 +- integrations/euler_usde.py | 19 +- integrations/firm_susde.py | 2 +- integrations/fluid_susde.py | 55 ++- integrations/fluid_usde.py | 57 ++- integrations/fluid_usde_t4.py | 42 +- integrations/gmx_usde_poitions_aug.py | 33 +- integrations/gmx_usde_usdc_aug.py | 10 +- integrations/gmx_wsteth_usde_aug.py | 10 +- integrations/hyperdrive.py | 63 ++- integrations/integration_ids.py | 401 ++++++++++++++++++++ integrations/lendle_usde.py | 7 +- integrations/lyra_susde_bull.py | 35 +- integrations/merchantmoe_lbt_integration.py | 32 +- integrations/nuri.py | 59 ++- integrations/pendle_lpt_integration.py | 6 +- integrations/pendle_yt_integration.py | 2 +- integrations/penpie_ena_aug.py | 13 +- integrations/penpie_ena_oct.py | 13 +- integrations/penpie_karak_susde_sep.py | 16 +- integrations/penpie_karak_usde_sep.py | 16 +- integrations/penpie_mellow_rsena_sep.py | 9 +- integrations/penpie_mellow_rusde_sep.py | 9 +- integrations/penpie_susde_25apr.py | 13 +- integrations/penpie_susde_dec.py | 9 +- integrations/penpie_susde_july.py | 13 +- integrations/penpie_susde_oct.py | 9 +- integrations/penpie_susde_sep.py | 13 +- integrations/penpie_usde_aug_Arb.py | 9 +- integrations/penpie_usde_dec.py | 13 +- integrations/penpie_usde_july.py | 13 +- integrations/penpie_usde_nov_arb.py | 13 +- integrations/penpie_usde_oct.py | 13 +- integrations/penpie_zircuit_usde_jun.py | 16 +- integrations/radiant_usde.py | 23 +- integrations/ramses.py | 46 ++- integrations/splice_susde_lpt.py | 4 +- integrations/splice_susde_yt.py | 3 +- integrations/splice_usde_lpt.py | 4 +- integrations/splice_usde_yt.py | 3 +- integrations/stakedao_susde_july.py | 4 +- integrations/stakedao_susde_sept.py | 4 +- integrations/stakedao_usde_july.py | 4 +- integrations/synthetix.py | 2 +- integrations/template.py | 2 +- integrations/term_susde.py | 50 +-- integrations/velodrome_mode_susde.py | 7 +- integrations/velodrome_mode_usde.py | 7 +- models/integration.py | 2 +- utils/allstake.py | 25 +- utils/beefy.py | 9 +- utils/equilibria.py | 53 +-- utils/gmx.py | 47 ++- utils/penpie.py | 60 +-- utils/rho_markets.py | 44 ++- utils/splice.py | 146 ++++--- utils/stakedao.py | 2 +- 78 files changed, 1297 insertions(+), 678 deletions(-) delete mode 100644 constants/integration_ids.py create mode 100644 integrations/integration_ids.py diff --git a/constants/allstake.py b/constants/allstake.py index 96a524b..d81fe3e 100644 --- a/constants/allstake.py +++ b/constants/allstake.py @@ -4,7 +4,7 @@ from web3.contract.contract import Contract from web3 import Web3 from constants.chains import Chain -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID with open("abi/ERC20_abi.json") as f: erc20_abi = json.load(f) @@ -17,6 +17,7 @@ class StrategyConfig(TypedDict): strategy: Contract page_size: int + contract = W3_BY_CHAIN[Chain.ETHEREUM]["w3"].eth.contract ALLSTAKE_STRATEGIES: Dict[IntegrationID, StrategyConfig] = { @@ -24,10 +25,16 @@ class StrategyConfig(TypedDict): start=20810640, chain=Chain.ETHEREUM, underlying=contract( - address=Web3.to_checksum_address("0x4c9edd5852cd905f086c759e8383e09bff1e68b3"), abi=erc20_abi + address=Web3.to_checksum_address( + "0x4c9edd5852cd905f086c759e8383e09bff1e68b3" + ), + abi=erc20_abi, ), strategy=contract( - address=Web3.to_checksum_address("0x8B6bF38B812BE4749577303FB8D222576957ff44"), abi=erc20_abi + address=Web3.to_checksum_address( + "0x8B6bF38B812BE4749577303FB8D222576957ff44" + ), + abi=erc20_abi, ), page_size=5000, ), @@ -35,10 +42,16 @@ class StrategyConfig(TypedDict): start=20811020, chain=Chain.ETHEREUM, underlying=contract( - address=Web3.to_checksum_address("0x9d39a5de30e57443bff2a8307a4256c8797a3497"), abi=erc20_abi + address=Web3.to_checksum_address( + "0x9d39a5de30e57443bff2a8307a4256c8797a3497" + ), + abi=erc20_abi, ), strategy=contract( - address=Web3.to_checksum_address("0x5d083d71F7A531F543070b78740880F5A346B53a"), abi=erc20_abi + address=Web3.to_checksum_address( + "0x5d083d71F7A531F543070b78740880F5A346B53a" + ), + abi=erc20_abi, ), page_size=5000, ), diff --git a/constants/balancer.py b/constants/balancer.py index 223413c..0f3f31c 100644 --- a/constants/balancer.py +++ b/constants/balancer.py @@ -3,7 +3,7 @@ from typing import Dict, Optional from constants.chains import Chain -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID ## If you want to integrate another Balancer Pool, first add it to the IntegrationID enum in integration_ids.py ## Then, add a new entry to the INTEGRATION_CONFIGS dictionary below. Aura integration is optional. diff --git a/constants/curve.py b/constants/curve.py index d5f87c1..19b3768 100644 --- a/constants/curve.py +++ b/constants/curve.py @@ -1,7 +1,7 @@ from constants.summary_columns import SummaryColumn from dataclasses import dataclass from constants.chains import Chain -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID @dataclass diff --git a/constants/integration_ids.py b/constants/integration_ids.py deleted file mode 100644 index a9ff6c3..0000000 --- a/constants/integration_ids.py +++ /dev/null @@ -1,158 +0,0 @@ -from enum import Enum - -from constants.integration_token import Token - - -class IntegrationID(Enum): - EXAMPLE = ('example', 'Example', Token.USDE) - PENDLE_USDE_LPT = ('pendle_effective_lpt_held', 'Pendle USDe LPT') - PENDLE_USDE_YT = ('pendle_yt_held', 'Pendle USDe YT') - PENDLE_SUSDE_LPT_APRIL_EXPIRY = ('pendle_effective_susde_apr_lpt_held', 'Pendle sUSDe LPT (April expiry)', Token.SUSDE) - PENDLE_SUSDE_YT_APRIL_EXPIRY = ('pendle_susde_apr_yt_held', 'Pendle sUSDe YT (April expiry)', Token.SUSDE) - PENDLE_SUSDE_LPT_JULY_EXPIRY = ('pendle_effective_susde_jul_lpt_held', 'Pendle sUSDe LPT (July expiry)', Token.SUSDE) - PENDLE_SUSDE_YT_JULY_EXPIRY = ('pendle_susde_jul_yt_held', 'Pendle sUSDe YT (July expiry)', Token.SUSDE) - PENDLE_SUSDE_LPT_SEPT_EXPIRY = ('pendle_effective_susde_sep_lpt_held', 'Pendle sUSDe LPT (Sept expiry)', Token.SUSDE) - PENDLE_SUSDE_YT_SEPT_EXPIRY = ('pendle_susde_sep_yt_held', 'Pendle sUSDe YT (Sept expiry)', Token.SUSDE) - PENDLE_ENA_LPT = ('pendle_effective_ena_lpt_held', 'Pendle ENA LPT', Token.ENA) - PENDLE_ENA_YT = ('pendle_ena_yt_held', 'Pendle ENA YT', Token.ENA) - PENDLE_ARBITRUM_USDE_LPT = ('pendle_arbtrium_effective_lpt_bal', 'Pendle Arbitrum USDe LPT') - PENDLE_ARBITRUM_USDE_YT = ('pendle_arbtrium_yt_bal', 'Pendle Arbitrum USDe YT') - PENDLE_KARAK_USDE_LPT = ('pendle_karak_usde_lpt_held', 'Pendle Karak USDe LPT') - PENDLE_KARAK_USDE_YT = ('pendle_karak_usde_yt_held', 'Pendle Karak USDe YT') - PENDLE_KARAK_SUSDE_LPT = ('pendle_karak_susde_lpt_held', 'Pendle Karak sUSDe LPT', Token.SUSDE) - PENDLE_KARAK_SUSDE_YT = ('pendle_karak_susde_yt_held', 'Pendle Karak sUSDe YT', Token.SUSDE) - PENDLE_MANTLE_USDE_LPT = ('pendle_mantle_effective_lpt_bal', 'Pendle Mantle USDe LPT') - PENDLE_MANTLE_USDE_YT = ('pendle_mantle_yt_bal', 'Pendle Mantle USDe YT') - PENDLE_ZIRCUIT_USDE_LPT = ('pendle_effective_zircuit_usde_lpt_held', 'Pendle Zircuit USDe LPT') - PENDLE_ZIRCUIT_USDE_YT = ('pendle_zircuit_usde_yt_held', 'Pendle Zircuit USDe YT') - - # Stake DAO - STAKEDAO_SUSDE_JULY_LPT = ('stakedao_susde_july_effective_lpt_held', 'Stake DAO sUSDe July LPT', Token.SUSDE) - STAKEDAO_SUSDE_SEPT_LPT = ('stakedao_susde_sept_effective_lpt_held', 'Stake DAO sUSDe Sept LPT', Token.SUSDE) - STAKEDAO_USDE_JULY_LPT = ('stakedao_usde_july_effective_lpt_held', 'Stake DAO USDe July LPT', Token.USDE) - - #PENPIE - PENPIE_SUSDE_JULY_LPT=('penpie_susde_july_effective_lpt_held', 'PENPIE sUSDe July LPT', Token.SUSDE) - PENPIE_Karak_sUSDe_26SEP2024_LPT= ('PENPIE_Karak_sUSDe_26SEP2024_effective_lpt_held', 'Karak_sUSDe_26SEP2024', Token.SUSDE) - PENPIE_Karak_USDE_26SEP2024_LPT= ('PENPIE_Karak_USDE_26SEP2024_effective_lpt_held', 'Karak_USDE_26SEP2024', Token.USDE) - PENPIE_sUSDe25APR2024_LPT= ('PENPIE_sUSDe25APR2024_effective_lpt_held', 'sUSDe25APR2024', Token.SUSDE) - PENPIE_sUSDe26SEP2024_LPT= ('PENPIE_sUSDe26SEP2024_effective_lpt_held', 'sUSDe26SEP2024', Token.SUSDE) - PENPIE_USDe25JUL2024_LPT= ('PENPIE_USDe25JUL2024_effective_lpt_held', 'USDe25JUL2024', Token.USDE) - PENPIE_Zircuit_USDe27JUN2024_LPT= ('PENPIE_Zircuit_USDe27JUN2024_effective_lpt_held', 'Zircuit_USDe27JUN2024', Token.USDE) - PENPIE_ENA29AUG2024_LPT= ('PENPIE_ENA29AUG2024_effective_lpt_held', 'ENA29AUG2024', Token.ENA) - PENPIE_USDE_ARB_AUG2024_LPT= ('PENPIE_USDE_ARB_AUG2024_effective_lpt_held', 'USDE_ARB_AUG2024', Token.USDE) - PENPIE_USDe_24OCT2024_LPT=('PENPIE_USDe_24OCT202_effective_lpt_held4','USDe_24OCT2024',Token.USDE) - PENPIE_ENA_31OCT2024_LPT=('PENPIE_ENA_31OCT2024_effective_lpt_held','ENA_31OCT2024',Token.ENA) - PENPIE_rsUSDe_26SEP2024_LPT =('PENPIE_rsUSDe_26SEP2024_effective_lpt_held','rsUSDe_26SEP2024',Token.USDE) - PENPIE_USDe_26DEC2024_LPT=('PENPIE_USDe_26DEC2024_effective_lpt_held','USDe_26DEC2024',Token.USDE) - PENPIE_sUSDE_26DEC2024_LPT=('PENPIE_sUSDE_26DEC2024_effective_lpt_held','sUSDE_26DEC2024',Token.SUSDE) - PENPIE_sUSDE_24OCT2024_LPT=('PENPIE_sUSDE_24OCT2024_effective_lpt_held','sUSDE_24OCT2024',Token.SUSDE) - PENPIE_rsENA_26SEP2024_LPT =('PENPIE_rsENA_26SEP2024_effective_lpt_held','rsENA_26SEP2024',Token.ENA) - PENPIE_USDE_ARB_NOV2024_LPT= ('PENPIE_USDE_ARB_NOV2024_effective_lpt_held', 'USDE_ARB_NOV2024', Token.USDE) - - # EQUILIBRIA - EQUILIBRIA_SUSDE_SEPT_LPT = ('equilibria_susde_sept_effective_lpt_held', 'Equilibria sUSDe Sept LPT', Token.SUSDE) - EQUILIBRIA_Karak_SUSDE_SEPT_SEPT = ('equilibria_karak_susde_sept_effective_lpt_held', 'Equilibria Karak sUSDe Sept LPT', Token.SUSDE) - EQUILIBRIA_Karak_USDE_SEPT_LPT = ('equilibria_karak_usde_sept_effective_lpt_held', 'Equilibria Karak USDe Sept LPT', Token.USDE) - EQUILIBRIA_Zircuit_USDE_AUG_LPT = ('equilibria_zircuit_usde_aug_effective_lpt_held', 'Equilibria Zircuit USDe Aug LPT', Token.USDE) - EQUILIBRIA_rUSDE_SEPT_LPT = ('equilibria_rusde_sept_effective_lpt_held', 'Equilibria rUSDe Sept LPT') - EQUILIBRIA_USDE_LPT_EXPIRY = ('equilibria_usde_lpt_expiry_effective_lpt_held', 'Equilibria USDe LPT Expiry', Token.USDE) - EQUILIBRIA_SUSDE_APR_EXPIRY = ('equilibria_susde_apr_expiry_effective_lpt_held', 'Equilibria sUSDe Apr Expiry', Token.SUSDE) - - # EulerV2 - EULER_USDE = ('euler_usde_deposit', 'EulerV2 USDe', Token.USDE) - EULER_SUSDE = ('euler_susde_deposit', 'EulerV2 sUSDe', Token.SUSDE) - - # Term Finance - TERM_SUSDE = ('term_susde_held', 'Term Finance sUSDe', Token.SUSDE) - - # Synthetix - SYNTHETIX_USDE_LP = ('synthetix_usde_arb_lp_bal', 'Synthetix V3 Arbitrum USDe LP', Token.USDE) - - # Lendle - LENDLE_USDE_LPT = ('lendle_usde_lpt_bal', 'Lendle Mantle USDe LPT', Token.USDE) - - # Lyra - LYRA_SUSDE_BULL_MAINNET = ("lyra_susde_bull_mainnet", "Lyra sUSDe Bull Vault Mainnet", Token.SUSDE) - LYRA_SUSDE_BULL_ARBITRUM = ("lyra_susde_bull_arbitrum", "Lyra sUSDe Bull Vault Arbitrum", Token.SUSDE) - LYRA_SUSDE_EXCHANGE_DEPOSIT= ("lyra_susde_exchange_deposit", "Lyra sUSDe Exchange Deposits", Token.SUSDE) - # Velodrome - VELODROME_MODE_USDE = ('velodrome_mode_usde', 'Velodrome Mode USDe', Token.USDE) - VELODROME_MODE_SUSDE = ('velodrome_mode_susde', 'Velodrome Mode sUSDe', Token.SUSDE) - # Ambient - AMBIENT_SCROLL_LP = ('ambient_usde_scroll_lp_bal', 'Ambient Scroll LP', Token.USDE) - - # Balancer - BALANCER_ARBITRUM_GHO_USDE = ('balancer_arbitrum_gho_usde', 'Balancer Arbitrum GHO/USDe', Token.USDE) - BALANCER_ARBITRUM_WAGHO_USDE = ('balancer_arbitrum_wagho_usde', 'Balancer Arbitrum waGHO/USDe', Token.USDE) - BALANCER_ARBITRUM_GYD_SUSDE = ('balancer_arbitrum_gyd_susde', 'Balancer Arbitrum GYD/sUSDe', Token.SUSDE) - BALANCER_ARBITRUM_SUSDE_SFRAX = ('balancer_arbitrum_susde_sfrax', 'Balancer Arbitrum sUSDe/sFRAX', Token.SUSDE) - BALANCER_ARBITRUM_SUSDE_USDC = ('balancer_arbitrum_susde_usdc', 'Balancer Arbitrum sUSDe/USDC', Token.SUSDE) - BALANCER_ETHEREUM_WSTETH_SUSDE = ('balancer_ethereum_wsteth_susde', 'Balancer Ethereum 50wstETH/50sUSDe', Token.SUSDE) - BALANCER_ETHEREUM_BAOUSD_SUSDE = ('balancer_ethereum_baousd_susde', 'Balancer Ethereum baoUSD/sUSDe', Token.SUSDE) - BALANCER_ETHEREUM_SUSDE_USDC = ('balancer_ethereum_susde_usdc', 'Balancer Ethereum sUSDe/USDC', Token.SUSDE) - BALANCER_ETHEREUM_SUSDE_GYD = ('balancer_ethereum_susde_gyd', 'Balancer Ethereum sUSDe/GYD', Token.SUSDE) - BALANCER_FRAXTAL_FRAX_USDE = ('balancer_fraxtal_frax_usde', 'Balancer Fraxtal FRAX/USDe', Token.USDE) - BALANCER_FRAXTAL_SFRAX_SDAI_SUSDE = ('balancer_fraxtal_sfrax_sdai_susde', 'Balancer Fraxtal sFRAX/sDAI/sUSDe', Token.SUSDE) - BALANCER_FRAXTAL_FRAX_USDE_DAI_USDT_USDC = ('balancer_fraxtal_frax_usde_dai_usdt_usdc', 'Balancer Fraxtal FRAX/USDe/DAI/USDT/USDC', Token.USDE) - - # Nuri - NURI_USDE_LP = ('nuri_usde_lp_bal', 'Nuri USDe LP', Token.USDE) - - # Merchant Moe - MERCHANT_MOE_METH_USDE_LBT = ('merchant_moe_in_range_lbt_liq_held', "Merchant Moe mETH/USDe Liquidity Book Token") - # Rho Markets - RHO_MARKETS_USDE_LP = ('rho_markets_usde_scroll_lp_bal', 'Rho Markets Scroll USDe LP', Token.USDE) - # Ramses - RAMSES_USDE_LP = ('ramses_usde_lp_bal', 'Ramses USDe LP', Token.USDE) - - # Radiant - RADIANT_USDE_CORE_ARBITRUM = ('radiant_usde_arb', 'Radiant USDE Lending', Token.USDE) - - # Splice - SPLICE_USDE_YT = ('splice_usde_yt', 'Splice USDe YT', Token.USDE) - SPLICE_USDE_LPT = ('splice_usde_lpt', 'Splice USDe LPT', Token.USDE) - SPLICE_SUSDE_YT = ('splice_susde_yt', 'Splice SUSDe YT', Token.SUSDE) - SPLICE_SUSDE_LPT = ('splice_susde_lpt', 'Splice SUSDu LPT', Token.SUSDE) - - # GMX - GMX_USDE_POSITIONS = ('gmx_usde_positions', 'GMX USDe Positions', Token.USDE) - GMX_USDE_USDC_LP = ('gmx_usde_usdc_aug', 'GMX USDe/USDc LP', Token.USDE) - GMX_WSTETH_USDE_LP = ('gmx_wsteth_usde_aug', 'GMX wstETH/USDe LP', Token.USDE) - - # CURVE - CURVE_ETHEREUM_USDE_BORROWERS = ('curve_ethereum_usde_borrowers', 'Curve.fi Ethereum USDe Borrowers', Token.USDE) - CURVE_ETHEREUM_SUSDE_BORROWERS = ('curve_ethereum_susde_borrowers', 'Curve.fi Ethereum sUSDe Borrowers', Token.SUSDE) - - # Beefy - BEEFY_ARBITRUM_USDE = ('beefy_arbitrum_usde_held', 'Beefy Arbitrum USDe', Token.USDE) - BEEFY_FRAXTAL_USDE = ('beefy_fraxtal_usde_held', 'Beefy Fraxtal USDe', Token.USDE) - BEEFY_MANTLE_USDE = ('beefy_mantle_usde_held', 'Beefy Mantle USDe', Token.USDE) - BEEFY_OPTIMISM_USDE = ('beefy_optimism_usde_held', 'Beefy Optimism USDe', Token.USDE) - - # Allstake - ALLSTAKE_USDE = ('allstake_usde', 'Allstake USDe', Token.USDE) - ALLSTAKE_SUSDE = ('allstake_susde', 'Allstake sUSDe', Token.SUSDE) - - # Inverse Finance FiRM - FIRM_SUSDE = ('firm_susde', 'Inverse Finance FiRM sUSDe', Token.SUSDE) - - # Hyperdrive - HYPERDRIVE_SUSDE = ('hyperdrive_susde', 'ElementDAO 182 Day sUSDe Hyperdrive', Token.SUSDE) - - # Fluid - FLUID = ('Fluid_susde', 'Fluid sUSDe', Token.SUSDE) - - def __init__(self, column_name: str, description: str, token: Token = Token.USDE): - self.column_name = column_name - self.description = description - self.token = token - - def get_column_name(self) -> str: - return self.column_name - - def get_description(self) -> str: - return self.description - - def get_token(self) -> Token: - return self.token diff --git a/constants/lyra.py b/constants/lyra.py index 8d298e7..2ba1968 100644 --- a/constants/lyra.py +++ b/constants/lyra.py @@ -4,12 +4,13 @@ from web3.contract.contract import Contract from web3 import Web3 from constants.chains import Chain -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from enum import Enum with open("abi/ERC20_abi.json") as f: erc20_abi = json.load(f) + class DetailType(Enum): Vault = "Vault" Exchange = "Exchange" @@ -21,8 +22,8 @@ class LyraVaultDetails(TypedDict): chain: str page_size: int integration_token: Contract | None - bridge: Contract| None - vault_token: Contract| None + bridge: Contract | None + vault_token: Contract | None # NOTE: does not handle cross-chain transfers of vault tokens @@ -32,13 +33,22 @@ class LyraVaultDetails(TypedDict): start=20211445, chain=Chain.ETHEREUM, integration_token=W3_BY_CHAIN[Chain.ETHEREUM]["w3"].eth.contract( - address=Web3.to_checksum_address("0x9d39a5de30e57443bff2a8307a4256c8797a3497"), abi=erc20_abi + address=Web3.to_checksum_address( + "0x9d39a5de30e57443bff2a8307a4256c8797a3497" + ), + abi=erc20_abi, ), # sUSDe bridge=W3_BY_CHAIN[Chain.ETHEREUM]["w3"].eth.contract( - address=Web3.to_checksum_address("0xE3E96892D30E0ee1a8131BAf87c891201F7137bf"), abi=erc20_abi + address=Web3.to_checksum_address( + "0xE3E96892D30E0ee1a8131BAf87c891201F7137bf" + ), + abi=erc20_abi, ), vault_token=W3_BY_CHAIN[Chain.ETHEREUM]["w3"].eth.contract( - address=Web3.to_checksum_address("0x1d080C689B930f9dEa69CB3B4Bc6b8c213DFC2ad"), abi=erc20_abi + address=Web3.to_checksum_address( + "0x1d080C689B930f9dEa69CB3B4Bc6b8c213DFC2ad" + ), + abi=erc20_abi, ), page_size=5000, ), @@ -47,13 +57,22 @@ class LyraVaultDetails(TypedDict): start=227626020, chain=Chain.ARBITRUM, integration_token=W3_BY_CHAIN[Chain.ARBITRUM]["w3"].eth.contract( - address=Web3.to_checksum_address("0x211cc4dd073734da055fbf44a2b4667d5e5fe5d2"), abi=erc20_abi + address=Web3.to_checksum_address( + "0x211cc4dd073734da055fbf44a2b4667d5e5fe5d2" + ), + abi=erc20_abi, ), # sUSDe bridge=W3_BY_CHAIN[Chain.ARBITRUM]["w3"].eth.contract( - address=Web3.to_checksum_address("0x3c143EA5eBaB50ad6D2B2d14FA719234d1d38F1b"), abi=erc20_abi + address=Web3.to_checksum_address( + "0x3c143EA5eBaB50ad6D2B2d14FA719234d1d38F1b" + ), + abi=erc20_abi, ), vault_token=W3_BY_CHAIN[Chain.ARBITRUM]["w3"].eth.contract( - address=Web3.to_checksum_address("0x81494d722DDceDbA31ac40F28daFa66b207f232B"), abi=erc20_abi + address=Web3.to_checksum_address( + "0x81494d722DDceDbA31ac40F28daFa66b207f232B" + ), + abi=erc20_abi, ), page_size=20000, ), @@ -62,5 +81,5 @@ class LyraVaultDetails(TypedDict): start=11481048, chain=Chain.Lyra, page_size=20000, - ) + ), } diff --git a/constants/radiant.py b/constants/radiant.py index a931023..0cc9668 100644 --- a/constants/radiant.py +++ b/constants/radiant.py @@ -4,7 +4,7 @@ from web3.contract.contract import Contract from web3 import Web3 from constants.chains import Chain -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID with open("abi/radiant_r_token.json") as f: r_token_abi = json.load(f) @@ -25,14 +25,21 @@ class RadiantLendingDetails(TypedDict): IntegrationID.RADIANT_USDE_CORE_ARBITRUM: RadiantLendingDetails( start=247318247, chain=Chain.ARBITRUM, - collateral_address= Web3.to_checksum_address("0x5d3a1Ff2b6BAb83b63cd9AD0787074081a52ef34"), + collateral_address=Web3.to_checksum_address( + "0x5d3a1Ff2b6BAb83b63cd9AD0787074081a52ef34" + ), r_token_contract=W3_BY_CHAIN[Chain.ARBITRUM]["w3"].eth.contract( - address=Web3.to_checksum_address("0x19f0bE6a603967c72bE32a30915a38d52cA31Ae2"), abi=r_token_abi + address=Web3.to_checksum_address( + "0x19f0bE6a603967c72bE32a30915a38d52cA31Ae2" + ), + abi=r_token_abi, ), lending_pool=W3_BY_CHAIN[Chain.ARBITRUM]["w3"].eth.contract( - address=Web3.to_checksum_address("0xF4B1486DD74D07706052A33d31d7c0AAFD0659E1"), abi=lending_pool_abi + address=Web3.to_checksum_address( + "0xF4B1486DD74D07706052A33d31d7c0AAFD0659E1" + ), + abi=lending_pool_abi, ), graph_url="https://gateway-arbitrum.network.thegraph.com/api/8d1d947ce53cce677d86d075396ad13b/subgraphs/id/E1UTUGaNbTb4XbEYoupJZ5hU62hW9CnadKTXLRSP2hM", ), } - diff --git a/integrations/allstake_susde.py b/integrations/allstake_susde.py index aa36e3d..4dbd4cd 100644 --- a/integrations/allstake_susde.py +++ b/integrations/allstake_susde.py @@ -1,5 +1,5 @@ from utils.web3_utils import W3_BY_CHAIN -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from utils.allstake import AllstakeIntegration diff --git a/integrations/allstake_usde.py b/integrations/allstake_usde.py index f136d11..af542c4 100644 --- a/integrations/allstake_usde.py +++ b/integrations/allstake_usde.py @@ -1,5 +1,5 @@ from utils.web3_utils import W3_BY_CHAIN -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from utils.allstake import AllstakeIntegration diff --git a/integrations/ambient_scroll.py b/integrations/ambient_scroll.py index 007117f..80340de 100644 --- a/integrations/ambient_scroll.py +++ b/integrations/ambient_scroll.py @@ -1,6 +1,6 @@ import requests from constants.chains import Chain -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from models.integration import Integration from constants.summary_columns import SummaryColumn from constants.ambient import AMBIENT_SCROLL_DEPLOYMENT_BLOCK, AMBIENT_SCROLL_API_URL diff --git a/integrations/balancer_integration.py b/integrations/balancer_integration.py index b08bfa7..52ded41 100644 --- a/integrations/balancer_integration.py +++ b/integrations/balancer_integration.py @@ -1,4 +1,4 @@ -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from models.integration import Integration from utils.balancer import ( get_vault_pool_token_balance, diff --git a/integrations/beefy_arbitrum_usde.py b/integrations/beefy_arbitrum_usde.py index 0e081a2..19ecd16 100644 --- a/integrations/beefy_arbitrum_usde.py +++ b/integrations/beefy_arbitrum_usde.py @@ -1,12 +1,10 @@ from constants.chains import Chain -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from utils.beefy import BeefyIntegration if __name__ == "__main__": beefy_integration = BeefyIntegration( - IntegrationID.BEEFY_ARBITRUM_USDE, - 179921508, - Chain.ARBITRUM + IntegrationID.BEEFY_ARBITRUM_USDE, 179921508, Chain.ARBITRUM ) print(beefy_integration.get_participants()) print( diff --git a/integrations/beefy_fraxtal_usde.py b/integrations/beefy_fraxtal_usde.py index e809140..faae56a 100644 --- a/integrations/beefy_fraxtal_usde.py +++ b/integrations/beefy_fraxtal_usde.py @@ -1,12 +1,10 @@ from constants.chains import Chain -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from utils.beefy import BeefyIntegration if __name__ == "__main__": beefy_integration = BeefyIntegration( - IntegrationID.BEEFY_FRAXTAL_USDE, - 2366784, - Chain.FRAXTAL + IntegrationID.BEEFY_FRAXTAL_USDE, 2366784, Chain.FRAXTAL ) print(beefy_integration.get_participants()) print( diff --git a/integrations/beefy_mantle_usde.py b/integrations/beefy_mantle_usde.py index 6f22980..6325511 100644 --- a/integrations/beefy_mantle_usde.py +++ b/integrations/beefy_mantle_usde.py @@ -1,12 +1,10 @@ from constants.chains import Chain -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from utils.beefy import BeefyIntegration if __name__ == "__main__": beefy_integration = BeefyIntegration( - IntegrationID.BEEFY_MANTLE_USDE, - 66470986, - Chain.MANTLE + IntegrationID.BEEFY_MANTLE_USDE, 66470986, Chain.MANTLE ) print(beefy_integration.get_participants()) print( diff --git a/integrations/beefy_optimism_usde.py b/integrations/beefy_optimism_usde.py index ecdea11..51cb5ab 100644 --- a/integrations/beefy_optimism_usde.py +++ b/integrations/beefy_optimism_usde.py @@ -1,12 +1,10 @@ from constants.chains import Chain -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from utils.beefy import BeefyIntegration if __name__ == "__main__": beefy_integration = BeefyIntegration( - IntegrationID.BEEFY_OPTIMISM_USDE, - 38082415, - Chain.OPTIMISM + IntegrationID.BEEFY_OPTIMISM_USDE, 38082415, Chain.OPTIMISM ) print(beefy_integration.get_participants()) print( diff --git a/integrations/equilibria_karak_susde_sept.py b/integrations/equilibria_karak_susde_sept.py index 6768070..db22ae4 100644 --- a/integrations/equilibria_karak_susde_sept.py +++ b/integrations/equilibria_karak_susde_sept.py @@ -1,6 +1,10 @@ -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from utils.equilibria import EquilibriaIntegration -from constants.equilibria import Karak_sUSDe_SEPT, Karak_sUSDe_SEPT_ID, Karak_sUSDe_SEPT_DEPLOYMENT_BLOCK +from constants.equilibria import ( + Karak_sUSDe_SEPT, + Karak_sUSDe_SEPT_ID, + Karak_sUSDe_SEPT_DEPLOYMENT_BLOCK, +) from constants.chains import Chain from constants.equilibria import PENDLE_LOCKER_ETHEREUM @@ -13,9 +17,12 @@ Chain.ETHEREUM, 20, 1, - [PENDLE_LOCKER_ETHEREUM] - + [PENDLE_LOCKER_ETHEREUM], ) print(equilibria_integration.get_participants()) - print(equilibria_integration.get_balance(list(equilibria_integration.get_participants())[0], "latest")) + print( + equilibria_integration.get_balance( + list(equilibria_integration.get_participants())[0], "latest" + ) + ) diff --git a/integrations/equilibria_karak_usde_sept.py b/integrations/equilibria_karak_usde_sept.py index 8f66067..50549f5 100644 --- a/integrations/equilibria_karak_usde_sept.py +++ b/integrations/equilibria_karak_usde_sept.py @@ -1,6 +1,10 @@ -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from utils.equilibria import EquilibriaIntegration -from constants.equilibria import Karak_USDE_SEPT, Karak_USDE_SEPT_ID, Karak_USDE_SEPT_DEPLOYMENT_BLOCK +from constants.equilibria import ( + Karak_USDE_SEPT, + Karak_USDE_SEPT_ID, + Karak_USDE_SEPT_DEPLOYMENT_BLOCK, +) from constants.chains import Chain from constants.equilibria import PENDLE_LOCKER_ETHEREUM @@ -13,9 +17,12 @@ Chain.ETHEREUM, 20, 1, - [PENDLE_LOCKER_ETHEREUM] - + [PENDLE_LOCKER_ETHEREUM], ) print(equilibria_integration.get_participants()) - print(equilibria_integration.get_balance(list(equilibria_integration.get_participants())[0], "latest")) + print( + equilibria_integration.get_balance( + list(equilibria_integration.get_participants())[0], "latest" + ) + ) diff --git a/integrations/equilibria_rusde_sept.py b/integrations/equilibria_rusde_sept.py index cfc480a..e139697 100644 --- a/integrations/equilibria_rusde_sept.py +++ b/integrations/equilibria_rusde_sept.py @@ -1,4 +1,4 @@ -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from utils.equilibria import EquilibriaIntegration from constants.equilibria import rUSDE_SEPT, rUSDE_SEPT_ID, rUSDE_SEPT_DEPLOYMENT_BLOCK from constants.chains import Chain @@ -13,9 +13,12 @@ Chain.ETHEREUM, 20, 1, - [PENDLE_LOCKER_ETHEREUM] - + [PENDLE_LOCKER_ETHEREUM], ) print(equilibria_integration.get_participants()) - print(equilibria_integration.get_balance(list(equilibria_integration.get_participants())[0], "latest")) + print( + equilibria_integration.get_balance( + list(equilibria_integration.get_participants())[0], "latest" + ) + ) diff --git a/integrations/equilibria_susde_apr_expiry.py b/integrations/equilibria_susde_apr_expiry.py index e16e941..1aa7772 100644 --- a/integrations/equilibria_susde_apr_expiry.py +++ b/integrations/equilibria_susde_apr_expiry.py @@ -1,6 +1,10 @@ -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from utils.equilibria import EquilibriaIntegration -from constants.equilibria import SUSDE_APR_EXPIRY, SUSDE_APR_EXPIRY_ID, SUSDE_APR_EXPIRY_DEPLOYMENT_BLOCK +from constants.equilibria import ( + SUSDE_APR_EXPIRY, + SUSDE_APR_EXPIRY_ID, + SUSDE_APR_EXPIRY_DEPLOYMENT_BLOCK, +) from constants.chains import Chain from constants.equilibria import PENDLE_LOCKER_ETHEREUM @@ -13,9 +17,12 @@ Chain.ETHEREUM, 20, 1, - [PENDLE_LOCKER_ETHEREUM] - + [PENDLE_LOCKER_ETHEREUM], ) print(equilibria_integration.get_participants()) - print(equilibria_integration.get_balance(list(equilibria_integration.get_participants())[0], "latest")) + print( + equilibria_integration.get_balance( + list(equilibria_integration.get_participants())[0], "latest" + ) + ) diff --git a/integrations/equilibria_susde_sept.py b/integrations/equilibria_susde_sept.py index 02c68b3..b6dc001 100644 --- a/integrations/equilibria_susde_sept.py +++ b/integrations/equilibria_susde_sept.py @@ -1,4 +1,4 @@ -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from utils.equilibria import EquilibriaIntegration from constants.equilibria import SUSDE_SEPT, SUSDE_SEPT_ID, SUSDE_SEPT_DEPLOYMENT_BLOCK from constants.chains import Chain @@ -13,9 +13,12 @@ Chain.ETHEREUM, 20, 1, - [PENDLE_LOCKER_ETHEREUM] - + [PENDLE_LOCKER_ETHEREUM], ) print(equilibria_integration.get_participants()) - print(equilibria_integration.get_balance(list(equilibria_integration.get_participants())[0], "latest")) + print( + equilibria_integration.get_balance( + list(equilibria_integration.get_participants())[0], "latest" + ) + ) diff --git a/integrations/equilibria_usde_expiry.py b/integrations/equilibria_usde_expiry.py index 147abfd..52f0139 100644 --- a/integrations/equilibria_usde_expiry.py +++ b/integrations/equilibria_usde_expiry.py @@ -1,6 +1,10 @@ -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from utils.equilibria import EquilibriaIntegration -from constants.equilibria import USDE_EXPIRY, USDE_EXPIRY_ID, USDE_EXPIRY_DEPLOYMENT_BLOCK +from constants.equilibria import ( + USDE_EXPIRY, + USDE_EXPIRY_ID, + USDE_EXPIRY_DEPLOYMENT_BLOCK, +) from constants.chains import Chain from constants.equilibria import PENDLE_LOCKER_ETHEREUM @@ -13,8 +17,12 @@ Chain.ETHEREUM, 20, 1, - [PENDLE_LOCKER_ETHEREUM] + [PENDLE_LOCKER_ETHEREUM], ) print(equilibria_integration.get_participants()) - print(equilibria_integration.get_balance(list(equilibria_integration.get_participants())[0], "latest")) + print( + equilibria_integration.get_balance( + list(equilibria_integration.get_participants())[0], "latest" + ) + ) diff --git a/integrations/equilibria_zircuit_usde_aug.py b/integrations/equilibria_zircuit_usde_aug.py index 8e5b8d8..c83284a 100644 --- a/integrations/equilibria_zircuit_usde_aug.py +++ b/integrations/equilibria_zircuit_usde_aug.py @@ -1,6 +1,10 @@ -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from utils.equilibria import EquilibriaIntegration -from constants.equilibria import Zircuit_USDe_AUG, Zircuit_USDe_AUG_ID, Zircuit_USDe_AUG_DEPLOYMENT_BLOCK +from constants.equilibria import ( + Zircuit_USDe_AUG, + Zircuit_USDe_AUG_ID, + Zircuit_USDe_AUG_DEPLOYMENT_BLOCK, +) from constants.chains import Chain from constants.equilibria import PENDLE_LOCKER_ETHEREUM @@ -13,9 +17,12 @@ Chain.ETHEREUM, 20, 1, - [PENDLE_LOCKER_ETHEREUM] - + [PENDLE_LOCKER_ETHEREUM], ) print(equilibria_integration.get_participants()) - print(equilibria_integration.get_balance(list(equilibria_integration.get_participants())[0], "latest")) + print( + equilibria_integration.get_balance( + list(equilibria_integration.get_participants())[0], "latest" + ) + ) diff --git a/integrations/euler_susde.py b/integrations/euler_susde.py index 5fbb418..b68536c 100644 --- a/integrations/euler_susde.py +++ b/integrations/euler_susde.py @@ -1,6 +1,6 @@ import json from constants.chains import Chain -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from constants.euler import SUSDE_VAULT_ADDRESS from constants.merchantmoe import DEAD_ADDRESS, ZERO_ADDRESS from models.integration import Integration diff --git a/integrations/euler_usde.py b/integrations/euler_usde.py index 6ec15d0..cf55c91 100644 --- a/integrations/euler_usde.py +++ b/integrations/euler_usde.py @@ -1,6 +1,6 @@ import json from constants.chains import Chain -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from constants.euler import USDE_VAULT_ADDRESS from models.integration import Integration from utils.web3_utils import ( @@ -13,9 +13,7 @@ evault_abi = json.load(f) -class EulerIntegration( - Integration -): +class EulerIntegration(Integration): def __init__(self): super().__init__( IntegrationID.EULER_USDE, @@ -28,14 +26,17 @@ def __init__(self): None, ) - self.vault_contract = w3.eth.contract(address = USDE_VAULT_ADDRESS, abi=evault_abi) + self.vault_contract = w3.eth.contract( + address=USDE_VAULT_ADDRESS, abi=evault_abi + ) def get_balance(self, user: str, block: int) -> float: try: - etoken_balance = call_with_retry(self.vault_contract.functions.balanceOf(user), block) + etoken_balance = call_with_retry( + self.vault_contract.functions.balanceOf(user), block + ) asset_balance = call_with_retry( - self.vault_contract.functions.convertToAssets(etoken_balance), - block + self.vault_contract.functions.convertToAssets(etoken_balance), block ) except Exception as ex: print("Error getting balance for user %s: %s", user, ex) @@ -58,7 +59,7 @@ def get_participants(self) -> list: f"Euler Vault {self.vault_contract}", self.vault_contract.events.Transfer(), start, - current_batch_end + current_batch_end, ) for transfer in transfers: diff --git a/integrations/firm_susde.py b/integrations/firm_susde.py index 2735adc..a2f05be 100644 --- a/integrations/firm_susde.py +++ b/integrations/firm_susde.py @@ -1,5 +1,5 @@ from constants.chains import Chain -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from models.integration import Integration from constants.firm import FIRM_SUSDE_DEPLOYMENT_BLOCK from utils.firm import get_escrow_contract, firm_susde_market_contract diff --git a/integrations/fluid_susde.py b/integrations/fluid_susde.py index df09164..8b49779 100644 --- a/integrations/fluid_susde.py +++ b/integrations/fluid_susde.py @@ -1,13 +1,12 @@ from constants.chains import Chain -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from models.integration import Integration from utils.web3_utils import call_with_retry, W3_BY_CHAIN from utils.fluid import vaultResolver_contract, vaultPositionResolver_contract from constants.fluid import sUSDe -class FluidIntegration( - Integration -): + +class FluidIntegration(Integration): def __init__(self): super().__init__( @@ -25,11 +24,13 @@ def __init__(self): def get_balance(self, user: str, block: int) -> float: balance = 0 try: - userPositions, vaultEntireDatas = call_with_retry(vaultResolver_contract.functions.positionsByUser(user), block) + userPositions, vaultEntireDatas = call_with_retry( + vaultResolver_contract.functions.positionsByUser(user), block + ) for i in range(len(userPositions)): if vaultEntireDatas[i][3][8][0] == sUSDe: balance += userPositions[i][9] - return balance/1e18 + return balance / 1e18 except Exception as e: return 0 @@ -40,10 +41,14 @@ def get_participants(self) -> list: relevant_vaults = self.get_relevant_vaults(current_block) relavantUserPositions = [] - try: for vault in relevant_vaults: - relavantUserPositions += call_with_retry(vaultPositionResolver_contract.functions.getAllVaultPositions(vault), current_block) + relavantUserPositions += call_with_retry( + vaultPositionResolver_contract.functions.getAllVaultPositions( + vault + ), + current_block, + ) for userPosition in relavantUserPositions: owner = userPosition[1] if owner not in participants: @@ -51,24 +56,36 @@ def get_participants(self) -> list: except Exception as e: print(f"Error: {str(e)}") return participants - + def get_relevant_vaults(self, block: int) -> list: if block in self.blocknumber_to_susdeVaults: return self.blocknumber_to_susdeVaults[block] - - + if self.blocknumber_to_susdeVaults != {}: - totalVaults = call_with_retry(vaultResolver_contract.functions.getTotalVaults(), block) + totalVaults = call_with_retry( + vaultResolver_contract.functions.getTotalVaults(), block + ) for block_number in self.blocknumber_to_susdeVaults: - totalVaults_at_block = call_with_retry(vaultResolver_contract.functions.getTotalVaults(), block_number) + totalVaults_at_block = call_with_retry( + vaultResolver_contract.functions.getTotalVaults(), block_number + ) if totalVaults == totalVaults_at_block: - self.blocknumber_to_susdeVaults[block] = self.blocknumber_to_susdeVaults[block_number] + self.blocknumber_to_susdeVaults[block] = ( + self.blocknumber_to_susdeVaults[block_number] + ) return self.blocknumber_to_susdeVaults[block_number] - vaults = call_with_retry(vaultResolver_contract.functions.getAllVaultsAddresses(), block) + vaults = call_with_retry( + vaultResolver_contract.functions.getAllVaultsAddresses(), block + ) relevantVaults = [] for vaultAddress in vaults: - supplyTokenOfVault = (call_with_retry(vaultResolver_contract.functions.getVaultEntireData(vaultAddress), block))[3][8][0] + supplyTokenOfVault = ( + call_with_retry( + vaultResolver_contract.functions.getVaultEntireData(vaultAddress), + block, + ) + )[3][8][0] if supplyTokenOfVault == sUSDe: relevantVaults.append(vaultAddress) self.blocknumber_to_susdeVaults[block] = relevantVaults @@ -85,5 +102,7 @@ def get_relevant_vaults(self, block: int) -> list: print("\n\n\n getting balance") print( - example_integration.get_balance("0xEb54fC872F70A4B7addb34C331DeC3fDf9a329de", 21079685) - ) \ No newline at end of file + example_integration.get_balance( + "0xEb54fC872F70A4B7addb34C331DeC3fDf9a329de", 21079685 + ) + ) diff --git a/integrations/fluid_usde.py b/integrations/fluid_usde.py index df850d1..a52d292 100644 --- a/integrations/fluid_usde.py +++ b/integrations/fluid_usde.py @@ -1,13 +1,12 @@ from constants.chains import Chain -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from models.integration import Integration from utils.web3_utils import call_with_retry, W3_BY_CHAIN from utils.fluid import vaultResolver_contract, vaultPositionResolver_contract from constants.fluid import USDe -class FluidIntegration( - Integration -): + +class FluidIntegration(Integration): def __init__(self): super().__init__( @@ -25,11 +24,16 @@ def __init__(self): def get_balance(self, user: str, block: int) -> float: balance = 0 try: - userPositions, vaultEntireDatas = call_with_retry(vaultResolver_contract.functions.positionsByUser(user), block) + userPositions, vaultEntireDatas = call_with_retry( + vaultResolver_contract.functions.positionsByUser(user), block + ) for i in range(len(userPositions)): - if (vaultEntireDatas[i][3][8][0] == USDe or vaultEntireDatas[i][3][8][1] == USDe) and userPositions[i][10] != 40000: + if ( + vaultEntireDatas[i][3][8][0] == USDe + or vaultEntireDatas[i][3][8][1] == USDe + ) and userPositions[i][10] != 40000: balance += userPositions[i][9] - return balance/1e18 + return balance / 1e18 except Exception as e: return 0 @@ -40,10 +44,14 @@ def get_participants(self) -> list: relevant_vaults = self.get_relevant_vaults(current_block) relavantUserPositions = [] - try: for vault in relevant_vaults: - relavantUserPositions += call_with_retry(vaultPositionResolver_contract.functions.getAllVaultPositions(vault), current_block) + relavantUserPositions += call_with_retry( + vaultPositionResolver_contract.functions.getAllVaultPositions( + vault + ), + current_block, + ) for userPosition in relavantUserPositions: owner = userPosition[1] if owner not in participants: @@ -51,25 +59,36 @@ def get_participants(self) -> list: except Exception as e: print(f"Error: {str(e)}") return participants - + def get_relevant_vaults(self, block: int) -> list: if block in self.blocknumber_to_usdeVaults: return self.blocknumber_to_usdeVaults[block] - - + if self.blocknumber_to_usdeVaults != {}: - totalVaults = call_with_retry(vaultResolver_contract.functions.getTotalVaults(), block) + totalVaults = call_with_retry( + vaultResolver_contract.functions.getTotalVaults(), block + ) for block_number in self.blocknumber_to_usdeVaults: - totalVaults_at_block = call_with_retry(vaultResolver_contract.functions.getTotalVaults(), block_number) + totalVaults_at_block = call_with_retry( + vaultResolver_contract.functions.getTotalVaults(), block_number + ) if totalVaults == totalVaults_at_block: - self.blocknumber_to_usdeVaults[block] = self.blocknumber_to_usdeVaults[block_number] + self.blocknumber_to_usdeVaults[block] = ( + self.blocknumber_to_usdeVaults[block_number] + ) return self.blocknumber_to_usdeVaults[block_number] - vaults = call_with_retry(vaultResolver_contract.functions.getAllVaultsAddresses(), block) + vaults = call_with_retry( + vaultResolver_contract.functions.getAllVaultsAddresses(), block + ) relevantVaults = [] for vaultAddress in vaults: - vaultData = call_with_retry(vaultResolver_contract.functions.getVaultEntireData(vaultAddress), block) - if (vaultData[3][8][0] == USDe or vaultData[3][8][1] == USDe) and not (vaultData[1] and vaultData[2]): + vaultData = call_with_retry( + vaultResolver_contract.functions.getVaultEntireData(vaultAddress), block + ) + if (vaultData[3][8][0] == USDe or vaultData[3][8][1] == USDe) and not ( + vaultData[1] and vaultData[2] + ): relevantVaults.append(vaultAddress) self.blocknumber_to_usdeVaults[block] = relevantVaults return relevantVaults @@ -82,4 +101,4 @@ def get_relevant_vaults(self, block: int) -> list: print(example_integration.get_relevant_vaults(current_block)) print("\n\n\ngetting participants") - print(example_integration.get_participants()) \ No newline at end of file + print(example_integration.get_participants()) diff --git a/integrations/fluid_usde_t4.py b/integrations/fluid_usde_t4.py index b585752..93db0de 100644 --- a/integrations/fluid_usde_t4.py +++ b/integrations/fluid_usde_t4.py @@ -1,14 +1,17 @@ from constants.chains import Chain -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from models.integration import Integration from utils.web3_utils import call_with_retry, W3_BY_CHAIN -from utils.fluid import vaultResolver_contract, vaultPositionResolver_contract, dexResolver_contract +from utils.fluid import ( + vaultResolver_contract, + vaultPositionResolver_contract, + dexResolver_contract, +) from constants.fluid import USDe import json -class FluidIntegration( - Integration -): + +class FluidIntegration(Integration): def __init__(self): super().__init__( @@ -26,18 +29,27 @@ def __init__(self): def get_balance(self, user: str, block: int) -> float: balance = 0 try: - userPositions, vaultEntireDatas = call_with_retry(vaultResolver_contract.functions.positionsByUser(user), block) + userPositions, vaultEntireDatas = call_with_retry( + vaultResolver_contract.functions.positionsByUser(user), block + ) dexStates = {} for i in range(len(userPositions)): - if (vaultEntireDatas[i][3][8][0] == USDe or vaultEntireDatas[i][3][8][1] == USDe) and userPositions[i][10] == 40000: + if ( + vaultEntireDatas[i][3][8][0] == USDe + or vaultEntireDatas[i][3][8][1] == USDe + ) and userPositions[i][10] == 40000: # underlying dex as supply token in the vault dexAddress = vaultEntireDatas[i][3][6] if dexAddress not in dexStates: - dexStates[dexAddress] = dexResolver_contract.functions.getDexState(dexAddress).call(block_identifier=block) + dexStates[dexAddress] = ( + dexResolver_contract.functions.getDexState(dexAddress).call( + block_identifier=block + ) + ) # fetching the dex state to get the shares to tokens ratio - token0PerSupplyShare = dexStates[dexAddress][-4] + token0PerSupplyShare = dexStates[dexAddress][-4] balance += userPositions[i][9] * token0PerSupplyShare - return balance/1e18 + return balance / 1e18 except Exception as e: return 0 @@ -46,10 +58,14 @@ def get_participants(self) -> list: current_block = W3_BY_CHAIN[self.chain]["w3"].eth.get_block_number() relavantUserPositions = [] - try: for vault in self.relevant_vaults: - relavantUserPositions += call_with_retry(vaultPositionResolver_contract.functions.getAllVaultPositions(vault), current_block) + relavantUserPositions += call_with_retry( + vaultPositionResolver_contract.functions.getAllVaultPositions( + vault + ), + current_block, + ) for userPosition in relavantUserPositions: owner = userPosition[1] if owner not in participants: @@ -63,4 +79,4 @@ def get_participants(self) -> list: example_integration = FluidIntegration() current_block = W3_BY_CHAIN[example_integration.chain]["w3"].eth.get_block_number() print("\n\n\ngetting participants") - print(example_integration.get_participants()) \ No newline at end of file + print(example_integration.get_participants()) diff --git a/integrations/gmx_usde_poitions_aug.py b/integrations/gmx_usde_poitions_aug.py index a2e7978..09e8eee 100644 --- a/integrations/gmx_usde_poitions_aug.py +++ b/integrations/gmx_usde_poitions_aug.py @@ -1,29 +1,36 @@ import requests -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from constants.chains import Chain -from constants.gmx import GMX_DATA_STORE_CONTRACT_ADDRESS, GMX_WSTETH_USDE_MARKET_BLOCK, GMX_SUBSQUID_ENDPOINT, USDE_TOKEN_ADDRESS +from constants.gmx import ( + GMX_DATA_STORE_CONTRACT_ADDRESS, + GMX_WSTETH_USDE_MARKET_BLOCK, + GMX_SUBSQUID_ENDPOINT, + USDE_TOKEN_ADDRESS, +) from utils.gmx import gmx_synthetics_reader_contract from constants.summary_columns import SummaryColumn from models.integration import Integration from utils.web3_utils import call_with_retry + def fetch_data(url, query): - response = requests.post(url, json={'query': query}) + response = requests.post(url, json={"query": query}) if response.status_code == 200: response_json = response.json() - if 'data' not in response_json: + if "data" not in response_json: print(f"Query failed with response: {response_json}") return None - return response_json['data'] + return response_json["data"] else: print(f"Query failed with status code {response.status_code}") return None + class GMXPositionsIntegration(Integration): def __init__( - self, - ): + self, + ): super().__init__( IntegrationID.GMX_USDE_POSITIONS, GMX_WSTETH_USDE_MARKET_BLOCK, @@ -35,8 +42,7 @@ def __init__( None, ) - - def get_balance(self, user: str, block: int) -> float: + def get_balance(self, user: str, block: int) -> float: accountPositions = call_with_retry( gmx_synthetics_reader_contract.functions.getAccountPositions( GMX_DATA_STORE_CONTRACT_ADDRESS, @@ -58,7 +64,6 @@ def get_balance(self, user: str, block: int) -> float: return total_collateral_amount - def get_participants(self) -> list: if self.participants is not None: return self.participants @@ -77,10 +82,10 @@ def get_participants(self) -> list: url=GMX_SUBSQUID_ENDPOINT, query=participants_query.format( collateralTokenw=USDE_TOKEN_ADDRESS, - ) + ), ) - accounts = [position['account'] for position in participants['positions']] + accounts = [position["account"] for position in participants["positions"]] return list(set(accounts)) @@ -89,5 +94,7 @@ def get_participants(self) -> list: gmx_integration = GMXPositionsIntegration() # print(gmx_integration.get_participants()) print( - gmx_integration.get_balance("0xDb59AB7d951f3D9F1d2E764c3A6F7507E11a4e4e", 238320844) + gmx_integration.get_balance( + "0xDb59AB7d951f3D9F1d2E764c3A6F7507E11a4e4e", 238320844 + ) ) diff --git a/integrations/gmx_usde_usdc_aug.py b/integrations/gmx_usde_usdc_aug.py index d8a900c..35fe7d6 100644 --- a/integrations/gmx_usde_usdc_aug.py +++ b/integrations/gmx_usde_usdc_aug.py @@ -1,6 +1,12 @@ -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID -from constants.gmx import GMX_USDE_USDC_MARKET_BLOCK, GMX_USDE_USDC_MARKET_ADDRESS, USDC_TOKEN_ADDRESS, USDE_TOKEN_ADDRESS, WETH_TOKEN_ADDRESS +from constants.gmx import ( + GMX_USDE_USDC_MARKET_BLOCK, + GMX_USDE_USDC_MARKET_ADDRESS, + USDC_TOKEN_ADDRESS, + USDE_TOKEN_ADDRESS, + WETH_TOKEN_ADDRESS, +) from utils.gmx import GMXLPIntegration if __name__ == "__main__": diff --git a/integrations/gmx_wsteth_usde_aug.py b/integrations/gmx_wsteth_usde_aug.py index 300b101..3aa745b 100644 --- a/integrations/gmx_wsteth_usde_aug.py +++ b/integrations/gmx_wsteth_usde_aug.py @@ -1,6 +1,12 @@ -from constants.gmx import GMX_WSTETH_USDE_MARKET_BLOCK, WSTETH_TOKEN_ADDRESS, GMX_WSTETH_USDE_MARKET_ADDRESS, USDE_TOKEN_ADDRESS, WETH_TOKEN_ADDRESS +from constants.gmx import ( + GMX_WSTETH_USDE_MARKET_BLOCK, + WSTETH_TOKEN_ADDRESS, + GMX_WSTETH_USDE_MARKET_ADDRESS, + USDE_TOKEN_ADDRESS, + WETH_TOKEN_ADDRESS, +) -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from utils.gmx import GMXLPIntegration if __name__ == "__main__": diff --git a/integrations/hyperdrive.py b/integrations/hyperdrive.py index 268ac26..cbf6a54 100644 --- a/integrations/hyperdrive.py +++ b/integrations/hyperdrive.py @@ -1,11 +1,20 @@ from decimal import Decimal from constants.chains import Chain from models.integration import Integration -from constants.integration_ids import IntegrationID -from constants.hyperdrive import HYPERDRIVE_SUSDE_POOL_ADDRESS, HYPERDRIVE_SUSDE_POOL_DEPLOYMENT_BLOCK, HYPERDRIVE_MORPHO_ABI -from utils.hyperdrive import get_hyperdrive_participants, get_pool_details, get_pool_positions +from integrations.integration_ids import IntegrationID +from constants.hyperdrive import ( + HYPERDRIVE_SUSDE_POOL_ADDRESS, + HYPERDRIVE_SUSDE_POOL_DEPLOYMENT_BLOCK, + HYPERDRIVE_MORPHO_ABI, +) +from utils.hyperdrive import ( + get_hyperdrive_participants, + get_pool_details, + get_pool_positions, +) from utils.web3_utils import w3 + class Hyperdrive(Integration): def __init__(self): super().__init__( @@ -38,7 +47,10 @@ def get_balance(self, user: str, block: int) -> float: if self.pool_users is None: self.update_participants() # get pool positions - pool_contract = w3.eth.contract(address=w3.to_checksum_address(HYPERDRIVE_SUSDE_POOL_ADDRESS), abi=HYPERDRIVE_MORPHO_ABI) + pool_contract = w3.eth.contract( + address=w3.to_checksum_address(HYPERDRIVE_SUSDE_POOL_ADDRESS), + abi=HYPERDRIVE_MORPHO_ABI, + ) _, lp_rewardable_tvl, short_rewardable_tvl = get_pool_details(pool_contract) self.pool_positions = get_pool_positions( pool_contract=pool_contract, @@ -49,13 +61,20 @@ def get_balance(self, user: str, block: int) -> float: block=block, ) # get the user's balance - rewardable_tvl = sum(position[5] for position in self.pool_positions if position[0] == user) + rewardable_tvl = sum( + position[5] for position in self.pool_positions if position[0] == user + ) return rewardable_tvl / 1e18 def test_hyperdrive(self): self.update_participants() - pool_contract = w3.eth.contract(address=w3.to_checksum_address(HYPERDRIVE_SUSDE_POOL_ADDRESS), abi=HYPERDRIVE_MORPHO_ABI) - vault_shares_balance, lp_rewardable_tvl, short_rewardable_tvl = get_pool_details(pool_contract) + pool_contract = w3.eth.contract( + address=w3.to_checksum_address(HYPERDRIVE_SUSDE_POOL_ADDRESS), + abi=HYPERDRIVE_MORPHO_ABI, + ) + vault_shares_balance, lp_rewardable_tvl, short_rewardable_tvl = ( + get_pool_details(pool_contract) + ) pool_positions = get_pool_positions( pool_contract=pool_contract, pool_users=self.pool_users, @@ -65,20 +84,36 @@ def test_hyperdrive(self): ) # Make sure rewards add up to rewardable TVL - combined_prefixes = [(0, 3), (2,)] # Treat prefixes 0 and 3 together, 2 separately + combined_prefixes = [ + (0, 3), + (2,), + ] # Treat prefixes 0 and 3 together, 2 separately for prefixes in combined_prefixes: - combined_shares = sum(position[5] for position in pool_positions if position[2] in prefixes) - combined_rewardable = lp_rewardable_tvl if prefixes[0] == 0 else short_rewardable_tvl + combined_shares = sum( + position[5] for position in pool_positions if position[2] in prefixes + ) + combined_rewardable = ( + lp_rewardable_tvl if prefixes[0] == 0 else short_rewardable_tvl + ) if combined_shares == combined_rewardable: - print(f"for prefixes={prefixes}, check combined_shares == combined_rewardable ({combined_shares} == {combined_rewardable}) ✅") + print( + f"for prefixes={prefixes}, check combined_shares == combined_rewardable ({combined_shares} == {combined_rewardable}) ✅" + ) else: - print(f"for prefixes={prefixes}, check combined_shares == combined_rewardable ({combined_shares} != {combined_rewardable}) ❌") + print( + f"for prefixes={prefixes}, check combined_shares == combined_rewardable ({combined_shares} != {combined_rewardable}) ❌" + ) total_rewardable = Decimal(sum(position[5] for position in pool_positions)) if vault_shares_balance == total_rewardable: - print(f"vault_shares_balance == total_rewardable ({vault_shares_balance} == {total_rewardable}) ✅") + print( + f"vault_shares_balance == total_rewardable ({vault_shares_balance} == {total_rewardable}) ✅" + ) else: - print(f"vault_shares_balance != total_rewardable ({vault_shares_balance} != {total_rewardable}) ❌") + print( + f"vault_shares_balance != total_rewardable ({vault_shares_balance} != {total_rewardable}) ❌" + ) + if __name__ == "__main__": hyperdrive = Hyperdrive() diff --git a/integrations/integration_ids.py b/integrations/integration_ids.py new file mode 100644 index 0000000..771c09e --- /dev/null +++ b/integrations/integration_ids.py @@ -0,0 +1,401 @@ +from enum import Enum + +from constants.integration_token import Token + + +class IntegrationID(Enum): + EXAMPLE = ("example", "Example", Token.USDE) + PENDLE_USDE_LPT = ("pendle_effective_lpt_held", "Pendle USDe LPT") + PENDLE_USDE_YT = ("pendle_yt_held", "Pendle USDe YT") + PENDLE_SUSDE_LPT_APRIL_EXPIRY = ( + "pendle_effective_susde_apr_lpt_held", + "Pendle sUSDe LPT (April expiry)", + Token.SUSDE, + ) + PENDLE_SUSDE_YT_APRIL_EXPIRY = ( + "pendle_susde_apr_yt_held", + "Pendle sUSDe YT (April expiry)", + Token.SUSDE, + ) + PENDLE_SUSDE_LPT_JULY_EXPIRY = ( + "pendle_effective_susde_jul_lpt_held", + "Pendle sUSDe LPT (July expiry)", + Token.SUSDE, + ) + PENDLE_SUSDE_YT_JULY_EXPIRY = ( + "pendle_susde_jul_yt_held", + "Pendle sUSDe YT (July expiry)", + Token.SUSDE, + ) + PENDLE_SUSDE_LPT_SEPT_EXPIRY = ( + "pendle_effective_susde_sep_lpt_held", + "Pendle sUSDe LPT (Sept expiry)", + Token.SUSDE, + ) + PENDLE_SUSDE_YT_SEPT_EXPIRY = ( + "pendle_susde_sep_yt_held", + "Pendle sUSDe YT (Sept expiry)", + Token.SUSDE, + ) + PENDLE_ENA_LPT = ("pendle_effective_ena_lpt_held", "Pendle ENA LPT", Token.ENA) + PENDLE_ENA_YT = ("pendle_ena_yt_held", "Pendle ENA YT", Token.ENA) + PENDLE_ARBITRUM_USDE_LPT = ( + "pendle_arbtrium_effective_lpt_bal", + "Pendle Arbitrum USDe LPT", + ) + PENDLE_ARBITRUM_USDE_YT = ("pendle_arbtrium_yt_bal", "Pendle Arbitrum USDe YT") + PENDLE_KARAK_USDE_LPT = ("pendle_karak_usde_lpt_held", "Pendle Karak USDe LPT") + PENDLE_KARAK_USDE_YT = ("pendle_karak_usde_yt_held", "Pendle Karak USDe YT") + PENDLE_KARAK_SUSDE_LPT = ( + "pendle_karak_susde_lpt_held", + "Pendle Karak sUSDe LPT", + Token.SUSDE, + ) + PENDLE_KARAK_SUSDE_YT = ( + "pendle_karak_susde_yt_held", + "Pendle Karak sUSDe YT", + Token.SUSDE, + ) + PENDLE_MANTLE_USDE_LPT = ( + "pendle_mantle_effective_lpt_bal", + "Pendle Mantle USDe LPT", + ) + PENDLE_MANTLE_USDE_YT = ("pendle_mantle_yt_bal", "Pendle Mantle USDe YT") + PENDLE_ZIRCUIT_USDE_LPT = ( + "pendle_effective_zircuit_usde_lpt_held", + "Pendle Zircuit USDe LPT", + ) + PENDLE_ZIRCUIT_USDE_YT = ("pendle_zircuit_usde_yt_held", "Pendle Zircuit USDe YT") + + # Stake DAO + STAKEDAO_SUSDE_JULY_LPT = ( + "stakedao_susde_july_effective_lpt_held", + "Stake DAO sUSDe July LPT", + Token.SUSDE, + ) + STAKEDAO_SUSDE_SEPT_LPT = ( + "stakedao_susde_sept_effective_lpt_held", + "Stake DAO sUSDe Sept LPT", + Token.SUSDE, + ) + STAKEDAO_USDE_JULY_LPT = ( + "stakedao_usde_july_effective_lpt_held", + "Stake DAO USDe July LPT", + Token.USDE, + ) + + # PENPIE + PENPIE_SUSDE_JULY_LPT = ( + "penpie_susde_july_effective_lpt_held", + "PENPIE sUSDe July LPT", + Token.SUSDE, + ) + PENPIE_Karak_sUSDe_26SEP2024_LPT = ( + "PENPIE_Karak_sUSDe_26SEP2024_effective_lpt_held", + "Karak_sUSDe_26SEP2024", + Token.SUSDE, + ) + PENPIE_Karak_USDE_26SEP2024_LPT = ( + "PENPIE_Karak_USDE_26SEP2024_effective_lpt_held", + "Karak_USDE_26SEP2024", + Token.USDE, + ) + PENPIE_sUSDe25APR2024_LPT = ( + "PENPIE_sUSDe25APR2024_effective_lpt_held", + "sUSDe25APR2024", + Token.SUSDE, + ) + PENPIE_sUSDe26SEP2024_LPT = ( + "PENPIE_sUSDe26SEP2024_effective_lpt_held", + "sUSDe26SEP2024", + Token.SUSDE, + ) + PENPIE_USDe25JUL2024_LPT = ( + "PENPIE_USDe25JUL2024_effective_lpt_held", + "USDe25JUL2024", + Token.USDE, + ) + PENPIE_Zircuit_USDe27JUN2024_LPT = ( + "PENPIE_Zircuit_USDe27JUN2024_effective_lpt_held", + "Zircuit_USDe27JUN2024", + Token.USDE, + ) + PENPIE_ENA29AUG2024_LPT = ( + "PENPIE_ENA29AUG2024_effective_lpt_held", + "ENA29AUG2024", + Token.ENA, + ) + PENPIE_USDE_ARB_AUG2024_LPT = ( + "PENPIE_USDE_ARB_AUG2024_effective_lpt_held", + "USDE_ARB_AUG2024", + Token.USDE, + ) + PENPIE_USDe_24OCT2024_LPT = ( + "PENPIE_USDe_24OCT202_effective_lpt_held4", + "USDe_24OCT2024", + Token.USDE, + ) + PENPIE_ENA_31OCT2024_LPT = ( + "PENPIE_ENA_31OCT2024_effective_lpt_held", + "ENA_31OCT2024", + Token.ENA, + ) + PENPIE_rsUSDe_26SEP2024_LPT = ( + "PENPIE_rsUSDe_26SEP2024_effective_lpt_held", + "rsUSDe_26SEP2024", + Token.USDE, + ) + PENPIE_USDe_26DEC2024_LPT = ( + "PENPIE_USDe_26DEC2024_effective_lpt_held", + "USDe_26DEC2024", + Token.USDE, + ) + PENPIE_sUSDE_26DEC2024_LPT = ( + "PENPIE_sUSDE_26DEC2024_effective_lpt_held", + "sUSDE_26DEC2024", + Token.SUSDE, + ) + PENPIE_sUSDE_24OCT2024_LPT = ( + "PENPIE_sUSDE_24OCT2024_effective_lpt_held", + "sUSDE_24OCT2024", + Token.SUSDE, + ) + PENPIE_rsENA_26SEP2024_LPT = ( + "PENPIE_rsENA_26SEP2024_effective_lpt_held", + "rsENA_26SEP2024", + Token.ENA, + ) + PENPIE_USDE_ARB_NOV2024_LPT = ( + "PENPIE_USDE_ARB_NOV2024_effective_lpt_held", + "USDE_ARB_NOV2024", + Token.USDE, + ) + + # EQUILIBRIA + EQUILIBRIA_SUSDE_SEPT_LPT = ( + "equilibria_susde_sept_effective_lpt_held", + "Equilibria sUSDe Sept LPT", + Token.SUSDE, + ) + EQUILIBRIA_Karak_SUSDE_SEPT_SEPT = ( + "equilibria_karak_susde_sept_effective_lpt_held", + "Equilibria Karak sUSDe Sept LPT", + Token.SUSDE, + ) + EQUILIBRIA_Karak_USDE_SEPT_LPT = ( + "equilibria_karak_usde_sept_effective_lpt_held", + "Equilibria Karak USDe Sept LPT", + Token.USDE, + ) + EQUILIBRIA_Zircuit_USDE_AUG_LPT = ( + "equilibria_zircuit_usde_aug_effective_lpt_held", + "Equilibria Zircuit USDe Aug LPT", + Token.USDE, + ) + EQUILIBRIA_rUSDE_SEPT_LPT = ( + "equilibria_rusde_sept_effective_lpt_held", + "Equilibria rUSDe Sept LPT", + ) + EQUILIBRIA_USDE_LPT_EXPIRY = ( + "equilibria_usde_lpt_expiry_effective_lpt_held", + "Equilibria USDe LPT Expiry", + Token.USDE, + ) + EQUILIBRIA_SUSDE_APR_EXPIRY = ( + "equilibria_susde_apr_expiry_effective_lpt_held", + "Equilibria sUSDe Apr Expiry", + Token.SUSDE, + ) + + # EulerV2 + EULER_USDE = ("euler_usde_deposit", "EulerV2 USDe", Token.USDE) + EULER_SUSDE = ("euler_susde_deposit", "EulerV2 sUSDe", Token.SUSDE) + + # Term Finance + TERM_SUSDE = ("term_susde_held", "Term Finance sUSDe", Token.SUSDE) + + # Synthetix + SYNTHETIX_USDE_LP = ( + "synthetix_usde_arb_lp_bal", + "Synthetix V3 Arbitrum USDe LP", + Token.USDE, + ) + + # Lendle + LENDLE_USDE_LPT = ("lendle_usde_lpt_bal", "Lendle Mantle USDe LPT", Token.USDE) + + # Lyra + LYRA_SUSDE_BULL_MAINNET = ( + "lyra_susde_bull_mainnet", + "Lyra sUSDe Bull Vault Mainnet", + Token.SUSDE, + ) + LYRA_SUSDE_BULL_ARBITRUM = ( + "lyra_susde_bull_arbitrum", + "Lyra sUSDe Bull Vault Arbitrum", + Token.SUSDE, + ) + LYRA_SUSDE_EXCHANGE_DEPOSIT = ( + "lyra_susde_exchange_deposit", + "Lyra sUSDe Exchange Deposits", + Token.SUSDE, + ) + # Velodrome + VELODROME_MODE_USDE = ("velodrome_mode_usde", "Velodrome Mode USDe", Token.USDE) + VELODROME_MODE_SUSDE = ("velodrome_mode_susde", "Velodrome Mode sUSDe", Token.SUSDE) + # Ambient + AMBIENT_SCROLL_LP = ("ambient_usde_scroll_lp_bal", "Ambient Scroll LP", Token.USDE) + + # Balancer + BALANCER_ARBITRUM_GHO_USDE = ( + "balancer_arbitrum_gho_usde", + "Balancer Arbitrum GHO/USDe", + Token.USDE, + ) + BALANCER_ARBITRUM_WAGHO_USDE = ( + "balancer_arbitrum_wagho_usde", + "Balancer Arbitrum waGHO/USDe", + Token.USDE, + ) + BALANCER_ARBITRUM_GYD_SUSDE = ( + "balancer_arbitrum_gyd_susde", + "Balancer Arbitrum GYD/sUSDe", + Token.SUSDE, + ) + BALANCER_ARBITRUM_SUSDE_SFRAX = ( + "balancer_arbitrum_susde_sfrax", + "Balancer Arbitrum sUSDe/sFRAX", + Token.SUSDE, + ) + BALANCER_ARBITRUM_SUSDE_USDC = ( + "balancer_arbitrum_susde_usdc", + "Balancer Arbitrum sUSDe/USDC", + Token.SUSDE, + ) + BALANCER_ETHEREUM_WSTETH_SUSDE = ( + "balancer_ethereum_wsteth_susde", + "Balancer Ethereum 50wstETH/50sUSDe", + Token.SUSDE, + ) + BALANCER_ETHEREUM_BAOUSD_SUSDE = ( + "balancer_ethereum_baousd_susde", + "Balancer Ethereum baoUSD/sUSDe", + Token.SUSDE, + ) + BALANCER_ETHEREUM_SUSDE_USDC = ( + "balancer_ethereum_susde_usdc", + "Balancer Ethereum sUSDe/USDC", + Token.SUSDE, + ) + BALANCER_ETHEREUM_SUSDE_GYD = ( + "balancer_ethereum_susde_gyd", + "Balancer Ethereum sUSDe/GYD", + Token.SUSDE, + ) + BALANCER_FRAXTAL_FRAX_USDE = ( + "balancer_fraxtal_frax_usde", + "Balancer Fraxtal FRAX/USDe", + Token.USDE, + ) + BALANCER_FRAXTAL_SFRAX_SDAI_SUSDE = ( + "balancer_fraxtal_sfrax_sdai_susde", + "Balancer Fraxtal sFRAX/sDAI/sUSDe", + Token.SUSDE, + ) + BALANCER_FRAXTAL_FRAX_USDE_DAI_USDT_USDC = ( + "balancer_fraxtal_frax_usde_dai_usdt_usdc", + "Balancer Fraxtal FRAX/USDe/DAI/USDT/USDC", + Token.USDE, + ) + + # Nuri + NURI_USDE_LP = ("nuri_usde_lp_bal", "Nuri USDe LP", Token.USDE) + + # Merchant Moe + MERCHANT_MOE_METH_USDE_LBT = ( + "merchant_moe_in_range_lbt_liq_held", + "Merchant Moe mETH/USDe Liquidity Book Token", + ) + # Rho Markets + RHO_MARKETS_USDE_LP = ( + "rho_markets_usde_scroll_lp_bal", + "Rho Markets Scroll USDe LP", + Token.USDE, + ) + # Ramses + RAMSES_USDE_LP = ("ramses_usde_lp_bal", "Ramses USDe LP", Token.USDE) + + # Radiant + RADIANT_USDE_CORE_ARBITRUM = ( + "radiant_usde_arb", + "Radiant USDE Lending", + Token.USDE, + ) + + # Splice + SPLICE_USDE_YT = ("splice_usde_yt", "Splice USDe YT", Token.USDE) + SPLICE_USDE_LPT = ("splice_usde_lpt", "Splice USDe LPT", Token.USDE) + SPLICE_SUSDE_YT = ("splice_susde_yt", "Splice SUSDe YT", Token.SUSDE) + SPLICE_SUSDE_LPT = ("splice_susde_lpt", "Splice SUSDu LPT", Token.SUSDE) + + # GMX + GMX_USDE_POSITIONS = ("gmx_usde_positions", "GMX USDe Positions", Token.USDE) + GMX_USDE_USDC_LP = ("gmx_usde_usdc_aug", "GMX USDe/USDc LP", Token.USDE) + GMX_WSTETH_USDE_LP = ("gmx_wsteth_usde_aug", "GMX wstETH/USDe LP", Token.USDE) + + # CURVE + CURVE_ETHEREUM_USDE_BORROWERS = ( + "curve_ethereum_usde_borrowers", + "Curve.fi Ethereum USDe Borrowers", + Token.USDE, + ) + CURVE_ETHEREUM_SUSDE_BORROWERS = ( + "curve_ethereum_susde_borrowers", + "Curve.fi Ethereum sUSDe Borrowers", + Token.SUSDE, + ) + + # Beefy + BEEFY_ARBITRUM_USDE = ( + "beefy_arbitrum_usde_held", + "Beefy Arbitrum USDe", + Token.USDE, + ) + BEEFY_FRAXTAL_USDE = ("beefy_fraxtal_usde_held", "Beefy Fraxtal USDe", Token.USDE) + BEEFY_MANTLE_USDE = ("beefy_mantle_usde_held", "Beefy Mantle USDe", Token.USDE) + BEEFY_OPTIMISM_USDE = ( + "beefy_optimism_usde_held", + "Beefy Optimism USDe", + Token.USDE, + ) + + # Allstake + ALLSTAKE_USDE = ("allstake_usde", "Allstake USDe", Token.USDE) + ALLSTAKE_SUSDE = ("allstake_susde", "Allstake sUSDe", Token.SUSDE) + + # Inverse Finance FiRM + FIRM_SUSDE = ("firm_susde", "Inverse Finance FiRM sUSDe", Token.SUSDE) + + # Hyperdrive + HYPERDRIVE_SUSDE = ( + "hyperdrive_susde", + "ElementDAO 182 Day sUSDe Hyperdrive", + Token.SUSDE, + ) + + # Fluid + FLUID = ("Fluid_susde", "Fluid sUSDe", Token.SUSDE) + + def __init__(self, column_name: str, description: str, token: Token = Token.USDE): + self.column_name = column_name + self.description = description + self.token = token + + def get_column_name(self) -> str: + return self.column_name + + def get_description(self) -> str: + return self.description + + def get_token(self) -> Token: + return self.token diff --git a/integrations/lendle_usde.py b/integrations/lendle_usde.py index ae51018..6688f9d 100644 --- a/integrations/lendle_usde.py +++ b/integrations/lendle_usde.py @@ -1,14 +1,13 @@ from constants.chains import Chain -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from models.integration import Integration from constants.summary_columns import SummaryColumn from constants.lendle import LENDLE_USDE_DEPLOYMENT_BLOCK from utils.web3_utils import w3_mantle, fetch_events_logs_with_retry, call_with_retry from utils.lendle import lendle_usde_contract -class LendleIntegration( - Integration -): + +class LendleIntegration(Integration): def __init__(self): super().__init__( IntegrationID.LENDLE_USDE_LPT, diff --git a/integrations/lyra_susde_bull.py b/integrations/lyra_susde_bull.py index 1b994aa..4f5867e 100644 --- a/integrations/lyra_susde_bull.py +++ b/integrations/lyra_susde_bull.py @@ -1,15 +1,26 @@ from utils.web3_utils import W3_BY_CHAIN import logging -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from models.integration import Integration -from utils.lyra import get_vault_users, get_effective_balance, get_exchange_users, get_exchange_balance -from constants.lyra import LYRA_CONTRACTS_AND_START_BY_TOKEN, LyraVaultDetails, DetailType +from utils.lyra import ( + get_vault_users, + get_effective_balance, + get_exchange_users, + get_exchange_balance, +) +from constants.lyra import ( + LYRA_CONTRACTS_AND_START_BY_TOKEN, + LyraVaultDetails, + DetailType, +) class LyraIntegration(Integration): def __init__(self, integration_id: IntegrationID): - self.vault_data: LyraVaultDetails = LYRA_CONTRACTS_AND_START_BY_TOKEN[integration_id] + self.vault_data: LyraVaultDetails = LYRA_CONTRACTS_AND_START_BY_TOKEN[ + integration_id + ] print(self.vault_data) @@ -32,14 +43,18 @@ def get_balance(self, user: str, block: int) -> float: self.vault_data["integration_token"], self.vault_data["bridge"], self.vault_data["vault_token"], - W3_BY_CHAIN[example_integration.chain]["w3"].eth.get_block(block)['timestamp'] + W3_BY_CHAIN[example_integration.chain]["w3"].eth.get_block(block)[ + "timestamp" + ], ) - + else: return get_exchange_balance(user, block) def get_participants(self) -> list: - logging.info(f"[{self.integration_id.get_description()}] Getting participants...") + logging.info( + f"[{self.integration_id.get_description()}] Getting participants..." + ) if self.vault_data["detail_type"] == DetailType.Vault: self.participants = get_vault_users( self.start_block, @@ -60,4 +75,8 @@ def get_participants(self) -> list: print("Found Lyra Participants:") print(example_integration.get_participants()) print("Found Balance of First Participant:") - print(example_integration.get_balance(list(example_integration.participants)[0], current_block)) + print( + example_integration.get_balance( + list(example_integration.participants)[0], current_block + ) + ) diff --git a/integrations/merchantmoe_lbt_integration.py b/integrations/merchantmoe_lbt_integration.py index d416ab5..d854234 100644 --- a/integrations/merchantmoe_lbt_integration.py +++ b/integrations/merchantmoe_lbt_integration.py @@ -3,7 +3,7 @@ from web3.contract import Contract from constants.chains import Chain -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from constants.merchantmoe import ( ZERO_ADDRESS, DEAD_ADDRESS, @@ -20,7 +20,7 @@ def __init__( self, start_block: int, lbt_contract: Contract, - liquidity_helper_contract: Contract + liquidity_helper_contract: Contract, ): super().__init__( IntegrationID.MERCHANT_MOE_METH_USDE_LBT, @@ -36,12 +36,8 @@ def __init__( self.lbt_contract = lbt_contract self.liquidity_helper_contract = liquidity_helper_contract - def get_balance(self, user: str, block: int) -> float: - active_id = call_with_retry( - self.lbt_contract.functions.getActiveId(), - block - ) + active_id = call_with_retry(self.lbt_contract.functions.getActiveId(), block) # calculate the amount in bins for ids that are +/- 20% from active price # 10bp pair, log(1.20)/log(1.001) = 183 bins each side of range @@ -50,18 +46,22 @@ def get_balance(self, user: str, block: int) -> float: bin_range = list(range(lower_bin_bound, upper_bin_bound + 1)) total_liquidity = 0 - logging.info(f"[{self.name}] Calling Liquidity Helper Contract for User: {user}, for bin ids: {bin_range}") + logging.info( + f"[{self.name}] Calling Liquidity Helper Contract for User: {user}, for bin ids: {bin_range}" + ) liquidity = call_with_retry( self.liquidity_helper_contract.functions.getLiquiditiesOf( METH_USDE_MERCHANT_MOE_LBT_CONTRACT, user, bin_range ), - block + block, ) total_liquidity += sum(liquidity) total_liquidity = round(total_liquidity / 10**18, 8) - logging.info(f"[{self.name}] {user} has {total_liquidity} total liquidity within 20% range of the active price") + logging.info( + f"[{self.name}] {user} has {total_liquidity} total liquidity within 20% range of the active price" + ) return total_liquidity def get_participants(self) -> list: @@ -80,10 +80,12 @@ def get_participants(self) -> list: f"{self.name} LBT TransferBatch events", self.lbt_contract.events.TransferBatch(), start_block, - to_block + to_block, ) - logging.info(f"[{self.name}] Scanning blocks {start_block} to {to_block}, received {len(transfers)} mETH/USDe transfer events") + logging.info( + f"[{self.name}] Scanning blocks {start_block} to {to_block}, received {len(transfers)} mETH/USDe transfer events" + ) for transfer in transfers: from_address = transfer["args"]["from"] to_address = transfer["args"]["to"] @@ -107,4 +109,8 @@ def get_participants(self) -> list: liquidity_helper_contract, ) print(merchant_moe_integration.get_participants()) - print(merchant_moe_integration.get_balance(list(merchant_moe_integration.get_participants())[1], "latest")) + print( + merchant_moe_integration.get_balance( + list(merchant_moe_integration.get_participants())[1], "latest" + ) + ) diff --git a/integrations/nuri.py b/integrations/nuri.py index b991eac..3d89396 100644 --- a/integrations/nuri.py +++ b/integrations/nuri.py @@ -1,13 +1,19 @@ from constants.chains import Chain -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from models.integration import Integration -from constants.nuri import NURI_NFP_MANAGER_ADDRESS, NURI_POOL_ADDRESS, NURI_DEPLOYMENT_BLOCK, SCROLL_USDE_TOKEN_ADDRESS +from constants.nuri import ( + NURI_NFP_MANAGER_ADDRESS, + NURI_POOL_ADDRESS, + NURI_DEPLOYMENT_BLOCK, + SCROLL_USDE_TOKEN_ADDRESS, +) from constants.summary_columns import SummaryColumn from utils.nuri import nfp_manager, pool from utils.web3_utils import w3_scroll, fetch_events_logs_with_retry, call_with_retry from web3 import Web3 import math + class Nuri(Integration): def __init__(self): super().__init__( @@ -22,12 +28,26 @@ def __init__(self): def calculate_sqrt_price(self, tick): return math.sqrt(1.0001**tick) * (2**96) - def calculate_token_amounts(self, liquidity, current_tick, lower_tick, upper_tick, sqrt_price_x96, decimals0, decimals1): + def calculate_token_amounts( + self, + liquidity, + current_tick, + lower_tick, + upper_tick, + sqrt_price_x96, + decimals0, + decimals1, + ): sqrt_price_current = sqrt_price_x96 sqrt_price_lower = self.calculate_sqrt_price(lower_tick) sqrt_price_upper = self.calculate_sqrt_price(upper_tick) - amount0 = liquidity * (sqrt_price_upper - sqrt_price_current) / (sqrt_price_current * sqrt_price_upper) * (2**96) + amount0 = ( + liquidity + * (sqrt_price_upper - sqrt_price_current) + / (sqrt_price_current * sqrt_price_upper) + * (2**96) + ) amount1 = liquidity * (sqrt_price_current - sqrt_price_lower) / (2**96) amount0_adjusted = amount0 / (10**decimals0) @@ -44,7 +64,7 @@ def get_balance(self, user: str, block: int) -> float: sqrtPriceX96 = current_tick[0] tick = current_tick[1] - + balance = call_with_retry( nfp_manager.functions.balanceOf(user), block, @@ -81,7 +101,13 @@ def get_balance(self, user: str, block: int) -> float: if token0 == SCROLL_USDE_TOKEN_ADDRESS: # Calculate token amounts for this position amount0, amount1 = self.calculate_token_amounts( - liquidity, tick, tickLower, tickUpper, sqrtPriceX96, 18, 6 # Assuming USDe is 18 decimals and USDT is 6 + liquidity, + tick, + tickLower, + tickUpper, + sqrtPriceX96, + 18, + 6, # Assuming USDe is 18 decimals and USDT is 6 ) # Assuming we want to sum up the USDe amounts @@ -105,23 +131,26 @@ def get_participants(self) -> list: to_block, ) print(f"Fetched {len(mint_events)} Mint events") - + for event in mint_events: - tx_hash = event['transactionHash'] + tx_hash = event["transactionHash"] tx = w3_scroll.eth.get_transaction(tx_hash) - user_address = tx['from'] + user_address = tx["from"] all_users.add(user_address) except Exception as e: - print(f"Error fetching events from block {start_block} to {to_block}: {e}") - + print( + f"Error fetching events from block {start_block} to {to_block}: {e}" + ) + start_block += page_size self.participants = list(all_users) return self.participants - + + if __name__ == "__main__": nuri = Nuri() - #print(nuri.get_balance(Web3.to_checksum_address("0xCE29ECB0D2d8c8f0126ED923C50A35cFb0B613A8"), 7249275)) - #print(nuri.get_participants()) - #print(nuri.get_balance(nuri.participants[0], 7249275)) + # print(nuri.get_balance(Web3.to_checksum_address("0xCE29ECB0D2d8c8f0126ED923C50A35cFb0B613A8"), 7249275)) + # print(nuri.get_participants()) + # print(nuri.get_balance(nuri.participants[0], 7249275)) diff --git a/integrations/pendle_lpt_integration.py b/integrations/pendle_lpt_integration.py index 09fcc6d..a7ec5fb 100644 --- a/integrations/pendle_lpt_integration.py +++ b/integrations/pendle_lpt_integration.py @@ -8,7 +8,7 @@ from constants.pendle import PENDLE_USDE_JULY_DEPLOYMENT_BLOCK from models.integration import Integration from utils import pendle -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from constants.summary_columns import SummaryColumn from utils.pendle import get_pendle_participants_v3 from utils.web3_utils import call_with_retry @@ -83,7 +83,9 @@ def get_participants(self) -> list: if self.participants is not None: return self.participants - logging.info(f"[{self.integration_id.get_description()}] Getting participants...") + logging.info( + f"[{self.integration_id.get_description()}] Getting participants..." + ) self.participants = self.get_participants_func( [self.sy_contract.address, self.lp_contract.address] ) diff --git a/integrations/pendle_yt_integration.py b/integrations/pendle_yt_integration.py index e3952e0..7eae671 100644 --- a/integrations/pendle_yt_integration.py +++ b/integrations/pendle_yt_integration.py @@ -6,7 +6,7 @@ from constants.chains import Chain from models.integration import Integration -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from constants.summary_columns import SummaryColumn from utils.pendle import get_pendle_participants_v3 from utils.web3_utils import call_with_retry diff --git a/integrations/penpie_ena_aug.py b/integrations/penpie_ena_aug.py index e425e34..c49cc00 100644 --- a/integrations/penpie_ena_aug.py +++ b/integrations/penpie_ena_aug.py @@ -1,6 +1,6 @@ -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from utils.penpie import PENPIEIntegration -from constants.penpie import ENA29AUG2024_PRT, ENA29AUG2024_PRT_DEPLOYMENT_BLOCK +from constants.penpie import ENA29AUG2024_PRT, ENA29AUG2024_PRT_DEPLOYMENT_BLOCK from constants.chains import Chain from constants.penpie import PENDLE_LOCKER_ETHEREUM @@ -12,8 +12,11 @@ Chain.ETHEREUM, 30, 1, - [PENDLE_LOCKER_ETHEREUM] - + [PENDLE_LOCKER_ETHEREUM], ) # print(penpie_integration.get_participants()) - print(penpie_integration.get_balance("0xb60c9094FF0DFfF6aA266063A4C176B00Ad07fE8", "latest")) \ No newline at end of file + print( + penpie_integration.get_balance( + "0xb60c9094FF0DFfF6aA266063A4C176B00Ad07fE8", "latest" + ) + ) diff --git a/integrations/penpie_ena_oct.py b/integrations/penpie_ena_oct.py index ac85d6f..1031c9f 100644 --- a/integrations/penpie_ena_oct.py +++ b/integrations/penpie_ena_oct.py @@ -1,6 +1,6 @@ -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from utils.penpie import PENPIEIntegration -from constants.penpie import ENA_31OCT2024, ENA_31OCT2024_DEPLOYMENT_BLOCK +from constants.penpie import ENA_31OCT2024, ENA_31OCT2024_DEPLOYMENT_BLOCK from constants.chains import Chain from constants.penpie import PENDLE_LOCKER_ETHEREUM @@ -12,8 +12,11 @@ Chain.ETHEREUM, 30, 1, - [PENDLE_LOCKER_ETHEREUM] - + [PENDLE_LOCKER_ETHEREUM], ) # print(penpie_integration.get_participants()) - print(penpie_integration.get_balance("0x9EF171A8C62Eea6455830Bde5de99Db5A7cA5119", "latest")) \ No newline at end of file + print( + penpie_integration.get_balance( + "0x9EF171A8C62Eea6455830Bde5de99Db5A7cA5119", "latest" + ) + ) diff --git a/integrations/penpie_karak_susde_sep.py b/integrations/penpie_karak_susde_sep.py index d60765d..803c65c 100644 --- a/integrations/penpie_karak_susde_sep.py +++ b/integrations/penpie_karak_susde_sep.py @@ -1,6 +1,9 @@ -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from utils.penpie import PENPIEIntegration -from constants.penpie import Karak_sUSDe_26SEP2024_PRT, Karak_sUSDe_26SEP2024_PRT_DEPLOYMENT_BLOCK +from constants.penpie import ( + Karak_sUSDe_26SEP2024_PRT, + Karak_sUSDe_26SEP2024_PRT_DEPLOYMENT_BLOCK, +) from constants.chains import Chain from constants.penpie import PENDLE_LOCKER_ETHEREUM @@ -12,8 +15,11 @@ Chain.ETHEREUM, 5, 1, - [PENDLE_LOCKER_ETHEREUM] - + [PENDLE_LOCKER_ETHEREUM], ) # print(penpie_integration.get_participants()) - print(penpie_integration.get_balance("0xb873BCF80afA89c2A9e5182f5792d64a03Eb4311", "latest")) \ No newline at end of file + print( + penpie_integration.get_balance( + "0xb873BCF80afA89c2A9e5182f5792d64a03Eb4311", "latest" + ) + ) diff --git a/integrations/penpie_karak_usde_sep.py b/integrations/penpie_karak_usde_sep.py index 7afd1f0..81bcd7a 100644 --- a/integrations/penpie_karak_usde_sep.py +++ b/integrations/penpie_karak_usde_sep.py @@ -1,6 +1,9 @@ -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from utils.penpie import PENPIEIntegration -from constants.penpie import Karak_USDE_26SEP2024_PRT, Karak_USDE_26SEP2024_PRT_DEPLOYMENT_BLOCK +from constants.penpie import ( + Karak_USDE_26SEP2024_PRT, + Karak_USDE_26SEP2024_PRT_DEPLOYMENT_BLOCK, +) from constants.chains import Chain from constants.penpie import PENDLE_LOCKER_ETHEREUM @@ -12,8 +15,11 @@ Chain.ETHEREUM, 20, 1, - [PENDLE_LOCKER_ETHEREUM] - + [PENDLE_LOCKER_ETHEREUM], ) # print(penpie_integration.get_participants()) - print(penpie_integration.get_balance("0x404581FA706E4E0d649A40eA503f9bCee3D2d76c", "latest")) \ No newline at end of file + print( + penpie_integration.get_balance( + "0x404581FA706E4E0d649A40eA503f9bCee3D2d76c", "latest" + ) + ) diff --git a/integrations/penpie_mellow_rsena_sep.py b/integrations/penpie_mellow_rsena_sep.py index ed67f63..1440c2f 100644 --- a/integrations/penpie_mellow_rsena_sep.py +++ b/integrations/penpie_mellow_rsena_sep.py @@ -1,6 +1,6 @@ -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from utils.penpie import PENPIEIntegration -from constants.penpie import rsENA_26SEP2024, rsENA_26SEP2024_DEPLOYMENT_BLOCK +from constants.penpie import rsENA_26SEP2024, rsENA_26SEP2024_DEPLOYMENT_BLOCK from constants.chains import Chain from constants.penpie import PENDLE_LOCKER_ETHEREUM @@ -12,8 +12,7 @@ Chain.ETHEREUM, 30, 1, - [PENDLE_LOCKER_ETHEREUM] - + [PENDLE_LOCKER_ETHEREUM], ) print(penpie_integration.get_participants()) - # print(penpie_integration.get_balance("0x9EF171A8C62Eea6455830Bde5de99Db5A7cA5119", "latest")) \ No newline at end of file + # print(penpie_integration.get_balance("0x9EF171A8C62Eea6455830Bde5de99Db5A7cA5119", "latest")) diff --git a/integrations/penpie_mellow_rusde_sep.py b/integrations/penpie_mellow_rusde_sep.py index f211e6e..663d75b 100644 --- a/integrations/penpie_mellow_rusde_sep.py +++ b/integrations/penpie_mellow_rusde_sep.py @@ -1,6 +1,6 @@ -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from utils.penpie import PENPIEIntegration -from constants.penpie import rsUSDe_26SEP2024, rsUSDe_26SEP2024_DEPLOYMENT_BLOCK +from constants.penpie import rsUSDe_26SEP2024, rsUSDe_26SEP2024_DEPLOYMENT_BLOCK from constants.chains import Chain from constants.penpie import PENDLE_LOCKER_ETHEREUM @@ -12,8 +12,7 @@ Chain.ETHEREUM, 10, 1, - [PENDLE_LOCKER_ETHEREUM] - + [PENDLE_LOCKER_ETHEREUM], ) print(penpie_integration.get_participants()) - # print(penpie_integration.get_balance("0x404581FA706E4E0d649A40eA503f9bCee3D2d76c", "latest")) \ No newline at end of file + # print(penpie_integration.get_balance("0x404581FA706E4E0d649A40eA503f9bCee3D2d76c", "latest")) diff --git a/integrations/penpie_susde_25apr.py b/integrations/penpie_susde_25apr.py index 512c55b..ce6f955 100644 --- a/integrations/penpie_susde_25apr.py +++ b/integrations/penpie_susde_25apr.py @@ -1,6 +1,6 @@ -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from utils.penpie import PENPIEIntegration -from constants.penpie import sUSDe25APR2024_PRT, sUSDe25APR2024_PRT_DEPLOYMENT_BLOCK +from constants.penpie import sUSDe25APR2024_PRT, sUSDe25APR2024_PRT_DEPLOYMENT_BLOCK from constants.chains import Chain from constants.penpie import PENDLE_LOCKER_ETHEREUM @@ -12,8 +12,11 @@ Chain.ETHEREUM, 20, 1, - [PENDLE_LOCKER_ETHEREUM] - + [PENDLE_LOCKER_ETHEREUM], ) # print(penpie_integration.get_participants()) - print(penpie_integration.get_balance("0x48553662B61D9B246206fdC5Ee06C643ED85cb00", "latest")) \ No newline at end of file + print( + penpie_integration.get_balance( + "0x48553662B61D9B246206fdC5Ee06C643ED85cb00", "latest" + ) + ) diff --git a/integrations/penpie_susde_dec.py b/integrations/penpie_susde_dec.py index 0238790..efab39e 100644 --- a/integrations/penpie_susde_dec.py +++ b/integrations/penpie_susde_dec.py @@ -1,6 +1,6 @@ -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from utils.penpie import PENPIEIntegration -from constants.penpie import sUSDE_26DEC2024, sUSDE_26DEC2024_DEPLOYMENT_BLOCK +from constants.penpie import sUSDE_26DEC2024, sUSDE_26DEC2024_DEPLOYMENT_BLOCK from constants.chains import Chain from constants.penpie import PENDLE_LOCKER_ETHEREUM @@ -12,8 +12,7 @@ Chain.ETHEREUM, 20, 1, - [PENDLE_LOCKER_ETHEREUM] - + [PENDLE_LOCKER_ETHEREUM], ) print(penpie_integration.get_participants()) - # print(penpie_integration.get_balance("0xe95176DF139a93D706655B32Df087a97e212B78E", "latest")) \ No newline at end of file + # print(penpie_integration.get_balance("0xe95176DF139a93D706655B32Df087a97e212B78E", "latest")) diff --git a/integrations/penpie_susde_july.py b/integrations/penpie_susde_july.py index e218a09..5c07a70 100644 --- a/integrations/penpie_susde_july.py +++ b/integrations/penpie_susde_july.py @@ -1,6 +1,6 @@ -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from utils.penpie import PENPIEIntegration -from constants.penpie import SUSDE_JULY, SUSDE_JULY_DEPLOYMENT_BLOCK +from constants.penpie import SUSDE_JULY, SUSDE_JULY_DEPLOYMENT_BLOCK from constants.chains import Chain from constants.penpie import PENDLE_LOCKER_ETHEREUM @@ -12,8 +12,11 @@ Chain.ETHEREUM, 20, 1, - [PENDLE_LOCKER_ETHEREUM] - + [PENDLE_LOCKER_ETHEREUM], ) # print(penpie_integration.get_participants()) - print(penpie_integration.get_balance("0x79E40Ab4BAc23E2910C03E2Fc24819fE498A9491", "latest")) \ No newline at end of file + print( + penpie_integration.get_balance( + "0x79E40Ab4BAc23E2910C03E2Fc24819fE498A9491", "latest" + ) + ) diff --git a/integrations/penpie_susde_oct.py b/integrations/penpie_susde_oct.py index d9dc0ca..e6a977d 100644 --- a/integrations/penpie_susde_oct.py +++ b/integrations/penpie_susde_oct.py @@ -1,6 +1,6 @@ -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from utils.penpie import PENPIEIntegration -from constants.penpie import sUSDE_24OCT2024, sUSDE_24OCT2024_DEPLOYMENT_BLOCK +from constants.penpie import sUSDE_24OCT2024, sUSDE_24OCT2024_DEPLOYMENT_BLOCK from constants.chains import Chain from constants.penpie import PENDLE_LOCKER_ETHEREUM @@ -12,8 +12,7 @@ Chain.ETHEREUM, 20, 1, - [PENDLE_LOCKER_ETHEREUM] - + [PENDLE_LOCKER_ETHEREUM], ) print(penpie_integration.get_participants()) - # print(penpie_integration.get_balance("0xe95176DF139a93D706655B32Df087a97e212B78E", "latest")) \ No newline at end of file + # print(penpie_integration.get_balance("0xe95176DF139a93D706655B32Df087a97e212B78E", "latest")) diff --git a/integrations/penpie_susde_sep.py b/integrations/penpie_susde_sep.py index 3d113bc..e8a468e 100644 --- a/integrations/penpie_susde_sep.py +++ b/integrations/penpie_susde_sep.py @@ -1,6 +1,6 @@ -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from utils.penpie import PENPIEIntegration -from constants.penpie import sUSDe26SEP2024_PRT, sUSDe26SEP2024_PRT_DEPLOYMENT_BLOCK +from constants.penpie import sUSDe26SEP2024_PRT, sUSDe26SEP2024_PRT_DEPLOYMENT_BLOCK from constants.chains import Chain from constants.penpie import PENDLE_LOCKER_ETHEREUM @@ -12,8 +12,11 @@ Chain.ETHEREUM, 20, 1, - [PENDLE_LOCKER_ETHEREUM] - + [PENDLE_LOCKER_ETHEREUM], ) # print(penpie_integration.get_participants()) - print(penpie_integration.get_balance("0xe95176DF139a93D706655B32Df087a97e212B78E", "latest")) \ No newline at end of file + print( + penpie_integration.get_balance( + "0xe95176DF139a93D706655B32Df087a97e212B78E", "latest" + ) + ) diff --git a/integrations/penpie_usde_aug_Arb.py b/integrations/penpie_usde_aug_Arb.py index 4a51db1..a788031 100644 --- a/integrations/penpie_usde_aug_Arb.py +++ b/integrations/penpie_usde_aug_Arb.py @@ -1,6 +1,6 @@ -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from utils.penpie import PENPIEIntegration -from constants.penpie import USDE_ARB_AUG2024, USDE_ARB_AUG2024_DEPLOYMENT_BLOCK +from constants.penpie import USDE_ARB_AUG2024, USDE_ARB_AUG2024_DEPLOYMENT_BLOCK from constants.chains import Chain from constants.penpie import PENDLE_LOCKER_ARBITRUM @@ -12,8 +12,7 @@ Chain.ARBITRUM, 20, 1, - [PENDLE_LOCKER_ARBITRUM] - + [PENDLE_LOCKER_ARBITRUM], ) print(penpie_integration.get_participants()) - # print(penpie_integration.get_balance("0xe95176DF139a93D706655B32Df087a97e212B78E", "latest")) \ No newline at end of file + # print(penpie_integration.get_balance("0xe95176DF139a93D706655B32Df087a97e212B78E", "latest")) diff --git a/integrations/penpie_usde_dec.py b/integrations/penpie_usde_dec.py index 7da7925..307910a 100644 --- a/integrations/penpie_usde_dec.py +++ b/integrations/penpie_usde_dec.py @@ -1,6 +1,6 @@ -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from utils.penpie import PENPIEIntegration -from constants.penpie import USDe_26DEC2024, USDe_26DEC2024_DEPLOYMENT_BLOCK +from constants.penpie import USDe_26DEC2024, USDe_26DEC2024_DEPLOYMENT_BLOCK from constants.chains import Chain from constants.penpie import PENDLE_LOCKER_ETHEREUM @@ -12,8 +12,11 @@ Chain.ETHEREUM, 25, 1, - [PENDLE_LOCKER_ETHEREUM] - + [PENDLE_LOCKER_ETHEREUM], ) # print(penpie_integration.get_participants()) - print(penpie_integration.get_balance("0xe95176DF139a93D706655B32Df087a97e212B78E", "latest")) \ No newline at end of file + print( + penpie_integration.get_balance( + "0xe95176DF139a93D706655B32Df087a97e212B78E", "latest" + ) + ) diff --git a/integrations/penpie_usde_july.py b/integrations/penpie_usde_july.py index 91b10c6..a42ce66 100644 --- a/integrations/penpie_usde_july.py +++ b/integrations/penpie_usde_july.py @@ -1,6 +1,6 @@ -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from utils.penpie import PENPIEIntegration -from constants.penpie import USDe25JUL2024_PRT, USDe25JUL2024_PRT_DEPLOYMENT_BLOCK +from constants.penpie import USDe25JUL2024_PRT, USDe25JUL2024_PRT_DEPLOYMENT_BLOCK from constants.chains import Chain from constants.penpie import PENDLE_LOCKER_ETHEREUM @@ -12,8 +12,11 @@ Chain.ETHEREUM, 25, 1, - [PENDLE_LOCKER_ETHEREUM] - + [PENDLE_LOCKER_ETHEREUM], ) # print(penpie_integration.get_participants()) - print(penpie_integration.get_balance("0x79E40Ab4BAc23E2910C03E2Fc24819fE498A9491", "latest")) \ No newline at end of file + print( + penpie_integration.get_balance( + "0x79E40Ab4BAc23E2910C03E2Fc24819fE498A9491", "latest" + ) + ) diff --git a/integrations/penpie_usde_nov_arb.py b/integrations/penpie_usde_nov_arb.py index 51471f6..9e81a1c 100644 --- a/integrations/penpie_usde_nov_arb.py +++ b/integrations/penpie_usde_nov_arb.py @@ -1,6 +1,6 @@ -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from utils.penpie import PENPIEIntegration -from constants.penpie import USDE_ARB_NOV2024, USDE_ARB_NOV2024_DEPLOYMENT_BLOCK +from constants.penpie import USDE_ARB_NOV2024, USDE_ARB_NOV2024_DEPLOYMENT_BLOCK from constants.chains import Chain from constants.penpie import PENDLE_LOCKER_ARBITRUM @@ -12,8 +12,11 @@ Chain.ARBITRUM, 20, 1, - [PENDLE_LOCKER_ARBITRUM] - + [PENDLE_LOCKER_ARBITRUM], ) # print(penpie_integration.get_participants()) - print(penpie_integration.get_balance("0xe95176DF139a93D706655B32Df087a97e212B78E", "latest")) \ No newline at end of file + print( + penpie_integration.get_balance( + "0xe95176DF139a93D706655B32Df087a97e212B78E", "latest" + ) + ) diff --git a/integrations/penpie_usde_oct.py b/integrations/penpie_usde_oct.py index 57f5d40..efccd89 100644 --- a/integrations/penpie_usde_oct.py +++ b/integrations/penpie_usde_oct.py @@ -1,6 +1,6 @@ -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from utils.penpie import PENPIEIntegration -from constants.penpie import USDe_24OCT2024, USDe_24OCT2024_DEPLOYMENT_BLOCK +from constants.penpie import USDe_24OCT2024, USDe_24OCT2024_DEPLOYMENT_BLOCK from constants.chains import Chain from constants.penpie import PENDLE_LOCKER_ETHEREUM @@ -12,8 +12,11 @@ Chain.ETHEREUM, 25, 1, - [PENDLE_LOCKER_ETHEREUM] - + [PENDLE_LOCKER_ETHEREUM], ) # print(penpie_integration.get_participants()) - print(penpie_integration.get_balance("0x79E40Ab4BAc23E2910C03E2Fc24819fE498A9491", "latest")) \ No newline at end of file + print( + penpie_integration.get_balance( + "0x79E40Ab4BAc23E2910C03E2Fc24819fE498A9491", "latest" + ) + ) diff --git a/integrations/penpie_zircuit_usde_jun.py b/integrations/penpie_zircuit_usde_jun.py index 0e17428..a77956f 100644 --- a/integrations/penpie_zircuit_usde_jun.py +++ b/integrations/penpie_zircuit_usde_jun.py @@ -1,6 +1,9 @@ -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from utils.penpie import PENPIEIntegration -from constants.penpie import Zircuit_USDe27JUN2024_PRT, Zircuit_USDe27JUN2024_PRT_DEPLOYMENT_BLOCK +from constants.penpie import ( + Zircuit_USDe27JUN2024_PRT, + Zircuit_USDe27JUN2024_PRT_DEPLOYMENT_BLOCK, +) from constants.chains import Chain from constants.penpie import PENDLE_LOCKER_ETHEREUM @@ -12,8 +15,11 @@ Chain.ETHEREUM, 25, 1, - [PENDLE_LOCKER_ETHEREUM] - + [PENDLE_LOCKER_ETHEREUM], ) # print(penpie_integration.get_participants()) - print(penpie_integration.get_balance("0xC5FBC522B2C1Ff8A47c2b7BF947321C808be5e64", "latest")) \ No newline at end of file + print( + penpie_integration.get_balance( + "0xC5FBC522B2C1Ff8A47c2b7BF947321C808be5e64", "latest" + ) + ) diff --git a/integrations/radiant_usde.py b/integrations/radiant_usde.py index b72d458..44727de 100644 --- a/integrations/radiant_usde.py +++ b/integrations/radiant_usde.py @@ -1,15 +1,20 @@ from utils.web3_utils import W3_BY_CHAIN import logging -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from models.integration import Integration from utils.radiant import get_radiant_lenders, get_effective_balance -from constants.radiant import RADIANT_CONTRACTS_AND_START_BY_TOKEN, RadiantLendingDetails +from constants.radiant import ( + RADIANT_CONTRACTS_AND_START_BY_TOKEN, + RadiantLendingDetails, +) class RadiantIntegration(Integration): def __init__(self, integration_id: IntegrationID): - self.vault_data: RadiantLendingDetails = RADIANT_CONTRACTS_AND_START_BY_TOKEN[integration_id] + self.vault_data: RadiantLendingDetails = RADIANT_CONTRACTS_AND_START_BY_TOKEN[ + integration_id + ] print(self.vault_data) @@ -34,7 +39,9 @@ def get_balance(self, user: str, block: int) -> float: ) def get_participants(self) -> list: - logging.info(f"[{self.integration_id.get_description()}] Getting participants...") + logging.info( + f"[{self.integration_id.get_description()}] Getting participants..." + ) self.participants = get_radiant_lenders( self.vault_data["graph_url"], self.vault_data["collateral_address"], @@ -45,10 +52,14 @@ def get_participants(self) -> list: if __name__ == "__main__": example_integration = RadiantIntegration(IntegrationID.RADIANT_USDE_CORE_ARBITRUM) - current_block = W3_BY_CHAIN[example_integration.chain]['w3'].eth.get_block_number() + current_block = W3_BY_CHAIN[example_integration.chain]["w3"].eth.get_block_number() print("Block:", current_block) print("Found Radiant Participants:") print(len(example_integration.get_participants())) print("Found Balance of First Participant:", example_integration.participants[0]) - print(example_integration.get_balance(example_integration.participants[0], current_block)) + print( + example_integration.get_balance( + example_integration.participants[0], current_block + ) + ) diff --git a/integrations/ramses.py b/integrations/ramses.py index 692327e..13056aa 100644 --- a/integrations/ramses.py +++ b/integrations/ramses.py @@ -1,13 +1,19 @@ from constants.chains import Chain -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from models.integration import Integration -from constants.ramses import RAMSES_DEPLOYMENT_BLOCK, RAMSES_NFP_MANAGER_ADDRESS, RAMSES_POOL_ADDRESS, ARBITRUM_USDE_TOKEN_ADDRESS +from constants.ramses import ( + RAMSES_DEPLOYMENT_BLOCK, + RAMSES_NFP_MANAGER_ADDRESS, + RAMSES_POOL_ADDRESS, + ARBITRUM_USDE_TOKEN_ADDRESS, +) from constants.summary_columns import SummaryColumn from utils.ramses import nfp_manager, pool from utils.web3_utils import w3_arb, fetch_events_logs_with_retry, call_with_retry from web3 import Web3 import math + class Ramses(Integration): def __init__(self): super().__init__( @@ -22,7 +28,16 @@ def __init__(self): def calculate_sqrt_price(self, tick): return math.sqrt(1.0001**tick) * (2**96) - def calculate_token_amounts(self, liquidity, current_tick, lower_tick, upper_tick, sqrt_price_x96, decimals0, decimals1): + def calculate_token_amounts( + self, + liquidity, + current_tick, + lower_tick, + upper_tick, + sqrt_price_x96, + decimals0, + decimals1, + ): sqrt_price_current = sqrt_price_x96 / (2**96) sqrt_price_lower = self.calculate_sqrt_price(lower_tick) / (2**96) sqrt_price_upper = self.calculate_sqrt_price(upper_tick) / (2**96) @@ -51,7 +66,7 @@ def get_balance(self, user: str, block: int) -> float: sqrtPriceX96 = current_tick[0] tick = current_tick[1] - + balance = call_with_retry( nfp_manager.functions.balanceOf(user), block, @@ -112,32 +127,37 @@ def get_participants(self) -> list: to_block, ) print(f"Fetched {len(mint_events)} Mint events") - + for event in mint_events: - tx_hash = event['transactionHash'] + tx_hash = event["transactionHash"] tx = w3_arb.eth.get_transaction(tx_hash) - user_address = tx['from'] + user_address = tx["from"] all_users.add(user_address) except Exception as e: - print(f"Error fetching events from block {start_block} to {to_block}: {e}") - + print( + f"Error fetching events from block {start_block} to {to_block}: {e}" + ) + start_block += page_size self.participants = list(all_users) return self.participants - + + if __name__ == "__main__": ramses = Ramses() try: latest_block = w3_arb.eth.get_block_number() test_block = latest_block - 100 print(f"Testing with block number: {test_block}") - - test_address = Web3.to_checksum_address("0xED12959952FAb1d304555cFb0146Ed3E6265DE42") + + test_address = Web3.to_checksum_address( + "0xED12959952FAb1d304555cFb0146Ed3E6265DE42" + ) balance = ramses.get_balance(test_address, test_block) print(f"Balance for {test_address}: {balance}") - + participants = ramses.get_participants() print(f"Number of participants: {len(participants)}") if participants: diff --git a/integrations/splice_susde_lpt.py b/integrations/splice_susde_lpt.py index 0dd5eab..d4e20fc 100644 --- a/integrations/splice_susde_lpt.py +++ b/integrations/splice_susde_lpt.py @@ -1,7 +1,7 @@ -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from utils.splice import SpliceIntegration if __name__ == "__main__": integration = SpliceIntegration(IntegrationID.SPLICE_SUSDE_LPT) print(integration.get_participants()) - print(integration.get_balance(list(integration.get_participants())[0], "latest")) \ No newline at end of file + print(integration.get_balance(list(integration.get_participants())[0], "latest")) diff --git a/integrations/splice_susde_yt.py b/integrations/splice_susde_yt.py index e9b57ca..5c7bed7 100644 --- a/integrations/splice_susde_yt.py +++ b/integrations/splice_susde_yt.py @@ -1,8 +1,7 @@ -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from utils.splice import SpliceIntegration if __name__ == "__main__": integration = SpliceIntegration(IntegrationID.SPLICE_SUSDE_YT) print(integration.get_participants()) print(integration.get_balance(list(integration.get_participants())[0], "latest")) - diff --git a/integrations/splice_usde_lpt.py b/integrations/splice_usde_lpt.py index 12361f7..865bbba 100644 --- a/integrations/splice_usde_lpt.py +++ b/integrations/splice_usde_lpt.py @@ -1,7 +1,7 @@ -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from utils.splice import SpliceIntegration if __name__ == "__main__": integration = SpliceIntegration(IntegrationID.SPLICE_USDE_LPT) print(integration.get_participants()) - print(integration.get_balance(list(integration.get_participants())[0], "latest")) \ No newline at end of file + print(integration.get_balance(list(integration.get_participants())[0], "latest")) diff --git a/integrations/splice_usde_yt.py b/integrations/splice_usde_yt.py index 4b9cda9..636da32 100644 --- a/integrations/splice_usde_yt.py +++ b/integrations/splice_usde_yt.py @@ -1,8 +1,7 @@ -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from utils.splice import SpliceIntegration if __name__ == "__main__": integration = SpliceIntegration(IntegrationID.SPLICE_USDE_YT) print(integration.get_participants()) print(integration.get_balance(list(integration.get_participants())[0], "latest")) - diff --git a/integrations/stakedao_susde_july.py b/integrations/stakedao_susde_july.py index df2f3ad..c7b8f3d 100644 --- a/integrations/stakedao_susde_july.py +++ b/integrations/stakedao_susde_july.py @@ -1,6 +1,6 @@ -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from utils.stakedao import StakeDAOIntegration -from constants.stakedao import SUSDE_JULY, SUSDE_JULY_DEPLOYMENT_BLOCK +from constants.stakedao import SUSDE_JULY, SUSDE_JULY_DEPLOYMENT_BLOCK if __name__ == "__main__": stakedao_integration = StakeDAOIntegration( diff --git a/integrations/stakedao_susde_sept.py b/integrations/stakedao_susde_sept.py index 3add097..ac6d4fc 100644 --- a/integrations/stakedao_susde_sept.py +++ b/integrations/stakedao_susde_sept.py @@ -1,6 +1,6 @@ -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from utils.stakedao import StakeDAOIntegration -from constants.stakedao import SUSDE_SEPT, SUSDE_SEPT_DEPLOYMENT_BLOCK +from constants.stakedao import SUSDE_SEPT, SUSDE_SEPT_DEPLOYMENT_BLOCK if __name__ == "__main__": stakedao_integration = StakeDAOIntegration( diff --git a/integrations/stakedao_usde_july.py b/integrations/stakedao_usde_july.py index 2c5f637..5db1567 100644 --- a/integrations/stakedao_usde_july.py +++ b/integrations/stakedao_usde_july.py @@ -1,6 +1,6 @@ -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from utils.stakedao import StakeDAOIntegration -from constants.stakedao import USDE_JULY, USDE_JULY_DEPLOYMENT_BLOCK +from constants.stakedao import USDE_JULY, USDE_JULY_DEPLOYMENT_BLOCK if __name__ == "__main__": stakedao_integration = StakeDAOIntegration( diff --git a/integrations/synthetix.py b/integrations/synthetix.py index cf7035c..c1f860c 100644 --- a/integrations/synthetix.py +++ b/integrations/synthetix.py @@ -1,5 +1,5 @@ from constants.chains import Chain -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from models.integration import Integration from constants.synthetix import SYNTHETIX_ARB_DEPLOYMENT_BLOCK, ARB_USDE_TOKEN_ADDRESS from constants.summary_columns import SummaryColumn diff --git a/integrations/template.py b/integrations/template.py index 941194f..430910a 100644 --- a/integrations/template.py +++ b/integrations/template.py @@ -1,5 +1,5 @@ from constants.chains import Chain -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from models.integration import Integration diff --git a/integrations/term_susde.py b/integrations/term_susde.py index c361097..58bb1a1 100644 --- a/integrations/term_susde.py +++ b/integrations/term_susde.py @@ -1,7 +1,7 @@ from typing import List import requests from constants.chains import Chain -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from constants.integration_token import Token from constants.summary_columns import SummaryColumn from models.integration import Integration @@ -90,20 +90,21 @@ """ collateral_token_addresses = { - Token.SUSDE: "0x9d39a5de30e57443bff2a8307a4256c8797a3497", # Mainnet address for SUSDE + Token.SUSDE: "0x9d39a5de30e57443bff2a8307a4256c8797a3497", # Mainnet address for SUSDE # Token.USDE: "0x7e7e112A68d8D2E221E11047f6E4D7a8eB2dC5e1", # Unsupported # Token.ENA: "0x5e0489aF6e9fd2177eA34aa7A3fD5cD205e3fEe6", # Unsupported } + # Helper for making graphql queries def fetch_data(url, query): - response = requests.post(url, json={'query': query}) + response = requests.post(url, json={"query": query}) if response.status_code == 200: response_json = response.json() - if 'data' not in response_json: + if "data" not in response_json: print(f"Query failed with response: {response_json}") return None - return response_json['data'] + return response_json["data"] else: print(f"Query failed with status code {response.status_code}") return None @@ -113,9 +114,8 @@ def fetch_data(url, query): # TermFinance integration ##################################################### ############################################################################### -class TermFinanceIntegration( - Integration -): + +class TermFinanceIntegration(Integration): def __init__(self): repo_lockers_response = fetch_data( url=term_finance_subgraph_url_mainnet, @@ -123,17 +123,17 @@ def __init__(self): ) repo_lockers = [] if repo_lockers_response is not None: - for result in repo_lockers_response['termRepos']: - repo_lockers.append(result['termRepoLocker']) + for result in repo_lockers_response["termRepos"]: + repo_lockers.append(result["termRepoLocker"]) super().__init__( integration_id=IntegrationID.TERM_SUSDE, start_block=16380765, chain=Chain.ETHEREUM, summary_cols=None, - reward_multiplier=20, # TODO: Change 20 to the sats multiplier for the protocol that has been agreed upon - balance_multiplier=1, # TODO: Almost always 1, optionally change to a different value if an adjustment needs to be applied to balances + reward_multiplier=20, # TODO: Change 20 to the sats multiplier for the protocol that has been agreed upon + balance_multiplier=1, # TODO: Almost always 1, optionally change to a different value if an adjustment needs to be applied to balances excluded_addresses=repo_lockers, - end_block=None, # No end block, protocol is still active + end_block=None, # No end block, protocol is still active reward_multiplier_func=None, # reward_multiplier should be the same across blocks ) @@ -151,15 +151,15 @@ def get_balance(self, user: str, block: int) -> float: # Add the results together (amount + amountLocked) to get the total balance total_balance = 0 if balance_results is not None: - for result in balance_results['termRepoCollaterals']: - total_balance += int(result['amountLocked']) - for result in balance_results['termBidCollaterals']: - total_balance += int(result['amount']) + for result in balance_results["termRepoCollaterals"]: + total_balance += int(result["amountLocked"]) + for result in balance_results["termBidCollaterals"]: + total_balance += int(result["amount"]) else: print(f"Failed to get balance for user {user} at block {block}") return total_balance - + def get_participants(self) -> list: # Make two queries: one to get borrower repo collateral and one to get borrower bid collateral participants_results = fetch_data( @@ -172,10 +172,10 @@ def get_participants(self) -> list: # Build a set of all possible borrowers (de-duplicating them during set add) participants = set() if participants_results is not None: - for result in participants_results['termRepoCollaterals']: - participants.add(result['repoExposure']['borrower']) - for result in participants_results['termBidCollaterals']: - participants.add(result['bid']['bidder']) + for result in participants_results["termRepoCollaterals"]: + participants.add(result["repoExposure"]["borrower"]) + for result in participants_results["termBidCollaterals"]: + participants.add(result["bid"]["bidder"]) else: print(f"Failed to get participants") @@ -233,4 +233,8 @@ def is_user_a_participant(self, user: str) -> bool: if __name__ == "__main__": example_integration = TermFinanceIntegration() print(example_integration.get_participants()) - print(example_integration.get_balance(list(example_integration.get_participants())[0], 20169604)) + print( + example_integration.get_balance( + list(example_integration.get_participants())[0], 20169604 + ) + ) diff --git a/integrations/velodrome_mode_susde.py b/integrations/velodrome_mode_susde.py index 2c4432d..659f16d 100644 --- a/integrations/velodrome_mode_susde.py +++ b/integrations/velodrome_mode_susde.py @@ -1,13 +1,11 @@ from constants.chains import Chain -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from models.integration import Integration from constants.velodrome import VELODROME_MODE_START_BLOCK, SUSDE_MODE_TOKEN from utils.velodrome import fetch_balance, fetch_participants -class VelodromeIntegration( - Integration -): +class VelodromeIntegration(Integration): def __init__(self): super().__init__( IntegrationID.VELODROME_MODE_SUSDE, @@ -27,5 +25,6 @@ def get_participants(self) -> list: self.participants = fetch_participants(SUSDE_MODE_TOKEN) return self.participants + if __name__ == "__main__": velodrome_integration = VelodromeIntegration() diff --git a/integrations/velodrome_mode_usde.py b/integrations/velodrome_mode_usde.py index aa293c2..e42037a 100644 --- a/integrations/velodrome_mode_usde.py +++ b/integrations/velodrome_mode_usde.py @@ -1,13 +1,11 @@ from constants.chains import Chain -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from models.integration import Integration from constants.velodrome import VELODROME_MODE_START_BLOCK, USDE_MODE_TOKEN from utils.velodrome import fetch_balance, fetch_participants -class VelodromeIntegration( - Integration -): +class VelodromeIntegration(Integration): def __init__(self): super().__init__( IntegrationID.VELODROME_MODE_USDE, @@ -27,6 +25,7 @@ def get_participants(self) -> list: self.participants = fetch_participants(USDE_MODE_TOKEN) return self.participants + if __name__ == "__main__": velodrome_integration = VelodromeIntegration() print(velodrome_integration.get_participants()) diff --git a/models/integration.py b/models/integration.py index a652fe0..0f57781 100644 --- a/models/integration.py +++ b/models/integration.py @@ -2,7 +2,7 @@ from typing import Dict, List, Optional, Set from constants.chains import Chain -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from constants.summary_columns import SummaryColumn diff --git a/utils/allstake.py b/utils/allstake.py index d3d75cc..a811830 100644 --- a/utils/allstake.py +++ b/utils/allstake.py @@ -6,7 +6,7 @@ from utils.web3_utils import call_with_retry import logging from constants.chains import Chain -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from constants.allstake import ALLSTAKE_STRATEGIES from models.integration import Integration from decimal import Decimal @@ -15,17 +15,28 @@ SHARES_OFFSET = 1000 BALANCE_OFFSET = 1000 -def get_underlying_balance(user: str, block: int, underlying: Contract, strategy: Contract): + +def get_underlying_balance( + user: str, block: int, underlying: Contract, strategy: Contract +): """ User's underlying token balance = underlying token balance of strategy contract * strategy.balanceOf(user) / strategy.totalSupply() """ - total_underlying_balance = call_with_retry(underlying.functions.balanceOf(strategy.address), block) + BALANCE_OFFSET - total_shares = call_with_retry(strategy.functions.totalSupply(), block) + SHARES_OFFSET + total_underlying_balance = ( + call_with_retry(underlying.functions.balanceOf(strategy.address), block) + + BALANCE_OFFSET + ) + total_shares = ( + call_with_retry(strategy.functions.totalSupply(), block) + SHARES_OFFSET + ) user_shares = call_with_retry(strategy.functions.balanceOf(user), block) return Decimal(user_shares * total_underlying_balance) / Decimal(total_shares) -def get_strategy_users(start_block: int, page_size: int, strategy: Contract, chain: Chain): + +def get_strategy_users( + start_block: int, page_size: int, strategy: Contract, chain: Chain +): """ Gets all participants that have ever interacted with the strategy by fetching all transfer events. """ @@ -79,7 +90,9 @@ def get_balance(self, user: str, block: int) -> float: ) def get_participants(self) -> list: - logging.info(f"[{self.integration_id.get_description()}] Getting participants...") + logging.info( + f"[{self.integration_id.get_description()}] Getting participants..." + ) self.participants = get_strategy_users( self.start_block, self.strategy_info["page_size"], diff --git a/utils/beefy.py b/utils/beefy.py index 0667f31..df4f61e 100644 --- a/utils/beefy.py +++ b/utils/beefy.py @@ -1,7 +1,7 @@ import requests from constants.chains import Chain from models.integration import Integration -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from constants.beefy import BEEFY_LRT_API_URL @@ -12,9 +12,10 @@ [Chain.OPTIMISM]: f"{BEEFY_LRT_API_URL}/api/v2/partner/ethena/optimism", } + class BeefyIntegration(Integration): def __init__( - self, + self, integration_id: IntegrationID, start_block: int, chain: Chain, @@ -41,7 +42,6 @@ def get_balance(self, user: str, block: int) -> float: data = response.json() return float(data["effective_balance"]) - def get_participants(self) -> list: """ @@ -52,8 +52,7 @@ def get_participants(self) -> list: url = f"{base_url}/users" response = requests.get(url) data = response.json() - + self.participants = data return data - diff --git a/utils/equilibria.py b/utils/equilibria.py index 85eafa3..32cc26d 100644 --- a/utils/equilibria.py +++ b/utils/equilibria.py @@ -1,5 +1,5 @@ from constants.chains import Chain -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from models.integration import Integration from constants.equilibria import PENDLE_LOCKER_ETHEREUM from constants.equilibria import equilibria_deposit_ethereum @@ -24,15 +24,15 @@ class EquilibriaIntegration(Integration): def __init__( - self, - integration_id: IntegrationID, - start_block: int, - lp_contract: str, - lp_contract_id: int, - chain: Chain, - reward_multiplier: int, - balance_multiplier: int, - excluded_addresses: List[str], + self, + integration_id: IntegrationID, + start_block: int, + lp_contract: str, + lp_contract_id: int, + chain: Chain, + reward_multiplier: int, + balance_multiplier: int, + excluded_addresses: List[str], ): super().__init__( integration_id, @@ -49,7 +49,9 @@ def __init__( self.lp_contract_id = lp_contract_id def get_balance(self, user: str, block: int) -> float: - equilibria_deposit_contract = w3.eth.contract(address=equilibria_deposit_ethereum, abi=equilibria_deposit) + equilibria_deposit_contract = w3.eth.contract( + address=equilibria_deposit_ethereum, abi=equilibria_deposit + ) # Get lpt token address from Stake DAO vault poolInfo = call_with_retry( @@ -99,9 +101,9 @@ def get_balance(self, user: str, block: int) -> float: print("total_active_supply is 0") return 0 - lockerSyBalance = round(((sy_bal / 10 ** 18) * lpt_bal) / total_active_supply, 4) - print(sy_bal / 10 ** 18) - print(lpt_bal / 10 ** 18) + lockerSyBalance = round(((sy_bal / 10**18) * lpt_bal) / total_active_supply, 4) + print(sy_bal / 10**18) + print(lpt_bal / 10**18) receipt_contract = w3.eth.contract(address=self.lp_contract, abi=erc20_abi) @@ -111,20 +113,20 @@ def get_balance(self, user: str, block: int) -> float: block, ) - print('equilibria_pool_TotalSupply', equilibria_pool_TotalSupply) + print("equilibria_pool_TotalSupply", equilibria_pool_TotalSupply) # Get gauge user balance user_equilibria_pool_bal = call_with_retry( receipt_contract.functions.balanceOf(user), block, ) - print('user_equilibria_pool_bal', user_equilibria_pool_bal) + print("user_equilibria_pool_bal", user_equilibria_pool_bal) # Get user share based on gauge#totalSupply / gauge#balanceOf(user) and lockerSyBalance userShare = user_equilibria_pool_bal * 100 / equilibria_pool_TotalSupply # print(user, userShare * lpt_bal / 100) - print('userShare lockerSyBalance:', userShare * lockerSyBalance / 100) - print('-------------------------------------------------') + print("userShare lockerSyBalance:", userShare * lockerSyBalance / 100) + print("-------------------------------------------------") return userShare * lockerSyBalance / 100 def get_participants(self) -> list: @@ -149,13 +151,18 @@ def get_equilibria_participants(self): start, to_block, ) - print('deposits', deposits) - print(start, to_block, len(deposits), "getting Equilibria Finance contract data") + print("deposits", deposits) + print( + start, + to_block, + len(deposits), + "getting Equilibria Finance contract data", + ) for deposit in deposits: - if (deposit["args"]["_user"]): + if deposit["args"]["_user"]: all_users.add(deposit["args"]["_user"]) print(deposit["args"]["_user"]) start += page_size - print('all_users', len(all_users)) - print('-------------------------------------------------') + print("all_users", len(all_users)) + print("-------------------------------------------------") return all_users diff --git a/utils/gmx.py b/utils/gmx.py index 596974a..bc4788c 100644 --- a/utils/gmx.py +++ b/utils/gmx.py @@ -1,12 +1,19 @@ import json import requests from constants.chains import Chain -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from models.integration import Integration from constants.summary_columns import SummaryColumn from utils.web3_utils import w3_arb, fetch_events_logs_with_retry, call_with_retry -from constants.gmx import GMX_SYNTHETICS_READER_CONTRACT_ADDRESS, GMX_WSTETH_USDE_MARKET_ADDRESS, GMX_DATA_STORE_CONTRACT_ADDRESS, GMX_USDE_USDC_MARKET_ADDRESS, GMX_MAX_PNL_FACTOR_FOR_TRADERS_KEY, GMX_PRICES_ENDPOINT +from constants.gmx import ( + GMX_SYNTHETICS_READER_CONTRACT_ADDRESS, + GMX_WSTETH_USDE_MARKET_ADDRESS, + GMX_DATA_STORE_CONTRACT_ADDRESS, + GMX_USDE_USDC_MARKET_ADDRESS, + GMX_MAX_PNL_FACTOR_FOR_TRADERS_KEY, + GMX_PRICES_ENDPOINT, +) with open("abi/gmx_gm_token.json") as f: gmx_gm_token_abi = json.load(f) @@ -23,15 +30,18 @@ ) gmx_synthetics_reader_contract = w3_arb.eth.contract( - address=GMX_SYNTHETICS_READER_CONTRACT_ADDRESS, abi=gmx_synthetics_reader_contract_abi + address=GMX_SYNTHETICS_READER_CONTRACT_ADDRESS, + abi=gmx_synthetics_reader_contract_abi, ) + def makePriceTuple(prices, token): return ( - int(prices[token]['minPrice']), - int(prices[token]['maxPrice']), + int(prices[token]["minPrice"]), + int(prices[token]["maxPrice"]), ) + def getContract(contract_address): if contract_address == GMX_USDE_USDC_MARKET_ADDRESS: return gmx_usde_usdc_market_contract @@ -40,6 +50,7 @@ def getContract(contract_address): else: return None + class GMXLPIntegration(Integration): prices = None market_address = None @@ -49,14 +60,14 @@ class GMXLPIntegration(Integration): short_token_address = None def __init__( - self, - integration_id: IntegrationID, - start_block: int, - market_address: str, - index_token_address: str, - long_token_address: str, - short_token_address: str, - ): + self, + integration_id: IntegrationID, + start_block: int, + market_address: str, + index_token_address: str, + long_token_address: str, + short_token_address: str, + ): super().__init__( integration_id, start_block, @@ -131,17 +142,19 @@ def get_participants(self) -> list: return all_users def fetchTokenPrices(self): - if (self.prices): + if self.prices: return self.prices response = requests.get(GMX_PRICES_ENDPOINT) if response.status_code == 200: pricesCollection = response.json() - pricesDict = { item['tokenAddress']: item for item in pricesCollection } + pricesDict = {item["tokenAddress"]: item for item in pricesCollection} self.prices = pricesDict return self.prices - print(f"GMX: failed to fetch token prices with status code {response.status_code}") + print( + f"GMX: failed to fetch token prices with status code {response.status_code}" + ) - return None \ No newline at end of file + return None diff --git a/utils/penpie.py b/utils/penpie.py index 687d917..fef2b5f 100644 --- a/utils/penpie.py +++ b/utils/penpie.py @@ -1,5 +1,5 @@ from constants.chains import Chain -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from models.integration import Integration from constants.penpie import PENDLE_LOCKER_ETHEREUM from constants.penpie import PENDLE_LOCKER_ARBITRUM @@ -25,7 +25,6 @@ penpie_tokens = json.load(f) - class PENPIEIntegration(Integration): def __init__( self, @@ -33,7 +32,7 @@ def __init__( start_block: int, lp_contract: str, chain: Chain, - reward_multiplier: int , + reward_multiplier: int, balance_multiplier: int, excluded_addresses: List[str], ): @@ -53,10 +52,14 @@ def __init__( def get_balance(self, user: str, block: int) -> float: # print(self.chain==Chain.ETHEREUM) - if(self.chain==Chain.ETHEREUM): - masterpenpiecontract = w3.eth.contract(address=master_penpie_ethereum, abi=master_penpie) - if(self.chain==Chain.ARBITRUM): - masterpenpiecontract = w3_arb.eth.contract(address=master_penpie_arbitrum, abi=master_penpie) + if self.chain == Chain.ETHEREUM: + masterpenpiecontract = w3.eth.contract( + address=master_penpie_ethereum, abi=master_penpie + ) + if self.chain == Chain.ARBITRUM: + masterpenpiecontract = w3_arb.eth.contract( + address=master_penpie_arbitrum, abi=master_penpie + ) # Get lpt token address from Stake DAO vault pendlePoolAddress = call_with_retry( @@ -64,9 +67,9 @@ def get_balance(self, user: str, block: int) -> float: block, ) # pendlePoolAddress = "0x107a2e3cD2BB9a32B9eE2E4d51143149F8367eBa" - if(self.chain==Chain.ETHEREUM): + if self.chain == Chain.ETHEREUM: lptContract = w3.eth.contract(address=pendlePoolAddress, abi=lpt_abi) - if(self.chain==Chain.ARBITRUM): + if self.chain == Chain.ARBITRUM: lptContract = w3_arb.eth.contract(address=pendlePoolAddress, abi=lpt_abi) print(pendlePoolAddress) # Get SY address @@ -76,9 +79,9 @@ def get_balance(self, user: str, block: int) -> float: ) sy = tokens[0] - if(self.chain==Chain.ETHEREUM): + if self.chain == Chain.ETHEREUM: sy_contract = w3.eth.contract(address=sy, abi=erc20_abi) - if(self.chain==Chain.ARBITRUM): + if self.chain == Chain.ARBITRUM: sy_contract = w3_arb.eth.contract(address=sy, abi=erc20_abi) # Get SY balance in the Pendle pool @@ -88,10 +91,10 @@ def get_balance(self, user: str, block: int) -> float: ) if sy_bal == 0: return 0 - if(self.chain==Chain.ETHEREUM): - PENDLE_LOCKER=PENDLE_LOCKER_ETHEREUM - if(self.chain==Chain.ARBITRUM): - PENDLE_LOCKER=PENDLE_LOCKER_ARBITRUM + if self.chain == Chain.ETHEREUM: + PENDLE_LOCKER = PENDLE_LOCKER_ETHEREUM + if self.chain == Chain.ARBITRUM: + PENDLE_LOCKER = PENDLE_LOCKER_ARBITRUM # Get Stake DAO lpt balance lpt_bal = call_with_retry( lptContract.functions.activeBalance(PENDLE_LOCKER), @@ -110,15 +113,15 @@ def get_balance(self, user: str, block: int) -> float: return 0 lockerSyBalance = round(((sy_bal / 10**18) * lpt_bal) / total_active_supply, 4) - print(sy_bal/10**18) - print(lpt_bal/10**18) + print(sy_bal / 10**18) + print(lpt_bal / 10**18) - - - if(self.chain==Chain.ETHEREUM): + if self.chain == Chain.ETHEREUM: receiptcontract = w3.eth.contract(address=self.lp_contract, abi=erc20_abi) - if(self.chain==Chain.ARBITRUM): - receiptcontract = w3_arb.eth.contract(address=self.lp_contract, abi=erc20_abi) + if self.chain == Chain.ARBITRUM: + receiptcontract = w3_arb.eth.contract( + address=self.lp_contract, abi=erc20_abi + ) # Get gauge total suply penpeiepoolTotalSupply = call_with_retry( @@ -153,14 +156,14 @@ def get_penpie_participants(self): all_users = set() start = self.start_block - if(self.chain==Chain.ETHEREUM): + if self.chain == Chain.ETHEREUM: contract = w3.eth.contract(address=self.lp_contract, abi=erc20_abi) - if(self.chain==Chain.ARBITRUM): + if self.chain == Chain.ARBITRUM: contract = w3_arb.eth.contract(address=self.lp_contract, abi=erc20_abi) page_size = 1900 - if(self.chain==Chain.ETHEREUM): + if self.chain == Chain.ETHEREUM: target_block = w3.eth.get_block_number() - if(self.chain==Chain.ARBITRUM): + if self.chain == Chain.ARBITRUM: target_block = w3_arb.eth.get_block_number() while start < target_block: to_block = min(start + page_size, target_block) @@ -172,7 +175,10 @@ def get_penpie_participants(self): ) # print(start, to_block, len(deposits), "getting Stake DAO contract data") for deposit in deposits: - if (deposit["args"]["to"]!="0x0000000000000000000000000000000000000000"): + if ( + deposit["args"]["to"] + != "0x0000000000000000000000000000000000000000" + ): all_users.add(deposit["args"]["to"]) print(deposit["args"]["to"]) start += page_size diff --git a/utils/rho_markets.py b/utils/rho_markets.py index 2b1796f..1b90fb4 100644 --- a/utils/rho_markets.py +++ b/utils/rho_markets.py @@ -1,8 +1,11 @@ from utils.web3_utils import call_with_retry -from constants.rho_markets import RHO_MARKETS_SCROLL_DEPLOYMENT_BLOCK, RHO_MARKETS_SCROLL_RUSDE_ADDRESS +from constants.rho_markets import ( + RHO_MARKETS_SCROLL_DEPLOYMENT_BLOCK, + RHO_MARKETS_SCROLL_RUSDE_ADDRESS, +) from models.integration import Integration from constants.summary_columns import SummaryColumn -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from constants.chains import Chain import json import requests @@ -34,14 +37,10 @@ def get_balance(self, user: str, block: int) -> float: r_usde_contract = w3_scroll.eth.contract( address=RHO_MARKETS_SCROLL_RUSDE_ADDRESS, abi=r_token_abi ) - balance = call_with_retry( - r_usde_contract.functions.balanceOf(user), - block - ) - + balance = call_with_retry(r_usde_contract.functions.balanceOf(user), block) + exchangeRate = call_with_retry( - r_usde_contract.functions.exchangeRateStored(), - block + r_usde_contract.functions.exchangeRateStored(), block ) return balance * exchangeRate / (1e18 * 1e18) @@ -50,7 +49,7 @@ def get_participants(self) -> list: try: users = self.fetch_compound_users("rUSDe") for user in users: - all_users.add(user['id']) + all_users.add(user["id"]) except Exception as e: print(e) all_users = list(all_users) @@ -76,22 +75,31 @@ def fetch_compound_users(self, asset_symbol): } } } - """ % (asset_symbol, last_id, asset_symbol) + """ % ( + asset_symbol, + last_id, + asset_symbol, + ) - response = requests.post(url, json={'query': query}) + response = requests.post(url, json={"query": query}) if response.status_code == 200: data = response.json() - accounts = data['data']['accounts'] + accounts = data["data"]["accounts"] if not accounts: break # 过滤掉0地址 - filtered_accounts = [account for account in accounts if account['id'] - != '0x0000000000000000000000000000000000000000'] + filtered_accounts = [ + account + for account in accounts + if account["id"] != "0x0000000000000000000000000000000000000000" + ] all_accounts.extend(filtered_accounts) - last_id = accounts[-1]['id'] + last_id = accounts[-1]["id"] else: - raise Exception(f"Query failed with status code { - response.status_code}: {response.text}") + raise Exception( + f"Query failed with status code { + response.status_code}: {response.text}" + ) return all_accounts diff --git a/utils/splice.py b/utils/splice.py index 93868cb..c3c404e 100644 --- a/utils/splice.py +++ b/utils/splice.py @@ -5,21 +5,21 @@ from web3.contract import Contract from functools import partial from constants.chains import Chain -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from models.integration import Integration from constants.splice import ( - USDE_SY, - USDE_YT, - USDE_LPT, - USDE_DEPLOYMENT_BLOCK, - SUSDE_SY, - SUSDE_YT, - SUSDE_LPT, - SUSDE_DEPLOYMENT_BLOCK, + USDE_SY, + USDE_YT, + USDE_LPT, + USDE_DEPLOYMENT_BLOCK, + SUSDE_SY, + SUSDE_YT, + SUSDE_LPT, + SUSDE_DEPLOYMENT_BLOCK, ) -w3 = W3_BY_CHAIN['mode']['w3'] +w3 = W3_BY_CHAIN["mode"]["w3"] ######################################################################## @@ -46,28 +46,36 @@ # Get Balance Functions ######################################################################## + def get_lpt_balance( - user: str, + user: str, block: int, - sy_contract: Contract, - lp_contract: Contract, + sy_contract: Contract, + lp_contract: Contract, ): - sy_bal = call_with_retry(sy_contract.functions.balanceOf(lp_contract.address), block) + sy_bal = call_with_retry( + sy_contract.functions.balanceOf(lp_contract.address), block + ) if sy_bal == 0: - return 0 + return 0 lpt_bal = call_with_retry(lp_contract.functions.activeBalance(user), block) if lpt_bal == 0: return 0 - total_active_supply = call_with_retry(lp_contract.functions.totalActiveSupply(), block) - + total_active_supply = call_with_retry( + lp_contract.functions.totalActiveSupply(), block + ) + if total_active_supply == 0: print("total_active_supply is 0") return 0 - print(f"sy_bal: {sy_bal}, lpt_bal: {lpt_bal}, total_active_supply: {total_active_supply}") + print( + f"sy_bal: {sy_bal}, lpt_bal: {lpt_bal}, total_active_supply: {total_active_supply}" + ) print(round(((sy_bal / 10**18) * lpt_bal) / total_active_supply, 4)) return round(((sy_bal / 10**18) * lpt_bal) / total_active_supply, 4) + def get_yt_balance(user: str, block: int, yt_contract: Contract) -> float: res = call_with_retry(yt_contract.functions.balanceOf(user), block) if not isinstance(res, (int, float)): @@ -79,6 +87,7 @@ def get_yt_balance(user: str, block: int, yt_contract: Contract) -> float: # Get Participants Functions ######################################################################## + def get_splice_participants_v3(token_addresses, start: int): page_size = 1900 all_users = set() @@ -86,8 +95,8 @@ def get_splice_participants_v3(token_addresses, start: int): for i in range(len(token_addresses)): token = token_addresses[i] - contract = w3.eth.contract(address=token, abi=erc20_abi) - + contract = w3.eth.contract(address=token, abi=erc20_abi) + while start < target_block: to_block = min(start + page_size, target_block) transfers = fetch_events_logs_with_retry( @@ -108,37 +117,43 @@ def get_splice_participants_v3(token_addresses, start: int): ######################################################################## config = { - IntegrationID.SPLICE_USDE_YT: { - 'chain': Chain.MODE, - 'start_block': USDE_DEPLOYMENT_BLOCK, - 'end_block': None, - 'sats_multiplier': 20, - 'token_addresses': [usde_yt_contract.address], - 'get_balance_func': partial(get_yt_balance, yt_contract=usde_yt_contract), - }, - IntegrationID.SPLICE_USDE_LPT: { - 'chain': Chain.MODE, - 'start_block': USDE_DEPLOYMENT_BLOCK, - 'end_block': None, - 'sats_multiplier': 20, - 'token_addresses': [usde_sy_contract.address, usde_lpt_contract.address], - 'get_balance_func': partial(get_lpt_balance, sy_contract=usde_sy_contract, lp_contract=usde_lpt_contract), - }, + IntegrationID.SPLICE_USDE_YT: { + "chain": Chain.MODE, + "start_block": USDE_DEPLOYMENT_BLOCK, + "end_block": None, + "sats_multiplier": 20, + "token_addresses": [usde_yt_contract.address], + "get_balance_func": partial(get_yt_balance, yt_contract=usde_yt_contract), + }, + IntegrationID.SPLICE_USDE_LPT: { + "chain": Chain.MODE, + "start_block": USDE_DEPLOYMENT_BLOCK, + "end_block": None, + "sats_multiplier": 20, + "token_addresses": [usde_sy_contract.address, usde_lpt_contract.address], + "get_balance_func": partial( + get_lpt_balance, sy_contract=usde_sy_contract, lp_contract=usde_lpt_contract + ), + }, IntegrationID.SPLICE_SUSDE_YT: { - 'chain': Chain.MODE, - 'start_block': SUSDE_DEPLOYMENT_BLOCK, - 'end_block': None, - 'sats_multiplier': 20, - 'token_addresses': [susde_yt_contract.address], - 'get_balance_func': partial(get_yt_balance, yt_contract=susde_yt_contract), + "chain": Chain.MODE, + "start_block": SUSDE_DEPLOYMENT_BLOCK, + "end_block": None, + "sats_multiplier": 20, + "token_addresses": [susde_yt_contract.address], + "get_balance_func": partial(get_yt_balance, yt_contract=susde_yt_contract), }, IntegrationID.SPLICE_SUSDE_LPT: { - 'chain': Chain.MODE, - 'start_block': SUSDE_DEPLOYMENT_BLOCK, - 'end_block': None, - 'sats_multiplier': 20, - 'token_addresses': [susde_sy_contract.address, susde_lpt_contract.address], - 'get_balance_func': partial(get_lpt_balance, sy_contract=susde_sy_contract, lp_contract=susde_lpt_contract), + "chain": Chain.MODE, + "start_block": SUSDE_DEPLOYMENT_BLOCK, + "end_block": None, + "sats_multiplier": 20, + "token_addresses": [susde_sy_contract.address, susde_lpt_contract.address], + "get_balance_func": partial( + get_lpt_balance, + sy_contract=susde_sy_contract, + lp_contract=susde_lpt_contract, + ), }, } @@ -147,32 +162,39 @@ def get_splice_participants_v3(token_addresses, start: int): # Integration Class ######################################################################## -class SpliceIntegration(Integration): + +class SpliceIntegration(Integration): def __init__(self, integration_id: IntegrationID): super().__init__( - integration_id, - config[integration_id]['start_block'], - config[integration_id]['chain'], - None, # SummaryColumn - config[integration_id]['sats_multiplier'], # SATS multiplier - 1, - config[integration_id]['end_block'], - None, # reward multiplier fn + integration_id, + config[integration_id]["start_block"], + config[integration_id]["chain"], + None, # SummaryColumn + config[integration_id]["sats_multiplier"], # SATS multiplier + 1, + config[integration_id]["end_block"], + None, # reward multiplier fn ) - self.token_addresses = config[integration_id]['token_addresses'] - self.get_balance_func = config[integration_id]['get_balance_func'] + self.token_addresses = config[integration_id]["token_addresses"] + self.get_balance_func = config[integration_id]["get_balance_func"] def get_description(self): return self.integration_id.get_description() def get_balance(self, user: str, block: int) -> float: - logging.info(f"[{self.get_description()}] Getting balance for {user} at block {block}") + logging.info( + f"[{self.get_description()}] Getting balance for {user} at block {block}" + ) return self.get_balance_func(user, block) def get_participants(self) -> list: if self.participants is not None: return self.participants logging.info(f"[{self.get_description()}] Getting participants...") - self.participants = get_splice_participants_v3(self.token_addresses, self.start_block) - logging.info(f"[{self.get_description()}] Found {len(self.participants)} participants") + self.participants = get_splice_participants_v3( + self.token_addresses, self.start_block + ) + logging.info( + f"[{self.get_description()}] Found {len(self.participants)} participants" + ) return self.participants diff --git a/utils/stakedao.py b/utils/stakedao.py index 14c9339..3221e2b 100644 --- a/utils/stakedao.py +++ b/utils/stakedao.py @@ -1,5 +1,5 @@ from constants.chains import Chain -from constants.integration_ids import IntegrationID +from integrations.integration_ids import IntegrationID from models.integration import Integration from constants.stakedao import PENDLE_LOCKER import logging From b573ef81731942f4f46165aadd377da5844fbc74 Mon Sep 17 00:00:00 2001 From: FJ-Riveros Date: Tue, 19 Nov 2024 09:37:19 +0100 Subject: [PATCH 03/16] chore: bump requests package --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index bcbcd3c..b1d75fb 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ DateTime~=4.9 web3~=6.19.0 python-dotenv~=1.0.0 -requests~=2.31.0 +requests~=2.32.0 tqdm~=4.66.4 rich==13.7.1 From 7154677c8bf09175fce17dc10cf3f68d99b4fb14 Mon Sep 17 00:00:00 2001 From: FJ-Riveros Date: Tue, 19 Nov 2024 10:01:25 +0100 Subject: [PATCH 04/16] chore: move the models into integrations to copy the original repo structure --- integrations/cached_balances_integration.py | 37 +++++++++++++++++++++ {models => integrations}/integration.py | 4 +++ 2 files changed, 41 insertions(+) create mode 100644 integrations/cached_balances_integration.py rename {models => integrations}/integration.py (88%) diff --git a/integrations/cached_balances_integration.py b/integrations/cached_balances_integration.py new file mode 100644 index 0000000..a3fc1c3 --- /dev/null +++ b/integrations/cached_balances_integration.py @@ -0,0 +1,37 @@ +from typing import Callable, Dict, List, Optional, Set +from eth_typing import ChecksumAddress +from constants.summary_columns import SummaryColumn +from constants.chains import Chain +from integrations.integration import Integration +from integrations.integration_ids import IntegrationID as IntID + + +class CachedBalancesIntegration(Integration): + def __init__( + self, + integration_id: IntID, + start_block: int, + chain: Chain = Chain.ETHEREUM, + summary_cols: Optional[List[SummaryColumn]] = None, + reward_multiplier: int = 1, + balance_multiplier: int = 1, + excluded_addresses: Optional[Set[ChecksumAddress]] = None, + end_block: Optional[int] = None, + ethereal_multiplier: int = 0, + ethereal_multiplier_func: Optional[Callable[[int, str], int]] = None, + ): + super().__init__( + integration_id=integration_id, + start_block=start_block, + chain=chain, + summary_cols=summary_cols, + reward_multiplier=reward_multiplier, + balance_multiplier=balance_multiplier, + excluded_addresses=excluded_addresses, + end_block=end_block, + ethereal_multiplier=ethereal_multiplier, + ethereal_multiplier_func=ethereal_multiplier_func, + ) + + def get_block_balances(self, blocks: List[int]) -> Dict[int, Dict[str, float]]: + raise NotImplementedError diff --git a/models/integration.py b/integrations/integration.py similarity index 88% rename from models/integration.py rename to integrations/integration.py index 0f57781..81ff5ab 100644 --- a/models/integration.py +++ b/integrations/integration.py @@ -19,6 +19,8 @@ def __init__( excluded_addresses: List[str] = None, end_block: int = None, reward_multiplier_func=None, + ethereal_multiplier: int = 0, + ethereal_multiplier_func=None, ): self.integration_id = integration_id self.start_block = start_block @@ -30,6 +32,8 @@ def __init__( self.balance_multiplier = balance_multiplier self.excluded_addresses = excluded_addresses self.reward_multiplier_func = reward_multiplier_func + self.ethereal_multiplier = ethereal_multiplier + self.ethereal_multiplier_func = ethereal_multiplier_func @abstractmethod def get_balance(self, user: str, block: int) -> float: From ee97672472bed2b9c79e4723133bf0df51d7489d Mon Sep 17 00:00:00 2001 From: FJ-Riveros Date: Tue, 19 Nov 2024 10:01:41 +0100 Subject: [PATCH 05/16] chore: update imports --- integrations/ambient_scroll.py | 2 +- integrations/balancer_integration.py | 2 +- integrations/euler_susde.py | 2 +- integrations/euler_usde.py | 2 +- integrations/firm_susde.py | 2 +- integrations/fluid_susde.py | 2 +- integrations/fluid_usde.py | 2 +- integrations/fluid_usde_t4.py | 2 +- integrations/gmx_usde_poitions_aug.py | 2 +- integrations/hyperdrive.py | 2 +- integrations/lendle_usde.py | 2 +- integrations/lyra_susde_bull.py | 2 +- integrations/merchantmoe_lbt_integration.py | 2 +- integrations/nuri.py | 2 +- integrations/pendle_lpt_integration.py | 2 +- integrations/pendle_yt_integration.py | 2 +- integrations/radiant_usde.py | 2 +- integrations/ramses.py | 2 +- integrations/synthetix.py | 2 +- integrations/template.py | 2 +- integrations/term_susde.py | 2 +- integrations/velodrome_mode_susde.py | 2 +- integrations/velodrome_mode_usde.py | 2 +- utils/allstake.py | 2 +- utils/beefy.py | 2 +- utils/curve.py | 38 ++++++++++----------- utils/equilibria.py | 2 +- utils/gmx.py | 2 +- utils/penpie.py | 2 +- utils/rho_markets.py | 2 +- utils/splice.py | 2 +- utils/stakedao.py | 2 +- utils/web3_utils.py | 19 ++++++----- 33 files changed, 61 insertions(+), 58 deletions(-) diff --git a/integrations/ambient_scroll.py b/integrations/ambient_scroll.py index 80340de..2ea5dcc 100644 --- a/integrations/ambient_scroll.py +++ b/integrations/ambient_scroll.py @@ -1,7 +1,7 @@ import requests from constants.chains import Chain from integrations.integration_ids import IntegrationID -from models.integration import Integration +from integrations.integration import Integration from constants.summary_columns import SummaryColumn from constants.ambient import AMBIENT_SCROLL_DEPLOYMENT_BLOCK, AMBIENT_SCROLL_API_URL diff --git a/integrations/balancer_integration.py b/integrations/balancer_integration.py index 52ded41..681b602 100644 --- a/integrations/balancer_integration.py +++ b/integrations/balancer_integration.py @@ -1,5 +1,5 @@ from integrations.integration_ids import IntegrationID -from models.integration import Integration +from integrations.integration import Integration from utils.balancer import ( get_vault_pool_token_balance, get_potential_token_holders, diff --git a/integrations/euler_susde.py b/integrations/euler_susde.py index b68536c..a38b3f8 100644 --- a/integrations/euler_susde.py +++ b/integrations/euler_susde.py @@ -3,7 +3,7 @@ from integrations.integration_ids import IntegrationID from constants.euler import SUSDE_VAULT_ADDRESS from constants.merchantmoe import DEAD_ADDRESS, ZERO_ADDRESS -from models.integration import Integration +from integrations.integration import Integration from utils.web3_utils import ( fetch_events_logs_with_retry, call_with_retry, diff --git a/integrations/euler_usde.py b/integrations/euler_usde.py index cf55c91..bffcc58 100644 --- a/integrations/euler_usde.py +++ b/integrations/euler_usde.py @@ -2,7 +2,7 @@ from constants.chains import Chain from integrations.integration_ids import IntegrationID from constants.euler import USDE_VAULT_ADDRESS -from models.integration import Integration +from integrations.integration import Integration from utils.web3_utils import ( fetch_events_logs_with_retry, call_with_retry, diff --git a/integrations/firm_susde.py b/integrations/firm_susde.py index a2f05be..20f0223 100644 --- a/integrations/firm_susde.py +++ b/integrations/firm_susde.py @@ -1,6 +1,6 @@ from constants.chains import Chain from integrations.integration_ids import IntegrationID -from models.integration import Integration +from integrations.integration import Integration from constants.firm import FIRM_SUSDE_DEPLOYMENT_BLOCK from utils.firm import get_escrow_contract, firm_susde_market_contract from utils.web3_utils import w3, fetch_events_logs_with_retry, call_with_retry diff --git a/integrations/fluid_susde.py b/integrations/fluid_susde.py index 8b49779..93a9151 100644 --- a/integrations/fluid_susde.py +++ b/integrations/fluid_susde.py @@ -1,6 +1,6 @@ from constants.chains import Chain from integrations.integration_ids import IntegrationID -from models.integration import Integration +from integrations.integration import Integration from utils.web3_utils import call_with_retry, W3_BY_CHAIN from utils.fluid import vaultResolver_contract, vaultPositionResolver_contract from constants.fluid import sUSDe diff --git a/integrations/fluid_usde.py b/integrations/fluid_usde.py index a52d292..b15aee5 100644 --- a/integrations/fluid_usde.py +++ b/integrations/fluid_usde.py @@ -1,6 +1,6 @@ from constants.chains import Chain from integrations.integration_ids import IntegrationID -from models.integration import Integration +from integrations.integration import Integration from utils.web3_utils import call_with_retry, W3_BY_CHAIN from utils.fluid import vaultResolver_contract, vaultPositionResolver_contract from constants.fluid import USDe diff --git a/integrations/fluid_usde_t4.py b/integrations/fluid_usde_t4.py index 93db0de..1d23d8d 100644 --- a/integrations/fluid_usde_t4.py +++ b/integrations/fluid_usde_t4.py @@ -1,6 +1,6 @@ from constants.chains import Chain from integrations.integration_ids import IntegrationID -from models.integration import Integration +from integrations.integration import Integration from utils.web3_utils import call_with_retry, W3_BY_CHAIN from utils.fluid import ( vaultResolver_contract, diff --git a/integrations/gmx_usde_poitions_aug.py b/integrations/gmx_usde_poitions_aug.py index 09e8eee..099a8e9 100644 --- a/integrations/gmx_usde_poitions_aug.py +++ b/integrations/gmx_usde_poitions_aug.py @@ -10,7 +10,7 @@ ) from utils.gmx import gmx_synthetics_reader_contract from constants.summary_columns import SummaryColumn -from models.integration import Integration +from integrations.integration import Integration from utils.web3_utils import call_with_retry diff --git a/integrations/hyperdrive.py b/integrations/hyperdrive.py index cbf6a54..dd77e8c 100644 --- a/integrations/hyperdrive.py +++ b/integrations/hyperdrive.py @@ -1,6 +1,6 @@ from decimal import Decimal from constants.chains import Chain -from models.integration import Integration +from integrations.integration import Integration from integrations.integration_ids import IntegrationID from constants.hyperdrive import ( HYPERDRIVE_SUSDE_POOL_ADDRESS, diff --git a/integrations/lendle_usde.py b/integrations/lendle_usde.py index 6688f9d..3e42d18 100644 --- a/integrations/lendle_usde.py +++ b/integrations/lendle_usde.py @@ -1,6 +1,6 @@ from constants.chains import Chain from integrations.integration_ids import IntegrationID -from models.integration import Integration +from integrations.integration import Integration from constants.summary_columns import SummaryColumn from constants.lendle import LENDLE_USDE_DEPLOYMENT_BLOCK from utils.web3_utils import w3_mantle, fetch_events_logs_with_retry, call_with_retry diff --git a/integrations/lyra_susde_bull.py b/integrations/lyra_susde_bull.py index 4f5867e..f30ecf0 100644 --- a/integrations/lyra_susde_bull.py +++ b/integrations/lyra_susde_bull.py @@ -2,7 +2,7 @@ import logging from integrations.integration_ids import IntegrationID -from models.integration import Integration +from integrations.integration import Integration from utils.lyra import ( get_vault_users, get_effective_balance, diff --git a/integrations/merchantmoe_lbt_integration.py b/integrations/merchantmoe_lbt_integration.py index d854234..f74b6ac 100644 --- a/integrations/merchantmoe_lbt_integration.py +++ b/integrations/merchantmoe_lbt_integration.py @@ -10,7 +10,7 @@ METH_USDE_MERCHANT_MOE_LBT_DEPLOYMENT_BLOCK, METH_USDE_MERCHANT_MOE_LBT_CONTRACT, ) -from models.integration import Integration +from integrations.integration import Integration from utils.merchantmoe import lb_pair_contract, liquidity_helper_contract from utils.web3_utils import W3_BY_CHAIN, fetch_events_logs_with_retry, call_with_retry diff --git a/integrations/nuri.py b/integrations/nuri.py index 3d89396..28d2f8d 100644 --- a/integrations/nuri.py +++ b/integrations/nuri.py @@ -1,6 +1,6 @@ from constants.chains import Chain from integrations.integration_ids import IntegrationID -from models.integration import Integration +from integrations.integration import Integration from constants.nuri import ( NURI_NFP_MANAGER_ADDRESS, NURI_POOL_ADDRESS, diff --git a/integrations/pendle_lpt_integration.py b/integrations/pendle_lpt_integration.py index a7ec5fb..c471ab7 100644 --- a/integrations/pendle_lpt_integration.py +++ b/integrations/pendle_lpt_integration.py @@ -6,7 +6,7 @@ from constants.chains import Chain from constants.pendle import PENDLE_USDE_JULY_DEPLOYMENT_BLOCK -from models.integration import Integration +from integrations.integration import Integration from utils import pendle from integrations.integration_ids import IntegrationID from constants.summary_columns import SummaryColumn diff --git a/integrations/pendle_yt_integration.py b/integrations/pendle_yt_integration.py index 7eae671..bfbd584 100644 --- a/integrations/pendle_yt_integration.py +++ b/integrations/pendle_yt_integration.py @@ -5,7 +5,7 @@ from web3.contract import Contract from constants.chains import Chain -from models.integration import Integration +from integrations.integration import Integration from integrations.integration_ids import IntegrationID from constants.summary_columns import SummaryColumn from utils.pendle import get_pendle_participants_v3 diff --git a/integrations/radiant_usde.py b/integrations/radiant_usde.py index 44727de..98cd2a6 100644 --- a/integrations/radiant_usde.py +++ b/integrations/radiant_usde.py @@ -2,7 +2,7 @@ import logging from integrations.integration_ids import IntegrationID -from models.integration import Integration +from integrations.integration import Integration from utils.radiant import get_radiant_lenders, get_effective_balance from constants.radiant import ( RADIANT_CONTRACTS_AND_START_BY_TOKEN, diff --git a/integrations/ramses.py b/integrations/ramses.py index 13056aa..636bfc3 100644 --- a/integrations/ramses.py +++ b/integrations/ramses.py @@ -1,6 +1,6 @@ from constants.chains import Chain from integrations.integration_ids import IntegrationID -from models.integration import Integration +from integrations.integration import Integration from constants.ramses import ( RAMSES_DEPLOYMENT_BLOCK, RAMSES_NFP_MANAGER_ADDRESS, diff --git a/integrations/synthetix.py b/integrations/synthetix.py index c1f860c..64eeaea 100644 --- a/integrations/synthetix.py +++ b/integrations/synthetix.py @@ -1,6 +1,6 @@ from constants.chains import Chain from integrations.integration_ids import IntegrationID -from models.integration import Integration +from integrations.integration import Integration from constants.synthetix import SYNTHETIX_ARB_DEPLOYMENT_BLOCK, ARB_USDE_TOKEN_ADDRESS from constants.summary_columns import SummaryColumn from utils.synthetix import core_proxy_contract, core_account_proxy_contract diff --git a/integrations/template.py b/integrations/template.py index 430910a..a990900 100644 --- a/integrations/template.py +++ b/integrations/template.py @@ -1,6 +1,6 @@ from constants.chains import Chain from integrations.integration_ids import IntegrationID -from models.integration import Integration +from integrations.integration import Integration class ProtocolNameIntegration( diff --git a/integrations/term_susde.py b/integrations/term_susde.py index 58bb1a1..feabf3d 100644 --- a/integrations/term_susde.py +++ b/integrations/term_susde.py @@ -4,7 +4,7 @@ from integrations.integration_ids import IntegrationID from constants.integration_token import Token from constants.summary_columns import SummaryColumn -from models.integration import Integration +from integrations.integration import Integration ############################################################################### diff --git a/integrations/velodrome_mode_susde.py b/integrations/velodrome_mode_susde.py index 659f16d..eec4ccc 100644 --- a/integrations/velodrome_mode_susde.py +++ b/integrations/velodrome_mode_susde.py @@ -1,6 +1,6 @@ from constants.chains import Chain from integrations.integration_ids import IntegrationID -from models.integration import Integration +from integrations.integration import Integration from constants.velodrome import VELODROME_MODE_START_BLOCK, SUSDE_MODE_TOKEN from utils.velodrome import fetch_balance, fetch_participants diff --git a/integrations/velodrome_mode_usde.py b/integrations/velodrome_mode_usde.py index e42037a..94a4ff7 100644 --- a/integrations/velodrome_mode_usde.py +++ b/integrations/velodrome_mode_usde.py @@ -1,6 +1,6 @@ from constants.chains import Chain from integrations.integration_ids import IntegrationID -from models.integration import Integration +from integrations.integration import Integration from constants.velodrome import VELODROME_MODE_START_BLOCK, USDE_MODE_TOKEN from utils.velodrome import fetch_balance, fetch_participants diff --git a/utils/allstake.py b/utils/allstake.py index a811830..a934d47 100644 --- a/utils/allstake.py +++ b/utils/allstake.py @@ -8,7 +8,7 @@ from constants.chains import Chain from integrations.integration_ids import IntegrationID from constants.allstake import ALLSTAKE_STRATEGIES -from models.integration import Integration +from integrations.integration import Integration from decimal import Decimal diff --git a/utils/beefy.py b/utils/beefy.py index df4f61e..10f856d 100644 --- a/utils/beefy.py +++ b/utils/beefy.py @@ -1,6 +1,6 @@ import requests from constants.chains import Chain -from models.integration import Integration +from integrations.integration import Integration from integrations.integration_ids import IntegrationID from constants.beefy import BEEFY_LRT_API_URL diff --git a/utils/curve.py b/utils/curve.py index 6831fe5..f4ee0df 100644 --- a/utils/curve.py +++ b/utils/curve.py @@ -5,25 +5,26 @@ from constants.summary_columns import SummaryColumn from constants.curve import RewardContractConfig -from models.integration import Integration +from integrations.integration import Integration from utils.web3_utils import ( - W3_BY_CHAIN, - fetch_events_logs_with_retry, + W3_BY_CHAIN, + fetch_events_logs_with_retry, call_with_retry, multicall, ) + @dataclass(frozen=True) class UserState: address: str state: tuple block: int - + def __init__(self, address: str, state: list, block: int): - object.__setattr__(self, 'address', address) - object.__setattr__(self, 'state', tuple(state)) - object.__setattr__(self, 'block', block) + object.__setattr__(self, "address", address) + object.__setattr__(self, "state", tuple(state)) + object.__setattr__(self, "block", block) def __hash__(self): return hash((self.address, self.state, self.block)) @@ -31,11 +32,11 @@ def __hash__(self): class Curve(Integration): """ - Base class for Curve integrations. + Base class for Curve integrations. """ def __init__( - self, + self, reward_config: RewardContractConfig, ): """ @@ -44,27 +45,26 @@ def __init__( Args: reward_config (RewardContractConfig): The configuration for the reward contract. """ - + super().__init__( integration_id=reward_config.integration_id, start_block=reward_config.genesis_block, chain=reward_config.chain, summary_cols=SummaryColumn.CURVE_LLAMALEND_SHARDS, ) - + self.w3 = W3_BY_CHAIN[self.chain]["w3"] self.reward_config = reward_config with open(self.reward_config.abi_filename, "r") as f: abi = json.load(f) self.contract = self.w3.eth.contract( - address=self.reward_config.address, - abi=abi + address=self.reward_config.address, abi=abi ) self.contract_function = self.contract.functions.user_state self.contract_event = self.contract.events.Borrow() self.start_state: List[UserState] = [] self.last_indexed_block: int = 0 - + def get_balance(self, user: str, block: int) -> float: """ Retrieve the collateral balance for a user at a specific block. @@ -77,7 +77,7 @@ def get_balance(self, user: str, block: int) -> float: float: The user's collateral balance in wei. """ return self.get_user_state(user, block)[self.reward_config.state_arg_no] - + def get_user_states(self, block: int) -> list: """ Retrieve user states for all participants at a specific block. @@ -103,12 +103,12 @@ def get_user_states(self, block: int) -> list: UserState( address=user_info.address, state=result[self.reward_config.state_arg_no], - block=block + block=block, ) ) return states - + def get_user_state(self, user: str, block: int) -> float: """ Retrieve the collateral balance for a user at a specific block. @@ -124,7 +124,7 @@ def get_user_state(self, user: str, block: int) -> float: self.contract_function(user), block, ) - + def get_current_block(self) -> int: return self.w3.eth.get_block_number() @@ -167,5 +167,5 @@ def get_participants(self) -> list: self.start_state.extend(all_users) self.last_indexed_block = current_block - + return [user_info.address for user_info in self.start_state] diff --git a/utils/equilibria.py b/utils/equilibria.py index 32cc26d..f2b1920 100644 --- a/utils/equilibria.py +++ b/utils/equilibria.py @@ -1,6 +1,6 @@ from constants.chains import Chain from integrations.integration_ids import IntegrationID -from models.integration import Integration +from integrations.integration import Integration from constants.equilibria import PENDLE_LOCKER_ETHEREUM from constants.equilibria import equilibria_deposit_ethereum import json diff --git a/utils/gmx.py b/utils/gmx.py index bc4788c..dd1ced1 100644 --- a/utils/gmx.py +++ b/utils/gmx.py @@ -2,7 +2,7 @@ import requests from constants.chains import Chain from integrations.integration_ids import IntegrationID -from models.integration import Integration +from integrations.integration import Integration from constants.summary_columns import SummaryColumn from utils.web3_utils import w3_arb, fetch_events_logs_with_retry, call_with_retry diff --git a/utils/penpie.py b/utils/penpie.py index fef2b5f..978a0bb 100644 --- a/utils/penpie.py +++ b/utils/penpie.py @@ -1,6 +1,6 @@ from constants.chains import Chain from integrations.integration_ids import IntegrationID -from models.integration import Integration +from integrations.integration import Integration from constants.penpie import PENDLE_LOCKER_ETHEREUM from constants.penpie import PENDLE_LOCKER_ARBITRUM from constants.penpie import master_penpie_ethereum diff --git a/utils/rho_markets.py b/utils/rho_markets.py index 1b90fb4..f2c3f34 100644 --- a/utils/rho_markets.py +++ b/utils/rho_markets.py @@ -3,7 +3,7 @@ RHO_MARKETS_SCROLL_DEPLOYMENT_BLOCK, RHO_MARKETS_SCROLL_RUSDE_ADDRESS, ) -from models.integration import Integration +from integrations.integration import Integration from constants.summary_columns import SummaryColumn from integrations.integration_ids import IntegrationID from constants.chains import Chain diff --git a/utils/splice.py b/utils/splice.py index c3c404e..f57a94d 100644 --- a/utils/splice.py +++ b/utils/splice.py @@ -6,7 +6,7 @@ from functools import partial from constants.chains import Chain from integrations.integration_ids import IntegrationID -from models.integration import Integration +from integrations.integration import Integration from constants.splice import ( USDE_SY, diff --git a/utils/stakedao.py b/utils/stakedao.py index 3221e2b..76bfcaf 100644 --- a/utils/stakedao.py +++ b/utils/stakedao.py @@ -1,6 +1,6 @@ from constants.chains import Chain from integrations.integration_ids import IntegrationID -from models.integration import Integration +from integrations.integration import Integration from constants.stakedao import PENDLE_LOCKER import logging import json diff --git a/utils/web3_utils.py b/utils/web3_utils.py index f7cc40f..94f1ccd 100644 --- a/utils/web3_utils.py +++ b/utils/web3_utils.py @@ -7,7 +7,6 @@ from eth_abi.abi import decode from web3 import Web3 -from web3.contract import Contract from utils.slack import slack_message from constants.chains import Chain @@ -81,7 +80,9 @@ } ] -MULTICALL_ADDRESS = "0x5BA1e12693Dc8F9c48aAD8770482f4739bEeD696" # Ethereum mainnet address +MULTICALL_ADDRESS = ( + "0x5BA1e12693Dc8F9c48aAD8770482f4739bEeD696" # Ethereum mainnet address +) def fetch_events_logs_with_retry( @@ -125,22 +126,24 @@ def call_with_retry(contract_function, block="latest", retries=3, delay=2): raise e -def multicall(w3: Web3, calls: list, block_identifier: int = 'latest'): +def multicall(w3: Web3, calls: list, block_identifier: int = "latest"): multicall_contract = w3.eth.contract(address=MULTICALL_ADDRESS, abi=MULTICALL_ABI) - + aggregate_calls = [] for call in calls: contract, fn_name, args = call call_data = contract.encodeABI(fn_name=fn_name, args=args) aggregate_calls.append((contract.address, call_data)) - result = multicall_contract.functions.aggregate(aggregate_calls).call(block_identifier=block_identifier) - + result = multicall_contract.functions.aggregate(aggregate_calls).call( + block_identifier=block_identifier + ) + decoded_results = [] for i, call in enumerate(calls): contract, fn_name, _ = call function = contract.get_function_by_name(fn_name) - output_types = [output['type'] for output in function.abi['outputs']] + output_types = [output["type"] for output in function.abi["outputs"]] decoded_results.append(decode(output_types, result[1][i])) - return decoded_results \ No newline at end of file + return decoded_results From 885eb3ac7c7dd0a9036cd049db76ab0806a79241 Mon Sep 17 00:00:00 2001 From: FJ-Riveros Date: Tue, 19 Nov 2024 12:52:35 +0100 Subject: [PATCH 06/16] feat: update readme, template & add campaign --- README.md | 22 ++++++------- campaign/campaign.py | 64 ++++++++++++++++++++++++++++++++++++ constants/summary_columns.py | 48 +++++++++++++++++++-------- integrations/template.py | 64 ++++++++++++++++++++++-------------- 4 files changed, 149 insertions(+), 49 deletions(-) create mode 100644 campaign/campaign.py diff --git a/README.md b/README.md index 12edebd..1a34e36 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,24 @@ # Overview -This repo offers a self service approach to Ethena Sats Campaign integrations. +This repo offers a self service approach to Ethena Points Campaign integrations. # Instructions -For your protocol to be included and your users to receive sats, you should submit a PR to this repo. Here some guidelines to follow: +For your protocol to be included and your users to receive points, you should submit a PR to this repo. Here some guidelines to follow: 1. Make a copy of `.env.example` and name it `.env`. 2. Run `pip install -r requirements.txt` to install the required packages. -3. Add your integration metadata to `constants/integration_ids.py`. -4. Make a copy of `integrations/template.py`, naming the file `[protocol name].py` and place in the `integrations` directory. -5. Your integration must be a class that inherits from `Integration` and implements the `get_balance` and `get_participants` methods. -6. The `get_balance` method should return the balance of a given user at a given block. -7. The `get_participants` method should return a list of all users that have interacted with the protocol. -8. Write some basic tests at the bottom of the file to ensure your integration is working correctly. -9. Submit a PR to this repo with your integration and ping the Ethena team in Telegram. +3. Add your integration metadata to `integrations/integration_ids.py`. +4. Add your integration metadata to `constants/summary_columns.py`. +5. Make a copy of `integrations/template.py`, naming the file `[protocol name]_integration.py` and place in the `integrations` directory. +6. Your integration must be a class that inherits from `CachedBalancesIntegration` and implements the `get_block_balances` method. +6. The `get_block_balances` method should return a dict of block numbers to a dict of user addresses to balances at that block. +7. Write some basic tests at the bottom of the file to ensure your integration is working correctly. +8. Submit a PR to this repo with your integration and ping the Ethena team in Telegram. # Guidelines - Integrations must follow this architecture and be written in python. - Pendle integrations are included as examples of functioning integrations. Run `python -m integrations.pendle_lpt_integration` to see the output. -- The `get_balance` and `get_participants` methods should be as efficient as possible. -- We prefer that on chain RPC calls are used to get information as much as possible due to reliability and trustlessness. For example one could cycle through events for `get_participants` and read from a smart contract for `get_balance`. Off chain calls to apis or subgraphs are acceptable if necessary. If usage is not reasonable or the external service is not reliable, users may not receive their sats. +- The `get_block_balances` method should be as efficient as possible. +- We prefer that on chain RPC calls are used to get information as much as possible due to reliability and trustlessness. Off chain calls to apis or subgraphs are acceptable if necessary. If usage is not reasonable or the external service is not reliable, users may not receive their sats. diff --git a/campaign/campaign.py b/campaign/campaign.py new file mode 100644 index 0000000..652fca0 --- /dev/null +++ b/campaign/campaign.py @@ -0,0 +1,64 @@ +from typing import List +from web3 import Web3 + +from constants.chains import Chain +from constants.pendle import PENDLE_USDE_JULY_DEPLOYMENT_BLOCK +from constants.summary_columns import SummaryColumn +from integrations.integration import Integration +from integrations.integration_ids import IntegrationID +from integrations.pendle_lpt_integration import PendleLPTIntegration +from integrations.pendle_yt_integration import PendleYTIntegration +from integrations.template import ProtocolNameIntegration + +# TODO: Add your integration here +INTEGRATIONS: List[Integration] = [ + # Template integration + ProtocolNameIntegration( + integration_id=IntegrationID.EXAMPLE, + start_block=20000000, + summary_cols=[SummaryColumn.TEMPLATE_PTS], + chain=Chain.ETHEREUM, + reward_multiplier=20, + excluded_addresses={ + Web3.to_checksum_address("0x0000000000000000000000000000000000000000") + }, + end_block=40000000, + ), + # Examples + PendleLPTIntegration( + integration_id=IntegrationID.PENDLE_USDE_LPT, + start_block=PENDLE_USDE_JULY_DEPLOYMENT_BLOCK, + sy_contract=None, + lp_contract=None, + summary_cols=[SummaryColumn.PENDLE_SHARDS], + chain=Chain.ETHEREUM, + reward_multiplier=20, + ), + PendleLPTIntegration( + integration_id=IntegrationID.PENDLE_ARBITRUM_USDE_LPT, + start_block=PENDLE_USDE_JULY_DEPLOYMENT_BLOCK, + sy_contract=None, + lp_contract=None, + summary_cols=[SummaryColumn.PENDLE_ARBITRUM_SHARDS], + chain=Chain.ARBITRUM, + reward_multiplier=20, + ), + PendleYTIntegration( + integration_id=IntegrationID.PENDLE_USDE_YT, + start_block=PENDLE_USDE_JULY_DEPLOYMENT_BLOCK, + summary_cols=[SummaryColumn.PENDLE_SHARDS], + chain=Chain.ETHEREUM, + reward_multiplier=20, + ), + PendleYTIntegration( + integration_id=IntegrationID.PENDLE_ARBITRUM_USDE_YT, + start_block=PENDLE_USDE_JULY_DEPLOYMENT_BLOCK, + summary_cols=[SummaryColumn.PENDLE_ARBITRUM_SHARDS], + chain=Chain.ARBITRUM, + reward_multiplier=20, + ), +] + + +def get_integrations() -> List[Integration]: + return INTEGRATIONS diff --git a/constants/summary_columns.py b/constants/summary_columns.py index 17876a8..e2ea4fc 100644 --- a/constants/summary_columns.py +++ b/constants/summary_columns.py @@ -1,21 +1,43 @@ from enum import Enum +class SummaryColumnType(Enum): + ETHENA_PTS = "ethena_pts" + ETHEREAL_PTS = "ethereal_pts" + + class SummaryColumn(Enum): - PENDLE_SHARDS = "pendle_shards" - PENDLE_ARBITRUM_SHARDS = "pendle_arbtrium_shards" - PENDLE_MANTLE_SHARDS = "pendle_mantle_shards" - SYNTHETIX_ARBITRUM_SHARDS = "synthetix_arbitrum_shards" + TEMPLATE_PTS = ("template_pts", SummaryColumnType.ETHENA_PTS) + PENDLE_SHARDS = ("pendle_shards", SummaryColumnType.ETHENA_PTS) + PENDLE_ARBITRUM_SHARDS = ("pendle_arbtrium_shards", SummaryColumnType.ETHENA_PTS) + PENDLE_MANTLE_SHARDS = ("pendle_mantle_shards", SummaryColumnType.ETHENA_PTS) + SYNTHETIX_ARBITRUM_SHARDS = ( + "synthetix_arbitrum_shards", + SummaryColumnType.ETHENA_PTS, + ) + + AMBIENT_SCROLL_SHARDS = ("ambient_scroll_shards", SummaryColumnType.ETHENA_PTS) + + NURI_SHARDS = ("nuri_shards", SummaryColumnType.ETHENA_PTS) + LENDLE_MANTLE_SHARDS = ("lendle_mantle_shards", SummaryColumnType.ETHENA_PTS) + + RHO_MARKETS_SCROLL_SHARDS = ( + "rho_markets_scroll_shards", + SummaryColumnType.ETHENA_PTS, + ) + + RAMSES_SHARDS = ("ramses_shards", SummaryColumnType.ETHENA_PTS) + + GMX_ARBITRUM_SHARDS = ("gmx_arbitrum_shards", SummaryColumnType.ETHENA_PTS) - AMBIENT_SCROLL_SHARDS = "ambient_scroll_shards" + CURVE_LLAMALEND_SHARDS = ("curve_llamalend_shards", SummaryColumnType.ETHENA_PTS) - NURI_SHARDS = "nuri_shards" - LENDLE_MANTLE_SHARDS = "lendle_mantle_shards" + def __init__(self, column_name: str, col_type: SummaryColumnType): + self.column_name = column_name + self.col_type = col_type - RHO_MARKETS_SCROLL_SHARDS = "rho_markets_scroll_shards" - - RAMSES_SHARDS = "ramses_shards" + def get_col_name(self) -> str: + return self.column_name - GMX_ARBITRUM_SHARDS = "gmx_arbitrum_shards" - - CURVE_LLAMALEND_SHARDS = "curve_llamalend_shards" + def get_col_type(self) -> SummaryColumnType: + return self.col_type diff --git a/integrations/template.py b/integrations/template.py index a990900..f3b7a8a 100644 --- a/integrations/template.py +++ b/integrations/template.py @@ -1,39 +1,53 @@ +from typing import Callable, Dict, List, Optional, Set from constants.chains import Chain +from constants.summary_columns import SummaryColumn +from integrations.cached_balances_integration import CachedBalancesIntegration from integrations.integration_ids import IntegrationID -from integrations.integration import Integration +from web3_typing import ChecksumAddress class ProtocolNameIntegration( - Integration + CachedBalancesIntegration ): # TODO: Change ProtocolNameIntegration to the name of the protocol - def __init__(self): + def __init__( + self, + integration_id: IntegrationID, + start_block: int, + chain: Chain = Chain.ETHEREUM, + summary_cols: Optional[List[SummaryColumn]] = None, + reward_multiplier: int = 1, + balance_multiplier: int = 1, + excluded_addresses: Optional[Set[ChecksumAddress]] = None, + end_block: Optional[int] = None, + ethereal_multiplier: int = 0, + ethereal_multiplier_func: Optional[Callable[[int, str], int]] = None, + ): super().__init__( - IntegrationID.EXAMPLE, # TODO: Change EXAMPLE to the name of the protocol - 20000000, # TODO: Change 20000000 to the start block of the protocol when events/balances should first be tracked - Chain.ETHEREUM, # TODO: Change ETHEREUM to the chain of the protocol - None, # TODO: Optional, change None to a list of SummaryColumn enums that this protocol should be associated with, see Pendle grouping example - 20, # TODO: Change 20 to the sats multiplier for the protocol that has been agreed upon - 1, # TODO: Almost always 1, optionally change to a different value if an adjustment needs to be applied to balances - None, # TODO: Optional, change None to the end block of the protocol when events/balances should stop being tracked - None, # TODO: Optional, change None to a function that takes a block number and returns the reward multiplier for that block if it has or will change over time + integration_id, + start_block, + chain, + summary_cols, + reward_multiplier, + balance_multiplier, + excluded_addresses, + end_block, + ethereal_multiplier, + ethereal_multiplier_func, ) - # TODO: Implement function for getting a given user's balance at a given block - def get_balance(self, user: str, block: int) -> float: - pass - - # TODO: Implement function for getting all participants of the protocol, ever - # Important: This function should only be called once and should cache the results by setting self.participants - def get_participants(self) -> list: + # TODO: Implement function that returns a dict of block numbers to a dict of user addresses to balances at that block + # This function should be efficient and use onchain calls where possible + # Example: + # { + # 20000000: {"0x123": 100, "0x456": 200}, + # 20000001: {"0x123": 101, "0x456": 201}, + # 20000002: {"0x123": 102, "0x456": 202}, + # } + def get_block_balances(self, blocks: List[int]) -> Dict[int, Dict[str, float]]: pass if __name__ == "__main__": - # TODO: Write simple tests for the integration + # TODO: Write a simple test for the integration example_integration = ProtocolNameIntegration() - print(example_integration.get_participants()) - print( - example_integration.get_balance( - list(example_integration.get_participants())[0], 20000001 - ) - ) + print(example_integration.get_block_balances([20000000, 20000001, 20000002])) From 6bd34e9ec8e5d998b8938528d5949094ca2521ba Mon Sep 17 00:00:00 2001 From: FJ-Riveros Date: Tue, 19 Nov 2024 14:30:56 +0100 Subject: [PATCH 07/16] feat: add the cached data param --- integrations/cached_balances_integration.py | 4 +- integrations/template.py | 65 +++++++++++++++++---- 2 files changed, 58 insertions(+), 11 deletions(-) diff --git a/integrations/cached_balances_integration.py b/integrations/cached_balances_integration.py index a3fc1c3..e5df540 100644 --- a/integrations/cached_balances_integration.py +++ b/integrations/cached_balances_integration.py @@ -33,5 +33,7 @@ def __init__( ethereal_multiplier_func=ethereal_multiplier_func, ) - def get_block_balances(self, blocks: List[int]) -> Dict[int, Dict[str, float]]: + def get_block_balances( + self, cached_data: Dict[int, Dict[ChecksumAddress, float]], blocks: List[int] + ) -> Dict[int, Dict[str, float]]: raise NotImplementedError diff --git a/integrations/template.py b/integrations/template.py index f3b7a8a..8ef382a 100644 --- a/integrations/template.py +++ b/integrations/template.py @@ -3,6 +3,7 @@ from constants.summary_columns import SummaryColumn from integrations.cached_balances_integration import CachedBalancesIntegration from integrations.integration_ids import IntegrationID +from web3 import Web3 from web3_typing import ChecksumAddress @@ -35,19 +36,63 @@ def __init__( ethereal_multiplier_func, ) - # TODO: Implement function that returns a dict of block numbers to a dict of user addresses to balances at that block - # This function should be efficient and use onchain calls where possible - # Example: + # TODO: Implement this function + def get_block_balances( + self, cached_data: Dict[int, Dict[ChecksumAddress, float]], blocks: List[int] + ) -> Dict[int, Dict[str, float]]: + """Get user balances for specified blocks, using cached data when available. + + Args: + cached_data (Dict[int, Dict[ChecksumAddress, float]]): Dictionary mapping block numbers + to user balances at that block. Used to avoid recomputing known balances. + The inner dictionary maps user addresses to their token balance. + blocks (List[int]): List of block numbers to get balances for. + + Returns: + Dict[int, Dict[str, float]]: Dictionary mapping block numbers to user balances, + where each inner dictionary maps user addresses to their token balance + at that block. + """ + pass + + +if __name__ == "__main__": + # TODO: Write simple tests for the integration + example_integration = ( + ProtocolNameIntegration( + integration_id=IntegrationID.EXAMPLE, + start_block=20000000, + summary_cols=[SummaryColumn.TEMPLATE_PTS], + chain=Chain.ETHEREUM, + reward_multiplier=20, + excluded_addresses={ + Web3.to_checksum_address("0x0000000000000000000000000000000000000000") + }, + end_block=40000000, + ), + ) + print( + example_integration.get_block_balances( + cached_data={}, blocks=[20000000, 20000001, 20000002] + ) + ) + # Example output: # { # 20000000: {"0x123": 100, "0x456": 200}, # 20000001: {"0x123": 101, "0x456": 201}, # 20000002: {"0x123": 102, "0x456": 202}, # } - def get_block_balances(self, blocks: List[int]) -> Dict[int, Dict[str, float]]: - pass - -if __name__ == "__main__": - # TODO: Write a simple test for the integration - example_integration = ProtocolNameIntegration() - print(example_integration.get_block_balances([20000000, 20000001, 20000002])) + print( + example_integration.get_block_balances( + cached_data={ + 20000000: {"0x123": 100, "0x456": 200}, + 20000001: {"0x123": 101, "0x456": 201}, + }, + blocks=[20000002], + ) + ) + # Example output: + # { + # 20000002: {"0x123": 102, "0x456": 202}, + # } From c322323df3edc7c43d3db4c82fc29bd9284fdf34 Mon Sep 17 00:00:00 2001 From: FJ-Riveros Date: Tue, 19 Nov 2024 15:31:10 +0100 Subject: [PATCH 08/16] chore: bump requests --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index b1d75fb..bccc01a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ DateTime~=4.9 web3~=6.19.0 python-dotenv~=1.0.0 -requests~=2.32.0 +requests==2.32.0 tqdm~=4.66.4 rich==13.7.1 From 386e5fa899d2b7d3056db52e2d1cf152095bd8cc Mon Sep 17 00:00:00 2001 From: FJ-Riveros Date: Tue, 19 Nov 2024 17:41:31 +0100 Subject: [PATCH 09/16] chore: linter fixes part 1 --- campaign/campaign.py | 11 ++- constants/balancer.py | 22 ++--- constants/gmx.py | 44 +++++++--- constants/lyra.py | 2 +- constants/pendle.py | 96 +++++++++++++-------- constants/splice.py | 14 +-- integrations/allstake_susde.py | 5 +- integrations/allstake_usde.py | 5 +- integrations/balancer_integration.py | 17 ++-- integrations/equilibria_rusde_sept.py | 2 +- integrations/equilibria_susde_apr_expiry.py | 2 +- integrations/equilibria_susde_sept.py | 2 +- integrations/equilibria_usde_expiry.py | 2 +- integrations/equilibria_zircuit_usde_aug.py | 2 +- integrations/euler_usde.py | 11 +-- integrations/firm_susde.py | 13 +-- integrations/fluid_susde.py | 8 +- integrations/fluid_usde.py | 8 +- integrations/fluid_usde_t4.py | 8 +- integrations/gmx_usde_poitions_aug.py | 6 +- integrations/hyperdrive.py | 2 +- integrations/integration.py | 12 +-- integrations/lendle_usde.py | 17 ++-- integrations/lyra_susde_bull.py | 29 +++---- integrations/merchantmoe_lbt_integration.py | 17 ++-- integrations/nuri.py | 9 +- integrations/pendle_lpt_integration.py | 31 +++---- integrations/pendle_yt_integration.py | 28 +++--- integrations/penpie_usde_july.py | 6 +- integrations/penpie_usde_nov_arb.py | 7 +- integrations/radiant_usde.py | 26 +++--- integrations/ramses.py | 10 ++- integrations/rho_markets.py | 10 +-- integrations/splice_usde_yt.py | 2 +- integrations/synthetix.py | 5 +- integrations/velodrome_mode_susde.py | 5 +- integrations/velodrome_mode_usde.py | 9 +- utils/allstake.py | 17 ++-- utils/balancer.py | 20 +++-- utils/curve.py | 12 +-- utils/equilibria.py | 2 +- utils/gmx.py | 2 +- utils/hyperdrive.py | 89 +++++++++++++------ utils/merchantmoe.py | 16 +++- utils/penpie.py | 13 +-- utils/ramses.py | 6 +- utils/rho_markets.py | 4 +- utils/splice.py | 4 +- utils/stakedao.py | 10 +-- utils/web3_utils.py | 2 +- 50 files changed, 392 insertions(+), 310 deletions(-) diff --git a/campaign/campaign.py b/campaign/campaign.py index 652fca0..aab0149 100644 --- a/campaign/campaign.py +++ b/campaign/campaign.py @@ -1,4 +1,5 @@ from typing import List +from utils import pendle from web3 import Web3 from constants.chains import Chain @@ -28,8 +29,8 @@ PendleLPTIntegration( integration_id=IntegrationID.PENDLE_USDE_LPT, start_block=PENDLE_USDE_JULY_DEPLOYMENT_BLOCK, - sy_contract=None, - lp_contract=None, + sy_contract=pendle.sy_contract, + lp_contract=pendle.lpt_contract, summary_cols=[SummaryColumn.PENDLE_SHARDS], chain=Chain.ETHEREUM, reward_multiplier=20, @@ -37,8 +38,8 @@ PendleLPTIntegration( integration_id=IntegrationID.PENDLE_ARBITRUM_USDE_LPT, start_block=PENDLE_USDE_JULY_DEPLOYMENT_BLOCK, - sy_contract=None, - lp_contract=None, + sy_contract=pendle.usde_arb_SY_contract, + lp_contract=pendle.usde_arb_LPT_contract, summary_cols=[SummaryColumn.PENDLE_ARBITRUM_SHARDS], chain=Chain.ARBITRUM, reward_multiplier=20, @@ -47,6 +48,7 @@ integration_id=IntegrationID.PENDLE_USDE_YT, start_block=PENDLE_USDE_JULY_DEPLOYMENT_BLOCK, summary_cols=[SummaryColumn.PENDLE_SHARDS], + yt_contract=pendle.yt_contract, chain=Chain.ETHEREUM, reward_multiplier=20, ), @@ -54,6 +56,7 @@ integration_id=IntegrationID.PENDLE_ARBITRUM_USDE_YT, start_block=PENDLE_USDE_JULY_DEPLOYMENT_BLOCK, summary_cols=[SummaryColumn.PENDLE_ARBITRUM_SHARDS], + yt_contract=pendle.usde_arb_YT_contract, chain=Chain.ARBITRUM, reward_multiplier=20, ), diff --git a/constants/balancer.py b/constants/balancer.py index 0f3f31c..d3e9c61 100644 --- a/constants/balancer.py +++ b/constants/balancer.py @@ -42,7 +42,7 @@ class IntegrationConfig: aura_address="0x56bA1E88340fD53968f686490519Fb0fBB692a39", has_preminted_bpts=True, ), - IntegrationID.BALANCER_ARBITRUM_GHO_USDE.value: IntegrationConfig( + IntegrationID.BALANCER_ARBITRUM_GHO_USDE: IntegrationConfig( chain=Chain.ARBITRUM, start_block=225688025, incentivized_token=Token.USDE.value, @@ -51,7 +51,7 @@ class IntegrationConfig: gauge_address="0xf2d151c40C18d8097AAa5157eE8f447CBe217269", aura_address="0x106398c0a78AE85F501FEE16d53A81401469b9B8", ), - IntegrationID.BALANCER_ARBITRUM_WAGHO_USDE.value: IntegrationConfig( + IntegrationID.BALANCER_ARBITRUM_WAGHO_USDE: IntegrationConfig( chain=Chain.ARBITRUM, start_block=245277323, incentivized_token=Token.USDE.value, @@ -60,7 +60,7 @@ class IntegrationConfig: gauge_address="0xcfab2efef3affdd158568dc896115eac26b3c498", aura_address="0x8f2c4c4ad0b45a3c740e7f7fbc5a106659adeee7", ), - IntegrationID.BALANCER_ARBITRUM_GYD_SUSDE.value: IntegrationConfig( + IntegrationID.BALANCER_ARBITRUM_GYD_SUSDE: IntegrationConfig( chain=Chain.ARBITRUM, start_block=240466292, incentivized_token=Token.SUSDE.value, @@ -69,7 +69,7 @@ class IntegrationConfig: gauge_address="0xdEC026525FE4FEF54857bCF551aEA97aBc24A673", aura_address="0x2d7cFe43BcDf10137924a20445B763Fb40E5871c", ), - IntegrationID.BALANCER_ARBITRUM_SUSDE_SFRAX.value: IntegrationConfig( + IntegrationID.BALANCER_ARBITRUM_SUSDE_SFRAX: IntegrationConfig( chain=Chain.ARBITRUM, start_block=197330091, incentivized_token=Token.SUSDE.value, @@ -79,7 +79,7 @@ class IntegrationConfig: aura_address="0x0a6a427867a3274909A04276cB5589AE8Cc2dfc7", has_preminted_bpts=True, ), - IntegrationID.BALANCER_ARBITRUM_SUSDE_USDC.value: IntegrationConfig( + IntegrationID.BALANCER_ARBITRUM_SUSDE_USDC: IntegrationConfig( chain=Chain.ARBITRUM, start_block=197316005, incentivized_token=Token.SUSDE.value, @@ -89,7 +89,7 @@ class IntegrationConfig: aura_address="0x043A59D13884DddCa18b99C3C184C29aAd973b35", has_preminted_bpts=True, ), - IntegrationID.BALANCER_ETHEREUM_WSTETH_SUSDE.value: IntegrationConfig( + IntegrationID.BALANCER_ETHEREUM_WSTETH_SUSDE: IntegrationConfig( chain=Chain.ETHEREUM, start_block=20005052, incentivized_token=Token.SUSDE.value, @@ -98,7 +98,7 @@ class IntegrationConfig: gauge_address="0xbd00c7cbe59dddbd784c899ac173b7ba514b9997", aura_address="0x99d9e4d3078f7c9c5b792999749290a54fb87257", ), - IntegrationID.BALANCER_ETHEREUM_BAOUSD_SUSDE.value: IntegrationConfig( + IntegrationID.BALANCER_ETHEREUM_BAOUSD_SUSDE: IntegrationConfig( chain=Chain.ETHEREUM, start_block=20169334, incentivized_token=Token.SUSDE.value, @@ -108,7 +108,7 @@ class IntegrationConfig: aura_address="0xd34793bf42d922b04e7e53253f7195725a4a7e9d", has_preminted_bpts=True, ), - IntegrationID.BALANCER_ETHEREUM_SUSDE_USDC.value: IntegrationConfig( + IntegrationID.BALANCER_ETHEREUM_SUSDE_USDC: IntegrationConfig( chain=Chain.ETHEREUM, start_block=19663564, incentivized_token=Token.SUSDE.value, @@ -118,7 +118,7 @@ class IntegrationConfig: aura_address="0x4b87dcff2f45535775a9564229119dca5e697a10", has_preminted_bpts=True, ), - IntegrationID.BALANCER_ETHEREUM_SUSDE_GYD.value: IntegrationConfig( + IntegrationID.BALANCER_ETHEREUM_SUSDE_GYD: IntegrationConfig( chain=Chain.ETHEREUM, start_block=20569775, incentivized_token=Token.SUSDE.value, @@ -127,7 +127,7 @@ class IntegrationConfig: gauge_address="0x146b6030E6d6a6398B918E9854652a71C9537180", aura_address="0x1f2b312c30b08c1957bd3ada616e77bc7bff51ff", ), - IntegrationID.BALANCER_FRAXTAL_SFRAX_SDAI_SUSDE.value: IntegrationConfig( + IntegrationID.BALANCER_FRAXTAL_SFRAX_SDAI_SUSDE: IntegrationConfig( chain=Chain.FRAXTAL, start_block=5931675, incentivized_token=Token.SUSDE.value, @@ -137,7 +137,7 @@ class IntegrationConfig: aura_address="0x8bb2303ab3ff8bcb1833b71ca14fde75cb88d0b8", has_preminted_bpts=True, ), - IntegrationID.BALANCER_FRAXTAL_FRAX_USDE_DAI_USDT_USDC.value: IntegrationConfig( + IntegrationID.BALANCER_FRAXTAL_FRAX_USDE_DAI_USDT_USDC: IntegrationConfig( chain=Chain.FRAXTAL, start_block=6859850, incentivized_token=Token.USDE.value, diff --git a/constants/gmx.py b/constants/gmx.py index ce53d0c..fea81f2 100644 --- a/constants/gmx.py +++ b/constants/gmx.py @@ -1,21 +1,43 @@ -GMX_USDE_USDC_MARKET_ADDRESS = "0x45aD16Aaa28fb66Ef74d5ca0Ab9751F2817c81a4" +from web3 import Web3 + +GMX_USDE_USDC_MARKET_ADDRESS = Web3.to_checksum_address( + "0x45aD16Aaa28fb66Ef74d5ca0Ab9751F2817c81a4" +) GMX_USDE_USDC_MARKET_BLOCK = 237528674 -GMX_WSTETH_USDE_MARKET_ADDRESS = "0x0Cf1fb4d1FF67A3D8Ca92c9d6643F8F9be8e03E5" +GMX_WSTETH_USDE_MARKET_ADDRESS = Web3.to_checksum_address( + "0x0Cf1fb4d1FF67A3D8Ca92c9d6643F8F9be8e03E5" +) GMX_WSTETH_USDE_MARKET_BLOCK = 237523986 -GMX_SYNTHETICS_READER_CONTRACT_ADDRESS = "0x5Ca84c34a381434786738735265b9f3FD814b824" -GMX_DATA_STORE_CONTRACT_ADDRESS = "0xFD70de6b91282D8017aA4E741e9Ae325CAb992d8" +GMX_SYNTHETICS_READER_CONTRACT_ADDRESS = Web3.to_checksum_address( + "0x5Ca84c34a381434786738735265b9f3FD814b824" +) +GMX_DATA_STORE_CONTRACT_ADDRESS = Web3.to_checksum_address( + "0xFD70de6b91282D8017aA4E741e9Ae325CAb992d8" +) -ETH_TOKEN_ADDRESS = "0x0000000000000000000000000000000000000000" -WETH_TOKEN_ADDRESS = "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1" -WSTETH_TOKEN_ADDRESS = "0x5979D7b546E38E414F7E9822514be443A4800529" -USDE_TOKEN_ADDRESS = "0x5d3a1Ff2b6BAb83b63cd9AD0787074081a52ef34" -USDC_TOKEN_ADDRESS = "0xaf88d065e77c8cC2239327C5EDb3A432268e5831" +ETH_TOKEN_ADDRESS = Web3.to_checksum_address( + "0x0000000000000000000000000000000000000000" +) +WETH_TOKEN_ADDRESS = Web3.to_checksum_address( + "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1" +) +WSTETH_TOKEN_ADDRESS = Web3.to_checksum_address( + "0x5979D7b546E38E414F7E9822514be443A4800529" +) +USDE_TOKEN_ADDRESS = Web3.to_checksum_address( + "0x5d3a1Ff2b6BAb83b63cd9AD0787074081a52ef34" +) +USDC_TOKEN_ADDRESS = Web3.to_checksum_address( + "0xaf88d065e77c8cC2239327C5EDb3A432268e5831" +) -GMX_MAX_PNL_FACTOR_FOR_TRADERS_KEY = "0xab15365d3aa743e766355e2557c230d8f943e195dc84d9b2b05928a07b635ee1" +GMX_MAX_PNL_FACTOR_FOR_TRADERS_KEY = ( + "0xab15365d3aa743e766355e2557c230d8f943e195dc84d9b2b05928a07b635ee1" +) GMX_PRICES_ENDPOINT = "https://arbitrum-v2-1-api.gmxinfra.io/prices/tickers" -GMX_SUBSQUID_ENDPOINT = "https://gmx.squids.live/gmx-synthetics-arbitrum/graphql" \ No newline at end of file +GMX_SUBSQUID_ENDPOINT = "https://gmx.squids.live/gmx-synthetics-arbitrum/graphql" diff --git a/constants/lyra.py b/constants/lyra.py index 2ba1968..d4dacee 100644 --- a/constants/lyra.py +++ b/constants/lyra.py @@ -19,7 +19,7 @@ class DetailType(Enum): class LyraVaultDetails(TypedDict): detail_type: DetailType start: int - chain: str + chain: Chain page_size: int integration_token: Contract | None bridge: Contract | None diff --git a/constants/pendle.py b/constants/pendle.py index 047500f..06ccb6a 100644 --- a/constants/pendle.py +++ b/constants/pendle.py @@ -1,49 +1,73 @@ -PENDLE_ETH_MULTISIG = "0x8270400d528c34e1596EF367eeDEc99080A1b592" -PENDLE_MANTLE_MULTISIG = "0x5C30d3578A4D07a340650a76B9Ae5dF20D5bdF55" -PENDLE_ARBITRUM_MULTISIG = "0xCbcb48e22622a3778b6F14C2f5d258Ba026b05e6" -KARAK_VAULT_SUPERVISOR = "0x54e44DbB92dBA848ACe27F44c0CB4268981eF1CC" +from web3 import Web3 + +PENDLE_ETH_MULTISIG = Web3.to_checksum_address( + "0x8270400d528c34e1596ef367eedec99080a1b592" +) +PENDLE_MANTLE_MULTISIG = Web3.to_checksum_address( + "0x5c30d3578a4d07a340650a76b9ae5df20d5bdf55" +) +PENDLE_ARBITRUM_MULTISIG = Web3.to_checksum_address( + "0xcbcb48e22622a3778b6f14c2f5d258ba026b05e6" +) +KARAK_VAULT_SUPERVISOR = Web3.to_checksum_address( + "0x54e44dbb92dba848ace27f44c0cb4268981ef1cc" +) PENDLE_DEDUCTION = 0.97 -SY = "0x42862F48eAdE25661558AFE0A630b132038553D0" -YT = "0x1e3d13932C31d7355fCb3FEc680b0cD159dC1A07" -LPT = "0x19588F29f9402Bb508007FeADd415c875Ee3f19F" +SY = Web3.to_checksum_address("0x42862f48eade25661558afe0a630b132038553d0") +YT = Web3.to_checksum_address("0x1e3d13932c31d7355fcb3fec680b0cd159dc1a07") +LPT = Web3.to_checksum_address("0x19588f29f9402bb508007feadd415c875ee3f19f") PENDLE_USDE_JULY_DEPLOYMENT_BLOCK = 19564654 -pendle_router = "0x00000000005BBB0EF59571E58418F9a4357b68A0" +pendle_router = Web3.to_checksum_address("0x00000000005bbb0ef59571e58418f9a4357b68a0") susde_new_pool_block = 19728566 -sUSDe_SY = "0xC4ed348c56223C5953939e932E315F9d72Cd83fF" -sUSDe_YT = "0xf65CD2460F4F199C5AC09c74Ac05c40559C29e4F" -sUSDe_LPT = "0x107a2e3cD2BB9a32B9eE2E4d51143149F8367eBa" +sUSDe_SY = Web3.to_checksum_address("0xc4ed348c56223c5953939e932e315f9d72cd83ff") +sUSDe_YT = Web3.to_checksum_address("0xf65cd2460f4f199c5ac09c74ac05c40559c29e4f") +sUSDe_LPT = Web3.to_checksum_address("0x107a2e3cd2bb9a32b9ee2e4d51143149f8367eba") PENDLE_SUSDE_JULY_DEPLOYMENT_BLOCK = 19717752 -SUSDE_SY_SEPT = "0x4139cDC6345aFFbaC0692b43bed4D059Df3e6d65" -SUSDE_YT_SEPT = "0xdc02b77a3986da62C7A78FED73949C9767850809" -SUSDE_LPT_SEPT = "0xd1D7D99764f8a52Aff007b7831cc02748b2013b5" +SUSDE_SY_SEPT = Web3.to_checksum_address("0x4139cdc6345affbac0692b43bed4d059df3e6d65") +SUSDE_YT_SEPT = Web3.to_checksum_address("0xdc02b77a3986da62c7a78fed73949c9767850809") +SUSDE_LPT_SEPT = Web3.to_checksum_address("0xd1d7d99764f8a52aff007b7831cc02748b2013b5") PENDLE_SUSDE_SEPT_DEPLOYMENT_BLOCK = 19909022 -sUSDe_SY_old = "0x215a61deaD7e1303b8571Bb429491aeAc5f2061e" -sUSDe_YT_old = "0x20c8Cf9714339fd018898cB5De84c089e48d1c87" -sUSDe_LPT_old = "0x8f7627bD46B30E296Aa3AAbe1dF9Bfac10920B6E" +sUSDe_SY_old = Web3.to_checksum_address("0x215a61dead7e1303b8571bb429491aeac5f2061e") +sUSDe_YT_old = Web3.to_checksum_address("0x20c8cf9714339fd018898cb5de84c089e48d1c87") +sUSDe_LPT_old = Web3.to_checksum_address("0x8f7627bd46b30e296aa3aabe1df9bfac10920b6e") PENDLE_SUSDE_APRIL_DEPLOYMENT_BLOCK = 19367010 -mantle_YT = "0xb3c0f96c4208185cC22Afd1b7CF21F1dabd9648A" -mantle_LPT = "0x7dc07C575A0c512422dCab82CE9Ed74dB58Be30C" -mantle_SY = "0x5B9e411c9E50164133DE07FE1cAC05A094000105" +mantle_YT = Web3.to_checksum_address("0xb3c0f96c4208185cc22afd1b7cf21f1dabd9648a") +mantle_LPT = Web3.to_checksum_address("0x7dc07c575a0c512422dcab82ce9ed74db58be30c") +mantle_SY = Web3.to_checksum_address("0x5b9e411c9e50164133de07fe1cac05a094000105") PENDLE_MANTLE_DEPLOYMENT_BLOCK = 59995414 -USDe_zircuit_LPT = "0x90c98ab215498B72Abfec04c651e2e496bA364C0" -USDe_zircuit_SY = "0x293C6937D8D82e05B01335F7B33FBA0c8e256E30" -USDe_zircuit_YT = "0x40357b9f22B4DfF0Bf56A90661b8eC106C259d29" +USDe_zircuit_LPT = Web3.to_checksum_address( + "0x90c98ab215498b72abfec04c651e2e496ba364c0" +) +USDe_zircuit_SY = Web3.to_checksum_address("0x293c6937d8d82e05b01335f7b33fba0c8e256e30") +USDe_zircuit_YT = Web3.to_checksum_address("0x40357b9f22b4dff0bf56a90661b8ec106c259d29") PENDLE_USDE_ZIRCUIT_DEPLOYMENT_BLOCK = 19588125 zircuit_USDe_start_block = 19589650 -ENA_LP = "0x9C73879F795CefA1D5239dE08d1B6Aba2D2d1434" -ENA_SY = "0x66C68a7bcC4CBcAb43A2947A529765d86D4ef14f" -ENA_YT = "0x87be82bBd3e6f1c0871001f8EB4C12b60462c835" +ENA_LP = Web3.to_checksum_address("0x9c73879f795cefa1d5239de08d1b6aba2d2d1434") +ENA_SY = Web3.to_checksum_address("0x66c68a7bcc4cbcab43a2947a529765d86d4ef14f") +ENA_YT = Web3.to_checksum_address("0x87be82bbd3e6f1c0871001f8eb4c12b60462c835") PENDLE_ENA_DEPLOYMENT_BLOCK = 19644726 -usde_arb_LP = "0x2Dfaf9a5E4F293BceedE49f2dBa29aACDD88E0C4" -usde_arb_SY = "0xb3C24D9dcCC2Ec5f778742389ffe448E295B84e0" -usde_arb_PT = "0xad853EB4fB3Fe4a66CdFCD7b75922a0494955292" -usde_arb_YT = "0xF478f7FeaeAB0DFdC91E02cDd6C63c66E30a7335" +usde_arb_LP = Web3.to_checksum_address("0x2dfaf9a5e4f293bceede49f2dba29aacdd88e0c4") +usde_arb_SY = Web3.to_checksum_address("0xb3c24d9dccc2ec5f778742389ffe448e295b84e0") +usde_arb_PT = Web3.to_checksum_address("0xad853eb4fb3fe4a66cdfcd7b75922a0494955292") +usde_arb_YT = Web3.to_checksum_address("0xf478f7feaeab0dfdc91e02cdd6c63c66e30a7335") PENDLE_USDE_ARB_DEPLOYMENT_BLOCK = 197776131 -PENDLE_USDE_KARAK_LP = "0x1BCBDB8c8652345A5ACF04e6E74f70086c68FEfC" -PENDLE_USDE_KARAK_SY = "0xfe2d379117895Fa6144B209C13894A17aB18C86c" -PENDLE_USDE_KARAK_YT = "0x2e40D7Cfee1e7D31d1F4875e6F33B2c9a17038fF" +PENDLE_USDE_KARAK_LP = Web3.to_checksum_address( + "0x1bcbdb8c8652345a5acf04e6e74f70086c68fefc" +) +PENDLE_USDE_KARAK_SY = Web3.to_checksum_address( + "0xfe2d379117895fa6144b209c13894a17ab18c86c" +) +PENDLE_USDE_KARAK_YT = Web3.to_checksum_address( + "0x2e40d7cfee1e7d31d1f4875e6f33b2c9a17038ff" +) PENDLE_USDE_KARAK_DEPLOYMENT_BLOCK = 19967899 -PENDLE_SUSDE_KARAK_LP = "0xB1f587B354a4a363f5332e88effbbC2E4961250A" -PENDLE_SUSDE_KARAK_SY = "0x1b641894e66aec7Bf5ab86517e8D81763Cc8e19E" -PENDLE_SUSDE_KARAK_YT = "0xdd68f5D26Bf1182d6b241108bfC01f95C030502b" +PENDLE_SUSDE_KARAK_LP = Web3.to_checksum_address( + "0xb1f587b354a4a363f5332e88effbbc2e4961250a" +) +PENDLE_SUSDE_KARAK_SY = Web3.to_checksum_address( + "0x1b641894e66aec7bf5ab86517e8d81763cc8e19e" +) +PENDLE_SUSDE_KARAK_YT = Web3.to_checksum_address( + "0xdd68f5d26bf1182d6b241108bfc01f95c030502b" +) PENDLE_SUSDE_KARAK_DEPLOYMENT_BLOCK = 19967918 diff --git a/constants/splice.py b/constants/splice.py index 1056745..30f0048 100644 --- a/constants/splice.py +++ b/constants/splice.py @@ -1,9 +1,11 @@ -USDE_SY = "0x86A30BE69D839d7E95948f5ba9d45B1F1f1749d6" -USDE_YT = "0xeB0D929e92A29D7Ee3cc83F334dB5Da5C28D0216" -USDE_LPT = "0x6bcbDF29Ccd99E8b76798336bA800946CAFa415d" +from web3 import Web3 + +USDE_SY = Web3.to_checksum_address("0x86A30BE69D839d7E95948f5ba9d45B1F1f1749d6") +USDE_YT = Web3.to_checksum_address("0xeB0D929e92A29D7Ee3cc83F334dB5Da5C28D0216") +USDE_LPT = Web3.to_checksum_address("0x6bcbDF29Ccd99E8b76798336bA800946CAFa415d") USDE_DEPLOYMENT_BLOCK = 11148972 -SUSDE_SY = "0x0E63b9d6138F363ecf7Db74dD05e3bA81C3c17eC" -SUSDE_YT = "0x0cC48a4616A636006A3C121AD5eF7D52155fAaFF" -SUSDE_LPT = "0xe138a963403037DB36349eD2b747aA05F4E171cc" +SUSDE_SY = Web3.to_checksum_address("0x0E63b9d6138F363ecf7Db74dD05e3bA81C3c17eC") +SUSDE_YT = Web3.to_checksum_address("0x0cC48a4616A636006A3C121AD5eF7D52155fAaFF") +SUSDE_LPT = Web3.to_checksum_address("0xe138a963403037DB36349eD2b747aA05F4E171cc") SUSDE_DEPLOYMENT_BLOCK = 11148921 diff --git a/integrations/allstake_susde.py b/integrations/allstake_susde.py index 4dbd4cd..3fc3059 100644 --- a/integrations/allstake_susde.py +++ b/integrations/allstake_susde.py @@ -7,8 +7,9 @@ integration = AllstakeIntegration(IntegrationID.ALLSTAKE_SUSDE) current_block = W3_BY_CHAIN[integration.chain]["w3"].eth.get_block_number() + participants = integration.get_participants() print("Get Participants:") - print(integration.get_participants()) + print(participants) print("Get Balances of All Participants:") - for participant in integration.participants: + for participant in participants: print(participant, integration.get_balance(participant, current_block)) diff --git a/integrations/allstake_usde.py b/integrations/allstake_usde.py index af542c4..7445fe6 100644 --- a/integrations/allstake_usde.py +++ b/integrations/allstake_usde.py @@ -7,8 +7,9 @@ integration = AllstakeIntegration(IntegrationID.ALLSTAKE_USDE) current_block = W3_BY_CHAIN[integration.chain]["w3"].eth.get_block_number() + participants = integration.get_participants() print("Get Participants:") - print(integration.get_participants()) + print(participants) print("Get Balances of All Participants:") - for participant in integration.participants: + for participant in participants: print(participant, integration.get_balance(participant, current_block)) diff --git a/integrations/balancer_integration.py b/integrations/balancer_integration.py index 681b602..24a0404 100644 --- a/integrations/balancer_integration.py +++ b/integrations/balancer_integration.py @@ -1,3 +1,4 @@ +from typing import List, Optional, Set from integrations.integration_ids import IntegrationID from integrations.integration import Integration from utils.balancer import ( @@ -21,7 +22,7 @@ def __init__(self, integration_id: IntegrationID): integration_id, config.start_block, config.chain, - None, + [], 20, 1, None, @@ -35,7 +36,7 @@ def __init__(self, integration_id: IntegrationID): self.incentivized_token = config.incentivized_token self.incentivized_token_decimals = config.incentivized_token_decimals - def get_balance(self, user: str, block: int) -> float: + def get_balance(self, user: str, block: int | str = "latest") -> float: """ Retrieve the balance of the user in the incentivized Ethena token. @@ -64,7 +65,10 @@ def get_balance(self, user: str, block: int) -> float: / pow(10, self.incentivized_token_decimals) ) - def get_participants(self) -> list: + def get_participants( + self, + blocks: Optional[List[int]], + ) -> Set[str]: """ Retrieve the set of all unique participants who might have staked Balancer Pool Tokens (BPTs). @@ -78,13 +82,11 @@ def get_participants(self) -> list: self.chain, self.aura_address, self.start_block ) - self.participants = set(aura_holders + gauge_holders) - return self.participants + return set(aura_holders + gauge_holders) if __name__ == "__main__": balancer = BalancerIntegration(IntegrationID.BALANCER_FRAXTAL_FRAX_USDE) - # print(balancer.get_participants()) participants = { "0x58d70BFa5B7dEf2B44c2B6c6e1F50bed4950B4D6", "0x5836130b9f34deeb78C7642f37E921F913E4C3d6", @@ -138,5 +140,4 @@ def get_participants(self) -> list: "0xC0fC2fA4629A1a23Ded78193ac16dfe6FFc05269", } for participant in participants: - print(participant, balancer.get_balance(participant, "latest")) - # print(balancer.get_balance(list(participants)[0], "latest")) + print(participant, balancer.get_balance(participant)) diff --git a/integrations/equilibria_rusde_sept.py b/integrations/equilibria_rusde_sept.py index e139697..dddec51 100644 --- a/integrations/equilibria_rusde_sept.py +++ b/integrations/equilibria_rusde_sept.py @@ -19,6 +19,6 @@ print(equilibria_integration.get_participants()) print( equilibria_integration.get_balance( - list(equilibria_integration.get_participants())[0], "latest" + list(equilibria_integration.get_participants())[0] ) ) diff --git a/integrations/equilibria_susde_apr_expiry.py b/integrations/equilibria_susde_apr_expiry.py index 1aa7772..a3a1ced 100644 --- a/integrations/equilibria_susde_apr_expiry.py +++ b/integrations/equilibria_susde_apr_expiry.py @@ -23,6 +23,6 @@ print(equilibria_integration.get_participants()) print( equilibria_integration.get_balance( - list(equilibria_integration.get_participants())[0], "latest" + list(equilibria_integration.get_participants())[0] ) ) diff --git a/integrations/equilibria_susde_sept.py b/integrations/equilibria_susde_sept.py index b6dc001..999bbd4 100644 --- a/integrations/equilibria_susde_sept.py +++ b/integrations/equilibria_susde_sept.py @@ -19,6 +19,6 @@ print(equilibria_integration.get_participants()) print( equilibria_integration.get_balance( - list(equilibria_integration.get_participants())[0], "latest" + list(equilibria_integration.get_participants())[0] ) ) diff --git a/integrations/equilibria_usde_expiry.py b/integrations/equilibria_usde_expiry.py index 52f0139..2c98421 100644 --- a/integrations/equilibria_usde_expiry.py +++ b/integrations/equilibria_usde_expiry.py @@ -23,6 +23,6 @@ print(equilibria_integration.get_participants()) print( equilibria_integration.get_balance( - list(equilibria_integration.get_participants())[0], "latest" + list(equilibria_integration.get_participants())[0] ) ) diff --git a/integrations/equilibria_zircuit_usde_aug.py b/integrations/equilibria_zircuit_usde_aug.py index c83284a..19973b6 100644 --- a/integrations/equilibria_zircuit_usde_aug.py +++ b/integrations/equilibria_zircuit_usde_aug.py @@ -23,6 +23,6 @@ print(equilibria_integration.get_participants()) print( equilibria_integration.get_balance( - list(equilibria_integration.get_participants())[0], "latest" + list(equilibria_integration.get_participants())[0] ) ) diff --git a/integrations/euler_usde.py b/integrations/euler_usde.py index bffcc58..c6e791f 100644 --- a/integrations/euler_usde.py +++ b/integrations/euler_usde.py @@ -43,7 +43,7 @@ def get_balance(self, user: str, block: int) -> float: return asset_balance - def get_participants(self) -> list: + def get_participants(self, blocks: list[int] | None) -> set[str]: if self.participants is not None: return self.participants @@ -77,9 +77,6 @@ def get_participants(self) -> list: if __name__ == "__main__": example_integration = EulerIntegration() - print(example_integration.get_participants()) - print( - example_integration.get_balance( - list(example_integration.get_participants())[0], 20677865 - ) - ) + participants = example_integration.get_participants(None) + print(participants) + print(example_integration.get_balance(list(participants)[0], 20677865)) diff --git a/integrations/firm_susde.py b/integrations/firm_susde.py index 20f0223..cde8083 100644 --- a/integrations/firm_susde.py +++ b/integrations/firm_susde.py @@ -1,3 +1,4 @@ +from typing import List, Optional, Set from constants.chains import Chain from integrations.integration_ids import IntegrationID from integrations.integration import Integration @@ -12,7 +13,7 @@ def __init__(self): IntegrationID.FIRM_SUSDE, FIRM_SUSDE_DEPLOYMENT_BLOCK, Chain.ETHEREUM, - None, + [], 20, 1, None, @@ -29,7 +30,10 @@ def get_balance(self, user: str, block: int) -> float: ) return balance / 1e18 - def get_participants(self) -> list: + def get_participants( + self, + blocks: Optional[List[int]], + ) -> Set[str]: page_size = 1900 start_block = FIRM_SUSDE_DEPLOYMENT_BLOCK target_block = w3.eth.get_block_number() @@ -46,15 +50,12 @@ def get_participants(self) -> list: for escrow_creation in escrow_creations: all_users.add(escrow_creation["args"]["user"]) start_block += page_size - - all_users = list(all_users) - self.participants = all_users return all_users if __name__ == "__main__": firm = Firm() - participants = firm.get_participants() + participants = firm.get_participants(None) print("participants", participants) currentBlock = w3.eth.get_block_number() if len(participants) > 0: diff --git a/integrations/fluid_susde.py b/integrations/fluid_susde.py index 93a9151..96c5ca5 100644 --- a/integrations/fluid_susde.py +++ b/integrations/fluid_susde.py @@ -13,7 +13,7 @@ def __init__(self): IntegrationID.FLUID, 21016131, Chain.ETHEREUM, - None, + [], 5, 1, None, @@ -34,7 +34,7 @@ def get_balance(self, user: str, block: int) -> float: except Exception as e: return 0 - def get_participants(self) -> list: + def get_participants(self, blocks: list[int] | None) -> set[str]: participants = [] current_block = W3_BY_CHAIN[self.chain]["w3"].eth.get_block_number() @@ -55,7 +55,7 @@ def get_participants(self) -> list: participants.append(owner) except Exception as e: print(f"Error: {str(e)}") - return participants + return set(participants) def get_relevant_vaults(self, block: int) -> list: if block in self.blocknumber_to_susdeVaults: @@ -98,7 +98,7 @@ def get_relevant_vaults(self, block: int) -> list: print(example_integration.get_relevant_vaults(21088189)) print("\n\n\ngetting participants") - print(example_integration.get_participants()) + print(example_integration.get_participants(None)) print("\n\n\n getting balance") print( diff --git a/integrations/fluid_usde.py b/integrations/fluid_usde.py index b15aee5..9ce5b8b 100644 --- a/integrations/fluid_usde.py +++ b/integrations/fluid_usde.py @@ -13,7 +13,7 @@ def __init__(self): IntegrationID.FLUID, 21016131, Chain.ETHEREUM, - None, + [], 20, 1, None, @@ -37,7 +37,7 @@ def get_balance(self, user: str, block: int) -> float: except Exception as e: return 0 - def get_participants(self) -> list: + def get_participants(self, blocks: list[int] | None) -> set[str]: participants = [] current_block = W3_BY_CHAIN[self.chain]["w3"].eth.get_block_number() @@ -58,7 +58,7 @@ def get_participants(self) -> list: participants.append(owner) except Exception as e: print(f"Error: {str(e)}") - return participants + return set(participants) def get_relevant_vaults(self, block: int) -> list: if block in self.blocknumber_to_usdeVaults: @@ -101,4 +101,4 @@ def get_relevant_vaults(self, block: int) -> list: print(example_integration.get_relevant_vaults(current_block)) print("\n\n\ngetting participants") - print(example_integration.get_participants()) + print(example_integration.get_participants(None)) diff --git a/integrations/fluid_usde_t4.py b/integrations/fluid_usde_t4.py index 1d23d8d..07c67fa 100644 --- a/integrations/fluid_usde_t4.py +++ b/integrations/fluid_usde_t4.py @@ -18,7 +18,7 @@ def __init__(self): IntegrationID.FLUID, 21016131, Chain.ETHEREUM, - None, + [], 30, 1, None, @@ -53,7 +53,7 @@ def get_balance(self, user: str, block: int) -> float: except Exception as e: return 0 - def get_participants(self) -> list: + def get_participants(self, blocks: list[int] | None) -> set[str]: participants = [] current_block = W3_BY_CHAIN[self.chain]["w3"].eth.get_block_number() relavantUserPositions = [] @@ -72,11 +72,11 @@ def get_participants(self) -> list: participants.append(owner) except Exception as e: print(f"Error: {str(e)}") - return participants + return set(participants) if __name__ == "__main__": example_integration = FluidIntegration() current_block = W3_BY_CHAIN[example_integration.chain]["w3"].eth.get_block_number() print("\n\n\ngetting participants") - print(example_integration.get_participants()) + print(example_integration.get_participants(None)) diff --git a/integrations/gmx_usde_poitions_aug.py b/integrations/gmx_usde_poitions_aug.py index 099a8e9..69c0bac 100644 --- a/integrations/gmx_usde_poitions_aug.py +++ b/integrations/gmx_usde_poitions_aug.py @@ -64,7 +64,7 @@ def get_balance(self, user: str, block: int) -> float: return total_collateral_amount - def get_participants(self) -> list: + def get_participants(self, blocks: list[int] | None) -> set[str]: if self.participants is not None: return self.participants @@ -87,12 +87,12 @@ def get_participants(self) -> list: accounts = [position["account"] for position in participants["positions"]] - return list(set(accounts)) + return set(accounts) if __name__ == "__main__": gmx_integration = GMXPositionsIntegration() - # print(gmx_integration.get_participants()) + print(gmx_integration.get_participants(None)) print( gmx_integration.get_balance( "0xDb59AB7d951f3D9F1d2E764c3A6F7507E11a4e4e", 238320844 diff --git a/integrations/hyperdrive.py b/integrations/hyperdrive.py index dd77e8c..fa167d3 100644 --- a/integrations/hyperdrive.py +++ b/integrations/hyperdrive.py @@ -21,7 +21,7 @@ def __init__(self): IntegrationID.HYPERDRIVE_SUSDE, HYPERDRIVE_SUSDE_POOL_DEPLOYMENT_BLOCK, Chain.ETHEREUM, - None, + [], 20, 1, None, diff --git a/integrations/integration.py b/integrations/integration.py index 81ff5ab..bcb6176 100644 --- a/integrations/integration.py +++ b/integrations/integration.py @@ -1,5 +1,6 @@ from abc import ABC, abstractmethod from typing import Dict, List, Optional, Set +from eth_typing import ChecksumAddress from constants.chains import Chain from integrations.integration_ids import IntegrationID @@ -13,11 +14,11 @@ def __init__( integration_id: IntegrationID, start_block: int, chain: Chain, - summary_cols: list[SummaryColumn], + summary_cols: list[SummaryColumn] | None = None, reward_multiplier: int = 1, balance_multiplier: int = 1, - excluded_addresses: List[str] = None, - end_block: int = None, + excluded_addresses: Optional[Set[ChecksumAddress]] = None, + end_block: Optional[int] = None, reward_multiplier_func=None, ethereal_multiplier: int = 0, ethereal_multiplier_func=None, @@ -25,7 +26,7 @@ def __init__( self.integration_id = integration_id self.start_block = start_block self.end_block = end_block - self.participants = None + self.participants = set() self.chain = chain self.summary_cols = summary_cols self.reward_multiplier = reward_multiplier @@ -35,9 +36,8 @@ def __init__( self.ethereal_multiplier = ethereal_multiplier self.ethereal_multiplier_func = ethereal_multiplier_func - @abstractmethod def get_balance(self, user: str, block: int) -> float: - pass + raise NotImplementedError # either get_participants OR get_block_balances must be implemented def get_participants( diff --git a/integrations/lendle_usde.py b/integrations/lendle_usde.py index 3e42d18..99b4b30 100644 --- a/integrations/lendle_usde.py +++ b/integrations/lendle_usde.py @@ -20,7 +20,7 @@ def __init__(self): None, ) - def get_balance(self, user: str, block: int) -> float: + def get_balance(self, user: str, block: int | str) -> float: bal = call_with_retry( lendle_usde_contract.functions.balanceOf(user), block, @@ -31,7 +31,7 @@ def get_balance(self, user: str, block: int) -> float: return round((bal / 10**18), 4) # Important: This function should only be called once and should cache the results by setting self.participants - def get_participants(self) -> list: + def get_participants(self, blocks: list[int] | None) -> set[str]: page_size = 1900 start_block = LENDLE_USDE_DEPLOYMENT_BLOCK target_block = w3_mantle.eth.get_block_number() @@ -49,16 +49,11 @@ def get_participants(self) -> list: all_users.add(transfer["args"]["to"]) start_block += page_size - all_users = list(all_users) - self.participants = all_users - return all_users + return set(all_users) if __name__ == "__main__": lendle_integration = LendleIntegration() - print(lendle_integration.get_participants()) - print( - lendle_integration.get_balance( - list(lendle_integration.participants)[0], "latest" - ) - ) + participants = lendle_integration.get_participants(None) + print(participants) + print(lendle_integration.get_balance(list(participants)[0], "latest")) diff --git a/integrations/lyra_susde_bull.py b/integrations/lyra_susde_bull.py index f30ecf0..683f258 100644 --- a/integrations/lyra_susde_bull.py +++ b/integrations/lyra_susde_bull.py @@ -40,10 +40,10 @@ def get_balance(self, user: str, block: int) -> float: return get_effective_balance( user, block, - self.vault_data["integration_token"], - self.vault_data["bridge"], - self.vault_data["vault_token"], - W3_BY_CHAIN[example_integration.chain]["w3"].eth.get_block(block)[ + integration_token=self.vault_data["integration_token"], + bridge=self.vault_data["bridge"], + vault_token=self.vault_data["vault_token"], + timestamp=W3_BY_CHAIN[self.chain]["w3"].eth.get_block(block)[ "timestamp" ], ) @@ -51,21 +51,21 @@ def get_balance(self, user: str, block: int) -> float: else: return get_exchange_balance(user, block) - def get_participants(self) -> list: + def get_participants(self, blocks: list[int] | None) -> set[str]: logging.info( f"[{self.integration_id.get_description()}] Getting participants..." ) if self.vault_data["detail_type"] == DetailType.Vault: self.participants = get_vault_users( - self.start_block, - self.vault_data["page_size"], - self.vault_data["vault_token"], - self.chain, + start_block=self.start_block, + page_size=self.vault_data["page_size"], + vault_token=self.vault_data["vault_token"], + chain=self.chain, ) else: self.participants = get_exchange_users() - return self.participants + return set(self.participants) if __name__ == "__main__": @@ -73,10 +73,7 @@ def get_participants(self) -> list: current_block = W3_BY_CHAIN[example_integration.chain]["w3"].eth.get_block_number() print("Found Lyra Participants:") - print(example_integration.get_participants()) + participants = example_integration.get_participants(None) + print(participants) print("Found Balance of First Participant:") - print( - example_integration.get_balance( - list(example_integration.participants)[0], current_block - ) - ) + print(example_integration.get_balance(list(participants)[0], current_block)) diff --git a/integrations/merchantmoe_lbt_integration.py b/integrations/merchantmoe_lbt_integration.py index f74b6ac..76d9073 100644 --- a/integrations/merchantmoe_lbt_integration.py +++ b/integrations/merchantmoe_lbt_integration.py @@ -45,7 +45,7 @@ def get_balance(self, user: str, block: int) -> float: upper_bin_bound = active_id + 183 bin_range = list(range(lower_bin_bound, upper_bin_bound + 1)) - total_liquidity = 0 + total_liquidity = 0.0 logging.info( f"[{self.name}] Calling Liquidity Helper Contract for User: {user}, for bin ids: {bin_range}" ) @@ -64,14 +64,14 @@ def get_balance(self, user: str, block: int) -> float: ) return total_liquidity - def get_participants(self) -> list: - if self.participants is not None: + def get_participants(self, blocks: list[int] | None) -> set[str]: + if self.participants: return self.participants logging.info(f"[{self.name}] Getting participants...") page_size = 1900 start_block = self.start_block - w3_client = W3_BY_CHAIN["mantle"]["w3"] + w3_client = W3_BY_CHAIN[self.chain]["w3"] target_block = w3_client.eth.get_block_number() all_users = set() while start_block < target_block: @@ -108,9 +108,6 @@ def get_participants(self) -> list: lb_pair_contract, liquidity_helper_contract, ) - print(merchant_moe_integration.get_participants()) - print( - merchant_moe_integration.get_balance( - list(merchant_moe_integration.get_participants())[1], "latest" - ) - ) + participants = merchant_moe_integration.get_participants() + print(participants) + print(merchant_moe_integration.get_balance(list(participants)[1], "latest")) diff --git a/integrations/nuri.py b/integrations/nuri.py index 28d2f8d..379fb17 100644 --- a/integrations/nuri.py +++ b/integrations/nuri.py @@ -115,7 +115,7 @@ def get_balance(self, user: str, block: int) -> float: return total_balance - def get_participants(self) -> list: + def get_participants(self, blocks: list[int] | None) -> set[str]: page_size = 999 start_block = NURI_DEPLOYMENT_BLOCK target_block = w3_scroll.eth.get_block_number() @@ -145,12 +145,13 @@ def get_participants(self) -> list: start_block += page_size - self.participants = list(all_users) - return self.participants + self.participants = all_users + return all_users if __name__ == "__main__": nuri = Nuri() # print(nuri.get_balance(Web3.to_checksum_address("0xCE29ECB0D2d8c8f0126ED923C50A35cFb0B613A8"), 7249275)) - # print(nuri.get_participants()) + participants = nuri.get_participants(None) + print(participants) # print(nuri.get_balance(nuri.participants[0], 7249275)) diff --git a/integrations/pendle_lpt_integration.py b/integrations/pendle_lpt_integration.py index c471ab7..fb4d464 100644 --- a/integrations/pendle_lpt_integration.py +++ b/integrations/pendle_lpt_integration.py @@ -26,21 +26,21 @@ def __init__( [[ChecksumAddress]], list # type: ignore ] = get_pendle_participants_v3, chain: Chain = Chain.ETHEREUM, - summary_cols: list[SummaryColumn] = None, + summary_cols: list[SummaryColumn] | None = None, reward_multiplier: int = 1, balance_multiplier: int = 1, - end_block: int = None, - reward_multiplier_func: Callable[[int], int] = None, + end_block: int | None = None, + reward_multiplier_func: Callable[[int], int] | None = None, ): super().__init__( - integration_id, - start_block, - chain, - summary_cols, - reward_multiplier, - balance_multiplier, - end_block, - reward_multiplier_func, + integration_id=integration_id, + start_block=start_block, + chain=chain, + summary_cols=summary_cols, + reward_multiplier=reward_multiplier, + balance_multiplier=balance_multiplier, + end_block=end_block, + reward_multiplier_func=reward_multiplier_func, ) self.sy_contract = sy_contract self.lp_contract = lp_contract @@ -49,7 +49,7 @@ def __init__( ) self.get_participants_func = get_participants_func - def get_balance(self, user: str, block: int) -> float: + def get_balance(self, user: str, block: int | str) -> float: logging.info( f"[{self.get_description()}] Getting balance for {user} at block {block}" ) @@ -79,7 +79,7 @@ def get_balance(self, user: str, block: int) -> float: print(round(((sy_bal / 10**18) * lpt_bal) / total_active_supply, 4)) return round(((sy_bal / 10**18) * lpt_bal) / total_active_supply, 4) - def get_participants(self) -> list: + def get_participants(self, blocks: list[int] | None) -> set[str]: if self.participants is not None: return self.participants @@ -103,5 +103,6 @@ def get_participants(self) -> list: pendle.lpt_contract, reward_multiplier=20, ) - print(integration.get_participants()) - print(integration.get_balance(list(integration.get_participants())[0], "latest")) + participants = integration.get_participants() + print(participants) + print(integration.get_balance(list(participants)[0], "latest")) diff --git a/integrations/pendle_yt_integration.py b/integrations/pendle_yt_integration.py index bfbd584..bf345d8 100644 --- a/integrations/pendle_yt_integration.py +++ b/integrations/pendle_yt_integration.py @@ -26,18 +26,18 @@ def __init__( summary_cols: list[SummaryColumn] = None, reward_multiplier: int = 1, balance_multiplier: int = 1, - end_block: int = None, - reward_multiplier_func: Callable[[int], int] = None, + end_block: int | None = None, + reward_multiplier_func: Callable[[int], int] | None = None, ): super().__init__( - integration_id, - start_block, - chain, - summary_cols, - reward_multiplier, - balance_multiplier, - end_block, - reward_multiplier_func, + integration_id=integration_id, + start_block=start_block, + chain=chain, + summary_cols=summary_cols, + reward_multiplier=reward_multiplier, + balance_multiplier=balance_multiplier, + end_block=end_block, + reward_multiplier_func=reward_multiplier_func, ) self.yt_contract = yt_contract self.summary_cols = ( @@ -46,20 +46,18 @@ def __init__( self.get_participants_func = get_participants_func def get_balance(self, user: str, block: int) -> float: - logging.info( - f"[{self.get_description()}] Getting balance for {user} at block {block}" - ) + logging.info(f"[Pendle YT] Getting balance for {user} at block {block}") # protect against silent rpc errors leading to large erroneous values res = call_with_retry(self.yt_contract.functions.balanceOf(user), block) if not isinstance(res, (int, float)): return 0 return round(res / 10**18, 4) - def get_participants(self) -> list: + def get_participants(self, blocks: list[int] | None = None) -> set[str]: if self.participants is not None: return self.participants - logging.info(f"[{self.get_description()}] Getting participants...") + logging.info("[Pendle YT] Getting participants...") self.participants = self.get_participants_func([self.yt_contract.address]) logging.info( f"[{self.get_description()}] Found {len(self.participants)} participants" diff --git a/integrations/penpie_usde_july.py b/integrations/penpie_usde_july.py index a42ce66..303aa17 100644 --- a/integrations/penpie_usde_july.py +++ b/integrations/penpie_usde_july.py @@ -15,8 +15,4 @@ [PENDLE_LOCKER_ETHEREUM], ) # print(penpie_integration.get_participants()) - print( - penpie_integration.get_balance( - "0x79E40Ab4BAc23E2910C03E2Fc24819fE498A9491", "latest" - ) - ) + print(penpie_integration.get_balance("0x79E40Ab4BAc23E2910C03E2Fc24819fE498A9491")) diff --git a/integrations/penpie_usde_nov_arb.py b/integrations/penpie_usde_nov_arb.py index 9e81a1c..a0e7549 100644 --- a/integrations/penpie_usde_nov_arb.py +++ b/integrations/penpie_usde_nov_arb.py @@ -14,9 +14,4 @@ 1, [PENDLE_LOCKER_ARBITRUM], ) - # print(penpie_integration.get_participants()) - print( - penpie_integration.get_balance( - "0xe95176DF139a93D706655B32Df087a97e212B78E", "latest" - ) - ) + print(penpie_integration.get_balance("0xe95176DF139a93D706655B32Df087a97e212B78E")) diff --git a/integrations/radiant_usde.py b/integrations/radiant_usde.py index 98cd2a6..22292fc 100644 --- a/integrations/radiant_usde.py +++ b/integrations/radiant_usde.py @@ -19,14 +19,11 @@ def __init__(self, integration_id: IntegrationID): print(self.vault_data) super().__init__( - integration_id, - self.vault_data["start"], - self.vault_data["chain"], - None, - 20, - 1, - None, - None, + integration_id=integration_id, + start_block=self.vault_data["start"], + chain=self.vault_data["chain"], + summary_cols=None, + page_size=20, ) def get_balance(self, user: str, block: int) -> float: @@ -38,7 +35,7 @@ def get_balance(self, user: str, block: int) -> float: self.vault_data["lending_pool"], ) - def get_participants(self) -> list: + def get_participants(self, blocks: list[int] | None = None) -> set[str]: logging.info( f"[{self.integration_id.get_description()}] Getting participants..." ) @@ -56,10 +53,7 @@ def get_participants(self) -> list: print("Block:", current_block) print("Found Radiant Participants:") - print(len(example_integration.get_participants())) - print("Found Balance of First Participant:", example_integration.participants[0]) - print( - example_integration.get_balance( - example_integration.participants[0], current_block - ) - ) + participants = example_integration.get_participants(None) + print(len(participants)) + print("Found Balance of First Participant:", participants[0]) + print(example_integration.get_balance(participants[0], current_block)) diff --git a/integrations/ramses.py b/integrations/ramses.py index 636bfc3..9939e68 100644 --- a/integrations/ramses.py +++ b/integrations/ramses.py @@ -111,7 +111,7 @@ def get_balance(self, user: str, block: int) -> float: return total_balance - def get_participants(self) -> list: + def get_participants(self, blocks: list[int] | None = None) -> set[str]: page_size = 999 start_block = RAMSES_DEPLOYMENT_BLOCK target_block = w3_arb.eth.get_block_number() @@ -141,8 +141,8 @@ def get_participants(self) -> list: start_block += page_size - self.participants = list(all_users) - return self.participants + self.participants = all_users + return all_users if __name__ == "__main__": @@ -161,7 +161,9 @@ def get_participants(self) -> list: participants = ramses.get_participants() print(f"Number of participants: {len(participants)}") if participants: - first_participant_balance = ramses.get_balance(participants[0], test_block) + first_participant_balance = ramses.get_balance( + list(participants)[0], test_block + ) print(f"Balance for first participant: {first_participant_balance}") except Exception as e: print(f"An error occurred: {e}") diff --git a/integrations/rho_markets.py b/integrations/rho_markets.py index 23c1a95..6e7dd28 100644 --- a/integrations/rho_markets.py +++ b/integrations/rho_markets.py @@ -3,8 +3,8 @@ if __name__ == "__main__": rho_markets = RhoMarkets() - print(len(rho_markets.get_participants())) - print(rho_markets.get_balance( - w3_scroll.to_checksum_address( - rho_markets.participants[0]), - 7751774)) + participants = rho_markets.get_participants() + print(len(participants)) + print( + rho_markets.get_balance(w3_scroll.to_checksum_address(participants[0]), 7751774) + ) diff --git a/integrations/splice_usde_yt.py b/integrations/splice_usde_yt.py index 636da32..9fc9cc6 100644 --- a/integrations/splice_usde_yt.py +++ b/integrations/splice_usde_yt.py @@ -4,4 +4,4 @@ if __name__ == "__main__": integration = SpliceIntegration(IntegrationID.SPLICE_USDE_YT) print(integration.get_participants()) - print(integration.get_balance(list(integration.get_participants())[0], "latest")) + print(integration.get_balance(list(integration.get_participants())[0])) diff --git a/integrations/synthetix.py b/integrations/synthetix.py index 64eeaea..34a36ca 100644 --- a/integrations/synthetix.py +++ b/integrations/synthetix.py @@ -71,5 +71,6 @@ def get_participants(self) -> list: if __name__ == "__main__": synthetix = Synthetix() - print(synthetix.get_participants()) - print(synthetix.get_balance(synthetix.participants[0], 227610000)) + participants = synthetix.get_participants(None) + print(len(participants)) + print(synthetix.get_balance(participants[0], 227610000)) diff --git a/integrations/velodrome_mode_susde.py b/integrations/velodrome_mode_susde.py index eec4ccc..feb9737 100644 --- a/integrations/velodrome_mode_susde.py +++ b/integrations/velodrome_mode_susde.py @@ -21,9 +21,8 @@ def __init__(self): def get_balance(self, user: str, block: int) -> float: return fetch_balance(user, block, SUSDE_MODE_TOKEN) - def get_participants(self) -> list: - self.participants = fetch_participants(SUSDE_MODE_TOKEN) - return self.participants + def get_participants(self, blocks: list[int] | None = None) -> set[str]: + return fetch_participants(SUSDE_MODE_TOKEN) if __name__ == "__main__": diff --git a/integrations/velodrome_mode_usde.py b/integrations/velodrome_mode_usde.py index 94a4ff7..17eb566 100644 --- a/integrations/velodrome_mode_usde.py +++ b/integrations/velodrome_mode_usde.py @@ -28,9 +28,6 @@ def get_participants(self) -> list: if __name__ == "__main__": velodrome_integration = VelodromeIntegration() - print(velodrome_integration.get_participants()) - print( - velodrome_integration.get_balance( - velodrome_integration.participants[0], 10100000 - ) - ) + participants = velodrome_integration.get_participants() + print(participants) + print(velodrome_integration.get_balance(participants[0], 10100000)) diff --git a/utils/allstake.py b/utils/allstake.py index a934d47..a243a10 100644 --- a/utils/allstake.py +++ b/utils/allstake.py @@ -71,14 +71,13 @@ def __init__(self, integration_id: IntegrationID): print(self.strategy_info) super().__init__( - integration_id, - self.strategy_info["start"], - self.strategy_info["chain"], - None, - 20, - 1, - None, - None, + integration_id=integration_id, + start_block=self.strategy_info["start"], + chain=self.strategy_info["chain"], + summary_cols=None, + page_size=20, + balance_multiplier=1, + reward_multiplier=None, ) def get_balance(self, user: str, block: int) -> float: @@ -89,7 +88,7 @@ def get_balance(self, user: str, block: int) -> float: self.strategy_info["strategy"], ) - def get_participants(self) -> list: + def get_participants(self, blocks: list[int] | None) -> set[str]: logging.info( f"[{self.integration_id.get_description()}] Getting participants..." ) diff --git a/utils/balancer.py b/utils/balancer.py index 2084a2b..5d3456c 100644 --- a/utils/balancer.py +++ b/utils/balancer.py @@ -21,11 +21,13 @@ def get_vault_pool_token_balance( - chain: Chain, pool_id: str, token_address: str, block: int + chain: Chain, pool_id: str, token_address: str, block: int | str ) -> float: w3 = W3_BY_CHAIN[chain]["w3"] - vaut_contract = w3.eth.contract(address=BALANCER_VAULT, abi=vault_abi) + vaut_contract = w3.eth.contract( + address=w3.to_checksum_address(BALANCER_VAULT), abi=vault_abi + ) tokens, balances, _ = call_with_retry( vaut_contract.functions.getPoolTokens(pool_id), @@ -39,10 +41,14 @@ def get_vault_pool_token_balance( raise ValueError(f"Token {token_address} not found in the Pool {pool_id}") -def get_user_balance(chain: Chain, user: str, token_address: str, block: int) -> float: +def get_user_balance( + chain: Chain, user: str, token_address: str, block: int | str +) -> float: w3 = W3_BY_CHAIN[chain]["w3"] - token_contract = w3.eth.contract(address=token_address, abi=erc20_abi) + token_contract = w3.eth.contract( + address=w3.to_checksum_address(token_address), abi=erc20_abi + ) user_balance = call_with_retry( token_contract.functions.balanceOf(user), @@ -53,7 +59,7 @@ def get_user_balance(chain: Chain, user: str, token_address: str, block: int) -> def get_bpt_supply( - chain: Chain, bpt_address: str, has_preminted_bpts: bool, block: int + chain: Chain, bpt_address: str, has_preminted_bpts: bool, block: int | str ) -> float: w3 = W3_BY_CHAIN[chain]["w3"] @@ -84,7 +90,9 @@ def get_potential_token_holders( ) -> list: w3 = W3_BY_CHAIN[chain]["w3"] - token_contract = w3.eth.contract(address=token_address, abi=erc20_abi) + token_contract = w3.eth.contract( + address=Web3.to_checksum_address(token_address), abi=erc20_abi + ) token_holders = set() latest_block = w3.eth.get_block_number() diff --git a/utils/curve.py b/utils/curve.py index f4ee0df..8f28aa1 100644 --- a/utils/curve.py +++ b/utils/curve.py @@ -1,7 +1,9 @@ import json from dataclasses import dataclass +from typing import List + +from web3 import Web3 -from constants.chains import Chain from constants.summary_columns import SummaryColumn from constants.curve import RewardContractConfig @@ -50,7 +52,7 @@ def __init__( integration_id=reward_config.integration_id, start_block=reward_config.genesis_block, chain=reward_config.chain, - summary_cols=SummaryColumn.CURVE_LLAMALEND_SHARDS, + summary_cols=[SummaryColumn.CURVE_LLAMALEND_SHARDS], ) self.w3 = W3_BY_CHAIN[self.chain]["w3"] @@ -58,7 +60,7 @@ def __init__( with open(self.reward_config.abi_filename, "r") as f: abi = json.load(f) self.contract = self.w3.eth.contract( - address=self.reward_config.address, abi=abi + address=Web3.to_checksum_address(self.reward_config.address), abi=abi ) self.contract_function = self.contract.functions.user_state self.contract_event = self.contract.events.Borrow() @@ -128,7 +130,7 @@ def get_user_state(self, user: str, block: int) -> float: def get_current_block(self) -> int: return self.w3.eth.get_block_number() - def get_participants(self) -> list: + def get_participants(self, blocks: list[int] | None = None) -> set[str]: """ Fetch all participants who have borrowed from the LlamaLend market. @@ -138,7 +140,7 @@ def get_participants(self) -> list: page_size = 50000 current_block = self.get_current_block() if self.last_indexed_block == current_block: - return [user_info.address for user_info in self.start_state] + return {user_info.address for user_info in self.start_state} start_block = max(self.start_block, self.last_indexed_block + 1) diff --git a/utils/equilibria.py b/utils/equilibria.py index f2b1920..fd7b11b 100644 --- a/utils/equilibria.py +++ b/utils/equilibria.py @@ -48,7 +48,7 @@ def __init__( self.lp_contract = lp_contract self.lp_contract_id = lp_contract_id - def get_balance(self, user: str, block: int) -> float: + def get_balance(self, user: str, block: int | str = "latest") -> float: equilibria_deposit_contract = w3.eth.contract( address=equilibria_deposit_ethereum, abi=equilibria_deposit ) diff --git a/utils/gmx.py b/utils/gmx.py index dd1ced1..bc4788c 100644 --- a/utils/gmx.py +++ b/utils/gmx.py @@ -2,7 +2,7 @@ import requests from constants.chains import Chain from integrations.integration_ids import IntegrationID -from integrations.integration import Integration +from models.integration import Integration from constants.summary_columns import SummaryColumn from utils.web3_utils import w3_arb, fetch_events_logs_with_retry, call_with_retry diff --git a/utils/hyperdrive.py b/utils/hyperdrive.py index 314296d..c25767b 100644 --- a/utils/hyperdrive.py +++ b/utils/hyperdrive.py @@ -3,22 +3,25 @@ from dotenv import load_dotenv -from constants.hyperdrive import ERC20_ABI,HYPERDRIVE_MORPHO_ABI,HyperdrivePrefix -from utils.web3_utils import fetch_events_logs_with_retry,w3 +from constants.hyperdrive import ERC20_ABI, HYPERDRIVE_MORPHO_ABI, HyperdrivePrefix +from utils.web3_utils import fetch_events_logs_with_retry, w3 load_dotenv() PAGE_SIZE = 1900 getcontext().prec = 100 # Set precision for Decimal calculations + def get_first_contract_block(contract_address): # do binary search up to latest block latest_block = w3.eth.get_block_number() earliest_block = 0 while earliest_block < latest_block: mid_block = (earliest_block + latest_block) // 2 - attempt_to_get_code = w3.eth.get_code(account=contract_address,block_identifier=mid_block) - if attempt_to_get_code == b'': + attempt_to_get_code = w3.eth.get_code( + account=contract_address, block_identifier=mid_block + ) + if attempt_to_get_code == b"": # Contract not yet deployed, continue searching in the later blocks earliest_block = mid_block + 1 else: @@ -26,10 +29,13 @@ def get_first_contract_block(contract_address): latest_block = mid_block - 1 # At this point, earliest_block and latest_block should be the same, # and it represents the block where we can first retrieve the contract code. - assert earliest_block >= latest_block, f"something fucked up since {earliest_block=} isn't greater than or equal to {latest_block=}" + assert ( + earliest_block >= latest_block + ), f"something fucked up since {earliest_block=} isn't greater than or equal to {latest_block=}" return earliest_block -def get_hyperdrive_participants(pool, start_block = None): + +def get_hyperdrive_participants(pool, start_block=None): target_block = w3.eth.get_block_number() all_users = set() all_ids = set() @@ -38,7 +44,7 @@ def get_hyperdrive_participants(pool, start_block = None): assert all_ids is not None, "error: all_ids is None" assert start_block is not None, "error: start_block is None" contract = w3.eth.contract(address=pool, abi=HYPERDRIVE_MORPHO_ABI) - + current_block = start_block while current_block < target_block: to_block = min(current_block + PAGE_SIZE, target_block) @@ -56,6 +62,7 @@ def get_hyperdrive_participants(pool, start_block = None): return all_users, all_ids + def decode_asset_id(asset_id: int) -> tuple[int, int]: r"""Decodes a transaction asset ID into its constituent parts of an identifier, data, and a timestamp. @@ -63,7 +70,7 @@ def decode_asset_id(asset_id: int) -> tuple[int, int]: This gives us a bit-mask with 248 bits set to 1 and the rest set to 0. Then apply this mask to the input ID using the bitwise-and operator `&` to extract the lower 248 bits as the timestamp. - + The prefix is a unique asset ID which denotes the following trade types: LP = 0 LONG = 1 @@ -85,29 +92,44 @@ def decode_asset_id(asset_id: int) -> tuple[int, int]: timestamp = asset_id & prefix_mask # apply the prefix mask return prefix, timestamp + def get_pool_details(pool_contract): config_values = pool_contract.functions.getPoolConfig().call() - config_outputs = pool_contract.functions.getPoolConfig().abi['outputs'][0]['components'] - config_keys = [i['name'] for i in config_outputs if 'name' in i] + config_outputs = pool_contract.functions.getPoolConfig().abi["outputs"][0][ + "components" + ] + config_keys = [i["name"] for i in config_outputs if "name" in i] config = dict(zip(config_keys, config_values)) - for k,v in config.items(): + for k, v in config.items(): print(f"{k}: {v}") info_values = pool_contract.functions.getPoolInfo().call() - info_outputs = pool_contract.functions.getPoolInfo().abi['outputs'][0]['components'] - info_keys = [i['name'] for i in info_outputs if 'name' in i] + info_outputs = pool_contract.functions.getPoolInfo().abi["outputs"][0]["components"] + info_keys = [i["name"] for i in info_outputs if "name" in i] info = dict(zip(info_keys, info_values)) # query pool holdings vault_shares_balance = None if config["vaultSharesToken"] != "0x0000000000000000000000000000000000000000": - vault_shares_contract = w3.eth.contract(address=config["vaultSharesToken"], abi=ERC20_ABI) - vault_shares_balance = vault_shares_contract.functions.balanceOf(pool_contract.address).call() - short_rewardable_tvl = info['shortsOutstanding'] + vault_shares_contract = w3.eth.contract( + address=config["vaultSharesToken"], abi=ERC20_ABI + ) + vault_shares_balance = vault_shares_contract.functions.balanceOf( + pool_contract.address + ).call() + short_rewardable_tvl = info["shortsOutstanding"] lp_rewardable_tvl = vault_shares_balance - short_rewardable_tvl return vault_shares_balance, lp_rewardable_tvl, short_rewardable_tvl -def get_pool_positions(pool_contract, pool_users, pool_ids, lp_rewardable_tvl, short_rewardable_tvl, block = None): + +def get_pool_positions( + pool_contract, + pool_users, + pool_ids, + lp_rewardable_tvl, + short_rewardable_tvl, + block=None, +): pool_positions = [] combined_prefixes = [(0, 3), (2,)] # Treat prefixes 0 and 3 together, 2 separately bal_by_prefix = {0: Decimal(0), 1: Decimal(0), 2: Decimal(0), 3: Decimal(0)} @@ -115,36 +137,53 @@ def get_pool_positions(pool_contract, pool_users, pool_ids, lp_rewardable_tvl, s # First pass: collect balances for user, id in itertools.product(pool_users, pool_ids): trade_type, prefix, timestamp = get_trade_details(int(id)) - bal = pool_contract.functions.balanceOf(int(id), user).call(block_identifier=block or "latest") + bal = pool_contract.functions.balanceOf(int(id), user).call( + block_identifier=block or "latest" + ) if bal > Decimal(1): - pool_positions.append([user, trade_type, prefix, timestamp, bal, Decimal(0)]) + pool_positions.append( + [user, trade_type, prefix, timestamp, bal, Decimal(0)] + ) bal_by_prefix[prefix] += bal # Second pass: calculate shares (prefix 1 (longs) get nothing, so we skip it) for position in pool_positions: prefix = position[2] if prefix in [0, 3]: # assign rewards for LPs and withdrawal shares - combined_lp_balance = bal_by_prefix[0] + bal_by_prefix[3] # combine LP and withdrawal share balance + combined_lp_balance = ( + bal_by_prefix[0] + bal_by_prefix[3] + ) # combine LP and withdrawal share balance if combined_lp_balance != Decimal(0): share_of_rewardable = position[4] / combined_lp_balance - position[5] = (lp_rewardable_tvl * share_of_rewardable).quantize(Decimal('0')) + position[5] = (lp_rewardable_tvl * share_of_rewardable).quantize( + Decimal("0") + ) elif prefix == 2: # assign rewards for shorts if bal_by_prefix[2] != Decimal(0): share_of_rewardable = position[4] / bal_by_prefix[2] - position[5] = (short_rewardable_tvl * share_of_rewardable).quantize(Decimal('0')) + position[5] = (short_rewardable_tvl * share_of_rewardable).quantize( + Decimal("0") + ) # Correction step to fix rounding errors for prefixes in combined_prefixes: - combined_shares = sum(position[5] for position in pool_positions if position[2] in prefixes) - combined_rewardable = lp_rewardable_tvl if prefixes[0] == 0 else short_rewardable_tvl + combined_shares = sum( + position[5] for position in pool_positions if position[2] in prefixes + ) + combined_rewardable = ( + lp_rewardable_tvl if prefixes[0] == 0 else short_rewardable_tvl + ) if combined_shares != combined_rewardable: diff = combined_rewardable - combined_shares # Find the position with the largest share among the combined prefixes - max_position = max((p for p in pool_positions if p[2] in prefixes), key=lambda x: x[5]) + max_position = max( + (p for p in pool_positions if p[2] in prefixes), key=lambda x: x[5] + ) max_position[5] += diff return pool_positions + def get_trade_details(asset_id: int) -> tuple[str, int, int]: prefix, timestamp = decode_asset_id(asset_id) trade_type = HyperdrivePrefix(prefix).name diff --git a/utils/merchantmoe.py b/utils/merchantmoe.py index f594a5d..b5ff31a 100644 --- a/utils/merchantmoe.py +++ b/utils/merchantmoe.py @@ -3,8 +3,12 @@ from dotenv import load_dotenv -from constants.merchantmoe import MERCHANT_MOE_LIQUIDITY_HELPER_CONTRACT, METH_USDE_MERCHANT_MOE_LBT_CONTRACT +from constants.merchantmoe import ( + MERCHANT_MOE_LIQUIDITY_HELPER_CONTRACT, + METH_USDE_MERCHANT_MOE_LBT_CONTRACT, +) from utils.web3_utils import w3_mantle +from web3 import Web3 load_dotenv() @@ -16,5 +20,11 @@ open(Path(__file__).parent.parent / "abi/merchant_moe_liquidity_helper.json") ) -lb_pair_contract = w3_mantle.eth.contract(address=METH_USDE_MERCHANT_MOE_LBT_CONTRACT, abi=merchant_moe_lb_pair_abi) -liquidity_helper_contract = w3_mantle.eth.contract(address=MERCHANT_MOE_LIQUIDITY_HELPER_CONTRACT, abi=merchant_moe_liquidity_helper_abi) \ No newline at end of file +lb_pair_contract = w3_mantle.eth.contract( + address=Web3.to_checksum_address(METH_USDE_MERCHANT_MOE_LBT_CONTRACT), + abi=merchant_moe_lb_pair_abi, +) +liquidity_helper_contract = w3_mantle.eth.contract( + address=Web3.to_checksum_address(MERCHANT_MOE_LIQUIDITY_HELPER_CONTRACT), + abi=merchant_moe_liquidity_helper_abi, +) diff --git a/utils/penpie.py b/utils/penpie.py index 978a0bb..132c8ea 100644 --- a/utils/penpie.py +++ b/utils/penpie.py @@ -49,16 +49,15 @@ def __init__( ) self.lp_contract = lp_contract - def get_balance(self, user: str, block: int) -> float: - # print(self.chain==Chain.ETHEREUM) - + def get_balance(self, user: str, block: int | str = "latest") -> float: if self.chain == Chain.ETHEREUM: masterpenpiecontract = w3.eth.contract( address=master_penpie_ethereum, abi=master_penpie ) if self.chain == Chain.ARBITRUM: masterpenpiecontract = w3_arb.eth.contract( - address=master_penpie_arbitrum, abi=master_penpie + address=w3_arb.to_checksum_address(master_penpie_arbitrum), + abi=master_penpie, ) # Get lpt token address from Stake DAO vault @@ -117,10 +116,12 @@ def get_balance(self, user: str, block: int) -> float: print(lpt_bal / 10**18) if self.chain == Chain.ETHEREUM: - receiptcontract = w3.eth.contract(address=self.lp_contract, abi=erc20_abi) + receiptcontract = w3.eth.contract( + address=w3.to_checksum_address(self.lp_contract), abi=erc20_abi + ) if self.chain == Chain.ARBITRUM: receiptcontract = w3_arb.eth.contract( - address=self.lp_contract, abi=erc20_abi + address=w3_arb.to_checksum_address(self.lp_contract), abi=erc20_abi ) # Get gauge total suply diff --git a/utils/ramses.py b/utils/ramses.py index 52d4af0..eb753b8 100644 --- a/utils/ramses.py +++ b/utils/ramses.py @@ -15,10 +15,10 @@ nfp_manager = w3_arb.eth.contract( - address=RAMSES_NFP_MANAGER_ADDRESS, abi=nfp_manager_abi + address=w3_arb.to_checksum_address(RAMSES_NFP_MANAGER_ADDRESS), + abi=nfp_manager_abi, ) pool = w3_arb.eth.contract( - address=RAMSES_POOL_ADDRESS, abi=pool_abi + address=w3_arb.to_checksum_address(RAMSES_POOL_ADDRESS), abi=pool_abi ) - diff --git a/utils/rho_markets.py b/utils/rho_markets.py index f2c3f34..28a4288 100644 --- a/utils/rho_markets.py +++ b/utils/rho_markets.py @@ -52,7 +52,6 @@ def get_participants(self) -> list: all_users.add(user["id"]) except Exception as e: print(e) - all_users = list(all_users) self.participants = all_users return all_users @@ -98,8 +97,7 @@ def fetch_compound_users(self, asset_symbol): last_id = accounts[-1]["id"] else: raise Exception( - f"Query failed with status code { - response.status_code}: {response.text}" + f"Query failed with status code {response.status_code}: {response.text}" ) return all_accounts diff --git a/utils/splice.py b/utils/splice.py index f57a94d..1183b88 100644 --- a/utils/splice.py +++ b/utils/splice.py @@ -181,7 +181,7 @@ def __init__(self, integration_id: IntegrationID): def get_description(self): return self.integration_id.get_description() - def get_balance(self, user: str, block: int) -> float: + def get_balance(self, user: str, block: int | str) -> float: logging.info( f"[{self.get_description()}] Getting balance for {user} at block {block}" ) @@ -197,4 +197,4 @@ def get_participants(self) -> list: logging.info( f"[{self.get_description()}] Found {len(self.participants)} participants" ) - return self.participants + return set(self.participants) diff --git a/utils/stakedao.py b/utils/stakedao.py index 76bfcaf..e194245 100644 --- a/utils/stakedao.py +++ b/utils/stakedao.py @@ -36,16 +36,16 @@ def __init__( chain, None, reward_multiplier, - balance_multiplier, - excluded_addresses, - None, - None, + balance_multiplier=balance_multiplier, + excluded_addresses=excluded_addresses, ) self.lp_contract = lp_contract def get_balance(self, user: str, block: int) -> float: - stakeDAOVaultContract = w3.eth.contract(address=self.lp_contract, abi=vault_abi) + stakeDAOVaultContract = w3.eth.contract( + address=w3.to_checksum_address(self.lp_contract), abi=vault_abi + ) # Get lpt token address from Stake DAO vault pendlePoolAddress = call_with_retry( diff --git a/utils/web3_utils.py b/utils/web3_utils.py index 94f1ccd..bf192b9 100644 --- a/utils/web3_utils.py +++ b/utils/web3_utils.py @@ -126,7 +126,7 @@ def call_with_retry(contract_function, block="latest", retries=3, delay=2): raise e -def multicall(w3: Web3, calls: list, block_identifier: int = "latest"): +def multicall(w3: Web3, calls: list, block_identifier: int | str = "latest"): multicall_contract = w3.eth.contract(address=MULTICALL_ADDRESS, abi=MULTICALL_ABI) aggregate_calls = [] From 83ee6b2de7774427ffae60b88d2ed248c9874b25 Mon Sep 17 00:00:00 2001 From: FJ-Riveros Date: Tue, 19 Nov 2024 20:09:09 +0100 Subject: [PATCH 10/16] chore: fix linter part 2 --- constants/allstake.py | 2 +- constants/equilibria.py | 30 +++-- constants/firm.py | 6 +- constants/fluid.py | 16 ++- constants/lyra.py | 2 +- constants/nuri.py | 14 ++- constants/penpie.py | 109 ++++++++++------- constants/radiant.py | 2 +- constants/synthetix.py | 14 ++- integrations/allstake_susde.py | 2 +- integrations/allstake_usde.py | 2 +- integrations/ambient_scroll.py | 10 +- integrations/beefy_arbitrum_usde.py | 4 +- integrations/beefy_fraxtal_usde.py | 4 +- integrations/beefy_mantle_usde.py | 4 +- integrations/beefy_optimism_usde.py | 4 +- integrations/equilibria_karak_susde_sept.py | 6 +- integrations/equilibria_karak_usde_sept.py | 6 +- integrations/equilibria_rusde_sept.py | 6 +- integrations/equilibria_susde_apr_expiry.py | 6 +- integrations/equilibria_susde_sept.py | 6 +- integrations/equilibria_usde_expiry.py | 6 +- integrations/equilibria_zircuit_usde_aug.py | 6 +- integrations/euler_susde.py | 8 +- integrations/gmx_usde_usdc_aug.py | 2 +- integrations/gmx_wsteth_usde_aug.py | 2 +- integrations/integration.py | 2 +- integrations/lyra_susde_bull.py | 10 +- integrations/merchantmoe_lbt_integration.py | 8 +- integrations/nuri.py | 6 +- integrations/pendle_lpt_integration.py | 6 +- integrations/pendle_yt_integration.py | 6 +- integrations/penpie_ena_aug.py | 2 +- integrations/penpie_ena_oct.py | 2 +- integrations/penpie_karak_susde_sep.py | 2 +- integrations/penpie_karak_usde_sep.py | 2 +- integrations/penpie_mellow_rsena_sep.py | 5 +- integrations/penpie_mellow_rusde_sep.py | 5 +- integrations/penpie_susde_25apr.py | 2 +- integrations/penpie_susde_dec.py | 4 +- integrations/penpie_susde_july.py | 2 +- integrations/penpie_susde_oct.py | 4 +- integrations/penpie_susde_sep.py | 2 +- integrations/penpie_usde_aug_Arb.py | 4 +- integrations/penpie_usde_dec.py | 2 +- integrations/penpie_usde_july.py | 2 +- integrations/penpie_usde_nov_arb.py | 2 +- integrations/penpie_usde_oct.py | 2 +- integrations/penpie_zircuit_usde_jun.py | 2 +- integrations/radiant_usde.py | 6 +- integrations/ramses.py | 2 +- integrations/rho_markets.py | 6 +- integrations/splice_susde_lpt.py | 6 +- integrations/splice_susde_yt.py | 6 +- integrations/splice_usde_lpt.py | 4 +- integrations/splice_usde_yt.py | 4 +- integrations/stakedao_susde_july.py | 2 +- integrations/stakedao_susde_sept.py | 2 +- integrations/stakedao_usde_july.py | 2 +- integrations/synthetix.py | 7 +- integrations/template.py | 34 +++--- integrations/term_susde.py | 43 ++----- integrations/velodrome_mode_usde.py | 6 +- utils/allstake.py | 3 +- utils/beefy.py | 10 +- utils/curve.py | 4 +- utils/equilibria.py | 28 ++--- utils/firm.py | 9 +- utils/gmx.py | 15 ++- utils/hyperdrive.py | 12 +- utils/lendle.py | 7 +- utils/lyra.py | 125 +++++++++++++------- utils/nuri.py | 7 +- utils/pendle.py | 11 +- utils/penpie.py | 42 ++++--- utils/rho_markets.py | 4 +- utils/slack.py | 5 +- utils/splice.py | 25 ++-- utils/stakedao.py | 21 ++-- utils/velodrome.py | 21 ++-- utils/web3_utils.py | 13 +- 81 files changed, 487 insertions(+), 368 deletions(-) diff --git a/constants/allstake.py b/constants/allstake.py index d81fe3e..841ecfe 100644 --- a/constants/allstake.py +++ b/constants/allstake.py @@ -12,7 +12,7 @@ class StrategyConfig(TypedDict): start: int - chain: str + chain: Chain underlying: Contract strategy: Contract page_size: int diff --git a/constants/equilibria.py b/constants/equilibria.py index 0896a21..1f8fa11 100644 --- a/constants/equilibria.py +++ b/constants/equilibria.py @@ -1,30 +1,42 @@ -PENDLE_LOCKER_ETHEREUM = "0x64627901dAdb46eD7f275fD4FC87d086cfF1e6E3" -equilibria_deposit_ethereum = "0x4D32C8Ff2fACC771eC7Efc70d6A8468bC30C26bF" +from web3 import Web3 -SUSDE_SEPT = "0x198Ddb596a080215F0e15caeABca7eAB6b2d7A8f" +PENDLE_LOCKER_ETHEREUM = Web3.to_checksum_address( + "0x64627901dAdb46eD7f275fD4FC87d086cfF1e6E3" +) +equilibria_deposit_ethereum = Web3.to_checksum_address( + "0x4D32C8Ff2fACC771eC7Efc70d6A8468bC30C26bF" +) + +SUSDE_SEPT = Web3.to_checksum_address("0x198Ddb596a080215F0e15caeABca7eAB6b2d7A8f") SUSDE_SEPT_ID = 51 SUSDE_SEPT_DEPLOYMENT_BLOCK = 19931018 -Karak_sUSDe_SEPT = "0xcB7212d19D52b53e44625Dc1A9d4B1f1d4833575" +Karak_sUSDe_SEPT = Web3.to_checksum_address( + "0xcB7212d19D52b53e44625Dc1A9d4B1f1d4833575" +) Karak_sUSDe_SEPT_ID = 57 Karak_sUSDe_SEPT_DEPLOYMENT_BLOCK = 19975464 -Karak_USDE_SEPT = "0x6fDF80071499b46Bb53AfBA7bAFf9D91A21133AB" +Karak_USDE_SEPT = Web3.to_checksum_address("0x6fDF80071499b46Bb53AfBA7bAFf9D91A21133AB") Karak_USDE_SEPT_ID = 56 Karak_USDE_SEPT_DEPLOYMENT_BLOCK = 19975462 -Zircuit_USDe_AUG = "0x0CaCF4ACdAAB8664857C29755Bd710B8bafDBeC3" +Zircuit_USDe_AUG = Web3.to_checksum_address( + "0x0CaCF4ACdAAB8664857C29755Bd710B8bafDBeC3" +) Zircuit_USDe_AUG_ID = 69 Zircuit_USDe_AUG_DEPLOYMENT_BLOCK = 20181693 -rUSDE_SEPT = "0x2F35DF137b64D1b62AE440b0D6A7b1cf9af4aB62" +rUSDE_SEPT = Web3.to_checksum_address("0x2F35DF137b64D1b62AE440b0D6A7b1cf9af4aB62") rUSDE_SEPT_ID = 70 rUSDE_SEPT_DEPLOYMENT_BLOCK = 20230561 -USDE_EXPIRY = "0x8c9590Fa87d5083668f1Ba0C6696688A0d2E8EC0" +USDE_EXPIRY = Web3.to_checksum_address("0x8c9590Fa87d5083668f1Ba0C6696688A0d2E8EC0") USDE_EXPIRY_ID = 33 USDE_EXPIRY_DEPLOYMENT_BLOCK = 19330240 -SUSDE_APR_EXPIRY = "0xDC947a371D46356859860451198cB3450086c88C" +SUSDE_APR_EXPIRY = Web3.to_checksum_address( + "0xDC947a371D46356859860451198cB3450086c88C" +) SUSDE_APR_EXPIRY_ID = 35 SUSDE_APR_EXPIRY_DEPLOYMENT_BLOCK = 19382154 diff --git a/constants/firm.py b/constants/firm.py index 11eca5a..e8e86f7 100644 --- a/constants/firm.py +++ b/constants/firm.py @@ -1,3 +1,7 @@ +from web3 import Web3 + FIRM_SUSDE_DEPLOYMENT_BLOCK = 20441987 -SUSDE_MARKET_ADDRESS = "0x79eF6d28C41e47A588E2F2ffB4140Eb6d952AEc4" \ No newline at end of file +SUSDE_MARKET_ADDRESS = Web3.to_checksum_address( + "0x79eF6d28C41e47A588E2F2ffB4140Eb6d952AEc4" +) diff --git a/constants/fluid.py b/constants/fluid.py index 997648a..45e6f57 100644 --- a/constants/fluid.py +++ b/constants/fluid.py @@ -1,6 +1,10 @@ -vaultResolver = "0x49290f778faAD125f2FBCDE6F09600e73bf4bBd9" -vaultPositionResolver = "0x3E3dae4F30347782089d398D462546eb5276801C" -vaultFactory = "0x324c5Dc1fC42c7a4D43d92df1eBA58a54d13Bf2d" -sUSDe = "0x9D39A5DE30e57443BfF2A8307A4256c8797A3497" -USDe = "0x4c9EDD5852cd905f086C759E8383e09bff1E68B3" -dexResolver = "0x7af0C11F5c787632e567e6418D74e5832d8FFd4c" +from web3 import Web3 + +vaultResolver = Web3.to_checksum_address("0x49290f778faAD125f2FBCDE6F09600e73bf4bBd9") +vaultPositionResolver = Web3.to_checksum_address( + "0x3E3dae4F30347782089d398D462546eb5276801C" +) +vaultFactory = Web3.to_checksum_address("0x324c5Dc1fC42c7a4D43d92df1eBA58a54d13Bf2d") +sUSDe = Web3.to_checksum_address("0x9D39A5DE30e57443BfF2A8307A4256c8797A3497") +USDe = Web3.to_checksum_address("0x4c9EDD5852cd905f086C759E8383e09bff1E68B3") +dexResolver = Web3.to_checksum_address("0x7af0C11F5c787632e567e6418D74e5832d8FFd4c") diff --git a/constants/lyra.py b/constants/lyra.py index d4dacee..5e1716f 100644 --- a/constants/lyra.py +++ b/constants/lyra.py @@ -76,7 +76,7 @@ class LyraVaultDetails(TypedDict): ), page_size=20000, ), - IntegrationID.LYRA_SUSDE_EXCHANGE_DEPOSIT: LyraVaultDetails( + IntegrationID.LYRA_SUSDE_EXCHANGE_DEPOSIT: LyraVaultDetails( # type: ignore detail_type=DetailType.Exchange, start=11481048, chain=Chain.Lyra, diff --git a/constants/nuri.py b/constants/nuri.py index 2bf4f14..fa2187a 100644 --- a/constants/nuri.py +++ b/constants/nuri.py @@ -1,5 +1,13 @@ -NURI_NFP_MANAGER_ADDRESS = "0xAAA78E8C4241990B4ce159E105dA08129345946A" -NURI_POOL_ADDRESS = "0x93b77EABf65921477EE1FbC1B3833D7071DB1797" +from web3 import Web3 + +NURI_NFP_MANAGER_ADDRESS = Web3.to_checksum_address( + "0xAAA78E8C4241990B4ce159E105dA08129345946A" +) +NURI_POOL_ADDRESS = Web3.to_checksum_address( + "0x93b77EABf65921477EE1FbC1B3833D7071DB1797" +) NURI_DEPLOYMENT_BLOCK = 7055711 -SCROLL_USDE_TOKEN_ADDRESS = "0x5d3a1Ff2b6BAb83b63cd9AD0787074081a52ef34" \ No newline at end of file +SCROLL_USDE_TOKEN_ADDRESS = Web3.to_checksum_address( + "0x5d3a1Ff2b6BAb83b63cd9AD0787074081a52ef34" +) diff --git a/constants/penpie.py b/constants/penpie.py index 3a365ec..8f08a9d 100644 --- a/constants/penpie.py +++ b/constants/penpie.py @@ -1,65 +1,94 @@ -PENDLE_LOCKER_ETHEREUM = "0x6E799758CEE75DAe3d84e09D40dc416eCf713652" -PENDLE_LOCKER_ARBITRUM = "0x6DB96BBEB081d2a85E0954C252f2c1dC108b3f81" -master_penpie_ethereum="0x16296859C15289731521F199F0a5f762dF6347d0" -master_penpie_arbitrum="0x0776C06907CE6Ff3d9Dbf84bA9B3422d7225942D" - - -SUSDE_JULY = "0xae52ec79F2444D642B7E855DfF67bA4849D365eB" +from web3 import Web3 + +PENDLE_LOCKER_ETHEREUM = Web3.to_checksum_address( + "0x6E799758CEE75DAe3d84e09D40dc416eCf713652" +) +PENDLE_LOCKER_ARBITRUM = Web3.to_checksum_address( + "0x6DB96BBEB081d2a85E0954C252f2c1dC108b3f81" +) +master_penpie_ethereum = Web3.to_checksum_address( + "0x16296859C15289731521F199F0a5f762dF6347d0" +) +master_penpie_arbitrum = Web3.to_checksum_address( + "0x0776C06907CE6Ff3d9Dbf84bA9B3422d7225942D" +) + + +SUSDE_JULY = Web3.to_checksum_address("0xae52ec79F2444D642B7E855DfF67bA4849D365eB") SUSDE_JULY_DEPLOYMENT_BLOCK = 19717752 -Karak_sUSDe_26SEP2024_PRT="0x1c055D8081CA3B2bE0DD00ABe784b142C608219E" -Karak_sUSDe_26SEP2024_PRT_DEPLOYMENT_BLOCK=19967918 - +Karak_sUSDe_26SEP2024_PRT = Web3.to_checksum_address( + "0x1c055D8081CA3B2bE0DD00ABe784b142C608219E" +) +Karak_sUSDe_26SEP2024_PRT_DEPLOYMENT_BLOCK = 19967918 -Karak_USDE_26SEP2024_PRT="0x0980Be7cC405ae7C31CC39E1dd1ee77483C1a430" -Karak_USDE_26SEP2024_PRT_DEPLOYMENT_BLOCK=19967899 +Karak_USDE_26SEP2024_PRT = Web3.to_checksum_address( + "0x0980Be7cC405ae7C31CC39E1dd1ee77483C1a430" +) +Karak_USDE_26SEP2024_PRT_DEPLOYMENT_BLOCK = 19967899 -sUSDe25APR2024_PRT="0xD35B5F85aeec81ba3A9BFa26478b2C43B8889C91" -sUSDe25APR2024_PRT_DEPLOYMENT_BLOCK=19367010 +sUSDe25APR2024_PRT = Web3.to_checksum_address( + "0xD35B5F85aeec81ba3A9BFa26478b2C43B8889C91" +) +sUSDe25APR2024_PRT_DEPLOYMENT_BLOCK = 19367010 -sUSDe26SEP2024_PRT="0xA60f87Eac3877dFCE688Df40AeBba20030E0eb75" -sUSDe26SEP2024_PRT_DEPLOYMENT_BLOCK=19909022 +sUSDe26SEP2024_PRT = Web3.to_checksum_address( + "0xA60f87Eac3877dFCE688Df40AeBba20030E0eb75" +) +sUSDe26SEP2024_PRT_DEPLOYMENT_BLOCK = 19909022 -USDe25JUL2024_PRT="0x3984E25AF3EbcfB4ca8925e9fA8855e17DC1D240" -USDe25JUL2024_PRT_DEPLOYMENT_BLOCK=19564654 +USDe25JUL2024_PRT = Web3.to_checksum_address( + "0x3984E25AF3EbcfB4ca8925e9fA8855e17DC1D240" +) +USDe25JUL2024_PRT_DEPLOYMENT_BLOCK = 19564654 -Zircuit_USDe27JUN2024_PRT="0x15254c0CD69cD5c92D6A8D66De487370E146b17d" -Zircuit_USDe27JUN2024_PRT_DEPLOYMENT_BLOCK=19588125 +Zircuit_USDe27JUN2024_PRT = Web3.to_checksum_address( + "0x15254c0CD69cD5c92D6A8D66De487370E146b17d" +) +Zircuit_USDe27JUN2024_PRT_DEPLOYMENT_BLOCK = 19588125 -ENA29AUG2024_PRT="0xF65d42E30C15E861bc410a94e01f0CbADC0356C2" -ENA29AUG2024_PRT_DEPLOYMENT_BLOCK=19644726 +ENA29AUG2024_PRT = Web3.to_checksum_address( + "0xF65d42E30C15E861bc410a94e01f0CbADC0356C2" +) +ENA29AUG2024_PRT_DEPLOYMENT_BLOCK = 19644726 -USDE_ARB_AUG2024="0x51FF42a579EBfC18EF9e92050494028B4aF34FA5" -USDE_ARB_AUG2024_DEPLOYMENT_BLOCK=197776131 +USDE_ARB_AUG2024 = Web3.to_checksum_address( + "0x51FF42a579EBfC18EF9e92050494028B4aF34FA5" +) +USDE_ARB_AUG2024_DEPLOYMENT_BLOCK = 197776131 -USDe_24OCT2024="0x39dAF77ad5514a9d3008313c2B8a37520C1F86D2" -USDe_24OCT2024_DEPLOYMENT_BLOCK=20326930 +USDe_24OCT2024 = Web3.to_checksum_address("0x39dAF77ad5514a9d3008313c2B8a37520C1F86D2") +USDe_24OCT2024_DEPLOYMENT_BLOCK = 20326930 -ENA_31OCT2024="0x0328C188287EaDA3E2E2151544d0226f800Eb9b5" -ENA_31OCT2024_DEPLOYMENT_BLOCK=20395113 +ENA_31OCT2024 = Web3.to_checksum_address("0x0328C188287EaDA3E2E2151544d0226f800Eb9b5") +ENA_31OCT2024_DEPLOYMENT_BLOCK = 20395113 -rsUSDe_26SEP2024="0x7F5955E5E36ABD98914c11E8c3Eff318CCc4eAF5" -rsUSDe_26SEP2024_DEPLOYMENT_BLOCK=20208513 +rsUSDe_26SEP2024 = Web3.to_checksum_address( + "0x7F5955E5E36ABD98914c11E8c3Eff318CCc4eAF5" +) +rsUSDe_26SEP2024_DEPLOYMENT_BLOCK = 20208513 -USDe_26DEC2024="0x6065c7870fF455fb9a78DD304579BdE2D7735703" -USDe_26DEC2024_DEPLOYMENT_BLOCK=20323985 +USDe_26DEC2024 = Web3.to_checksum_address("0x6065c7870fF455fb9a78DD304579BdE2D7735703") +USDe_26DEC2024_DEPLOYMENT_BLOCK = 20323985 -sUSDE_26DEC2024="0x590F0AB4c70686985D2C5a38859E0550445ACC20" -sUSDE_26DEC2024_DEPLOYMENT_BLOCK=20323930 +sUSDE_26DEC2024 = Web3.to_checksum_address("0x590F0AB4c70686985D2C5a38859E0550445ACC20") +sUSDE_26DEC2024_DEPLOYMENT_BLOCK = 20323930 -sUSDE_24OCT2024="0xaf09EE734B9B7157F371Ce984F67b1E87f8f2b2c" -sUSDE_24OCT2024_DEPLOYMENT_BLOCK=20326872 +sUSDE_24OCT2024 = Web3.to_checksum_address("0xaf09EE734B9B7157F371Ce984F67b1E87f8f2b2c") +sUSDE_24OCT2024_DEPLOYMENT_BLOCK = 20326872 -rsENA_26SEP2024="0x618e5ee4DD5BbD995883425B8AaC87dDCfb48Cf7" -rsENA_26SEP2024_DEPLOYMENT_BLOCK=20208485 +rsENA_26SEP2024 = Web3.to_checksum_address("0x618e5ee4DD5BbD995883425B8AaC87dDCfb48Cf7") +rsENA_26SEP2024_DEPLOYMENT_BLOCK = 20208485 -USDE_ARB_NOV2024="0x706f7F4cc144d6621E0c8798381575a8Cd1E0572" -USDE_ARB_NOV2024_DEPLOYMENT_BLOCK=242775302 \ No newline at end of file +USDE_ARB_NOV2024 = Web3.to_checksum_address( + "0x706f7F4cc144d6621E0c8798381575a8Cd1E0572" +) +USDE_ARB_NOV2024_DEPLOYMENT_BLOCK = 242775302 diff --git a/constants/radiant.py b/constants/radiant.py index 0cc9668..4c5e676 100644 --- a/constants/radiant.py +++ b/constants/radiant.py @@ -14,7 +14,7 @@ class RadiantLendingDetails(TypedDict): start: int - chain: str + chain: Chain collateral_address: str r_token_contract: Contract lending_pool: Contract diff --git a/constants/synthetix.py b/constants/synthetix.py index 212b617..e9cd15f 100644 --- a/constants/synthetix.py +++ b/constants/synthetix.py @@ -1,5 +1,13 @@ -SYNTHETIX_ARB_CORE_PROXY_ADDRESS = "0xffffffaEff0B96Ea8e4f94b2253f31abdD875847" -SYNTHETIX_ARB_CORE_ACCOUNT_PROXY_ADDRESS = "0x0E429603D3Cb1DFae4E6F52Add5fE82d96d77Dac" +from web3 import Web3 + +SYNTHETIX_ARB_CORE_PROXY_ADDRESS = Web3.to_checksum_address( + "0xffffffaEff0B96Ea8e4f94b2253f31abdD875847" +) +SYNTHETIX_ARB_CORE_ACCOUNT_PROXY_ADDRESS = Web3.to_checksum_address( + "0x0E429603D3Cb1DFae4E6F52Add5fE82d96d77Dac" +) SYNTHETIX_ARB_DEPLOYMENT_BLOCK = 218272801 -ARB_USDE_TOKEN_ADDRESS = "0x5d3a1Ff2b6BAb83b63cd9AD0787074081a52ef34" \ No newline at end of file +ARB_USDE_TOKEN_ADDRESS = Web3.to_checksum_address( + "0x5d3a1Ff2b6BAb83b63cd9AD0787074081a52ef34" +) diff --git a/integrations/allstake_susde.py b/integrations/allstake_susde.py index 3fc3059..a6aff73 100644 --- a/integrations/allstake_susde.py +++ b/integrations/allstake_susde.py @@ -7,7 +7,7 @@ integration = AllstakeIntegration(IntegrationID.ALLSTAKE_SUSDE) current_block = W3_BY_CHAIN[integration.chain]["w3"].eth.get_block_number() - participants = integration.get_participants() + participants = integration.get_participants(None) print("Get Participants:") print(participants) print("Get Balances of All Participants:") diff --git a/integrations/allstake_usde.py b/integrations/allstake_usde.py index 7445fe6..309cea0 100644 --- a/integrations/allstake_usde.py +++ b/integrations/allstake_usde.py @@ -7,7 +7,7 @@ integration = AllstakeIntegration(IntegrationID.ALLSTAKE_USDE) current_block = W3_BY_CHAIN[integration.chain]["w3"].eth.get_block_number() - participants = integration.get_participants() + participants = integration.get_participants(None) print("Get Participants:") print(participants) print("Get Balances of All Participants:") diff --git a/integrations/ambient_scroll.py b/integrations/ambient_scroll.py index 2ea5dcc..f83972f 100644 --- a/integrations/ambient_scroll.py +++ b/integrations/ambient_scroll.py @@ -22,12 +22,12 @@ def get_balance(self, user: str, block: int) -> float: Get the balance of a user at a given block """ url = f"{AMBIENT_SCROLL_API_URL}/sats/scroll/balance" - params = {"user": user, "block": block} - response = requests.get(url, params=params) + params = {"user": str(user), "block": str(block)} + response = requests.get(url, params=params) # type: ignore data = response.json() return data["data"] - def get_participants(self) -> list: + def get_participants(self, blocks: list[int] | None) -> set[str]: """ Get all participants of the protocol, ever. This function should only be called once and should cache the results by setting self.participants @@ -41,5 +41,5 @@ def get_participants(self) -> list: if __name__ == "__main__": # Simple tests for the integration ambient = Ambient() - print(ambient.get_participants()) - print(ambient.get_balance(list(ambient.get_participants())[2], 7372500)) + print(ambient.get_participants(None)) + print(ambient.get_balance(list(ambient.get_participants(None))[2], 7372500)) diff --git a/integrations/beefy_arbitrum_usde.py b/integrations/beefy_arbitrum_usde.py index 19ecd16..1c885e0 100644 --- a/integrations/beefy_arbitrum_usde.py +++ b/integrations/beefy_arbitrum_usde.py @@ -6,9 +6,9 @@ beefy_integration = BeefyIntegration( IntegrationID.BEEFY_ARBITRUM_USDE, 179921508, Chain.ARBITRUM ) - print(beefy_integration.get_participants()) + print(beefy_integration.get_participants(None)) print( beefy_integration.get_balance( - list(beefy_integration.get_participants())[0], 20000001 + list(beefy_integration.get_participants(None))[0], 20000001 ) ) diff --git a/integrations/beefy_fraxtal_usde.py b/integrations/beefy_fraxtal_usde.py index faae56a..a7bf160 100644 --- a/integrations/beefy_fraxtal_usde.py +++ b/integrations/beefy_fraxtal_usde.py @@ -6,9 +6,9 @@ beefy_integration = BeefyIntegration( IntegrationID.BEEFY_FRAXTAL_USDE, 2366784, Chain.FRAXTAL ) - print(beefy_integration.get_participants()) + print(beefy_integration.get_participants(None)) print( beefy_integration.get_balance( - list(beefy_integration.get_participants())[0], 2466784 + list(beefy_integration.get_participants(None))[0], 2466784 ) ) diff --git a/integrations/beefy_mantle_usde.py b/integrations/beefy_mantle_usde.py index 6325511..980b9be 100644 --- a/integrations/beefy_mantle_usde.py +++ b/integrations/beefy_mantle_usde.py @@ -6,9 +6,9 @@ beefy_integration = BeefyIntegration( IntegrationID.BEEFY_MANTLE_USDE, 66470986, Chain.MANTLE ) - print(beefy_integration.get_participants()) + print(beefy_integration.get_participants(None)) print( beefy_integration.get_balance( - list(beefy_integration.get_participants())[0], 66480986 + list(beefy_integration.get_participants(None))[0], 66480986 ) ) diff --git a/integrations/beefy_optimism_usde.py b/integrations/beefy_optimism_usde.py index 51cb5ab..c5b1c48 100644 --- a/integrations/beefy_optimism_usde.py +++ b/integrations/beefy_optimism_usde.py @@ -6,9 +6,9 @@ beefy_integration = BeefyIntegration( IntegrationID.BEEFY_OPTIMISM_USDE, 38082415, Chain.OPTIMISM ) - print(beefy_integration.get_participants()) + print(beefy_integration.get_participants(None)) print( beefy_integration.get_balance( - list(beefy_integration.get_participants())[0], 106819558 + list(beefy_integration.get_participants(None))[0], 106819558 ) ) diff --git a/integrations/equilibria_karak_susde_sept.py b/integrations/equilibria_karak_susde_sept.py index db22ae4..de55cfa 100644 --- a/integrations/equilibria_karak_susde_sept.py +++ b/integrations/equilibria_karak_susde_sept.py @@ -17,12 +17,12 @@ Chain.ETHEREUM, 20, 1, - [PENDLE_LOCKER_ETHEREUM], + {PENDLE_LOCKER_ETHEREUM}, ) - print(equilibria_integration.get_participants()) + print(equilibria_integration.get_participants(None)) print( equilibria_integration.get_balance( - list(equilibria_integration.get_participants())[0], "latest" + list(equilibria_integration.get_participants(None))[0] ) ) diff --git a/integrations/equilibria_karak_usde_sept.py b/integrations/equilibria_karak_usde_sept.py index 50549f5..67473df 100644 --- a/integrations/equilibria_karak_usde_sept.py +++ b/integrations/equilibria_karak_usde_sept.py @@ -17,12 +17,12 @@ Chain.ETHEREUM, 20, 1, - [PENDLE_LOCKER_ETHEREUM], + {PENDLE_LOCKER_ETHEREUM}, ) - print(equilibria_integration.get_participants()) + print(equilibria_integration.get_participants(None)) print( equilibria_integration.get_balance( - list(equilibria_integration.get_participants())[0], "latest" + list(equilibria_integration.get_participants(None))[0] ) ) diff --git a/integrations/equilibria_rusde_sept.py b/integrations/equilibria_rusde_sept.py index dddec51..a289b64 100644 --- a/integrations/equilibria_rusde_sept.py +++ b/integrations/equilibria_rusde_sept.py @@ -13,12 +13,12 @@ Chain.ETHEREUM, 20, 1, - [PENDLE_LOCKER_ETHEREUM], + {PENDLE_LOCKER_ETHEREUM}, ) - print(equilibria_integration.get_participants()) + print(equilibria_integration.get_participants(None)) print( equilibria_integration.get_balance( - list(equilibria_integration.get_participants())[0] + list(equilibria_integration.get_participants(None))[0] ) ) diff --git a/integrations/equilibria_susde_apr_expiry.py b/integrations/equilibria_susde_apr_expiry.py index a3a1ced..11ee7af 100644 --- a/integrations/equilibria_susde_apr_expiry.py +++ b/integrations/equilibria_susde_apr_expiry.py @@ -17,12 +17,12 @@ Chain.ETHEREUM, 20, 1, - [PENDLE_LOCKER_ETHEREUM], + {PENDLE_LOCKER_ETHEREUM}, ) - print(equilibria_integration.get_participants()) + print(equilibria_integration.get_participants(None)) print( equilibria_integration.get_balance( - list(equilibria_integration.get_participants())[0] + list(equilibria_integration.get_participants(None))[0] ) ) diff --git a/integrations/equilibria_susde_sept.py b/integrations/equilibria_susde_sept.py index 999bbd4..e4b47c7 100644 --- a/integrations/equilibria_susde_sept.py +++ b/integrations/equilibria_susde_sept.py @@ -13,12 +13,12 @@ Chain.ETHEREUM, 20, 1, - [PENDLE_LOCKER_ETHEREUM], + {PENDLE_LOCKER_ETHEREUM}, ) - print(equilibria_integration.get_participants()) + print(equilibria_integration.get_participants(None)) print( equilibria_integration.get_balance( - list(equilibria_integration.get_participants())[0] + list(equilibria_integration.get_participants(None))[0] ) ) diff --git a/integrations/equilibria_usde_expiry.py b/integrations/equilibria_usde_expiry.py index 2c98421..4797ec5 100644 --- a/integrations/equilibria_usde_expiry.py +++ b/integrations/equilibria_usde_expiry.py @@ -17,12 +17,12 @@ Chain.ETHEREUM, 20, 1, - [PENDLE_LOCKER_ETHEREUM], + {PENDLE_LOCKER_ETHEREUM}, ) - print(equilibria_integration.get_participants()) + print(equilibria_integration.get_participants(None)) print( equilibria_integration.get_balance( - list(equilibria_integration.get_participants())[0] + list(equilibria_integration.get_participants(None))[0] ) ) diff --git a/integrations/equilibria_zircuit_usde_aug.py b/integrations/equilibria_zircuit_usde_aug.py index 19973b6..be01e27 100644 --- a/integrations/equilibria_zircuit_usde_aug.py +++ b/integrations/equilibria_zircuit_usde_aug.py @@ -17,12 +17,12 @@ Chain.ETHEREUM, 20, 1, - [PENDLE_LOCKER_ETHEREUM], + {PENDLE_LOCKER_ETHEREUM}, ) - print(equilibria_integration.get_participants()) + print(equilibria_integration.get_participants(None)) print( equilibria_integration.get_balance( - list(equilibria_integration.get_participants())[0] + list(equilibria_integration.get_participants(None))[0] ) ) diff --git a/integrations/euler_susde.py b/integrations/euler_susde.py index a38b3f8..ff41513 100644 --- a/integrations/euler_susde.py +++ b/integrations/euler_susde.py @@ -47,11 +47,11 @@ def get_balance(self, user: str, block: int) -> float: return round(asset_balance / 1e18, 4) - def get_participants(self) -> list: + def get_participants(self, blocks: list[int] | None) -> set[str]: if self.participants is not None: return self.participants - all_users = set() + all_users: set[str] = set() start = self.start_block end = w3.eth.get_block_number() @@ -81,6 +81,6 @@ def get_participants(self) -> list: if __name__ == "__main__": example_integration = EulerIntegration() - participants = example_integration.get_participants() + participants = example_integration.get_participants(None) print(participants) - print(example_integration.get_balance(participants[0], 20677865)) + print(example_integration.get_balance(list(participants)[0], 20677865)) diff --git a/integrations/gmx_usde_usdc_aug.py b/integrations/gmx_usde_usdc_aug.py index 35fe7d6..75478a2 100644 --- a/integrations/gmx_usde_usdc_aug.py +++ b/integrations/gmx_usde_usdc_aug.py @@ -18,7 +18,7 @@ USDE_TOKEN_ADDRESS, USDC_TOKEN_ADDRESS, ) - print(gmx_integration.get_participants()) + print(gmx_integration.get_participants(None)) print( gmx_integration.get_balance( "0x8F091A33f310EFd8Ca31f7aE4362d6306cA6Ec8d", 237999816 diff --git a/integrations/gmx_wsteth_usde_aug.py b/integrations/gmx_wsteth_usde_aug.py index 3aa745b..4528074 100644 --- a/integrations/gmx_wsteth_usde_aug.py +++ b/integrations/gmx_wsteth_usde_aug.py @@ -18,7 +18,7 @@ WSTETH_TOKEN_ADDRESS, USDE_TOKEN_ADDRESS, ) - print(gmx_integration.get_participants()) + print(gmx_integration.get_participants(None)) print( gmx_integration.get_balance( "0x596CDbB0d4b74Cb5dCdf86613d8012E0cD3E522f", 238329658 diff --git a/integrations/integration.py b/integrations/integration.py index bcb6176..90b8fed 100644 --- a/integrations/integration.py +++ b/integrations/integration.py @@ -26,7 +26,7 @@ def __init__( self.integration_id = integration_id self.start_block = start_block self.end_block = end_block - self.participants = set() + self.participants: set[str] = set() self.chain = chain self.summary_cols = summary_cols self.reward_multiplier = reward_multiplier diff --git a/integrations/lyra_susde_bull.py b/integrations/lyra_susde_bull.py index 683f258..29ff44e 100644 --- a/integrations/lyra_susde_bull.py +++ b/integrations/lyra_susde_bull.py @@ -40,9 +40,9 @@ def get_balance(self, user: str, block: int) -> float: return get_effective_balance( user, block, - integration_token=self.vault_data["integration_token"], - bridge=self.vault_data["bridge"], - vault_token=self.vault_data["vault_token"], + integration_token=self.vault_data["integration_token"], # type: ignore + bridge=self.vault_data["bridge"], # type: ignore + vault_token=self.vault_data["vault_token"], # type: ignore timestamp=W3_BY_CHAIN[self.chain]["w3"].eth.get_block(block)[ "timestamp" ], @@ -58,8 +58,8 @@ def get_participants(self, blocks: list[int] | None) -> set[str]: if self.vault_data["detail_type"] == DetailType.Vault: self.participants = get_vault_users( start_block=self.start_block, - page_size=self.vault_data["page_size"], - vault_token=self.vault_data["vault_token"], + page_size=self.vault_data["page_size"], # type: ignore + vault_token=self.vault_data["vault_token"], # type: ignore chain=self.chain, ) else: diff --git a/integrations/merchantmoe_lbt_integration.py b/integrations/merchantmoe_lbt_integration.py index 76d9073..3ef8a9f 100644 --- a/integrations/merchantmoe_lbt_integration.py +++ b/integrations/merchantmoe_lbt_integration.py @@ -36,7 +36,7 @@ def __init__( self.lbt_contract = lbt_contract self.liquidity_helper_contract = liquidity_helper_contract - def get_balance(self, user: str, block: int) -> float: + def get_balance(self, user: str, block: int | str = "latest") -> float: active_id = call_with_retry(self.lbt_contract.functions.getActiveId(), block) # calculate the amount in bins for ids that are +/- 20% from active price @@ -99,7 +99,7 @@ def get_participants(self, blocks: list[int] | None) -> set[str]: logging.info(f"[{self.name}] {len(all_users)} users found") self.participants = all_users - return list(all_users) + return all_users if __name__ == "__main__": @@ -108,6 +108,6 @@ def get_participants(self, blocks: list[int] | None) -> set[str]: lb_pair_contract, liquidity_helper_contract, ) - participants = merchant_moe_integration.get_participants() + participants = merchant_moe_integration.get_participants(None) print(participants) - print(merchant_moe_integration.get_balance(list(participants)[1], "latest")) + print(merchant_moe_integration.get_balance(list(participants)[1])) diff --git a/integrations/nuri.py b/integrations/nuri.py index 379fb17..035c878 100644 --- a/integrations/nuri.py +++ b/integrations/nuri.py @@ -2,15 +2,13 @@ from integrations.integration_ids import IntegrationID from integrations.integration import Integration from constants.nuri import ( - NURI_NFP_MANAGER_ADDRESS, - NURI_POOL_ADDRESS, NURI_DEPLOYMENT_BLOCK, SCROLL_USDE_TOKEN_ADDRESS, ) from constants.summary_columns import SummaryColumn from utils.nuri import nfp_manager, pool from utils.web3_utils import w3_scroll, fetch_events_logs_with_retry, call_with_retry -from web3 import Web3 + import math @@ -120,7 +118,7 @@ def get_participants(self, blocks: list[int] | None) -> set[str]: start_block = NURI_DEPLOYMENT_BLOCK target_block = w3_scroll.eth.get_block_number() - all_users = set() + all_users: set[str] = set() while start_block < target_block: to_block = min(start_block + page_size, target_block) try: diff --git a/integrations/pendle_lpt_integration.py b/integrations/pendle_lpt_integration.py index fb4d464..4c05903 100644 --- a/integrations/pendle_lpt_integration.py +++ b/integrations/pendle_lpt_integration.py @@ -23,7 +23,7 @@ def __init__( sy_contract: Contract, lp_contract: Contract, get_participants_func: Callable[ - [[ChecksumAddress]], list # type: ignore + [list[ChecksumAddress]], set[str] ] = get_pendle_participants_v3, chain: Chain = Chain.ETHEREUM, summary_cols: list[SummaryColumn] | None = None, @@ -51,7 +51,7 @@ def __init__( def get_balance(self, user: str, block: int | str) -> float: logging.info( - f"[{self.get_description()}] Getting balance for {user} at block {block}" + f"[{self.integration_id.get_description()}] Getting balance for {user} at block {block}" ) sy_bal = call_with_retry( self.sy_contract.functions.balanceOf(self.lp_contract.address), @@ -103,6 +103,6 @@ def get_participants(self, blocks: list[int] | None) -> set[str]: pendle.lpt_contract, reward_multiplier=20, ) - participants = integration.get_participants() + participants = integration.get_participants(None) print(participants) print(integration.get_balance(list(participants)[0], "latest")) diff --git a/integrations/pendle_yt_integration.py b/integrations/pendle_yt_integration.py index bf345d8..aac5872 100644 --- a/integrations/pendle_yt_integration.py +++ b/integrations/pendle_yt_integration.py @@ -1,4 +1,4 @@ -from typing import Callable +from typing import Callable, List, Optional import logging from eth_typing import ChecksumAddress @@ -20,10 +20,10 @@ def __init__( start_block: int, yt_contract: Contract, get_participants_func: Callable[ - [[ChecksumAddress]], list # type: ignore + [list[ChecksumAddress]], set[str] ] = get_pendle_participants_v3, chain: Chain = Chain.ETHEREUM, - summary_cols: list[SummaryColumn] = None, + summary_cols: Optional[List[SummaryColumn]] = None, reward_multiplier: int = 1, balance_multiplier: int = 1, end_block: int | None = None, diff --git a/integrations/penpie_ena_aug.py b/integrations/penpie_ena_aug.py index c49cc00..27878cf 100644 --- a/integrations/penpie_ena_aug.py +++ b/integrations/penpie_ena_aug.py @@ -12,7 +12,7 @@ Chain.ETHEREUM, 30, 1, - [PENDLE_LOCKER_ETHEREUM], + {PENDLE_LOCKER_ETHEREUM}, ) # print(penpie_integration.get_participants()) print( diff --git a/integrations/penpie_ena_oct.py b/integrations/penpie_ena_oct.py index 1031c9f..0a02437 100644 --- a/integrations/penpie_ena_oct.py +++ b/integrations/penpie_ena_oct.py @@ -12,7 +12,7 @@ Chain.ETHEREUM, 30, 1, - [PENDLE_LOCKER_ETHEREUM], + {PENDLE_LOCKER_ETHEREUM}, ) # print(penpie_integration.get_participants()) print( diff --git a/integrations/penpie_karak_susde_sep.py b/integrations/penpie_karak_susde_sep.py index 803c65c..38d52ea 100644 --- a/integrations/penpie_karak_susde_sep.py +++ b/integrations/penpie_karak_susde_sep.py @@ -15,7 +15,7 @@ Chain.ETHEREUM, 5, 1, - [PENDLE_LOCKER_ETHEREUM], + {PENDLE_LOCKER_ETHEREUM}, ) # print(penpie_integration.get_participants()) print( diff --git a/integrations/penpie_karak_usde_sep.py b/integrations/penpie_karak_usde_sep.py index 81bcd7a..a445f69 100644 --- a/integrations/penpie_karak_usde_sep.py +++ b/integrations/penpie_karak_usde_sep.py @@ -15,7 +15,7 @@ Chain.ETHEREUM, 20, 1, - [PENDLE_LOCKER_ETHEREUM], + {PENDLE_LOCKER_ETHEREUM}, ) # print(penpie_integration.get_participants()) print( diff --git a/integrations/penpie_mellow_rsena_sep.py b/integrations/penpie_mellow_rsena_sep.py index 1440c2f..7042c28 100644 --- a/integrations/penpie_mellow_rsena_sep.py +++ b/integrations/penpie_mellow_rsena_sep.py @@ -12,7 +12,6 @@ Chain.ETHEREUM, 30, 1, - [PENDLE_LOCKER_ETHEREUM], + {PENDLE_LOCKER_ETHEREUM}, ) - print(penpie_integration.get_participants()) - # print(penpie_integration.get_balance("0x9EF171A8C62Eea6455830Bde5de99Db5A7cA5119", "latest")) + print(penpie_integration.get_participants(None)) diff --git a/integrations/penpie_mellow_rusde_sep.py b/integrations/penpie_mellow_rusde_sep.py index 663d75b..1118317 100644 --- a/integrations/penpie_mellow_rusde_sep.py +++ b/integrations/penpie_mellow_rusde_sep.py @@ -12,7 +12,6 @@ Chain.ETHEREUM, 10, 1, - [PENDLE_LOCKER_ETHEREUM], + {PENDLE_LOCKER_ETHEREUM}, ) - print(penpie_integration.get_participants()) - # print(penpie_integration.get_balance("0x404581FA706E4E0d649A40eA503f9bCee3D2d76c", "latest")) + print(penpie_integration.get_participants(None)) diff --git a/integrations/penpie_susde_25apr.py b/integrations/penpie_susde_25apr.py index ce6f955..d1ecda6 100644 --- a/integrations/penpie_susde_25apr.py +++ b/integrations/penpie_susde_25apr.py @@ -12,7 +12,7 @@ Chain.ETHEREUM, 20, 1, - [PENDLE_LOCKER_ETHEREUM], + {PENDLE_LOCKER_ETHEREUM}, ) # print(penpie_integration.get_participants()) print( diff --git a/integrations/penpie_susde_dec.py b/integrations/penpie_susde_dec.py index efab39e..2b6def1 100644 --- a/integrations/penpie_susde_dec.py +++ b/integrations/penpie_susde_dec.py @@ -12,7 +12,7 @@ Chain.ETHEREUM, 20, 1, - [PENDLE_LOCKER_ETHEREUM], + {PENDLE_LOCKER_ETHEREUM}, ) - print(penpie_integration.get_participants()) + print(penpie_integration.get_participants(None)) # print(penpie_integration.get_balance("0xe95176DF139a93D706655B32Df087a97e212B78E", "latest")) diff --git a/integrations/penpie_susde_july.py b/integrations/penpie_susde_july.py index 5c07a70..bc7c961 100644 --- a/integrations/penpie_susde_july.py +++ b/integrations/penpie_susde_july.py @@ -12,7 +12,7 @@ Chain.ETHEREUM, 20, 1, - [PENDLE_LOCKER_ETHEREUM], + {PENDLE_LOCKER_ETHEREUM}, ) # print(penpie_integration.get_participants()) print( diff --git a/integrations/penpie_susde_oct.py b/integrations/penpie_susde_oct.py index e6a977d..9b8b0dd 100644 --- a/integrations/penpie_susde_oct.py +++ b/integrations/penpie_susde_oct.py @@ -12,7 +12,7 @@ Chain.ETHEREUM, 20, 1, - [PENDLE_LOCKER_ETHEREUM], + {PENDLE_LOCKER_ETHEREUM}, ) - print(penpie_integration.get_participants()) + print(penpie_integration.get_participants(None)) # print(penpie_integration.get_balance("0xe95176DF139a93D706655B32Df087a97e212B78E", "latest")) diff --git a/integrations/penpie_susde_sep.py b/integrations/penpie_susde_sep.py index e8a468e..fa2bf7d 100644 --- a/integrations/penpie_susde_sep.py +++ b/integrations/penpie_susde_sep.py @@ -12,7 +12,7 @@ Chain.ETHEREUM, 20, 1, - [PENDLE_LOCKER_ETHEREUM], + {PENDLE_LOCKER_ETHEREUM}, ) # print(penpie_integration.get_participants()) print( diff --git a/integrations/penpie_usde_aug_Arb.py b/integrations/penpie_usde_aug_Arb.py index a788031..33fb497 100644 --- a/integrations/penpie_usde_aug_Arb.py +++ b/integrations/penpie_usde_aug_Arb.py @@ -12,7 +12,7 @@ Chain.ARBITRUM, 20, 1, - [PENDLE_LOCKER_ARBITRUM], + {PENDLE_LOCKER_ARBITRUM}, ) - print(penpie_integration.get_participants()) + print(penpie_integration.get_participants(None)) # print(penpie_integration.get_balance("0xe95176DF139a93D706655B32Df087a97e212B78E", "latest")) diff --git a/integrations/penpie_usde_dec.py b/integrations/penpie_usde_dec.py index 307910a..dcfb519 100644 --- a/integrations/penpie_usde_dec.py +++ b/integrations/penpie_usde_dec.py @@ -12,7 +12,7 @@ Chain.ETHEREUM, 25, 1, - [PENDLE_LOCKER_ETHEREUM], + {PENDLE_LOCKER_ETHEREUM}, ) # print(penpie_integration.get_participants()) print( diff --git a/integrations/penpie_usde_july.py b/integrations/penpie_usde_july.py index 303aa17..62052e3 100644 --- a/integrations/penpie_usde_july.py +++ b/integrations/penpie_usde_july.py @@ -12,7 +12,7 @@ Chain.ETHEREUM, 25, 1, - [PENDLE_LOCKER_ETHEREUM], + {PENDLE_LOCKER_ETHEREUM}, ) # print(penpie_integration.get_participants()) print(penpie_integration.get_balance("0x79E40Ab4BAc23E2910C03E2Fc24819fE498A9491")) diff --git a/integrations/penpie_usde_nov_arb.py b/integrations/penpie_usde_nov_arb.py index a0e7549..57d11f8 100644 --- a/integrations/penpie_usde_nov_arb.py +++ b/integrations/penpie_usde_nov_arb.py @@ -12,6 +12,6 @@ Chain.ARBITRUM, 20, 1, - [PENDLE_LOCKER_ARBITRUM], + {PENDLE_LOCKER_ARBITRUM}, ) print(penpie_integration.get_balance("0xe95176DF139a93D706655B32Df087a97e212B78E")) diff --git a/integrations/penpie_usde_oct.py b/integrations/penpie_usde_oct.py index efccd89..f443d7b 100644 --- a/integrations/penpie_usde_oct.py +++ b/integrations/penpie_usde_oct.py @@ -12,7 +12,7 @@ Chain.ETHEREUM, 25, 1, - [PENDLE_LOCKER_ETHEREUM], + {PENDLE_LOCKER_ETHEREUM}, ) # print(penpie_integration.get_participants()) print( diff --git a/integrations/penpie_zircuit_usde_jun.py b/integrations/penpie_zircuit_usde_jun.py index a77956f..b22b4b3 100644 --- a/integrations/penpie_zircuit_usde_jun.py +++ b/integrations/penpie_zircuit_usde_jun.py @@ -15,7 +15,7 @@ Chain.ETHEREUM, 25, 1, - [PENDLE_LOCKER_ETHEREUM], + {PENDLE_LOCKER_ETHEREUM}, ) # print(penpie_integration.get_participants()) print( diff --git a/integrations/radiant_usde.py b/integrations/radiant_usde.py index 22292fc..2dfebcb 100644 --- a/integrations/radiant_usde.py +++ b/integrations/radiant_usde.py @@ -23,7 +23,7 @@ def __init__(self, integration_id: IntegrationID): start_block=self.vault_data["start"], chain=self.vault_data["chain"], summary_cols=None, - page_size=20, + reward_multiplier=20, ) def get_balance(self, user: str, block: int) -> float: @@ -55,5 +55,5 @@ def get_participants(self, blocks: list[int] | None = None) -> set[str]: print("Found Radiant Participants:") participants = example_integration.get_participants(None) print(len(participants)) - print("Found Balance of First Participant:", participants[0]) - print(example_integration.get_balance(participants[0], current_block)) + print("Found Balance of First Participant:", list(participants)[0]) + print(example_integration.get_balance(list(participants)[0], current_block)) diff --git a/integrations/ramses.py b/integrations/ramses.py index 9939e68..559f732 100644 --- a/integrations/ramses.py +++ b/integrations/ramses.py @@ -116,7 +116,7 @@ def get_participants(self, blocks: list[int] | None = None) -> set[str]: start_block = RAMSES_DEPLOYMENT_BLOCK target_block = w3_arb.eth.get_block_number() - all_users = set() + all_users: set[str] = set() while start_block < target_block: to_block = min(start_block + page_size, target_block) try: diff --git a/integrations/rho_markets.py b/integrations/rho_markets.py index 6e7dd28..8baf9f9 100644 --- a/integrations/rho_markets.py +++ b/integrations/rho_markets.py @@ -3,8 +3,10 @@ if __name__ == "__main__": rho_markets = RhoMarkets() - participants = rho_markets.get_participants() + participants = rho_markets.get_participants(None) print(len(participants)) print( - rho_markets.get_balance(w3_scroll.to_checksum_address(participants[0]), 7751774) + rho_markets.get_balance( + w3_scroll.to_checksum_address(list(participants)[0]), 7751774 + ) ) diff --git a/integrations/splice_susde_lpt.py b/integrations/splice_susde_lpt.py index d4e20fc..aad5432 100644 --- a/integrations/splice_susde_lpt.py +++ b/integrations/splice_susde_lpt.py @@ -3,5 +3,7 @@ if __name__ == "__main__": integration = SpliceIntegration(IntegrationID.SPLICE_SUSDE_LPT) - print(integration.get_participants()) - print(integration.get_balance(list(integration.get_participants())[0], "latest")) + print(integration.get_participants(None)) + print( + integration.get_balance(list(integration.get_participants(None))[0], "latest") + ) diff --git a/integrations/splice_susde_yt.py b/integrations/splice_susde_yt.py index 5c7bed7..f0871a7 100644 --- a/integrations/splice_susde_yt.py +++ b/integrations/splice_susde_yt.py @@ -3,5 +3,7 @@ if __name__ == "__main__": integration = SpliceIntegration(IntegrationID.SPLICE_SUSDE_YT) - print(integration.get_participants()) - print(integration.get_balance(list(integration.get_participants())[0], "latest")) + print(integration.get_participants(None)) + print( + integration.get_balance(list(integration.get_participants(None))[0], "latest") + ) diff --git a/integrations/splice_usde_lpt.py b/integrations/splice_usde_lpt.py index 865bbba..fee66d9 100644 --- a/integrations/splice_usde_lpt.py +++ b/integrations/splice_usde_lpt.py @@ -3,5 +3,5 @@ if __name__ == "__main__": integration = SpliceIntegration(IntegrationID.SPLICE_USDE_LPT) - print(integration.get_participants()) - print(integration.get_balance(list(integration.get_participants())[0], "latest")) + print(integration.get_participants(None)) + print(integration.get_balance(list(integration.get_participants(None))[0])) diff --git a/integrations/splice_usde_yt.py b/integrations/splice_usde_yt.py index 9fc9cc6..f5c57b1 100644 --- a/integrations/splice_usde_yt.py +++ b/integrations/splice_usde_yt.py @@ -3,5 +3,5 @@ if __name__ == "__main__": integration = SpliceIntegration(IntegrationID.SPLICE_USDE_YT) - print(integration.get_participants()) - print(integration.get_balance(list(integration.get_participants())[0])) + print(integration.get_participants(None)) + print(integration.get_balance(list(integration.get_participants(None))[0])) diff --git a/integrations/stakedao_susde_july.py b/integrations/stakedao_susde_july.py index c7b8f3d..8092b7d 100644 --- a/integrations/stakedao_susde_july.py +++ b/integrations/stakedao_susde_july.py @@ -8,4 +8,4 @@ SUSDE_JULY_DEPLOYMENT_BLOCK, SUSDE_JULY, ) - print(stakedao_integration.get_participants()) + print(stakedao_integration.get_participants(None)) diff --git a/integrations/stakedao_susde_sept.py b/integrations/stakedao_susde_sept.py index ac6d4fc..4f3fb20 100644 --- a/integrations/stakedao_susde_sept.py +++ b/integrations/stakedao_susde_sept.py @@ -8,4 +8,4 @@ SUSDE_SEPT_DEPLOYMENT_BLOCK, SUSDE_SEPT, ) - print(stakedao_integration.get_participants()) + print(stakedao_integration.get_participants(None)) diff --git a/integrations/stakedao_usde_july.py b/integrations/stakedao_usde_july.py index 5db1567..9cc1aa9 100644 --- a/integrations/stakedao_usde_july.py +++ b/integrations/stakedao_usde_july.py @@ -8,4 +8,4 @@ USDE_JULY_DEPLOYMENT_BLOCK, USDE_JULY, ) - print(stakedao_integration.get_participants()) + print(stakedao_integration.get_participants(None)) diff --git a/integrations/synthetix.py b/integrations/synthetix.py index 34a36ca..394e5d0 100644 --- a/integrations/synthetix.py +++ b/integrations/synthetix.py @@ -46,12 +46,12 @@ def get_balance(self, user: str, block: int) -> float: total_balance += balance return total_balance / 1e18 - def get_participants(self) -> list: + def get_participants(self, blocks: list[int] | None) -> set[str]: page_size = 1900 start_block = SYNTHETIX_ARB_DEPLOYMENT_BLOCK target_block = w3_arb.eth.get_block_number() - all_users = set() + all_users: set[str] = set() while start_block < target_block: to_block = min(start_block + page_size, target_block) transfers = fetch_events_logs_with_retry( @@ -64,7 +64,6 @@ def get_participants(self) -> list: all_users.add(transfer["args"]["to"]) start_block += page_size - all_users = list(all_users) self.participants = all_users return all_users @@ -73,4 +72,4 @@ def get_participants(self) -> list: synthetix = Synthetix() participants = synthetix.get_participants(None) print(len(participants)) - print(synthetix.get_balance(participants[0], 227610000)) + print(synthetix.get_balance(list(participants)[0], 227610000)) diff --git a/integrations/template.py b/integrations/template.py index 8ef382a..e8236df 100644 --- a/integrations/template.py +++ b/integrations/template.py @@ -4,7 +4,7 @@ from integrations.cached_balances_integration import CachedBalancesIntegration from integrations.integration_ids import IntegrationID from web3 import Web3 -from web3_typing import ChecksumAddress +from eth_typing import ChecksumAddress class ProtocolNameIntegration( @@ -58,18 +58,16 @@ def get_block_balances( if __name__ == "__main__": # TODO: Write simple tests for the integration - example_integration = ( - ProtocolNameIntegration( - integration_id=IntegrationID.EXAMPLE, - start_block=20000000, - summary_cols=[SummaryColumn.TEMPLATE_PTS], - chain=Chain.ETHEREUM, - reward_multiplier=20, - excluded_addresses={ - Web3.to_checksum_address("0x0000000000000000000000000000000000000000") - }, - end_block=40000000, - ), + example_integration = ProtocolNameIntegration( + integration_id=IntegrationID.EXAMPLE, + start_block=20000000, + summary_cols=[SummaryColumn.TEMPLATE_PTS], + chain=Chain.ETHEREUM, + reward_multiplier=20, + excluded_addresses={ + Web3.to_checksum_address("0x0000000000000000000000000000000000000000") + }, + end_block=40000000, ) print( example_integration.get_block_balances( @@ -86,8 +84,14 @@ def get_block_balances( print( example_integration.get_block_balances( cached_data={ - 20000000: {"0x123": 100, "0x456": 200}, - 20000001: {"0x123": 101, "0x456": 201}, + 20000000: { + Web3.to_checksum_address("0x123"): 100, + Web3.to_checksum_address("0x456"): 200, + }, + 20000001: { + Web3.to_checksum_address("0x123"): 101, + Web3.to_checksum_address("0x456"): 201, + }, }, blocks=[20000002], ) diff --git a/integrations/term_susde.py b/integrations/term_susde.py index feabf3d..8ec9777 100644 --- a/integrations/term_susde.py +++ b/integrations/term_susde.py @@ -1,11 +1,10 @@ -from typing import List import requests from constants.chains import Chain from integrations.integration_ids import IntegrationID from constants.integration_token import Token from constants.summary_columns import SummaryColumn from integrations.integration import Integration - +from web3 import Web3 ############################################################################### # Integration helpers ######################################################### @@ -121,10 +120,10 @@ def __init__(self): url=term_finance_subgraph_url_mainnet, query=repo_lockers_query, ) - repo_lockers = [] + repo_lockers = set() if repo_lockers_response is not None: for result in repo_lockers_response["termRepos"]: - repo_lockers.append(result["termRepoLocker"]) + repo_lockers.add(Web3.to_checksum_address(result["termRepoLocker"])) super().__init__( integration_id=IntegrationID.TERM_SUSDE, start_block=16380765, @@ -160,7 +159,7 @@ def get_balance(self, user: str, block: int) -> float: return total_balance - def get_participants(self) -> list: + def get_participants(self, blocks: list[int] | None) -> set[str]: # Make two queries: one to get borrower repo collateral and one to get borrower bid collateral participants_results = fetch_data( url=term_finance_subgraph_url_mainnet, @@ -177,9 +176,9 @@ def get_participants(self) -> list: for result in participants_results["termBidCollaterals"]: participants.add(result["bid"]["bidder"]) else: - print(f"Failed to get participants") + print("Failed to get participants") - return list(participants) + return participants def get_id(self) -> IntegrationID: return self.integration_id @@ -196,33 +195,9 @@ def get_col_name(self) -> str: def get_chain(self) -> Chain: return self.chain - def get_summary_cols(self) -> list[SummaryColumn]: - return self.summary_cols - - def get_reward_multiplier(self, block: int) -> int: - if self.reward_multiplier_func is not None: - return self.reward_multiplier_func(block) - return self.reward_multiplier - - def get_balance_multiplier(self) -> int: - return self.balance_multiplier - - def get_start_block(self) -> int: - return self.start_block - - def get_end_block(self) -> int: - if self.end_block is None: - return ( - 2**31 - 1 - ) # if no end block is specified, return the maximum possible block number - return self.end_block - - def get_excluded_addresses(self) -> List[str]: - return self.excluded_addresses - def is_user_a_participant(self, user: str) -> bool: if self.participants is None: - self.get_participants() + self.get_participants(None) return user in self.participants @@ -232,9 +207,9 @@ def is_user_a_participant(self, user: str) -> bool: if __name__ == "__main__": example_integration = TermFinanceIntegration() - print(example_integration.get_participants()) + print(example_integration.get_participants(None)) print( example_integration.get_balance( - list(example_integration.get_participants())[0], 20169604 + list(example_integration.get_participants(None))[0], 20169604 ) ) diff --git a/integrations/velodrome_mode_usde.py b/integrations/velodrome_mode_usde.py index 17eb566..5b741b8 100644 --- a/integrations/velodrome_mode_usde.py +++ b/integrations/velodrome_mode_usde.py @@ -21,13 +21,13 @@ def __init__(self): def get_balance(self, user: str, block: int) -> float: return fetch_balance(user, block, USDE_MODE_TOKEN) - def get_participants(self) -> list: + def get_participants(self, blocks: list[int] | None) -> set[str]: self.participants = fetch_participants(USDE_MODE_TOKEN) return self.participants if __name__ == "__main__": velodrome_integration = VelodromeIntegration() - participants = velodrome_integration.get_participants() + participants = velodrome_integration.get_participants(None) print(participants) - print(velodrome_integration.get_balance(participants[0], 10100000)) + print(velodrome_integration.get_balance(list(participants)[0], 10100000)) diff --git a/utils/allstake.py b/utils/allstake.py index a243a10..b861add 100644 --- a/utils/allstake.py +++ b/utils/allstake.py @@ -75,9 +75,8 @@ def __init__(self, integration_id: IntegrationID): start_block=self.strategy_info["start"], chain=self.strategy_info["chain"], summary_cols=None, - page_size=20, + reward_multiplier=20, balance_multiplier=1, - reward_multiplier=None, ) def get_balance(self, user: str, block: int) -> float: diff --git a/utils/beefy.py b/utils/beefy.py index 10f856d..8189992 100644 --- a/utils/beefy.py +++ b/utils/beefy.py @@ -6,10 +6,10 @@ from constants.beefy import BEEFY_LRT_API_URL CHAIN_TO_API_URL_PREFIX = { - [Chain.ARBITRUM]: f"{BEEFY_LRT_API_URL}/api/v2/partner/ethena/arbitrum", - [Chain.FRAXTAL]: f"{BEEFY_LRT_API_URL}/api/v2/partner/ethena/fraxtal", - [Chain.MANTLE]: f"{BEEFY_LRT_API_URL}/api/v2/partner/ethena/mantle", - [Chain.OPTIMISM]: f"{BEEFY_LRT_API_URL}/api/v2/partner/ethena/optimism", + Chain.ARBITRUM: f"{BEEFY_LRT_API_URL}/api/v2/partner/ethena/arbitrum", + Chain.FRAXTAL: f"{BEEFY_LRT_API_URL}/api/v2/partner/ethena/fraxtal", + Chain.MANTLE: f"{BEEFY_LRT_API_URL}/api/v2/partner/ethena/mantle", + Chain.OPTIMISM: f"{BEEFY_LRT_API_URL}/api/v2/partner/ethena/optimism", } @@ -43,7 +43,7 @@ def get_balance(self, user: str, block: int) -> float: return float(data["effective_balance"]) - def get_participants(self) -> list: + def get_participants(self, blocks: list[int] | None) -> set[str]: """ Get all participants of the protocol, ever. This function should only be called once and should cache the results by setting self.participants diff --git a/utils/curve.py b/utils/curve.py index 8f28aa1..8b14984 100644 --- a/utils/curve.py +++ b/utils/curve.py @@ -111,7 +111,7 @@ def get_user_states(self, block: int) -> list: return states - def get_user_state(self, user: str, block: int) -> float: + def get_user_state(self, user: str, block: int) -> list: """ Retrieve the collateral balance for a user at a specific block. @@ -170,4 +170,4 @@ def get_participants(self, blocks: list[int] | None = None) -> set[str]: self.start_state.extend(all_users) self.last_indexed_block = current_block - return [user_info.address for user_info in self.start_state] + return {user_info.address for user_info in self.start_state} diff --git a/utils/equilibria.py b/utils/equilibria.py index fd7b11b..5ee1410 100644 --- a/utils/equilibria.py +++ b/utils/equilibria.py @@ -8,9 +8,10 @@ fetch_events_logs_with_retry, call_with_retry, w3, - w3_arb, ) -from typing import List +from typing import Optional, Set +from web3 import Web3 +from eth_typing import ChecksumAddress with open("abi/equilibria_deposit.json") as f: equilibria_deposit = json.load(f) @@ -32,20 +33,17 @@ def __init__( chain: Chain, reward_multiplier: int, balance_multiplier: int, - excluded_addresses: List[str], + excluded_addresses: Optional[Set[ChecksumAddress]] = None, ): super().__init__( - integration_id, - start_block, - chain, - None, - reward_multiplier, - balance_multiplier, - excluded_addresses, - None, - None, + integration_id=integration_id, + start_block=start_block, + chain=chain, + reward_multiplier=reward_multiplier, + balance_multiplier=balance_multiplier, + excluded_addresses=excluded_addresses, ) - self.lp_contract = lp_contract + self.lp_contract = Web3.to_checksum_address(lp_contract) self.lp_contract_id = lp_contract_id def get_balance(self, user: str, block: int | str = "latest") -> float: @@ -129,14 +127,14 @@ def get_balance(self, user: str, block: int | str = "latest") -> float: print("-------------------------------------------------") return userShare * lockerSyBalance / 100 - def get_participants(self) -> list: + def get_participants(self, blocks: list[int] | None) -> set[str]: if self.participants is not None: return self.participants self.participants = self.get_equilibria_participants() return self.participants - def get_equilibria_participants(self): + def get_equilibria_participants(self) -> set[str]: all_users = set() start = self.start_block diff --git a/utils/firm.py b/utils/firm.py index b55f2f4..70d7c66 100644 --- a/utils/firm.py +++ b/utils/firm.py @@ -1,4 +1,5 @@ import json +from web3 import Web3 from utils.web3_utils import ( w3, ) @@ -18,5 +19,9 @@ def get_escrow_contract(user_address: str): - escrow_address = firm_susde_market_contract.functions.escrows(user_address) - return w3.eth.contract(address=escrow_address, abi=firm_simple_escrow_abi) + escrow_address: str = firm_susde_market_contract.functions.escrows( + user_address + ).call() + return w3.eth.contract( + address=Web3.to_checksum_address(escrow_address), abi=firm_simple_escrow_abi + ) diff --git a/utils/gmx.py b/utils/gmx.py index bc4788c..dccad49 100644 --- a/utils/gmx.py +++ b/utils/gmx.py @@ -1,10 +1,12 @@ import json +from typing import List, Optional, Set import requests from constants.chains import Chain from integrations.integration_ids import IntegrationID -from models.integration import Integration +from integrations.integration import Integration from constants.summary_columns import SummaryColumn from utils.web3_utils import w3_arb, fetch_events_logs_with_retry, call_with_retry +from web3.contract import Contract from constants.gmx import ( GMX_SYNTHETICS_READER_CONTRACT_ADDRESS, @@ -42,7 +44,7 @@ def makePriceTuple(prices, token): ) -def getContract(contract_address): +def getContract(contract_address) -> Optional[Contract]: if contract_address == GMX_USDE_USDC_MARKET_ADDRESS: return gmx_usde_usdc_market_contract elif contract_address == GMX_WSTETH_USDE_MARKET_ADDRESS: @@ -106,6 +108,8 @@ def get_balance(self, user: str, block: int) -> float: ) ) + if self.market_contract is None: + return 0 user_token_balance = call_with_retry( self.market_contract.functions.balanceOf(user), block, @@ -116,7 +120,10 @@ def get_balance(self, user: str, block: int) -> float: return gm_token_price * user_token_balance / oracle_price_decimals - def get_participants(self) -> list: + def get_participants( + self, + blocks: Optional[List[int]], + ) -> Set[str]: if self.participants is not None: return self.participants @@ -124,7 +131,7 @@ def get_participants(self) -> list: start_block = self.start_block target_block = w3_arb.eth.get_block_number() - all_users = set() + all_users: set[str] = set() while start_block < target_block: to_block = min(start_block + page_size, target_block) transfers = fetch_events_logs_with_retry( diff --git a/utils/hyperdrive.py b/utils/hyperdrive.py index c25767b..2042c5c 100644 --- a/utils/hyperdrive.py +++ b/utils/hyperdrive.py @@ -14,10 +14,10 @@ def get_first_contract_block(contract_address): # do binary search up to latest block - latest_block = w3.eth.get_block_number() - earliest_block = 0 + latest_block: int = w3.eth.get_block_number() + earliest_block: int = 0 while earliest_block < latest_block: - mid_block = (earliest_block + latest_block) // 2 + mid_block: int = (earliest_block + latest_block) // 2 attempt_to_get_code = w3.eth.get_code( account=contract_address, block_identifier=mid_block ) @@ -36,9 +36,9 @@ def get_first_contract_block(contract_address): def get_hyperdrive_participants(pool, start_block=None): - target_block = w3.eth.get_block_number() - all_users = set() - all_ids = set() + target_block: int = w3.eth.get_block_number() + all_users: set[str] = set() + all_ids: set[int] = set() start_block = start_block or get_first_contract_block(pool) assert all_users is not None, "error: all_users is None" assert all_ids is not None, "error: all_ids is None" diff --git a/utils/lendle.py b/utils/lendle.py index 13c0f1c..fe99d33 100644 --- a/utils/lendle.py +++ b/utils/lendle.py @@ -1,4 +1,6 @@ import json +from web3.contract import Contract +from web3 import Web3 from utils.web3_utils import ( w3_mantle, ) @@ -9,5 +11,6 @@ erc20_abi = json.load(f) -lendle_usde_contract = w3_mantle.eth.contract(address=LENDLE_USDE_TOKEN, abi=erc20_abi) - +lendle_usde_contract: Contract = w3_mantle.eth.contract( + address=Web3.to_checksum_address(LENDLE_USDE_TOKEN), abi=erc20_abi +) diff --git a/utils/lyra.py b/utils/lyra.py index 851a915..977b88d 100644 --- a/utils/lyra.py +++ b/utils/lyra.py @@ -10,10 +10,12 @@ from constants.chains import Chain from web3 import Web3 -url = 'https://app.sentio.xyz/api/v1/graphql/derive/v2_subgraph' -SUSDE_VAULT_ADDRESS = "0x0b4eD379da8eF4FCF06F697c5782CA7b4c3E505E" +url = "https://app.sentio.xyz/api/v1/graphql/derive/v2_subgraph" +SUSDE_VAULT_ADDRESS = Web3.to_checksum_address( + "0x0b4eD379da8eF4FCF06F697c5782CA7b4c3E505E" +) -user_balance_query = ''' +user_balance_query = """ { accounts(where: {or: [{id: "{user}"}, {owner: "{user}"}]}, block: {number: {block}}) { id @@ -32,64 +34,85 @@ } } } -''' +""" -def get_exchange_balance(user: str, block: int) -> int: +def get_exchange_balance(user: str, block: int) -> float: user = user.lower() # Replace the user and block placeholders in the query - user_balance_query_filled = user_balance_query.replace("{user}", user).replace("{block}", str(block)) + user_balance_query_filled = user_balance_query.replace("{user}", user).replace( + "{block}", str(block) + ) headers = { - 'Content-Type': 'application/json', - 'api-key': os.getenv("DERIVE_SUBGRAPH_API_KEY") + "Content-Type": "application/json", + "api-key": str(os.getenv("DERIVE_SUBGRAPH_API_KEY", "")), } print(user_balance_query_filled) # Send the POST request - response = requests.post(url, json={'query': user_balance_query_filled}, headers=headers) + response = requests.post( + url, json={"query": user_balance_query_filled}, headers=headers + ) - total_balance = 0 + total_balance = 0.0 if response.status_code == 200: response_json = response.json() - accounts = response_json['data']['accounts'] + accounts = response_json["data"]["accounts"] for account in accounts: - for subaccount in account['subaccounts']: - for balance in subaccount['balances']: - total_balance += float(balance['balance']) - for subaccount in account['depositedSubaccounts']: - for balance in subaccount['balances']: - total_balance += float(balance['balance']) + for subaccount in account["subaccounts"]: + for balance in subaccount["balances"]: + total_balance += float(balance["balance"]) + for subaccount in account["depositedSubaccounts"]: + for balance in subaccount["balances"]: + total_balance += float(balance["balance"]) else: print(f"Query failed with status code {response.status_code}: {response.text}") return total_balance -def get_effective_balance(user: str, block: int, integration_token: Contract, bridge: Contract, vault_token: Contract, timestamp): + +def get_effective_balance( + user: str, + block: int, + integration_token: Contract, + bridge: Contract, + vault_token: Contract, + timestamp, +): """ Since vault tokens can be transferred, calculates the portion of totalSupply() of the vault held by user. User's effective ethena integration token balance = (vault.balanceOf(user) / vault.totalSupply()) * total bridge balance """ - user_vault_token_balance = call_with_retry(vault_token.functions.balanceOf(user), block) + user_vault_token_balance = call_with_retry( + vault_token.functions.balanceOf(user), block + ) - headers = { - 'Content-Type': 'application/json' - } + headers = {"Content-Type": "application/json"} # Send the POST request - response = requests.post("https://api.lyra.finance/public/get_vault_share", json={'from_timestamp_sec': 0, 'to_timestamp_sec': timestamp, 'vault_name': 'sUSDePrincipal Protected Bull Call Spread', 'page_size': 1}, headers=headers) + response = requests.post( + "https://api.lyra.finance/public/get_vault_share", + json={ + "from_timestamp_sec": 0, + "to_timestamp_sec": timestamp, + "vault_name": "sUSDePrincipal Protected Bull Call Spread", + "page_size": 1, + }, + headers=headers, + ) try: response_json = response.json() - vault_price = float(response_json['result']['vault_shares'][0]["base_value"]) - except: + vault_price = float(response_json["result"]["vault_shares"][0]["base_value"]) + except: print("Failed to get vault price, using default") vault_price = float(1) - return user_vault_token_balance * vault_price /1e18 + return user_vault_token_balance * vault_price / 1e18 -all_users_query = ''' +all_users_query = """ { subAccountBalances(where: {asset: "0x375804cdcf0d534fdd2657584a7c4ff5ab14a2bb000000000000000000000000"}) { subaccount { @@ -105,42 +128,62 @@ def get_effective_balance(user: str, block: int, integration_token: Contract, br } } } -''' +""" + def get_exchange_users() -> set: headers = { - 'Content-Type': 'application/json', - 'api-key': os.getenv("DERIVE_SUBGRAPH_API_KEY") + "Content-Type": "application/json", + "api-key": str(os.getenv("DERIVE_SUBGRAPH_API_KEY", "")), } - response = requests.post(url, json={'query': all_users_query}, headers=headers) + response = requests.post(url, json={"query": all_users_query}, headers=headers) users = set() if response.status_code == 200: response_json = response.json() - balances = response_json['data']['subAccountBalances'] + balances = response_json["data"]["subAccountBalances"] for balance in balances: - if balance['subaccount']['matchingOwner'] is not None: - if balance['subaccount']['matchingOwner']['owner'] is not None: - users.add(Web3.to_checksum_address(balance['subaccount']['matchingOwner']['owner'])) + if balance["subaccount"]["matchingOwner"] is not None: + if balance["subaccount"]["matchingOwner"]["owner"] is not None: + users.add( + Web3.to_checksum_address( + balance["subaccount"]["matchingOwner"]["owner"] + ) + ) else: - users.add(Web3.to_checksum_address(balance['subaccount']['matchingOwner']['id'])) + users.add( + Web3.to_checksum_address( + balance["subaccount"]["matchingOwner"]["id"] + ) + ) else: - if balance['subaccount']['owner']['owner'] is not None: - users.add(Web3.to_checksum_address(balance['subaccount']['owner']['owner'])) + if balance["subaccount"]["owner"]["owner"] is not None: + users.add( + Web3.to_checksum_address( + balance["subaccount"]["owner"]["owner"] + ) + ) else: - users.add(Web3.to_checksum_address(balance['subaccount']['owner']['id'])) + users.add( + Web3.to_checksum_address(balance["subaccount"]["owner"]["id"]) + ) else: print(f"Query failed with status code {response.status_code}: {response.text}") try: - users.remove(SUSDE_VAULT_ADDRESS) # Ignore the sUSDe vault which is accounted for separately + users.remove( + SUSDE_VAULT_ADDRESS + ) # Ignore the sUSDe vault which is accounted for separately except: pass return users -def get_vault_users(start_block: int, page_size: int, vault_token: Contract, chain: Chain): + +def get_vault_users( + start_block: int, page_size: int, vault_token: Contract, chain: Chain +): """ Gets all participants that have ever interacted with the vault token by fetching all vault transfer events. diff --git a/utils/nuri.py b/utils/nuri.py index cc29084..340565e 100644 --- a/utils/nuri.py +++ b/utils/nuri.py @@ -1,6 +1,4 @@ -import os import json -from dotenv import load_dotenv from utils.web3_utils import ( w3_scroll, ) @@ -18,7 +16,4 @@ address=NURI_NFP_MANAGER_ADDRESS, abi=nfp_manager_abi ) -pool = w3_scroll.eth.contract( - address=NURI_POOL_ADDRESS, abi=pool_abi -) - +pool = w3_scroll.eth.contract(address=NURI_POOL_ADDRESS, abi=pool_abi) diff --git a/utils/pendle.py b/utils/pendle.py index 0719b09..a404758 100644 --- a/utils/pendle.py +++ b/utils/pendle.py @@ -1,5 +1,6 @@ import os import json +from typing import Any, Dict from dotenv import load_dotenv from utils.web3_utils import ( W3_BY_CHAIN, @@ -9,6 +10,8 @@ w3_arb, ) from constants.chains import Chain +from web3.contract import Contract + from constants.pendle import ( LPT, @@ -129,7 +132,7 @@ usde_arb_SY_contract = w3_arb.eth.contract(address=usde_arb_SY, abi=erc20_abi) usde_arb_YT_contract = w3_arb.eth.contract(address=usde_arb_YT, abi=erc20_abi) -PENDLE_CONTRACT_AND_START_BY_LP_TOKEN = { +PENDLE_CONTRACT_AND_START_BY_LP_TOKEN: Dict[str, Dict[str, Any]] = { SY: { "start": PENDLE_USDE_JULY_DEPLOYMENT_BLOCK, "contract": sy_contract, @@ -329,8 +332,10 @@ def get_pendle_participants_v3(token_addresses): token_data = PENDLE_CONTRACT_AND_START_BY_LP_TOKEN[token] if not token_data: continue - start = token_data["start"] - contract = token_data["contract"] + start: int = token_data["start"] + if start is None: + continue + contract: Contract = token_data["contract"] chain = token_data["chain"] web3_for_token = W3_BY_CHAIN[chain]["w3"] page_size = 1900 diff --git a/utils/penpie.py b/utils/penpie.py index 132c8ea..c74ffba 100644 --- a/utils/penpie.py +++ b/utils/penpie.py @@ -13,7 +13,9 @@ w3, w3_arb, ) -from typing import List +from typing import Optional, Set +from web3.contract import Contract +from eth_typing import ChecksumAddress with open("abi/penpie_master.json") as f: master_penpie = json.load(f) @@ -34,18 +36,15 @@ def __init__( chain: Chain, reward_multiplier: int, balance_multiplier: int, - excluded_addresses: List[str], + excluded_addresses: Optional[Set[ChecksumAddress]] = None, ): super().__init__( - integration_id, - start_block, - chain, - None, - reward_multiplier, - balance_multiplier, - excluded_addresses, - None, - None, + integration_id=integration_id, + start_block=start_block, + chain=chain, + reward_multiplier=reward_multiplier, + balance_multiplier=balance_multiplier, + excluded_addresses=excluded_addresses, ) self.lp_contract = lp_contract @@ -142,11 +141,10 @@ def get_balance(self, user: str, block: int | str = "latest") -> float: print(user, userShare * lpt_bal / 100) return userShare * lockerSyBalance / 100 - def get_participants(self) -> list: + def get_participants(self, blocks: list[int] | None) -> set[str]: if self.participants is not None: return self.participants - # logging.info(f"[{self.get_description()}] Getting participants...") self.participants = self.get_penpie_participants() logging.info( f"[{self.get_description()}] Found {len(self.participants)} participants" @@ -155,17 +153,25 @@ def get_participants(self) -> list: def get_penpie_participants(self): all_users = set() - start = self.start_block + if self.chain == Chain.ETHEREUM: - contract = w3.eth.contract(address=self.lp_contract, abi=erc20_abi) - if self.chain == Chain.ARBITRUM: - contract = w3_arb.eth.contract(address=self.lp_contract, abi=erc20_abi) + contract = w3.eth.contract( + address=w3.to_checksum_address(self.lp_contract), abi=erc20_abi + ) + elif self.chain == Chain.ARBITRUM: + contract = w3_arb.eth.contract( + address=w3_arb.to_checksum_address(self.lp_contract), abi=erc20_abi + ) + else: + return set() page_size = 1900 if self.chain == Chain.ETHEREUM: target_block = w3.eth.get_block_number() - if self.chain == Chain.ARBITRUM: + elif self.chain == Chain.ARBITRUM: target_block = w3_arb.eth.get_block_number() + else: + return set() while start < target_block: to_block = min(start + page_size, target_block) deposits = fetch_events_logs_with_retry( diff --git a/utils/rho_markets.py b/utils/rho_markets.py index 28a4288..a3b7323 100644 --- a/utils/rho_markets.py +++ b/utils/rho_markets.py @@ -44,8 +44,8 @@ def get_balance(self, user: str, block: int) -> float: ) return balance * exchangeRate / (1e18 * 1e18) - def get_participants(self) -> list: - all_users = set() + def get_participants(self, blocks: list[int] | None) -> set[str]: + all_users: set[str] = set() try: users = self.fetch_compound_users("rUSDe") for user in users: diff --git a/utils/slack.py b/utils/slack.py index a58f142..7fd6909 100644 --- a/utils/slack.py +++ b/utils/slack.py @@ -5,12 +5,13 @@ load_dotenv() + def slack_message(message: str): response = requests.post( - os.getenv("SLACK_WEBHOOK"), + os.getenv("SLACK_WEBHOOK", ""), json={ "text": message, }, timeout=60, ) - logging.info(f"Slack response: {response}") \ No newline at end of file + logging.info(f"Slack response: {response}") diff --git a/utils/splice.py b/utils/splice.py index 1183b88..9456086 100644 --- a/utils/splice.py +++ b/utils/splice.py @@ -1,5 +1,6 @@ import json import logging +from typing import Callable from utils.web3_utils import W3_BY_CHAIN, call_with_retry, fetch_events_logs_with_retry from web3.contract import Contract @@ -19,7 +20,7 @@ SUSDE_DEPLOYMENT_BLOCK, ) -w3 = W3_BY_CHAIN["mode"]["w3"] +w3 = W3_BY_CHAIN[Chain.MODE]["w3"] ######################################################################## @@ -116,7 +117,7 @@ def get_splice_participants_v3(token_addresses, start: int): # Configs ######################################################################## -config = { +config: dict[IntegrationID, dict] = { IntegrationID.SPLICE_USDE_YT: { "chain": Chain.MODE, "start_block": USDE_DEPLOYMENT_BLOCK, @@ -166,14 +167,12 @@ def get_splice_participants_v3(token_addresses, start: int): class SpliceIntegration(Integration): def __init__(self, integration_id: IntegrationID): super().__init__( - integration_id, - config[integration_id]["start_block"], - config[integration_id]["chain"], - None, # SummaryColumn - config[integration_id]["sats_multiplier"], # SATS multiplier - 1, - config[integration_id]["end_block"], - None, # reward multiplier fn + integration_id=integration_id, + start_block=config[integration_id]["start_block"], + chain=config[integration_id]["chain"], + reward_multiplier=config[integration_id]["sats_multiplier"], + balance_multiplier=1, + end_block=config[integration_id]["end_block"], ) self.token_addresses = config[integration_id]["token_addresses"] self.get_balance_func = config[integration_id]["get_balance_func"] @@ -181,13 +180,13 @@ def __init__(self, integration_id: IntegrationID): def get_description(self): return self.integration_id.get_description() - def get_balance(self, user: str, block: int | str) -> float: + def get_balance(self, user: str, block: int | str = "latest") -> float: logging.info( f"[{self.get_description()}] Getting balance for {user} at block {block}" ) - return self.get_balance_func(user, block) + return self.get_balance_func(user, block) # type: ignore - def get_participants(self) -> list: + def get_participants(self, blocks: list[int] | None) -> set[str]: if self.participants is not None: return self.participants logging.info(f"[{self.get_description()}] Getting participants...") diff --git a/utils/stakedao.py b/utils/stakedao.py index e194245..69378fa 100644 --- a/utils/stakedao.py +++ b/utils/stakedao.py @@ -9,7 +9,9 @@ call_with_retry, w3, ) -from typing import List +from typing import Optional, Set +from eth_typing import ChecksumAddress +from web3 import Web3 with open("abi/stakedao_vault.json") as f: vault_abi = json.load(f) @@ -28,18 +30,19 @@ def __init__( chain: Chain = Chain.ETHEREUM, reward_multiplier: int = 20, balance_multiplier: int = 1, - excluded_addresses: List[str] = [PENDLE_LOCKER], + excluded_addresses: Optional[Set[ChecksumAddress]] = { + Web3.to_checksum_address(PENDLE_LOCKER), + }, ): super().__init__( - integration_id, - start_block, - chain, - None, - reward_multiplier, + integration_id=integration_id, + start_block=start_block, + chain=chain, + reward_multiplier=reward_multiplier, balance_multiplier=balance_multiplier, excluded_addresses=excluded_addresses, ) - self.lp_contract = lp_contract + self.lp_contract = Web3.to_checksum_address(lp_contract) def get_balance(self, user: str, block: int) -> float: @@ -117,7 +120,7 @@ def get_balance(self, user: str, block: int) -> float: print(user, userShare * lockerSyBalance / 100) return userShare * lockerSyBalance / 100 - def get_participants(self) -> list: + def get_participants(self, blocks: list[int] | None) -> set[str]: if self.participants is not None: return self.participants diff --git a/utils/velodrome.py b/utils/velodrome.py index aa0ee46..0553c9e 100644 --- a/utils/velodrome.py +++ b/utils/velodrome.py @@ -1,24 +1,28 @@ -import os import json -from dotenv import load_dotenv from utils.web3_utils import ( w3_mode, fetch_events_logs_with_retry, call_with_retry, ) - -from constants.velodrome import VELODROME_MODE_SUGAR_ADDRESS, PAGE_SIZE, VELODROME_MODE_START_BLOCK +from web3 import Web3 +from constants.velodrome import ( + VELODROME_MODE_SUGAR_ADDRESS, + PAGE_SIZE, + VELODROME_MODE_START_BLOCK, +) with open("abi/velodrome_sugar.json") as f: sugar_abi = json.load(f) with open("abi/velodrome_pool.json") as f: - pool_abi = json.load(f) + pool_abi = json.load(f) sugar_contract = w3_mode.eth.contract( - address=VELODROME_MODE_SUGAR_ADDRESS, abi=sugar_abi + address=Web3.to_checksum_address(VELODROME_MODE_SUGAR_ADDRESS), + abi=sugar_abi, ) + def fetch_pools(block): total_pools = [] offset = 0 @@ -31,7 +35,7 @@ def fetch_pools(block): ) total_pools.extend(pools) - + if len(pools) < PAGE_SIZE: break @@ -39,6 +43,7 @@ def fetch_pools(block): return total_pools + def fetch_participants(token): latest_block = w3_mode.eth.get_block_number() all_pools = fetch_pools(latest_block) @@ -61,9 +66,9 @@ def fetch_participants(token): for lp in lps: participants.add(lp["args"]["to"]) - participants = list(participants) return participants + def fetch_balance(user, block, token): all_pools = fetch_pools(block) total_pools_size = len(all_pools) diff --git a/utils/web3_utils.py b/utils/web3_utils.py index bf192b9..635ca46 100644 --- a/utils/web3_utils.py +++ b/utils/web3_utils.py @@ -2,11 +2,13 @@ import os import time import traceback +from typing import Union, Literal from dotenv import load_dotenv from eth_abi.abi import decode from web3 import Web3 +from web3.types import HexStr, HexBytes, BlockIdentifier from utils.slack import slack_message from constants.chains import Chain @@ -89,10 +91,10 @@ def fetch_events_logs_with_retry( label: str, contract_event, from_block: int, - to_block: int = "latest", + to_block: int | str = "latest", retries: int = 3, delay: int = 2, - filter: dict = None, + filter: dict | None = None, ) -> dict: for attempt in range(retries): try: @@ -109,6 +111,7 @@ def fetch_events_logs_with_retry( logging.error(msg) slack_message(msg) raise e + return {} def call_with_retry(contract_function, block="latest", retries=3, delay=2): @@ -126,8 +129,10 @@ def call_with_retry(contract_function, block="latest", retries=3, delay=2): raise e -def multicall(w3: Web3, calls: list, block_identifier: int | str = "latest"): - multicall_contract = w3.eth.contract(address=MULTICALL_ADDRESS, abi=MULTICALL_ABI) +def multicall(w3: Web3, calls: list, block_identifier: BlockIdentifier = "latest"): + multicall_contract = w3.eth.contract( + address=Web3.to_checksum_address(MULTICALL_ADDRESS), abi=MULTICALL_ABI + ) aggregate_calls = [] for call in calls: From 634a1efc0cc20d5f449e7e32459f66bda8fc00e6 Mon Sep 17 00:00:00 2001 From: FJ-Riveros Date: Tue, 19 Nov 2024 20:15:44 +0100 Subject: [PATCH 11/16] chore: remaining lint issues --- integrations/integration.py | 3 +-- integrations/template.py | 3 ++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/integrations/integration.py b/integrations/integration.py index 90b8fed..a17048d 100644 --- a/integrations/integration.py +++ b/integrations/integration.py @@ -48,7 +48,6 @@ def get_participants( # either get_participants OR get_block_balances must be implemented def get_block_balances( - self, - blocks: List[int], + self, cached_data: Dict[int, Dict[ChecksumAddress, float]], blocks: List[int] ) -> Dict[int, Dict[str, float]]: raise NotImplementedError diff --git a/integrations/template.py b/integrations/template.py index e8236df..e26e837 100644 --- a/integrations/template.py +++ b/integrations/template.py @@ -53,7 +53,8 @@ def get_block_balances( where each inner dictionary maps user addresses to their token balance at that block. """ - pass + # TODO: Implement your logic here + return {} if __name__ == "__main__": From 636565ae9cbc88472e4d4fd1f7ebc011c6111901 Mon Sep 17 00:00:00 2001 From: FJ-Riveros Date: Tue, 19 Nov 2024 20:28:07 +0100 Subject: [PATCH 12/16] chore: minor tweaks --- integrations/hyperdrive.py | 4 ++-- requirements.txt | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/integrations/hyperdrive.py b/integrations/hyperdrive.py index fa167d3..9808d75 100644 --- a/integrations/hyperdrive.py +++ b/integrations/hyperdrive.py @@ -37,9 +37,9 @@ def update_participants(self): start_block=HYPERDRIVE_SUSDE_POOL_DEPLOYMENT_BLOCK, ) - def get_participants(self): + def get_participants(self, blocks: list[int] | None) -> set[str]: self.update_participants() - return self.pool_users + return self.pool_users # type: ignore def get_balance(self, user: str, block: int) -> float: # update hyperdrive participants diff --git a/requirements.txt b/requirements.txt index bccc01a..bf1b473 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,3 +4,4 @@ python-dotenv~=1.0.0 requests==2.32.0 tqdm~=4.66.4 rich==13.7.1 +types-requests==2.31.0.6 From bcfceb382f815dda18ae5b7373b6683c4cb3d2a4 Mon Sep 17 00:00:00 2001 From: FJ-Riveros Date: Tue, 19 Nov 2024 23:06:45 +0100 Subject: [PATCH 13/16] feat: add cached balances examples & minor tweaks --- campaign/campaign.py | 27 ++++- constants/example_integrations.py | 16 +++ constants/summary_columns.py | 7 ++ ...eefy_cached_balance_example_integration.py | 112 ++++++++++++++++++ integrations/cached_balances_integration.py | 2 +- .../claimed_ena_example_integration.py | 109 +++++++++++++++++ integrations/integration.py | 2 +- integrations/integration_ids.py | 8 ++ integrations/template.py | 4 +- utils/request_utils.py | 23 ++++ utils/web3_utils.py | 3 +- 11 files changed, 306 insertions(+), 7 deletions(-) create mode 100644 constants/example_integrations.py create mode 100644 integrations/beefy_cached_balance_example_integration.py create mode 100644 integrations/claimed_ena_example_integration.py create mode 100644 utils/request_utils.py diff --git a/campaign/campaign.py b/campaign/campaign.py index aab0149..bfd4092 100644 --- a/campaign/campaign.py +++ b/campaign/campaign.py @@ -1,4 +1,12 @@ from typing import List +from constants.example_integrations import ( + ACTIVE_ENA_START_BLOCK_EXAMPLE, + BEEFY_ARBITRUM_START_BLOCK_EXAMPLE, +) +from integrations.beefy_cached_balance_example_integration import ( + BeefyCachedBalanceIntegration, +) +from integrations.claimed_ena_example_integration import ClaimedEnaIntegration from utils import pendle from web3 import Web3 @@ -25,7 +33,24 @@ }, end_block=40000000, ), - # Examples + # Example integration using cached user balances for improved performance, + # reads from previous balance snapshots + ClaimedEnaIntegration( + integration_id=IntegrationID.CLAIMED_ENA_EXAMPLE, + start_block=ACTIVE_ENA_START_BLOCK_EXAMPLE, + summary_cols=[SummaryColumn.CLAIMED_ENA_PTS_EXAMPLE], + reward_multiplier=1, + ), + # Cached balances integration example, based on API calls + BeefyCachedBalanceIntegration( + integration_id=IntegrationID.BEEFY_CACHED_BALANCE_EXAMPLE, + start_block=BEEFY_ARBITRUM_START_BLOCK_EXAMPLE, + summary_cols=[SummaryColumn.BEEFY_CACHED_BALANCE_EXAMPLE], + chain=Chain.ARBITRUM, + reward_multiplier=1, + ), + # Simple Integration class examples (outdated), + # don't use these anymore PendleLPTIntegration( integration_id=IntegrationID.PENDLE_USDE_LPT, start_block=PENDLE_USDE_JULY_DEPLOYMENT_BLOCK, diff --git a/constants/example_integrations.py b/constants/example_integrations.py new file mode 100644 index 0000000..2b1ca8b --- /dev/null +++ b/constants/example_integrations.py @@ -0,0 +1,16 @@ +import json +from web3 import Web3 +from utils.web3_utils import w3 + +PAGINATION_SIZE = 2000 +ACTIVE_ENA_START_BLOCK_EXAMPLE = 21202656 +ENA_ADDRESS = Web3.to_checksum_address("0x57e114B691Db790C35207b2e685D4A43181e6061") +with open("abi/ERC20_abi.json") as f: + ERC20_ABI = json.load(f) + +ENA_CONTRACT = w3.eth.contract( + address=ENA_ADDRESS, + abi=ERC20_ABI, +) + +BEEFY_ARBITRUM_START_BLOCK_EXAMPLE = 219870802 diff --git a/constants/summary_columns.py b/constants/summary_columns.py index e2ea4fc..e0c35b4 100644 --- a/constants/summary_columns.py +++ b/constants/summary_columns.py @@ -32,6 +32,13 @@ class SummaryColumn(Enum): CURVE_LLAMALEND_SHARDS = ("curve_llamalend_shards", SummaryColumnType.ETHENA_PTS) + CLAIMED_ENA_PTS_EXAMPLE = ("claimed_ena_example", SummaryColumnType.ETHENA_PTS) + + BEEFY_CACHED_BALANCE_EXAMPLE = ( + "beefy_cached_balance_example", + SummaryColumnType.ETHENA_PTS, + ) + def __init__(self, column_name: str, col_type: SummaryColumnType): self.column_name = column_name self.col_type = col_type diff --git a/integrations/beefy_cached_balance_example_integration.py b/integrations/beefy_cached_balance_example_integration.py new file mode 100644 index 0000000..eded118 --- /dev/null +++ b/integrations/beefy_cached_balance_example_integration.py @@ -0,0 +1,112 @@ +import logging + +from constants.example_integrations import ( + BEEFY_ARBITRUM_START_BLOCK_EXAMPLE, +) +from integrations.cached_balances_integration import CachedBalancesIntegration +from web3 import Web3 +from constants.chains import Chain +from typing import Dict, List, Set, cast +from eth_typing import ChecksumAddress + +from constants.beefy import BEEFY_LRT_API_URL +from constants.summary_columns import SummaryColumn +from integrations.integration_ids import IntegrationID +from utils.request_utils import requests_retry_session +from utils.slack import slack_message + +CHAIN_TO_API_URL_PREFIX = { + Chain.ARBITRUM: f"{BEEFY_LRT_API_URL}/partner/ethena/arbitrum", + Chain.FRAXTAL: f"{BEEFY_LRT_API_URL}/partner/ethena/fraxtal", + Chain.MANTLE: f"{BEEFY_LRT_API_URL}/partner/ethena/mantle", + Chain.OPTIMISM: f"{BEEFY_LRT_API_URL}/partner/ethena/optimism", +} + + +class BeefyCachedBalanceIntegration(CachedBalancesIntegration): + def __init__( + self, + integration_id: IntegrationID, + start_block: int, + chain: Chain, + summary_cols: List[SummaryColumn], + reward_multiplier: int = 1, + ): + super().__init__( + integration_id=integration_id, + start_block=start_block, + chain=chain, + summary_cols=summary_cols, + reward_multiplier=reward_multiplier, + balance_multiplier=1, + excluded_addresses=None, + end_block=None, + ) + + def get_beefy_users(self) -> Set[ChecksumAddress]: + """ + Get all participants of the protocol, ever. + """ + logging.info("[Beefy integration] Getting participants...") + try: + base_url = CHAIN_TO_API_URL_PREFIX[self.chain] + url = f"{base_url}/users" + + response = requests_retry_session().get(url) + data = cast(List[str], response.json()) + return set(Web3.to_checksum_address(user) for user in data) + except Exception as e: + msg = f"Error getting participants for beefy: {e}" + logging.error(msg) + slack_message(msg) + return set() + + def get_data_for_block( + self, block: int, users: Set[ChecksumAddress] + ) -> Dict[ChecksumAddress, float]: + logging.info(f"Getting data for beefy at block {block}...") + + if block < self.start_block: + return {} + data: Dict[ChecksumAddress, float] = {} + # Just get the first 10 users as a quick example + for user in list(users)[:10]: + try: + base_url = CHAIN_TO_API_URL_PREFIX[self.chain] + url = f"{base_url}/user/{user}/balance/{block}" + response = requests_retry_session(retries=1, backoff_factor=0).get(url) + user_data = response.json() + + if user_data is None or "effective_balance" not in user_data: + data[user] = 0.0 + data[user] = round(float(user_data["effective_balance"]), 4) + except Exception as e: + msg = f"Error getting beefy data for {user} at block {block}: {e}" + logging.error(msg) + slack_message(msg) + data[user] = 0.0 + return data + + def get_block_balances( + self, cached_data: Dict[int, Dict[ChecksumAddress, float]], blocks: List[int] + ) -> Dict[int, Dict[ChecksumAddress, float]]: + logging.info("Getting block data for beefy...") + block_data: Dict[int, Dict[ChecksumAddress, float]] = {} + beefy_users = self.get_beefy_users() + for block in blocks: + if block < self.start_block: + block_data[block] = {} + continue + block_data[block] = self.get_data_for_block(block, beefy_users) + return block_data + + +if __name__ == "__main__": + example_integration = BeefyCachedBalanceIntegration( + integration_id=IntegrationID.BEEFY_CACHED_BALANCE_EXAMPLE, + start_block=BEEFY_ARBITRUM_START_BLOCK_EXAMPLE, + chain=Chain.ARBITRUM, + summary_cols=[SummaryColumn.BEEFY_CACHED_BALANCE_EXAMPLE], + ) + # Since this integration is based on API calls, we don't need to use the cached data + print(example_integration.get_block_balances(cached_data={}, blocks=[276231389])) diff --git a/integrations/cached_balances_integration.py b/integrations/cached_balances_integration.py index e5df540..f935736 100644 --- a/integrations/cached_balances_integration.py +++ b/integrations/cached_balances_integration.py @@ -35,5 +35,5 @@ def __init__( def get_block_balances( self, cached_data: Dict[int, Dict[ChecksumAddress, float]], blocks: List[int] - ) -> Dict[int, Dict[str, float]]: + ) -> Dict[int, Dict[ChecksumAddress, float]]: raise NotImplementedError diff --git a/integrations/claimed_ena_example_integration.py b/integrations/claimed_ena_example_integration.py new file mode 100644 index 0000000..8e39851 --- /dev/null +++ b/integrations/claimed_ena_example_integration.py @@ -0,0 +1,109 @@ +from copy import deepcopy +import logging + +from typing import Dict, List, Optional + +from constants.summary_columns import SummaryColumn +from eth_typing import ChecksumAddress + +from constants.example_integrations import ( + ACTIVE_ENA_START_BLOCK_EXAMPLE, + ENA_CONTRACT, + PAGINATION_SIZE, +) + +from constants.chains import Chain +from integrations.integration_ids import IntegrationID +from integrations.cached_balances_integration import CachedBalancesIntegration +from utils.web3_utils import fetch_events_logs_with_retry + + +class ClaimedEnaIntegration(CachedBalancesIntegration): + def __init__( + self, + integration_id: IntegrationID, + start_block: int, + chain: Chain = Chain.ETHEREUM, + summary_cols: Optional[List[SummaryColumn]] = None, + reward_multiplier: int = 1, + ): + super().__init__( + integration_id, + start_block, + chain, + summary_cols, + reward_multiplier, + ) + + def get_block_balances( + self, cached_data: Dict[int, Dict[ChecksumAddress, float]], blocks: List[int] + ) -> Dict[int, Dict[ChecksumAddress, float]]: + logging.info("Getting block data for claimed ENA") + new_block_data: Dict[int, Dict[ChecksumAddress, float]] = {} + if not blocks: + logging.error("No blocks provided to claimed ENA get_block_balances") + return new_block_data + sorted_blocks = sorted(blocks) + cache_copy: Dict[int, Dict[ChecksumAddress, float]] = deepcopy(cached_data) + for block in sorted_blocks: + # find the closest prev block in the data + # list keys parsed as ints and in descending order + sorted_existing_blocks = sorted( + cache_copy, + reverse=True, + ) + # loop through the sorted blocks and find the closest previous block + prev_block = self.start_block + start = prev_block + bals = {} + for existing_block in sorted_existing_blocks: + if existing_block < block: + prev_block = existing_block + start = existing_block + 1 + bals = deepcopy(cache_copy[prev_block]) + break + # parse transfer events since and update bals + while start <= block: + to_block = min(start + PAGINATION_SIZE, block) + # print(f"Fetching transfers from {start} to {to_block}") + transfers = fetch_events_logs_with_retry( + "Token transfers claimed ENA", + ENA_CONTRACT.events.Transfer(), + start, + to_block, + ) + for transfer in transfers: + recipient = transfer["args"]["to"] + if recipient not in bals: + bals[recipient] = 0 + bals[recipient] += round(transfer["args"]["value"] / 10**18, 4) + start = to_block + 1 + new_block_data[block] = bals + cache_copy[block] = bals + return new_block_data + + +if __name__ == "__main__": + example_integration = ClaimedEnaIntegration( + integration_id=IntegrationID.CLAIMED_ENA_EXAMPLE, + start_block=ACTIVE_ENA_START_BLOCK_EXAMPLE, + summary_cols=[SummaryColumn.CLAIMED_ENA_PTS_EXAMPLE], + reward_multiplier=20, + ) + + # Without cached data + without_cached_data_output = example_integration.get_block_balances( + cached_data={}, blocks=[21209856, 21217056] + ) + + print("=" * 120) + print("Run without cached data", without_cached_data_output) + print("=" * 120, "\n" * 5) + + # With cached data, using the previous output so there is no need + # to fetch the previous blocks again + with_cached_data_output = example_integration.get_block_balances( + cached_data=without_cached_data_output, blocks=[21224256] + ) + print("Run with cached data", with_cached_data_output) + print("=" * 120) diff --git a/integrations/integration.py b/integrations/integration.py index a17048d..90ce12b 100644 --- a/integrations/integration.py +++ b/integrations/integration.py @@ -49,5 +49,5 @@ def get_participants( # either get_participants OR get_block_balances must be implemented def get_block_balances( self, cached_data: Dict[int, Dict[ChecksumAddress, float]], blocks: List[int] - ) -> Dict[int, Dict[str, float]]: + ) -> Dict[int, Dict[ChecksumAddress, float]]: raise NotImplementedError diff --git a/integrations/integration_ids.py b/integrations/integration_ids.py index 771c09e..aa89852 100644 --- a/integrations/integration_ids.py +++ b/integrations/integration_ids.py @@ -386,6 +386,14 @@ class IntegrationID(Enum): # Fluid FLUID = ("Fluid_susde", "Fluid sUSDe", Token.SUSDE) + # Claimed ENA + CLAIMED_ENA_EXAMPLE = ("claimed_ena_example", "Claimed ENA Example", Token.ENA) + BEEFY_CACHED_BALANCE_EXAMPLE = ( + "beefy_cached_balance_example", + "Beefy Cached Balance Example", + Token.USDE, + ) + def __init__(self, column_name: str, description: str, token: Token = Token.USDE): self.column_name = column_name self.description = description diff --git a/integrations/template.py b/integrations/template.py index e26e837..3116684 100644 --- a/integrations/template.py +++ b/integrations/template.py @@ -39,7 +39,7 @@ def __init__( # TODO: Implement this function def get_block_balances( self, cached_data: Dict[int, Dict[ChecksumAddress, float]], blocks: List[int] - ) -> Dict[int, Dict[str, float]]: + ) -> Dict[int, Dict[ChecksumAddress, float]]: """Get user balances for specified blocks, using cached data when available. Args: @@ -49,7 +49,7 @@ def get_block_balances( blocks (List[int]): List of block numbers to get balances for. Returns: - Dict[int, Dict[str, float]]: Dictionary mapping block numbers to user balances, + Dict[int, Dict[ChecksumAddress, float]]: Dictionary mapping block numbers to user balances, where each inner dictionary maps user addresses to their token balance at that block. """ diff --git a/utils/request_utils.py b/utils/request_utils.py new file mode 100644 index 0000000..55ec194 --- /dev/null +++ b/utils/request_utils.py @@ -0,0 +1,23 @@ +import requests +from requests.adapters import HTTPAdapter +from urllib3.util.retry import Retry + + +def requests_retry_session( + retries=5, + backoff_factor=0.3, + status_forcelist=(400, 404, 500, 502, 504), + session=None, +): + session = session or requests.Session() + retry = Retry( + total=retries, + read=retries, + connect=retries, + backoff_factor=backoff_factor, + status_forcelist=status_forcelist, + ) + adapter = HTTPAdapter(max_retries=retry) + session.mount("http://", adapter) + session.mount("https://", adapter) + return session diff --git a/utils/web3_utils.py b/utils/web3_utils.py index 635ca46..c8150ef 100644 --- a/utils/web3_utils.py +++ b/utils/web3_utils.py @@ -2,13 +2,12 @@ import os import time import traceback -from typing import Union, Literal from dotenv import load_dotenv from eth_abi.abi import decode from web3 import Web3 -from web3.types import HexStr, HexBytes, BlockIdentifier +from web3.types import BlockIdentifier from utils.slack import slack_message from constants.chains import Chain From 7a9787df33cb611a0b12ba0493880282e5d21b8b Mon Sep 17 00:00:00 2001 From: FJ-Riveros Date: Tue, 19 Nov 2024 23:19:34 +0100 Subject: [PATCH 14/16] chore: update the readme --- README.md | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 1a34e36..693a907 100644 --- a/README.md +++ b/README.md @@ -9,16 +9,22 @@ For your protocol to be included and your users to receive points, you should su 1. Make a copy of `.env.example` and name it `.env`. 2. Run `pip install -r requirements.txt` to install the required packages. 3. Add your integration metadata to `integrations/integration_ids.py`. -4. Add your integration metadata to `constants/summary_columns.py`. -5. Make a copy of `integrations/template.py`, naming the file `[protocol name]_integration.py` and place in the `integrations` directory. +4. Create a new summary column in `constants/summary_columns.py`. +5. Make a copy of [Template](integrations/template.py), naming the file `[protocol name]_integration.py` and place in the `integrations` directory. 6. Your integration must be a class that inherits from `CachedBalancesIntegration` and implements the `get_block_balances` method. -6. The `get_block_balances` method should return a dict of block numbers to a dict of user addresses to balances at that block. -7. Write some basic tests at the bottom of the file to ensure your integration is working correctly. -8. Submit a PR to this repo with your integration and ping the Ethena team in Telegram. +7. The `get_block_balances` method should return a dict of block numbers to a dict of user addresses to balances at that block. +8. Write some basic tests at the bottom of the file to ensure your integration is working correctly. +9. Submit a PR to this repo with your integration and ping the Ethena team in Telegram. # Guidelines - Integrations must follow this architecture and be written in python. - Pendle integrations are included as examples of functioning integrations. Run `python -m integrations.pendle_lpt_integration` to see the output. -- The `get_block_balances` method should be as efficient as possible. +- The `get_block_balances` method should be as efficient as possible. So the use of the cached data from previous blocks if possible is highly encouraged. - We prefer that on chain RPC calls are used to get information as much as possible due to reliability and trustlessness. Off chain calls to apis or subgraphs are acceptable if necessary. If usage is not reasonable or the external service is not reliable, users may not receive their sats. + +# Example Integrations +- [ClaimedEnaIntegration](integrations/claimed_ena_example_integration.py): This integration demonstrates how to track ENA token claims using cached balance snapshots for improved performance. It reads from previous balance snapshots to efficiently track user claim history. +- [BeefyCachedBalanceExampleIntegration](integrations/beefy_cached_balance_example_integration.py): This integration is an example of a cached balance integration that is based on API calls. +- [PendleLPTIntegration](integrations/pendle_lpt_integration.py): (Legacy Example) A basic integration showing Pendle LPT staking tracking. Note: This is a non-cached implementation included only for reference - new integrations should use the cached approach for better efficiency. +- [PendleYTIntegration](integrations/pendle_yt_integration.py): (Legacy Example) A basic integration showing Pendle YT staking tracking. Note: This is a non-cached implementation included only for reference - new integrations should use the cached approach for better efficiency. From bb5a6fbd8525a5408a7adcb5f4979dcc15243bf8 Mon Sep 17 00:00:00 2001 From: b Date: Wed, 20 Nov 2024 08:11:16 -0500 Subject: [PATCH 15/16] update readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 693a907..2b2e804 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ For your protocol to be included and your users to receive points, you should su 4. Create a new summary column in `constants/summary_columns.py`. 5. Make a copy of [Template](integrations/template.py), naming the file `[protocol name]_integration.py` and place in the `integrations` directory. 6. Your integration must be a class that inherits from `CachedBalancesIntegration` and implements the `get_block_balances` method. -7. The `get_block_balances` method should return a dict of block numbers to a dict of user addresses to balances at that block. +7. The `get_block_balances` method should return a dict of block numbers to a dict of user addresses to balances at that block. (Note: Not all blocks are queried by this service in production- only a sampling, but your code should be capable of handling any block number.) 8. Write some basic tests at the bottom of the file to ensure your integration is working correctly. 9. Submit a PR to this repo with your integration and ping the Ethena team in Telegram. @@ -21,7 +21,7 @@ For your protocol to be included and your users to receive points, you should su - Integrations must follow this architecture and be written in python. - Pendle integrations are included as examples of functioning integrations. Run `python -m integrations.pendle_lpt_integration` to see the output. - The `get_block_balances` method should be as efficient as possible. So the use of the cached data from previous blocks if possible is highly encouraged. -- We prefer that on chain RPC calls are used to get information as much as possible due to reliability and trustlessness. Off chain calls to apis or subgraphs are acceptable if necessary. If usage is not reasonable or the external service is not reliable, users may not receive their sats. +- We prefer that on chain RPC calls are used to get information as much as possible due to reliability and trustlessness. Off chain calls to apis or subgraphs are acceptable if necessary. If usage is not reasonable or the external service is not reliable, users may not receive their points. # Example Integrations - [ClaimedEnaIntegration](integrations/claimed_ena_example_integration.py): This integration demonstrates how to track ENA token claims using cached balance snapshots for improved performance. It reads from previous balance snapshots to efficiently track user claim history. From 1ea22bc5577c3aebe3e3b104e17b7e0b2e13945b Mon Sep 17 00:00:00 2001 From: b Date: Wed, 20 Nov 2024 08:28:37 -0500 Subject: [PATCH 16/16] remove python path --- .github/workflows/main-push-and-pr.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/main-push-and-pr.yml b/.github/workflows/main-push-and-pr.yml index 0c6b255..0c133e3 100644 --- a/.github/workflows/main-push-and-pr.yml +++ b/.github/workflows/main-push-and-pr.yml @@ -39,7 +39,4 @@ jobs: flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics - name: Type check with mypy - run: mypy . --explicit-package-bases --pretty --check-untyped-defs - - - name: Set PYTHONPATH - run: echo "PYTHONPATH=$GITHUB_WORKSPACE" >> $GITHUB_ENV \ No newline at end of file + run: mypy . --explicit-package-bases --pretty --check-untyped-defs \ No newline at end of file