Skip to content

Commit 18ee101

Browse files
authored
Merge pull request #41 from Qwoyn/master
Created client.ropsten.py. Merged despite comment from @AndreMiras, this can be refactored, rather have the functionality first. I do agree that your solution was an easier method.
2 parents 883117b + 6b8fcc3 commit 18ee101

File tree

2 files changed

+135
-1
lines changed

2 files changed

+135
-1
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ EtherScan.io API python bindings
77

88
## Description
99
This module is written as an effort to provide python bindings to the EtherScan.io API, which can be found at:
10-
https://etherscan.io/apis
10+
https://etherscan.io/apis. If you are interacting with a contract on the Ropsten Testnet please use
11+
https://ropsten.etherscan.io/apis.
1112
In order to use this, you must attain an Etherscan user account, and generate an API key.
1213

1314
In order to use the API, you must provide an API key at runtime, which can be found at the Etherscan.io API website.
@@ -22,6 +23,7 @@ with `YourApiKeyToken` is your provided API key token from EtherScan.io
2223
To install the package to your computer, simply run the following command in the base directory:
2324

2425
python setup.py install
26+
2527

2628
## Available bindings
2729
Currently, only the following Etherscan.io API modules are available:

etherscan/client.ropsten.py

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
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

Comments
 (0)