blockapi 1.3.0__tar.gz → 1.3.2__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.3.0 → blockapi-1.3.2}/PKG-INFO +27 -5
- blockapi-1.3.2/blockapi/test/v2/api/test_subscan_polkadot.py +93 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/v2/api/subscan.py +11 -35
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi.egg-info/PKG-INFO +27 -5
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi.egg-info/requires.txt +1 -1
- {blockapi-1.3.0 → blockapi-1.3.2}/setup.py +2 -2
- blockapi-1.3.0/blockapi/test/v2/api/test_subscan_polkadot.py +0 -32
- {blockapi-1.3.0 → blockapi-1.3.2}/LICENSE.md +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/README.md +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/__init__.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/services.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/test/__init__.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/test/test_blockapi.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/test/test_num.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/test/test_random_user_agent.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/test/v2/__init__.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/test/v2/api/__init__.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/test/v2/api/conftest.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/test/v2/api/covalenth/__init__.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/test/v2/api/covalenth/test_ethereum.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/test/v2/api/fake_sleep_provider.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/test/v2/api/nft/__init__.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/test/v2/api/nft/test_magic_eden.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/test/v2/api/nft/test_opensea.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/test/v2/api/nft/test_simple_hash.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/test/v2/api/nft/test_unisat.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/test/v2/api/perpetual/__init__.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/test/v2/api/perpetual/test_perpetual.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/test/v2/api/synthetix/__init__.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/test/v2/api/synthetix/test_synthetix.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/test/v2/api/test_blockchainos.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/test/v2/api/test_blockchair_btc.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/test/v2/api/test_blockchair_doge.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/test/v2/api/test_blockchair_ltc.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/test/v2/api/test_cosmos.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/test/v2/api/test_ethplorer.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/test/v2/api/test_multisources.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/test/v2/api/test_optimistic_etherscan.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/test/v2/api/test_solana.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/test/v2/api/test_sui.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/test/v2/api/test_trezor_btc.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/test/v2/test_base.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/test/v2/test_blockchain_api.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/test/v2/test_blockchain_mapping.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/test/v2/test_data.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/test/v2/test_enumerate_classes.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/test/v2/test_generic.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/test/v2/test_models.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/test_data.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/utils/__init__.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/utils/address.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/utils/datetime.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/utils/num.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/utils/user_agent.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/v2/__init__.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/v2/api/__init__.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/v2/api/blockchainos.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/v2/api/blockchair.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/v2/api/cosmos.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/v2/api/covalenth/__init__.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/v2/api/covalenth/arbitrum.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/v2/api/covalenth/astar.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/v2/api/covalenth/avalanche.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/v2/api/covalenth/axie.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/v2/api/covalenth/base.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/v2/api/covalenth/binance_smart_chain.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/v2/api/covalenth/ethereum.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/v2/api/covalenth/fantom.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/v2/api/covalenth/heco.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/v2/api/covalenth/iotex.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/v2/api/covalenth/klaytn.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/v2/api/covalenth/moonbeam.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/v2/api/covalenth/palm.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/v2/api/covalenth/polygon.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/v2/api/covalenth/rsk.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/v2/api/debank.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/v2/api/debank_maps.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/v2/api/ethplorer.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/v2/api/nft/__init__.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/v2/api/nft/magic_eden.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/v2/api/nft/opensea.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/v2/api/nft/simple_hash.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/v2/api/nft/unisat.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/v2/api/optimistic_etherscan.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/v2/api/perpetual/__init__.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/v2/api/perpetual/perp_abi.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/v2/api/perpetual/perpetual.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/v2/api/solana.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/v2/api/sui.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/v2/api/synthetix/__init__.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/v2/api/synthetix/synthetix.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/v2/api/synthetix/synthetix_abi.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/v2/api/terra.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/v2/api/trezor.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/v2/api/web3_utils.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/v2/base.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/v2/blockchain_mapping.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/v2/coin_mapping.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/v2/coins.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi/v2/models.py +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi.egg-info/SOURCES.txt +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi.egg-info/dependency_links.txt +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/blockapi.egg-info/top_level.txt +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/pyproject.toml +0 -0
- {blockapi-1.3.0 → blockapi-1.3.2}/setup.cfg +0 -0
|
@@ -1,13 +1,37 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: blockapi
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.2
|
|
4
4
|
Summary: BlockAPI library
|
|
5
5
|
Home-page: https://github.com/crypkit/blockapi
|
|
6
6
|
Author: Devmons s.r.o.
|
|
7
7
|
License: MIT
|
|
8
|
-
Platform: UNKNOWN
|
|
9
8
|
Description-Content-Type: text/markdown
|
|
10
9
|
License-File: LICENSE.md
|
|
10
|
+
Requires-Dist: requests==2.32.4
|
|
11
|
+
Requires-Dist: pytz>=2019.2
|
|
12
|
+
Requires-Dist: python-dateutil>=2.8.0
|
|
13
|
+
Requires-Dist: coinaddrng==1.1.1
|
|
14
|
+
Requires-Dist: cfscrape>=2.0.8
|
|
15
|
+
Requires-Dist: ethereum_input_decoder>=0.2.2
|
|
16
|
+
Requires-Dist: web3<6.0.0,>=5.2.2
|
|
17
|
+
Requires-Dist: bs4>=0.0.1
|
|
18
|
+
Requires-Dist: lxml>=4.4.1
|
|
19
|
+
Requires-Dist: pydantic>=1.10.2
|
|
20
|
+
Requires-Dist: marko==1.3.0
|
|
21
|
+
Requires-Dist: fake_useragent>=1.1.3
|
|
22
|
+
Requires-Dist: pytest
|
|
23
|
+
Requires-Dist: pytest-vcr
|
|
24
|
+
Requires-Dist: requests_mock>=1.9.3
|
|
25
|
+
Requires-Dist: attrs<=22.1.0,>=17.4.0
|
|
26
|
+
Requires-Dist: solders==0.22.0
|
|
27
|
+
Dynamic: author
|
|
28
|
+
Dynamic: description
|
|
29
|
+
Dynamic: description-content-type
|
|
30
|
+
Dynamic: home-page
|
|
31
|
+
Dynamic: license
|
|
32
|
+
Dynamic: license-file
|
|
33
|
+
Dynamic: requires-dist
|
|
34
|
+
Dynamic: summary
|
|
11
35
|
|
|
12
36
|
# blockapi
|
|
13
37
|
|
|
@@ -157,5 +181,3 @@ See also the list of [contributors](https://github.com/crypkit/blockapi/contribu
|
|
|
157
181
|
|
|
158
182
|
This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details
|
|
159
183
|
|
|
160
|
-
|
|
161
|
-
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
from decimal import Decimal
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
|
|
5
|
+
from blockapi.test.v2.api.conftest import read_file
|
|
6
|
+
from blockapi.v2.api import PolkadotSubscanApi
|
|
7
|
+
from blockapi.v2.models import AssetType
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@pytest.fixture
|
|
11
|
+
def api():
|
|
12
|
+
"""Create a PolkadotSubscanApi instance for testing."""
|
|
13
|
+
return PolkadotSubscanApi()
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@pytest.mark.parametrize(
|
|
17
|
+
'address, response_path, expected_balance',
|
|
18
|
+
[
|
|
19
|
+
(
|
|
20
|
+
'1NjjK81oA9is7eWhFJ7n7kQhaPT3pnxLFH5MkwDfduAiWE9',
|
|
21
|
+
'data/subscan_polkadot_response_WE9.json',
|
|
22
|
+
Decimal('4649.9139999889'),
|
|
23
|
+
),
|
|
24
|
+
(
|
|
25
|
+
'15j4dg5GzsL1bw2U2AWgeyAk6QTxq43V7ZPbXdAmbVLjvDCK',
|
|
26
|
+
'data/subscan_polkadot_response_DCK.json',
|
|
27
|
+
Decimal('17970279.0085871699'),
|
|
28
|
+
),
|
|
29
|
+
],
|
|
30
|
+
)
|
|
31
|
+
def test_fetch_balances(requests_mock, address, response_path, expected_balance, api):
|
|
32
|
+
requests_mock.post(
|
|
33
|
+
'https://polkadot.api.subscan.io/api/v2/scan/search',
|
|
34
|
+
text=read_file(response_path),
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
balances = api.get_balance(address)
|
|
38
|
+
assert sum(b.balance for b in balances) == expected_balance
|
|
39
|
+
assert all(isinstance(balance.raw, dict) for balance in balances)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def test_real_problematic_address_overlap(requests_mock, api):
|
|
43
|
+
"""
|
|
44
|
+
Test the real problematic address that exhibits balance overlap.
|
|
45
|
+
"""
|
|
46
|
+
requests_mock.post(
|
|
47
|
+
'https://polkadot.api.subscan.io/api/v2/scan/search',
|
|
48
|
+
text=read_file('data/subscan_polkadot_balance_overlap_1567z.json'),
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
balances = list(api.get_balance("1567zYrTN6G1YXoF47KyC5Lyto8MhJjzDB8dY8ZvudMAAEet"))
|
|
52
|
+
available_balances = [b for b in balances if b.asset_type == AssetType.AVAILABLE]
|
|
53
|
+
|
|
54
|
+
assert len(available_balances) == 1, "Expected 1 available balance item"
|
|
55
|
+
available_balance = available_balances[0]
|
|
56
|
+
|
|
57
|
+
# Correct calculation: 69.1806120067 - 64.5655723106 = 4.6150396961 DOT
|
|
58
|
+
expected_balance = Decimal("4.6150396961")
|
|
59
|
+
assert (
|
|
60
|
+
available_balance.balance == expected_balance
|
|
61
|
+
), f"Expected {expected_balance}, got {available_balance.balance}"
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def test_second_problematic_address_overlap(requests_mock, api):
|
|
65
|
+
"""
|
|
66
|
+
Test another problematic address with reserved > locked scenario.
|
|
67
|
+
|
|
68
|
+
Address 15gT3MY2oVDqi1WPFnpkhPKVNUXAUPscMagaJeW8dqmLzfJ6 has large reserved
|
|
69
|
+
amount (154.31 DOT) but no staking locks, demonstrating reserved > locked case.
|
|
70
|
+
"""
|
|
71
|
+
requests_mock.post(
|
|
72
|
+
'https://polkadot.api.subscan.io/api/v2/scan/search',
|
|
73
|
+
text=read_file('data/subscan_polkadot_balance_overlap_15gT3.json'),
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
balances = list(api.get_balance("15gT3MY2oVDqi1WPFnpkhPKVNUXAUPscMagaJeW8dqmLzfJ6"))
|
|
77
|
+
|
|
78
|
+
available_balances = [b for b in balances if b.asset_type == AssetType.AVAILABLE]
|
|
79
|
+
assert len(available_balances) == 1
|
|
80
|
+
available_balance = available_balances[0]
|
|
81
|
+
|
|
82
|
+
# 162.469 total, 154.307 locked
|
|
83
|
+
expected_balance = Decimal('8.1611794137')
|
|
84
|
+
assert (
|
|
85
|
+
available_balance.balance == expected_balance
|
|
86
|
+
), f"Expected {expected_balance}, got {available_balance.balance}"
|
|
87
|
+
|
|
88
|
+
other_balances = [b for b in balances if b.asset_type != AssetType.AVAILABLE]
|
|
89
|
+
assert len(other_balances) == 1
|
|
90
|
+
|
|
91
|
+
other_balance = other_balances[0]
|
|
92
|
+
assert other_balance.balance == Decimal('154.3078601187')
|
|
93
|
+
assert other_balance.asset_type == AssetType.LOCKED
|
|
@@ -43,7 +43,7 @@ class SubscanApi(BlockchainApi, BalanceMixin, ABC):
|
|
|
43
43
|
return FetchResult(data=response)
|
|
44
44
|
|
|
45
45
|
def parse_balances(self, fetch_result: FetchResult) -> ParseResult:
|
|
46
|
-
balances = list(self.
|
|
46
|
+
balances = list(self._yield_native_balances_zero_zum(fetch_result.data))
|
|
47
47
|
|
|
48
48
|
# add staking rewards (and slashes) too? it's a lot of requests
|
|
49
49
|
# per single address
|
|
@@ -52,34 +52,15 @@ class SubscanApi(BlockchainApi, BalanceMixin, ABC):
|
|
|
52
52
|
|
|
53
53
|
return ParseResult(data=balances)
|
|
54
54
|
|
|
55
|
-
def
|
|
55
|
+
def _yield_native_balances_zero_zum(self, response: dict) -> Iterable[BalanceItem]:
|
|
56
56
|
data = response['data']['account']
|
|
57
57
|
b_total = decimals_to_raw(data['balance'], self.coin.decimals)
|
|
58
58
|
if b_total == 0:
|
|
59
59
|
return []
|
|
60
60
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
b_staked = Decimal(0)
|
|
64
|
-
if data['staking_info']:
|
|
65
|
-
b_staked = b_total_locked
|
|
66
|
-
|
|
67
|
-
# ignore data['unbonding'] - it's still staked
|
|
68
|
-
|
|
69
|
-
b_reserved = safe_opt_decimal(data['reserved'])
|
|
70
|
-
b_vesting = (
|
|
71
|
-
to_decimal(data['vesting']['total_locked'])
|
|
72
|
-
if data['vesting']
|
|
73
|
-
else Decimal(0)
|
|
74
|
-
)
|
|
75
|
-
|
|
76
|
-
# do we want to include these?
|
|
77
|
-
# b_democracy = safe_opt_decimal(data['democracy_lock'])
|
|
78
|
-
# b_election = safe_opt_decimal(data['election_lock'])
|
|
79
|
-
|
|
80
|
-
b_available = b_total - b_total_locked - b_reserved
|
|
81
|
-
b_locked = b_reserved
|
|
61
|
+
b_reserved = safe_opt_decimal(data.get('reserved'))
|
|
82
62
|
|
|
63
|
+
b_available = b_total - b_reserved
|
|
83
64
|
if b_available:
|
|
84
65
|
yield BalanceItem.from_api(
|
|
85
66
|
balance_raw=int(b_available),
|
|
@@ -88,25 +69,20 @@ class SubscanApi(BlockchainApi, BalanceMixin, ABC):
|
|
|
88
69
|
raw=data,
|
|
89
70
|
)
|
|
90
71
|
|
|
91
|
-
|
|
72
|
+
b_bonded = safe_opt_decimal(data.get('bonded'))
|
|
73
|
+
if b_bonded:
|
|
92
74
|
yield BalanceItem.from_api(
|
|
93
|
-
balance_raw=int(
|
|
75
|
+
balance_raw=int(b_bonded),
|
|
94
76
|
coin=self.coin,
|
|
95
77
|
asset_type=AssetType.STAKED,
|
|
96
78
|
raw=data,
|
|
97
79
|
)
|
|
98
80
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
coin=self.coin,
|
|
103
|
-
asset_type=AssetType.VESTING,
|
|
104
|
-
raw=data['vesting'],
|
|
105
|
-
)
|
|
106
|
-
|
|
107
|
-
if b_locked:
|
|
81
|
+
# Others: reserved - bonded (includes unbonding + other reserves)
|
|
82
|
+
b_others = b_reserved - b_bonded
|
|
83
|
+
if b_others > 0:
|
|
108
84
|
yield BalanceItem.from_api(
|
|
109
|
-
balance_raw=int(
|
|
85
|
+
balance_raw=int(b_others),
|
|
110
86
|
coin=self.coin,
|
|
111
87
|
asset_type=AssetType.LOCKED,
|
|
112
88
|
raw=data,
|
|
@@ -1,13 +1,37 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: blockapi
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.2
|
|
4
4
|
Summary: BlockAPI library
|
|
5
5
|
Home-page: https://github.com/crypkit/blockapi
|
|
6
6
|
Author: Devmons s.r.o.
|
|
7
7
|
License: MIT
|
|
8
|
-
Platform: UNKNOWN
|
|
9
8
|
Description-Content-Type: text/markdown
|
|
10
9
|
License-File: LICENSE.md
|
|
10
|
+
Requires-Dist: requests==2.32.4
|
|
11
|
+
Requires-Dist: pytz>=2019.2
|
|
12
|
+
Requires-Dist: python-dateutil>=2.8.0
|
|
13
|
+
Requires-Dist: coinaddrng==1.1.1
|
|
14
|
+
Requires-Dist: cfscrape>=2.0.8
|
|
15
|
+
Requires-Dist: ethereum_input_decoder>=0.2.2
|
|
16
|
+
Requires-Dist: web3<6.0.0,>=5.2.2
|
|
17
|
+
Requires-Dist: bs4>=0.0.1
|
|
18
|
+
Requires-Dist: lxml>=4.4.1
|
|
19
|
+
Requires-Dist: pydantic>=1.10.2
|
|
20
|
+
Requires-Dist: marko==1.3.0
|
|
21
|
+
Requires-Dist: fake_useragent>=1.1.3
|
|
22
|
+
Requires-Dist: pytest
|
|
23
|
+
Requires-Dist: pytest-vcr
|
|
24
|
+
Requires-Dist: requests_mock>=1.9.3
|
|
25
|
+
Requires-Dist: attrs<=22.1.0,>=17.4.0
|
|
26
|
+
Requires-Dist: solders==0.22.0
|
|
27
|
+
Dynamic: author
|
|
28
|
+
Dynamic: description
|
|
29
|
+
Dynamic: description-content-type
|
|
30
|
+
Dynamic: home-page
|
|
31
|
+
Dynamic: license
|
|
32
|
+
Dynamic: license-file
|
|
33
|
+
Dynamic: requires-dist
|
|
34
|
+
Dynamic: summary
|
|
11
35
|
|
|
12
36
|
# blockapi
|
|
13
37
|
|
|
@@ -157,5 +181,3 @@ See also the list of [contributors](https://github.com/crypkit/blockapi/contribu
|
|
|
157
181
|
|
|
158
182
|
This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details
|
|
159
183
|
|
|
160
|
-
|
|
161
|
-
|
|
@@ -6,7 +6,7 @@ with open("README.md", "r") as f:
|
|
|
6
6
|
|
|
7
7
|
PACKAGES = find_packages(where='.')
|
|
8
8
|
|
|
9
|
-
__version__ = "1.3.
|
|
9
|
+
__version__ = "1.3.2"
|
|
10
10
|
|
|
11
11
|
setuptools.setup(
|
|
12
12
|
name='blockapi',
|
|
@@ -18,7 +18,7 @@ setuptools.setup(
|
|
|
18
18
|
long_description_content_type='text/markdown',
|
|
19
19
|
packages=PACKAGES,
|
|
20
20
|
install_requires=[
|
|
21
|
-
'requests==2.32.
|
|
21
|
+
'requests==2.32.4',
|
|
22
22
|
'pytz>=2019.2',
|
|
23
23
|
'python-dateutil>=2.8.0',
|
|
24
24
|
'coinaddrng==1.1.1',
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
from decimal import Decimal
|
|
2
|
-
|
|
3
|
-
import pytest
|
|
4
|
-
|
|
5
|
-
from blockapi.test.v2.api.conftest import read_file
|
|
6
|
-
from blockapi.v2.api import PolkadotSubscanApi
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
@pytest.mark.parametrize(
|
|
10
|
-
'address, response_path, expected_balance',
|
|
11
|
-
[
|
|
12
|
-
(
|
|
13
|
-
'1NjjK81oA9is7eWhFJ7n7kQhaPT3pnxLFH5MkwDfduAiWE9',
|
|
14
|
-
'data/subscan_polkadot_response_WE9.json',
|
|
15
|
-
Decimal('4649.9139999889'),
|
|
16
|
-
),
|
|
17
|
-
(
|
|
18
|
-
'15j4dg5GzsL1bw2U2AWgeyAk6QTxq43V7ZPbXdAmbVLjvDCK',
|
|
19
|
-
'data/subscan_polkadot_response_DCK.json',
|
|
20
|
-
Decimal('49296244.7887007465'),
|
|
21
|
-
),
|
|
22
|
-
],
|
|
23
|
-
)
|
|
24
|
-
def test_fetch_balances(requests_mock, address, response_path, expected_balance):
|
|
25
|
-
requests_mock.post(
|
|
26
|
-
'https://polkadot.api.subscan.io/api/v2/scan/search',
|
|
27
|
-
text=read_file(response_path),
|
|
28
|
-
)
|
|
29
|
-
|
|
30
|
-
api = PolkadotSubscanApi()
|
|
31
|
-
balances = api.get_balance(address)
|
|
32
|
-
assert sum(b.balance for b in balances) == expected_balance
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|