Remove ETH / ERC20 transfer distinction
This commit is contained in:
parent
f7fbd97a50
commit
378f5b248e
@ -11,8 +11,8 @@ from mev_inspect.schemas.classified_traces import (
|
|||||||
Protocol,
|
Protocol,
|
||||||
)
|
)
|
||||||
|
|
||||||
from mev_inspect.schemas.transfers import ERC20Transfer
|
|
||||||
from mev_inspect.schemas.liquidations import Liquidation
|
from mev_inspect.schemas.liquidations import Liquidation
|
||||||
|
from mev_inspect.transfers import get_transfer
|
||||||
|
|
||||||
AAVE_CONTRACT_ADDRESSES: List[str] = [
|
AAVE_CONTRACT_ADDRESSES: List[str] = [
|
||||||
# AAVE Proxy
|
# AAVE Proxy
|
||||||
@ -76,10 +76,12 @@ def _get_liquidator_payback(
|
|||||||
for child in child_traces:
|
for child in child_traces:
|
||||||
if child.classification == Classification.transfer:
|
if child.classification == Classification.transfer:
|
||||||
|
|
||||||
child_transfer = ERC20Transfer.from_trace(child)
|
child_transfer = get_transfer(child)
|
||||||
|
|
||||||
if (child_transfer.to_address == liquidator) and (
|
if (
|
||||||
child.from_address in AAVE_CONTRACT_ADDRESSES
|
child_transfer is not None
|
||||||
|
and child_transfer.to_address == liquidator
|
||||||
|
and child.from_address in AAVE_CONTRACT_ADDRESSES
|
||||||
):
|
):
|
||||||
return child_transfer.amount
|
return child_transfer.amount
|
||||||
|
|
||||||
|
@ -3,13 +3,13 @@ from mev_inspect.schemas.classifiers import (
|
|||||||
ClassifierSpec,
|
ClassifierSpec,
|
||||||
TransferClassifier,
|
TransferClassifier,
|
||||||
)
|
)
|
||||||
from mev_inspect.schemas.transfers import ERC20Transfer
|
from mev_inspect.schemas.transfers import Transfer
|
||||||
|
|
||||||
|
|
||||||
class ERC20TransferClassifier(TransferClassifier):
|
class ERC20TransferClassifier(TransferClassifier):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_transfer(trace: DecodedCallTrace) -> ERC20Transfer:
|
def get_transfer(trace: DecodedCallTrace) -> Transfer:
|
||||||
return ERC20Transfer(
|
return Transfer(
|
||||||
block_number=trace.block_number,
|
block_number=trace.block_number,
|
||||||
transaction_hash=trace.transaction_hash,
|
transaction_hash=trace.transaction_hash,
|
||||||
trace_address=trace.trace_address,
|
trace_address=trace.trace_address,
|
||||||
|
@ -6,13 +6,13 @@ from mev_inspect.schemas.classifiers import (
|
|||||||
DecodedCallTrace,
|
DecodedCallTrace,
|
||||||
TransferClassifier,
|
TransferClassifier,
|
||||||
)
|
)
|
||||||
from mev_inspect.schemas.transfers import ERC20Transfer
|
from mev_inspect.schemas.transfers import Transfer
|
||||||
|
|
||||||
|
|
||||||
class WethTransferClassifier(TransferClassifier):
|
class WethTransferClassifier(TransferClassifier):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_transfer(trace: DecodedCallTrace) -> ERC20Transfer:
|
def get_transfer(trace: DecodedCallTrace) -> Transfer:
|
||||||
return ERC20Transfer(
|
return Transfer(
|
||||||
block_number=trace.block_number,
|
block_number=trace.block_number,
|
||||||
transaction_hash=trace.transaction_hash,
|
transaction_hash=trace.transaction_hash,
|
||||||
trace_address=trace.trace_address,
|
trace_address=trace.trace_address,
|
||||||
|
@ -2,7 +2,7 @@ import json
|
|||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
from mev_inspect.models.transfers import TransferModel
|
from mev_inspect.models.transfers import TransferModel
|
||||||
from mev_inspect.schemas.transfers import ERC20Transfer
|
from mev_inspect.schemas.transfers import Transfer
|
||||||
|
|
||||||
|
|
||||||
def delete_transfers_for_block(
|
def delete_transfers_for_block(
|
||||||
@ -20,7 +20,7 @@ def delete_transfers_for_block(
|
|||||||
|
|
||||||
def write_transfers(
|
def write_transfers(
|
||||||
db_session,
|
db_session,
|
||||||
transfers: List[ERC20Transfer],
|
transfers: List[Transfer],
|
||||||
) -> None:
|
) -> None:
|
||||||
models = [TransferModel(**json.loads(transfer.json())) for transfer in transfers]
|
models = [TransferModel(**json.loads(transfer.json())) for transfer in transfers]
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ from typing import Dict, List, Optional, Type
|
|||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
|
|
||||||
from .classified_traces import Classification, DecodedCallTrace, Protocol
|
from .classified_traces import Classification, DecodedCallTrace, Protocol
|
||||||
from .transfers import ERC20Transfer
|
from .transfers import Transfer
|
||||||
|
|
||||||
|
|
||||||
class Classifier(ABC):
|
class Classifier(ABC):
|
||||||
@ -21,7 +21,7 @@ class TransferClassifier(Classifier):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def get_transfer(trace: DecodedCallTrace) -> ERC20Transfer:
|
def get_transfer(trace: DecodedCallTrace) -> Transfer:
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
from typing import List, TypeVar
|
from typing import List
|
||||||
|
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
|
|
||||||
from .classified_traces import Classification, ClassifiedTrace, Protocol
|
|
||||||
|
ETH_TOKEN_ADDRESS = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"
|
||||||
|
|
||||||
|
|
||||||
class Transfer(BaseModel):
|
class Transfer(BaseModel):
|
||||||
@ -12,50 +13,4 @@ class Transfer(BaseModel):
|
|||||||
from_address: str
|
from_address: str
|
||||||
to_address: str
|
to_address: str
|
||||||
amount: int
|
amount: int
|
||||||
|
|
||||||
|
|
||||||
# To preserve the specific Transfer type
|
|
||||||
TransferGeneric = TypeVar("TransferGeneric", bound="Transfer")
|
|
||||||
|
|
||||||
|
|
||||||
class EthTransfer(Transfer):
|
|
||||||
@classmethod
|
|
||||||
def from_trace(cls, trace: ClassifiedTrace) -> "EthTransfer":
|
|
||||||
return cls(
|
|
||||||
block_number=trace.block_number,
|
|
||||||
transaction_hash=trace.transaction_hash,
|
|
||||||
trace_address=trace.trace_address,
|
|
||||||
amount=trace.value,
|
|
||||||
to_address=trace.to_address,
|
|
||||||
from_address=trace.from_address,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class ERC20Transfer(Transfer):
|
|
||||||
token_address: str
|
token_address: str
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_trace(cls, trace: ClassifiedTrace) -> "ERC20Transfer":
|
|
||||||
if trace.classification != Classification.transfer or trace.inputs is None:
|
|
||||||
raise ValueError("Invalid transfer")
|
|
||||||
|
|
||||||
if trace.protocol == Protocol.weth:
|
|
||||||
return cls(
|
|
||||||
block_number=trace.block_number,
|
|
||||||
transaction_hash=trace.transaction_hash,
|
|
||||||
trace_address=trace.trace_address,
|
|
||||||
amount=trace.inputs["wad"],
|
|
||||||
to_address=trace.inputs["dst"],
|
|
||||||
from_address=trace.from_address,
|
|
||||||
token_address=trace.to_address,
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
return cls(
|
|
||||||
block_number=trace.block_number,
|
|
||||||
transaction_hash=trace.transaction_hash,
|
|
||||||
trace_address=trace.trace_address,
|
|
||||||
amount=trace.inputs["amount"],
|
|
||||||
to_address=trace.inputs["recipient"],
|
|
||||||
from_address=trace.inputs.get("sender", trace.from_address),
|
|
||||||
token_address=trace.to_address,
|
|
||||||
)
|
|
||||||
|
@ -8,11 +8,11 @@ from mev_inspect.schemas.classified_traces import (
|
|||||||
)
|
)
|
||||||
from mev_inspect.schemas.classifiers import SwapClassifier
|
from mev_inspect.schemas.classifiers import SwapClassifier
|
||||||
from mev_inspect.schemas.swaps import Swap
|
from mev_inspect.schemas.swaps import Swap
|
||||||
from mev_inspect.schemas.transfers import ERC20Transfer
|
from mev_inspect.schemas.transfers import Transfer
|
||||||
from mev_inspect.traces import get_traces_by_transaction_hash
|
from mev_inspect.traces import get_traces_by_transaction_hash
|
||||||
from mev_inspect.transfers import (
|
from mev_inspect.transfers import (
|
||||||
get_child_transfers,
|
get_child_transfers,
|
||||||
get_erc20_transfer,
|
get_transfer,
|
||||||
filter_transfers,
|
filter_transfers,
|
||||||
remove_child_transfers_of_transfers,
|
remove_child_transfers_of_transfers,
|
||||||
)
|
)
|
||||||
@ -31,14 +31,14 @@ def _get_swaps_for_transaction(traces: List[ClassifiedTrace]) -> List[Swap]:
|
|||||||
ordered_traces = list(sorted(traces, key=lambda t: t.trace_address))
|
ordered_traces = list(sorted(traces, key=lambda t: t.trace_address))
|
||||||
|
|
||||||
swaps: List[Swap] = []
|
swaps: List[Swap] = []
|
||||||
prior_transfers: List[ERC20Transfer] = []
|
prior_transfers: List[Transfer] = []
|
||||||
|
|
||||||
for trace in ordered_traces:
|
for trace in ordered_traces:
|
||||||
if not isinstance(trace, DecodedCallTrace):
|
if not isinstance(trace, DecodedCallTrace):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
elif trace.classification == Classification.transfer:
|
elif trace.classification == Classification.transfer:
|
||||||
transfer = get_erc20_transfer(trace)
|
transfer = get_transfer(trace)
|
||||||
if transfer is not None:
|
if transfer is not None:
|
||||||
prior_transfers.append(transfer)
|
prior_transfers.append(transfer)
|
||||||
|
|
||||||
@ -63,8 +63,8 @@ def _get_swaps_for_transaction(traces: List[ClassifiedTrace]) -> List[Swap]:
|
|||||||
|
|
||||||
def _parse_swap(
|
def _parse_swap(
|
||||||
trace: DecodedCallTrace,
|
trace: DecodedCallTrace,
|
||||||
prior_transfers: List[ERC20Transfer],
|
prior_transfers: List[Transfer],
|
||||||
child_transfers: List[ERC20Transfer],
|
child_transfers: List[Transfer],
|
||||||
) -> Optional[Swap]:
|
) -> Optional[Swap]:
|
||||||
pool_address = trace.to_address
|
pool_address = trace.to_address
|
||||||
recipient_address = _get_recipient_address(trace)
|
recipient_address = _get_recipient_address(trace)
|
||||||
|
@ -3,40 +3,57 @@ from typing import Dict, List, Optional, Sequence
|
|||||||
from mev_inspect.classifiers.specs import get_classifier
|
from mev_inspect.classifiers.specs import get_classifier
|
||||||
from mev_inspect.schemas.classifiers import TransferClassifier
|
from mev_inspect.schemas.classifiers import TransferClassifier
|
||||||
from mev_inspect.schemas.classified_traces import (
|
from mev_inspect.schemas.classified_traces import (
|
||||||
Classification,
|
|
||||||
ClassifiedTrace,
|
ClassifiedTrace,
|
||||||
DecodedCallTrace,
|
DecodedCallTrace,
|
||||||
)
|
)
|
||||||
from mev_inspect.schemas.transfers import ERC20Transfer, EthTransfer, TransferGeneric
|
from mev_inspect.schemas.transfers import ETH_TOKEN_ADDRESS, Transfer
|
||||||
from mev_inspect.traces import is_child_trace_address, get_child_traces
|
from mev_inspect.traces import is_child_trace_address, get_child_traces
|
||||||
|
|
||||||
|
|
||||||
def get_eth_transfers(traces: List[ClassifiedTrace]) -> List[EthTransfer]:
|
def get_transfers(traces: List[ClassifiedTrace]) -> List[Transfer]:
|
||||||
transfers = []
|
transfers = []
|
||||||
|
|
||||||
for trace in traces:
|
for trace in traces:
|
||||||
if trace.value is not None and trace.value > 0:
|
transfer = get_transfer(trace)
|
||||||
transfers.append(EthTransfer.from_trace(trace))
|
|
||||||
|
|
||||||
return transfers
|
|
||||||
|
|
||||||
|
|
||||||
def get_transfers(traces: List[ClassifiedTrace]) -> List[ERC20Transfer]:
|
|
||||||
transfers = []
|
|
||||||
|
|
||||||
for trace in traces:
|
|
||||||
if isinstance(trace, DecodedCallTrace):
|
|
||||||
transfer = get_erc20_transfer(trace)
|
|
||||||
if transfer is not None:
|
if transfer is not None:
|
||||||
transfers.append(transfer)
|
transfers.append(transfer)
|
||||||
|
|
||||||
return transfers
|
return transfers
|
||||||
|
|
||||||
|
|
||||||
def get_erc20_transfer(trace: DecodedCallTrace) -> Optional[ERC20Transfer]:
|
def get_eth_transfers(traces: List[ClassifiedTrace]) -> List[Transfer]:
|
||||||
if not isinstance(trace, DecodedCallTrace):
|
transfers = get_transfers(traces)
|
||||||
|
|
||||||
|
return [
|
||||||
|
transfer
|
||||||
|
for transfer in transfers
|
||||||
|
if transfer.token_address == ETH_TOKEN_ADDRESS
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def get_transfer(trace: ClassifiedTrace) -> Optional[Transfer]:
|
||||||
|
if trace.value is not None and trace.value > 0:
|
||||||
|
return _build_eth_transfer(trace)
|
||||||
|
|
||||||
|
if isinstance(trace, DecodedCallTrace):
|
||||||
|
return _build_erc20_transfer(trace)
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def _build_eth_transfer(trace: ClassifiedTrace) -> Transfer:
|
||||||
|
return Transfer(
|
||||||
|
block_number=trace.block_number,
|
||||||
|
transaction_hash=trace.transaction_hash,
|
||||||
|
trace_address=trace.trace_address,
|
||||||
|
amount=trace.value,
|
||||||
|
to_address=trace.to_address,
|
||||||
|
from_address=trace.from_address,
|
||||||
|
token_address=ETH_TOKEN_ADDRESS,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _build_erc20_transfer(trace: DecodedCallTrace) -> Optional[Transfer]:
|
||||||
classifier = get_classifier(trace)
|
classifier = get_classifier(trace)
|
||||||
if classifier is not None and issubclass(classifier, TransferClassifier):
|
if classifier is not None and issubclass(classifier, TransferClassifier):
|
||||||
return classifier.get_transfer(trace)
|
return classifier.get_transfer(trace)
|
||||||
@ -48,14 +65,11 @@ def get_child_transfers(
|
|||||||
transaction_hash: str,
|
transaction_hash: str,
|
||||||
parent_trace_address: List[int],
|
parent_trace_address: List[int],
|
||||||
traces: List[ClassifiedTrace],
|
traces: List[ClassifiedTrace],
|
||||||
) -> List[ERC20Transfer]:
|
) -> List[Transfer]:
|
||||||
child_transfers = []
|
child_transfers = []
|
||||||
|
|
||||||
for child_trace in get_child_traces(transaction_hash, parent_trace_address, traces):
|
for child_trace in get_child_traces(transaction_hash, parent_trace_address, traces):
|
||||||
if child_trace.classification == Classification.transfer and isinstance(
|
transfer = get_transfer(child_trace)
|
||||||
child_trace, DecodedCallTrace
|
|
||||||
):
|
|
||||||
transfer = get_erc20_transfer(child_trace)
|
|
||||||
if transfer is not None:
|
if transfer is not None:
|
||||||
child_transfers.append(transfer)
|
child_transfers.append(transfer)
|
||||||
|
|
||||||
@ -63,10 +77,10 @@ def get_child_transfers(
|
|||||||
|
|
||||||
|
|
||||||
def filter_transfers(
|
def filter_transfers(
|
||||||
transfers: Sequence[TransferGeneric],
|
transfers: Sequence[Transfer],
|
||||||
to_address: Optional[str] = None,
|
to_address: Optional[str] = None,
|
||||||
from_address: Optional[str] = None,
|
from_address: Optional[str] = None,
|
||||||
) -> List[TransferGeneric]:
|
) -> List[Transfer]:
|
||||||
filtered_transfers = []
|
filtered_transfers = []
|
||||||
|
|
||||||
for transfer in transfers:
|
for transfer in transfers:
|
||||||
@ -82,8 +96,8 @@ def filter_transfers(
|
|||||||
|
|
||||||
|
|
||||||
def remove_child_transfers_of_transfers(
|
def remove_child_transfers_of_transfers(
|
||||||
transfers: List[ERC20Transfer],
|
transfers: List[Transfer],
|
||||||
) -> List[ERC20Transfer]:
|
) -> List[Transfer]:
|
||||||
updated_transfers = []
|
updated_transfers = []
|
||||||
transfer_addresses_by_transaction: Dict[str, List[List[int]]] = {}
|
transfer_addresses_by_transaction: Dict[str, List[List[int]]] = {}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
from mev_inspect.schemas.transfers import ERC20Transfer
|
from mev_inspect.schemas.transfers import Transfer
|
||||||
from mev_inspect.transfers import remove_child_transfers_of_transfers
|
from mev_inspect.transfers import remove_child_transfers_of_transfers
|
||||||
|
|
||||||
|
|
||||||
@ -13,7 +13,7 @@ def test_remove_child_transfers_of_transfers(get_transaction_hashes, get_address
|
|||||||
third_token_address,
|
third_token_address,
|
||||||
] = get_addresses(5)
|
] = get_addresses(5)
|
||||||
|
|
||||||
outer_transfer = ERC20Transfer(
|
outer_transfer = Transfer(
|
||||||
block_number=123,
|
block_number=123,
|
||||||
transaction_hash=transaction_hash,
|
transaction_hash=transaction_hash,
|
||||||
trace_address=[0],
|
trace_address=[0],
|
||||||
@ -23,7 +23,7 @@ def test_remove_child_transfers_of_transfers(get_transaction_hashes, get_address
|
|||||||
token_address=first_token_address,
|
token_address=first_token_address,
|
||||||
)
|
)
|
||||||
|
|
||||||
inner_transfer = ERC20Transfer(
|
inner_transfer = Transfer(
|
||||||
**{
|
**{
|
||||||
**outer_transfer.dict(),
|
**outer_transfer.dict(),
|
||||||
**dict(
|
**dict(
|
||||||
@ -33,7 +33,7 @@ def test_remove_child_transfers_of_transfers(get_transaction_hashes, get_address
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
other_transfer = ERC20Transfer(
|
other_transfer = Transfer(
|
||||||
block_number=123,
|
block_number=123,
|
||||||
transaction_hash=transaction_hash,
|
transaction_hash=transaction_hash,
|
||||||
trace_address=[1],
|
trace_address=[1],
|
||||||
@ -43,7 +43,7 @@ def test_remove_child_transfers_of_transfers(get_transaction_hashes, get_address
|
|||||||
token_address=third_token_address,
|
token_address=third_token_address,
|
||||||
)
|
)
|
||||||
|
|
||||||
separate_transaction_transfer = ERC20Transfer(
|
separate_transaction_transfer = Transfer(
|
||||||
**{
|
**{
|
||||||
**inner_transfer.dict(),
|
**inner_transfer.dict(),
|
||||||
**dict(transaction_hash=other_transaction_hash),
|
**dict(transaction_hash=other_transaction_hash),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user