Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Access CoinGecko crypto market data: spot prices, OHLC, trending coins, exchange listings, NFTs, and global stats.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
tools/contracts.py
1#!/usr/bin/env python32"""3CoinGecko Contract/Token Tools45Tools for fetching token data by contract address.6"""78import os9from dotenv import load_dotenv10import json11import argparse12from typing import Dict, Any1314from core.http_client import proxied_get1516# Load environment variables17load_dotenv()181920def get_api_key() -> str:21"""Get CoinGecko API key from environment."""22api_key = os.getenv("COINGECKO_API_KEY")23if not api_key:24raise ValueError("COINGECKO_API_KEY environment variable is required")25return api_key262728def get_token_price(29platform: str,30contract_addresses: str,31vs_currencies: str = "usd",32include_market_cap: bool = False,33include_24hr_vol: bool = False,34include_24hr_change: bool = False,35include_last_updated_at: bool = False36) -> Dict[str, Any]:37"""38Get token prices by contract address.3940Args:41platform: Asset platform id (ethereum, solana, polygon-pos, etc.)42contract_addresses: Comma-separated contract addresses43vs_currencies: Comma-separated target currencies (usd, eur, btc)44include_market_cap: Include market cap45include_24hr_vol: Include 24h volume46include_24hr_change: Include 24h price change47include_last_updated_at: Include last updated timestamp4849Returns:50Dictionary with token prices51"""52api_key = get_api_key()5354url = f"https://pro-api.coingecko.com/api/v3/simple/token_price/{platform}"55headers = {"x-cg-pro-api-key": api_key}56params = {57"contract_addresses": contract_addresses,58"vs_currencies": vs_currencies,59"include_market_cap": str(include_market_cap).lower(),60"include_24hr_vol": str(include_24hr_vol).lower(),61"include_24hr_change": str(include_24hr_change).lower(),62"include_last_updated_at": str(include_last_updated_at).lower()63}6465response = proxied_get(url, headers=headers, params=params, timeout=30)66response.raise_for_status()67data = response.json()6869# Format response70tokens = {}71for address, price_data in data.items():72tokens[address.lower()] = price_data7374return {75"platform": platform,76"vs_currencies": vs_currencies.split(","),77"tokens": tokens,78"count": len(tokens)79}808182def get_coin_by_contract(83platform: str,84contract_address: str85) -> Dict[str, Any]:86"""87Get coin data by contract address.8889Args:90platform: Asset platform id (ethereum, solana, polygon-pos, etc.)91contract_address: Token contract address9293Returns:94Dictionary with coin data95"""96api_key = get_api_key()9798url = f"https://pro-api.coingecko.com/api/v3/coins/{platform}/contract/{contract_address}"99headers = {"x-cg-pro-api-key": api_key}100101response = proxied_get(url, headers=headers, timeout=30)102response.raise_for_status()103data = response.json()104105result = {106"id": data.get("id", ""),107"symbol": data.get("symbol", "").upper(),108"name": data.get("name", ""),109"asset_platform_id": data.get("asset_platform_id"),110"platforms": data.get("platforms", {}),111"block_time_in_minutes": data.get("block_time_in_minutes"),112"hashing_algorithm": data.get("hashing_algorithm"),113"categories": data.get("categories", []),114"description": data.get("description", {}).get("en", ""),115"links": {116"homepage": data.get("links", {}).get("homepage", []),117"blockchain_site": data.get("links", {}).get("blockchain_site", []),118"twitter_screen_name": data.get("links", {}).get("twitter_screen_name"),119"telegram_channel_identifier": data.get("links", {}).get("telegram_channel_identifier"),120"subreddit_url": data.get("links", {}).get("subreddit_url")121},122"image": data.get("image", {}),123"country_origin": data.get("country_origin"),124"genesis_date": data.get("genesis_date"),125"contract_address": data.get("contract_address"),126"sentiment_votes_up_percentage": data.get("sentiment_votes_up_percentage"),127"sentiment_votes_down_percentage": data.get("sentiment_votes_down_percentage"),128"market_cap_rank": data.get("market_cap_rank"),129"coingecko_rank": data.get("coingecko_rank"),130"coingecko_score": data.get("coingecko_score"),131"developer_score": data.get("developer_score"),132"community_score": data.get("community_score"),133"liquidity_score": data.get("liquidity_score"),134"public_interest_score": data.get("public_interest_score"),135"last_updated": data.get("last_updated")136}137138# Include market data if available139if "market_data" in data:140md = data["market_data"]141result["market_data"] = {142"current_price": md.get("current_price", {}),143"ath": md.get("ath", {}),144"ath_change_percentage": md.get("ath_change_percentage", {}),145"ath_date": md.get("ath_date", {}),146"atl": md.get("atl", {}),147"atl_change_percentage": md.get("atl_change_percentage", {}),148"atl_date": md.get("atl_date", {}),149"market_cap": md.get("market_cap", {}),150"market_cap_rank": md.get("market_cap_rank"),151"fully_diluted_valuation": md.get("fully_diluted_valuation", {}),152"total_volume": md.get("total_volume", {}),153"high_24h": md.get("high_24h", {}),154"low_24h": md.get("low_24h", {}),155"price_change_24h": md.get("price_change_24h"),156"price_change_percentage_24h": md.get("price_change_percentage_24h"),157"price_change_percentage_7d": md.get("price_change_percentage_7d"),158"price_change_percentage_14d": md.get("price_change_percentage_14d"),159"price_change_percentage_30d": md.get("price_change_percentage_30d"),160"price_change_percentage_60d": md.get("price_change_percentage_60d"),161"price_change_percentage_200d": md.get("price_change_percentage_200d"),162"price_change_percentage_1y": md.get("price_change_percentage_1y"),163"market_cap_change_24h": md.get("market_cap_change_24h"),164"market_cap_change_percentage_24h": md.get("market_cap_change_percentage_24h"),165"total_supply": md.get("total_supply"),166"max_supply": md.get("max_supply"),167"circulating_supply": md.get("circulating_supply")168}169170return result171172173def main():174"""CLI interface for contract tools."""175parser = argparse.ArgumentParser(176description="CoinGecko Contract/Token Tools",177formatter_class=argparse.RawDescriptionHelpFormatter178)179180subparsers = parser.add_subparsers(dest="command")181182# Token price command183price_parser = subparsers.add_parser("price", help="Get token price by contract")184price_parser.add_argument("platform", help="Asset platform (ethereum, solana, etc.)")185price_parser.add_argument("addresses", help="Contract addresses (comma-separated)")186price_parser.add_argument("--currencies", default="usd", help="Target currencies")187price_parser.add_argument("--market-cap", action="store_true", help="Include market cap")188price_parser.add_argument("--volume", action="store_true", help="Include 24h volume")189price_parser.add_argument("--change", action="store_true", help="Include 24h change")190191# Coin data command192data_parser = subparsers.add_parser("data", help="Get coin data by contract")193data_parser.add_argument("platform", help="Asset platform (ethereum, solana, etc.)")194data_parser.add_argument("address", help="Contract address")195196args = parser.parse_args()197198try:199if args.command == "price":200result = get_token_price(201platform=args.platform,202contract_addresses=args.addresses,203vs_currencies=args.currencies,204include_market_cap=args.market_cap,205include_24hr_vol=args.volume,206include_24hr_change=args.change207)208elif args.command == "data":209result = get_coin_by_contract(args.platform, args.address)210else:211parser.print_help()212return 0213214print(json.dumps(result, indent=2, ensure_ascii=False))215return 0216217except Exception as e:218print(json.dumps({"error": str(e)}, indent=2))219return 1220221222if __name__ == "__main__":223exit(main())224