blockapi 1.2.0__tar.gz → 1.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {blockapi-1.2.0 → blockapi-1.3.0}/PKG-INFO +1 -1
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/__init__.py +0 -25
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/test/v2/test_enumerate_classes.py +0 -2
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi.egg-info/PKG-INFO +1 -1
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi.egg-info/SOURCES.txt +0 -56
- {blockapi-1.2.0 → blockapi-1.3.0}/setup.py +1 -1
- blockapi-1.2.0/blockapi/api/__init__.py +0 -32
- blockapi-1.2.0/blockapi/api/alethio.py +0 -372
- blockapi-1.2.0/blockapi/api/amberdata.py +0 -152
- blockapi-1.2.0/blockapi/api/binance.py +0 -75
- blockapi-1.2.0/blockapi/api/blockchaininfo.py +0 -81
- blockapi-1.2.0/blockapi/api/blockchainos.py +0 -92
- blockapi-1.2.0/blockapi/api/blockchair.py +0 -196
- blockapi-1.2.0/blockapi/api/blockcypher.py +0 -45
- blockapi-1.2.0/blockapi/api/blockonomics.py +0 -76
- blockapi-1.2.0/blockapi/api/blockscout.py +0 -104
- blockapi-1.2.0/blockapi/api/btc.py +0 -35
- blockapi-1.2.0/blockapi/api/cardanoexplorer.py +0 -84
- blockapi-1.2.0/blockapi/api/chainso.py +0 -94
- blockapi-1.2.0/blockapi/api/cosmos.py +0 -339
- blockapi-1.2.0/blockapi/api/cryptoid.py +0 -51
- blockapi-1.2.0/blockapi/api/dcrdata.py +0 -227
- blockapi-1.2.0/blockapi/api/digonchain.py +0 -40
- blockapi-1.2.0/blockapi/api/eospark.py +0 -57
- blockapi-1.2.0/blockapi/api/etherscan.py +0 -144
- blockapi-1.2.0/blockapi/api/ethplorer.py +0 -67
- blockapi-1.2.0/blockapi/api/greymass.py +0 -45
- blockapi-1.2.0/blockapi/api/insight.py +0 -84
- blockapi-1.2.0/blockapi/api/kyber.py +0 -175
- blockapi-1.2.0/blockapi/api/neoscan.py +0 -107
- blockapi-1.2.0/blockapi/api/ontology.py +0 -35
- blockapi-1.2.0/blockapi/api/solana.py +0 -155
- blockapi-1.2.0/blockapi/api/stellar.py +0 -41
- blockapi-1.2.0/blockapi/api/subscan.py +0 -284
- blockapi-1.2.0/blockapi/api/terra_money.py +0 -138
- blockapi-1.2.0/blockapi/api/trezor.py +0 -87
- blockapi-1.2.0/blockapi/api/tronscan.py +0 -75
- blockapi-1.2.0/blockapi/api/tzscan.py +0 -312
- blockapi-1.2.0/blockapi/api/tzstats.py +0 -29
- blockapi-1.2.0/blockapi/api/zchain.py +0 -31
- blockapi-1.2.0/blockapi/api/zensystem.py +0 -31
- blockapi-1.2.0/blockapi/test/api/test_amberdata.py +0 -29
- blockapi-1.2.0/blockapi/test/api/test_balances.py +0 -28
- blockapi-1.2.0/blockapi/test/api/test_binance.py +0 -28
- blockapi-1.2.0/blockapi/test/api/test_blockchainos.py +0 -23
- blockapi-1.2.0/blockapi/test/api/test_blockchair.py +0 -23
- blockapi-1.2.0/blockapi/test/api/test_blockscout.py +0 -26
- blockapi-1.2.0/blockapi/test/api/test_btc.py +0 -15
- blockapi-1.2.0/blockapi/test/api/test_cosmos.py +0 -68
- blockapi-1.2.0/blockapi/test/api/test_dcrdata.py +0 -78
- blockapi-1.2.0/blockapi/test/api/test_digonchain.py +0 -15
- blockapi-1.2.0/blockapi/test/api/test_insight.py +0 -15
- blockapi-1.2.0/blockapi/test/api/test_kyber.py +0 -88
- blockapi-1.2.0/blockapi/test/api/test_ontio.py +0 -13
- blockapi-1.2.0/blockapi/test/api/test_solana.py +0 -38
- blockapi-1.2.0/blockapi/test/api/test_subscan.py +0 -41
- blockapi-1.2.0/blockapi/test/api/test_terra_money.py +0 -41
- blockapi-1.2.0/blockapi/test/api/test_tronscan.py +0 -16
- blockapi-1.2.0/blockapi/test/api/test_tzscan.py +0 -44
- blockapi-1.2.0/blockapi/test/api/test_tzstats.py +0 -31
- blockapi-1.2.0/blockapi/utils/__init__.py +0 -1
- blockapi-1.2.0/blockapi/utils/ethereum.py +0 -259
- {blockapi-1.2.0 → blockapi-1.3.0}/LICENSE.md +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/README.md +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/services.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/test/__init__.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/test/test_blockapi.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/test/test_num.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/test/test_random_user_agent.py +0 -0
- {blockapi-1.2.0/blockapi/test/api → blockapi-1.3.0/blockapi/test/v2}/__init__.py +0 -0
- {blockapi-1.2.0/blockapi/test/v2 → blockapi-1.3.0/blockapi/test/v2/api}/__init__.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/test/v2/api/conftest.py +0 -0
- {blockapi-1.2.0/blockapi/test/v2/api → blockapi-1.3.0/blockapi/test/v2/api/covalenth}/__init__.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/test/v2/api/covalenth/test_ethereum.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/test/v2/api/fake_sleep_provider.py +0 -0
- {blockapi-1.2.0/blockapi/test/v2/api/covalenth → blockapi-1.3.0/blockapi/test/v2/api/nft}/__init__.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/test/v2/api/nft/test_magic_eden.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/test/v2/api/nft/test_opensea.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/test/v2/api/nft/test_simple_hash.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/test/v2/api/nft/test_unisat.py +0 -0
- {blockapi-1.2.0/blockapi/test/v2/api/nft → blockapi-1.3.0/blockapi/test/v2/api/perpetual}/__init__.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/test/v2/api/perpetual/test_perpetual.py +0 -0
- {blockapi-1.2.0/blockapi/test/v2/api/perpetual → blockapi-1.3.0/blockapi/test/v2/api/synthetix}/__init__.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/test/v2/api/synthetix/test_synthetix.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/test/v2/api/test_blockchainos.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/test/v2/api/test_blockchair_btc.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/test/v2/api/test_blockchair_doge.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/test/v2/api/test_blockchair_ltc.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/test/v2/api/test_cosmos.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/test/v2/api/test_ethplorer.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/test/v2/api/test_multisources.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/test/v2/api/test_optimistic_etherscan.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/test/v2/api/test_solana.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/test/v2/api/test_subscan_polkadot.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/test/v2/api/test_sui.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/test/v2/api/test_trezor_btc.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/test/v2/test_base.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/test/v2/test_blockchain_api.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/test/v2/test_blockchain_mapping.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/test/v2/test_data.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/test/v2/test_generic.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/test/v2/test_models.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/test_data.py +0 -0
- {blockapi-1.2.0/blockapi/test/v2/api/synthetix → blockapi-1.3.0/blockapi/utils}/__init__.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/utils/address.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/utils/datetime.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/utils/num.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/utils/user_agent.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/v2/__init__.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/v2/api/__init__.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/v2/api/blockchainos.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/v2/api/blockchair.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/v2/api/cosmos.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/v2/api/covalenth/__init__.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/v2/api/covalenth/arbitrum.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/v2/api/covalenth/astar.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/v2/api/covalenth/avalanche.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/v2/api/covalenth/axie.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/v2/api/covalenth/base.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/v2/api/covalenth/binance_smart_chain.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/v2/api/covalenth/ethereum.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/v2/api/covalenth/fantom.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/v2/api/covalenth/heco.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/v2/api/covalenth/iotex.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/v2/api/covalenth/klaytn.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/v2/api/covalenth/moonbeam.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/v2/api/covalenth/palm.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/v2/api/covalenth/polygon.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/v2/api/covalenth/rsk.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/v2/api/debank.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/v2/api/debank_maps.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/v2/api/ethplorer.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/v2/api/nft/__init__.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/v2/api/nft/magic_eden.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/v2/api/nft/opensea.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/v2/api/nft/simple_hash.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/v2/api/nft/unisat.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/v2/api/optimistic_etherscan.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/v2/api/perpetual/__init__.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/v2/api/perpetual/perp_abi.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/v2/api/perpetual/perpetual.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/v2/api/solana.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/v2/api/subscan.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/v2/api/sui.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/v2/api/synthetix/__init__.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/v2/api/synthetix/synthetix.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/v2/api/synthetix/synthetix_abi.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/v2/api/terra.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/v2/api/trezor.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/v2/api/web3_utils.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/v2/base.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/v2/blockchain_mapping.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/v2/coin_mapping.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/v2/coins.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi/v2/models.py +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi.egg-info/dependency_links.txt +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi.egg-info/requires.txt +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/blockapi.egg-info/top_level.txt +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/pyproject.toml +0 -0
- {blockapi-1.2.0 → blockapi-1.3.0}/setup.cfg +0 -0
|
@@ -3,7 +3,6 @@ import random
|
|
|
3
3
|
|
|
4
4
|
import coinaddrng
|
|
5
5
|
|
|
6
|
-
import blockapi.api
|
|
7
6
|
import blockapi.utils
|
|
8
7
|
|
|
9
8
|
from .services import APIError
|
|
@@ -111,30 +110,6 @@ def _inheritors(klass):
|
|
|
111
110
|
return subclasses
|
|
112
111
|
|
|
113
112
|
|
|
114
|
-
def _get_subclasses(class_name):
|
|
115
|
-
return [getattr(class_name, x) for x in dir(class_name) if not x.startswith('__')]
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
def _get_all_inheritors():
|
|
119
|
-
all_inheritors = []
|
|
120
|
-
|
|
121
|
-
tridy = _get_subclasses(blockapi.api)
|
|
122
|
-
|
|
123
|
-
for trida in tridy:
|
|
124
|
-
tridy_sub = _get_subclasses(trida)
|
|
125
|
-
for trida_sub in tridy_sub:
|
|
126
|
-
if (
|
|
127
|
-
inspect.isclass(trida_sub)
|
|
128
|
-
and blockapi.services.BlockchainAPI in trida_sub.__bases__
|
|
129
|
-
):
|
|
130
|
-
all_inheritors.append(trida_sub)
|
|
131
|
-
grandchildren = _inheritors(trida_sub)
|
|
132
|
-
if len(grandchildren) > 0:
|
|
133
|
-
all_inheritors += _inheritors(trida_sub)
|
|
134
|
-
|
|
135
|
-
return all_inheritors
|
|
136
|
-
|
|
137
|
-
|
|
138
113
|
def get_working_apis_for_coin(symbol, debug=False):
|
|
139
114
|
coin_classes = get_api_classes_for_coin(symbol)
|
|
140
115
|
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import re
|
|
2
2
|
|
|
3
|
-
from blockapi.api import SolanaApi
|
|
4
3
|
from blockapi.test.v2.test_data import (
|
|
5
4
|
get_debank_addresses,
|
|
6
5
|
yield_api_balance_classes,
|
|
@@ -28,7 +27,6 @@ def test_enumerate_subclasses():
|
|
|
28
27
|
classes = [x.__name__ for x in yield_api_balance_classes()]
|
|
29
28
|
|
|
30
29
|
assert classes
|
|
31
|
-
assert SolanaApi.__name__ in classes
|
|
32
30
|
assert EthplorerApi.__name__ in classes
|
|
33
31
|
assert DebankApi.__name__ not in classes
|
|
34
32
|
assert PerpetualApi.__name__ not in classes
|
|
@@ -11,65 +11,10 @@ blockapi.egg-info/SOURCES.txt
|
|
|
11
11
|
blockapi.egg-info/dependency_links.txt
|
|
12
12
|
blockapi.egg-info/requires.txt
|
|
13
13
|
blockapi.egg-info/top_level.txt
|
|
14
|
-
blockapi/api/__init__.py
|
|
15
|
-
blockapi/api/alethio.py
|
|
16
|
-
blockapi/api/amberdata.py
|
|
17
|
-
blockapi/api/binance.py
|
|
18
|
-
blockapi/api/blockchaininfo.py
|
|
19
|
-
blockapi/api/blockchainos.py
|
|
20
|
-
blockapi/api/blockchair.py
|
|
21
|
-
blockapi/api/blockcypher.py
|
|
22
|
-
blockapi/api/blockonomics.py
|
|
23
|
-
blockapi/api/blockscout.py
|
|
24
|
-
blockapi/api/btc.py
|
|
25
|
-
blockapi/api/cardanoexplorer.py
|
|
26
|
-
blockapi/api/chainso.py
|
|
27
|
-
blockapi/api/cosmos.py
|
|
28
|
-
blockapi/api/cryptoid.py
|
|
29
|
-
blockapi/api/dcrdata.py
|
|
30
|
-
blockapi/api/digonchain.py
|
|
31
|
-
blockapi/api/eospark.py
|
|
32
|
-
blockapi/api/etherscan.py
|
|
33
|
-
blockapi/api/ethplorer.py
|
|
34
|
-
blockapi/api/greymass.py
|
|
35
|
-
blockapi/api/insight.py
|
|
36
|
-
blockapi/api/kyber.py
|
|
37
|
-
blockapi/api/neoscan.py
|
|
38
|
-
blockapi/api/ontology.py
|
|
39
|
-
blockapi/api/solana.py
|
|
40
|
-
blockapi/api/stellar.py
|
|
41
|
-
blockapi/api/subscan.py
|
|
42
|
-
blockapi/api/terra_money.py
|
|
43
|
-
blockapi/api/trezor.py
|
|
44
|
-
blockapi/api/tronscan.py
|
|
45
|
-
blockapi/api/tzscan.py
|
|
46
|
-
blockapi/api/tzstats.py
|
|
47
|
-
blockapi/api/zchain.py
|
|
48
|
-
blockapi/api/zensystem.py
|
|
49
14
|
blockapi/test/__init__.py
|
|
50
15
|
blockapi/test/test_blockapi.py
|
|
51
16
|
blockapi/test/test_num.py
|
|
52
17
|
blockapi/test/test_random_user_agent.py
|
|
53
|
-
blockapi/test/api/__init__.py
|
|
54
|
-
blockapi/test/api/test_amberdata.py
|
|
55
|
-
blockapi/test/api/test_balances.py
|
|
56
|
-
blockapi/test/api/test_binance.py
|
|
57
|
-
blockapi/test/api/test_blockchainos.py
|
|
58
|
-
blockapi/test/api/test_blockchair.py
|
|
59
|
-
blockapi/test/api/test_blockscout.py
|
|
60
|
-
blockapi/test/api/test_btc.py
|
|
61
|
-
blockapi/test/api/test_cosmos.py
|
|
62
|
-
blockapi/test/api/test_dcrdata.py
|
|
63
|
-
blockapi/test/api/test_digonchain.py
|
|
64
|
-
blockapi/test/api/test_insight.py
|
|
65
|
-
blockapi/test/api/test_kyber.py
|
|
66
|
-
blockapi/test/api/test_ontio.py
|
|
67
|
-
blockapi/test/api/test_solana.py
|
|
68
|
-
blockapi/test/api/test_subscan.py
|
|
69
|
-
blockapi/test/api/test_terra_money.py
|
|
70
|
-
blockapi/test/api/test_tronscan.py
|
|
71
|
-
blockapi/test/api/test_tzscan.py
|
|
72
|
-
blockapi/test/api/test_tzstats.py
|
|
73
18
|
blockapi/test/v2/__init__.py
|
|
74
19
|
blockapi/test/v2/test_base.py
|
|
75
20
|
blockapi/test/v2/test_blockchain_api.py
|
|
@@ -107,7 +52,6 @@ blockapi/test/v2/api/synthetix/test_synthetix.py
|
|
|
107
52
|
blockapi/utils/__init__.py
|
|
108
53
|
blockapi/utils/address.py
|
|
109
54
|
blockapi/utils/datetime.py
|
|
110
|
-
blockapi/utils/ethereum.py
|
|
111
55
|
blockapi/utils/num.py
|
|
112
56
|
blockapi/utils/user_agent.py
|
|
113
57
|
blockapi/v2/__init__.py
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
from blockapi.api.alethio import *
|
|
2
|
-
from blockapi.api.amberdata import *
|
|
3
|
-
from blockapi.api.binance import *
|
|
4
|
-
from blockapi.api.blockchaininfo import *
|
|
5
|
-
from blockapi.api.blockchainos import *
|
|
6
|
-
from blockapi.api.blockchair import *
|
|
7
|
-
from blockapi.api.blockcypher import *
|
|
8
|
-
from blockapi.api.blockonomics import *
|
|
9
|
-
from blockapi.api.blockscout import *
|
|
10
|
-
from blockapi.api.btc import *
|
|
11
|
-
from blockapi.api.cardanoexplorer import *
|
|
12
|
-
from blockapi.api.chainso import *
|
|
13
|
-
from blockapi.api.cosmos import *
|
|
14
|
-
from blockapi.api.cryptoid import *
|
|
15
|
-
from blockapi.api.dcrdata import *
|
|
16
|
-
from blockapi.api.digonchain import *
|
|
17
|
-
from blockapi.api.eospark import *
|
|
18
|
-
from blockapi.api.etherscan import *
|
|
19
|
-
from blockapi.api.ethplorer import *
|
|
20
|
-
from blockapi.api.greymass import *
|
|
21
|
-
from blockapi.api.insight import *
|
|
22
|
-
from blockapi.api.neoscan import *
|
|
23
|
-
from blockapi.api.ontology import *
|
|
24
|
-
from blockapi.api.solana import *
|
|
25
|
-
from blockapi.api.stellar import *
|
|
26
|
-
from blockapi.api.terra_money import *
|
|
27
|
-
from blockapi.api.trezor import *
|
|
28
|
-
from blockapi.api.tronscan import *
|
|
29
|
-
from blockapi.api.tzscan import *
|
|
30
|
-
from blockapi.api.tzstats import *
|
|
31
|
-
from blockapi.api.zchain import *
|
|
32
|
-
from blockapi.api.zensystem import *
|
|
@@ -1,372 +0,0 @@
|
|
|
1
|
-
from datetime import datetime
|
|
2
|
-
|
|
3
|
-
import pytz
|
|
4
|
-
|
|
5
|
-
from blockapi.services import APIError, BlockchainAPI
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class AlethioAPI(BlockchainAPI):
|
|
9
|
-
"""
|
|
10
|
-
Ethereum
|
|
11
|
-
API docs: https://docs.aleth.io/api
|
|
12
|
-
Explorer:
|
|
13
|
-
notice: API key is needed
|
|
14
|
-
"""
|
|
15
|
-
|
|
16
|
-
active = True
|
|
17
|
-
|
|
18
|
-
symbol = 'ETH'
|
|
19
|
-
base_url = 'https://api.aleth.io/v1'
|
|
20
|
-
rate_limit = 1 # 1 req per second
|
|
21
|
-
coef = 1e-18
|
|
22
|
-
max_items_per_page = 100
|
|
23
|
-
page_offset_step = None
|
|
24
|
-
confirmed_num = None
|
|
25
|
-
has_next = {'normal': True, 'token': True}
|
|
26
|
-
collect_logs = True
|
|
27
|
-
|
|
28
|
-
supported_requests = {
|
|
29
|
-
'get_balance': '/accounts/{address}/etherBalances',
|
|
30
|
-
'get_token_balances': '/accounts/{address}/tokenBalances',
|
|
31
|
-
'get_token_info': '/tokens/{token_id}',
|
|
32
|
-
'get_txs': '/transactions?filter[account]={address}&page[limit]={limit}'
|
|
33
|
-
'&page[next]={page}',
|
|
34
|
-
'get_txs_next': None,
|
|
35
|
-
'get_token_txs': '/token-transfers?filter[account]={address}'
|
|
36
|
-
'&page[limit]={limit}&page[next]={page}',
|
|
37
|
-
'get_token_txs_next': None,
|
|
38
|
-
'get_logs': None,
|
|
39
|
-
'get_info': '/accounts/{address}',
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
def __init__(self, address, api_key=None):
|
|
43
|
-
self.has_next['normal'] = True
|
|
44
|
-
self.has_next['token'] = True
|
|
45
|
-
self._address_type = None
|
|
46
|
-
self.supported_requests['get_txs_next'] = None
|
|
47
|
-
self.supported_requests['get_token_txs_next'] = None
|
|
48
|
-
self.supported_requests['get_logs'] = None
|
|
49
|
-
super().__init__(address, api_key)
|
|
50
|
-
|
|
51
|
-
def _query_api(self, request_method, **kwargs):
|
|
52
|
-
return self.request(
|
|
53
|
-
request_method,
|
|
54
|
-
headers={'Authorization': 'Bearer {}'.format(self.api_key)},
|
|
55
|
-
**kwargs
|
|
56
|
-
)
|
|
57
|
-
|
|
58
|
-
def get_balance(self):
|
|
59
|
-
"""
|
|
60
|
-
Returns a list of all balances, both Ethereum and token ones
|
|
61
|
-
|
|
62
|
-
:return: list
|
|
63
|
-
"""
|
|
64
|
-
response = self._query_api('get_balance', address=self.address)
|
|
65
|
-
if not response:
|
|
66
|
-
return None
|
|
67
|
-
|
|
68
|
-
amount = int(response['data'][0]['attributes']['balance']) * self.coef
|
|
69
|
-
balance_eth = [
|
|
70
|
-
{'symbol': self.symbol, 'amount': amount, 'name': 'Ethereum', 'address': ''}
|
|
71
|
-
]
|
|
72
|
-
balances_tokens = self._get_token_balances()
|
|
73
|
-
if balances_tokens is None:
|
|
74
|
-
return None
|
|
75
|
-
|
|
76
|
-
return balance_eth + balances_tokens
|
|
77
|
-
|
|
78
|
-
def _get_token_balances(self):
|
|
79
|
-
response = self._query_api('get_token_balances', address=self.address)
|
|
80
|
-
if not response:
|
|
81
|
-
return None
|
|
82
|
-
|
|
83
|
-
balances = []
|
|
84
|
-
|
|
85
|
-
for token in response['data']:
|
|
86
|
-
bal = token['attributes']['balance']
|
|
87
|
-
if bal is None:
|
|
88
|
-
continue
|
|
89
|
-
|
|
90
|
-
token_id = token['relationships']['token']['data']['id']
|
|
91
|
-
token_info = self._query_api('get_token_info', token_id=token_id)
|
|
92
|
-
if not token_info:
|
|
93
|
-
return None
|
|
94
|
-
|
|
95
|
-
token_info_attrs = token_info['data']['attributes']
|
|
96
|
-
token_decimals = int(token_info_attrs['decimals'])
|
|
97
|
-
token_symbol = token_info_attrs['symbol']
|
|
98
|
-
token_name = token_info_attrs['name']
|
|
99
|
-
|
|
100
|
-
token_balance = int(bal) * pow(10, -token_decimals)
|
|
101
|
-
|
|
102
|
-
balances.append(
|
|
103
|
-
{
|
|
104
|
-
'address': token_id,
|
|
105
|
-
'name': token_name,
|
|
106
|
-
'symbol': token_symbol,
|
|
107
|
-
'amount': token_balance,
|
|
108
|
-
}
|
|
109
|
-
)
|
|
110
|
-
|
|
111
|
-
return balances
|
|
112
|
-
|
|
113
|
-
def get_txs(self, page=None, limit=None, unconfirmed=False, collect_logs=True):
|
|
114
|
-
"""
|
|
115
|
-
Returns the list of collected transactions, subsequent calls
|
|
116
|
-
download next transactions if available
|
|
117
|
-
|
|
118
|
-
:param page: tx cursor
|
|
119
|
-
:param limit: page limit; 100 is the maximum with AlethioAPI
|
|
120
|
-
:param unconfirmed: not used at all here
|
|
121
|
-
:param collect_logs: True if you'd like to collect eventlogs for each
|
|
122
|
-
transaction, otherwise False
|
|
123
|
-
:return: list
|
|
124
|
-
"""
|
|
125
|
-
self.collect_logs = collect_logs
|
|
126
|
-
return self._get_txs(tx_type='normal', page=page, limit=limit)
|
|
127
|
-
|
|
128
|
-
def get_token_txs(self, page=None, limit=None, unconfirmed=False):
|
|
129
|
-
"""
|
|
130
|
-
Returns a list of collected token transactions, subsequent calls
|
|
131
|
-
download next transactions if available
|
|
132
|
-
|
|
133
|
-
:param page: tx cursor
|
|
134
|
-
:param limit: page limit; 100 is the maximum with AlethioAPI
|
|
135
|
-
:param unconfirmed: not used here at all
|
|
136
|
-
:return: list
|
|
137
|
-
"""
|
|
138
|
-
return self._get_txs(tx_type='token', page=page, limit=limit)
|
|
139
|
-
|
|
140
|
-
def _get_txs(self, tx_type='normal', page=None, limit=None, unconfirmed=False):
|
|
141
|
-
if tx_type == 'normal':
|
|
142
|
-
fetch_req = 'get_txs'
|
|
143
|
-
fetch_next_req = 'get_txs_next'
|
|
144
|
-
parser = self._parse_tx
|
|
145
|
-
else:
|
|
146
|
-
fetch_req = 'get_token_txs'
|
|
147
|
-
fetch_next_req = 'get_token_txs_next'
|
|
148
|
-
parser = self._parse_token_tx
|
|
149
|
-
|
|
150
|
-
if page is None:
|
|
151
|
-
page = ''
|
|
152
|
-
|
|
153
|
-
if not self.has_next[tx_type]:
|
|
154
|
-
return []
|
|
155
|
-
|
|
156
|
-
if limit is None:
|
|
157
|
-
limit = self.max_items_per_page
|
|
158
|
-
|
|
159
|
-
if limit > self.max_items_per_page:
|
|
160
|
-
limit = self.max_items_per_page
|
|
161
|
-
|
|
162
|
-
if self.supported_requests[fetch_next_req] is None:
|
|
163
|
-
txs = self._query_api(
|
|
164
|
-
fetch_req, address=self.address, page=page, limit=limit
|
|
165
|
-
)
|
|
166
|
-
else:
|
|
167
|
-
txs = self._query_api(fetch_next_req)
|
|
168
|
-
|
|
169
|
-
if txs['meta']['page']['hasNext']:
|
|
170
|
-
self.has_next[tx_type] = True
|
|
171
|
-
self.supported_requests[fetch_next_req] = txs['links']['next'].replace(
|
|
172
|
-
self.base_url, ''
|
|
173
|
-
)
|
|
174
|
-
else:
|
|
175
|
-
self.has_next[tx_type] = False
|
|
176
|
-
|
|
177
|
-
parsed_txs = [parser(tx) for tx in txs['data']]
|
|
178
|
-
return parsed_txs
|
|
179
|
-
|
|
180
|
-
def _parse_token_tx(self, tx):
|
|
181
|
-
attributes = tx['attributes']
|
|
182
|
-
relationships = tx['relationships']
|
|
183
|
-
|
|
184
|
-
tx_symbol = attributes['symbol']
|
|
185
|
-
tx_from_address = relationships['from']['data']['id']
|
|
186
|
-
tx_to_address = relationships['to']['data']['id']
|
|
187
|
-
tx_contract_address = relationships['token']['data']['id']
|
|
188
|
-
|
|
189
|
-
tx_direction = self._get_tx_direction(
|
|
190
|
-
tx_from_address, tx_to_address, tx_contract_address
|
|
191
|
-
)
|
|
192
|
-
tx_token_data = {
|
|
193
|
-
'name': None, # there's no such field
|
|
194
|
-
'symbol': tx_symbol,
|
|
195
|
-
'decimals': attributes['decimals'],
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
return {
|
|
199
|
-
'symbol': tx_symbol,
|
|
200
|
-
'date': datetime.fromtimestamp(
|
|
201
|
-
int(attributes['blockCreationTime']), pytz.utc
|
|
202
|
-
),
|
|
203
|
-
'from_address': tx_from_address,
|
|
204
|
-
'to_address': tx_to_address,
|
|
205
|
-
'contract_address': tx_contract_address,
|
|
206
|
-
'amount': float(attributes['value']) * pow(10, -attributes['decimals']),
|
|
207
|
-
'fee': 0.0,
|
|
208
|
-
'gas': {
|
|
209
|
-
'gas': float(attributes['transactionGasLimit']),
|
|
210
|
-
'gas_price': float(attributes['transactionGasPrice']),
|
|
211
|
-
'cumulative_gas_used': None,
|
|
212
|
-
'gas_used': float(attributes['transactionGasUsed']),
|
|
213
|
-
},
|
|
214
|
-
'hash': relationships['transaction']['data']['id'],
|
|
215
|
-
'confirmations': None,
|
|
216
|
-
'confirmed': None,
|
|
217
|
-
'is_error': False, # should be always valid
|
|
218
|
-
'type': 'token',
|
|
219
|
-
'kind': 'transaction',
|
|
220
|
-
'direction': tx_direction,
|
|
221
|
-
'token_data': tx_token_data,
|
|
222
|
-
'page': attributes['cursor'],
|
|
223
|
-
'raw': tx,
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
def _parse_tx(self, tx):
|
|
227
|
-
attributes = tx['attributes']
|
|
228
|
-
relationships = tx['relationships']
|
|
229
|
-
|
|
230
|
-
tx_from_address = relationships['from']['data']['id']
|
|
231
|
-
tx_to_address = relationships['to']['data']['id']
|
|
232
|
-
if attributes['msgType'] in ('CallTx', 'CreateTx'):
|
|
233
|
-
tx_contract_address = tx_to_address
|
|
234
|
-
else:
|
|
235
|
-
tx_contract_address = ''
|
|
236
|
-
|
|
237
|
-
tx_direction = self._get_tx_direction(
|
|
238
|
-
tx_from_address, tx_to_address, tx_contract_address
|
|
239
|
-
)
|
|
240
|
-
log_entries_req = relationships['logEntries']['links']['related']
|
|
241
|
-
self.supported_requests['get_logs'] = log_entries_req.replace(self.base_url, '')
|
|
242
|
-
|
|
243
|
-
if self.collect_logs:
|
|
244
|
-
parsed_logs = self._get_logs()
|
|
245
|
-
else:
|
|
246
|
-
parsed_logs = None
|
|
247
|
-
|
|
248
|
-
return {
|
|
249
|
-
'symbol': 'ETH',
|
|
250
|
-
'date': datetime.fromtimestamp(
|
|
251
|
-
int(attributes['blockCreationTime']), pytz.utc
|
|
252
|
-
),
|
|
253
|
-
'from_address': tx_from_address,
|
|
254
|
-
'to_address': tx_to_address,
|
|
255
|
-
'contract_address': tx_contract_address,
|
|
256
|
-
'amount': float(attributes['value']) * self.coef,
|
|
257
|
-
'fee': float(attributes['fee']) * self.coef,
|
|
258
|
-
'gas': {
|
|
259
|
-
'gas': float(attributes['msgGasLimit']),
|
|
260
|
-
'gas_price': float(attributes['txGasPrice']),
|
|
261
|
-
'cumulative_gas_used': None,
|
|
262
|
-
'gas_used': float(attributes['txGasUsed']),
|
|
263
|
-
},
|
|
264
|
-
'hash': attributes['txHash'],
|
|
265
|
-
'confirmations': None,
|
|
266
|
-
'confirmed': None,
|
|
267
|
-
'is_error': attributes['msgError'],
|
|
268
|
-
'type': 'normal',
|
|
269
|
-
'kind': 'transaction',
|
|
270
|
-
'direction': tx_direction,
|
|
271
|
-
'token_data': None,
|
|
272
|
-
'page': attributes['cursor'],
|
|
273
|
-
'raw': tx,
|
|
274
|
-
'event_logs': parsed_logs,
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
def _get_tx_direction(self, tx_from_address, tx_to_address, tx_contract_address):
|
|
278
|
-
tx_direction = None
|
|
279
|
-
if self.address.lower() == tx_from_address.lower():
|
|
280
|
-
tx_direction = 'outgoing'
|
|
281
|
-
elif self.address.lower() == tx_to_address.lower():
|
|
282
|
-
tx_direction = 'incoming'
|
|
283
|
-
elif not tx_contract_address:
|
|
284
|
-
tx_direction = 'outgoing'
|
|
285
|
-
|
|
286
|
-
return tx_direction
|
|
287
|
-
|
|
288
|
-
def _get_logs(self):
|
|
289
|
-
response = self._query_api('get_logs')
|
|
290
|
-
if not response:
|
|
291
|
-
return None
|
|
292
|
-
|
|
293
|
-
logs = []
|
|
294
|
-
|
|
295
|
-
next_logs = True
|
|
296
|
-
while next_logs:
|
|
297
|
-
for log in response['data']:
|
|
298
|
-
logs.append(self._parse_log(log))
|
|
299
|
-
next_logs = response['meta']['page']['hasNext']
|
|
300
|
-
if next_logs:
|
|
301
|
-
self.supported_requests['get_logs'] = response['links']['next'].replace(
|
|
302
|
-
self.base_url, ''
|
|
303
|
-
)
|
|
304
|
-
response = self._query_api('get_logs')
|
|
305
|
-
|
|
306
|
-
return logs
|
|
307
|
-
|
|
308
|
-
def _parse_log(self, log):
|
|
309
|
-
attributes = log['attributes']
|
|
310
|
-
relationships = log['relationships']
|
|
311
|
-
|
|
312
|
-
if attributes['eventDecodedError'] == '':
|
|
313
|
-
event_name = attributes['eventDecoded']['event']
|
|
314
|
-
inputs = self._parse_log_inputs(attributes)
|
|
315
|
-
else:
|
|
316
|
-
event_name = ''
|
|
317
|
-
inputs = None
|
|
318
|
-
|
|
319
|
-
result = {
|
|
320
|
-
'log_data': attributes['logData'],
|
|
321
|
-
'event': event_name,
|
|
322
|
-
'inputs': inputs,
|
|
323
|
-
'address': relationships['loggedBy']['data']['id'],
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
topics = attributes['hasLogTopics']
|
|
327
|
-
|
|
328
|
-
i = 0
|
|
329
|
-
for topic in topics:
|
|
330
|
-
result['topic{}'.format(i)] = topic
|
|
331
|
-
i += 1
|
|
332
|
-
|
|
333
|
-
return result
|
|
334
|
-
|
|
335
|
-
def _parse_log_inputs(self, attributes):
|
|
336
|
-
inputs = []
|
|
337
|
-
if 'inputs' in attributes['eventDecoded']:
|
|
338
|
-
for inp in attributes['eventDecoded']['inputs']:
|
|
339
|
-
if 'indexed' in inp:
|
|
340
|
-
is_indexed = inp['indexed']
|
|
341
|
-
else:
|
|
342
|
-
is_indexed = False
|
|
343
|
-
|
|
344
|
-
parsed_log = {
|
|
345
|
-
'name': inp['name'],
|
|
346
|
-
'type': inp['type'],
|
|
347
|
-
'is_indexed': is_indexed,
|
|
348
|
-
}
|
|
349
|
-
if 'value' in inp:
|
|
350
|
-
parsed_log['value'] = inp['value']
|
|
351
|
-
if 'components' in inp:
|
|
352
|
-
parsed_log['components'] = inp['components']
|
|
353
|
-
|
|
354
|
-
inputs.append(parsed_log)
|
|
355
|
-
|
|
356
|
-
return inputs
|
|
357
|
-
|
|
358
|
-
@property
|
|
359
|
-
def address_type(self):
|
|
360
|
-
if self._address_type is None:
|
|
361
|
-
result = self._query_api('get_info', address=self.address)
|
|
362
|
-
if result['data']['relationships']['contract']['data'] is None:
|
|
363
|
-
self._address_type = 'address'
|
|
364
|
-
else:
|
|
365
|
-
# contract or token
|
|
366
|
-
try:
|
|
367
|
-
self._query_api('get_token_info', token_id=self.address)
|
|
368
|
-
self._address_type = 'token'
|
|
369
|
-
except APIError:
|
|
370
|
-
self._address_type = 'contract'
|
|
371
|
-
|
|
372
|
-
return self._address_type
|