Skip to content

Commit 1165709

Browse files
authored
Merge pull request #52 from RichHorrocks/proxies-module
Proxies module additions
2 parents 6ad7187 + b15381b commit 1165709

22 files changed

+630
-20
lines changed

README.md

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,47 +2,52 @@
22

33
[![Build Status](https://secure.travis-ci.org/corpetty/py-etherscan-api.png?branch=master)](http://travis-ci.org/corpetty/py-etherscan-api) [![Join the chat at https://gitter.im/py-etherscan/Lobby](https://badges.gitter.im/py-etherscan/Lobby.svg)](https://gitter.im/py-etherscan/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
44

5-
65
EtherScan.io API python bindings
76

87
## Description
9-
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. If you are interacting with a contract on the Ropsten Testnet please use
11-
https://ropsten.etherscan.io/apis.
8+
9+
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. If you are interacting with a contract on the Ropsten Testnet please use
11+
https://ropsten.etherscan.io/apis.
1212
In order to use this, you must attain an Etherscan user account, and generate an API key.
1313

1414
In order to use the API, you must provide an API key at runtime, which can be found at the Etherscan.io API website.
1515
If you'd like to use the provided examples without altering them, then the JSON file `api_key.json` must be stored in
16-
the base directory. Its format is as follows:
16+
the base directory. Its format is as follows:
1717

1818
{ "key" : "YourApiKeyToken" }
19-
19+
2020
with `YourApiKeyToken` is your provided API key token from EtherScan.io
2121

2222
## Installation
23+
2324
To install the package to your computer, simply run the following command in the base directory:
2425

2526
python3 -m pip install py-etherscan-api
26-
2727

2828
## Available bindings
29+
2930
Currently, only the following Etherscan.io API modules are available:
3031

3132
- accounts
3233
- contracts
3334
- stats
3435
- tokens
3536
- proxies
37+
- blocks
38+
- transactions
3639

3740
The remaining available modules provided by Etherscan.io will be added eventually...
3841

3942
## Available Networks
43+
4044
Currently, this works for the following networks:
4145

4246
- Mainnet
4347
- Ropsten
4448

4549
## Examples
50+
4651
All possible calls have an associated example file in the examples folder to show how to call the binding
4752

4853
These of course will be fleshed out with more details and explanation in time
@@ -53,15 +58,15 @@ Jupyter notebooks area also included in each directory to show all examples
5358

5459
- Package and submit to PyPI
5560
- Add the following modules:
56-
- event logs
57-
- geth proxy
58-
- websockets
61+
- event logs
62+
- geth proxy
63+
- websockets
5964
- Add robust documentation
6065
- Add unit test suite
6166
- Add request throttling based on Etherscan's suggestions
6267

63-
6468
## Holla at ya' boy
69+
6570
BTC: 16Ny72US78VEjL5GUinSAavDwARb8dXWKG
6671

6772
ETH: 0x5E8047fc033499BD5d8C463ADb29f10f11165ed0

etherscan/blocks.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
from .client import Client
2+
from typing import Union
3+
4+
5+
class Blocks(Client):
6+
def __init__(self, api_key='YourApiKeyToken'):
7+
Client.__init__(self, address='', api_key=api_key)
8+
self.url_dict[self.MODULE] = 'block'
9+
10+
def get_block_reward(self, block_number: Union[str, int]):
11+
self.url_dict[self.ACTION] = 'getblockreward'
12+
self.url_dict[self.BLOCKNO] = block_number if type(
13+
block_number) is str else str(block_number)
14+
self.build_url()
15+
req = self.connect()
16+
return req['result']

etherscan/client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ class Client(object):
4848
TO = '&to='
4949
VALUE = '&value='
5050
DATA = '&data='
51-
POSITION = '&='
51+
POSITION = '&position='
5252
HEX = '&hex='
5353
GAS_PRICE = '&gasPrice='
5454
GAS = '&gas='

etherscan/client.ropsten.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ class Client(object):
4747
TO = '&to='
4848
VALUE = '&value='
4949
DATA = '&data='
50-
POSITION = '&='
50+
POSITION = '&position='
5151
HEX = '&hex='
5252
GAS_PRICE = '&gasPrice='
5353
GAS = '&gas='

etherscan/proxies.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,3 +74,27 @@ def get_transaction_receipt(self, tx_hash: str):
7474
self.build_url()
7575
req = self.connect()
7676
return req['result']
77+
78+
def get_code(self, address: str):
79+
self.url_dict[self.ACTION] = 'eth_getCode'
80+
self.url_dict[self.ADDRESS] = address
81+
self.url_dict[self.TAG] = 'latest'
82+
self.build_url()
83+
req = self.connect()
84+
return req['result']
85+
86+
def get_storage_at(self, address: str, position: Union[str, int]):
87+
self.url_dict[self.ACTION] = 'eth_getStorageAt'
88+
self.url_dict[self.ADDRESS] = address
89+
self.url_dict[self.POSITION] = position if type(
90+
position) is str else hex(position)
91+
self.url_dict[self.TAG] = 'latest'
92+
self.build_url()
93+
req = self.connect()
94+
return req['result']
95+
96+
def gas_price(self):
97+
self.url_dict[self.ACTION] = 'eth_gasPrice'
98+
self.build_url()
99+
req = self.connect()
100+
return req['result']

etherscan/transactions.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
from .client import Client
2+
3+
4+
class Transactions(Client):
5+
def __init__(self, api_key='YourApiKeyToken'):
6+
Client.__init__(self, address='', api_key=api_key)
7+
self.url_dict[self.MODULE] = 'transaction'
8+
9+
def get_status(self, tx_hash: str):
10+
self.url_dict[self.ACTION] = 'getstatus'
11+
self.url_dict[self.TXHASH] = tx_hash
12+
self.build_url()
13+
req = self.connect()
14+
return req['result']
15+
16+
def get_tx_receipt_status(self, tx_hash: str):
17+
self.url_dict[self.ACTION] = 'gettxreceiptstatus'
18+
self.url_dict[self.TXHASH] = tx_hash
19+
self.build_url()
20+
req = self.connect()
21+
return req['result']
Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "code",
5+
"execution_count": 2,
6+
"metadata": {},
7+
"outputs": [],
8+
"source": [
9+
"%load_ext autoreload\n",
10+
"%autoreload 2\n",
11+
"import etherscan.blocks as blocks\n",
12+
"import json"
13+
]
14+
},
15+
{
16+
"cell_type": "markdown",
17+
"metadata": {},
18+
"source": [
19+
"## Import our api_key"
20+
]
21+
},
22+
{
23+
"cell_type": "markdown",
24+
"metadata": {},
25+
"source": [
26+
"The JSON keyfile being read in has only one line in the format:\n",
27+
" \n",
28+
" {\"key\" : \"YourApiKey\" }"
29+
]
30+
},
31+
{
32+
"cell_type": "code",
33+
"execution_count": 4,
34+
"metadata": {},
35+
"outputs": [],
36+
"source": [
37+
"with open('../../api_key.json', mode='r') as key_file:\n",
38+
" key = json.loads(key_file.read())['key']"
39+
]
40+
},
41+
{
42+
"cell_type": "markdown",
43+
"metadata": {},
44+
"source": [
45+
"## Set up API"
46+
]
47+
},
48+
{
49+
"cell_type": "code",
50+
"execution_count": 5,
51+
"metadata": {},
52+
"outputs": [],
53+
"source": [
54+
"block = 2165403\n",
55+
"api = blocks.Blocks(api_key=key)"
56+
]
57+
},
58+
{
59+
"cell_type": "markdown",
60+
"metadata": {},
61+
"source": [
62+
"## Get the block reward"
63+
]
64+
},
65+
{
66+
"cell_type": "code",
67+
"execution_count": 7,
68+
"metadata": {
69+
"scrolled": false
70+
},
71+
"outputs": [],
72+
"source": [
73+
"reward = api.get_block_reward(block)"
74+
]
75+
},
76+
{
77+
"cell_type": "code",
78+
"execution_count": 9,
79+
"metadata": {},
80+
"outputs": [
81+
{
82+
"data": {
83+
"text/plain": [
84+
"{'blockNumber': '2165403',\n",
85+
" 'timeStamp': '1472533979',\n",
86+
" 'blockMiner': '0x13a06d3dfe21e0db5c016c03ea7d2509f7f8d1e3',\n",
87+
" 'blockReward': '5314181600000000000',\n",
88+
" 'uncles': [{'miner': '0xbcdfc35b86bedf72f0cda046a3c16829a2ef41d1',\n",
89+
" 'unclePosition': '0',\n",
90+
" 'blockreward': '3750000000000000000'},\n",
91+
" {'miner': '0x0d0c9855c722ff0c78f21e43aa275a5b8ea60dce',\n",
92+
" 'unclePosition': '1',\n",
93+
" 'blockreward': '3750000000000000000'}],\n",
94+
" 'uncleInclusionReward': '312500000000000000'}"
95+
]
96+
},
97+
"execution_count": 9,
98+
"metadata": {},
99+
"output_type": "execute_result"
100+
}
101+
],
102+
"source": [
103+
"reward"
104+
]
105+
},
106+
{
107+
"cell_type": "code",
108+
"execution_count": 10,
109+
"metadata": {},
110+
"outputs": [
111+
{
112+
"data": {
113+
"text/plain": [
114+
"'5314181600000000000'"
115+
]
116+
},
117+
"execution_count": 10,
118+
"metadata": {},
119+
"output_type": "execute_result"
120+
}
121+
],
122+
"source": [
123+
"reward['blockReward']"
124+
]
125+
},
126+
{
127+
"cell_type": "code",
128+
"execution_count": 11,
129+
"metadata": {},
130+
"outputs": [
131+
{
132+
"data": {
133+
"text/plain": [
134+
"'312500000000000000'"
135+
]
136+
},
137+
"execution_count": 11,
138+
"metadata": {},
139+
"output_type": "execute_result"
140+
}
141+
],
142+
"source": [
143+
"reward['uncleInclusionReward']"
144+
]
145+
},
146+
{
147+
"cell_type": "code",
148+
"execution_count": null,
149+
"metadata": {},
150+
"outputs": [],
151+
"source": []
152+
}
153+
],
154+
"metadata": {
155+
"kernelspec": {
156+
"display_name": "Python 3",
157+
"language": "python",
158+
"name": "python3"
159+
},
160+
"language_info": {
161+
"codemirror_mode": {
162+
"name": "ipython",
163+
"version": 3
164+
},
165+
"file_extension": ".py",
166+
"mimetype": "text/x-python",
167+
"name": "python",
168+
"nbconvert_exporter": "python",
169+
"pygments_lexer": "ipython3",
170+
"version": "3.7.0"
171+
},
172+
"latex_envs": {
173+
"bibliofile": "biblio.bib",
174+
"cite_by": "apalike",
175+
"current_citInitial": 1,
176+
"eqLabelWithNumbers": true,
177+
"eqNumInitial": 0
178+
},
179+
"toc": {
180+
"nav_menu": {
181+
"height": "121px",
182+
"width": "252px"
183+
},
184+
"navigate_menu": true,
185+
"number_sections": true,
186+
"sideBar": true,
187+
"threshold": 4,
188+
"toc_cell": false,
189+
"toc_section_display": "block",
190+
"toc_window_display": false
191+
}
192+
},
193+
"nbformat": 4,
194+
"nbformat_minor": 2
195+
}

examples/blocks/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
__author__ = 'Corey Petty'

examples/blocks/get_block_reward.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
from etherscan.blocks import Blocks
2+
import json
3+
4+
with open('../../api_key.json', mode='r') as key_file:
5+
key = json.loads(key_file.read())['key']
6+
7+
api = Blocks(api_key=key)
8+
reward = api.get_block_reward(2165403)
9+
print(reward)

examples/proxies/gas_price.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
from etherscan.proxies import Proxies
2+
import json
3+
4+
with open('../../api_key.json', mode='r') as key_file:
5+
key = json.loads(key_file.read())['key']
6+
7+
api = Proxies(api_key=key)
8+
price = api.gas_price()
9+
print(price)

0 commit comments

Comments
 (0)