Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion mainnet/Cake/logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions mainnet/IDRX/logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion mainnet/MVT/logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion mainnet/WBTC/logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion mainnet/aprMON/logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion mainnet/earnAUSD/logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions mainnet/gMON/logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ readme = "README.md"
requires-python = ">=3.9"
dependencies = [
"json5>=0.12.1",
"pillow>=11.0.0",
"pyjson5>=2.0.0",
"requests>=2.32.5",
"web3>=7.6.0",
Expand Down
92 changes: 86 additions & 6 deletions scripts/validate_tokens.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@
import argparse
import re
import sys
import xml.etree.ElementTree as ET
from pathlib import Path
from typing import Any
from typing import Any, Optional

import json5
from PIL import Image
from utils.web3 import (
DEFAULT_RPC_URL,
fetch_token_decimals_with_retry,
Expand All @@ -39,6 +41,7 @@
EXPECTED_CHAIN_ID = 143
MIN_DECIMALS = 0
MAX_DECIMALS = 36
MIN_LOGO_SIZE = 200
ZERO_ADDRESS = "0x0000000000000000000000000000000000000000"


Expand Down Expand Up @@ -130,6 +133,85 @@ def validate_bridge_info(bridge_info: dict[str, Any]) -> list[str]:
return errors


def get_svg_dimensions(svg_path: Path) -> tuple[Optional[int], Optional[int]]:
"""Extract width and height from an SVG file.

Args:
svg_path: Path to the SVG file.

Returns:
tuple[Optional[int], Optional[int]]: (width, height) in pixels, or (None, None) if not
found.
"""
try:
tree = ET.parse(svg_path)
root = tree.getroot()

width_str = root.get("width")
height_str = root.get("height")

if width_str and height_str:
width = int(re.sub(r"[^0-9.]", "", width_str).split(".")[0])
height = int(re.sub(r"[^0-9.]", "", height_str).split(".")[0])
return width, height

return None, None
except Exception:
return None, None


def validate_logo_dimensions(token_dir_path: Path) -> list[str]:
"""Validate logo file dimensions.

Args:
token_dir_path: Path to the token directory.

Returns:
list[str]: List of error messages. Empty list if validation passes.
"""
errors = []
svg_logo_path = token_dir_path / "logo.svg"
png_logo_path = token_dir_path / "logo.png"

logo_path = None
if svg_logo_path.exists():
logo_path = svg_logo_path
elif png_logo_path.exists():
logo_path = png_logo_path
else:
return ["Logo file not found"]

try:
if logo_path.suffix == ".svg":
width, height = get_svg_dimensions(logo_path)
if width is None or height is None:
errors.append(
"Could not extract dimensions from SVG. "
"Ensure the SVG has width/height attributes or a viewBox."
)
return errors
elif logo_path.suffix == ".png":
with Image.open(logo_path) as img:
width, height = img.size
else:
errors.append(f"Unsupported logo format: {logo_path.suffix}")
return errors

# Check if square
if width != height:
errors.append(f"Logo must be square: current dimensions are {width}x{height}px")
# Check minimum size
elif width < MIN_LOGO_SIZE:
errors.append(
f"Logo dimensions must be at least {MIN_LOGO_SIZE}x{MIN_LOGO_SIZE}px: "
f"current dimensions are {width}x{height}px"
)
except Exception as e:
errors.append(f"Failed to validate logo dimensions: {e}")

return errors


def validate_token_data(
data: dict[str, Any],
token_dir_path: Path,
Expand Down Expand Up @@ -184,11 +266,9 @@ def validate_token_data(
f"Invalid decimals: must be an integer between {MIN_DECIMALS} and {MAX_DECIMALS}"
)

# Validate logo
svg_logo_path = token_dir_path / "logo.svg"
png_logo_path = token_dir_path / "logo.png"
if not svg_logo_path.exists() and not png_logo_path.exists():
errors.append("Logo file not found")
# Validate logo dimensions
logo_errors = validate_logo_dimensions(token_dir_path)
errors.extend(logo_errors)

# Validate extensions (optional)
if "extensions" in data:
Expand Down
Loading
Loading