Skip to content

Commit 2d17ff0

Browse files
committed
Add more tests and mocks
1 parent 1d866c8 commit 2d17ff0

File tree

7 files changed

+3012
-45
lines changed

7 files changed

+3012
-45
lines changed

app/datasources/db/models.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,10 @@ class Abi(SqlQueryBase, SQLModel, table=True):
5252

5353
@classmethod
5454
async def get_abis_sorted_by_relevance(cls, session: AsyncSession):
55-
results = await session.exec(
56-
select(cls.abi_json).order_by(col(cls.relevance).desc())
57-
)
55+
"""
56+
:returns: Abi JSON, with the ones with less relevance first
57+
"""
58+
results = await session.exec(select(cls.abi_json).order_by(col(cls.relevance)))
5859
for result in results:
5960
yield result
6061

app/services/data_decoder.py

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import logging
2-
from functools import cache, cached_property, lru_cache
2+
from functools import cache
33
from typing import Any, AsyncIterator, NotRequired, Sequence, TypedDict, cast
44

5+
from async_lru import alru_cache
56
from eth_abi import decode as decode_abi
67
from eth_abi.exceptions import DecodingError
78
from eth_typing import ABIFunction, Address, HexStr
@@ -80,8 +81,14 @@ async def init(self, session: AsyncSession) -> None:
8081
logger.info(
8182
"%s: Contract ABIs for decoding were loaded", self.__class__.__name__
8283
)
83-
self.multisend_abis: list[Sequence[ABIFunction]] = [m async for m in self.get_multisend_abis()]
84-
self.multisend_fn_selectors_with_abis: dict[bytes, ABIFunction] = await self._generate_selectors_with_abis_from_abis(self.get_multisend_abis())
84+
self.multisend_abis: list[Sequence[ABIFunction]] = [
85+
m async for m in self.get_multisend_abis()
86+
]
87+
self.multisend_fn_selectors_with_abis: dict[bytes, ABIFunction] = (
88+
await self._generate_selectors_with_abis_from_abis(
89+
self.get_multisend_abis()
90+
)
91+
)
8592

8693
def _generate_selectors_with_abis_from_abi(
8794
self, abi: Sequence[ABIFunction]
@@ -112,7 +119,9 @@ async def _generate_selectors_with_abis_from_abis(
112119
).items()
113120
}
114121

115-
async def get_supported_abis(self, session: AsyncSession) -> AsyncIterator[Sequence[ABIFunction]]:
122+
async def get_supported_abis(
123+
self, session: AsyncSession
124+
) -> AsyncIterator[Sequence[ABIFunction]]:
116125
"""
117126
:return: Every ABI in the database
118127
"""
@@ -121,7 +130,7 @@ async def get_supported_abis(self, session: AsyncSession) -> AsyncIterator[Seque
121130
async def get_multisend_abis(self) -> AsyncIterator[Sequence[ABIFunction]]:
122131
yield get_multi_send_contract(self.dummy_w3).abi
123132

124-
# @lru_cache(maxsize=2048)
133+
@alru_cache(maxsize=2048)
125134
async def get_contract_abi(self, address: Address) -> list[ABIFunction] | None:
126135
"""
127136
Retrieves the ABI for the contract at the given address.
@@ -130,10 +139,14 @@ async def get_contract_abi(self, address: Address) -> list[ABIFunction] | None:
130139
:return: List of ABI data if found, `None` otherwise.
131140
"""
132141
async with AsyncSession(get_engine(), expire_on_commit=False) as session:
133-
return await Contract.get_abi_by_contract_address(session, HexBytes(address))
142+
return await Contract.get_abi_by_contract_address(
143+
session, HexBytes(address)
144+
)
134145

135-
# @lru_cache(maxsize=2048)
136-
async def get_contract_fallback_function(self, address: Address) -> ABIFunction | None:
146+
@alru_cache(maxsize=2048)
147+
async def get_contract_fallback_function(
148+
self, address: Address
149+
) -> ABIFunction | None:
137150
"""
138151
:param address: Contract address
139152
:return: Fallback ABIFunction if found, `None` otherwise.
@@ -149,7 +162,7 @@ async def get_contract_fallback_function(self, address: Address) -> ABIFunction
149162
None,
150163
)
151164

152-
# @lru_cache(maxsize=2048)
165+
@alru_cache(maxsize=2048)
153166
async def get_contract_abi_selectors_with_functions(
154167
self, address: Address
155168
) -> dict[bytes, ABIFunction] | None:
@@ -300,7 +313,7 @@ async def decode_parameters_data(
300313
fn_selector = data[:4]
301314
if fn_selector in self.multisend_fn_selectors_with_abis:
302315
# If MultiSend, decode the transactions
303-
parameters[0]["value_decoded"] = self.decode_multisend_data(data)
316+
parameters[0]["value_decoded"] = await self.decode_multisend_data(data)
304317

305318
elif (
306319
fn_selector == self.EXEC_TRANSACTION_SELECTOR
@@ -353,10 +366,25 @@ async def decode_transaction(
353366
:raises: CannotDecode if data cannot be decoded. You should catch this exception when using this function
354367
:raises: UnexpectedProblemDecoding if there's an unexpected problem decoding (it shouldn't happen)
355368
"""
356-
fn_name, decoded_transactions_with_types = await self.decode_transaction_with_types(
357-
data, address=address
369+
fn_name, decoded_transactions_with_types = (
370+
await self.decode_transaction_with_types(data, address=address)
358371
)
359372
decoded_transactions = {
360373
d["name"]: d["value"] for d in decoded_transactions_with_types
361374
}
362375
return fn_name, decoded_transactions
376+
377+
def add_abi(self, abi: ABIFunction) -> bool:
378+
"""
379+
Add a new abi without rebuilding the entire decoder
380+
381+
:return: True if decoder updated, False otherwise
382+
"""
383+
updated = False
384+
for selector, new_abi in self._generate_selectors_with_abis_from_abi(
385+
abi
386+
).items():
387+
if selector not in self.fn_selectors_with_abis:
388+
self.fn_selectors_with_abis[selector] = new_abi
389+
updated = True
390+
return updated

0 commit comments

Comments
 (0)