Initial commit: coin-hunter skill
This commit is contained in:
296
SKILL.md
Normal file
296
SKILL.md
Normal file
@@ -0,0 +1,296 @@
|
|||||||
|
---
|
||||||
|
name: coin-hunter
|
||||||
|
description: Hunt, triage, and compare speculative crypto coins — especially meme coins, 妖币-style runners, fake-hype pumps, and possible rug/scam setups. Use when a user wants to actively search for coins with breakout potential, rank a shortlist, ask whether a coin still has "妖性", or check whether a token looks late, fragile, manipulated, or likely to be a scam.
|
||||||
|
---
|
||||||
|
|
||||||
|
# Coin Hunter
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
Use this skill to help a user search for and judge **high-volatility crypto setups** without pretending certainty.
|
||||||
|
|
||||||
|
Default buckets:
|
||||||
|
- **candidate runner** — has ingredients for further speculative expansion
|
||||||
|
- **watch-only / incomplete** — interesting, but not clean enough yet
|
||||||
|
- **late / overheated** — may still move, but entry quality is already poor
|
||||||
|
- **avoid / scam-risk** — liquidity, distribution, credibility, or structure is too weak
|
||||||
|
|
||||||
|
Frame the work as **speculative pattern recognition**, not investment advice.
|
||||||
|
|
||||||
|
## Core rule
|
||||||
|
|
||||||
|
Judge a coin by **attention + liquidity + distribution + timing** first. Narrative matters, but only when it can attract and hold money.
|
||||||
|
|
||||||
|
A technically weak project can still become a runner. A sophisticated-looking project can still be dead money.
|
||||||
|
|
||||||
|
## Supported request types
|
||||||
|
|
||||||
|
Use this skill for four common modes:
|
||||||
|
- **single-coin triage** — "look at this coin"
|
||||||
|
- **active discovery** — "find me coins that could become 妖币"
|
||||||
|
- **shortlist ranking** — "which of these 5 is most interesting"
|
||||||
|
- **scam / rug check** — "is this coin just fake hype"
|
||||||
|
|
||||||
|
If the request is broad, ask at most **one compact clarifying question**. Prefer:
|
||||||
|
- chain
|
||||||
|
- theme / narrative
|
||||||
|
- risk level
|
||||||
|
- whether the user accepts microcaps or wants only reasonably tradable names
|
||||||
|
|
||||||
|
If no preference is given, default to: **liquid speculative candidates, not ultra-illiquid microcaps**.
|
||||||
|
|
||||||
|
## Workflow
|
||||||
|
|
||||||
|
### 1. Identify the mode
|
||||||
|
|
||||||
|
Decide whether the user wants:
|
||||||
|
- discovery
|
||||||
|
- triage
|
||||||
|
- comparison
|
||||||
|
- scam-check
|
||||||
|
|
||||||
|
Then bias the workflow accordingly.
|
||||||
|
|
||||||
|
### 2. Choose the data path
|
||||||
|
|
||||||
|
Use **structured market data first** when available. Use web search to discover names and collect context, not as the only source of truth.
|
||||||
|
|
||||||
|
Preferred source order:
|
||||||
|
- **Bybit** for real-time-ish price, 24h turnover, and tradability on a major venue
|
||||||
|
- **DexScreener** for meme-coin pair discovery, DEX liquidity, and small-cap flow
|
||||||
|
- **Birdeye** for Solana token activity and confirmation
|
||||||
|
- **CoinGecko** for market-cap, rank, and metadata cross-check
|
||||||
|
- **web_search** for discovery, narratives, and scam-discussion context
|
||||||
|
|
||||||
|
Private user state must live outside the skill directory under `~/.coin-hunter/`, not inside `skills/coin-hunter/`.
|
||||||
|
Read `references/provider-playbook.md` when choosing which source to trust first.
|
||||||
|
Read `references/user-data-layout.md` when adding or updating personal accounts, positions, watchlists, or notes.
|
||||||
|
Use `scripts/market_probe.py` for deterministic provider lookups.
|
||||||
|
Use `scripts/init_user_state.py` to initialize the private user-data directory.
|
||||||
|
|
||||||
|
### 3. Discovery mode: build a candidate list
|
||||||
|
|
||||||
|
When the user wants active search rather than analysis of a known ticker, use public web sources to build a shortlist.
|
||||||
|
|
||||||
|
Look for evidence of:
|
||||||
|
- rising attention
|
||||||
|
- listing or venue expansion
|
||||||
|
- narrative/theme alignment
|
||||||
|
- market-cap and liquidity context
|
||||||
|
- breakout discussion or unusual participation
|
||||||
|
|
||||||
|
Useful search patterns include:
|
||||||
|
- `<theme> meme coin trending`
|
||||||
|
- `<chain> meme coin watchlist`
|
||||||
|
- `new meme coin listed`
|
||||||
|
- `<coin> market cap liquidity`
|
||||||
|
- `<coin> holders tokenomics`
|
||||||
|
- `<coin> rug risk`
|
||||||
|
|
||||||
|
Do not trust a single source or a single viral thread. Build the list first, then vet the names.
|
||||||
|
|
||||||
|
Read `references/search-workflow.md` for the detailed discovery flow.
|
||||||
|
|
||||||
|
### 4. Triage mode: score the coin on six dimensions
|
||||||
|
|
||||||
|
Assess each coin qualitatively across these dimensions.
|
||||||
|
|
||||||
|
#### A. Narrative fit
|
||||||
|
Ask:
|
||||||
|
- Is the story attached to a live theme?
|
||||||
|
- Is the idea easy to repeat in one sentence?
|
||||||
|
- Does the symbol / meme / framing have social spread potential?
|
||||||
|
|
||||||
|
Strong examples:
|
||||||
|
- obvious meme identity
|
||||||
|
- attached to a live chain or hot sector
|
||||||
|
- easy cultural hook
|
||||||
|
|
||||||
|
Weak examples:
|
||||||
|
- vague utility story
|
||||||
|
- no memorable angle
|
||||||
|
- cold or stale narrative
|
||||||
|
|
||||||
|
#### B. Attention acceleration
|
||||||
|
Ask:
|
||||||
|
- Is visibility rising now?
|
||||||
|
- Is the coin spreading beyond its original niche?
|
||||||
|
- Are larger accounts, aggregators, or trading communities starting to notice it?
|
||||||
|
|
||||||
|
Treat **acceleration** as more important than absolute popularity.
|
||||||
|
|
||||||
|
#### C. Liquidity quality
|
||||||
|
Ask:
|
||||||
|
- Can a normal user realistically enter and exit?
|
||||||
|
- Is volume believable relative to market cap and attention?
|
||||||
|
- Are spreads or venue quality obviously problematic?
|
||||||
|
|
||||||
|
If the user can probably buy but may not be able to exit cleanly, score this harshly.
|
||||||
|
|
||||||
|
#### D. Distribution / holder risk
|
||||||
|
Ask:
|
||||||
|
- Is ownership too concentrated?
|
||||||
|
- Are deployer or team wallets still dangerous?
|
||||||
|
- Is there an obvious unlock or dump overhang?
|
||||||
|
|
||||||
|
Ugly distribution does not automatically kill a trade, but it makes the setup fragile.
|
||||||
|
|
||||||
|
#### E. Timing / chart state
|
||||||
|
Ask:
|
||||||
|
- Is it emerging from a base or already vertical?
|
||||||
|
- Has participation expanded recently?
|
||||||
|
- Do pullbacks hold, or do they collapse?
|
||||||
|
|
||||||
|
Prefer:
|
||||||
|
- fresh breakout from longer consolidation
|
||||||
|
- early or mid-stage expansion
|
||||||
|
- resilient retraces
|
||||||
|
|
||||||
|
Be cautious when:
|
||||||
|
- it already went parabolic
|
||||||
|
- volume fades after the first mania burst
|
||||||
|
- price action is mostly wick-and-dump behavior
|
||||||
|
|
||||||
|
#### F. Rug / scam risk
|
||||||
|
Check for:
|
||||||
|
- fake partnerships or fake listing claims
|
||||||
|
- unverifiable team paired with aggressive promotion
|
||||||
|
- suspicious contract / public warning signals
|
||||||
|
- impossible tokenomics promises
|
||||||
|
- unverified liquidity-lock claims
|
||||||
|
- nothing but shill posts and no independent discussion
|
||||||
|
|
||||||
|
One severe scam signal can outweigh several bullish ones.
|
||||||
|
Read `references/scam-signals.md` when the user specifically asks about rugs, scams, fake hype, manipulation, or exit-liquidity bait.
|
||||||
|
|
||||||
|
### 5. Classify the result
|
||||||
|
|
||||||
|
Use these buckets:
|
||||||
|
|
||||||
|
#### Candidate runner
|
||||||
|
Use when most are true:
|
||||||
|
- narrative is live
|
||||||
|
- attention is accelerating
|
||||||
|
- liquidity is usable
|
||||||
|
- timing is not obviously exhausted
|
||||||
|
- no fatal scam / exit-risk signal is present
|
||||||
|
|
||||||
|
#### Watch-only / incomplete
|
||||||
|
Use when:
|
||||||
|
- something is interesting, but evidence is incomplete
|
||||||
|
- narrative is decent but timing is unclear
|
||||||
|
- liquidity or distribution is acceptable but not clean
|
||||||
|
- it deserves monitoring more than action
|
||||||
|
|
||||||
|
#### Late / overheated
|
||||||
|
Use when:
|
||||||
|
- the move is already widely noticed
|
||||||
|
- chart is extended or near blow-off behavior
|
||||||
|
- upside may remain, but entry quality is poor
|
||||||
|
- new buyers are at risk of becoming exit liquidity
|
||||||
|
|
||||||
|
#### Avoid / scam-risk
|
||||||
|
Use when:
|
||||||
|
- liquidity quality is bad
|
||||||
|
- exit risk is high
|
||||||
|
- holder concentration is dangerous
|
||||||
|
- legitimacy claims are weak or fake
|
||||||
|
- the setup feels more fabricated than organic
|
||||||
|
|
||||||
|
## Provider execution patterns
|
||||||
|
|
||||||
|
### Known tradable coin
|
||||||
|
If the user gives a Bybit-listed ticker or asks for current price/tradability:
|
||||||
|
1. run `python3 scripts/market_probe.py bybit-ticker <SYMBOL>`
|
||||||
|
2. optionally run `python3 scripts/market_probe.py bybit-klines <SYMBOL> --interval 60 --limit 10`
|
||||||
|
3. cross-check with CoinGecko when market-cap context matters
|
||||||
|
|
||||||
|
### Meme / 妖币 discovery
|
||||||
|
If the user wants runners, meme coins, or small-cap candidates:
|
||||||
|
1. use `web_search` to gather names
|
||||||
|
2. run `python3 scripts/market_probe.py dex-search <name>` for the strongest candidates
|
||||||
|
3. if Solana, run Birdeye when API access is configured
|
||||||
|
4. use CoinGecko to verify market-cap and ranking
|
||||||
|
5. only use Bybit if the coin is also on a major CEX
|
||||||
|
|
||||||
|
### Birdeye requirement
|
||||||
|
`market_probe.py birdeye-token <address>` requires `BIRDEYE_API_KEY` in the environment. If it is not configured, say so briefly and continue with DexScreener + CoinGecko + web search.
|
||||||
|
|
||||||
|
### Private portfolio state
|
||||||
|
If the user wants account, position, watchlist, or thesis tracking for coin-hunter:
|
||||||
|
1. initialize `~/.coin-hunter/` with `python3 scripts/init_user_state.py`
|
||||||
|
2. store private data only there
|
||||||
|
3. never place personal holdings inside the skill folder
|
||||||
|
4. treat the skill folder as logic only, and the user-data directory as state only
|
||||||
|
|
||||||
|
## Output style
|
||||||
|
|
||||||
|
Default to **compact, decision-first** answers.
|
||||||
|
|
||||||
|
For a single coin, include:
|
||||||
|
- **Verdict**
|
||||||
|
- **Radar score** — use the 0-12 checklist when evidence is sufficient
|
||||||
|
- **Why it could run** — 2-4 bullets
|
||||||
|
- **Why it could fail** — 2-4 bullets
|
||||||
|
- **What confirms strength**
|
||||||
|
- **What kills the thesis**
|
||||||
|
- **Risk line** — clearly state this is speculative, not investment advice
|
||||||
|
|
||||||
|
For multiple coins:
|
||||||
|
1. rank the shortlist
|
||||||
|
2. mark each as candidate runner / watch-only / late / avoid
|
||||||
|
3. state the main attraction and main flaw for each
|
||||||
|
|
||||||
|
Prefer bullets, short sections, and hard judgments over long essays.
|
||||||
|
Use `references/output-templates.md` when you want a reusable answer skeleton.
|
||||||
|
|
||||||
|
## Practical heuristics
|
||||||
|
|
||||||
|
### Often bullish for speculative expansion
|
||||||
|
- the meme or story is instantly repeatable
|
||||||
|
- attention is accelerating, not just present
|
||||||
|
- volume expands with the move
|
||||||
|
- pullbacks are bought
|
||||||
|
- exchange accessibility improves
|
||||||
|
- more mainstream crypto accounts begin to mention it
|
||||||
|
|
||||||
|
### Often a sign it is late
|
||||||
|
- everyone is already talking about it
|
||||||
|
- the chart has been vertical for days
|
||||||
|
- promotion is everywhere after the main move already happened
|
||||||
|
- price keeps spiking while structure gets messier
|
||||||
|
|
||||||
|
### Often a sign to avoid
|
||||||
|
- no trustworthy liquidity information
|
||||||
|
- suspicious ownership concentration
|
||||||
|
- clearly manufactured chart behavior
|
||||||
|
- incoherent or constantly shifting explanation
|
||||||
|
- obviously botted or repetitive social activity
|
||||||
|
|
||||||
|
## What not to do
|
||||||
|
|
||||||
|
- Do not describe a coin as safe.
|
||||||
|
- Do not confuse a polished whitepaper with breakout potential.
|
||||||
|
- Do not imply expected returns.
|
||||||
|
- Do not recommend leverage.
|
||||||
|
- Do not ignore slippage and exit risk.
|
||||||
|
- Do not push microcaps on beginners unless the user explicitly asks for extreme risk.
|
||||||
|
|
||||||
|
## Optional deeper pass
|
||||||
|
|
||||||
|
If the user wants more depth, expand in this order:
|
||||||
|
1. narrative and timing
|
||||||
|
2. liquidity and market structure
|
||||||
|
3. holder / tokenomics risk
|
||||||
|
4. why it could become a runner
|
||||||
|
5. why it probably will not
|
||||||
|
6. watch triggers
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
Read `references/provider-playbook.md` for source selection and provider roles.
|
||||||
|
Read `references/user-data-layout.md` for private state layout under `~/.coin-hunter/`.
|
||||||
|
Read `references/radar-checklist.md` for a quick scoring framework.
|
||||||
|
Read `references/search-workflow.md` for active discovery.
|
||||||
|
Read `references/output-templates.md` for compact response structure.
|
||||||
|
Read `references/scam-signals.md` for sharper scam / fake-hype judgment.
|
||||||
71
references/output-templates.md
Normal file
71
references/output-templates.md
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
# Output Templates
|
||||||
|
|
||||||
|
Use these templates to keep answers crisp and decision-first.
|
||||||
|
|
||||||
|
## Single-coin quick triage
|
||||||
|
|
||||||
|
**Verdict:** candidate runner | late / overheated | avoid / scam-risk
|
||||||
|
**Radar score:** X/12
|
||||||
|
**Spec setup quality:** high | medium | low
|
||||||
|
|
||||||
|
**Why it could run**
|
||||||
|
- ...
|
||||||
|
- ...
|
||||||
|
- ...
|
||||||
|
|
||||||
|
**Why it could fail**
|
||||||
|
- ...
|
||||||
|
- ...
|
||||||
|
- ...
|
||||||
|
|
||||||
|
**What confirms strength**
|
||||||
|
- ...
|
||||||
|
- ...
|
||||||
|
|
||||||
|
**What kills the thesis**
|
||||||
|
- ...
|
||||||
|
- ...
|
||||||
|
|
||||||
|
**Risk note:** This is speculative pattern recognition, not investment advice.
|
||||||
|
|
||||||
|
## Multi-coin shortlist
|
||||||
|
|
||||||
|
### 1. <coin>
|
||||||
|
- **Verdict:**
|
||||||
|
- **Radar score:** X/12
|
||||||
|
- **Why it made the cut:**
|
||||||
|
- **Biggest flaw:**
|
||||||
|
|
||||||
|
### 2. <coin>
|
||||||
|
- **Verdict:**
|
||||||
|
- **Radar score:** X/12
|
||||||
|
- **Why it made the cut:**
|
||||||
|
- **Biggest flaw:**
|
||||||
|
|
||||||
|
### 3. <coin>
|
||||||
|
- **Verdict:**
|
||||||
|
- **Radar score:** X/12
|
||||||
|
- **Why it made the cut:**
|
||||||
|
- **Biggest flaw:**
|
||||||
|
|
||||||
|
**Bottom line**
|
||||||
|
- Most interesting now:
|
||||||
|
- Worth watching only:
|
||||||
|
- Avoid first:
|
||||||
|
|
||||||
|
## Scam-check format
|
||||||
|
|
||||||
|
**Verdict:** likely tradable speculation | fragile / high-risk | avoid / scam-risk
|
||||||
|
|
||||||
|
**Main warning signs**
|
||||||
|
- ...
|
||||||
|
- ...
|
||||||
|
|
||||||
|
**Any redeeming signs**
|
||||||
|
- ...
|
||||||
|
- ...
|
||||||
|
|
||||||
|
**Decision**
|
||||||
|
- what a cautious user should do next
|
||||||
|
|
||||||
|
**Risk note:** Absence of red flags is not proof of safety.
|
||||||
92
references/provider-playbook.md
Normal file
92
references/provider-playbook.md
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
# Provider Playbook
|
||||||
|
|
||||||
|
Use this reference when the user wants fresher crypto market data instead of relying only on web search.
|
||||||
|
|
||||||
|
## Source roles
|
||||||
|
|
||||||
|
### Bybit
|
||||||
|
Use for:
|
||||||
|
- real-time-ish price
|
||||||
|
- 24h turnover / volume
|
||||||
|
- tradability check
|
||||||
|
- kline context for listed pairs
|
||||||
|
|
||||||
|
Prefer Bybit first when the coin has a clear CEX symbol like `BTCUSDT`, `ETHUSDT`, `BONKUSDT`, etc.
|
||||||
|
|
||||||
|
### DexScreener
|
||||||
|
Use for:
|
||||||
|
- meme-coin discovery
|
||||||
|
- DEX liquidity / pair context
|
||||||
|
- chain and pool identification
|
||||||
|
- faster read on small-cap or newly-hot coins
|
||||||
|
|
||||||
|
Prefer DexScreener when:
|
||||||
|
- the coin is meme-heavy
|
||||||
|
- it may not be on major CEXs
|
||||||
|
- you need pair/liquidity context more than exchange execution context
|
||||||
|
|
||||||
|
### Birdeye
|
||||||
|
Use for:
|
||||||
|
- Solana meme-coin discovery
|
||||||
|
- Solana token activity and pair context
|
||||||
|
- confirming whether a Solana coin has genuine participation
|
||||||
|
|
||||||
|
Birdeye is especially useful when Solana names appear early in discovery.
|
||||||
|
|
||||||
|
### CoinGecko
|
||||||
|
Use for:
|
||||||
|
- market-cap cross-check
|
||||||
|
- ranking / metadata / basic overview
|
||||||
|
- fallback verification when exchange or DEX data is messy
|
||||||
|
|
||||||
|
Use CoinGecko to sanity-check whether the coin is a real market object with broad coverage.
|
||||||
|
|
||||||
|
## Recommended order
|
||||||
|
|
||||||
|
### For a known Bybit-listed coin
|
||||||
|
1. Bybit
|
||||||
|
2. CoinGecko
|
||||||
|
3. DexScreener if meme angle matters
|
||||||
|
|
||||||
|
### For a meme / 妖币 candidate
|
||||||
|
1. DexScreener
|
||||||
|
2. Birdeye if Solana
|
||||||
|
3. CoinGecko
|
||||||
|
4. Bybit only if it is also listed there
|
||||||
|
|
||||||
|
### For discovery mode
|
||||||
|
1. web_search to gather candidate names
|
||||||
|
2. DexScreener to confirm pair/liquidity reality
|
||||||
|
3. Birdeye for Solana candidates
|
||||||
|
4. CoinGecko for market-cap verification
|
||||||
|
5. Bybit to see whether the name graduated into a major tradable venue
|
||||||
|
|
||||||
|
## What each source answers
|
||||||
|
|
||||||
|
- **Bybit** → "Can I trade it on a major venue, and what does the market look like right now?"
|
||||||
|
- **DexScreener** → "Does it actually have live DEX flow and liquidity?"
|
||||||
|
- **Birdeye** → "Is the Solana on-chain activity real enough to care about?"
|
||||||
|
- **CoinGecko** → "How big is it, and is it broadly recognized?"
|
||||||
|
|
||||||
|
## Practical rule
|
||||||
|
|
||||||
|
Do not make conviction from a single source.
|
||||||
|
|
||||||
|
For high-risk coins, prefer at least two independent checks:
|
||||||
|
- one trading/liquidity source
|
||||||
|
- one metadata/market-cap source
|
||||||
|
|
||||||
|
## Token identity hygiene
|
||||||
|
|
||||||
|
DexScreener search can return clones, stale pairs, and same-name distractions.
|
||||||
|
|
||||||
|
Before treating a result as the real target, prefer the pair that has:
|
||||||
|
- the strongest 24h volume and usable liquidity
|
||||||
|
- a market cap / FDV that roughly matches CoinGecko or other broad coverage sources
|
||||||
|
- a chain and venue context that fits the narrative you are checking
|
||||||
|
|
||||||
|
If search results show multiple same-name tokens, explicitly say which contract or pair you are treating as the primary one.
|
||||||
|
|
||||||
|
## Script usage
|
||||||
|
|
||||||
|
Use `scripts/market_probe.py` for deterministic lookups instead of redoing provider URLs by hand.
|
||||||
63
references/radar-checklist.md
Normal file
63
references/radar-checklist.md
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
# Coin Radar Checklist
|
||||||
|
|
||||||
|
Use this checklist for fast triage.
|
||||||
|
|
||||||
|
## Fast scorecard
|
||||||
|
|
||||||
|
Score each dimension from 0 to 2.
|
||||||
|
|
||||||
|
- **Narrative**
|
||||||
|
- 0 = no clear story or hook
|
||||||
|
- 1 = understandable but weak
|
||||||
|
- 2 = strong, simple, contagious
|
||||||
|
|
||||||
|
- **Attention acceleration**
|
||||||
|
- 0 = stagnant / invisible
|
||||||
|
- 1 = niche chatter rising
|
||||||
|
- 2 = clearly spreading beyond niche
|
||||||
|
|
||||||
|
- **Liquidity**
|
||||||
|
- 0 = poor / suspicious / hard to exit
|
||||||
|
- 1 = usable but thin
|
||||||
|
- 2 = solid enough for speculation
|
||||||
|
|
||||||
|
- **Distribution quality**
|
||||||
|
- 0 = dangerous concentration
|
||||||
|
- 1 = somewhat fragile
|
||||||
|
- 2 = acceptable for a speculative trade
|
||||||
|
|
||||||
|
- **Timing / chart state**
|
||||||
|
- 0 = broken or exhausted
|
||||||
|
- 1 = unclear
|
||||||
|
- 2 = early-to-mid expansion setup
|
||||||
|
|
||||||
|
- **Scam-risk cleanliness**
|
||||||
|
- 0 = obvious warnings
|
||||||
|
- 1 = mixed / uncertain
|
||||||
|
- 2 = no major public red flags found
|
||||||
|
|
||||||
|
## Quick interpretation
|
||||||
|
|
||||||
|
- **10-12** → strong speculative candidate; timing still matters
|
||||||
|
- **7-9** → watchlist material; interesting but incomplete
|
||||||
|
- **4-6** → weak; only for high-risk curiosity
|
||||||
|
- **0-3** → avoid
|
||||||
|
|
||||||
|
## Compact answer template
|
||||||
|
|
||||||
|
- **Verdict:**
|
||||||
|
- **Radar score:** X/12
|
||||||
|
- **Why it’s interesting:**
|
||||||
|
- **Main flaws:**
|
||||||
|
- **What would confirm it:**
|
||||||
|
- **What would invalidate it:**
|
||||||
|
- **Risk note:** speculative only, not investment advice
|
||||||
|
|
||||||
|
## Hard-stop red flags
|
||||||
|
|
||||||
|
If any of these appear, strongly consider overriding the score to avoid:
|
||||||
|
- obvious inability to exit
|
||||||
|
- strong public rug warnings
|
||||||
|
- fake or unverifiable listing/partnership claims
|
||||||
|
- extreme wallet concentration with live dump risk
|
||||||
|
- chart structure that looks purely manipulated
|
||||||
109
references/scam-signals.md
Normal file
109
references/scam-signals.md
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
# Scam / Fake-Hype Signals
|
||||||
|
|
||||||
|
Use this reference when a user asks whether a coin is a rug, scam, fake narrative pump, or suspicious meme coin.
|
||||||
|
|
||||||
|
## Goal
|
||||||
|
|
||||||
|
Separate three different bad cases:
|
||||||
|
- **obvious scam-risk** — high chance of rug, manipulation, or fabricated legitimacy
|
||||||
|
- **fake-hype / low-quality pump** — may trade, but the story is mostly noise and exit liquidity risk is high
|
||||||
|
- **messy but tradable** — ugly structure, but not enough evidence to call it a scam
|
||||||
|
|
||||||
|
Do not collapse all weak coins into "scam." Be precise.
|
||||||
|
|
||||||
|
## Primary red flags
|
||||||
|
|
||||||
|
### 1. Liquidity illusion
|
||||||
|
Warning signs:
|
||||||
|
- the coin appears tradable, but exits are unclear
|
||||||
|
- volume looks large relative to real attention
|
||||||
|
- spreads are erratic or suspiciously wide
|
||||||
|
- price moves hard on small visible participation
|
||||||
|
|
||||||
|
Interpretation:
|
||||||
|
- if buyers can enter more easily than they can exit, treat this as a severe warning
|
||||||
|
|
||||||
|
### 2. Holder concentration risk
|
||||||
|
Warning signs:
|
||||||
|
- a few wallets dominate supply
|
||||||
|
- deployer/team wallets remain powerful
|
||||||
|
- clustered wallets look related
|
||||||
|
- unlock or dump overhang seems obvious
|
||||||
|
|
||||||
|
Interpretation:
|
||||||
|
- concentration does not automatically mean scam, but it makes the coin structurally fragile
|
||||||
|
- if concentration is extreme and active, classify closer to avoid / scam-risk
|
||||||
|
|
||||||
|
### 3. Legitimacy theater
|
||||||
|
Warning signs:
|
||||||
|
- loud claims of partnerships with no verifiable source
|
||||||
|
- fake exchange-listing rumors
|
||||||
|
- website looks polished but contains no falsifiable specifics
|
||||||
|
- team bios are vague, recycled, or unverifiable
|
||||||
|
- social posts overpromise and under-document
|
||||||
|
|
||||||
|
Interpretation:
|
||||||
|
- fake credibility signals are often more important than weak fundamentals
|
||||||
|
|
||||||
|
### 4. Social proof distortion
|
||||||
|
Warning signs:
|
||||||
|
- comments feel repetitive or botted
|
||||||
|
- follower count is high but engagement quality is low
|
||||||
|
- shill accounts post identical talking points
|
||||||
|
- the project feels ubiquitous inside its own bubble but invisible elsewhere
|
||||||
|
|
||||||
|
Interpretation:
|
||||||
|
- hype quality matters more than hype quantity
|
||||||
|
|
||||||
|
### 5. Chart manipulation smell
|
||||||
|
Warning signs:
|
||||||
|
- repeated long wicks without stable follow-through
|
||||||
|
- random explosive candles with no broader market pickup
|
||||||
|
- price repeatedly returns to the same area after dramatic spikes
|
||||||
|
- pattern looks designed to bait breakout traders
|
||||||
|
|
||||||
|
Interpretation:
|
||||||
|
- manufactured excitement often looks different from organic expansion
|
||||||
|
|
||||||
|
## Secondary warning signs
|
||||||
|
|
||||||
|
These do not prove scam by themselves, but they weaken the case:
|
||||||
|
- narrative changes every few days
|
||||||
|
- too many sectors/themes stapled together
|
||||||
|
- tokenomics explanation is confusing on purpose
|
||||||
|
- everything depends on one influencer wave
|
||||||
|
- no credible venue improvement despite heavy promotion
|
||||||
|
|
||||||
|
## Useful distinctions
|
||||||
|
|
||||||
|
### Scam-risk
|
||||||
|
Use when one or more of these are true:
|
||||||
|
- severe exit/liquidity concerns
|
||||||
|
- strong public warnings from multiple independent places
|
||||||
|
- fabricated legitimacy claims look credible
|
||||||
|
- wallet concentration plus active dump risk is severe
|
||||||
|
|
||||||
|
### Fake-hype / low-quality pump
|
||||||
|
Use when:
|
||||||
|
- the coin may still trade, but most of the fuel is shallow attention
|
||||||
|
- quality of discussion is poor
|
||||||
|
- market structure looks weak
|
||||||
|
- timing is bad and late buyers are likely exit liquidity
|
||||||
|
|
||||||
|
### Messy but tradable
|
||||||
|
Use when:
|
||||||
|
- structure is ugly, but not enough to call scam
|
||||||
|
- there is still credible liquidity and real attention
|
||||||
|
- risk is high, but the market is not obviously fake
|
||||||
|
|
||||||
|
## Output guidance
|
||||||
|
|
||||||
|
When scam risk is part of the analysis, include:
|
||||||
|
- **Suspicion level:** low / medium / high
|
||||||
|
- **Main red flags:** 2-5 bullets
|
||||||
|
- **What would reduce suspicion:** specific evidence, not vibes
|
||||||
|
- **Bottom line:** tradable speculation / watch-only / avoid
|
||||||
|
|
||||||
|
## Hard override rule
|
||||||
|
|
||||||
|
Even if the narrative and attention look strong, classify as **avoid / scam-risk** when exit risk or fabricated legitimacy is severe enough.
|
||||||
90
references/search-workflow.md
Normal file
90
references/search-workflow.md
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
# Search Workflow
|
||||||
|
|
||||||
|
Use this workflow when the user wants you to proactively discover meme-coin / 妖币 candidates instead of analyzing a known ticker.
|
||||||
|
|
||||||
|
## Goal
|
||||||
|
|
||||||
|
Produce a shortlist with enough evidence to answer:
|
||||||
|
- what deserves attention now
|
||||||
|
- what is merely noisy
|
||||||
|
- what should be avoided
|
||||||
|
|
||||||
|
## Default search strategy
|
||||||
|
|
||||||
|
Unless the user specifies otherwise, search for **liquid speculative candidates** first and avoid ultra-microcaps.
|
||||||
|
|
||||||
|
Run search in this order:
|
||||||
|
|
||||||
|
1. **Theme scan**
|
||||||
|
- Search current meme-coin themes by chain or narrative
|
||||||
|
- Examples:
|
||||||
|
- `Solana meme coins trending`
|
||||||
|
- `Base meme coin watchlist`
|
||||||
|
- `AI meme coin trending`
|
||||||
|
- `new meme coin listed today`
|
||||||
|
|
||||||
|
2. **Candidate extraction**
|
||||||
|
- Pull out repeated names that appear across multiple sources
|
||||||
|
- Prefer coins that appear in both market-oriented and community-oriented sources
|
||||||
|
|
||||||
|
3. **Candidate verification**
|
||||||
|
- For each candidate, search:
|
||||||
|
- `<coin> market cap liquidity`
|
||||||
|
- `<coin> holders tokenomics`
|
||||||
|
- `<coin> rug risk`
|
||||||
|
- `<coin> listed on exchange`
|
||||||
|
|
||||||
|
4. **Cross-check timing**
|
||||||
|
- Search whether the coin is already broadly saturated:
|
||||||
|
- `<coin> trending X`
|
||||||
|
- `<coin> breakout volume`
|
||||||
|
- `<coin> price surge`
|
||||||
|
- If it is already universally discussed, consider classifying it as late rather than early
|
||||||
|
|
||||||
|
## Source preference
|
||||||
|
|
||||||
|
Prefer a mix of:
|
||||||
|
- credible exchange announcements or listing pages
|
||||||
|
- market data summaries
|
||||||
|
- crypto news aggregation
|
||||||
|
- community/trading discussion summaries
|
||||||
|
|
||||||
|
Do not rely entirely on project websites or obvious promotion pages.
|
||||||
|
|
||||||
|
## Discovery rules
|
||||||
|
|
||||||
|
### Good candidate signs during search
|
||||||
|
- name appears repeatedly across different sources
|
||||||
|
- tied to a live narrative or active chain
|
||||||
|
- discussion suggests recent acceleration, not just old fame
|
||||||
|
- accessible enough that the user can realistically trade it
|
||||||
|
|
||||||
|
### Weak candidate signs during search
|
||||||
|
- only appears in promotional pages
|
||||||
|
- only appears on tiny venues
|
||||||
|
- no independent discussion or market data context
|
||||||
|
- most results are already about an explosive move that happened days ago
|
||||||
|
|
||||||
|
## Shortlist size
|
||||||
|
|
||||||
|
Default to **3-5 candidates**.
|
||||||
|
|
||||||
|
If the search returns many names:
|
||||||
|
- keep the most repeated
|
||||||
|
- keep the ones with the clearest narrative
|
||||||
|
- remove obviously illiquid or scammy names first
|
||||||
|
|
||||||
|
## Output shape for discovery mode
|
||||||
|
|
||||||
|
For each shortlisted candidate include:
|
||||||
|
- ticker / name
|
||||||
|
- chain / venue context if known
|
||||||
|
- why it entered the shortlist
|
||||||
|
- biggest risk
|
||||||
|
- tentative bucket: candidate runner / watch-only / avoid
|
||||||
|
|
||||||
|
Then give a final rank order.
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
When evidence is weak, say so. Discovery mode is for narrowing attention, not pretending certainty.
|
||||||
143
references/user-data-layout.md
Normal file
143
references/user-data-layout.md
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
# User Data Layout
|
||||||
|
|
||||||
|
Store private coin-hunter data outside the skill directory.
|
||||||
|
|
||||||
|
## Root directory
|
||||||
|
|
||||||
|
Use:
|
||||||
|
|
||||||
|
```text
|
||||||
|
~/.coin-hunter/
|
||||||
|
```
|
||||||
|
|
||||||
|
This keeps personal accounts, positions, and watchlists out of packaged skill artifacts.
|
||||||
|
|
||||||
|
## Layout
|
||||||
|
|
||||||
|
```text
|
||||||
|
~/.coin-hunter/
|
||||||
|
├── config.json
|
||||||
|
├── accounts.json
|
||||||
|
├── positions.json
|
||||||
|
├── watchlist.json
|
||||||
|
├── notes.json
|
||||||
|
└── cache/
|
||||||
|
```
|
||||||
|
|
||||||
|
## File roles
|
||||||
|
|
||||||
|
### config.json
|
||||||
|
Store user-level defaults.
|
||||||
|
|
||||||
|
Suggested fields:
|
||||||
|
- `default_exchange`
|
||||||
|
- `default_quote_currency`
|
||||||
|
- `timezone`
|
||||||
|
- `preferred_chains`
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"default_exchange": "bybit",
|
||||||
|
"default_quote_currency": "USDT",
|
||||||
|
"timezone": "Asia/Shanghai",
|
||||||
|
"preferred_chains": ["solana", "base"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### accounts.json
|
||||||
|
Store exchange accounts and balances.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"accounts": [
|
||||||
|
{
|
||||||
|
"id": "bybit-main",
|
||||||
|
"exchange": "bybit",
|
||||||
|
"label": "Bybit Main",
|
||||||
|
"currency": "USDT",
|
||||||
|
"cash_balance": 0,
|
||||||
|
"available_cash": 0,
|
||||||
|
"updated_at": null,
|
||||||
|
"note": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### positions.json
|
||||||
|
Store coin positions.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"positions": [
|
||||||
|
{
|
||||||
|
"account_id": "bybit-main",
|
||||||
|
"symbol": "BTCUSDT",
|
||||||
|
"base_asset": "BTC",
|
||||||
|
"quote_asset": "USDT",
|
||||||
|
"market_type": "spot",
|
||||||
|
"quantity": 0,
|
||||||
|
"avg_cost": 0,
|
||||||
|
"opened_at": null,
|
||||||
|
"updated_at": null,
|
||||||
|
"note": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### watchlist.json
|
||||||
|
Store watched coins.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"watchlist": [
|
||||||
|
{
|
||||||
|
"symbol": "FARTCOIN",
|
||||||
|
"chain": "solana",
|
||||||
|
"contract_address": null,
|
||||||
|
"source": "manual",
|
||||||
|
"status": "watching",
|
||||||
|
"added_at": null,
|
||||||
|
"note": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### notes.json
|
||||||
|
Store discretionary notes and thesis fragments.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"notes": [
|
||||||
|
{
|
||||||
|
"symbol": "FARTCOIN",
|
||||||
|
"title": "Why this stays on radar",
|
||||||
|
"body": "Good liquidity, strong meme spread, only for high-risk observation.",
|
||||||
|
"updated_at": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### cache/
|
||||||
|
Store disposable API results or normalized snapshots. Never treat this as source-of-truth portfolio state.
|
||||||
|
|
||||||
|
## Rules
|
||||||
|
|
||||||
|
- Keep personal data only under `~/.coin-hunter/`
|
||||||
|
- Never write personal account or position data into `skills/coin-hunter/`
|
||||||
|
- Treat `cache/` as disposable
|
||||||
|
- Prefer stable IDs for accounts like `bybit-main`
|
||||||
|
- For meme coins, include `chain` and `contract_address` when known
|
||||||
63
scripts/init_user_state.py
Normal file
63
scripts/init_user_state.py
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
import json
|
||||||
|
from datetime import datetime, timezone
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
ROOT = Path.home() / ".coin-hunter"
|
||||||
|
CACHE_DIR = ROOT / "cache"
|
||||||
|
|
||||||
|
|
||||||
|
def now_iso():
|
||||||
|
return datetime.now(timezone.utc).replace(microsecond=0).isoformat()
|
||||||
|
|
||||||
|
|
||||||
|
def ensure_file(path: Path, payload: dict):
|
||||||
|
if path.exists():
|
||||||
|
return False
|
||||||
|
path.write_text(json.dumps(payload, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
ROOT.mkdir(parents=True, exist_ok=True)
|
||||||
|
CACHE_DIR.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
created = []
|
||||||
|
ts = now_iso()
|
||||||
|
|
||||||
|
templates = {
|
||||||
|
ROOT / "config.json": {
|
||||||
|
"default_exchange": "bybit",
|
||||||
|
"default_quote_currency": "USDT",
|
||||||
|
"timezone": "Asia/Shanghai",
|
||||||
|
"preferred_chains": ["solana", "base"],
|
||||||
|
"created_at": ts,
|
||||||
|
"updated_at": ts,
|
||||||
|
},
|
||||||
|
ROOT / "accounts.json": {
|
||||||
|
"accounts": []
|
||||||
|
},
|
||||||
|
ROOT / "positions.json": {
|
||||||
|
"positions": []
|
||||||
|
},
|
||||||
|
ROOT / "watchlist.json": {
|
||||||
|
"watchlist": []
|
||||||
|
},
|
||||||
|
ROOT / "notes.json": {
|
||||||
|
"notes": []
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for path, payload in templates.items():
|
||||||
|
if ensure_file(path, payload):
|
||||||
|
created.append(str(path))
|
||||||
|
|
||||||
|
print(json.dumps({
|
||||||
|
"root": str(ROOT),
|
||||||
|
"created": created,
|
||||||
|
"cache_dir": str(CACHE_DIR),
|
||||||
|
}, ensure_ascii=False, indent=2))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
243
scripts/market_probe.py
Normal file
243
scripts/market_probe.py
Normal file
@@ -0,0 +1,243 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
import argparse
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import urllib.parse
|
||||||
|
import urllib.request
|
||||||
|
|
||||||
|
DEFAULT_TIMEOUT = 20
|
||||||
|
|
||||||
|
|
||||||
|
def fetch_json(url, headers=None, timeout=DEFAULT_TIMEOUT):
|
||||||
|
merged_headers = {
|
||||||
|
"Accept": "application/json",
|
||||||
|
"User-Agent": "Mozilla/5.0 (compatible; OpenClaw Coin Hunter/1.0)",
|
||||||
|
}
|
||||||
|
if headers:
|
||||||
|
merged_headers.update(headers)
|
||||||
|
req = urllib.request.Request(url, headers=merged_headers)
|
||||||
|
with urllib.request.urlopen(req, timeout=timeout) as resp:
|
||||||
|
data = resp.read()
|
||||||
|
return json.loads(data.decode("utf-8"))
|
||||||
|
|
||||||
|
|
||||||
|
def print_json(data):
|
||||||
|
print(json.dumps(data, ensure_ascii=False, indent=2))
|
||||||
|
|
||||||
|
|
||||||
|
def bybit_ticker(symbol: str):
|
||||||
|
url = (
|
||||||
|
"https://api.bybit.com/v5/market/tickers?category=spot&symbol="
|
||||||
|
+ urllib.parse.quote(symbol.upper())
|
||||||
|
)
|
||||||
|
payload = fetch_json(url)
|
||||||
|
items = payload.get("result", {}).get("list", [])
|
||||||
|
if not items:
|
||||||
|
raise SystemExit(f"No Bybit spot ticker found for {symbol}")
|
||||||
|
item = items[0]
|
||||||
|
out = {
|
||||||
|
"provider": "bybit",
|
||||||
|
"symbol": symbol.upper(),
|
||||||
|
"lastPrice": item.get("lastPrice"),
|
||||||
|
"price24hPcnt": item.get("price24hPcnt"),
|
||||||
|
"highPrice24h": item.get("highPrice24h"),
|
||||||
|
"lowPrice24h": item.get("lowPrice24h"),
|
||||||
|
"turnover24h": item.get("turnover24h"),
|
||||||
|
"volume24h": item.get("volume24h"),
|
||||||
|
"bid1Price": item.get("bid1Price"),
|
||||||
|
"ask1Price": item.get("ask1Price"),
|
||||||
|
}
|
||||||
|
print_json(out)
|
||||||
|
|
||||||
|
|
||||||
|
def bybit_klines(symbol: str, interval: str, limit: int):
|
||||||
|
params = urllib.parse.urlencode({
|
||||||
|
"category": "spot",
|
||||||
|
"symbol": symbol.upper(),
|
||||||
|
"interval": interval,
|
||||||
|
"limit": str(limit),
|
||||||
|
})
|
||||||
|
url = f"https://api.bybit.com/v5/market/kline?{params}"
|
||||||
|
payload = fetch_json(url)
|
||||||
|
rows = payload.get("result", {}).get("list", [])
|
||||||
|
out = {
|
||||||
|
"provider": "bybit",
|
||||||
|
"symbol": symbol.upper(),
|
||||||
|
"interval": interval,
|
||||||
|
"candles": [
|
||||||
|
{
|
||||||
|
"startTime": r[0],
|
||||||
|
"open": r[1],
|
||||||
|
"high": r[2],
|
||||||
|
"low": r[3],
|
||||||
|
"close": r[4],
|
||||||
|
"volume": r[5],
|
||||||
|
"turnover": r[6],
|
||||||
|
}
|
||||||
|
for r in rows
|
||||||
|
],
|
||||||
|
}
|
||||||
|
print_json(out)
|
||||||
|
|
||||||
|
|
||||||
|
def dexscreener_search(query: str):
|
||||||
|
url = "https://api.dexscreener.com/latest/dex/search/?q=" + urllib.parse.quote(query)
|
||||||
|
payload = fetch_json(url)
|
||||||
|
pairs = payload.get("pairs") or []
|
||||||
|
out = []
|
||||||
|
for p in pairs[:10]:
|
||||||
|
out.append({
|
||||||
|
"chainId": p.get("chainId"),
|
||||||
|
"dexId": p.get("dexId"),
|
||||||
|
"pairAddress": p.get("pairAddress"),
|
||||||
|
"url": p.get("url"),
|
||||||
|
"baseToken": p.get("baseToken"),
|
||||||
|
"quoteToken": p.get("quoteToken"),
|
||||||
|
"priceUsd": p.get("priceUsd"),
|
||||||
|
"liquidityUsd": (p.get("liquidity") or {}).get("usd"),
|
||||||
|
"fdv": p.get("fdv"),
|
||||||
|
"marketCap": p.get("marketCap"),
|
||||||
|
"volume24h": (p.get("volume") or {}).get("h24"),
|
||||||
|
"buys24h": ((p.get("txns") or {}).get("h24") or {}).get("buys"),
|
||||||
|
"sells24h": ((p.get("txns") or {}).get("h24") or {}).get("sells"),
|
||||||
|
})
|
||||||
|
print_json({"provider": "dexscreener", "query": query, "pairs": out})
|
||||||
|
|
||||||
|
|
||||||
|
def dexscreener_token(chain: str, address: str):
|
||||||
|
url = f"https://api.dexscreener.com/tokens/v1/{urllib.parse.quote(chain)}/{urllib.parse.quote(address)}"
|
||||||
|
payload = fetch_json(url)
|
||||||
|
pairs = payload if isinstance(payload, list) else payload.get("pairs") or []
|
||||||
|
out = []
|
||||||
|
for p in pairs[:10]:
|
||||||
|
out.append({
|
||||||
|
"chainId": p.get("chainId"),
|
||||||
|
"dexId": p.get("dexId"),
|
||||||
|
"pairAddress": p.get("pairAddress"),
|
||||||
|
"baseToken": p.get("baseToken"),
|
||||||
|
"quoteToken": p.get("quoteToken"),
|
||||||
|
"priceUsd": p.get("priceUsd"),
|
||||||
|
"liquidityUsd": (p.get("liquidity") or {}).get("usd"),
|
||||||
|
"fdv": p.get("fdv"),
|
||||||
|
"marketCap": p.get("marketCap"),
|
||||||
|
"volume24h": (p.get("volume") or {}).get("h24"),
|
||||||
|
})
|
||||||
|
print_json({"provider": "dexscreener", "chain": chain, "address": address, "pairs": out})
|
||||||
|
|
||||||
|
|
||||||
|
def coingecko_search(query: str):
|
||||||
|
url = "https://api.coingecko.com/api/v3/search?query=" + urllib.parse.quote(query)
|
||||||
|
payload = fetch_json(url)
|
||||||
|
coins = payload.get("coins") or []
|
||||||
|
out = []
|
||||||
|
for c in coins[:10]:
|
||||||
|
out.append({
|
||||||
|
"id": c.get("id"),
|
||||||
|
"name": c.get("name"),
|
||||||
|
"symbol": c.get("symbol"),
|
||||||
|
"marketCapRank": c.get("market_cap_rank"),
|
||||||
|
"thumb": c.get("thumb"),
|
||||||
|
})
|
||||||
|
print_json({"provider": "coingecko", "query": query, "coins": out})
|
||||||
|
|
||||||
|
|
||||||
|
def coingecko_coin(coin_id: str):
|
||||||
|
params = urllib.parse.urlencode({
|
||||||
|
"localization": "false",
|
||||||
|
"tickers": "false",
|
||||||
|
"market_data": "true",
|
||||||
|
"community_data": "false",
|
||||||
|
"developer_data": "false",
|
||||||
|
"sparkline": "false",
|
||||||
|
})
|
||||||
|
url = f"https://api.coingecko.com/api/v3/coins/{urllib.parse.quote(coin_id)}?{params}"
|
||||||
|
payload = fetch_json(url)
|
||||||
|
md = payload.get("market_data") or {}
|
||||||
|
out = {
|
||||||
|
"provider": "coingecko",
|
||||||
|
"id": payload.get("id"),
|
||||||
|
"symbol": payload.get("symbol"),
|
||||||
|
"name": payload.get("name"),
|
||||||
|
"marketCapRank": payload.get("market_cap_rank"),
|
||||||
|
"currentPriceUsd": (md.get("current_price") or {}).get("usd"),
|
||||||
|
"marketCapUsd": (md.get("market_cap") or {}).get("usd"),
|
||||||
|
"fullyDilutedValuationUsd": (md.get("fully_diluted_valuation") or {}).get("usd"),
|
||||||
|
"totalVolumeUsd": (md.get("total_volume") or {}).get("usd"),
|
||||||
|
"priceChangePercentage24h": md.get("price_change_percentage_24h"),
|
||||||
|
"priceChangePercentage7d": md.get("price_change_percentage_7d"),
|
||||||
|
"priceChangePercentage30d": md.get("price_change_percentage_30d"),
|
||||||
|
"circulatingSupply": md.get("circulating_supply"),
|
||||||
|
"totalSupply": md.get("total_supply"),
|
||||||
|
"maxSupply": md.get("max_supply"),
|
||||||
|
"homepage": (payload.get("links") or {}).get("homepage", [None])[0],
|
||||||
|
}
|
||||||
|
print_json(out)
|
||||||
|
|
||||||
|
|
||||||
|
def birdeye_token(address: str):
|
||||||
|
api_key = os.getenv("BIRDEYE_API_KEY") or os.getenv("BIRDEYE_APIKEY")
|
||||||
|
if not api_key:
|
||||||
|
raise SystemExit("Birdeye requires BIRDEYE_API_KEY in the environment")
|
||||||
|
url = "https://public-api.birdeye.so/defi/token_overview?address=" + urllib.parse.quote(address)
|
||||||
|
payload = fetch_json(url, headers={
|
||||||
|
"x-api-key": api_key,
|
||||||
|
"x-chain": "solana",
|
||||||
|
})
|
||||||
|
print_json({"provider": "birdeye", "address": address, "data": payload.get("data")})
|
||||||
|
|
||||||
|
|
||||||
|
def build_parser():
|
||||||
|
parser = argparse.ArgumentParser(description="Coin Hunter market data probe")
|
||||||
|
sub = parser.add_subparsers(dest="command", required=True)
|
||||||
|
|
||||||
|
p = sub.add_parser("bybit-ticker", help="Fetch Bybit spot ticker")
|
||||||
|
p.add_argument("symbol")
|
||||||
|
|
||||||
|
p = sub.add_parser("bybit-klines", help="Fetch Bybit spot klines")
|
||||||
|
p.add_argument("symbol")
|
||||||
|
p.add_argument("--interval", default="60", help="Bybit interval, e.g. 1, 5, 15, 60, 240, D")
|
||||||
|
p.add_argument("--limit", type=int, default=10)
|
||||||
|
|
||||||
|
p = sub.add_parser("dex-search", help="Search DexScreener by query")
|
||||||
|
p.add_argument("query")
|
||||||
|
|
||||||
|
p = sub.add_parser("dex-token", help="Fetch DexScreener token pairs by chain/address")
|
||||||
|
p.add_argument("chain")
|
||||||
|
p.add_argument("address")
|
||||||
|
|
||||||
|
p = sub.add_parser("gecko-search", help="Search CoinGecko")
|
||||||
|
p.add_argument("query")
|
||||||
|
|
||||||
|
p = sub.add_parser("gecko-coin", help="Fetch CoinGecko coin by id")
|
||||||
|
p.add_argument("coin_id")
|
||||||
|
|
||||||
|
p = sub.add_parser("birdeye-token", help="Fetch Birdeye token overview (Solana)")
|
||||||
|
p.add_argument("address")
|
||||||
|
|
||||||
|
return parser
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = build_parser()
|
||||||
|
args = parser.parse_args()
|
||||||
|
if args.command == "bybit-ticker":
|
||||||
|
bybit_ticker(args.symbol)
|
||||||
|
elif args.command == "bybit-klines":
|
||||||
|
bybit_klines(args.symbol, args.interval, args.limit)
|
||||||
|
elif args.command == "dex-search":
|
||||||
|
dexscreener_search(args.query)
|
||||||
|
elif args.command == "dex-token":
|
||||||
|
dexscreener_token(args.chain, args.address)
|
||||||
|
elif args.command == "gecko-search":
|
||||||
|
coingecko_search(args.query)
|
||||||
|
elif args.command == "gecko-coin":
|
||||||
|
coingecko_coin(args.coin_id)
|
||||||
|
elif args.command == "birdeye-token":
|
||||||
|
birdeye_token(args.address)
|
||||||
|
else:
|
||||||
|
parser.error("Unknown command")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Reference in New Issue
Block a user