-
Notifications
You must be signed in to change notification settings - Fork 38
/
transaction_event.py
124 lines (111 loc) · 4.66 KB
/
transaction_event.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
import json
from hexbytes import HexBytes
from .event_type import EventType
from .network import Network
from .transaction import Transaction
from .receipt import Log
from .trace import Trace
class TxEventBlock:
def __init__(self, dict):
self.hash = dict.get('hash')
self.number = dict.get('number')
self.timestamp = dict.get('timestamp')
class TransactionEvent:
def __init__(self, dict):
typeVal = dict.get('type', "BLOCK")
self.type = EventType[typeVal] if type(
typeVal) == str else EventType(typeVal)
networkVal = dict.get('network', "MAINNET")
networkVal = int(networkVal) if type(
networkVal) == str and networkVal.isdigit() else networkVal
self.network = Network[networkVal] if type(
networkVal) == str else Network(networkVal)
self.transaction = Transaction(dict.get('transaction', {}))
self.traces = list(map(lambda t: Trace(t), dict.get('traces', [])))
self.addresses = dict.get('addresses', {})
self.block = TxEventBlock(dict.get('block', {}))
self.logs = list(map(lambda l: Log(l), dict.get('logs', [])))
self.contract_address = dict.get(
'contractAddress', dict.get('contract_address'))
@property
def hash(self):
return self.transaction.hash
@property
def to(self):
return self.transaction.to
@property
def from_(self):
return self.transaction.from_
@property
def gas_price(self):
return self.transaction.gas_price
@property
def timestamp(self):
return self.block.timestamp
@property
def block_number(self):
return self.block.number
@property
def block_hash(self):
return self.block.hash
def filter_log(self, abi, contract_address=''):
abi = abi if isinstance(abi, list) else [abi]
abi = [json.loads(abi_item) for abi_item in abi]
logs = self.logs
# filter logs by contract address, if provided
if (contract_address):
contract_address = contract_address if isinstance(
contract_address, list) else [contract_address]
contract_address_map = {
address.lower(): True for address in contract_address}
logs = filter(lambda log: log.address.lower()
in contract_address_map, logs)
# determine which event names to filter
event_names = []
for abi_item in abi:
if abi_item['type'] == "event":
event_names.append(abi_item['name'])
# parse logs
results = []
from . import web3Provider
contract = web3Provider.eth.contract(
"0x0000000000000000000000000000000000000000", abi=abi)
for log in logs:
log.topics = [HexBytes(topic) for topic in log.topics]
for event_name in event_names:
try:
results.append(
contract.events[event_name]().processLog(log))
except:
continue # TODO see if theres a better way to handle 'no matching event' error
return results
def filter_function(self, abi, contract_address=''):
abi = abi if isinstance(abi, list) else [abi]
abi = [json.loads(abi_object) for abi_object in abi]
# determine where to look for function calls (i.e. transaction object or traces)
sources = [{'data': self.transaction.data, 'to': self.transaction.to}]
if self.traces:
sources = [{'data': trace.action.input,
'to': trace.action.to} for trace in self.traces]
# filter by contract address, if provided
if (contract_address):
contract_address = contract_address if isinstance(
contract_address, list) else [contract_address]
contract_address_map = {
address.lower(): True for address in contract_address}
sources = filter(
lambda source: source['to'] and source['to'].lower() in contract_address_map, sources)
# parse function inputs
results = []
from . import web3Provider
contract = web3Provider.eth.contract(
"0x0000000000000000000000000000000000000000", abi=abi)
for source in sources:
try:
decoded_function = contract.decode_function_input(
source['data'])
decoded_function[1]["address"] = source['to'].lower()
results.append(decoded_function)
except:
continue # TODO see if theres a better way to handle 'no matching function' error
return results