cryptologo 0.1.0__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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 dobestan
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,308 @@
1
+ Metadata-Version: 2.4
2
+ Name: cryptologo
3
+ Version: 0.1.0
4
+ Summary: Python client for crypto-logo.com — 413 cryptocurrency logos in SVG, PNG, WebP, ICO
5
+ Project-URL: Homepage, https://crypto-logo.com
6
+ Project-URL: Documentation, https://crypto-logo.com/api/docs/
7
+ Project-URL: Repository, https://github.com/dobestan/cryptologo-python
8
+ Project-URL: API Reference, https://crypto-logo.com/api/docs/
9
+ Author-email: dobestan <dobestan@gmail.com>
10
+ License-Expression: MIT
11
+ License-File: LICENSE
12
+ Keywords: api-client,bitcoin,branding,crypto,cryptocurrency,ethereum,icon,logo,png,svg
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Programming Language :: Python :: 3.14
22
+ Classifier: Topic :: Multimedia :: Graphics
23
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
24
+ Classifier: Typing :: Typed
25
+ Requires-Python: >=3.10
26
+ Description-Content-Type: text/markdown
27
+
28
+ # cryptologo
29
+
30
+ [![PyPI](https://img.shields.io/pypi/v/cryptologo)](https://pypi.org/project/cryptologo/)
31
+ [![Python](https://img.shields.io/pypi/pyversions/cryptologo)](https://pypi.org/project/cryptologo/)
32
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
33
+ [![Zero Dependencies](https://img.shields.io/badge/dependencies-0-brightgreen)](https://pypi.org/project/cryptologo/)
34
+
35
+ Python client for [crypto-logo.com](https://crypto-logo.com) — the cryptocurrency logo database with 413 coins in SVG, PNG, WebP, JPEG, and ICO formats. Zero dependencies (stdlib `urllib` only).
36
+
37
+ Every logo is available as a scalable SVG vector and pre-generated raster derivatives in 13 standard sizes (16px to 2000px). Logos are served from Cloudflare R2 CDN with immutable cache headers for production-grade performance. The dataset is extracted from [crypto-logo.com](https://crypto-logo.com), which tracks logo assets for Bitcoin, Ethereum, Solana, and 410+ other cryptocurrencies ranked by market cap.
38
+
39
+ > **Try the interactive logo browser at [crypto-logo.com](https://crypto-logo.com)** — [Bitcoin logo](https://crypto-logo.com/bitcoin-btc/), [Ethereum logo](https://crypto-logo.com/ethereum-eth/), [API docs](https://crypto-logo.com/api/docs/)
40
+
41
+ ## Table of Contents
42
+
43
+ - [Install](#install)
44
+ - [Quick Start](#quick-start)
45
+ - [What You Can Do](#what-you-can-do)
46
+ - [List All Coins](#list-all-coins)
47
+ - [Download Logos](#download-logos)
48
+ - [Generate CDN URLs](#generate-cdn-urls)
49
+ - [Fetch Logo Variants and History](#fetch-logo-variants-and-history)
50
+ - [Cryptocurrency Logo Standards](#cryptocurrency-logo-standards)
51
+ - [SVG vs PNG — When to Use Which](#svg-vs-png--when-to-use-which)
52
+ - [Standard Sizes for Crypto Logos](#standard-sizes-for-crypto-logos)
53
+ - [Brand Color Consistency](#brand-color-consistency)
54
+ - [API Reference](#api-reference)
55
+ - [API Endpoints](#api-endpoints)
56
+ - [Learn More About Cryptocurrency Logos](#learn-more-about-cryptocurrency-logos)
57
+ - [Also Available](#also-available)
58
+ - [License](#license)
59
+
60
+ ## Install
61
+
62
+ ```bash
63
+ pip install cryptologo
64
+ ```
65
+
66
+ ## Quick Start
67
+
68
+ ```python
69
+ from cryptologo import CryptoLogo
70
+
71
+ client = CryptoLogo()
72
+
73
+ # List all 413 coins sorted by market cap
74
+ coins = client.list_coins()
75
+ for coin in coins[:5]:
76
+ print(f"{coin.name} ({coin.ticker}) — rank #{coin.market_cap_rank}")
77
+ # Bitcoin (BTC) — rank #1
78
+ # Ethereum (ETH) — rank #2
79
+ # Tether (USDT) — rank #3
80
+
81
+ # Download Bitcoin logo as SVG
82
+ client.download_logo("bitcoin-btc", "svg")
83
+ # Saved: bitcoin-btc.svg
84
+
85
+ # Download Ethereum logo as 512x512 PNG
86
+ client.download_logo("ethereum-eth", "png", width=512)
87
+ # Saved: ethereum-eth-512x512.png
88
+ ```
89
+
90
+ ## What You Can Do
91
+
92
+ ### List All Coins
93
+
94
+ The `list_coins()` method returns all 413 active coins with metadata including name, ticker, slug, format availability (PNG/SVG), localized search terms in 14 languages, and CoinGecko market cap ranking.
95
+
96
+ | Field | Type | Description |
97
+ |-------|------|-------------|
98
+ | `name` | str | Display name (e.g., "Bitcoin") |
99
+ | `ticker` | str | Trading symbol (e.g., "BTC") |
100
+ | `slug` | str | URL identifier (e.g., "bitcoin-btc") |
101
+ | `has_png` | bool | PNG logo available |
102
+ | `has_svg` | bool | SVG vector available |
103
+ | `search_terms` | list | Names in Korean, Japanese, Chinese, etc. |
104
+ | `market_cap_rank` | int/None | CoinGecko ranking |
105
+
106
+ ```python
107
+ from cryptologo import CryptoLogo
108
+
109
+ client = CryptoLogo()
110
+ coins = client.list_coins()
111
+
112
+ # Filter coins that have SVG logos
113
+ svg_coins = [c for c in coins if c.has_svg]
114
+ print(f"{len(svg_coins)} coins have SVG logos") # 413 coins have SVG logos
115
+
116
+ # Find a specific coin by ticker
117
+ btc = next((c for c in coins if c.ticker == "BTC"), None)
118
+ if btc:
119
+ print(f"{btc.name}: slug={btc.slug}, rank=#{btc.market_cap_rank}")
120
+ ```
121
+
122
+ ### Download Logos
123
+
124
+ Fetch logo image data as bytes or save directly to a file. SVG logos require no size parameter. Raster formats (PNG, WebP, JPEG, ICO) require a width.
125
+
126
+ ```python
127
+ from cryptologo import CryptoLogo
128
+
129
+ client = CryptoLogo()
130
+
131
+ # Get raw SVG bytes — scalable vector, ideal for web
132
+ svg_bytes = client.get_logo("bitcoin-btc", "svg")
133
+
134
+ # Get PNG at specific size — pre-generated, not resized on-the-fly
135
+ png_bytes = client.get_logo("solana-sol", "png", width=256)
136
+
137
+ # Download to file with auto-generated filename
138
+ path = client.download_logo("bitcoin-btc", "svg")
139
+ print(path) # bitcoin-btc.svg
140
+
141
+ # Download to specific path
142
+ path = client.download_logo("ethereum-eth", "png", "logos/eth.png", width=128)
143
+
144
+ # ICO format for favicons (sizes: 16, 32, 48, 64, 128, 256)
145
+ client.download_logo("bitcoin-btc", "ico", width=32)
146
+
147
+ # OG image with white background (1200x630 for social sharing)
148
+ client.download_logo("bitcoin-btc", "png", width=1200, height=630, bg="FFFFFF")
149
+ ```
150
+
151
+ ### Generate CDN URLs
152
+
153
+ Build URLs for direct embedding in HTML, Markdown, or documentation. The CDN serves pre-generated derivatives from Cloudflare R2 with `Cache-Control: immutable` — no Django server overhead.
154
+
155
+ ```python
156
+ from cryptologo import CryptoLogo
157
+
158
+ client = CryptoLogo()
159
+
160
+ # CDN URL for fast image display (recommended for <img> tags)
161
+ url = client.get_cdn_url("bitcoin-btc", "webp", 128)
162
+ # https://cdn.crypto-logo.com/logos/bitcoin-btc/128x128/transparent.webp
163
+
164
+ # CDN URL for SVG vector
165
+ url = client.get_cdn_url("ethereum-eth", "svg")
166
+ # https://cdn.crypto-logo.com/logos/ethereum-eth/vector.svg
167
+
168
+ # API URL (for downloads with Content-Disposition header)
169
+ url = client.get_logo_url("bitcoin-btc", "png", width=512, height=512)
170
+ # https://crypto-logo.com/api/logo/bitcoin-btc.png?w=512&h=512
171
+ ```
172
+
173
+ ### Fetch Logo Variants and History
174
+
175
+ Some coins have alternate logo designs (full wordmark, diamond shape, animated) and historical versions showing brand evolution.
176
+
177
+ ```python
178
+ from cryptologo import CryptoLogo
179
+
180
+ client = CryptoLogo()
181
+
182
+ # Get a logo variant (alternate design)
183
+ full_logo = client.get_asset("versions/bitcoin-btc-full.svg")
184
+
185
+ # Get a historical logo version
186
+ old_logo = client.get_asset("history/bitcoin-btc-2009.png")
187
+ ```
188
+
189
+ ## Cryptocurrency Logo Standards
190
+
191
+ ### SVG vs PNG — When to Use Which
192
+
193
+ Cryptocurrency projects publish official logos in SVG (vector) and PNG (raster). Choosing the right format depends on the use case.
194
+
195
+ | Use Case | Recommended Format | Reason |
196
+ |----------|--------------------|--------|
197
+ | Website/app UI | SVG | Scales to any resolution, small file size (~2-15KB) |
198
+ | Exchange listing | PNG 512x512 | Standard requirement for CoinGecko, CoinMarketCap |
199
+ | Mobile app icon | PNG 128x128 or 256x256 | iOS/Android require raster at specific sizes |
200
+ | Favicon | ICO 32x32 or SVG | ICO for legacy browsers, SVG for modern |
201
+ | Social media / OG image | PNG 1200x630 | Open Graph standard with solid background |
202
+ | Print / merch | SVG | Infinite scalability without quality loss |
203
+ | Documentation | SVG or PNG 64-128px | SVG preferred, PNG for Markdown compatibility |
204
+ | Email signature | PNG 48-64px | Most email clients don't render SVG |
205
+
206
+ ### Standard Sizes for Crypto Logos
207
+
208
+ The industry has converged on standard sizes. CryptoLogo pre-generates all 13 standard sizes for each coin.
209
+
210
+ | Size | Common Use |
211
+ |------|-----------|
212
+ | 16x16 | Favicon, inline text icons |
213
+ | 32x32 | Favicon, small UI elements |
214
+ | 48x48 | Tab icons, small badges |
215
+ | 64x64 | List items, table cells |
216
+ | 96x96 | Grid thumbnails |
217
+ | 128x128 | Card previews, mobile |
218
+ | 200x200 | Profile images |
219
+ | 256x256 | Medium detail views |
220
+ | 400x400 | Large cards |
221
+ | 512x512 | Exchange listing standard |
222
+ | 1024x1024 | High-DPI displays |
223
+ | 2000x2000 | Maximum quality raster |
224
+ | 1200x630 | OG image (social sharing) |
225
+
226
+ ### Brand Color Consistency
227
+
228
+ Each cryptocurrency has an official brand color (e.g., Bitcoin's #F7931A orange, Ethereum's #627EEA purple). CryptoLogo stores the `brand_color` for each coin, enabling consistent color theming in portfolio apps, dashboards, and data visualizations.
229
+
230
+ Notable brand colors:
231
+ - **Bitcoin**: #F7931A (orange) — designed by Satoshi-era contributor
232
+ - **Ethereum**: #627EEA (purple) — from the Ethereum Foundation brand kit
233
+ - **Solana**: #9945FF (violet) — gradient-based identity system
234
+ - **Cardano**: #0033AD (blue) — academic/formal positioning
235
+ - **Dogecoin**: #C2A633 (gold) — matches the Shiba Inu meme aesthetic
236
+
237
+ ## API Reference
238
+
239
+ | Method | Parameters | Returns | Description |
240
+ |--------|-----------|---------|-------------|
241
+ | `list_coins()` | — | `list[Coin]` | All 413 coins with metadata |
242
+ | `get_logo(slug, fmt, ...)` | slug, fmt, width, height, bg | `bytes` | Logo image bytes |
243
+ | `get_logo_url(slug, fmt, ...)` | slug, fmt, width, height, bg | `str` | API URL for logo |
244
+ | `get_cdn_url(slug, fmt, width)` | slug, fmt, width, cdn_domain | `str` | CDN URL for embedding |
245
+ | `download_logo(slug, fmt, dest, ...)` | slug, fmt, dest, width, height, bg | `Path` | Save logo to file |
246
+ | `get_asset(file_path)` | file_path | `bytes` | Variant/history asset |
247
+
248
+ ## API Endpoints
249
+
250
+ The crypto-logo.com REST API is free, requires no authentication, and supports CORS.
251
+
252
+ | Method | Endpoint | Description |
253
+ |--------|----------|-------------|
254
+ | GET | `/api/logo/{slug}.{fmt}` | Logo image (png, svg, webp, jpeg, ico) |
255
+ | GET | `/api/coins.json` | All coins metadata (JSON array) |
256
+ | GET | `/api/asset/{path}` | Variant and history files |
257
+ | GET | `/api/docs/` | Interactive API documentation |
258
+ | GET | `/api/schema/` | OpenAPI 3.0 schema |
259
+
260
+ ### Example
261
+
262
+ ```bash
263
+ # List all coins
264
+ curl -s "https://crypto-logo.com/api/coins.json" | python3 -m json.tool | head -20
265
+
266
+ # Download Bitcoin SVG
267
+ curl -O "https://crypto-logo.com/api/logo/bitcoin-btc.svg"
268
+
269
+ # Download Ethereum PNG 256x256
270
+ curl -O "https://crypto-logo.com/api/logo/ethereum-eth.png?w=256&h=256"
271
+
272
+ # Get OG image with white background
273
+ curl -O "https://crypto-logo.com/api/logo/bitcoin-btc.png?w=1200&h=630&bg=FFFFFF"
274
+ ```
275
+
276
+ ```json
277
+ [
278
+ {
279
+ "name": "Bitcoin",
280
+ "ticker": "BTC",
281
+ "slug": "bitcoin-btc",
282
+ "has_png": true,
283
+ "has_svg": true,
284
+ "search_terms": ["\ube44\ud2b8\ucf54\uc778", "\u30d3\u30c3\u30c8\u30b3\u30a4\u30f3"],
285
+ "market_cap_rank": 1
286
+ }
287
+ ]
288
+ ```
289
+
290
+ Full API documentation at [crypto-logo.com/api/docs/](https://crypto-logo.com/api/docs/).
291
+
292
+ ## Learn More About Cryptocurrency Logos
293
+
294
+ - **Browse**: [All Coins](https://crypto-logo.com/) · [Categories](https://crypto-logo.com/categories/) · [Formats](https://crypto-logo.com/formats/)
295
+ - **API**: [API Docs](https://crypto-logo.com/api/docs/) · [OpenAPI Schema](https://crypto-logo.com/api/schema/)
296
+
297
+ ## Also Available
298
+
299
+ | Platform | Package | Install |
300
+ |----------|---------|---------|
301
+ | **npm** | [cryptologo](https://www.npmjs.com/package/cryptologo) | `npm install cryptologo` |
302
+ | **Go** | [cryptologo-go](https://github.com/dobestan/cryptologo-go) | `go get github.com/dobestan/cryptologo-go` |
303
+ | **Rust** | [cryptologo](https://crates.io/crates/cryptologo) | `cargo add cryptologo` |
304
+ | **Ruby** | [cryptologo](https://rubygems.org/gems/cryptologo) | `gem install cryptologo` |
305
+
306
+ ## License
307
+
308
+ MIT
@@ -0,0 +1,281 @@
1
+ # cryptologo
2
+
3
+ [![PyPI](https://img.shields.io/pypi/v/cryptologo)](https://pypi.org/project/cryptologo/)
4
+ [![Python](https://img.shields.io/pypi/pyversions/cryptologo)](https://pypi.org/project/cryptologo/)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
6
+ [![Zero Dependencies](https://img.shields.io/badge/dependencies-0-brightgreen)](https://pypi.org/project/cryptologo/)
7
+
8
+ Python client for [crypto-logo.com](https://crypto-logo.com) — the cryptocurrency logo database with 413 coins in SVG, PNG, WebP, JPEG, and ICO formats. Zero dependencies (stdlib `urllib` only).
9
+
10
+ Every logo is available as a scalable SVG vector and pre-generated raster derivatives in 13 standard sizes (16px to 2000px). Logos are served from Cloudflare R2 CDN with immutable cache headers for production-grade performance. The dataset is extracted from [crypto-logo.com](https://crypto-logo.com), which tracks logo assets for Bitcoin, Ethereum, Solana, and 410+ other cryptocurrencies ranked by market cap.
11
+
12
+ > **Try the interactive logo browser at [crypto-logo.com](https://crypto-logo.com)** — [Bitcoin logo](https://crypto-logo.com/bitcoin-btc/), [Ethereum logo](https://crypto-logo.com/ethereum-eth/), [API docs](https://crypto-logo.com/api/docs/)
13
+
14
+ ## Table of Contents
15
+
16
+ - [Install](#install)
17
+ - [Quick Start](#quick-start)
18
+ - [What You Can Do](#what-you-can-do)
19
+ - [List All Coins](#list-all-coins)
20
+ - [Download Logos](#download-logos)
21
+ - [Generate CDN URLs](#generate-cdn-urls)
22
+ - [Fetch Logo Variants and History](#fetch-logo-variants-and-history)
23
+ - [Cryptocurrency Logo Standards](#cryptocurrency-logo-standards)
24
+ - [SVG vs PNG — When to Use Which](#svg-vs-png--when-to-use-which)
25
+ - [Standard Sizes for Crypto Logos](#standard-sizes-for-crypto-logos)
26
+ - [Brand Color Consistency](#brand-color-consistency)
27
+ - [API Reference](#api-reference)
28
+ - [API Endpoints](#api-endpoints)
29
+ - [Learn More About Cryptocurrency Logos](#learn-more-about-cryptocurrency-logos)
30
+ - [Also Available](#also-available)
31
+ - [License](#license)
32
+
33
+ ## Install
34
+
35
+ ```bash
36
+ pip install cryptologo
37
+ ```
38
+
39
+ ## Quick Start
40
+
41
+ ```python
42
+ from cryptologo import CryptoLogo
43
+
44
+ client = CryptoLogo()
45
+
46
+ # List all 413 coins sorted by market cap
47
+ coins = client.list_coins()
48
+ for coin in coins[:5]:
49
+ print(f"{coin.name} ({coin.ticker}) — rank #{coin.market_cap_rank}")
50
+ # Bitcoin (BTC) — rank #1
51
+ # Ethereum (ETH) — rank #2
52
+ # Tether (USDT) — rank #3
53
+
54
+ # Download Bitcoin logo as SVG
55
+ client.download_logo("bitcoin-btc", "svg")
56
+ # Saved: bitcoin-btc.svg
57
+
58
+ # Download Ethereum logo as 512x512 PNG
59
+ client.download_logo("ethereum-eth", "png", width=512)
60
+ # Saved: ethereum-eth-512x512.png
61
+ ```
62
+
63
+ ## What You Can Do
64
+
65
+ ### List All Coins
66
+
67
+ The `list_coins()` method returns all 413 active coins with metadata including name, ticker, slug, format availability (PNG/SVG), localized search terms in 14 languages, and CoinGecko market cap ranking.
68
+
69
+ | Field | Type | Description |
70
+ |-------|------|-------------|
71
+ | `name` | str | Display name (e.g., "Bitcoin") |
72
+ | `ticker` | str | Trading symbol (e.g., "BTC") |
73
+ | `slug` | str | URL identifier (e.g., "bitcoin-btc") |
74
+ | `has_png` | bool | PNG logo available |
75
+ | `has_svg` | bool | SVG vector available |
76
+ | `search_terms` | list | Names in Korean, Japanese, Chinese, etc. |
77
+ | `market_cap_rank` | int/None | CoinGecko ranking |
78
+
79
+ ```python
80
+ from cryptologo import CryptoLogo
81
+
82
+ client = CryptoLogo()
83
+ coins = client.list_coins()
84
+
85
+ # Filter coins that have SVG logos
86
+ svg_coins = [c for c in coins if c.has_svg]
87
+ print(f"{len(svg_coins)} coins have SVG logos") # 413 coins have SVG logos
88
+
89
+ # Find a specific coin by ticker
90
+ btc = next((c for c in coins if c.ticker == "BTC"), None)
91
+ if btc:
92
+ print(f"{btc.name}: slug={btc.slug}, rank=#{btc.market_cap_rank}")
93
+ ```
94
+
95
+ ### Download Logos
96
+
97
+ Fetch logo image data as bytes or save directly to a file. SVG logos require no size parameter. Raster formats (PNG, WebP, JPEG, ICO) require a width.
98
+
99
+ ```python
100
+ from cryptologo import CryptoLogo
101
+
102
+ client = CryptoLogo()
103
+
104
+ # Get raw SVG bytes — scalable vector, ideal for web
105
+ svg_bytes = client.get_logo("bitcoin-btc", "svg")
106
+
107
+ # Get PNG at specific size — pre-generated, not resized on-the-fly
108
+ png_bytes = client.get_logo("solana-sol", "png", width=256)
109
+
110
+ # Download to file with auto-generated filename
111
+ path = client.download_logo("bitcoin-btc", "svg")
112
+ print(path) # bitcoin-btc.svg
113
+
114
+ # Download to specific path
115
+ path = client.download_logo("ethereum-eth", "png", "logos/eth.png", width=128)
116
+
117
+ # ICO format for favicons (sizes: 16, 32, 48, 64, 128, 256)
118
+ client.download_logo("bitcoin-btc", "ico", width=32)
119
+
120
+ # OG image with white background (1200x630 for social sharing)
121
+ client.download_logo("bitcoin-btc", "png", width=1200, height=630, bg="FFFFFF")
122
+ ```
123
+
124
+ ### Generate CDN URLs
125
+
126
+ Build URLs for direct embedding in HTML, Markdown, or documentation. The CDN serves pre-generated derivatives from Cloudflare R2 with `Cache-Control: immutable` — no Django server overhead.
127
+
128
+ ```python
129
+ from cryptologo import CryptoLogo
130
+
131
+ client = CryptoLogo()
132
+
133
+ # CDN URL for fast image display (recommended for <img> tags)
134
+ url = client.get_cdn_url("bitcoin-btc", "webp", 128)
135
+ # https://cdn.crypto-logo.com/logos/bitcoin-btc/128x128/transparent.webp
136
+
137
+ # CDN URL for SVG vector
138
+ url = client.get_cdn_url("ethereum-eth", "svg")
139
+ # https://cdn.crypto-logo.com/logos/ethereum-eth/vector.svg
140
+
141
+ # API URL (for downloads with Content-Disposition header)
142
+ url = client.get_logo_url("bitcoin-btc", "png", width=512, height=512)
143
+ # https://crypto-logo.com/api/logo/bitcoin-btc.png?w=512&h=512
144
+ ```
145
+
146
+ ### Fetch Logo Variants and History
147
+
148
+ Some coins have alternate logo designs (full wordmark, diamond shape, animated) and historical versions showing brand evolution.
149
+
150
+ ```python
151
+ from cryptologo import CryptoLogo
152
+
153
+ client = CryptoLogo()
154
+
155
+ # Get a logo variant (alternate design)
156
+ full_logo = client.get_asset("versions/bitcoin-btc-full.svg")
157
+
158
+ # Get a historical logo version
159
+ old_logo = client.get_asset("history/bitcoin-btc-2009.png")
160
+ ```
161
+
162
+ ## Cryptocurrency Logo Standards
163
+
164
+ ### SVG vs PNG — When to Use Which
165
+
166
+ Cryptocurrency projects publish official logos in SVG (vector) and PNG (raster). Choosing the right format depends on the use case.
167
+
168
+ | Use Case | Recommended Format | Reason |
169
+ |----------|--------------------|--------|
170
+ | Website/app UI | SVG | Scales to any resolution, small file size (~2-15KB) |
171
+ | Exchange listing | PNG 512x512 | Standard requirement for CoinGecko, CoinMarketCap |
172
+ | Mobile app icon | PNG 128x128 or 256x256 | iOS/Android require raster at specific sizes |
173
+ | Favicon | ICO 32x32 or SVG | ICO for legacy browsers, SVG for modern |
174
+ | Social media / OG image | PNG 1200x630 | Open Graph standard with solid background |
175
+ | Print / merch | SVG | Infinite scalability without quality loss |
176
+ | Documentation | SVG or PNG 64-128px | SVG preferred, PNG for Markdown compatibility |
177
+ | Email signature | PNG 48-64px | Most email clients don't render SVG |
178
+
179
+ ### Standard Sizes for Crypto Logos
180
+
181
+ The industry has converged on standard sizes. CryptoLogo pre-generates all 13 standard sizes for each coin.
182
+
183
+ | Size | Common Use |
184
+ |------|-----------|
185
+ | 16x16 | Favicon, inline text icons |
186
+ | 32x32 | Favicon, small UI elements |
187
+ | 48x48 | Tab icons, small badges |
188
+ | 64x64 | List items, table cells |
189
+ | 96x96 | Grid thumbnails |
190
+ | 128x128 | Card previews, mobile |
191
+ | 200x200 | Profile images |
192
+ | 256x256 | Medium detail views |
193
+ | 400x400 | Large cards |
194
+ | 512x512 | Exchange listing standard |
195
+ | 1024x1024 | High-DPI displays |
196
+ | 2000x2000 | Maximum quality raster |
197
+ | 1200x630 | OG image (social sharing) |
198
+
199
+ ### Brand Color Consistency
200
+
201
+ Each cryptocurrency has an official brand color (e.g., Bitcoin's #F7931A orange, Ethereum's #627EEA purple). CryptoLogo stores the `brand_color` for each coin, enabling consistent color theming in portfolio apps, dashboards, and data visualizations.
202
+
203
+ Notable brand colors:
204
+ - **Bitcoin**: #F7931A (orange) — designed by Satoshi-era contributor
205
+ - **Ethereum**: #627EEA (purple) — from the Ethereum Foundation brand kit
206
+ - **Solana**: #9945FF (violet) — gradient-based identity system
207
+ - **Cardano**: #0033AD (blue) — academic/formal positioning
208
+ - **Dogecoin**: #C2A633 (gold) — matches the Shiba Inu meme aesthetic
209
+
210
+ ## API Reference
211
+
212
+ | Method | Parameters | Returns | Description |
213
+ |--------|-----------|---------|-------------|
214
+ | `list_coins()` | — | `list[Coin]` | All 413 coins with metadata |
215
+ | `get_logo(slug, fmt, ...)` | slug, fmt, width, height, bg | `bytes` | Logo image bytes |
216
+ | `get_logo_url(slug, fmt, ...)` | slug, fmt, width, height, bg | `str` | API URL for logo |
217
+ | `get_cdn_url(slug, fmt, width)` | slug, fmt, width, cdn_domain | `str` | CDN URL for embedding |
218
+ | `download_logo(slug, fmt, dest, ...)` | slug, fmt, dest, width, height, bg | `Path` | Save logo to file |
219
+ | `get_asset(file_path)` | file_path | `bytes` | Variant/history asset |
220
+
221
+ ## API Endpoints
222
+
223
+ The crypto-logo.com REST API is free, requires no authentication, and supports CORS.
224
+
225
+ | Method | Endpoint | Description |
226
+ |--------|----------|-------------|
227
+ | GET | `/api/logo/{slug}.{fmt}` | Logo image (png, svg, webp, jpeg, ico) |
228
+ | GET | `/api/coins.json` | All coins metadata (JSON array) |
229
+ | GET | `/api/asset/{path}` | Variant and history files |
230
+ | GET | `/api/docs/` | Interactive API documentation |
231
+ | GET | `/api/schema/` | OpenAPI 3.0 schema |
232
+
233
+ ### Example
234
+
235
+ ```bash
236
+ # List all coins
237
+ curl -s "https://crypto-logo.com/api/coins.json" | python3 -m json.tool | head -20
238
+
239
+ # Download Bitcoin SVG
240
+ curl -O "https://crypto-logo.com/api/logo/bitcoin-btc.svg"
241
+
242
+ # Download Ethereum PNG 256x256
243
+ curl -O "https://crypto-logo.com/api/logo/ethereum-eth.png?w=256&h=256"
244
+
245
+ # Get OG image with white background
246
+ curl -O "https://crypto-logo.com/api/logo/bitcoin-btc.png?w=1200&h=630&bg=FFFFFF"
247
+ ```
248
+
249
+ ```json
250
+ [
251
+ {
252
+ "name": "Bitcoin",
253
+ "ticker": "BTC",
254
+ "slug": "bitcoin-btc",
255
+ "has_png": true,
256
+ "has_svg": true,
257
+ "search_terms": ["\ube44\ud2b8\ucf54\uc778", "\u30d3\u30c3\u30c8\u30b3\u30a4\u30f3"],
258
+ "market_cap_rank": 1
259
+ }
260
+ ]
261
+ ```
262
+
263
+ Full API documentation at [crypto-logo.com/api/docs/](https://crypto-logo.com/api/docs/).
264
+
265
+ ## Learn More About Cryptocurrency Logos
266
+
267
+ - **Browse**: [All Coins](https://crypto-logo.com/) · [Categories](https://crypto-logo.com/categories/) · [Formats](https://crypto-logo.com/formats/)
268
+ - **API**: [API Docs](https://crypto-logo.com/api/docs/) · [OpenAPI Schema](https://crypto-logo.com/api/schema/)
269
+
270
+ ## Also Available
271
+
272
+ | Platform | Package | Install |
273
+ |----------|---------|---------|
274
+ | **npm** | [cryptologo](https://www.npmjs.com/package/cryptologo) | `npm install cryptologo` |
275
+ | **Go** | [cryptologo-go](https://github.com/dobestan/cryptologo-go) | `go get github.com/dobestan/cryptologo-go` |
276
+ | **Rust** | [cryptologo](https://crates.io/crates/cryptologo) | `cargo add cryptologo` |
277
+ | **Ruby** | [cryptologo](https://rubygems.org/gems/cryptologo) | `gem install cryptologo` |
278
+
279
+ ## License
280
+
281
+ MIT
@@ -0,0 +1,58 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "cryptologo"
7
+ version = "0.1.0"
8
+ description = "Python client for crypto-logo.com — 413 cryptocurrency logos in SVG, PNG, WebP, ICO"
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ requires-python = ">=3.10"
12
+ authors = [{ name = "dobestan", email = "dobestan@gmail.com" }]
13
+ keywords = [
14
+ "cryptocurrency",
15
+ "logo",
16
+ "bitcoin",
17
+ "ethereum",
18
+ "svg",
19
+ "png",
20
+ "crypto",
21
+ "branding",
22
+ "icon",
23
+ "api-client",
24
+ ]
25
+ classifiers = [
26
+ "Development Status :: 4 - Beta",
27
+ "Intended Audience :: Developers",
28
+ "License :: OSI Approved :: MIT License",
29
+ "Programming Language :: Python :: 3",
30
+ "Programming Language :: Python :: 3.10",
31
+ "Programming Language :: Python :: 3.11",
32
+ "Programming Language :: Python :: 3.12",
33
+ "Programming Language :: Python :: 3.13",
34
+ "Programming Language :: Python :: 3.14",
35
+ "Topic :: Multimedia :: Graphics",
36
+ "Topic :: Software Development :: Libraries :: Python Modules",
37
+ "Typing :: Typed",
38
+ ]
39
+
40
+ [project.urls]
41
+ Homepage = "https://crypto-logo.com"
42
+ Documentation = "https://crypto-logo.com/api/docs/"
43
+ Repository = "https://github.com/dobestan/cryptologo-python"
44
+ "API Reference" = "https://crypto-logo.com/api/docs/"
45
+
46
+ [tool.hatch.build.targets.wheel]
47
+ packages = ["src/cryptologo"]
48
+
49
+ [tool.ruff]
50
+ target-version = "py310"
51
+ line-length = 120
52
+
53
+ [tool.ruff.lint]
54
+ select = ["E", "F", "I", "UP"]
55
+
56
+ [tool.mypy]
57
+ python_version = "3.10"
58
+ strict = true
@@ -0,0 +1,20 @@
1
+ """cryptologo — Python client for crypto-logo.com cryptocurrency logo API.
2
+
3
+ Fetch, download, and generate URLs for 413+ cryptocurrency logos in SVG, PNG,
4
+ WebP, JPEG, and ICO formats. Zero dependencies (stdlib urllib only).
5
+
6
+ Usage::
7
+
8
+ from cryptologo import CryptoLogo
9
+
10
+ client = CryptoLogo()
11
+ coins = client.list_coins()
12
+ logo_bytes = client.get_logo("bitcoin-btc", "svg")
13
+ client.download_logo("ethereum-eth", "png", "eth-logo.png", width=512)
14
+ """
15
+
16
+ from cryptologo.client import CryptoLogo
17
+ from cryptologo.types import Coin
18
+
19
+ __all__ = ["CryptoLogo", "Coin"]
20
+ __version__ = "0.1.0"
@@ -0,0 +1,289 @@
1
+ """CryptoLogo API client — zero dependencies (stdlib urllib only)."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import json
6
+ import urllib.request
7
+ from pathlib import Path
8
+ from typing import Any
9
+
10
+ from cryptologo.types import ALL_FORMATS, ALLOWED_SIZES, ICO_SIZES, Coin
11
+
12
+
13
+ class CryptoLogoError(Exception):
14
+ """Base exception for CryptoLogo client errors."""
15
+
16
+
17
+ class NotFoundError(CryptoLogoError):
18
+ """Raised when a coin or logo is not found (HTTP 404)."""
19
+
20
+
21
+ class CryptoLogo:
22
+ """Client for the crypto-logo.com API.
23
+
24
+ Provides methods to list coins, fetch logos, generate logo URLs,
25
+ and download logo files. No API key required.
26
+
27
+ Args:
28
+ base_url: API base URL. Defaults to ``https://crypto-logo.com``.
29
+ timeout: Request timeout in seconds. Defaults to 30.
30
+
31
+ Example::
32
+
33
+ client = CryptoLogo()
34
+
35
+ # List all coins
36
+ coins = client.list_coins()
37
+ for coin in coins[:5]:
38
+ print(f"{coin.name} ({coin.ticker}) — rank #{coin.market_cap_rank}")
39
+
40
+ # Get logo bytes
41
+ svg_data = client.get_logo("bitcoin-btc", "svg")
42
+
43
+ # Download to file
44
+ client.download_logo("ethereum-eth", "png", "eth.png", width=256)
45
+ """
46
+
47
+ def __init__(
48
+ self,
49
+ base_url: str = "https://crypto-logo.com",
50
+ timeout: int = 30,
51
+ ) -> None:
52
+ self.base_url = base_url.rstrip("/")
53
+ self.timeout = timeout
54
+
55
+ def list_coins(self) -> list[Coin]:
56
+ """Fetch all active coins from the API.
57
+
58
+ Returns:
59
+ List of Coin objects sorted by market cap rank.
60
+
61
+ Example::
62
+
63
+ coins = client.list_coins()
64
+ bitcoin = next(c for c in coins if c.ticker == "BTC")
65
+ print(f"{bitcoin.name}: rank #{bitcoin.market_cap_rank}")
66
+ """
67
+ data = self._get_json("/api/coins.json")
68
+ if not isinstance(data, list):
69
+ raise CryptoLogoError("Unexpected response format")
70
+ return [Coin.from_dict(item) for item in data]
71
+
72
+ def get_logo(
73
+ self,
74
+ slug: str,
75
+ fmt: str = "svg",
76
+ *,
77
+ width: int | None = None,
78
+ height: int | None = None,
79
+ bg: str | None = None,
80
+ ) -> bytes:
81
+ """Fetch logo image bytes from the API.
82
+
83
+ Args:
84
+ slug: Coin slug (e.g., "bitcoin-btc").
85
+ fmt: Image format — "svg", "png", "webp", "jpeg", or "ico".
86
+ width: Output width in pixels (required for raster formats).
87
+ height: Output height in pixels (defaults to width for square).
88
+ bg: Background hex color without # (e.g., "FFFFFF").
89
+
90
+ Returns:
91
+ Raw image bytes.
92
+
93
+ Raises:
94
+ NotFoundError: If the coin or requested derivative is not found.
95
+ ValueError: If the format or size is invalid.
96
+
97
+ Example::
98
+
99
+ # SVG (no size needed)
100
+ svg = client.get_logo("bitcoin-btc", "svg")
101
+
102
+ # PNG at 256x256
103
+ png = client.get_logo("bitcoin-btc", "png", width=256)
104
+
105
+ # OG image with white background
106
+ og = client.get_logo("bitcoin-btc", "png", width=1200, height=630, bg="FFFFFF")
107
+ """
108
+ fmt = fmt.lower()
109
+ if fmt not in ALL_FORMATS:
110
+ raise ValueError(f"Unsupported format: {fmt}. Use one of: {', '.join(ALL_FORMATS)}")
111
+
112
+ if fmt != "svg" and width is None:
113
+ raise ValueError("Width is required for raster formats. Use one of: " + ", ".join(str(s) for s in ALLOWED_SIZES))
114
+
115
+ if fmt == "ico" and width is not None and width not in ICO_SIZES:
116
+ raise ValueError(f"ICO size must be one of: {', '.join(str(s) for s in ICO_SIZES)}")
117
+
118
+ if fmt != "svg" and width is not None and height is None:
119
+ height = width
120
+
121
+ url = self.get_logo_url(slug, fmt, width=width, height=height, bg=bg)
122
+ return self._get_bytes(url)
123
+
124
+ def get_logo_url(
125
+ self,
126
+ slug: str,
127
+ fmt: str = "svg",
128
+ *,
129
+ width: int | None = None,
130
+ height: int | None = None,
131
+ bg: str | None = None,
132
+ ) -> str:
133
+ """Build the API URL for a logo.
134
+
135
+ Args:
136
+ slug: Coin slug (e.g., "bitcoin-btc").
137
+ fmt: Image format.
138
+ width: Output width in pixels.
139
+ height: Output height in pixels.
140
+ bg: Background hex color without #.
141
+
142
+ Returns:
143
+ Full API URL string.
144
+
145
+ Example::
146
+
147
+ url = client.get_logo_url("bitcoin-btc", "png", width=512)
148
+ # https://crypto-logo.com/api/logo/bitcoin-btc.png?w=512&h=512
149
+ """
150
+ url = f"{self.base_url}/api/logo/{slug}.{fmt}"
151
+ params: list[str] = []
152
+ if width is not None:
153
+ params.append(f"w={width}")
154
+ if height is not None:
155
+ params.append(f"h={height}")
156
+ if bg:
157
+ params.append(f"bg={bg}")
158
+ if params:
159
+ url += "?" + "&".join(params)
160
+ return url
161
+
162
+ def get_cdn_url(
163
+ self,
164
+ slug: str,
165
+ fmt: str = "png",
166
+ width: int = 128,
167
+ *,
168
+ cdn_domain: str = "cdn.crypto-logo.com",
169
+ ) -> str:
170
+ """Build a CDN URL for direct image embedding (faster than API).
171
+
172
+ The CDN serves pre-generated derivatives without going through Django.
173
+ Use this for ``<img>`` tags and other display contexts.
174
+
175
+ Args:
176
+ slug: Coin slug.
177
+ fmt: Image format ("png", "webp", "jpeg", "svg").
178
+ width: Square size in pixels.
179
+ cdn_domain: CDN hostname.
180
+
181
+ Returns:
182
+ CDN URL string.
183
+
184
+ Example::
185
+
186
+ url = client.get_cdn_url("bitcoin-btc", "webp", 128)
187
+ # https://cdn.crypto-logo.com/logos/bitcoin-btc/128x128/transparent.webp
188
+ """
189
+ if fmt == "svg":
190
+ return f"https://{cdn_domain}/logos/{slug}/vector.svg"
191
+ return f"https://{cdn_domain}/logos/{slug}/{width}x{width}/transparent.{fmt}"
192
+
193
+ def download_logo(
194
+ self,
195
+ slug: str,
196
+ fmt: str = "svg",
197
+ dest: str | Path | None = None,
198
+ *,
199
+ width: int | None = None,
200
+ height: int | None = None,
201
+ bg: str | None = None,
202
+ ) -> Path:
203
+ """Download a logo to a local file.
204
+
205
+ Args:
206
+ slug: Coin slug (e.g., "bitcoin-btc").
207
+ fmt: Image format.
208
+ dest: Destination file path. Auto-generated if None.
209
+ width: Output width in pixels.
210
+ height: Output height in pixels.
211
+ bg: Background hex color without #.
212
+
213
+ Returns:
214
+ Path to the downloaded file.
215
+
216
+ Example::
217
+
218
+ path = client.download_logo("bitcoin-btc", "svg")
219
+ print(f"Saved to {path}") # bitcoin-btc.svg
220
+
221
+ path = client.download_logo("ethereum-eth", "png", width=512)
222
+ print(f"Saved to {path}") # ethereum-eth-512x512.png
223
+ """
224
+ data = self.get_logo(slug, fmt, width=width, height=height, bg=bg)
225
+
226
+ if dest is None:
227
+ if fmt == "svg":
228
+ dest = Path(f"{slug}.svg")
229
+ elif width and height and width != height:
230
+ dest = Path(f"{slug}-{width}x{height}.{fmt}")
231
+ elif width:
232
+ dest = Path(f"{slug}-{width}x{width}.{fmt}")
233
+ else:
234
+ dest = Path(f"{slug}.{fmt}")
235
+ else:
236
+ dest = Path(dest)
237
+
238
+ dest.write_bytes(data)
239
+ return dest
240
+
241
+ def get_asset(self, file_path: str) -> bytes:
242
+ """Fetch an asset file (variant or historical logo).
243
+
244
+ Args:
245
+ file_path: Relative path within assets/ (e.g., "versions/bitcoin-btc-full.svg").
246
+
247
+ Returns:
248
+ Raw file bytes.
249
+
250
+ Example::
251
+
252
+ # Get a logo variant
253
+ data = client.get_asset("versions/bitcoin-btc-full.svg")
254
+
255
+ # Get a historical logo
256
+ data = client.get_asset("history/bitcoin-btc-2009.png")
257
+ """
258
+ url = f"{self.base_url}/api/asset/{file_path}"
259
+ return self._get_bytes(url)
260
+
261
+ # -- internal helpers --
262
+
263
+ def _get_json(self, path: str) -> Any:
264
+ """GET JSON from relative path."""
265
+ url = f"{self.base_url}{path}" if path.startswith("/") else path
266
+ req = urllib.request.Request(url, headers={"Accept": "application/json", "User-Agent": "cryptologo-python/0.1.0"})
267
+ try:
268
+ with urllib.request.urlopen(req, timeout=self.timeout) as resp:
269
+ return json.loads(resp.read().decode())
270
+ except urllib.error.HTTPError as e:
271
+ if e.code == 404:
272
+ raise NotFoundError(f"Not found: {url}") from None
273
+ raise CryptoLogoError(f"HTTP {e.code}: {url}") from e
274
+
275
+ def _get_bytes(self, url: str) -> bytes:
276
+ """GET binary data from full or relative URL."""
277
+ if url.startswith("/"):
278
+ url = f"{self.base_url}{url}"
279
+ req = urllib.request.Request(url, headers={"User-Agent": "cryptologo-python/0.1.0"})
280
+ try:
281
+ with urllib.request.urlopen(req, timeout=self.timeout) as resp:
282
+ return resp.read() # type: ignore[no-any-return]
283
+ except urllib.error.HTTPError as e:
284
+ if e.code == 404:
285
+ raise NotFoundError(f"Not found: {url}") from None
286
+ raise CryptoLogoError(f"HTTP {e.code}: {url}") from e
287
+
288
+
289
+ __all__ = ["CryptoLogo", "CryptoLogoError", "NotFoundError"]
File without changes
@@ -0,0 +1,57 @@
1
+ """Type definitions for the CryptoLogo API client."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass, field
6
+
7
+
8
+ @dataclass(frozen=True)
9
+ class Coin:
10
+ """A cryptocurrency coin with logo availability metadata.
11
+
12
+ Attributes:
13
+ name: Display name (e.g., "Bitcoin").
14
+ ticker: Trading symbol (e.g., "BTC").
15
+ slug: URL-safe identifier (e.g., "bitcoin-btc").
16
+ has_png: Whether a PNG logo is available.
17
+ has_svg: Whether an SVG logo is available.
18
+ search_terms: Localized names for search (Korean, Japanese, etc.).
19
+ market_cap_rank: CoinGecko market cap ranking (None if unranked).
20
+ """
21
+
22
+ name: str
23
+ ticker: str
24
+ slug: str
25
+ has_png: bool = False
26
+ has_svg: bool = False
27
+ search_terms: list[str] = field(default_factory=list)
28
+ market_cap_rank: int | None = None
29
+
30
+ @classmethod
31
+ def from_dict(cls, data: dict[str, object]) -> Coin:
32
+ """Create a Coin from the API JSON response dict."""
33
+ return cls(
34
+ name=str(data.get("name", "")),
35
+ ticker=str(data.get("ticker", "")),
36
+ slug=str(data.get("slug", "")),
37
+ has_png=bool(data.get("has_png", False)),
38
+ has_svg=bool(data.get("has_svg", False)),
39
+ search_terms=list(data.get("search_terms", [])), # type: ignore[arg-type]
40
+ market_cap_rank=data.get("market_cap_rank") if data.get("market_cap_rank") is not None else None, # type: ignore[arg-type]
41
+ )
42
+
43
+
44
+ # Supported raster formats for logo downloads
45
+ RASTER_FORMATS = ("png", "webp", "jpeg", "ico")
46
+
47
+ # Supported vector formats
48
+ VECTOR_FORMATS = ("svg",)
49
+
50
+ # All supported formats
51
+ ALL_FORMATS = RASTER_FORMATS + VECTOR_FORMATS
52
+
53
+ # Standard logo sizes (square, in pixels)
54
+ ALLOWED_SIZES = (16, 32, 48, 64, 96, 120, 128, 200, 256, 400, 512, 1024, 2000)
55
+
56
+ # ICO-specific sizes
57
+ ICO_SIZES = (16, 32, 48, 64, 128, 256)
File without changes
@@ -0,0 +1,95 @@
1
+ """Tests for the CryptoLogo Python client."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import pytest
6
+
7
+ from cryptologo import CryptoLogo
8
+ from cryptologo.client import CryptoLogoError
9
+ from cryptologo.types import ALLOWED_SIZES, ALL_FORMATS, ICO_SIZES, Coin
10
+
11
+
12
+ class TestCoin:
13
+ def test_from_dict(self) -> None:
14
+ data = {
15
+ "name": "Bitcoin",
16
+ "ticker": "BTC",
17
+ "slug": "bitcoin-btc",
18
+ "has_png": True,
19
+ "has_svg": True,
20
+ "search_terms": ["\ube44\ud2b8\ucf54\uc778"],
21
+ "market_cap_rank": 1,
22
+ }
23
+ coin = Coin.from_dict(data)
24
+ assert coin.name == "Bitcoin"
25
+ assert coin.ticker == "BTC"
26
+ assert coin.slug == "bitcoin-btc"
27
+ assert coin.has_png is True
28
+ assert coin.has_svg is True
29
+ assert coin.market_cap_rank == 1
30
+
31
+ def test_from_dict_minimal(self) -> None:
32
+ coin = Coin.from_dict({"name": "Test", "ticker": "TST", "slug": "test-tst"})
33
+ assert coin.has_png is False
34
+ assert coin.market_cap_rank is None
35
+
36
+
37
+ class TestCryptoLogoClient:
38
+ def test_default_base_url(self) -> None:
39
+ client = CryptoLogo()
40
+ assert client.base_url == "https://crypto-logo.com"
41
+
42
+ def test_custom_base_url(self) -> None:
43
+ client = CryptoLogo(base_url="http://localhost:8002/")
44
+ assert client.base_url == "http://localhost:8002"
45
+
46
+ def test_get_logo_url_svg(self) -> None:
47
+ client = CryptoLogo()
48
+ url = client.get_logo_url("bitcoin-btc", "svg")
49
+ assert url == "https://crypto-logo.com/api/logo/bitcoin-btc.svg"
50
+
51
+ def test_get_logo_url_png_with_size(self) -> None:
52
+ client = CryptoLogo()
53
+ url = client.get_logo_url("bitcoin-btc", "png", width=256, height=256)
54
+ assert url == "https://crypto-logo.com/api/logo/bitcoin-btc.png?w=256&h=256"
55
+
56
+ def test_get_logo_url_with_bg(self) -> None:
57
+ client = CryptoLogo()
58
+ url = client.get_logo_url("bitcoin-btc", "png", width=1200, height=630, bg="FFFFFF")
59
+ assert "bg=FFFFFF" in url
60
+
61
+ def test_get_cdn_url_png(self) -> None:
62
+ client = CryptoLogo()
63
+ url = client.get_cdn_url("bitcoin-btc", "png", 128)
64
+ assert url == "https://cdn.crypto-logo.com/logos/bitcoin-btc/128x128/transparent.png"
65
+
66
+ def test_get_cdn_url_svg(self) -> None:
67
+ client = CryptoLogo()
68
+ url = client.get_cdn_url("bitcoin-btc", "svg")
69
+ assert url == "https://cdn.crypto-logo.com/logos/bitcoin-btc/vector.svg"
70
+
71
+ def test_invalid_format(self) -> None:
72
+ client = CryptoLogo()
73
+ with pytest.raises(ValueError, match="Unsupported format"):
74
+ client.get_logo("bitcoin-btc", "bmp")
75
+
76
+ def test_raster_requires_width(self) -> None:
77
+ client = CryptoLogo()
78
+ with pytest.raises(ValueError, match="Width is required"):
79
+ client.get_logo("bitcoin-btc", "png")
80
+
81
+
82
+ class TestConstants:
83
+ def test_all_formats(self) -> None:
84
+ assert "svg" in ALL_FORMATS
85
+ assert "png" in ALL_FORMATS
86
+ assert "webp" in ALL_FORMATS
87
+
88
+ def test_allowed_sizes(self) -> None:
89
+ assert 128 in ALLOWED_SIZES
90
+ assert 512 in ALLOWED_SIZES
91
+ assert 2000 in ALLOWED_SIZES
92
+
93
+ def test_ico_sizes(self) -> None:
94
+ assert 32 in ICO_SIZES
95
+ assert 256 in ICO_SIZES
@@ -0,0 +1,8 @@
1
+ version = 1
2
+ revision = 3
3
+ requires-python = ">=3.10"
4
+
5
+ [[package]]
6
+ name = "cryptologo"
7
+ version = "0.1.0"
8
+ source = { editable = "." }