Swamps, transfers, tests imp

This commit is contained in:
Gui Heise 2021-08-27 13:20:50 -04:00
parent 0f3070a08a
commit 27d71014bf
11 changed files with 181 additions and 100 deletions

View File

@ -1,8 +1,7 @@
from itertools import groupby from itertools import groupby
from typing import List, Optional from typing import List, Optional
from mev_inspect.schemas.arbitrages import Arbitrage from mev_inspect.schemas.classified_traces import Swap, Arbitrage
from mev_inspect.schemas.swaps import Swap
def get_arbitrages(swaps: List[Swap]) -> List[Arbitrage]: def get_arbitrages(swaps: List[Swap]) -> List[Arbitrage]:

View File

@ -2,7 +2,7 @@ from typing import List
from pydantic import BaseModel from pydantic import BaseModel
from .swaps import Swap from .classified_traces import Swap
class Arbitrage(BaseModel): class Arbitrage(BaseModel):

View File

@ -45,11 +45,8 @@ class TraceType(Enum):
class Trace(CamelModel): class Trace(CamelModel):
action: dict
block_hash: str
block_number: int block_number: int
result: Optional[dict] result: Optional[dict]
subtraces: int
trace_address: List[int] trace_address: List[int]
transaction_hash: Optional[str] transaction_hash: Optional[str]
transaction_position: Optional[int] transaction_position: Optional[int]

View File

@ -1,9 +1,14 @@
from enum import Enum from enum import Enum
from typing import Any, Dict, List, Optional from typing import Any, Dict, List, Optional
from pydantic import BaseModel from pydantic import BaseModel
from .blocks import TraceType from .blocks import Trace
from .utils import CamelModel
# -------- Enums ------------------------------------------------------------------------------
class Classification(Enum): class Classification(Enum):
@ -23,23 +28,29 @@ class Protocol(Enum):
curve = "curve" curve = "curve"
class ClassifiedTrace(BaseModel): # -------- Trace Models ------------------------------------------------------------------------------
class ClassifiedTrace(Trace):
transaction_hash: str transaction_hash: str
block_number: int block_number: int
trace_type: TraceType
trace_address: List[int] trace_address: List[int]
classification: Classification classification: Classification
protocol: Optional[Protocol] error: Optional[str]
abi_name: Optional[str] block_hash: Optional[str]
function_name: Optional[str] subtraces: Optional[int]
function_signature: Optional[str] action: Optional[dict]
inputs: Optional[Dict[str, Any]]
to_address: Optional[str] to_address: Optional[str]
from_address: Optional[str] from_address: Optional[str]
gas: Optional[int] gas: Optional[int]
value: Optional[int] value: Optional[int]
gas_used: Optional[int] gas_used: Optional[int]
error: Optional[str] protocol: Optional[Protocol]
function_name: Optional[str]
function_signature: Optional[str]
inputs: Optional[Dict[str, Any]]
abi_name: Optional[str]
class Config: class Config:
json_encoders = { json_encoders = {
@ -49,6 +60,135 @@ class ClassifiedTrace(BaseModel):
} }
class Call(ClassifiedTrace):
to_address: str
from_address: str
inputs: Dict[str, Any]
class ClassifiedCall(ClassifiedTrace):
gas: Optional[int]
gas_used: Optional[int]
function_name: Optional[str]
function_signature: Optional[str]
abi_name: str
class Config:
json_encoders = {
# a little lazy but fine for now
# this is used for bytes value inputs
bytes: lambda b: b.hex(),
}
# -------- Swaps ------------------------------------------------------------------------------
class Swap(BaseModel):
abi_name: str
transaction_hash: str
block_number: int
trace_address: List[int]
protocol: Optional[Protocol]
pool_address: str
from_address: str
to_address: str
token_in_address: str
token_in_amount: int
token_out_address: str
token_out_amount: int
error: Optional[str]
class Arbitrage(BaseModel):
swaps: List[Swap]
block_number: int
transaction_hash: str
account_address: str
profit_token_address: str
start_amount: int
end_amount: int
profit_amount: int
# -------- Transfers------------------------------------------------------------------------------
class Transfer(BaseModel):
transaction_hash: str
trace_address: List[int]
from_address: str
to_address: str
amount: int
token_address: str
@classmethod
def from_trace(cls, trace: ClassifiedTrace) -> "Transfer":
if trace.classification != Classification.transfer or trace.inputs is None:
raise ValueError("Invalid transfer")
if trace.protocol == Protocol.weth:
return cls(
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(
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,
)
# -------- Liquidations ------------------------------------------------------------------------------
class LiquidationType(Enum):
compound_v2_ceth_liquidation = "compound_v2_ceth_liquidation"
compound_v2_ctoken_liquidation = "compound_v2_ctoken_liquidation" # TODO: add logic to handle ctoken liquidations
class LiquidationStatus(Enum):
seized = "seized" # succesfully completed
check = "check" # just a liquidation check. i.e searcher only checks if opportunity is still available and reverts accordingly
out_of_gas = "out_of_gas" # tx ran out of gas
class LiquidationCollateralSource(Enum):
aave_flashloan = "aave_flashloan"
dydx_flashloan = "dydx_flashloan"
uniswap_flashloan = "uniswap_flashloan"
searcher_eoa = "searcher_eoa" # searchers own funds
searcher_contract = "searcher_contract"
other = "other"
class Liquidation(CamelModel):
tx_hash: str
borrower: str # account that got liquidated
collateral_provided: str # collateral provided by searcher, 'ether' or token contract address
collateral_provided_amount: int # amount of collateral provided
asset_seized: str # asset that was given to searcher at a discount upon liquidation
asset_seized_amount: int # amount of asset that was given to searcher upon liquidation
profit_in_eth: int # profit estimated by strategy inspector
tokenflow_estimate_in_eth: int # profit estimated by tokenflow
tokenflow_diff: int # diff between tokenflow and strategy inspector
status: LiquidationStatus
type: LiquidationType
collateral_source: LiquidationCollateralSource
# -------- Config ------------------------------------------------------------------------------
class ClassifierSpec(BaseModel): class ClassifierSpec(BaseModel):
abi_name: str abi_name: str
protocol: Optional[Protocol] = None protocol: Optional[Protocol] = None

View File

@ -1,21 +0,0 @@
from typing import List, Optional
from pydantic import BaseModel
from mev_inspect.schemas.classified_traces import Protocol
class Swap(BaseModel):
abi_name: str
transaction_hash: str
block_number: int
trace_address: List[int]
protocol: Optional[Protocol]
pool_address: str
from_address: str
to_address: str
token_in_address: str
token_in_amount: int
token_out_address: str
token_out_amount: int
error: Optional[str]

View File

@ -1,57 +0,0 @@
from typing import List, TypeVar
from pydantic import BaseModel
from .classified_traces import Classification, ClassifiedTrace, Protocol
class Transfer(BaseModel):
transaction_hash: str
trace_address: List[int]
from_address: str
to_address: str
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(
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
@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(
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(
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,
)

View File

@ -3,10 +3,16 @@ from typing import List, Optional
from mev_inspect.schemas.classified_traces import ( from mev_inspect.schemas.classified_traces import (
ClassifiedTrace, ClassifiedTrace,
Classification, Classification,
Swap,
Transfer,
) )
<<<<<<< HEAD
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 ERC20Transfer
from mev_inspect.traces import get_traces_by_transaction_hash from mev_inspect.traces import get_traces_by_transaction_hash
=======
>>>>>>> Swamps, transfers, tests imp
from mev_inspect.transfers import ( from mev_inspect.transfers import (
get_child_transfers, get_child_transfers,
filter_transfers, filter_transfers,

View File

@ -1,7 +1,15 @@
from typing import Dict, List, Optional, Sequence from typing import Dict, List, Optional, Sequence
<<<<<<< HEAD
from mev_inspect.schemas.classified_traces import Classification, ClassifiedTrace from mev_inspect.schemas.classified_traces import Classification, ClassifiedTrace
from mev_inspect.schemas.transfers import ERC20Transfer, EthTransfer, TransferGeneric from mev_inspect.schemas.transfers import ERC20Transfer, EthTransfer, TransferGeneric
=======
from mev_inspect.schemas.classified_traces import (
Classification,
ClassifiedTrace,
Transfer,
)
>>>>>>> Swamps, transfers, tests imp
from mev_inspect.traces import is_child_trace_address, get_child_traces from mev_inspect.traces import is_child_trace_address, get_child_traces

View File

@ -1,7 +1,12 @@
from typing import List from typing import List
from mev_inspect.schemas.blocks import TraceType from mev_inspect.schemas.blocks import TraceType
from mev_inspect.schemas.classified_traces import Classification, ClassifiedTrace from mev_inspect.schemas.classified_traces import (
Classification,
ClassifiedTrace,
Call,
ClassifiedCall,
)
def make_transfer_trace( def make_transfer_trace(
@ -13,10 +18,10 @@ def make_transfer_trace(
token_address: str, token_address: str,
amount: int, amount: int,
): ):
return ClassifiedTrace( return Call(
transaction_hash=transaction_hash, transaction_hash=transaction_hash,
block_number=block_number, block_number=block_number,
trace_type=TraceType.call, type=TraceType.call,
trace_address=trace_address, trace_address=trace_address,
classification=Classification.transfer, classification=Classification.transfer,
from_address=from_address, from_address=from_address,
@ -38,10 +43,10 @@ def make_swap_trace(
recipient_address: str, recipient_address: str,
recipient_input_key: str, recipient_input_key: str,
): ):
return ClassifiedTrace( return ClassifiedCall(
transaction_hash=transaction_hash, transaction_hash=transaction_hash,
block_number=block_number, block_number=block_number,
trace_type=TraceType.call, type=TraceType.call,
trace_address=trace_address, trace_address=trace_address,
classification=Classification.swap, classification=Classification.swap,
from_address=from_address, from_address=from_address,
@ -59,7 +64,7 @@ def make_unknown_trace(
return ClassifiedTrace( return ClassifiedTrace(
transaction_hash=transaction_hash, transaction_hash=transaction_hash,
block_number=block_number, block_number=block_number,
trace_type=TraceType.call, type=TraceType.call,
trace_address=trace_address, trace_address=trace_address,
classification=Classification.unknown, classification=Classification.unknown,
) )

View File

@ -1,5 +1,5 @@
from mev_inspect.arbitrages import get_arbitrages from mev_inspect.arbitrages import get_arbitrages
from mev_inspect.schemas.swaps import Swap from mev_inspect.schemas.classified_traces import Swap
from mev_inspect.swaps import ( from mev_inspect.swaps import (
UNISWAP_V2_PAIR_ABI_NAME, UNISWAP_V2_PAIR_ABI_NAME,
UNISWAP_V3_POOL_ABI_NAME, UNISWAP_V3_POOL_ABI_NAME,

View File

@ -1,4 +1,8 @@
<<<<<<< HEAD
from mev_inspect.schemas.transfers import ERC20Transfer from mev_inspect.schemas.transfers import ERC20Transfer
=======
from mev_inspect.schemas.classified_traces import Transfer
>>>>>>> Swamps, transfers, tests imp
from mev_inspect.transfers import remove_child_transfers_of_transfers from mev_inspect.transfers import remove_child_transfers_of_transfers