Skip to content

Commit 265c3e0

Browse files
authored
feat: enhance handling of icon_url in unisat parse_collection, polished NftCollectionTotalStats object attributes (#240)
* feat: enhance handling of icon_url in unisat parse_collection * polished NftCollectionTotalStats object attributes * fix:unisat test fixed assertion values
1 parent 4b07296 commit 265c3e0

3 files changed

Lines changed: 87 additions & 46 deletions

File tree

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"code": 0,
3+
"msg": "ok",
4+
"data": {
5+
"collectionId": "rune-mania-miner",
6+
"name": "Rune Mania Miner",
7+
"desc": "Rune Mania: Utilize your RMM to mine Runes using:⛏️ Mining Boosts🧱 Block Boosts🧪 Mana Boosts🗿 Stone Boosts ✨ Rune Boosts",
8+
"icon": "https://creator-hub-prod.s3.us-east-2.amazonaws.com/ord-rmm_pfp_1708461604099.png",
9+
"btcValue": 0,
10+
"btcValuePercent": 0,
11+
"floorPrice": 80000,
12+
"listed": 9,
13+
"total": 3800,
14+
"supply": null,
15+
"attrs": [],
16+
"twitter": "https://twitter.com/RuneManiaMiner",
17+
"discord": null,
18+
"website": "https://www.ord.io/61549984",
19+
"pricePercent": 0,
20+
"verification": false
21+
}
22+
}

blockapi/test/v2/api/nft/test_unisat.py

Lines changed: 56 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -24,36 +24,62 @@
2424
test_nft_type = BtcNftType.COLLECTION
2525

2626

27-
def test_fetch_collection(requests_mock, unisat_client, collection_stats):
27+
def test_fetch_collection_icon_code(requests_mock, unisat_client, collection_stats):
28+
"""
29+
UniSat sometimes sends only the icon *code* ― no URL.
30+
We expect `parse_collection` to prepend the static CDN prefix automatically.
31+
"""
2832
requests_mock.post(
29-
f"{unisat_client.api_options.base_url}v3/market/collection/auction/collection_statistic",
33+
f"{unisat_client.api_options.base_url}"
34+
"v3/market/collection/auction/collection_statistic",
3035
text=collection_stats,
3136
)
3237

33-
test_collection = "pixel-pepes"
34-
fetch_result = unisat_client.fetch_collection(test_collection)
35-
assert not fetch_result.errors, f"Fetch errors: {fetch_result.errors}"
38+
fetch_result = unisat_client.fetch_collection("pixel-pepes")
39+
assert not fetch_result.errors
40+
41+
parsed = unisat_client.parse_collection(fetch_result)
42+
assert not parsed.errors and len(parsed.data) == 1
43+
44+
col: NftCollection = parsed.data[0]
45+
assert col.ident == "pixel-pepes"
46+
assert col.name == "Pixel Pepes"
47+
assert (
48+
col.image == "https://static.unisat.io/content/"
49+
"47c1d21c508f6d49dfde64d958f14acd041244e1bb616f9b78114b8d9dc7b945i0"
50+
)
51+
assert str(col.total_stats.floor_price) == "0.0099"
52+
assert str(col.total_stats.volume) == "0.399"
53+
3654

37-
parse_result = unisat_client.parse_collection(fetch_result)
38-
assert not parse_result.errors, f"Parse errors: {parse_result.errors}"
39-
assert len(parse_result.data) == 1
55+
def test_fetch_collection_icon_full_url(
56+
requests_mock, unisat_client, collection_stats_full_url
57+
):
58+
"""
59+
UniSat may also deliver a *fully-qualified* icon URL.
60+
In that case we should **not** touch the value.
61+
"""
62+
requests_mock.post(
63+
f"{unisat_client.api_options.base_url}"
64+
"v3/market/collection/auction/collection_statistic",
65+
text=collection_stats_full_url,
66+
)
67+
68+
fetch_result = unisat_client.fetch_collection("rune-mania-miner")
69+
assert not fetch_result.errors
4070

41-
collection = parse_result.data[0]
42-
assert isinstance(collection, NftCollection)
43-
assert collection.ident == "pixel-pepes"
44-
assert collection.name == "Pixel Pepes"
71+
parsed = unisat_client.parse_collection(fetch_result)
72+
assert not parsed.errors and len(parsed.data) == 1
73+
74+
col: NftCollection = parsed.data[0]
75+
assert col.ident == "rune-mania-miner"
76+
assert col.name == "Rune Mania Miner"
4577
assert (
46-
collection.image
47-
== "https://static.unisat.io/content/47c1d21c508f6d49dfde64d958f14acd041244e1bb616f9b78114b8d9dc7b945i0"
78+
col.image == "https://creator-hub-prod.s3.us-east-2.amazonaws.com/"
79+
"ord-rmm_pfp_1708461604099.png"
4880
)
49-
assert not collection.is_disabled
50-
assert not collection.is_nsfw
51-
assert collection.blockchain == Blockchain.BITCOIN
52-
assert str(collection.total_stats.floor_price) == "0.0099"
53-
assert str(collection.total_stats.owners_count) == "1563"
54-
assert str(collection.total_stats.sales_count) == "20"
55-
assert str(collection.total_stats.volume) == "0.399"
56-
assert str(collection.total_stats.market_cap) == "15.4737"
81+
82+
assert str(col.total_stats.floor_price) == "0.0008"
5783

5884

5985
def test_fetch_listings(requests_mock, unisat_client, listings_data):
@@ -153,21 +179,6 @@ def unisat_client(fake_sleep_provider):
153179
return UnisatApi(api_key="test_key", sleep_provider=fake_sleep_provider)
154180

155181

156-
@pytest.fixture
157-
def inscription_data():
158-
return read_file('data/unisat/inscription_data.json')
159-
160-
161-
@pytest.fixture
162-
def inscription_data_edge_cases():
163-
return read_file('data/unisat/inscription_data_edge_cases.json')
164-
165-
166-
@pytest.fixture
167-
def collection_edge_cases():
168-
return read_file('data/unisat/collection_edge_cases.json')
169-
170-
171182
@pytest.fixture
172183
def listings_data():
173184
return read_file('data/unisat/listings.json')
@@ -180,4 +191,11 @@ def offers_data():
180191

181192
@pytest.fixture
182193
def collection_stats():
183-
return read_file('data/unisat/collection_stats.json')
194+
"""Pixel Pepes – icon **code** only."""
195+
return read_file("data/unisat/collection_stats.json")
196+
197+
198+
@pytest.fixture
199+
def collection_stats_full_url():
200+
"""Rune Mania Miner – icon is a full URL."""
201+
return read_file("data/unisat/collection_stats_full_url.json")

blockapi/v2/api/nft/unisat.py

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -293,23 +293,24 @@ def parse_collection(self, fetch_result: FetchResult) -> ParseResult:
293293
# Format the icon URL
294294
icon = stats.get("icon")
295295
icon_url = None
296+
296297
if icon:
297-
icon_url = f"https://static.unisat.io/content/{icon}"
298+
if icon.startswith(("http://", "https://")):
299+
icon_url = icon
300+
else:
301+
icon_url = f"https://static.unisat.io/content/{icon.lstrip('/')}"
298302

299303
floor_price = raw_to_decimals(stats.get("floorPrice", 0), self.coin.decimals)
300304

301305
volume = raw_to_decimals(stats.get("btcValue", 0), self.coin.decimals)
302306

303-
total_nfts = stats.get("total", 0)
304-
market_cap = floor_price * total_nfts if total_nfts else 0
305-
306307
total_stats = NftCollectionTotalStats.from_api(
307308
volume=str(volume),
308-
sales_count=str(stats.get("listed", 0)),
309-
owners_count=str(total_nfts),
310-
market_cap=str(market_cap),
309+
sales_count=None,
310+
owners_count=None,
311+
market_cap=None,
311312
floor_price=str(floor_price),
312-
average_price="0",
313+
average_price=None,
313314
coin=self.coin,
314315
)
315316

0 commit comments

Comments
 (0)