blockapi 2.10.3__tar.gz → 2.10.4__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-2.10.3 → blockapi-2.10.4}/PKG-INFO +1 -1
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/services.py +3 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/test/v2/api/nft/test_opensea.py +3 -1
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/test/v2/api/nft/test_simple_hash.py +3 -1
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/utils/datetime.py +6 -1
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/v2/api/debank.py +3 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/v2/api/nft/unisat.py +2 -2
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/v2/base.py +4 -4
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/v2/models.py +4 -2
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi.egg-info/PKG-INFO +1 -1
- {blockapi-2.10.3 → blockapi-2.10.4}/setup.py +1 -1
- {blockapi-2.10.3 → blockapi-2.10.4}/LICENSE.md +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/README.md +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/__init__.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/test/__init__.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/test/test_blockapi.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/test/test_num.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/test/test_random_user_agent.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/test/v2/__init__.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/test/v2/api/__init__.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/test/v2/api/conftest.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/test/v2/api/covalenth/__init__.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/test/v2/api/covalenth/test_ethereum.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/test/v2/api/fake_sleep_provider.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/test/v2/api/nft/__init__.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/test/v2/api/nft/test_magic_eden.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/test/v2/api/nft/test_unisat.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/test/v2/api/test_bitaps_ltc.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/test/v2/api/test_blockchain_info.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/test/v2/api/test_blockchainos.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/test/v2/api/test_blockchair_btc.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/test/v2/api/test_blockchair_doge.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/test/v2/api/test_blockchair_ltc.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/test/v2/api/test_cosmos.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/test/v2/api/test_ethplorer.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/test/v2/api/test_haskoin.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/test/v2/api/test_litecoinspace.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/test/v2/api/test_multisources.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/test/v2/api/test_optimistic_etherscan.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/test/v2/api/test_solana.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/test/v2/api/test_subscan_polkadot.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/test/v2/api/test_sui.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/test/v2/api/test_terra.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/test/v2/api/test_trezor_btc.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/test/v2/api/test_trezor_zec.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/test/v2/test_base.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/test/v2/test_blockchain_api.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/test/v2/test_blockchain_mapping.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/test/v2/test_data.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/test/v2/test_enumerate_classes.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/test/v2/test_generic.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/test/v2/test_models.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/test_data.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/utils/__init__.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/utils/address.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/utils/num.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/utils/user_agent.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/v2/__init__.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/v2/api/__init__.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/v2/api/bitaps.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/v2/api/blockchain_info.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/v2/api/blockchainos.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/v2/api/blockchair.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/v2/api/cosmos.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/v2/api/covalenth/__init__.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/v2/api/covalenth/arbitrum.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/v2/api/covalenth/astar.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/v2/api/covalenth/avalanche.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/v2/api/covalenth/axie.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/v2/api/covalenth/base.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/v2/api/covalenth/binance_smart_chain.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/v2/api/covalenth/ethereum.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/v2/api/covalenth/fantom.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/v2/api/covalenth/heco.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/v2/api/covalenth/iotex.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/v2/api/covalenth/klaytn.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/v2/api/covalenth/moonbeam.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/v2/api/covalenth/palm.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/v2/api/covalenth/polygon.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/v2/api/covalenth/rsk.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/v2/api/debank_maps.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/v2/api/ethplorer.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/v2/api/haskoin.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/v2/api/litecoinspace.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/v2/api/nft/__init__.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/v2/api/nft/magic_eden.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/v2/api/nft/opensea.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/v2/api/nft/simple_hash.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/v2/api/optimistic_etherscan.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/v2/api/solana.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/v2/api/subscan.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/v2/api/sui.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/v2/api/terra.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/v2/api/trezor.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/v2/blockchain_mapping.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/v2/coin_mapping.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi/v2/coins.py +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi.egg-info/SOURCES.txt +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi.egg-info/dependency_links.txt +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi.egg-info/requires.txt +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/blockapi.egg-info/top_level.txt +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/pyproject.toml +0 -0
- {blockapi-2.10.3 → blockapi-2.10.4}/setup.cfg +0 -0
|
@@ -56,6 +56,9 @@ class Service(ABC):
|
|
|
56
56
|
response = reqobj.get(request_url, headers=headers)
|
|
57
57
|
|
|
58
58
|
self.last_response = response
|
|
59
|
+
# Naive local time on purpose: only used to measure elapsed time against
|
|
60
|
+
# datetime.now() in wait_for_next_request (rate limiting), never compared
|
|
61
|
+
# with tz-aware datetimes.
|
|
59
62
|
self.last_response_time = datetime.now()
|
|
60
63
|
|
|
61
64
|
if response.status_code != 200:
|
|
@@ -162,7 +162,9 @@ def test_parse_nfts(requests_mock, api, nfts_response, nfts_next_response):
|
|
|
162
162
|
== 'data:application/json;base64,eyJuYW1lIjoiVW5pc3dhcCAtIDElIC0gUFJJTUUvV0VUSCAtIDMzMC4yMDw+NzgwLjI5In0='
|
|
163
163
|
)
|
|
164
164
|
assert not data.metadata
|
|
165
|
-
assert data.updated_time == datetime.datetime(
|
|
165
|
+
assert data.updated_time == datetime.datetime(
|
|
166
|
+
2023, 8, 15, 13, 56, 39, 759414, tzinfo=datetime.timezone.utc
|
|
167
|
+
)
|
|
166
168
|
assert not data.is_disabled
|
|
167
169
|
assert not data.is_nsfw
|
|
168
170
|
assert data.blockchain == Blockchain.ETHEREUM
|
|
@@ -55,7 +55,9 @@ def test_parse_nfts(requests_mock, api, nfts_response):
|
|
|
55
55
|
)
|
|
56
56
|
assert not data.metadata_url
|
|
57
57
|
assert not data.metadata
|
|
58
|
-
assert data.updated_time == datetime.datetime(
|
|
58
|
+
assert data.updated_time == datetime.datetime(
|
|
59
|
+
2023, 3, 11, 3, 46, 15, tzinfo=datetime.timezone.utc
|
|
60
|
+
)
|
|
59
61
|
assert not data.is_disabled
|
|
60
62
|
assert not data.is_nsfw
|
|
61
63
|
assert data.blockchain == Blockchain.BITCOIN
|
|
@@ -12,7 +12,12 @@ def parse_dt(dt: Union[str, int, float]) -> datetime:
|
|
|
12
12
|
try:
|
|
13
13
|
return datetime.fromtimestamp(int(dt), tz=timezone.utc)
|
|
14
14
|
except ValueError:
|
|
15
|
-
|
|
15
|
+
parsed = parse_date(dt)
|
|
16
|
+
# Assume UTC for strings that carry no timezone, so parse_dt always
|
|
17
|
+
# returns a tz-aware datetime (consistent with the numeric paths).
|
|
18
|
+
if parsed.tzinfo is None:
|
|
19
|
+
parsed = parsed.replace(tzinfo=timezone.utc)
|
|
20
|
+
return parsed
|
|
16
21
|
elif isinstance(dt, int) or isinstance(dt, float):
|
|
17
22
|
return datetime.fromtimestamp(dt, tz=timezone.utc)
|
|
18
23
|
else:
|
|
@@ -243,6 +243,9 @@ class DebankProtocolCache:
|
|
|
243
243
|
def __init__(self, timeout: int = 3600):
|
|
244
244
|
self._timeout: int = timeout
|
|
245
245
|
self._data: Dict[str, Protocol] = {}
|
|
246
|
+
# Naive local time on purpose: _timelimit is only ever compared against
|
|
247
|
+
# other datetime.now() values here (cache TTL), never mixed with the
|
|
248
|
+
# tz-aware datetimes used elsewhere, so there is no naive/aware hazard.
|
|
246
249
|
self._timelimit = datetime.now()
|
|
247
250
|
|
|
248
251
|
def invalidate(self):
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
from typing import Optional, Dict, Generator, Tuple
|
|
3
3
|
from enum import Enum
|
|
4
|
-
from datetime import datetime
|
|
4
|
+
from datetime import datetime, timezone
|
|
5
5
|
|
|
6
6
|
from blockapi.v2.base import BlockchainApi, INftParser, INftProvider, ISleepProvider
|
|
7
7
|
from blockapi.v2.coins import COIN_BTC
|
|
@@ -670,7 +670,7 @@ class UnisatApi(BlockchainApi, INftParser, INftProvider):
|
|
|
670
670
|
try:
|
|
671
671
|
timestamp_seconds = timestamp / 1000
|
|
672
672
|
formatted_time = datetime.fromtimestamp(
|
|
673
|
-
timestamp_seconds
|
|
673
|
+
timestamp_seconds, tz=timezone.utc
|
|
674
674
|
).isoformat()
|
|
675
675
|
except (ValueError, TypeError, OverflowError):
|
|
676
676
|
logger.warning(
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
import time
|
|
3
3
|
from abc import ABC
|
|
4
|
-
from datetime import datetime, timedelta
|
|
4
|
+
from datetime import datetime, timedelta, timezone
|
|
5
5
|
from typing import Dict, List, Optional
|
|
6
6
|
from urllib.parse import urljoin
|
|
7
7
|
|
|
@@ -107,7 +107,7 @@ class CustomizableBlockchainApi(ABC):
|
|
|
107
107
|
return FetchResult(
|
|
108
108
|
status_code=1,
|
|
109
109
|
errors=[str(connection_error)],
|
|
110
|
-
time=datetime.
|
|
110
|
+
time=datetime.now(timezone.utc),
|
|
111
111
|
)
|
|
112
112
|
|
|
113
113
|
self.sleep_provider.sleep(self.base_url, seconds=sleep_seconds)
|
|
@@ -155,7 +155,7 @@ class CustomizableBlockchainApi(ABC):
|
|
|
155
155
|
headers=dict(),
|
|
156
156
|
errors=[f'{type(ex).__name__}: {str(ex)}'],
|
|
157
157
|
extra=extra,
|
|
158
|
-
time=datetime.
|
|
158
|
+
time=datetime.now(timezone.utc),
|
|
159
159
|
)
|
|
160
160
|
|
|
161
161
|
time = self._get_response_time(response.headers)
|
|
@@ -236,7 +236,7 @@ class CustomizableBlockchainApi(ABC):
|
|
|
236
236
|
return parse_dt(date_str)
|
|
237
237
|
|
|
238
238
|
if age_str := headers.get('age'):
|
|
239
|
-
return datetime.
|
|
239
|
+
return datetime.now(timezone.utc) - timedelta(seconds=int(age_str))
|
|
240
240
|
|
|
241
241
|
return None
|
|
242
242
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import json
|
|
2
|
-
from datetime import datetime
|
|
2
|
+
from datetime import datetime, timezone
|
|
3
3
|
from decimal import Decimal
|
|
4
4
|
from enum import Enum
|
|
5
5
|
from typing import Dict, List, Literal, Optional, Union
|
|
@@ -863,7 +863,9 @@ class NftOffer:
|
|
|
863
863
|
contract=contract,
|
|
864
864
|
blockchain=blockchain,
|
|
865
865
|
offerer=offerer,
|
|
866
|
-
start_time=
|
|
866
|
+
start_time=(
|
|
867
|
+
parse_dt(start_time) if start_time else datetime.now(timezone.utc)
|
|
868
|
+
),
|
|
867
869
|
end_time=parse_dt(end_time) if end_time else None,
|
|
868
870
|
offer_coin=offer_coin,
|
|
869
871
|
offer_contract=offer_contract.lower() if offer_contract else None,
|
|
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
|