1
+ # coding: utf-8
2
+ import collections
3
+
4
+ import requests
5
+
6
+
7
+ class ClientException (Exception ):
8
+ """Unhandled API client exception"""
9
+ message = 'unhandled error'
10
+
11
+ def __init__ (self , message = None ):
12
+ if message is not None :
13
+ self .message = message
14
+
15
+ def __unicode__ (self ):
16
+ return u'<Err: {0.message}>' .format (self )
17
+
18
+ __str__ = __unicode__
19
+
20
+
21
+ class ConnectionRefused (ClientException ):
22
+ """Connection refused by remote host"""
23
+
24
+
25
+ class EmptyResponse (ClientException ):
26
+ """Empty response from API"""
27
+
28
+
29
+ class BadRequest (ClientException ):
30
+ """Invalid request passed"""
31
+
32
+
33
+ # Assume user puts his API key in the api_key.json file under variable name "key"
34
+ class Client (object ):
35
+ dao_address = '0xbb9bc244d798123fde783fcc1c72d3bb8c189413'
36
+
37
+ # Constants
38
+ PREFIX = 'https://api-ropsten.etherscan.io/api?' # TESTNET
39
+ MODULE = 'module='
40
+ ACTION = '&action='
41
+ CONTRACT_ADDRESS = '&contractaddress='
42
+ ADDRESS = '&address='
43
+ OFFSET = '&offset='
44
+ PAGE = '&page='
45
+ SORT = '&sort='
46
+ BLOCK_TYPE = '&blocktype='
47
+ TO = '&to='
48
+ VALUE = '&value='
49
+ DATA = '&data='
50
+ POSITION = '&='
51
+ HEX = '&hex='
52
+ GAS_PRICE = '&gasPrice='
53
+ GAS = '&gas='
54
+ START_BLOCK = '&startblock='
55
+ END_BLOCK = '&endblock='
56
+ BLOCKNO = '&blockno='
57
+ TXHASH = '&txhash='
58
+ TAG = '&tag='
59
+ BOOLEAN = '&boolean='
60
+ INDEX = '&index='
61
+ API_KEY = '&apikey='
62
+
63
+ url_dict = {}
64
+
65
+ def __init__ (self , address , api_key = '' ):
66
+ self .http = requests .session ()
67
+ self .url_dict = collections .OrderedDict ([
68
+
69
+ (self .MODULE , '' ),
70
+ (self .ADDRESS , '' ),
71
+ (self .OFFSET , '' ),
72
+ (self .PAGE , '' ),
73
+ (self .SORT , '' ),
74
+ (self .BLOCK_TYPE , '' ),
75
+ (self .TO , '' ),
76
+ (self .VALUE , '' ),
77
+ (self .DATA , '' ),
78
+ (self .POSITION , '' ),
79
+ (self .HEX , '' ),
80
+ (self .GAS_PRICE , '' ),
81
+ (self .GAS , '' ),
82
+ (self .START_BLOCK , '' ),
83
+ (self .END_BLOCK , '' ),
84
+ (self .BLOCKNO , '' ),
85
+ (self .TXHASH , '' ),
86
+ (self .TAG , '' ),
87
+ (self .BOOLEAN , '' ),
88
+ (self .INDEX , '' ),
89
+ (self .API_KEY , api_key )]
90
+ )
91
+
92
+ # self.url_dict[API_KEY] = str(api_key)
93
+ self .check_and_get_api ()
94
+ # self.key = self.URL_BASES['key'] + self.API_KEY
95
+
96
+ if (len (address ) > 20 ) and (type (address ) == list ):
97
+ raise BadRequest ("Etherscan only takes 20 addresses at a time" )
98
+ elif (type (address ) == list ) and (len (address ) <= 20 ):
99
+ self .url_dict [self .ADDRESS ] = ',' .join (address )
100
+ else :
101
+ self .url_dict [self .ADDRESS ] = address
102
+
103
+ def build_url (self ):
104
+ self .url = self .PREFIX + '' .join ([param + val if val else '' for param , val in self .url_dict .items ()])
105
+
106
+ def connect (self ):
107
+ # TODO: deal with "unknown exception" error
108
+ try :
109
+ req = self .http .get (self .url )
110
+ except requests .exceptions .ConnectionError :
111
+ raise ConnectionRefused
112
+
113
+ if req .status_code == 200 :
114
+ # Check for empty response
115
+ if req .text :
116
+ data = req .json ()
117
+ status = data .get ('status' )
118
+ if status == '1' or self .check_keys_api (data ):
119
+ return data
120
+ else :
121
+ raise EmptyResponse (data .get ('message' , 'no message' ))
122
+ raise BadRequest ("Problem with connection, status code: %s" % req .status_code )
123
+
124
+ def check_and_get_api (self ):
125
+ if self .url_dict [self .API_KEY ]: # Check if api_key is empty string
126
+ pass
127
+ else :
128
+ self .url_dict [self .API_KEY ] = input ('Please type your EtherScan.io API key: ' )
129
+
130
+ def check_keys_api (self , data ):
131
+ return all (k in data for k in ('jsonrpc' , 'id' , 'result' ))
132
+
0 commit comments