blockapi 0.59.2__tar.gz → 0.59.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.
- {blockapi-0.59.2 → blockapi-0.59.3}/PKG-INFO +1 -1
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/test/v2/api/nft/test_unisat.py +0 -3
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/v2/api/nft/unisat.py +44 -45
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi.egg-info/PKG-INFO +1 -1
- {blockapi-0.59.2 → blockapi-0.59.3}/setup.py +1 -1
- {blockapi-0.59.2 → blockapi-0.59.3}/LICENSE.md +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/README.md +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/__init__.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/api/__init__.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/api/alethio.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/api/amberdata.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/api/binance.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/api/blockchaininfo.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/api/blockchainos.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/api/blockchair.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/api/blockcypher.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/api/blockonomics.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/api/blockscout.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/api/btc.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/api/cardanoexplorer.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/api/chainso.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/api/cosmos.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/api/cryptoid.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/api/dcrdata.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/api/digonchain.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/api/eospark.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/api/etherscan.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/api/ethplorer.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/api/greymass.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/api/insight.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/api/kyber.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/api/neoscan.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/api/ontology.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/api/solana.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/api/stellar.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/api/subscan.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/api/terra_money.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/api/trezor.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/api/tronscan.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/api/tzscan.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/api/tzstats.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/api/zchain.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/api/zensystem.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/services.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/test/__init__.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/test/api/__init__.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/test/api/test_amberdata.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/test/api/test_balances.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/test/api/test_binance.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/test/api/test_blockchainos.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/test/api/test_blockchair.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/test/api/test_blockscout.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/test/api/test_btc.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/test/api/test_cosmos.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/test/api/test_dcrdata.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/test/api/test_digonchain.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/test/api/test_insight.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/test/api/test_kyber.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/test/api/test_ontio.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/test/api/test_solana.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/test/api/test_subscan.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/test/api/test_terra_money.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/test/api/test_tronscan.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/test/api/test_tzscan.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/test/api/test_tzstats.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/test/test_blockapi.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/test/test_num.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/test/test_random_user_agent.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/test/v2/__init__.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/test/v2/api/__init__.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/test/v2/api/conftest.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/test/v2/api/covalenth/__init__.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/test/v2/api/covalenth/test_ethereum.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/test/v2/api/fake_sleep_provider.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/test/v2/api/nft/__init__.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/test/v2/api/nft/test_magic_eden.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/test/v2/api/nft/test_opensea.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/test/v2/api/nft/test_simple_hash.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/test/v2/api/perpetual/__init__.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/test/v2/api/perpetual/test_perpetual.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/test/v2/api/synthetix/__init__.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/test/v2/api/synthetix/test_synthetix.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/test/v2/api/test_blockchainos.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/test/v2/api/test_blockchair_btc.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/test/v2/api/test_blockchair_doge.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/test/v2/api/test_blockchair_ltc.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/test/v2/api/test_cosmos.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/test/v2/api/test_ethplorer.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/test/v2/api/test_multisources.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/test/v2/api/test_optimistic_etherscan.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/test/v2/api/test_solana.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/test/v2/api/test_subscan_polkadot.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/test/v2/api/test_sui.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/test/v2/api/test_trezor_btc.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/test/v2/test_base.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/test/v2/test_blockchain_api.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/test/v2/test_blockchain_mapping.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/test/v2/test_data.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/test/v2/test_enumerate_classes.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/test/v2/test_generic.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/test/v2/test_models.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/test_data.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/utils/__init__.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/utils/address.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/utils/datetime.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/utils/ethereum.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/utils/num.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/utils/user_agent.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/v2/__init__.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/v2/api/__init__.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/v2/api/blockchainos.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/v2/api/blockchair.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/v2/api/cosmos.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/v2/api/covalenth/__init__.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/v2/api/covalenth/arbitrum.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/v2/api/covalenth/astar.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/v2/api/covalenth/avalanche.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/v2/api/covalenth/axie.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/v2/api/covalenth/base.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/v2/api/covalenth/binance_smart_chain.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/v2/api/covalenth/ethereum.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/v2/api/covalenth/fantom.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/v2/api/covalenth/heco.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/v2/api/covalenth/iotex.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/v2/api/covalenth/klaytn.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/v2/api/covalenth/moonbeam.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/v2/api/covalenth/palm.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/v2/api/covalenth/polygon.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/v2/api/covalenth/rsk.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/v2/api/debank.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/v2/api/debank_maps.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/v2/api/ethplorer.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/v2/api/nft/__init__.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/v2/api/nft/magic_eden.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/v2/api/nft/opensea.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/v2/api/nft/simple_hash.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/v2/api/optimistic_etherscan.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/v2/api/perpetual/__init__.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/v2/api/perpetual/perp_abi.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/v2/api/perpetual/perpetual.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/v2/api/solana.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/v2/api/subscan.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/v2/api/sui.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/v2/api/synthetix/__init__.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/v2/api/synthetix/synthetix.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/v2/api/synthetix/synthetix_abi.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/v2/api/terra.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/v2/api/trezor.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/v2/api/web3_utils.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/v2/base.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/v2/blockchain_mapping.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/v2/coin_mapping.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/v2/coins.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi/v2/models.py +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi.egg-info/SOURCES.txt +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi.egg-info/dependency_links.txt +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi.egg-info/requires.txt +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/blockapi.egg-info/top_level.txt +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/pyproject.toml +0 -0
- {blockapi-0.59.2 → blockapi-0.59.3}/setup.cfg +0 -0
|
@@ -53,7 +53,6 @@ def test_parse_nfts(requests_mock, unisat_client, inscription_data):
|
|
|
53
53
|
assert nft1.standard == "ordinals"
|
|
54
54
|
assert nft1.name == "Ordinal #12345"
|
|
55
55
|
assert nft1.amount == 1
|
|
56
|
-
assert nft1.updated_time == 1672531200
|
|
57
56
|
assert nft1.blockchain == Blockchain.BITCOIN
|
|
58
57
|
assert nft1.asset_type == AssetType.AVAILABLE
|
|
59
58
|
|
|
@@ -72,7 +71,6 @@ def test_parse_nfts(requests_mock, unisat_client, inscription_data):
|
|
|
72
71
|
assert nft2.standard == "ordinals"
|
|
73
72
|
assert nft2.name == "Ordinal #12346"
|
|
74
73
|
assert nft2.amount == 1
|
|
75
|
-
assert nft2.updated_time == 1672531300
|
|
76
74
|
assert nft2.blockchain == Blockchain.BITCOIN
|
|
77
75
|
assert nft2.asset_type == AssetType.AVAILABLE
|
|
78
76
|
|
|
@@ -108,7 +106,6 @@ def test_parse_nfts_edge_cases(
|
|
|
108
106
|
assert nft.standard == "ordinals"
|
|
109
107
|
assert nft.name == "Ordinal #2"
|
|
110
108
|
assert nft.amount == 1
|
|
111
|
-
assert nft.updated_time == 1234567890
|
|
112
109
|
assert nft.blockchain == Blockchain.BITCOIN
|
|
113
110
|
assert nft.asset_type == AssetType.AVAILABLE
|
|
114
111
|
|
|
@@ -54,7 +54,12 @@ class UnisatApi(BlockchainApi, INftParser, INftProvider):
|
|
|
54
54
|
'get_collection_stats': 'v3/market/collection/auction/collection_statistic',
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
def __init__(
|
|
57
|
+
def __init__(
|
|
58
|
+
self,
|
|
59
|
+
api_key: str,
|
|
60
|
+
sleep_provider: Optional[ISleepProvider] = None,
|
|
61
|
+
limit: Optional[int] = 10000,
|
|
62
|
+
):
|
|
58
63
|
"""
|
|
59
64
|
Initialize the Unisat API client
|
|
60
65
|
|
|
@@ -70,17 +75,14 @@ class UnisatApi(BlockchainApi, INftParser, INftProvider):
|
|
|
70
75
|
'Authorization': f'Bearer {api_key}',
|
|
71
76
|
'Content-Type': 'application/json',
|
|
72
77
|
}
|
|
78
|
+
self.limit = limit
|
|
73
79
|
|
|
74
|
-
def fetch_nfts(
|
|
75
|
-
self, address: str, cursor: Optional[int] = None, size: int = 16
|
|
76
|
-
) -> FetchResult:
|
|
80
|
+
def fetch_nfts(self, address: str) -> FetchResult:
|
|
77
81
|
"""
|
|
78
82
|
Fetch NFTs (inscriptions) owned by the address
|
|
79
83
|
|
|
80
84
|
Args:
|
|
81
85
|
address: BTC address to fetch NFTs for
|
|
82
|
-
cursor: Pagination cursor (offset)
|
|
83
|
-
size: Number of items to return per page (default: 16)
|
|
84
86
|
|
|
85
87
|
Returns:
|
|
86
88
|
FetchResult containing the NFT data
|
|
@@ -91,9 +93,7 @@ class UnisatApi(BlockchainApi, INftParser, INftProvider):
|
|
|
91
93
|
if not address:
|
|
92
94
|
raise ValueError("Address is required")
|
|
93
95
|
|
|
94
|
-
params = {'size':
|
|
95
|
-
if cursor is not None:
|
|
96
|
-
params['cursor'] = cursor
|
|
96
|
+
params = {'size': self.limit, 'cursor': 0}
|
|
97
97
|
|
|
98
98
|
try:
|
|
99
99
|
return self.get_data(
|
|
@@ -116,76 +116,74 @@ class UnisatApi(BlockchainApi, INftParser, INftProvider):
|
|
|
116
116
|
"""Parse NFT data from API response"""
|
|
117
117
|
errors = []
|
|
118
118
|
data = []
|
|
119
|
-
cursor = None
|
|
120
119
|
|
|
121
120
|
if not fetch_result.data:
|
|
122
121
|
errors.append("No data in fetch result")
|
|
123
122
|
return ParseResult(data=[], errors=errors)
|
|
124
123
|
|
|
124
|
+
if isinstance(fetch_result.data, dict) and "code" in fetch_result.data:
|
|
125
|
+
api_code = fetch_result.data["code"]
|
|
126
|
+
if api_code != 0:
|
|
127
|
+
api_msg = fetch_result.data.get("msg", "Unknown error")
|
|
128
|
+
errors.append(f"Unisat error {api_code}: {api_msg}")
|
|
129
|
+
return ParseResult(data=[], errors=errors)
|
|
130
|
+
|
|
125
131
|
inner_data = fetch_result.data.get("data", {})
|
|
126
132
|
if not inner_data:
|
|
127
133
|
errors.append("No data in API response")
|
|
128
134
|
return ParseResult(data=[], errors=errors)
|
|
129
135
|
|
|
130
|
-
cursor = (
|
|
131
|
-
str(inner_data.get("cursor"))
|
|
132
|
-
if inner_data.get("cursor") is not None
|
|
133
|
-
else None
|
|
134
|
-
)
|
|
135
|
-
|
|
136
136
|
for nft in self._yield_parsed_nfts(inner_data):
|
|
137
137
|
data.append(nft)
|
|
138
138
|
|
|
139
|
-
return ParseResult(data=data, errors=errors
|
|
139
|
+
return ParseResult(data=data, errors=errors)
|
|
140
140
|
|
|
141
141
|
def _yield_parsed_nfts(self, data: Dict) -> Generator[NftToken, None, None]:
|
|
142
|
-
"""Yield parsed NFT tokens from API response
|
|
142
|
+
"""Yield parsed NFT tokens from Unisat API response"""
|
|
143
143
|
if not data or "inscription" not in data:
|
|
144
|
+
logger.warning("No NFT data found in response")
|
|
144
145
|
return
|
|
145
146
|
|
|
146
147
|
for item in data["inscription"]:
|
|
147
148
|
try:
|
|
148
149
|
if not all(
|
|
149
150
|
k in item
|
|
150
|
-
for k in
|
|
151
|
+
for k in (
|
|
151
152
|
"inscriptionId",
|
|
152
153
|
"inscriptionNumber",
|
|
153
154
|
"timestamp",
|
|
154
155
|
"utxo",
|
|
155
|
-
|
|
156
|
+
)
|
|
156
157
|
):
|
|
157
158
|
logger.warning(f"Missing required fields in NFT data: {item}")
|
|
158
159
|
continue
|
|
159
160
|
|
|
160
161
|
utxo = item["utxo"]
|
|
161
|
-
if not all(k in utxo for k in
|
|
162
|
+
if not all(k in utxo for k in ("txid", "address")):
|
|
162
163
|
logger.warning(f"Missing required fields in UTXO data: {utxo}")
|
|
163
164
|
continue
|
|
164
165
|
|
|
165
|
-
|
|
166
|
-
timestamp = str(item["timestamp"])
|
|
167
|
-
|
|
168
|
-
yield NftToken(
|
|
166
|
+
yield NftToken.from_api(
|
|
169
167
|
ident=item["inscriptionId"],
|
|
170
168
|
collection="ordinals",
|
|
171
169
|
collection_name="Bitcoin Ordinals",
|
|
172
170
|
contract=utxo["txid"],
|
|
173
171
|
standard="ordinals",
|
|
174
|
-
name=f"Ordinal #{
|
|
172
|
+
name=f"Ordinal #{item['inscriptionNumber']}",
|
|
175
173
|
description="",
|
|
176
174
|
amount=1,
|
|
177
175
|
image_url="",
|
|
178
176
|
metadata_url=None,
|
|
179
|
-
|
|
180
|
-
updated_time=int(timestamp),
|
|
177
|
+
updated_time=str(item["timestamp"]),
|
|
181
178
|
is_disabled=False,
|
|
182
179
|
is_nsfw=False,
|
|
183
180
|
blockchain=Blockchain.BITCOIN,
|
|
184
181
|
asset_type=AssetType.AVAILABLE,
|
|
185
182
|
market_url=None,
|
|
186
183
|
)
|
|
184
|
+
|
|
187
185
|
except Exception as e:
|
|
188
|
-
logger.warning(f"Error parsing NFT item {item}: {e}")
|
|
186
|
+
logger.warning(f"Error parsing NFT item {item}: {str(e)}")
|
|
189
187
|
continue
|
|
190
188
|
|
|
191
189
|
def fetch_collection(self, collection: str) -> FetchResult:
|
|
@@ -269,8 +267,7 @@ class UnisatApi(BlockchainApi, INftParser, INftProvider):
|
|
|
269
267
|
self,
|
|
270
268
|
nft_type: BtcNftType = BtcNftType.COLLECTION,
|
|
271
269
|
collection: Optional[str] = None,
|
|
272
|
-
|
|
273
|
-
limit: int = 100,
|
|
270
|
+
limit: int = 499,
|
|
274
271
|
address: Optional[str] = None,
|
|
275
272
|
tick: Optional[str] = None,
|
|
276
273
|
min_price: Optional[int] = None,
|
|
@@ -293,7 +290,6 @@ class UnisatApi(BlockchainApi, INftParser, INftProvider):
|
|
|
293
290
|
Args:
|
|
294
291
|
nft_type: Type of NFT (brc20, domain, collection, arc20, runes)
|
|
295
292
|
collection: Collection ID (slug), optional
|
|
296
|
-
cursor: Pagination cursor (offset, 'start' parameter)
|
|
297
293
|
limit: Number of items per page
|
|
298
294
|
address: Filter by address
|
|
299
295
|
tick: Filter by tick (for BRC20)
|
|
@@ -319,8 +315,6 @@ class UnisatApi(BlockchainApi, INftParser, INftProvider):
|
|
|
319
315
|
nft_type.value if isinstance(nft_type, BtcNftType) else str(nft_type)
|
|
320
316
|
)
|
|
321
317
|
|
|
322
|
-
start = int(cursor) if cursor else 0
|
|
323
|
-
|
|
324
318
|
filter_dict = {"nftType": nft_type_str}
|
|
325
319
|
|
|
326
320
|
if collection:
|
|
@@ -355,10 +349,16 @@ class UnisatApi(BlockchainApi, INftParser, INftProvider):
|
|
|
355
349
|
sort_dict = {}
|
|
356
350
|
sort_dict[sort_by] = sort_order
|
|
357
351
|
|
|
352
|
+
if limit >= 500:
|
|
353
|
+
logger.warning(
|
|
354
|
+
f"Unisat API limit is 500. You tried to fetch {limit} items. Truncating to 499."
|
|
355
|
+
)
|
|
356
|
+
limit = 499
|
|
357
|
+
|
|
358
358
|
request_body = {
|
|
359
359
|
"filter": filter_dict,
|
|
360
360
|
"sort": sort_dict,
|
|
361
|
-
"start":
|
|
361
|
+
"start": 0,
|
|
362
362
|
"limit": limit,
|
|
363
363
|
}
|
|
364
364
|
|
|
@@ -394,12 +394,9 @@ class UnisatApi(BlockchainApi, INftParser, INftProvider):
|
|
|
394
394
|
return ParseResult(errors=fetch_result.errors)
|
|
395
395
|
|
|
396
396
|
items = inner_data.get("list", [])
|
|
397
|
-
timestamp = inner_data.get("timestamp")
|
|
398
|
-
cursor = str(timestamp) if timestamp else None
|
|
399
397
|
|
|
400
398
|
return ParseResult(
|
|
401
399
|
data=list(self._yield_parsed_listings(items)),
|
|
402
|
-
cursor=cursor,
|
|
403
400
|
errors=fetch_result.errors,
|
|
404
401
|
)
|
|
405
402
|
|
|
@@ -457,8 +454,7 @@ class UnisatApi(BlockchainApi, INftParser, INftProvider):
|
|
|
457
454
|
tick: Optional[str] = None,
|
|
458
455
|
domain_type: Optional[str] = None,
|
|
459
456
|
collection: Optional[str] = None,
|
|
460
|
-
|
|
461
|
-
limit: int = 100,
|
|
457
|
+
limit: int = 499,
|
|
462
458
|
) -> FetchResult:
|
|
463
459
|
"""
|
|
464
460
|
Fetch listing events (historical or recent) in a collection.
|
|
@@ -471,8 +467,7 @@ class UnisatApi(BlockchainApi, INftParser, INftProvider):
|
|
|
471
467
|
tick: Filter by tick (for BRC20)
|
|
472
468
|
domain_type: Filter by domain type
|
|
473
469
|
collection: Collection ID to filter by
|
|
474
|
-
|
|
475
|
-
limit: Number of items per page
|
|
470
|
+
limit: Number of items
|
|
476
471
|
|
|
477
472
|
Returns:
|
|
478
473
|
FetchResult containing the listing action data
|
|
@@ -482,8 +477,6 @@ class UnisatApi(BlockchainApi, INftParser, INftProvider):
|
|
|
482
477
|
nft_type.value if isinstance(nft_type, BtcNftType) else str(nft_type)
|
|
483
478
|
)
|
|
484
479
|
|
|
485
|
-
start = int(cursor) if cursor else 0
|
|
486
|
-
|
|
487
480
|
filter_dict = {}
|
|
488
481
|
if nft_type_str:
|
|
489
482
|
filter_dict["nftType"] = nft_type_str
|
|
@@ -500,9 +493,15 @@ class UnisatApi(BlockchainApi, INftParser, INftProvider):
|
|
|
500
493
|
if collection:
|
|
501
494
|
filter_dict["collectionId"] = collection
|
|
502
495
|
|
|
496
|
+
if limit >= 500:
|
|
497
|
+
logger.warning(
|
|
498
|
+
f"Unisat API limit is 500. You tried to fetch {limit} items. Truncating to 499."
|
|
499
|
+
)
|
|
500
|
+
limit = 499
|
|
501
|
+
|
|
503
502
|
request_body = {
|
|
504
503
|
"filter": filter_dict,
|
|
505
|
-
"start":
|
|
504
|
+
"start": 0,
|
|
506
505
|
"limit": limit,
|
|
507
506
|
}
|
|
508
507
|
|
|
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
|
|
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
|