blockapi 2.11.2__tar.gz → 2.11.3__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.
Files changed (103) hide show
  1. {blockapi-2.11.2 → blockapi-2.11.3}/PKG-INFO +1 -1
  2. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/test/v2/api/test_solana.py +148 -7
  3. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/v2/api/solana.py +46 -17
  4. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi.egg-info/PKG-INFO +1 -1
  5. {blockapi-2.11.2 → blockapi-2.11.3}/setup.py +1 -1
  6. {blockapi-2.11.2 → blockapi-2.11.3}/LICENSE.md +0 -0
  7. {blockapi-2.11.2 → blockapi-2.11.3}/README.md +0 -0
  8. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/__init__.py +0 -0
  9. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/services.py +0 -0
  10. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/test/__init__.py +0 -0
  11. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/test/test_blockapi.py +0 -0
  12. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/test/test_num.py +0 -0
  13. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/test/test_random_user_agent.py +0 -0
  14. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/test/v2/__init__.py +0 -0
  15. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/test/v2/api/__init__.py +0 -0
  16. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/test/v2/api/conftest.py +0 -0
  17. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/test/v2/api/covalenth/__init__.py +0 -0
  18. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/test/v2/api/covalenth/test_ethereum.py +0 -0
  19. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/test/v2/api/fake_sleep_provider.py +0 -0
  20. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/test/v2/api/nft/__init__.py +0 -0
  21. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/test/v2/api/nft/test_magic_eden.py +0 -0
  22. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/test/v2/api/nft/test_opensea.py +0 -0
  23. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/test/v2/api/nft/test_simple_hash.py +0 -0
  24. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/test/v2/api/nft/test_unisat.py +0 -0
  25. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/test/v2/api/test_bitaps_ltc.py +0 -0
  26. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/test/v2/api/test_blockchain_info.py +0 -0
  27. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/test/v2/api/test_blockchainos.py +0 -0
  28. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/test/v2/api/test_blockchair_btc.py +0 -0
  29. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/test/v2/api/test_blockchair_doge.py +0 -0
  30. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/test/v2/api/test_blockchair_ltc.py +0 -0
  31. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/test/v2/api/test_cosmos.py +0 -0
  32. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/test/v2/api/test_ethplorer.py +0 -0
  33. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/test/v2/api/test_haskoin.py +0 -0
  34. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/test/v2/api/test_litecoinspace.py +0 -0
  35. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/test/v2/api/test_multisources.py +0 -0
  36. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/test/v2/api/test_optimistic_etherscan.py +0 -0
  37. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/test/v2/api/test_subscan_polkadot.py +0 -0
  38. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/test/v2/api/test_sui.py +0 -0
  39. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/test/v2/api/test_terra.py +0 -0
  40. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/test/v2/api/test_trezor_btc.py +0 -0
  41. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/test/v2/api/test_trezor_zec.py +0 -0
  42. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/test/v2/test_base.py +0 -0
  43. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/test/v2/test_blockchain_api.py +0 -0
  44. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/test/v2/test_blockchain_mapping.py +0 -0
  45. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/test/v2/test_data.py +0 -0
  46. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/test/v2/test_enumerate_classes.py +0 -0
  47. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/test/v2/test_generic.py +0 -0
  48. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/test/v2/test_models.py +0 -0
  49. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/test_data.py +0 -0
  50. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/utils/__init__.py +0 -0
  51. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/utils/address.py +0 -0
  52. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/utils/datetime.py +0 -0
  53. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/utils/num.py +0 -0
  54. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/utils/user_agent.py +0 -0
  55. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/v2/__init__.py +0 -0
  56. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/v2/api/__init__.py +0 -0
  57. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/v2/api/bitaps.py +0 -0
  58. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/v2/api/blockchain_info.py +0 -0
  59. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/v2/api/blockchainos.py +0 -0
  60. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/v2/api/blockchair.py +0 -0
  61. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/v2/api/cosmos.py +0 -0
  62. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/v2/api/covalenth/__init__.py +0 -0
  63. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/v2/api/covalenth/arbitrum.py +0 -0
  64. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/v2/api/covalenth/astar.py +0 -0
  65. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/v2/api/covalenth/avalanche.py +0 -0
  66. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/v2/api/covalenth/axie.py +0 -0
  67. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/v2/api/covalenth/base.py +0 -0
  68. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/v2/api/covalenth/binance_smart_chain.py +0 -0
  69. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/v2/api/covalenth/ethereum.py +0 -0
  70. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/v2/api/covalenth/fantom.py +0 -0
  71. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/v2/api/covalenth/heco.py +0 -0
  72. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/v2/api/covalenth/iotex.py +0 -0
  73. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/v2/api/covalenth/klaytn.py +0 -0
  74. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/v2/api/covalenth/moonbeam.py +0 -0
  75. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/v2/api/covalenth/palm.py +0 -0
  76. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/v2/api/covalenth/polygon.py +0 -0
  77. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/v2/api/covalenth/rsk.py +0 -0
  78. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/v2/api/debank.py +0 -0
  79. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/v2/api/debank_maps.py +0 -0
  80. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/v2/api/ethplorer.py +0 -0
  81. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/v2/api/haskoin.py +0 -0
  82. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/v2/api/litecoinspace.py +0 -0
  83. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/v2/api/nft/__init__.py +0 -0
  84. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/v2/api/nft/magic_eden.py +0 -0
  85. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/v2/api/nft/opensea.py +0 -0
  86. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/v2/api/nft/simple_hash.py +0 -0
  87. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/v2/api/nft/unisat.py +0 -0
  88. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/v2/api/optimistic_etherscan.py +0 -0
  89. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/v2/api/subscan.py +0 -0
  90. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/v2/api/sui.py +0 -0
  91. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/v2/api/terra.py +0 -0
  92. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/v2/api/trezor.py +0 -0
  93. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/v2/base.py +0 -0
  94. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/v2/blockchain_mapping.py +0 -0
  95. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/v2/coin_mapping.py +0 -0
  96. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/v2/coins.py +0 -0
  97. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi/v2/models.py +0 -0
  98. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi.egg-info/SOURCES.txt +0 -0
  99. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi.egg-info/dependency_links.txt +0 -0
  100. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi.egg-info/requires.txt +0 -0
  101. {blockapi-2.11.2 → blockapi-2.11.3}/blockapi.egg-info/top_level.txt +0 -0
  102. {blockapi-2.11.2 → blockapi-2.11.3}/pyproject.toml +0 -0
  103. {blockapi-2.11.2 → blockapi-2.11.3}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: blockapi
3
- Version: 2.11.2
3
+ Version: 2.11.3
4
4
  Summary: BlockAPI library
5
5
  Home-page: https://github.com/crypkit/blockapi
6
6
  Author: Devmons s.r.o.
@@ -1,11 +1,13 @@
1
+ import json
1
2
  from decimal import Decimal
2
- from unittest.mock import patch
3
+ from unittest.mock import call, patch
3
4
 
4
5
  import pytest
5
6
  from requests_mock import ANY, Mocker
6
7
 
7
8
  from blockapi.test.v2.api.conftest import read_file
8
9
  from blockapi.v2.api import SolanaApi, SolscanApi
10
+ from blockapi.v2.base import ApiException
9
11
  from blockapi.v2.models import (
10
12
  AssetType,
11
13
  BalanceItem,
@@ -74,14 +76,26 @@ def test_use_base_url():
74
76
  assert api.base_url == 'https://api.mainnet-beta.solana.com/'
75
77
 
76
78
 
77
- def test_use_base_url_in_post(
79
+ @pytest.mark.parametrize(
80
+ ('rpc_url', 'uses_v2_staking'),
81
+ [
82
+ ('https://mainnet.helius-rpc.com/', True),
83
+ ('https://proxy/solana/', False),
84
+ ],
85
+ )
86
+ def test_get_balance_supports_helius_and_legacy_staking_responses(
78
87
  sol_balance_response,
79
88
  token_accounts_response,
80
89
  das_asset_batch_response,
81
90
  staked_solana_response,
91
+ rpc_url,
92
+ uses_v2_staking,
82
93
  ):
83
94
  test_addr = '5PjMxaijeVVQtuEzxK2NxyJeWwUbpTsi2uXuZ653WoHu'
84
95
  empty_token_accounts = '{"jsonrpc":"2.0","result":{"context":{"apiVersion":"1.17.34","slot":268207149},"value":[]},"id":1}'
96
+ staking_response = json.loads(staked_solana_response)
97
+ if not uses_v2_staking:
98
+ staking_response['result'] = staking_response['result']['accounts']
85
99
 
86
100
  iterator = iter(
87
101
  [
@@ -89,19 +103,29 @@ def test_use_base_url_in_post(
89
103
  token_accounts_response,
90
104
  empty_token_accounts,
91
105
  das_asset_batch_response,
92
- staked_solana_response,
106
+ json.dumps(staking_response),
93
107
  ]
94
108
  )
95
109
 
96
110
  def get_text(*args, **kwargs):
97
- assert args[0].url == 'https://proxy/solana/'
111
+ assert args[0].url == rpc_url
98
112
  data = next(iterator)
99
113
  return data
100
114
 
101
115
  with Mocker() as m:
102
- m.post(ANY, text=get_text),
103
- api = SolanaApi(base_url='https://proxy/solana/')
104
- api.get_balance(test_addr)
116
+ m.post(ANY, text=get_text)
117
+ api = SolanaApi(base_url=rpc_url)
118
+ balances = api.get_balance(test_addr)
119
+
120
+ staking_balances = {
121
+ balance.asset_type: balance.balance_raw
122
+ for balance in balances
123
+ if balance.asset_type in {AssetType.STAKED, AssetType.LOCKED}
124
+ }
125
+ assert staking_balances == {
126
+ AssetType.STAKED: Decimal('179062913955311'),
127
+ AssetType.LOCKED: Decimal('424045085255'),
128
+ }
105
129
 
106
130
 
107
131
  def test_build_coin_from_das_asset():
@@ -237,6 +261,123 @@ def test_parse_staked_balance_skips_undelegated():
237
261
  assert result.asset_type == AssetType.STAKED
238
262
 
239
263
 
264
+ def test_fetch_staked_sol_uses_v2_pagination():
265
+ api = SolanaApi(base_url='https://mainnet.helius-rpc.com/')
266
+ address = '5PjMxaijeVVQtuEzxK2NxyJeWwUbpTsi2uXuZ653WoHu'
267
+ first_account = {'pubkey': 'first'}
268
+ second_account = {'pubkey': 'second'}
269
+
270
+ with patch.object(
271
+ api,
272
+ '_request',
273
+ side_effect=[
274
+ {
275
+ 'jsonrpc': '2.0',
276
+ 'id': 1,
277
+ 'result': {
278
+ 'accounts': [first_account],
279
+ 'paginationKey': 'next-page',
280
+ },
281
+ },
282
+ {
283
+ 'jsonrpc': '2.0',
284
+ 'id': 2,
285
+ 'result': {
286
+ 'accounts': [],
287
+ 'paginationKey': 'last-page',
288
+ },
289
+ },
290
+ {
291
+ 'jsonrpc': '2.0',
292
+ 'id': 3,
293
+ 'result': {
294
+ 'accounts': [second_account],
295
+ 'paginationKey': None,
296
+ },
297
+ },
298
+ ],
299
+ ) as request:
300
+ response = api._fetch_staked_sol(address)
301
+
302
+ config = {
303
+ 'filters': [
304
+ {
305
+ 'memcmp': {
306
+ 'offset': api.STAKE_AUTHORITY_OFFSET,
307
+ 'bytes': address,
308
+ 'encoding': 'base58',
309
+ }
310
+ }
311
+ ],
312
+ 'encoding': 'jsonParsed',
313
+ 'commitment': 'finalized',
314
+ 'limit': api.HELIUS_PROGRAM_ACCOUNTS_PAGE_SIZE,
315
+ }
316
+ assert request.call_args_list == [
317
+ call(
318
+ method='getProgramAccountsV2',
319
+ params=[api.STAKE_PROGRAM_ID, config],
320
+ ),
321
+ call(
322
+ method='getProgramAccountsV2',
323
+ params=[
324
+ api.STAKE_PROGRAM_ID,
325
+ {**config, 'paginationKey': 'next-page'},
326
+ ],
327
+ ),
328
+ call(
329
+ method='getProgramAccountsV2',
330
+ params=[
331
+ api.STAKE_PROGRAM_ID,
332
+ {**config, 'paginationKey': 'last-page'},
333
+ ],
334
+ ),
335
+ ]
336
+ assert response == {
337
+ 'jsonrpc': '2.0',
338
+ 'id': 3,
339
+ 'result': [first_account, second_account],
340
+ }
341
+
342
+
343
+ def test_fetch_staked_sol_rejects_repeated_pagination_key():
344
+ api = SolanaApi(base_url='https://mainnet.helius-rpc.com/')
345
+ repeated_page = {
346
+ 'result': {
347
+ 'accounts': [],
348
+ 'paginationKey': 'same-page',
349
+ }
350
+ }
351
+ terminal_page = {
352
+ 'result': {
353
+ 'accounts': [],
354
+ 'paginationKey': None,
355
+ }
356
+ }
357
+
358
+ with patch.object(
359
+ api,
360
+ '_request',
361
+ side_effect=[repeated_page, repeated_page, terminal_page],
362
+ ) as request:
363
+ with pytest.raises(ApiException, match='repeated pagination key'):
364
+ api._fetch_staked_sol('address')
365
+
366
+ assert request.call_count == 2
367
+
368
+
369
+ def test_fetch_staked_sol_uses_legacy_method_for_non_helius_rpc():
370
+ api = SolanaApi()
371
+
372
+ with patch.object(api, '_request', return_value={'result': []}) as request:
373
+ response = api._fetch_staked_sol('address')
374
+
375
+ request.assert_called_once()
376
+ assert request.call_args.kwargs['method'] == 'getProgramAccounts'
377
+ assert 'limit' not in request.call_args.kwargs['params'][1]
378
+ assert response == {'result': []}
379
+
380
+
240
381
  def test_das_cache_stores_sentinel_for_unknown_mint():
241
382
  api = SolanaApi()
242
383
  unknown_mint = 'UnknownMint111111111111111111111111111111111'
@@ -1,6 +1,7 @@
1
1
  import json
2
2
  import logging
3
3
  from typing import Optional, Union
4
+ from urllib.parse import urlparse
4
5
 
5
6
  from cytoolz import reduceby
6
7
  from requests import Response
@@ -79,6 +80,8 @@ class SolanaApi(CustomizableBlockchainApi, BalanceMixin):
79
80
  TOKEN_2022_PROGRAM_ID = 'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb'
80
81
  STAKE_PROGRAM_ID = 'Stake11111111111111111111111111111111111111'
81
82
  STAKE_AUTHORITY_OFFSET = 44
83
+ HELIUS_RPC_DOMAIN = 'helius-rpc.com'
84
+ HELIUS_PROGRAM_ACCOUNTS_PAGE_SIZE = 5000
82
85
  DAS_BATCH_SIZE = 1000
83
86
  _JSONRPC_INVALID_PARAMS = -32602
84
87
 
@@ -314,25 +317,51 @@ class SolanaApi(CustomizableBlockchainApi, BalanceMixin):
314
317
 
315
318
  def _fetch_staked_sol(self, address: str) -> dict:
316
319
  """Fetch staked SOL accounts for a given address."""
317
- return self._request(
318
- method='getProgramAccounts',
319
- params=[
320
- self.STAKE_PROGRAM_ID,
320
+ config = {
321
+ 'filters': [
321
322
  {
322
- 'filters': [
323
- {
324
- 'memcmp': {
325
- 'offset': self.STAKE_AUTHORITY_OFFSET,
326
- 'bytes': address,
327
- 'encoding': 'base58',
328
- }
329
- }
330
- ],
331
- 'encoding': 'jsonParsed',
332
- 'commitment': 'finalized',
333
- },
323
+ 'memcmp': {
324
+ 'offset': self.STAKE_AUTHORITY_OFFSET,
325
+ 'bytes': address,
326
+ 'encoding': 'base58',
327
+ }
328
+ }
334
329
  ],
330
+ 'encoding': 'jsonParsed',
331
+ 'commitment': 'finalized',
332
+ }
333
+
334
+ hostname = urlparse(self.base_url).hostname or ''
335
+ is_helius_rpc = hostname == self.HELIUS_RPC_DOMAIN or hostname.endswith(
336
+ f'.{self.HELIUS_RPC_DOMAIN}'
335
337
  )
338
+ if not is_helius_rpc:
339
+ return self._request(
340
+ method='getProgramAccounts',
341
+ params=[self.STAKE_PROGRAM_ID, config],
342
+ )
343
+
344
+ config['limit'] = self.HELIUS_PROGRAM_ACCOUNTS_PAGE_SIZE
345
+ accounts = []
346
+ seen_pagination_keys = set()
347
+
348
+ while True:
349
+ response = self._request(
350
+ method='getProgramAccountsV2',
351
+ params=[self.STAKE_PROGRAM_ID, config],
352
+ )
353
+ page = response['result']
354
+ accounts.extend(page['accounts'])
355
+
356
+ pagination_key = page.get('paginationKey')
357
+ if pagination_key is None:
358
+ response['result'] = accounts
359
+ return response
360
+ if pagination_key in seen_pagination_keys:
361
+ raise ApiException('Solana RPC returned a repeated pagination key')
362
+
363
+ seen_pagination_keys.add(pagination_key)
364
+ config = {**config, 'paginationKey': pagination_key}
336
365
 
337
366
  # ── Balance parsing ────────────────────────────────────────
338
367
 
@@ -373,7 +402,7 @@ class SolanaApi(CustomizableBlockchainApi, BalanceMixin):
373
402
  def _parse_rent_reserve(
374
403
  self, staked_sol: BalanceItem, raw_staked_sol: dict
375
404
  ) -> BalanceItem:
376
- """Parse rent reserve from getProgramAccounts response.
405
+ """Parse rent reserve from a program accounts response.
377
406
 
378
407
  Uses result[].account.lamports already returned by _fetch_staked_sol,
379
408
  avoiding a separate getMultipleAccounts call.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: blockapi
3
- Version: 2.11.2
3
+ Version: 2.11.3
4
4
  Summary: BlockAPI library
5
5
  Home-page: https://github.com/crypkit/blockapi
6
6
  Author: Devmons s.r.o.
@@ -6,7 +6,7 @@ with open("README.md", "r") as f:
6
6
 
7
7
  PACKAGES = find_packages(where='.')
8
8
 
9
- __version__ = "2.11.2"
9
+ __version__ = "2.11.3"
10
10
 
11
11
  setuptools.setup(
12
12
  name='blockapi',
File without changes
File without changes
File without changes
File without changes
File without changes