YouMind
Se connecter

Grok Bot de zéro en une nuit : configuration complète + filtre anti-rug copier-coller

@0xboan
ANGLAIS17 oct. 2026
126K
139
19
20
439

TL;DR

Ce guide détaille la création d'un bureau de trading Grok Bot à partir de rien, en mettant l'accent sur un filtre anti-rug rigoureux en 14 étapes pour éliminer les tokens frauduleux avant l'exécution. Il souligne le flux de travail « le code tue, Grok lit, vous signez » avec des garde-fous de paper trading.

la plupart des gens découvrent Grok Bot via la capture d'écran de PnL de quelqu'un d'autre, l'ouvrent, le pointent sur un graphique et perdent leurs premiers 50 $ sur un token qui était déjà mort avant même qu'ils ne l'achètent. le problème n'était pas le bot. personne ne lui avait expliqué à quoi ressemble un token mort.

voici la configuration que je reconstruirais ce soir si je devais tout reprendre à zéro. un bot, un dossier, dix petits fichiers. il ne chasse pas les x100. son rôle principal est d'éliminer des tokens, et les rares qui survivent ont encore besoin que Grok lise X avant que le moindre dollar ne bouge.

les étapes 01 à 07 correspondent à la première soirée : le bot, la clé, les limites, les sorties. de 08 à 12, c'est le filtre anti-rug, 14 vérifications, chacune écrite sous forme de code. 13 et 14 mettent le tout en pilote automatique, d'abord sur le papier.

si vous avez lu mon article sur le desk à huit agents, voici le socle sur lequel ce desk repose.

https://x.com/0xboan/status/2092226208234647626

comment l'utiliser : ouvrez votre Grok Bot, collez l'intégralité de cet article et dites « construis ce desk dans /workspace/desk, mode paper, demande-moi avant que quoi que ce soit touche un wallet. » il écrit chaque fichier lui-même, sur son propre ordinateur.

la règle d'or à retenir : le code élimine, Grok lit X, vous signez. personne sur le desk ne fait le travail d'un autre.

01. réunissez quatre choses avant de commencer

quatre choses. pour chacune : ce que c'est, ce que vous faites ce soir, et pourquoi le desk en a besoin.

1. Grok Bot

ce que c'est. l'application où vous embauchez des bots nommés. chacun travaille sur un ordinateur cloud équipé d'un navigateur, de fichiers et d'un terminal, et continue de tourner même quand votre PC portable est fermé.

ce que vous faites. téléchargez-le sur x.ai/bot, connectez-vous, choisissez Create your own.

pourquoi. tout le desk vit sur cet ordinateur. fichiers, routines, alertes, tout est au même endroit, accessible depuis votre téléphone.

2. une clé API xAI

ce que c'est. un accès payant à Grok depuis du code, avec la recherche X intégrée.

ce que vous faites. allez sur console.x.ai, API Keys, créez-en une. ne la collez nulle part pour l'instant, l'étape 03 indique où elle va.

pourquoi. une routine ne peut pas rester assise à réfléchir sur quarante tokens dans un chat. un script qui fait un appel par token le peut, et il journalise chaque réponse dans le même format.

3. Rugcheck et DexScreener

ce que c'est. deux API publiques gratuites. Rugcheck lit le contrat : autorités, LP, holders, insiders, le wallet du dev. DexScreener lit la pool : profondeur, ancienneté, achats contre ventes.

ce que vous faites. rien. pas d'inscription, pas de clé pour les lectures.

pourquoi. les faits passent avant les opinions. une autorité de mint ouverte n'est pas une question de jugement, c'est un fait, et ce sont les faits qui tuent en premier.

4. un burner wallet, mais pas ce soir

ce que c'est. un wallet Solana tout neuf qui n'a jamais rien contenu d'autre.

ce que vous faites. rien pour l'instant. la première semaine se joue sur le papier.

pourquoi. le desk ne détient jamais de clé. quand vous passerez en live, il vous dira quoi acheter et vous signerez vous-même.

02. embauchez un seul bot, pas huit

mon desk fait tourner huit bots aujourd'hui. ça n'a pas commencé comme ça, et le vôtre ne devrait pas non plus. huit bots dès le premier jour, c'est huit trucs à débugger en même temps. un bot avec une seule mission vous montrera ce dont les sept autres auront besoin plus tard.

choisissez Create your own et donnez-lui ceci, mot pour mot :

text
1Nom : RUG DESK
2Mission : Desk memecoin Solana, d'abord sur le papier
3Description : Construis et fais tourner le desk dans /workspace/desk à partir de l'article que je colle.
4Chaque token passe par check.py, sans exception, sans raccourci.
5Tu n'achètes, ne vends, ne signes ni ne déplaces jamais de fonds. Tu ne modifies jamais config.py sauf si je te le demande
6dans ce chat. Tu n'abaisses jamais un seuil de filtre pour laisser passer un token.
7Signale chaque élimination avec sa raison, pas ton opinion sur le token.
8Quand une source est hors ligne, dis laquelle et passe. Ne devine jamais un chiffre manquant.

les deux dernières lignes comptent plus que les cinq premières. un bot qui devine un chiffre manquant finira par en deviner un qui vous coûtera cher.

boan - inline image

03. gardez la clé hors du chat

tout ce que vous tapez à un bot atterrit dans un historique. la clé doit donc aller dans un fichier, tapée par vous, sur l'ordinateur du bot.

ouvrez l'ordinateur du bot, cliquez sur Take over, ouvrez le terminal et lancez ceci. la commande demande la clé sans l'afficher, elle n'apparaîtra donc pas non plus dans l'historique :

bash
1mkdir -p /workspace/desk && cd /workspace/desk
2read -rs -p "xai key: " K && printf 'XAI_API_KEY=%s\n' "$K" > .env && unset K
3chmod 600 .env
4pip install requests

ensuite, prouvez que la clé fonctionne avant toute chose. un seul appel, pour ne jamais confondre plus tard une mauvaise clé avec un mauvais prompt :

bash
1curl -s https://api.x.ai/v1/responses \
2 -H "Authorization: Bearer $(cut -d= -f2 .env)" \
3 -H "Content-Type: application/json" \
4 -d '{"model":"grok-4.7","input":"reply with OK"}'
5
6-> ... "type":"output_text","text":"OK" ...

cliquez sur I'm done et rendez-lui l'ordinateur. à partir de là, le bot peut faire tourner le desk, sans jamais voir la clé dans le chat.

boan - inline image

04. visualisez tout l'entonnoir avant d'en construire la moindre partie

huit passes. les gratuites tournent en premier. seul ce qui survit aux passes gratuites coûte un appel Grok, et seul ce que Grok marque BUY coûte de l'argent. cette semaine, même pas.

text
10. PISTE un CA venu de n'importe où : un appel, un post, scan.py -> un mint
21. LIMITES book.py : perte quotidienne, slots ouverts, cooldown -> gratuit, aucun réseau
32. FAITS rugcheck.py : 10 éliminations sèches -> mint ouvert, LP déverrouillée, top 10 trop lourd meurent ici
43. POOL market.py : profondeur, ancienneté, ventes -> pools fines et honeypots meurent ici
54. JUGE grok.py + recherche X, un appel -> BUY ou SKIP, une raison, un risque
65. FILL paper : book.py au prix live -> live : vous signez vous-même
76. SUIVI watch.py toutes les 10 minutes -> stop, ladder, trail, time stop
87. RAPPORT report.py à 21h30 -> ce qui est mort, ce qui a payé, ce qu'il faut remettre en question

une autorité de mint ouverte n'est pas une question de jugement. c'est un fait, et les faits sont gratuits. Grok ne voit jamais que les tokens ayant déjà passé toutes les vérifications qu'un script peut faire.

boan - inline image

05. mettez tous les chiffres dans un seul fichier

enregistrez sous config.py. tous les chiffres du desk vivent ici, ainsi quand vous réajustez, vous ne modifiez qu'un seul fichier. voici les miens, réglés pour un ticket de 25 $. ce n'est pas une recommandation, c'est un point de départ que vous ferez évoluer.

python
1# config.py
2# tous les chiffres du desk vivent ici. quand vous réajustez, vous ne modifiez que ce fichier.
3
4MODEL = "grok-4.7" # vérifiez console.x.ai -> Models si l'API le rejette
5PAPER = True # semaine 1 : exécutions fictives aux prix réels. ne changez qu'après avoir lu le log
6
7TICKET_USD = 25 # fixe. jamais calibré sur le dernier gain
8MAX_OPEN = 4 # 4 x 25 $ = 100 $ max sur le marché
9MAX_ENTRIES_PER_DAY = 6
10DAILY_LOSS_HALT_USD = 50 # perte réalisée du jour atteint ça -> aucune nouvelle entrée avant demain
11COOLDOWN_HOURS = 24 # pas de retour sur un token que vous venez de quitter
12
13FACTS = { # le filtre anti-rug. code uniquement, aucun modèle
14 "max_risk_score": 40, # score_normalised rugcheck, 0-100, plus haut = plus risqué
15 "min_lp_locked_pct": 90, # plus grosse pool : LP verrouillée ou brûlée
16 "max_top10_pct": 30, # top 10 holders, pools et lockers exclus
17 "max_dev_pct": 5, # supply encore sur le wallet du créateur
18 "max_insiders": 0, # holders flaggés insiders + hits du graphe insider
19 "min_liquidity_usd": 30000,
20 "max_ticket_share": 0.01, # votre ticket ne dépasse jamais 1 % de la pool
21 "min_age_min": 30, # plus jeune que ça, chaque rapport relève encore de la devinette
22 "max_age_hours": 72,
23}
24
25MIN_CONFIDENCE = 0.7 # si Grok dit BUY en dessous de ça -> traité comme SKIP
26
27EXIT = {
28 "stop_pct": -35, # stop sec depuis l'entrée
29 "ladder": [(100, 0.50), (200, 0.25)], # +100 % vend la moitié, +200 % vend un quart
30 "trail_pct": 30, # le reste : sortie quand le prix chute de 30 % depuis son sommet
31 "time_stop_hours": 6, # pas +20 % après 6 heures -> sortie, argent mort
32 "time_stop_min_pct": 20,
33 "liq_drop_pct": 40, # liquidité de la pool en baisse de 40 % depuis l'entrée -> sortie immédiate
34}
35
36LOG = "checks.csv"
37POSITIONS = "positions.json"
38TRADES = "trades.csv"
text
1TICKET FIXE. la taille n'augmente jamais parce que les trois derniers ont gagné.
2LE BOT LIT config.py, IL NE L'ÉCRIT JAMAIS. un chiffre bouge uniquement quand vous le bougez.
3UN FILTRE EST ASSOUPLI PAR ÉCRIT. vous changez un chiffre, vous expliquez pourquoi dans le chat, le jour même.

06. lancez les limites avant toute chose

enregistrez sous book.py. la vérification la moins chère du desk est celle qui n'appelle aucune API. si la journée a déjà perdu 50 $, le desk ne regarde même pas le token. si quatre positions sont ouvertes, pareil. ce fichier est aussi la mémoire du desk : deux fichiers que vous pouvez ouvrir vous-même, positions.json et trades.csv.

python
1# book.py
2# positions, trades, limites. la mémoire du desk vit dans deux fichiers que vous pouvez ouvrir vous-même.
3import csv, json, os, sys, time
4from config import (POSITIONS, TRADES, TICKET_USD, MAX_OPEN, MAX_ENTRIES_PER_DAY,
5 DAILY_LOSS_HALT_USD, COOLDOWN_HOURS)
6
7def load() -> dict:
8 return json.load(open(POSITIONS)) if os.path.exists(POSITIONS) else {}
9
10def save(book: dict):
11 json.dump(book, open(POSITIONS, "w"), indent=2)
12
13def trades() -> list[dict]:
14 return list(csv.DictReader(open(TRADES))) if os.path.exists(TRADES) else []
15
16def record(mint, symbol, action, usd, pnl, reason):
17 new = not os.path.exists(TRADES)
18 with open(TRADES, "a", newline="") as f:
19 w = csv.DictWriter(f, fieldnames=["time", "mint", "symbol", "action", "usd", "pnl", "reason"])
20 if new:
21 w.writeheader()
22 w.writerow({"time": time.strftime("%Y-%m-%d %H:%M"), "mint": mint, "symbol": symbol,
23 "action": action, "usd": round(usd, 2), "pnl": round(pnl, 2), "reason": reason})
24
25def today_pnl() -> float:
26 day = time.strftime("%Y-%m-%d")
27 return sum(float(t["pnl"]) for t in trades() if t["time"].startswith(day))
28
29def guard(mint: str) -> str | None:
30 """Les limites tournent avant tout appel réseau. Une entrée bloquée ne coûte rien."""
31 day = time.strftime("%Y-%m-%d")
32 book = load()
33 if today_pnl() <= -DAILY_LOSS_HALT_USD: return "halted_daily_loss"
34 if mint in book: return "already_open"
35 if len(book) >= MAX_OPEN: return "max_open"
36 opens = [t for t in trades() if t["action"] == "open" and t["time"].startswith(day)]
37 if len(opens) >= MAX_ENTRIES_PER_DAY: return "max_entries_today"
38 cutoff = time.strftime("%Y-%m-%d %H:%M", time.localtime(time.time() - COOLDOWN_HOURS * 3600))
39 if any(t["mint"] == mint and t["action"] == "close" and t["time"] >= cutoff for t in trades()):
40 return "cooldown"
41 return None
42
43def open_position(mint, symbol, price, liq_usd, usd=TICKET_USD):
44 book = load()
45 book[mint] = {"symbol": symbol, "entry": price, "qty0": usd / price, "qty": usd / price,
46 "peak": price, "liq0": liq_usd, "opened": time.time(), "steps": 0}
47 save(book)
48 record(mint, symbol, "open", usd, 0, "entry")
49
50def sell(mint, frac_of_original, price, reason) -> float:
51 """Vend une fraction de la TAILLE INITIALE (1.0 = tout ce qui reste). Retourne le pnl réalisé."""
52 book = load()
53 p = book[mint]
54 q = min(p["qty"], p["qty0"] * frac_of_original)
55 pnl = q * (price - p["entry"])
56 p["qty"] -= q
57 action = "close" if p["qty"] <= p["qty0"] * 1e-6 else "partial"
58 record(mint, p["symbol"], action, q * price, pnl, reason)
59 if action == "close":
60 del book[mint]
61 save(book)
62 return pnl
63
64if __name__ == "__main__":
65 # mode live : après avoir acheté sur votre propre wallet -> python book.py add <mint> <usd> <price> <liq_usd>
66 # après avoir vendu à la main -> python book.py close <mint> <price>
67 cmd = sys.argv[1]
68 if cmd == "add":
69 mint, usd, price, liq = sys.argv[2], float(sys.argv[3]), float(sys.argv[4]), float(sys.argv[5])
70 open_position(mint, mint[:6], price, liq, usd)
71 elif cmd == "close":
72 print(round(sell(sys.argv[2], 1.0, float(sys.argv[3]), "manual"), 2))

07. écrivez la sortie avant l'entrée

la plupart des gens décident quand vendre en fixant une bougie verte. c'est le pire moment pour décider de quoi que ce soit. sur ce desk, chaque sortie existe avant que le token ne soit acheté, et le bot se contente de vérifier toutes les 10 minutes :

  • liquidité retirée de 40 % depuis l'entrée : sortie, tout, sans poser de questions
  • -35 % : sortie
  • +100 % : la moitié sort, le reste est l'argent du marché
  • +200 % : un autre quart sort
  • après la première prise de profit, le reste sort quand le prix chute de 30 % depuis son sommet
  • six heures sans +20 % : sortie, le slot vaut plus que l'espoir

enregistrez sous watch.py :

python
1# watch.py
2# chaque position ouverte, toutes les 10 minutes. n'imprime rien si rien n'a changé.
3import time
4from config import EXIT, PAPER
5from market import pool
6import book
7
8def watch() -> list[str]:
9 events = []
10 for mint, p in list(book.load().items()):
11 try:
12 m = pool(mint)
13 except Exception as e:
14 events.append(f"{p['symbol']}: flux de prix HS ({e}), on garde, nouvelle tentative à venir")
15 continue
16 if not m or m["price"] <= 0:
17 events.append(f"{p['symbol']}: pool disparue. traiter comme rugged, vendre ce qui peut l'être")
18 book.sell(mint, 1.0, 0.0, "pool_gone")
19 continue
20
21 price = m["price"]
22 b = book.load(); s = b[mint]
23 s["peak"] = max(s["peak"], price); book.save(b)
24 pct = (price / s["entry"] - 1) * 100
25 hours = (time.time() - s["opened"]) / 3600
26
27 def out(frac, why):
28 pnl = book.sell(mint, frac, price, why)
29 verb = "vendu" if PAPER else "VENDRE MAINTENANT sur votre wallet"
30 size = "le reste" if frac >= 1 else f"{int(frac * 100)}%"
31 events.append(f"{s['symbol']}: {verb} {size} à {pct:+.0f}% ({why}), pnl ${pnl:+.2f}")
32
33 if m["liq_usd"] < s["liq0"] * (1 - EXIT["liq_drop_pct"] / 100):
34 out(1.0, "liquidity_pulled"); continue
35 if pct <= EXIT["stop_pct"]:
36 out(1.0, "stop"); continue
37 ladder = EXIT["ladder"]
38 if s["steps"] < len(ladder) and pct >= ladder[s["steps"]][0]:
39 out(ladder[s["steps"]][1], f"take_profit_{ladder[s['steps']][0]}")
40 b = book.load()
41 if mint in b:
42 b[mint]["steps"] += 1; book.save(b)
43 continue
44 if s["steps"] > 0 and price <= s["peak"] * (1 - EXIT["trail_pct"] / 100):
45 out(1.0, "trailing_stop"); continue
46 if hours >= EXIT["time_stop_hours"] and pct < EXIT["time_stop_min_pct"]:
47 out(1.0, "time_stop")
48 return events
49
50if __name__ == "__main__":
51 for e in watch():
52 print(e)
text
1LA LIQUIDITÉ D'ABORD. une pool vidée bat toutes les autres règles, même sur une position gagnante.
2LE TRAIL S'ARME APRÈS LA PREMIÈRE PRISE DE PROFIT. avant ça, -35 % est le seul plancher.
3L'ARGENT MORT EST AUSSI UNE PERTE. six heures à plat libèrent le slot pour le token suivant.
4LE SILENCE EST UN STATUT. watch.py n'imprime rien si rien n'a changé, donc un chat silencieux signifie que vous n'avez pas besoin de regarder.
boan - inline image

08. apprenez les 14 façons dont un token meurt

si je devais jeter tout ce qui précède et ne garder qu'une chose, ce serait ça. ça marche aussi sans aucun bot : faites les mêmes 14 vérifications à la main sur rugcheck.xyz et dexscreener avant votre prochain achat et vous éviterez la plupart des tokens que vous alliez regretter.

13 des vérifications sont du code. des comparaisons, pas de modèle, pas d'opinion. la 14e est la seule qui nécessite Grok.

#

vérification

élimine quand

pourquoi

1

déjà rugged

Rugcheck le marque comme rugged

quelqu'un l'a déjà fait

2

autorité de mint

encore ouverte

le dev peut imprimer de la nouvelle supply dans votre sac

3

autorité de gel

encore ouverte

le dev peut geler vos tokens, vous ne pouvez pas vendre

4

signaux de danger

tout risque de niveau danger

Rugcheck a déjà vu quelque chose que vous auriez du mal à contredire

5

score de risque

supérieur à 40/100

les petits avertissements s'accumulent

6

verrouillage LP

plus grosse pool sous 90 % verrouillée ou brûlée

une liquidité déverrouillée est un bouton de retrait

7

top 10 holders

plus de 30 %, pools et lockers exclus

dix wallets peuvent mettre fin à votre trade ensemble

8

wallet du dev

le créateur détient encore plus de 5 %

le dev est le premier vendeur

9

insiders / bundles

tout holder insider ou hit du graphe insider

les wallets financés ensemble vendent ensemble

10

profondeur de la pool

moins de 30 k$ de liquidité

vous seriez la sortie de quelqu'un d'autre

11

part du ticket

vos 25 $ représentent plus de 1 % de la pool

votre propre achat fait bouger le prix

12

ancienneté

moins de 30 min ou plus de 72 h

trop récent pour le moindre rapport, ou le mouvement a déjà eu lieu

13

ventes existantes

20+ achats dans la dernière heure, zéro vente

c'est la forme typique d'un honeypot

14

lecture X (Grok)

aucun post, CA copié-collé, hype achetée, historique de rug

la partie qu'aucune API ne renvoie

boan - inline image

09. laissez le code éliminer les cas évidents

vérifications 1 à 9. il récupère un rapport et ne conserve que les champs que le desk lit. Grok ne voit jamais le rapport brut, un payload énorme coûte des tokens et nuit à la précision.

un détail qui échappe souvent : le vault de la pool elle-même et les lockers figurent dans la liste des top holders. comptez-les et chaque token ressemblera à un token de baleine. le code les retire avant de calculer le top 10.

python
1# rugcheck.py
2# un rapport par token, réduit aux champs que le desk lit. Grok ne voit jamais le rapport brut.
3import requests
4from config import FACTS
5
6RC = "https://api.rugcheck.xyz/v1/tokens"
7
8def report(mint: str) -> dict:
9 r = requests.get(f"{RC}/{mint}/report", timeout=20)
10 r.raise_for_status()
11 d = r.json()
12 token = d.get("token") or {}
13 known = d.get("knownAccounts") or {}
14
15 def is_pool(h): # les vaults AMM et les lockers sont dans le top holders, ce ne sont pas des baleines
16 tag = known.get(h.get("owner")) or known.get(h.get("address")) or {}
17 return str(tag.get("type", "")).upper() in ("AMM", "LOCKER")
18
19 holders = [h for h in (d.get("topHolders") or []) if not is_pool(h)]
20 markets = sorted(d.get("markets") or [],
21 key=lambda m: ((m.get("lp") or {}).get("baseUSD") or 0)
22 + ((m.get("lp") or {}).get("quoteUSD") or 0),
23 reverse=True)
24 lp = (markets[0].get("lp") or {}) if markets else {}
25 supply = token.get("supply") or 0
26 risks = d.get("risks") or []
27
28 return {
29 "mint": mint,
30 "symbol": (d.get("tokenMeta") or {}).get("symbol"),
31 "rugged": bool(d.get("rugged")),
32 "risk_score": d.get("score_normalised"),
33 "danger": [x.get("name") for x in risks if x.get("level") == "danger"],
34 "warn": [x.get("name") for x in risks if x.get("level") == "warn"],
35 "mint_authority": token.get("mintAuthority", d.get("mintAuthority")),
36 "freeze_authority": token.get("freezeAuthority", d.get("freezeAuthority")),
37 "lp_locked_pct": lp.get("lpLockedPct", d.get("lpLockedPct")),
38 "top10_pct": round(sum(h.get("pct") or 0 for h in holders[:10]), 2) if holders else None,
39 "dev_pct": round((d.get("creatorBalance") or 0) / supply * 100, 2) if supply else None,
40 "insiders": sum(1 for h in holders if h.get("insider")) + (d.get("graphInsidersDetected") or 0),
41 "holders": d.get("totalHolders"),
42 }
43
44def fact_kill(t: dict) -> str | None:
45 """Comparaisons simples. Le premier échec l'emporte, la raison est journalisée."""
46 if t["risk_score"] is None: return "no_report"
47 if t["rugged"]: return "already_rugged"
48 if t["mint_authority"]: return "mint_open"
49 if t["freeze_authority"]: return "freeze_open"
50 if t["danger"]: return "danger:" + t["danger"][0]
51 if t["risk_score"] > FACTS["max_risk_score"]: return "risk_score"
52 if t["lp_locked_pct"] is None or t["lp_locked_pct"] < FACTS["min_lp_locked_pct"]:
53 return "lp_unlocked"
54 if t["top10_pct"] is None or t["top10_pct"] > FACTS["max_top10_pct"]:
55 return "top10_heavy"
56 if t["dev_pct"] is None or t["dev_pct"] > FACTS["max_dev_pct"]:
57 return "dev_holds"
58 if t["insiders"] > FACTS["max_insiders"]: return "insiders"
59 return None
boan - inline image

10. vérifiez la pool, pas seulement le contrat

vérifications 10 à 13. un contrat peut être parfait et la pool vous empêcher quand même de sortir. ceci lit la pool la plus profonde pour le token et pose quatre questions ennuyeuses : y a-t-il assez dedans, quelle est la taille de mon ticket par rapport à elle, quel âge a-t-elle, et est-ce que quelqu'un vend vraiment.

python
1# market.py
2# la pool elle-même : profondeur, ancienneté, prix, et si quelqu'un peut réellement vendre.
3import time
4import requests
5from config import FACTS, TICKET_USD
6
7DS = "https://api.dexscreener.com/tokens/v1/solana"
8
9def pool(mint: str) -> dict | None:
10 r = requests.get(f"{DS}/{mint}", timeout=15)
11 r.raise_for_status()
12 data = r.json()
13 pairs = data if isinstance(data, list) else (data.get("pairs") or [])
14 pairs = [p for p in pairs if (p.get("baseToken") or {}).get("address") == mint]
15 if not pairs:
16 return None
17 p = max(pairs, key=lambda x: (x.get("liquidity") or {}).get("usd") or 0)
18 h1 = (p.get("txns") or {}).get("h1") or {}
19 born = p.get("pairCreatedAt")
20 return {
21 "symbol": (p.get("baseToken") or {}).get("symbol"),
22 "price": float(p.get("priceUsd") or 0),
23 "liq_usd": (p.get("liquidity") or {}).get("usd") or 0,
24 "age_min": round((time.time() * 1000 - born) / 60000) if born else None,
25 "buys_1h": h1.get("buys", 0),
26 "sells_1h": h1.get("sells", 0),
27 "vol_1h": (p.get("volume") or {}).get("h1"),
28 "url": p.get("url"),
29 }
30
31def market_kill(m: dict | None) -> str | None:
32 if not m: return "no_pool"
33 if m["price"] <= 0: return "no_price"
34 if m["liq_usd"] < FACTS["min_liquidity_usd"]: return "thin_pool"
35 if TICKET_USD / m["liq_usd"] > FACTS["max_ticket_share"]: return "ticket_too_big"
36 if m["age_min"] is None or m["age_min"] < FACTS["min_age_min"]:
37 return "too_fresh"
38 if m["age_min"] > FACTS["max_age_hours"] * 60: return "too_old"
39 if m["buys_1h"] >= 20 and m["sells_1h"] == 0: return "nobody_can_sell"
40 return None

11. laissez Grok lire ce que le code ne peut pas

vérification 14. c'est la raison pour laquelle le desk tourne sur Grok et non sur un autre modèle : il peut chercher sur X pendant qu'il réfléchit. un token peut passer les 13 vérifications et rester une copie avec une adresse de contrat différente, ou un lancement où quarante comptes créés la semaine dernière ont posté la même phrase à la même minute. aucune API ne renvoie ça. X si.

enregistrez sous grok.py. c'est le seul fichier qui lit la clé et le seul endroit où le desk parle à xAI :

python
1# grok.py
2# le seul fichier qui contient la clé et le seul endroit où le desk communique avec xAI.
3import os, json, datetime, requests
4from config import MODEL
5
6URL = "https://api.x.ai/v1/responses"
7
8def _key() -> str:
9 k = os.environ.get("XAI_API_KEY")
10 if not k and os.path.exists(".env"):
11 for line in open(".env"):
12 if line.startswith("XAI_API_KEY="):
13 k = line.split("=", 1)[1].strip().strip('"')
14 if not k:
15 raise RuntimeError("pas de XAI_API_KEY dans l'environnement ou dans .env")
16 return k
17
18def _text(resp: dict) -> str:
19 if isinstance(resp.get("output_text"), str):
20 return resp["output_text"]
21 parts = []
22 for item in resp.get("output") or []:
23 if item.get("type") == "message":
24 for c in item.get("content") or []:
25 if c.get("type") in ("output_text", "text"):
26 parts.append(c.get("text") or "")
27 return "\n".join(parts)
28
29def ask(system: str, payload: dict, read_x: bool = False) -> dict:
30 """Un seul appel, JSON en entrée, JSON en sortie. Tout ce qui n'est pas du JSON déclenche une erreur, et une erreur signifie un SKIP en amont."""
31 body = {"model": MODEL,
32 "input": [{"role": "system", "content": system},
33 {"role": "user", "content": json.dumps(payload)}]}
34 if read_x:
35 since = (datetime.date.today() - datetime.timedelta(days=3)).isoformat()
36 body["tools"] = [{"type": "x_search", "from_date": since}]
37 body["max_turns"] = 2 # deux tours de recherche, puis il doit répondre
38 r = requests.post(URL, timeout=180, json=body,
39 headers={"Authorization": f"Bearer {_key()}"})
40 r.raise_for_status()
41 text = _text(r.json())
42 start, end = text.find("{"), text.rfind("}")
43 if start == -1:
44 raise ValueError(f"pas de json dans la réponse : {text[:200]}")
45 return json.loads(text[start:end + 1])

enregistrez sous prompts.py. c'est le fichier que vous allez réellement relire :

python
1# prompts.py
2# l'unique prompt Grok sur le desk. c'est le fichier que vous allez réellement relire.
3
4JUDGE_PROMPT = """
5Tu es RUG DESK. Un memecoin Solana vient de passer tous les contrôles stricts dans le code :
6autorités, LP, holders, wallet du dev, initiés, profondeur du pool, ancienneté.
7Ne revérifie pas ces chiffres. Tu décides si un seul ticket fixe est engagé.
8Tu ne dimensionnes jamais les positions, tu ne choisis jamais les sorties.
9
10ENTRÉE : {"token": {...faits rugcheck...}, "pool": {...faits dexscreener...}}
11
12ÉTAPE 1. Cherche le ticker et l'adresse du contrat sur X, sur les 72 dernières heures.
13ÉTAPE 2. Juge uniquement ce que le code ne peut pas voir :
14 - est-ce que les risques de niveau « warn » s'accumulent pour former quelque chose de pire ensemble
15 - qui a posté en premier : le dev, un vrai compte avec un historique, ou une vague de comptes tout neufs
16 - organique ou acheté : mêmes formulations, même minute, comptes sans passé
17 - l'adresse du contrat dans ces posts est-elle la même que celle de l'ENTRÉE
18 - ce nom de ticker ou ce dev ont-ils déjà été liés à un rug par le passé
19
20RETOURNE UNIQUEMENT DU JSON :
21{"verdict": "BUY" | "SKIP", "confidence": 0.0-1.0,
22 "why": "deux lignes maximum", "x_read": "une ligne sur ce à quoi ressemble X",
23 "main_risk": "une ligne"}
24
25Zéro post sur X est une réponse : personne ne sait qu'il existe. SKIP.
26Une autre adresse de contrat sous le même ticker sur X : risque de copie. SKIP.
27Ne réponds JAMAIS BUY lorsqu'un champ dont tu as besoin est null.
28Ne mentionne JAMAIS d'objectifs de prix. Tu ne les connais pas.
29"""

12. reliez le tout dans une seule commande

une adresse de contrat en entrée, un verdict en sortie. limites, faits, pool, Grok, dans cet ordre, et le premier qui dit non met fin au processus :

python
1# check.py
2# une adresse de contrat en entrée, un verdict en sortie. s'exécute à chaque fois qu'un token passe sur ton desk.
3import csv, json, os, sys, time
4from config import LOG, MIN_CONFIDENCE, PAPER, TICKET_USD
5from rugcheck import report, fact_kill
6from market import pool, market_kill
7from grok import ask
8from prompts import JUDGE_PROMPT
9import book
10
11def log(row: dict):
12 new = not os.path.exists(LOG)
13 with open(LOG, "a", newline="") as f:
14 w = csv.DictWriter(f, fieldnames=["time", "mint", "symbol", "stage", "verdict",
15 "confidence", "reason"])
16 if new:
17 w.writeheader()
18 w.writerow({k: row.get(k) for k in w.fieldnames})
19
20def check(mint: str) -> dict:
21 if (g := book.guard(mint)): # limites, gratuit
22 return {"stage": "limits", "verdict": "SKIP", "reason": g}
23
24 try:
25 token = report(mint) # filtre rug, gratuit
26 except Exception as e:
27 return {"stage": "facts", "verdict": "SKIP", "reason": f"rugcheck a échoué : {e}"}
28 if (k := fact_kill(token)):
29 return {"stage": "facts", "verdict": "SKIP", "reason": k, "symbol": token["symbol"]}
30
31 try:
32 m = pool(mint) # pool, gratuit
33 except Exception as e:
34 return {"stage": "pool", "verdict": "SKIP", "reason": f"dexscreener a échoué : {e}"}
35 if (k := market_kill(m)):
36 return {"stage": "pool", "verdict": "SKIP", "reason": k, "symbol": token["symbol"]}
37
38 try:
39 ans = ask(JUDGE_PROMPT, {"token": token, "pool": m}, read_x=True) # la seule étape payante
40 except Exception as e:
41 return {"stage": "grok", "verdict": "SKIP", "reason": f"grok a échoué : {e}"}
42
43 verdict, conf = ans.get("verdict"), ans.get("confidence") or 0
44 if verdict == "BUY" and conf < MIN_CONFIDENCE:
45 verdict = "SKIP"
46 ans["why"] = f"confiance faible {conf}"
47 return {**ans, "stage": "grok", "verdict": verdict, "symbol": m["symbol"] or token["symbol"],
48 "reason": ans.get("why"), "price": m["price"], "liq_usd": m["liq_usd"], "url": m["url"]}
49
50if __name__ == "__main__":
51 mint = sys.argv[1].strip()
52 v = check(mint)
53 log({"time": time.strftime("%Y-%m-%d %H:%M"), "mint": mint, **v})
54 if v["verdict"] == "BUY":
55 if PAPER:
56 book.open_position(mint, v["symbol"], v["price"], v["liq_usd"])
57 v["action"] = f"PAPER BUY ${TICKET_USD} at {v['price']}"
58 else:
59 v["action"] = (f"APPROBATION REQUISE : achète ${TICKET_USD} de {v['symbol']} dans ton propre wallet, "
60 f"puis exécute : python book.py add {mint} {TICKET_USD} <prix d'exécution> {v['liq_usd']}")
61 print(json.dumps(v, indent=2))

vous n'avez pas besoin d'un scanner pour l'utiliser. une CA provenant d'un canal vocal, d'un post, du message d'un ami : dites au bot « check <CA> » et il exécute une ligne. voici à quoi ressemble le retour (structure d'exemple, pas un vrai token) :

json
1{
2 "verdict": "SKIP",
3 "confidence": 0.78,
4 "why": "passe tous les contrôles stricts, mais les 30 premiers posts proviennent de comptes créés cette semaine, avec les mêmes formulations.",
5 "x_read": "un vrai compte, une vague de comptes tout neufs, aucune divergence de CA",
6 "main_risk": "hype achetée, les acheteurs partiront quand les posts s'arrêteront",
7 "stage": "grok",
8 "symbol": "EXEMPLE",
9 "reason": "passe tous les contrôles stricts, mais les 30 premiers posts proviennent de comptes créés cette semaine, avec les mêmes formulations."
10}
boan - inline image
text
1LES FAITS AVANT LES OPINIONS. Grok ne décide jamais si un mint est ouvert.
2UN APPEL ÉCHOUÉ EST UN SKIP. Rugcheck en panne, DexScreener en panne, Grok en panne, mauvais JSON : SKIP.
3NULL N'EST PAS PROPRE. un champ qui ne revient pas élimine le token, il ne le valide jamais.
4UN VERDICT PAR TOKEN. ne relancez jamais tant qu'il n'a pas dit BUY. si vous n'êtes pas d'accord, c'est avec config.py que vous n'êtes pas d'accord.
5LISEZ LES KILLS, PAS LES BUYS. les buys font plaisir. les raisons des kills vous disent si le filtre fonctionne.

13. trois routines, une phrase chacune

aucun constructeur de workflow. vous indiquez chaque routine au bot une seule fois, en une phrase, et il vous montre la prochaine exécution. voici les miennes, mot pour mot :

text
1Toutes les 10 minutes, dans /workspace/desk exécute python watch.py.
2Si ça n'affiche rien, ne dis rien. Si ça affiche quoi que ce soit, poste-le ici mot pour mot.
text
1Toutes les 30 minutes, dans /workspace/desk exécute python scan.py.
2Poste uniquement les verdicts BUY : symbol, confidence, x_read.
3Si Rugcheck ou DexScreener est en panne, dis lequel une seule fois, pas à chaque exécution.
text
1Chaque jour à 21h30, dans /workspace/desk exécute python report.py et poste le résultat ici.
2Ajoute une chose qui a fonctionné aujourd'hui et un chiffre dans config.py que tu remettrais en question, avec la raison.
3Ne modifie jamais ce chiffre toi-même.

les deux fichiers que ces routines exécutent. enregistrez sous report.py :

python
1# report.py
2# le rapport du soir. tout ce qu'il contient vient de checks.csv et trades.csv, rien de la mémoire.
3import csv, os, time
4from collections import Counter
5from config import LOG, PAPER
6import book
7
8day = time.strftime("%Y-%m-%d")
9checks = [r for r in csv.DictReader(open(LOG))] if os.path.exists(LOG) else []
10checks = [r for r in checks if r["time"].startswith(day)]
11done = [t for t in book.trades() if t["time"].startswith(day) and t["action"] != "open"]
12
13by_stage = Counter(r["stage"] for r in checks if r["verdict"] == "SKIP")
14buys = [r for r in checks if r["verdict"] == "BUY"]
15wins = [t for t in done if float(t["pnl"]) > 0]
16reasons = Counter(r["reason"] for r in checks if r["stage"] in ("facts", "pool"))
17
18print(f"RAPPORT DU SOIR {day} {'(PAPER)' if PAPER else '(LIVE)'}")
19print(f"vérifiés : {len(checks)}")
20print(f"éliminés par le filtre rug : {by_stage['facts']} | par le pool : {by_stage['pool']} | "
21 f"par Grok : {by_stage['grok']} | par les limites : {by_stage['limits']}")
22print(f"achetés : {len(buys)} | ouverts actuellement : {len(book.load())}")
23print(f"pnl réalisé aujourd'hui : ${book.today_pnl():+.2f}")
24if done:
25 print(f"sorties gagnantes : {len(wins)}/{len(done)}")
26 best = max(done, key=lambda t: float(t["pnl"]))
27 worst = min(done, key=lambda t: float(t["pnl"]))
28 print(f"meilleur : {best['symbol']} ${float(best['pnl']):+.2f} | pire : {worst['symbol']} ${float(worst['pnl']):+.2f}")
29if reasons:
30 top, n = reasons.most_common(1)[0]
31 print(f"élimination la plus fréquente : {top} ({n}x)")

et scan.py, la source de leads optionnelle. il récupère les nouveaux tokens Solana qui viennent de payer pour un profil DexScreener. un profil payant n'est pas un signal de qualité, cela signifie seulement que le dev a dépensé de l'argent. le filtre décide du reste :

python
1# scan.py
2# source de leads optionnelle : nouveaux tokens Solana qui viennent de payer pour un profil DexScreener.
3# un profil payant n'est pas un signal de qualité, cela signifie juste que le dev a dépensé de l'argent. le filtre décide.
4import csv, os, subprocess, sys
5import requests
6from config import LOG
7
8seen = {r["mint"] for r in csv.DictReader(open(LOG))} if os.path.exists(LOG) else set()
9r = requests.get("https://api.dexscreener.com/token-profiles/latest/v1", timeout=15)
10r.raise_for_status()
11fresh = [t["tokenAddress"] for t in r.json()
12 if t.get("chainId") == "solana" and t.get("tokenAddress") not in seen]
13
14for mint in fresh[:5]: # cinq par exécution, pour qu'une heure chargée ne vide pas le budget API
15 subprocess.run([sys.executable, "check.py", mint])

dernière chose pour ce soir : Settings, General, Auto-review. ajoutez deux règles « Ask first », elles bloquent l'action et vous attendent quoi que pense n'importe quelle routine :

text
1Demande-moi d'abord avant toute connexion de wallet, signature, swap ou transfert.
2Demande-moi d'abord avant de modifier tout fichier nommé config.py.
boan - inline image
boan - inline image

14. une semaine sur papier avant le premier dollar

PAPER = True signifie que le desk fait tout pour de vrai, sauf l'argent. vrais tokens, vrais prix, vraies sorties, fausses exécutions. après sept jours, ouvrez checks.csv et lisez-le comme s'il avait été écrit par un inconnu.

ce que vous cherchez : quel contrôle élimine le plus, si les BUY auraient été ceux que vous auriez achetés, et si une raison de SKIP semble incorrecte. une exécution papier se fait au prix affiché à l'écran, une exécution live jamais, alors considérez le résultat papier comme un plafond, pas comme une prévision.

quand vous passez en live, basculez PAPER sur False et rien d'autre ne change, sauf la dernière étape. check.py arrête d'acheter et publie plutôt une ligne d'approbation : achetez vous-même 25 $ dans votre propre wallet, puis une commande l'inscrit dans le registre pour que watch.py commence à le surveiller.

quand ça casse

ça touche à l'argent, donc chaque défaillance a une réponse écrite avant même qu'elle ne se produise.

text
1401 de xAI -> mauvaise clé. Prends le contrôle, réécris .env, relance le curl de l'étape 03.
2400 / 404 de xAI -> le nom du modèle a changé. corrige MODEL dans config.py, rien d'autre.
3429 de xAI -> limite de taux atteinte. ce token est un SKIP, la prochaine exécution passe à autre chose. ne boucle jamais dessus.
4erreur concernant x_search -> ton MODEL ne peut pas chercher sur X. choisis-en un qui le peut sur console.x.ai -> Models.
5Grok répond en prose -> ValueError, journalisé, SKIP. ne transforme jamais un paragraphe en trade.
6rugcheck 404 ou vide -> trop récent pour être indexé. SKIP. récent ne veut pas dire propre.
7lp_unlocked sur tout -> certains types de pools n'ont aucun token LP. ouvre-en un toi-même sur rugcheck
8 avant de toucher à ce chiffre, et modifie-le par écrit.
9no_pool -> pas encore tradé sur un DEX, ou pas sur Solana. SKIP.
10les routines sont devenues silencieuses -> Grok Bot met les routines en pause après une longue absence.
11 ouvre Routines et réactive-les.

la facture

tout ce qui précède le juge est gratuit : les limites, Rugcheck, DexScreener. la seule étape payante est un appel Grok par token ayant survécu aux 13 contrôles, avec la recherche X activée.

text
1coût_par_token = input_tokens / 1_000_000 * prix_par_M_input
2 + output_tokens / 1_000_000 * prix_par_M_output
3 + posts_récupérés / 1_000 * 5 # recherche X : 5 $ pour 1 000 posts récupérés
4
5max_turns = 2 limite la recherche à deux tours, donc posts_récupérés reste faible.
6chaque réponse indique son propre x_posts_fetched, donc dès le premier jour tu connais le vrai chiffre.
7
8prix : [prix depuis console.x.ai]

l'erreur que font les gens : la facture évolue avec les survivants, pas avec le scanner. scan.py peut fournir 240 tokens par jour au desk et la plupart meurent gratuitement avant même que Grok n'en entende parler.

boan - inline image

le point important

c'est ma configuration, pas votre stratégie.

chaque chiffre dans config.py est le mien, choisi pour un ticket de 25 $ et ma propre tolérance à regarder quelque chose tomber à zéro. la plupart des memecoins tombent effectivement à zéro, et la plupart des gens qui les tradent perdent de l'argent. le filtre ne rend pas un token bon. il élimine les façons évidentes de perdre, et il vous oblige à lire pourquoi chaque token est mort.

faites tourner une semaine sur papier. lisez les kills. déplacez les chiffres avec lesquels vous n'êtes pas d'accord, par écrit. copiez la structure, pas les constantes. ceci n'est pas un conseil financier.

le code élimine, Grok lit X, vous signez. un script n'a jamais le droit de juger, Grok n'a jamais de calculatrice, et personne d'autre que vous n'a accès au wallet.

sauvegardez ceci avant votre prochain achat. abonnez-vous si vous prévoyez de faire tourner la même chose, la suite arrive bientôt 🫶

mon tg - t.me/+8wAXS0nHWgA2MGEy

mon github - github.com/0xboan

tradez ici - fomo.family/r/0xboan

Enregistrer en un clic

Lire les articles viraux en profondeur avec l’IA de YouMind

Enregistrez la source, posez des questions ciblées, résumez l’argument et transformez un article viral en notes réutilisables dans un seul espace de travail IA.

Découvrir YouMind
Pour les créateurs

Transformez votre Markdown en un article 𝕏 impeccable

Quand vous publiez vos propres textes longs, la mise en forme 𝕏 des images, tableaux et blocs de code est pénible. YouMind transforme un brouillon Markdown complet en un article 𝕏 impeccable, prêt à publier.

Essayer Markdown vers 𝕏

D'autres patterns à décoder

Articles viraux récents

Explorer plus d'articles viraux