From 5d8ba0bddb69660702cfcec80f55a364b2d68970 Mon Sep 17 00:00:00 2001 From: river Date: Tue, 29 Jul 2025 14:42:31 +0800 Subject: [PATCH 1/4] add hyper multicall --- config/indexer-config-hyper.yaml | 32 +++++++++++++++++++ .../utils/multicall_hemera/constants.py | 1 + 2 files changed, 33 insertions(+) create mode 100644 config/indexer-config-hyper.yaml diff --git a/config/indexer-config-hyper.yaml b/config/indexer-config-hyper.yaml new file mode 100644 index 000000000..8bd3e082f --- /dev/null +++ b/config/indexer-config-hyper.yaml @@ -0,0 +1,32 @@ +chain_id: 999 + +export_tokens_and_transfers_job: + filter_token_address: + - "0xe6829d9a7ee3040e1276fa75293bde931859e8fa" + + +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: From b53e9c3a61d007a7f679c7a06585663d046c4781 Mon Sep 17 00:00:00 2001 From: river Date: Mon, 18 Aug 2025 14:57:49 +0800 Subject: [PATCH 2/4] add spectra --- config/indexer-config-hyper.yaml | 4 +++ hemera_udf/spectra/__init__.py | 0 hemera_udf/spectra/abi/__init__.py | 0 hemera_udf/spectra/abi/abi.py | 12 +++++++ hemera_udf/spectra/domains.py | 15 ++++++++ hemera_udf/spectra/jobs/__init__.py | 6 ++++ hemera_udf/spectra/models/__init__.py | 0 .../models/af_uniswap_v2_swap_event.py | 34 +++++++++++++++++++ 8 files changed, 71 insertions(+) create mode 100644 hemera_udf/spectra/__init__.py create mode 100644 hemera_udf/spectra/abi/__init__.py create mode 100644 hemera_udf/spectra/abi/abi.py create mode 100644 hemera_udf/spectra/domains.py create mode 100644 hemera_udf/spectra/jobs/__init__.py create mode 100644 hemera_udf/spectra/models/__init__.py create mode 100644 hemera_udf/spectra/models/af_uniswap_v2_swap_event.py diff --git a/config/indexer-config-hyper.yaml b/config/indexer-config-hyper.yaml index 8bd3e082f..d1a33b0ab 100644 --- a/config/indexer-config-hyper.yaml +++ b/config/indexer-config-hyper.yaml @@ -3,6 +3,10 @@ chain_id: 999 export_tokens_and_transfers_job: filter_token_address: - "0xe6829d9a7ee3040e1276fa75293bde931859e8fa" +# YT + - "0x6bd129974d12d3c3efe1cce95a9bc822d811033c" +# LP + - "0x1dc93df5d77b705c8c16527ec800961f1a7b3413" export_transactions_and_logs_job: 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/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_uniswap_v2_swap_event.py b/hemera_udf/spectra/models/af_uniswap_v2_swap_event.py new file mode 100644 index 000000000..92d3773fa --- /dev/null +++ b/hemera_udf/spectra/models/af_uniswap_v2_swap_event.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, + } + ] From ef5a341bf8c2f7ec0449544a106e159a4f211553 Mon Sep 17 00:00:00 2001 From: river Date: Mon, 18 Aug 2025 15:42:50 +0800 Subject: [PATCH 3/4] rename model --- ...af_uniswap_v2_swap_event.py => af_spectra_lp_balance_model.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename hemera_udf/spectra/models/{af_uniswap_v2_swap_event.py => af_spectra_lp_balance_model.py} (100%) diff --git a/hemera_udf/spectra/models/af_uniswap_v2_swap_event.py b/hemera_udf/spectra/models/af_spectra_lp_balance_model.py similarity index 100% rename from hemera_udf/spectra/models/af_uniswap_v2_swap_event.py rename to hemera_udf/spectra/models/af_spectra_lp_balance_model.py From bda4c3368d08c94a397e7ed81eca044906c4766b Mon Sep 17 00:00:00 2001 From: river Date: Mon, 18 Aug 2025 15:58:17 +0800 Subject: [PATCH 4/4] add spectra_job.py --- hemera_udf/spectra/jobs/spectra_job.py | 77 ++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 hemera_udf/spectra/jobs/spectra_job.py 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)