Files
randebu/docs/scripts/ave_data_rest.py
shokollm 90283d7403 docs: expand AVE Claw Hackathon research with code examples and guides
- Added 3 runnable Python scripts for Data REST, Data WebSocket, and Trading APIs
- Expanded research with 7 new sections:
  - Extended API documentation with full request/response examples
  - Working code examples with CLI commands
  - Security guide (API keys, HMAC signing, private key protection)
  - Testing strategies (dry-run, paper trading, testnets)
  - Troubleshooting guide with error codes
  - Competitive analysis vs DexScreener, Moralis, CoinGecko
  - Quick reference appendix

Research doc grew from 242 to 906 lines
2026-04-05 20:52:58 +00:00

495 lines
15 KiB
Python

#!/usr/bin/env python3
"""
AVE Cloud Data REST API - Token Search, Prices, Klines, Holders, Risk
Usage:
export AVE_API_KEY=your_api_key_here
export API_PLAN=free # free, normal, pro
python3 docs/scripts/ave_data_rest.py search --keyword PEPE
python3 docs/scripts/ave_data_rest.py price --token-ids "PEPE-bsc,TRUMP-bsc"
python3 docs/scripts/ave_data_rest.py trending --chain bsc
python3 docs/scripts/ave_data_rest.py token --token-id "0x6982508145454Ce325dDbE47a25d4ec3d2311933-bsc"
python3 docs/scripts/ave_data_rest.py risk --token-id "0x6982508145454Ce325dDbE47a25d4ec3d2311933-bsc"
python3 docs/scripts/ave_data_rest.py holders --token-id "0x6982508145454Ce325dDbE47a25d4ec3d2311933-bsc"
python3 docs/scripts/ave_data_rest.py klines --token-id "0x6982508145454Ce325dDbE47a25d4ec3d2311933-bsc"
python3 docs/scripts/ave_data_rest.py pairs --pair-id "0x16b9a82891338f9ba80e2d6970fdda79d1eb0dae-bsc"
python3 docs/scripts/ave_data_rest.py wallet-pnl --wallet "0xd9c500dff816a1da21a48a732d3498bf09dc9aeb" --chain bsc --token "0x55d398326f99059fF775485246999027B3197955"
python3 docs/scripts/ave_data_rest.py wallet-info --wallet "0xd9c500dff816a1da21a48a732d3498bf09dc9aeb" --chain bsc
python3 docs/scripts/ave_data_rest.py smart-wallets --chain bsc
"""
import argparse
import json
import os
import sys
import time
from dataclasses import dataclass
from typing import Optional
import requests
BASE_URL = "https://prod.ave-api.com"
API_KEY = os.getenv("AVE_API_KEY", "")
API_PLAN = os.getenv("API_PLAN", "free")
CU_COSTS = {
"search": 5,
"price": 100,
"trending": 5,
"token": 5,
"risk": 10,
"holders": 10,
"klines_token": 10,
"klines_pair": 10,
"pairs": 5,
"wallet_pnl": 5,
"wallet_info": 5,
"wallet_tokens": 10,
"smart_wallet": 5,
}
TIER_LIMITS = {
"free": {"tps": 1, "data_wss": False, "proxy_wallet": False},
"normal": {"tps": 5, "data_wss": False, "proxy_wallet": True},
"pro": {"tps": 20, "data_wss": True, "proxy_wallet": True},
}
@dataclass
class ApiResponse:
status: int
data: Optional[dict] = None
error: Optional[str] = None
def make_headers():
return {
"X-API-KEY": API_KEY,
"Content-Type": "application/json",
}
def handle_response(response: requests.Response) -> ApiResponse:
if response.status_code == 200:
return ApiResponse(status=200, data=response.json())
elif response.status_code == 401:
return ApiResponse(
status=401, error="Unauthorized - invalid or missing API key"
)
elif response.status_code == 403:
return ApiResponse(
status=403, error="Forbidden - API key expired or plan limits reached"
)
elif response.status_code == 429:
return ApiResponse(status=429, error="Rate limited - TPS exceeded")
else:
return ApiResponse(status=response.status_code, error=response.text)
def search_tokens(
keyword: str, chain: Optional[str] = None, limit: int = 100
) -> ApiResponse:
params = {"keyword": keyword, "limit": limit}
if chain:
params["chain"] = chain
response = requests.get(
f"{BASE_URL}/v2/tokens", headers=make_headers(), params=params
)
return handle_response(response)
def get_token_price(token_ids: list) -> ApiResponse:
data = {"token_ids": token_ids}
response = requests.post(
f"{BASE_URL}/v2/tokens/price", headers=make_headers(), json=data
)
return handle_response(response)
def get_trending_tokens(chain: str, page: int = 0, page_size: int = 50) -> ApiResponse:
params = {"chain": chain, "current_page": page, "page_size": page_size}
response = requests.get(
f"{BASE_URL}/v2/tokens/trending", headers=make_headers(), params=params
)
return handle_response(response)
def get_token_detail(token_id: str) -> ApiResponse:
response = requests.get(f"{BASE_URL}/v2/tokens/{token_id}", headers=make_headers())
return handle_response(response)
def get_token_risk(token_id: str) -> ApiResponse:
response = requests.get(
f"{BASE_URL}/v2/contracts/{token_id}", headers=make_headers()
)
return handle_response(response)
def get_top_holders(token_id: str, limit: int = 100) -> ApiResponse:
params = {"limit": limit} if limit != 100 else {}
response = requests.get(
f"{BASE_URL}/v2/tokens/top100/{token_id}", headers=make_headers(), params=params
)
return handle_response(response)
def get_klines_by_token(
token_id: str, interval: str = "1h", limit: int = 100
) -> ApiResponse:
params = {"interval": interval, "limit": limit}
response = requests.get(
f"{BASE_URL}/v2/klines/token/{token_id}", headers=make_headers(), params=params
)
return handle_response(response)
def get_klines_by_pair(
pair_id: str, interval: str = "1h", limit: int = 100
) -> ApiResponse:
params = {"interval": interval, "limit": limit}
response = requests.get(
f"{BASE_URL}/v2/klines/pair/{pair_id}", headers=make_headers(), params=params
)
return handle_response(response)
def get_pair_detail(pair_id: str) -> ApiResponse:
response = requests.get(f"{BASE_URL}/v2/pairs/{pair_id}", headers=make_headers())
return handle_response(response)
def get_wallet_pnl(
wallet_address: str,
chain: str,
token_address: str,
from_time: Optional[int] = None,
to_time: Optional[int] = None,
) -> ApiResponse:
params = {
"wallet_address": wallet_address,
"chain": chain,
"token_address": token_address,
}
if from_time:
params["from_time"] = from_time
if to_time:
params["to_time"] = to_time
response = requests.get(
f"{BASE_URL}/v2/address/pnl", headers=make_headers(), params=params
)
return handle_response(response)
def get_wallet_info(wallet_address: str, chain: str) -> ApiResponse:
params = {"wallet_address": wallet_address, "chain": chain}
response = requests.get(
f"{BASE_URL}/v2/address/walletinfo", headers=make_headers(), params=params
)
return handle_response(response)
def get_wallet_tokens(
wallet_address: str,
chain: str,
sort: str = "last_txn_time",
sort_dir: str = "desc",
hide_sold: int = 0,
hide_small: int = 0,
) -> ApiResponse:
params = {
"wallet_address": wallet_address,
"chain": chain,
"sort": sort,
"sort_dir": sort_dir,
"hide_sold": hide_sold,
"hide_small": hide_small,
}
response = requests.get(
f"{BASE_URL}/v2/address/walletinfo/tokens",
headers=make_headers(),
params=params,
)
return handle_response(response)
def get_smart_wallets(
chain: str, sort: str = "total_profit", sort_dir: str = "desc"
) -> ApiResponse:
params = {"chain": chain, "sort": sort, "sort_dir": sort_dir}
response = requests.get(
f"{BASE_URL}/v2/address/smart_wallet/list",
headers=make_headers(),
params=params,
)
return handle_response(response)
def format_json(data):
return json.dumps(data, indent=2, ensure_ascii=False)
def print_cu_warning(operation: str):
cu_cost = CU_COSTS.get(operation, "unknown")
print(f"[CU Cost: {cu_cost}]", file=sys.stderr)
def cmd_search(args):
result = search_tokens(args.keyword, args.chain, args.limit)
if result.error:
print(f"Error: {result.error}")
sys.exit(1)
print_cu_warning("search")
print(format_json(result.data))
def cmd_price(args):
token_ids = [t.strip() for t in args.token_ids.split(",")]
result = get_token_price(token_ids)
if result.error:
print(f"Error: {result.error}")
sys.exit(1)
print_cu_warning("price")
print(format_json(result.data))
def cmd_trending(args):
result = get_trending_tokens(args.chain, args.page, args.page_size)
if result.error:
print(f"Error: {result.error}")
sys.exit(1)
print_cu_warning("trending")
print(format_json(result.data))
def cmd_token(args):
result = get_token_detail(args.token_id)
if result.error:
print(f"Error: {result.error}")
sys.exit(1)
print_cu_warning("token")
print(format_json(result.data))
def cmd_risk(args):
result = get_token_risk(args.token_id)
if result.error:
print(f"Error: {result.error}")
sys.exit(1)
print_cu_warning("risk")
print(format_json(result.data))
def cmd_holders(args):
result = get_top_holders(args.token_id, args.limit)
if result.error:
print(f"Error: {result.error}")
sys.exit(1)
print_cu_warning("holders")
print(format_json(result.data))
def cmd_klines(args):
if args.pair_id:
result = get_klines_by_pair(args.pair_id, args.interval, args.limit)
print_cu_warning("klines_pair")
else:
result = get_klines_by_token(args.token_id, args.interval, args.limit)
print_cu_warning("klines_token")
if result.error:
print(f"Error: {result.error}")
sys.exit(1)
print(format_json(result.data))
def cmd_pairs(args):
result = get_pair_detail(args.pair_id)
if result.error:
print(f"Error: {result.error}")
sys.exit(1)
print_cu_warning("pairs")
print(format_json(result.data))
def cmd_wallet_pnl(args):
result = get_wallet_pnl(
args.wallet, args.chain, args.token, args.from_time, args.to_time
)
if result.error:
print(f"Error: {result.error}")
sys.exit(1)
print_cu_warning("wallet_pnl")
print(format_json(result.data))
def cmd_wallet_info(args):
result = get_wallet_info(args.wallet, args.chain)
if result.error:
print(f"Error: {result.error}")
sys.exit(1)
print_cu_warning("wallet_info")
print(format_json(result.data))
def cmd_wallet_tokens(args):
result = get_wallet_tokens(
args.wallet,
args.chain,
args.sort,
args.sort_dir,
args.hide_sold,
args.hide_small,
)
if result.error:
print(f"Error: {result.error}")
sys.exit(1)
print_cu_warning("wallet_tokens")
print(format_json(result.data))
def cmd_smart_wallets(args):
result = get_smart_wallets(args.chain, args.sort, args.sort_dir)
if result.error:
print(f"Error: {result.error}")
sys.exit(1)
print_cu_warning("smart_wallet")
print(format_json(result.data))
def main():
parser = argparse.ArgumentParser(description="AVE Cloud Data REST API")
parser.add_argument(
"--api-key", default=API_KEY, help="AVE API key (or set AVE_API_KEY env)"
)
parser.add_argument(
"--api-plan",
default=API_PLAN,
choices=["free", "normal", "pro"],
help="API plan",
)
subparsers = parser.add_subparsers(dest="command", help="Commands")
p_search = subparsers.add_parser("search", help="Search tokens by keyword")
p_search.add_argument("--keyword", required=True, help="Token symbol or address")
p_search.add_argument("--chain", help="Chain name (bsc, solana, eth, base)")
p_search.add_argument(
"--limit", type=int, default=100, help="Number of results (max 300)"
)
p_price = subparsers.add_parser("price", help="Get batch token prices")
p_price.add_argument(
"--token-ids",
required=True,
help="Comma-separated token IDs (e.g. PEPE-bsc,TRUMP-bsc)",
)
p_trending = subparsers.add_parser("trending", help="Get trending tokens")
p_trending.add_argument("--chain", required=True, help="Chain name")
p_trending.add_argument("--page", type=int, default=0, help="Page number")
p_trending.add_argument(
"--page-size", type=int, default=50, help="Results per page (max 100)"
)
p_token = subparsers.add_parser("token", help="Get token details and top pairs")
p_token.add_argument(
"--token-id", required=True, help="Token ID (address-chain format)"
)
p_risk = subparsers.add_parser("risk", help="Get token risk information")
p_risk.add_argument(
"--token-id", required=True, help="Token ID (address-chain format)"
)
p_holders = subparsers.add_parser("holders", help="Get top 100 token holders")
p_holders.add_argument(
"--token-id", required=True, help="Token ID (address-chain format)"
)
p_holders.add_argument(
"--limit", type=int, default=100, help="Number of holders (max 100)"
)
p_klines = subparsers.add_parser("klines", help="Get kline/candlestick data")
p_klines.add_argument("--token-id", help="Token ID (use OR --pair-id)")
p_klines.add_argument("--pair-id", help="Pair ID (use OR --token-id)")
p_klines.add_argument(
"--interval", default="1h", help="Interval (1m, 5m, 15m, 30m, 1h, 4h, 1d)"
)
p_klines.add_argument("--limit", type=int, default=100, help="Number of klines")
p_pairs = subparsers.add_parser("pairs", help="Get pair details")
p_pairs.add_argument(
"--pair-id", required=True, help="Pair ID (address-chain format)"
)
p_wallet_pnl = subparsers.add_parser(
"wallet-pnl", help="Get wallet PnL for a token"
)
p_wallet_pnl.add_argument("--wallet", required=True, help="Wallet address")
p_wallet_pnl.add_argument("--chain", required=True, help="Chain name")
p_wallet_pnl.add_argument("--token", required=True, help="Token address")
p_wallet_pnl.add_argument(
"--from-time", type=int, help="Unix epoch seconds (earliest 15 days ago)"
)
p_wallet_pnl.add_argument("--to-time", type=int, help="Unix epoch seconds")
p_wallet_info = subparsers.add_parser(
"wallet-info", help="Get wallet info (all tokens on chain)"
)
p_wallet_info.add_argument("--wallet", required=True, help="Wallet address")
p_wallet_info.add_argument("--chain", required=True, help="Chain name")
p_wallet_tokens = subparsers.add_parser(
"wallet-tokens", help="Get all tokens holding in wallet"
)
p_wallet_tokens.add_argument("--wallet", required=True, help="Wallet address")
p_wallet_tokens.add_argument("--chain", required=True, help="Chain name")
p_wallet_tokens.add_argument("--sort", default="last_txn_time", help="Sort field")
p_wallet_tokens.add_argument(
"--sort-dir", default="desc", help="Sort direction (desc/asc)"
)
p_wallet_tokens.add_argument(
"--hide-sold", type=int, default=0, help="Hide sold tokens (0/1)"
)
p_wallet_tokens.add_argument(
"--hide-small", type=int, default=0, help="Hide small balances (0/1)"
)
p_smart = subparsers.add_parser(
"smart-wallets", help="Get smart wallet list (for copy trading)"
)
p_smart.add_argument("--chain", required=True, help="Chain name")
p_smart.add_argument("--sort", default="total_profit", help="Sort field")
p_smart.add_argument("--sort-dir", default="desc", help="Sort direction (desc/asc)")
args = parser.parse_args()
if not args.api_key:
print("Error: API key required. Set AVE_API_KEY env or use --api-key")
sys.exit(1)
if not args.command:
parser.print_help()
sys.exit(1)
cmd_map = {
"search": cmd_search,
"price": cmd_price,
"trending": cmd_trending,
"token": cmd_token,
"risk": cmd_risk,
"holders": cmd_holders,
"klines": cmd_klines,
"pairs": cmd_pairs,
"wallet-pnl": cmd_wallet_pnl,
"wallet-info": cmd_wallet_info,
"wallet-tokens": cmd_wallet_tokens,
"smart-wallets": cmd_smart_wallets,
}
cmd_map[args.command](args)
if __name__ == "__main__":
main()