Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions etherscan/accounts.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ class Account(Client):
PAGE_NUM_PATTERN = re.compile(
r'[1-9](?:\d{0,2})(?:,\d{3})*(?:\.\d*[1-9])?|0?\.\d*[1-9]|0')

def __init__(self, address=Client.dao_address, api_key='YourApiKeyToken'):
Client.__init__(self, address=address, api_key=api_key)
def __init__(self, address=Client.dao_address, chain_id=1, api_key='YourApiKeyToken'):
Client.__init__(self, address=address, chain_id=chain_id, api_key=api_key)
self.url_dict[self.MODULE] = 'account'

def get_balance(self):
Expand Down
4 changes: 2 additions & 2 deletions etherscan/blocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@


class Blocks(Client):
def __init__(self, api_key='YourApiKeyToken'):
Client.__init__(self, address='', api_key=api_key)
def __init__(self, chain_id=1, api_key='YourApiKeyToken'):
Client.__init__(self, address='', chain_id=chain_id, api_key=api_key)
self.url_dict[self.MODULE] = 'block'

def get_block_reward(self, block_number: Union[str, int]):
Expand Down
9 changes: 6 additions & 3 deletions etherscan/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,9 @@ class Client(object):
dao_address = '0xbb9bc244d798123fde783fcc1c72d3bb8c189413'

# Constants
PREFIX = 'https://api.etherscan.io/api?'
MODULE = 'module='
PREFIX = 'https://api.etherscan.io/v2/api?'
CHAINID = 'chainid='
MODULE = '&module='
ACTION = '&action='
CONTRACT_ADDRESS = '&contractaddress='
ADDRESS = '&address='
Expand Down Expand Up @@ -72,9 +73,11 @@ class Client(object):

url_dict = {}

def __init__(self, address, api_key=''):
def __init__(self, address, chain_id=1, api_key=''):
self.http = requests.session()
self.chain_id = str(chain_id)
self.url_dict = collections.OrderedDict([
(self.CHAINID, self.chain_id),
(self.MODULE, ''),
(self.ADDRESS, ''),
(self.OFFSET, ''),
Expand Down
165 changes: 32 additions & 133 deletions etherscan/client.ropsten.py
Original file line number Diff line number Diff line change
@@ -1,134 +1,33 @@
# coding: utf-8
import collections

import requests


class ClientException(Exception):
"""Unhandled API client exception"""
message = 'unhandled error'

def __init__(self, message=None):
if message is not None:
self.message = message

def __unicode__(self):
return u'<Err: {0.message}>'.format(self)

__str__ = __unicode__


class ConnectionRefused(ClientException):
"""Connection refused by remote host"""


class EmptyResponse(ClientException):
"""Empty response from API"""


class BadRequest(ClientException):
"""Invalid request passed"""


# API key must be in the api_key.json file under variable name "key"
class Client(object):
dao_address = '0xbb9bc244d798123fde783fcc1c72d3bb8c189413'

# Constants
PREFIX = 'https://api-ropsten.etherscan.io/api?' # TESTNET
MODULE = 'module='
ACTION = '&action='
CONTRACT_ADDRESS = '&contractaddress='
ADDRESS = '&address='
OFFSET = '&offset='
PAGE = '&page='
SORT = '&sort='
BLOCK_TYPE = '&blocktype='
TO = '&to='
VALUE = '&value='
DATA = '&data='
POSITION = '&position='
HEX = '&hex='
GAS_PRICE = '&gasPrice='
GAS = '&gas='
START_BLOCK = '&startblock='
END_BLOCK = '&endblock='
BLOCKNO = '&blockno='
TXHASH = '&txhash='
TAG = '&tag='
BOOLEAN = '&boolean='
INDEX = '&index='
API_KEY = '&apikey='

url_dict = {}

def __init__(self, address, api_key=''):
self.http = requests.session()
self.url_dict = collections.OrderedDict([

(self.MODULE, ''),
(self.ADDRESS, ''),
(self.OFFSET, ''),
(self.PAGE, ''),
(self.SORT, ''),
(self.BLOCK_TYPE, ''),
(self.TO, ''),
(self.VALUE, ''),
(self.DATA, ''),
(self.POSITION, ''),
(self.HEX, ''),
(self.GAS_PRICE, ''),
(self.GAS, ''),
(self.START_BLOCK, ''),
(self.END_BLOCK, ''),
(self.BLOCKNO, ''),
(self.TXHASH, ''),
(self.TAG, ''),
(self.BOOLEAN, ''),
(self.INDEX, ''),
(self.API_KEY, api_key)]
)

# self.url_dict[API_KEY] = str(api_key)
self.check_and_get_api()
# self.key = self.URL_BASES['key'] + self.API_KEY

if (len(address) > 20) and (type(address) == list):
raise BadRequest("Etherscan only takes 20 addresses at a time")
elif (type(address) == list) and (len(address) <= 20):
self.url_dict[self.ADDRESS] = ','.join(address)
else:
self.url_dict[self.ADDRESS] = address

def build_url(self):
self.url = self.PREFIX + ''.join(
[parm + val if val else '' for parm, val in self.url_dict.items()])

def connect(self):
# TODO: deal with "unknown exception" error
try:
req = self.http.get(self.url)
except requests.exceptions.ConnectionError:
raise ConnectionRefused

if req.status_code == 200:
# Check for empty response
if req.text:
data = req.json()
status = data.get('status')
if status == '1' or self.check_keys_api(data):
return data
else:
raise EmptyResponse(data.get('message', 'no message'))
raise BadRequest(
f"Problem with connection, status code: {req.status_code}")

def check_and_get_api(self):
if self.url_dict[self.API_KEY]: # Check if api_key is empty string
pass
else:
self.url_dict[self.API_KEY] = input(
'Please type your EtherScan.io API key: ')

def check_keys_api(self, data):
return all(k in data for k in ('jsonrpc', 'id', 'result'))
import warnings
from .client import Client as MainClient
from .client import (
ClientException,
ConnectionRefused,
EmptyResponse,
BadRequest,
InvalidAPIKey
)

# dao_address was present in the original ropsten client and is also in the main client.
# Keeping it here for compatibility if any code specifically imports it from client.ropsten.
dao_address = '0xbb9bc244d798123fde783fcc1c72d3bb8c189413'

def Client(address, api_key=''):
"""
Initializes a client for the Ropsten testnet using the main Etherscan API V2 client.

This Ropsten-specific client is deprecated. Users should transition to importing
Client directly from `etherscan.client` and specifying `chain_id=3`.
"""
warnings.warn(
"The Client in etherscan.client.ropsten is deprecated and will be removed in a future version. "
"Please use `from etherscan.client import Client` and initialize with `chain_id=3` for Ropsten.",
DeprecationWarning,
stacklevel=2
)
return MainClient(address=address, chain_id=3, api_key=api_key)

# Ensure that only explicitly re-defined or imported names are available.
# All other constants and the old Client class from the original client.ropsten.py are now gone.
__all__ = ['Client', 'ClientException', 'ConnectionRefused', 'EmptyResponse', 'BadRequest', 'InvalidAPIKey', 'dao_address']
4 changes: 2 additions & 2 deletions etherscan/contracts.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@


class Contract(Client):
def __init__(self, address=Client.dao_address, api_key='YourApiKeyToken'):
Client.__init__(self, address=address, api_key=api_key)
def __init__(self, address=Client.dao_address, chain_id=1, api_key='YourApiKeyToken'):
Client.__init__(self, address=address, chain_id=chain_id, api_key=api_key)
self.url_dict[self.MODULE] = 'contract'

def get_abi(self):
Expand Down