Skip to content

Commit

Permalink
Merge branch 'release/20200320'
Browse files Browse the repository at this point in the history
  • Loading branch information
AndreMiras committed Mar 21, 2020
2 parents db3eca7 + 07dd531 commit 727d33b
Show file tree
Hide file tree
Showing 10 changed files with 58 additions and 30 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
@@ -1,5 +1,9 @@
# Change Log

## [20200320]

- Move API keys to env var, refs #9

## [20191108]

- Fix Ropsten 403 errors
Expand Down
5 changes: 5 additions & 0 deletions README.md
Expand Up @@ -37,6 +37,11 @@ etheroll = Etheroll(chain_id, contract_address)

Find out more in [docs/Examples.md](docs/Examples.md).

## API keys
Both Etherscan and Infura require API keys which are retrieved from the following environment variables:
- `ETHERSCAN_API_KEY` (consumed by pyetheroll directly)
- `WEB3_INFURA_PROJECT_ID` (consumed by [web3.py](https://github.com/ethereum/web3.py))

## Install

[Latest stable release](https://github.com/AndreMiras/pyetheroll/tree/master):
Expand Down
5 changes: 5 additions & 0 deletions docs/changelog.rst
@@ -0,0 +1,5 @@
CHANGELOG
=========

.. mdinclude:: ../CHANGELOG.md

1 change: 1 addition & 0 deletions docs/index.rst
Expand Up @@ -13,6 +13,7 @@ Welcome to pyetheroll's documentation!
readme.rst
Examples.md
Release.md
changelog.rst


Indices and tables
Expand Down
3 changes: 2 additions & 1 deletion pyetheroll/constants.py
Expand Up @@ -3,7 +3,8 @@
ROUND_DIGITS = 2
DEFAULT_GAS_PRICE_GWEI = 4
DEFAULT_GAS_PRICE_WEI = int(DEFAULT_GAS_PRICE_GWEI * 1e9)
DEFAULT_API_KEY_TOKEN = "YourApiKeyToken"
DEFAULT_ETHERSCAN_API_KEY = "YourApiKeyToken"
DEFAULT_INFURA_PROJECT_ID = "7c841c560b1e4660a9683507cb27b2f8"


class ChainID(Enum):
Expand Down
31 changes: 12 additions & 19 deletions pyetheroll/etheroll.py
Expand Up @@ -13,12 +13,7 @@
from web3 import Web3
from web3.contract import Contract

from pyetheroll.constants import (
DEFAULT_API_KEY_TOKEN,
DEFAULT_GAS_PRICE_WEI,
ROUND_DIGITS,
ChainID,
)
from pyetheroll.constants import DEFAULT_GAS_PRICE_WEI, ROUND_DIGITS, ChainID
from pyetheroll.etherscan_utils import (
ChainEtherscanAccountFactory,
ChainEtherscanContractFactory,
Expand All @@ -27,7 +22,7 @@
HTTPProviderFactory,
TransactionDebugger,
)
from pyetheroll.utils import timestamp2datetime
from pyetheroll.utils import get_etherscan_api_key, timestamp2datetime

REQUESTS_CACHE_PARAMS = {
"cache_name": "requests_cache",
Expand Down Expand Up @@ -83,7 +78,6 @@ class Etheroll:

def __init__(
self,
api_key: str = DEFAULT_API_KEY_TOKEN,
chain_id: ChainID = ChainID.MAINNET,
contract_address: str = None,
):
Expand All @@ -96,7 +90,7 @@ def __init__(
# self.provider = EthereumTesterProvider(ethereum_tester)
self.provider = HTTPProviderFactory.create(self.chain_id)
self.web3 = Web3(self.provider)
self.etherscan_api_key = api_key
self.etherscan_api_key = get_etherscan_api_key()
ChainEtherscanContract = ChainEtherscanContractFactory.create(
self.chain_id
)
Expand All @@ -111,7 +105,8 @@ def __init__(
address=self.contract_address, api_key=self.etherscan_api_key
)
self.etherscan_contract_api.http.headers = update_user_agent(
self.etherscan_contract_api.http.headers)
self.etherscan_contract_api.http.headers
)
self.contract_abi = json.loads(
self.etherscan_contract_api.get_abi()
)
Expand All @@ -130,22 +125,18 @@ def __init__(

@classmethod
def get_or_create(
cls,
api_key: str = DEFAULT_API_KEY_TOKEN,
chain_id: ChainID = ChainID.MAINNET,
contract_address: str = None,
cls, chain_id: ChainID = ChainID.MAINNET, contract_address: str = None,
):
"""
Gets or creates the Etheroll object.
Also recreates the object if one init property changed.
"""
contract_address = contract_address or cls.CONTRACT_ADDRESSES[chain_id]
if cls._etheroll is None or (
cls._etheroll.etherscan_api_key,
cls._etheroll.chain_id,
cls._etheroll.contract_address,
) != (api_key, chain_id, contract_address):
cls._etheroll = cls(api_key, chain_id, contract_address)
) != (chain_id, contract_address):
cls._etheroll = cls(chain_id, contract_address)
return cls._etheroll

def definitions(self, contract_abi, typ):
Expand Down Expand Up @@ -284,7 +275,8 @@ def get_transaction_page(
address=address, api_key=self.etherscan_api_key
)
etherscan_account_api.http.headers = update_user_agent(
etherscan_account_api.http.headers)
etherscan_account_api.http.headers
)
sort = "desc"
try:
transactions = etherscan_account_api.get_transaction_page(
Expand Down Expand Up @@ -612,7 +604,8 @@ def get_balance(self, address):
address=address, api_key=self.etherscan_api_key
)
etherscan_account_api.http.headers = update_user_agent(
etherscan_account_api.http.headers)
etherscan_account_api.http.headers
)
balance_wei = int(etherscan_account_api.get_balance())
balance_eth = round(balance_wei / 1e18, ROUND_DIGITS)
return balance_eth
16 changes: 10 additions & 6 deletions pyetheroll/transaction_debugger.py
Expand Up @@ -4,8 +4,9 @@
from eth_utils import decode_hex, function_abi_to_4byte_selector
from web3 import HTTPProvider, Web3

from pyetheroll.constants import DEFAULT_API_KEY_TOKEN, ChainID
from pyetheroll.constants import ChainID
from pyetheroll.etherscan_utils import ChainEtherscanContractFactory
from pyetheroll.utils import get_etherscan_api_key, get_infura_project_id


def decode_contract_call(contract_abi: list, call_data: str):
Expand All @@ -30,10 +31,14 @@ class HTTPProviderFactory:
# ChainID.MAINNET: 'https://api.myetherapi.com/eth',
# ChainID.MAINNET: 'https://api.infura.io/v1/jsonrpc/mainnet',
# ChainID.MAINNET: 'https://api.mycryptoapi.com/eth',
ChainID.MAINNET: "https://mainnet.infura.io",
ChainID.MAINNET: (
f"https://mainnet.infura.io/v3/{get_infura_project_id()}"
),
# ChainID.ROPSTEN: 'https://api.myetherapi.com/rop',
# ChainID.ROPSTEN: 'https://api.infura.io/v1/jsonrpc/ropsten',
ChainID.ROPSTEN: "https://ropsten.infura.io",
ChainID.ROPSTEN: (
f"https://ropsten.infura.io/v3/{get_infura_project_id()}"
),
}

@classmethod
Expand All @@ -48,13 +53,12 @@ def __init__(self, contract_abi):
self.methods_infos = None

@staticmethod
def get_contract_abi(
chain_id, contract_address, api_key: str = DEFAULT_API_KEY_TOKEN
) -> dict:
def get_contract_abi(chain_id, contract_address) -> dict:
"""
Given a contract address returns the contract ABI from Etherscan,
refs #2
"""
api_key = get_etherscan_api_key()
ChainEtherscanContract = ChainEtherscanContractFactory.create(chain_id)
api = ChainEtherscanContract(address=contract_address, api_key=api_key)
json_abi = api.get_abi()
Expand Down
17 changes: 16 additions & 1 deletion pyetheroll/utils.py
@@ -1,6 +1,11 @@
import os
from datetime import datetime

from pyetheroll.constants import ROUND_DIGITS
from pyetheroll.constants import (
DEFAULT_ETHERSCAN_API_KEY,
DEFAULT_INFURA_PROJECT_ID,
ROUND_DIGITS,
)


class EtherollUtils:
Expand Down Expand Up @@ -34,3 +39,13 @@ def timestamp2datetime(timestamp: str) -> datetime:
base = 16
date_time = datetime.utcfromtimestamp(int(timestamp, base))
return date_time


def get_etherscan_api_key():
"""Returns ETHERSCAN_API_KEY from environment variable."""
return os.environ.get("ETHERSCAN_API_KEY", DEFAULT_ETHERSCAN_API_KEY)


def get_infura_project_id():
"""Returns WEB3_INFURA_PROJECT_ID from environment variable."""
return os.environ.get("WEB3_INFURA_PROJECT_ID", DEFAULT_INFURA_PROJECT_ID)
2 changes: 1 addition & 1 deletion setup.py
Expand Up @@ -11,7 +11,7 @@ def read(fname):
# exposing the params so it can be imported
setup_params = {
"name": "pyetheroll",
"version": "20191108",
"version": "20200320",
"description": "Python library to Etheroll smart contract",
"long_description": read("README.md"),
"long_description_content_type": "text/markdown",
Expand Down
4 changes: 2 additions & 2 deletions tests/test_etheroll.py
Expand Up @@ -624,7 +624,7 @@ def test_get_log_bet_events(self):
"&topic2=0x"
"00000000000000000000000046044beaa1e985c67767e04de58181de5daaa00f"
"&topic0_2_opr=and&",
headers={'User-Agent': 'https://github.com/AndreMiras/pyetheroll'},
headers={"User-Agent": "https://github.com/AndreMiras/pyetheroll"},
)
expected_calls = [expected_call]
assert m_get.call_args_list == expected_calls
Expand Down Expand Up @@ -655,7 +655,7 @@ def test_get_log_result_events(self):
"&topic3=0x"
"00000000000000000000000046044beaa1e985c67767e04de58181de5daaa00f"
"&topic0_3_opr=and&",
headers={'User-Agent': 'https://github.com/AndreMiras/pyetheroll'},
headers={"User-Agent": "https://github.com/AndreMiras/pyetheroll"},
)
expected_calls = [expected_call]
assert m_get.call_args_list == expected_calls
Expand Down

0 comments on commit 727d33b

Please sign in to comment.