diff --git a/config/indexer-config-hyper.yaml b/config/indexer-config-hyper.yaml new file mode 100644 index 000000000..d1a33b0ab --- /dev/null +++ b/config/indexer-config-hyper.yaml @@ -0,0 +1,36 @@ +chain_id: 999 + +export_tokens_and_transfers_job: + filter_token_address: + - "0xe6829d9a7ee3040e1276fa75293bde931859e8fa" +# YT + - "0x6bd129974d12d3c3efe1cce95a9bc822d811033c" +# LP + - "0x1dc93df5d77b705c8c16527ec800961f1a7b3413" + + +export_transactions_and_logs_job: + use_receipt_from_blocks_rpc: True + + +uniswap_v3_job: + # empty means no filter. only work in price job + pool_address: + - '0x765975e3f795ce8607497818b72493569faec961' + + # works in price\token job + jobs: + - type: uniswapv3 # uniswapv3` + factory_address: '0xb1c0fa0b789320044a6f623cfe5ebda9562602e3' + position_token_address: '0x6eda206207c09e5428f281761ddc0d300851fbc8' + + +export_staked_transferred_balance_job: + TRANSFERRED_CONTRACTS_DICT: +# hypurr: +# - "0x64df7b4da81a26a59417857f508b39370138d95e" + morphobeat: + - "0x68e37de8d93d3496ae143f2e900490f6280c57cd" + token_address: + # cmeth + - "0xe6829d9a7ee3040e1276fa75293bde931859e8fa" \ No newline at end of file diff --git a/hemera/indexer/utils/multicall_hemera/constants.py b/hemera/indexer/utils/multicall_hemera/constants.py index 4ffb07d40..84dd03664 100644 --- a/hemera/indexer/utils/multicall_hemera/constants.py +++ b/hemera/indexer/utils/multicall_hemera/constants.py @@ -111,6 +111,7 @@ def get_all_networks(cls) -> Dict[int, "NetworkConfig"]: MONAD_TESTNET = NetworkConfig(10143, "MonadalTestnet", 251449) SONIC = NetworkConfig(146, "Sonic", 60) SONIC_TESTNET = NetworkConfig(57054, "SonicTestnet", 1100) +HYPER = NetworkConfig(999, "HyperEVM", 13051) def get_multicall_network(chain_id: int) -> NetworkConfig: diff --git a/hemera_udf/spectra/__init__.py b/hemera_udf/spectra/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/hemera_udf/spectra/abi/__init__.py b/hemera_udf/spectra/abi/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/hemera_udf/spectra/abi/abi.py b/hemera_udf/spectra/abi/abi.py new file mode 100644 index 000000000..d8aeb58e8 --- /dev/null +++ b/hemera_udf/spectra/abi/abi.py @@ -0,0 +1,12 @@ +from hemera.common.utils.abi_code_utils import Event, Function + + +GET_BALANCES_FUNCTION = Function( + { + "inputs": [], + "name": "get_balances", + "outputs": [{"name": "", "type": "uint256[]"}], + "stateMutability": "view", + "type": "function", + } +) \ No newline at end of file diff --git a/hemera_udf/spectra/domains.py b/hemera_udf/spectra/domains.py new file mode 100644 index 000000000..fbdcd9cca --- /dev/null +++ b/hemera_udf/spectra/domains.py @@ -0,0 +1,15 @@ +from dataclasses import dataclass + +from hemera.indexer.domains import Domain + + +@dataclass +class SpectraLpBalance(Domain): + token0_address: str + token1_address: str + token0_balance: int + token1_balance: int + + block_number: int + block_timestamp: int + diff --git a/hemera_udf/spectra/jobs/__init__.py b/hemera_udf/spectra/jobs/__init__.py new file mode 100644 index 000000000..c3e1a2eaf --- /dev/null +++ b/hemera_udf/spectra/jobs/__init__.py @@ -0,0 +1,6 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# @Time 2024/12/10 17:09 +# @Author will +# @File __init__.py.py +# @Brief diff --git a/hemera_udf/spectra/jobs/spectra_job.py b/hemera_udf/spectra/jobs/spectra_job.py new file mode 100644 index 000000000..b2646034a --- /dev/null +++ b/hemera_udf/spectra/jobs/spectra_job.py @@ -0,0 +1,77 @@ +import logging + +from hemera.indexer.domains.token_transfer import ERC20TokenTransfer +from hemera.indexer.jobs.base_job import FilterTransactionDataJob +from hemera.indexer.specification.specification import TransactionFilterByLogs, TopicSpecification +from hemera.indexer.utils.multicall_hemera import Call +from hemera.indexer.utils.multicall_hemera.multi_call_helper import MultiCallHelper +from hemera_udf.spectra.abi.abi import GET_BALANCES_FUNCTION +from hemera_udf.spectra.domains import SpectraLpBalance + +logger = logging.getLogger(__name__) + + +class ExportSpectraLpBalance(FilterTransactionDataJob): + dependency_types = [ERC20TokenTransfer] + + output_types = [SpectraLpBalance] + able_to_reorg = True + + def __init__(self, **kwargs): + super().__init__(**kwargs) + self.multi_call_helper = MultiCallHelper(self._web3, kwargs, logger) + self.lp_address = '0x1dc93df5d77b705c8c16527ec800961f1a7b3413' + + self.token0_address = '0xb74e4f4add805a7191a934a05d3a826e8d714a44' + self.token1_address = '0x40defb4b2a451c7bad7c256132085ac4348c3b4c' + + + def get_filter(self): + return TransactionFilterByLogs( + [ + TopicSpecification( + addresses=[str(self.lp_address)], + ), + ] + ) + + def _process(self, **kwargs): + erc_20_token_transfers = self._data_buff[ERC20TokenTransfer.type()] + lp_token_transfers = [ + tt for tt in erc_20_token_transfers if tt.token_address in self.lp_address + ] + + call_dict = {} + for token_transfer in lp_token_transfers: + block_number = token_transfer.block_number + call = Call( + target=self.lp_address, + function_abi=GET_BALANCES_FUNCTION, + block_number=block_number, + user_defined_k=token_transfer.block_timestamp, + ) + call_dict[block_number] = call + + call_list = list(call_dict.values()) + + self.multi_call_helper.execute_calls(call_list) + + records = [] + + call_list.sort(key=lambda call: call.block_number) + + for call in call_list: + returns = call.returns + if returns: + token0_balance, token1_balance = returns.get("") + domain = SpectraLpBalance( + token0_address=self.token0_address, + token1_address=self.token1_address, + token0_balance=token0_balance, + token1_balance=token1_balance, + block_number=call.block_number, + block_timestamp=call.user_defined_k, + ) + + records.append(domain) + self._collect_domains(records) diff --git a/hemera_udf/spectra/models/__init__.py b/hemera_udf/spectra/models/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/hemera_udf/spectra/models/af_spectra_lp_balance_model.py b/hemera_udf/spectra/models/af_spectra_lp_balance_model.py new file mode 100644 index 000000000..92d3773fa --- /dev/null +++ b/hemera_udf/spectra/models/af_spectra_lp_balance_model.py @@ -0,0 +1,34 @@ +from sqlalchemy import Column, PrimaryKeyConstraint, func +from sqlalchemy.dialects.postgresql import BIGINT, BYTEA, NUMERIC, TIMESTAMP + +from hemera.common.models import HemeraModel, general_converter +from hemera_udf.spectra.domains import SpectraLpBalance + + +class SpectraLpBalanceModel(HemeraModel): + __tablename__ = "af_spectra_lp_balance" + + block_number = Column(BIGINT) + block_timestamp = Column(TIMESTAMP, primary_key=True) + + token0_address = Column(BYTEA) + token1_address = Column(BYTEA) + + token0_balance = Column(NUMERIC) + token1_balance = Column(NUMERIC) + + create_time = Column(TIMESTAMP, server_default=func.now()) + update_time = Column(TIMESTAMP, server_default=func.now()) + + __table_args__ = (PrimaryKeyConstraint("block_timestamp", "block_number"),) + + @staticmethod + def model_domain_mapping(): + return [ + { + "domain": SpectraLpBalance, + "conflict_do_update": True, + "update_strategy": None, + "converter": general_converter, + } + ]