|
| 1 | +--- |
| 2 | +name: add-icon |
| 3 | +description: Add a new cryptocurrency icon to the project with proper compression and mapping |
| 4 | +--- |
| 5 | + |
| 6 | +# Add Icon |
| 7 | + |
| 8 | +Guide user through adding a new cryptocurrency icon following the project's README.md guidelines. |
| 9 | + |
| 10 | +## Prompt Variables |
| 11 | + |
| 12 | +$TICKER |
| 13 | + |
| 14 | +> The token ticker (will be used as PNG filename in UPPERCASE) |
| 15 | +> Examples: USDC, BTC, PEPE, RSETH |
| 16 | +
|
| 17 | +$FETCH_LEDGER_IDS |
| 18 | + |
| 19 | +> Should ledger IDs be fetched from Coinradar? yes | no |
| 20 | +> |
| 21 | +> - `yes`: Automatically fetch ledger IDs from Coinradar API |
| 22 | +> - `no`: User will provide ledger IDs manually or they already exist in \_record.json |
| 23 | +
|
| 24 | +$SKIP_COMPRESSION |
| 25 | + |
| 26 | +> Skip the compression step? yes | no |
| 27 | +> |
| 28 | +> - `yes`: File is already compressed and in assets/ folder |
| 29 | +> - `no`: File needs to be compressed from compress/ folder (default) |
| 30 | +
|
| 31 | +$RUN_GENERATE_INDEX |
| 32 | + |
| 33 | +> Run pnpm generate:index after updating? yes | no |
| 34 | +> |
| 35 | +> - `yes`: Automatically generate index.json (default) |
| 36 | +> - `no`: Skip index generation (user will run manually) |
| 37 | +
|
| 38 | +## Instructions |
| 39 | + |
| 40 | +**⚠️ Important:** All file paths in these instructions are relative to the workspace root. When running commands or checking files, ensure you're using paths from the workspace root or absolute paths to avoid confusion with relative paths. |
| 41 | + |
| 42 | +### Step 1: Validate Prerequisites |
| 43 | + |
| 44 | +According to README.md, the icon must meet these requirements: |
| 45 | + |
| 46 | +**PNG File Requirements:** |
| 47 | + |
| 48 | +- Size: 144x144 pixels |
| 49 | +- Format: PNG |
| 50 | +- Background: Required (no transparent background) |
| 51 | +- Max size after compression: ≤50 KB (aim for smaller, 41 KB is already large) |
| 52 | +- Naming: Use ticker or recognizable name (e.g., PEPE.png, USDC.png) |
| 53 | + |
| 54 | +Inform the user of these requirements. |
| 55 | + |
| 56 | +### Step 2: Fetch Ledger IDs (if requested) |
| 57 | + |
| 58 | +If $FETCH_LEDGER_IDS is "yes": |
| 59 | + |
| 60 | +1. Fetch top 1000 currencies from Coinradar: |
| 61 | + |
| 62 | + ``` |
| 63 | + https://api.coinradar.ledger.com/v1/live/currencies?limit=1000&offset=0 |
| 64 | + ``` |
| 65 | + |
| 66 | +2. Find the currency matching $TICKER (case-insensitive) |
| 67 | + |
| 68 | +3. If found: |
| 69 | + - Extract `coinradarId` |
| 70 | + - Fetch detailed data: |
| 71 | + ``` |
| 72 | + https://api.coinradar.ledger.com/v1/live/currency-nested/{coinradarId} |
| 73 | + ``` |
| 74 | + - Extract all `ledgerId` values where `ledgerId !== null` |
| 75 | + - Store for later use |
| 76 | +
|
| 77 | +4. If not found: |
| 78 | + - Log warning: "Token not found in Coinradar API" |
| 79 | + - Continue without ledger IDs (user can add manually) |
| 80 | +
|
| 81 | +If $FETCH_LEDGER_IDS is "no": |
| 82 | +
|
| 83 | +- Skip this step |
| 84 | +- Check if $TICKER already exists in `_record.json` |
| 85 | +
|
| 86 | +### Step 3: Prepare PNG File |
| 87 | +
|
| 88 | +The filename will be: `{$TICKER}.png` (uppercase) |
| 89 | +
|
| 90 | +**If $SKIP_COMPRESSION is "no" (default):** |
| 91 | +
|
| 92 | +1. Instruct user: |
| 93 | +
|
| 94 | + ``` |
| 95 | + Please add your PNG file to the compress/ folder: |
| 96 | + compress/{$TICKER}.png |
| 97 | + |
| 98 | + Requirements: |
| 99 | + - 144x144 pixels |
| 100 | + - PNG format with background |
| 101 | + - Named: {$TICKER}.png |
| 102 | + |
| 103 | + Type 'ready' when the file is in place. |
| 104 | + ``` |
| 105 | +
|
| 106 | +2. Wait for user confirmation |
| 107 | +
|
| 108 | +3. Verify file exists at `compress/{$TICKER}.png` (use absolute path from workspace root) |
| 109 | +
|
| 110 | +4. Run compression: |
| 111 | +
|
| 112 | + ```bash |
| 113 | + cd lib && pnpm compress |
| 114 | + ``` |
| 115 | + |
| 116 | + **IMPORTANT:** The compression script outputs to `compress/out/{$TICKER}.png`, not `compress/`! |
| 117 | + |
| 118 | +5. Verify compressed file exists: |
| 119 | + |
| 120 | + ```bash |
| 121 | + ls -lh compress/out/{$TICKER}.png |
| 122 | + ``` |
| 123 | + |
| 124 | +6. Move compressed file to assets: |
| 125 | + |
| 126 | + ```bash |
| 127 | + mv compress/out/{$TICKER}.png assets/{$TICKER}.png |
| 128 | + ``` |
| 129 | + |
| 130 | + **Note:** Always use paths from the workspace root or absolute paths to avoid confusion. |
| 131 | + |
| 132 | +7. Clean up source files: |
| 133 | + ```bash |
| 134 | + rm compress/{$TICKER}.png |
| 135 | + rmdir compress/out 2>/dev/null || true |
| 136 | + ``` |
| 137 | + |
| 138 | +**If $SKIP_COMPRESSION is "yes":** |
| 139 | + |
| 140 | +1. Verify file exists at `assets/{$TICKER}.png` |
| 141 | +2. If not found, error and exit |
| 142 | + |
| 143 | +### Step 5: Verify File Size |
| 144 | + |
| 145 | +Check the file size of `assets/{$TICKER}.png`: |
| 146 | + |
| 147 | +```bash |
| 148 | +ls -lh assets/{$TICKER}.png |
| 149 | +``` |
| 150 | + |
| 151 | +**Note:** If the file is not found, ensure you're using the path from the workspace root, or use the absolute path to avoid confusion. |
| 152 | + |
| 153 | +**Validation:** |
| 154 | + |
| 155 | +- If ≤50 KB: ✅ "File size: {size} KB (within limit)" |
| 156 | +- If >50 KB: ⚠️ "Warning: File exceeds 50 KB limit ({size} KB). Consider optimizing further." |
| 157 | + |
| 158 | +### Step 6: Update \_record.json |
| 159 | + |
| 160 | +1. Read `assets/_record.json` |
| 161 | + |
| 162 | +2. Convert $TICKER to UPPERCASE |
| 163 | + |
| 164 | +3. Check if entry exists: |
| 165 | + |
| 166 | + **If exists:** |
| 167 | + - Get existing IDs: `record[$TICKER].ids` |
| 168 | + - If we have new ledger IDs from Step 2: |
| 169 | + - Merge: `[...existingIds, ...newIds]` |
| 170 | + - Remove duplicates |
| 171 | + - Sort alphabetically |
| 172 | + - Update: `record[$TICKER].ids = mergedIds` |
| 173 | + - Log: "Updated existing entry for {$TICKER}" |
| 174 | + |
| 175 | + **If not exists:** |
| 176 | + - Create new entry: `record[$TICKER] = { ids: ledgerIds }` |
| 177 | + - Ensure alphabetical insertion in the JSON object |
| 178 | + - Log: "Created new entry for {$TICKER}" |
| 179 | + |
| 180 | +4. Write updated record to `assets/_record.json` |
| 181 | + - Maintain alphabetical order of keys |
| 182 | + - Use 2-space indentation |
| 183 | + - Add newline at end of file |
| 184 | + |
| 185 | +### Step 7: Generate Index |
| 186 | + |
| 187 | +If $RUN_GENERATE_INDEX is "yes" (default): |
| 188 | + |
| 189 | +```bash |
| 190 | +cd lib && pnpm generate:index |
| 191 | +``` |
| 192 | + |
| 193 | +This updates `assets/index.json` from `_record.json`. |
| 194 | + |
| 195 | +If "no": |
| 196 | + |
| 197 | +- Skip and remind user: "Remember to run: cd lib && pnpm generate:index" |
| 198 | + |
| 199 | +### Step 8: Output Summary |
| 200 | + |
| 201 | +Display completion message: |
| 202 | + |
| 203 | +``` |
| 204 | +✅ Icon for {$TICKER} added successfully! |
| 205 | +
|
| 206 | +Files updated: |
| 207 | +✓ assets/{$TICKER}.png ({size} KB) |
| 208 | +✓ assets/_record.json |
| 209 | +✓ assets/index.json |
| 210 | +
|
| 211 | +Ledger IDs: {count} total |
| 212 | +``` |
| 213 | + |
| 214 | +### Step 9: Suggest Next Steps |
| 215 | + |
| 216 | +Suggest running verification: |
| 217 | + |
| 218 | +``` |
| 219 | +Next steps: |
| 220 | +- Verify icon: node scripts/verify-icons.js |
| 221 | +- View icon: open assets/{$TICKER}.png |
| 222 | +``` |
| 223 | + |
| 224 | +## Example Execution |
| 225 | + |
| 226 | +**Variables:** |
| 227 | + |
| 228 | +- $TICKER: "PEPE" |
| 229 | +- $FETCH_LEDGER_IDS: "yes" |
| 230 | +- $SKIP_COMPRESSION: "no" |
| 231 | +- $RUN_GENERATE_INDEX: "yes" |
| 232 | + |
| 233 | +**Expected flow:** |
| 234 | + |
| 235 | +``` |
| 236 | +🎨 Adding icon for PEPE... |
| 237 | +
|
| 238 | +Step 1: Fetching ledger IDs from Coinradar... |
| 239 | + ✓ Found: Pepe (PEPE) |
| 240 | + ✓ Fetched 3 ledger IDs |
| 241 | +
|
| 242 | +Step 2: Preparing PNG file... |
| 243 | + 📝 Please add your PNG file to: compress/PEPE.png |
| 244 | +
|
| 245 | + Requirements: |
| 246 | + - 144x144 pixels |
| 247 | + - PNG format with background |
| 248 | + - Named: PEPE.png |
| 249 | +
|
| 250 | + Type 'ready' when the file is in place. |
| 251 | +
|
| 252 | +[User types: ready] |
| 253 | +
|
| 254 | + ✓ File found at compress/PEPE.png |
| 255 | + 🔄 Running compression... |
| 256 | + ✓ Compression complete (output: compress/out/PEPE.png) |
| 257 | + ✓ Verified compressed file |
| 258 | + ✓ Moved to assets/PEPE.png |
| 259 | +
|
| 260 | +Step 3: Verifying file size... |
| 261 | + ✓ File size: 28.4 KB (within 50 KB limit) |
| 262 | +
|
| 263 | +Step 4: Updating _record.json... |
| 264 | + ✓ Created new entry for PEPE |
| 265 | + ✓ Added 3 ledger IDs |
| 266 | +
|
| 267 | +Step 5: Generating index... |
| 268 | + 🔄 Running pnpm generate:index... |
| 269 | + ✓ Index generated successfully |
| 270 | +
|
| 271 | +✅ Icon for PEPE added successfully! |
| 272 | +
|
| 273 | +Files updated: |
| 274 | +✓ assets/PEPE.png (28.4 KB) |
| 275 | +✓ assets/_record.json |
| 276 | +✓ assets/index.json |
| 277 | +
|
| 278 | +Ledger IDs: 3 total |
| 279 | + - arbitrum/erc20/pepe |
| 280 | + - ethereum/erc20/pepe |
| 281 | + - linea/erc20/pepe |
| 282 | +
|
| 283 | +Next steps: |
| 284 | +- Verify icon: node scripts/verify-icons.js |
| 285 | +- View icon: open assets/PEPE.png |
| 286 | +``` |
| 287 | + |
| 288 | +## Error Handling |
| 289 | + |
| 290 | +**File not found after user confirmation:** |
| 291 | + |
| 292 | +``` |
| 293 | +❌ Error: File not found at compress/PEPE.png |
| 294 | + Please ensure the file is in place and try again. |
| 295 | +``` |
| 296 | + |
| 297 | +**Compression failed:** |
| 298 | + |
| 299 | +``` |
| 300 | +❌ Error: Compression failed |
| 301 | + Reason: {error message} |
| 302 | + You may need to optimize the source file manually. |
| 303 | +``` |
| 304 | + |
| 305 | +**File too large:** |
| 306 | + |
| 307 | +``` |
| 308 | +⚠️ Warning: File size is 68.2 KB (exceeds 50 KB limit) |
| 309 | + The icon was added, but consider re-optimizing the source file. |
| 310 | + Aim for <50 KB (ideally much smaller). |
| 311 | +``` |
| 312 | + |
| 313 | +**Token not found in Coinradar:** |
| 314 | + |
| 315 | +``` |
| 316 | +⚠️ Warning: PEPE not found in Coinradar API |
| 317 | + Icon will be added without ledger IDs. |
| 318 | + You can add them manually to _record.json later. |
| 319 | +``` |
| 320 | + |
| 321 | +**generate:index failed:** |
| 322 | + |
| 323 | +``` |
| 324 | +❌ Error: Failed to generate index |
| 325 | + Reason: {error message} |
| 326 | + You can run it manually: cd lib && pnpm generate:index |
| 327 | +``` |
| 328 | + |
| 329 | +## Notes |
| 330 | + |
| 331 | +- PNG filename becomes the key in `_record.json` (without .png extension) |
| 332 | +- All tickers are converted to UPPERCASE for consistency |
| 333 | +- Compression is done via `pnpm compress` which: |
| 334 | + - Reads from `compress/` folder |
| 335 | + - Outputs compressed files to `compress/out/` folder |
| 336 | + - Files must then be moved from `compress/out/` to `assets/` |
| 337 | +- The verification script (`scripts/verify-icons.js`) validates file sizes and ledger IDs |
| 338 | +- Storybook shows production icons only, so new icons won't appear in storybook branches |
| 339 | +- If design/UX help is needed for the icon, user should contact the design or WXP team |
| 340 | +- Always use paths from workspace root or absolute paths when verifying file locations |
0 commit comments