vivraDocumentationV1Comprendre le vote

Annexe F · Mise en place du projet

Tout ce qu'il faut pour démarrer le code le premier jour : structure du repo, comptes et clés à créer, variables d'environnement, lancement en local, workers et tâches planifiées, déploiement.

Structure du repo#

Un seul repo (monorepo pnpm + Turborepo), TypeScript partout sauf les contrats.

text
vivra/
├── apps/
│   ├── web/            # Next.js : landing + dapp (4 écrans)
│   ├── admin/          # Next.js : back-office (SIWE)
│   ├── api/            # serveur HTTP + WebSocket (Fastify)
│   └── workers/        # BullMQ : analyse, suivi, orchestrateur, agents, buyback, trésorerie, bots
├── packages/
│   ├── db/             # schéma, migrations, client (annexe A)
│   ├── core/           # logique métier pure : statuts, score de reprise, règles de vote
│   ├── chain/          # config des chaînes, ABI, lectures et écritures viem (annexe D)
│   ├── agents/         # specs YAML, prompts, schémas de sortie, outils (annexe C)
│   ├── templates/      # templates de sites, de visuels et de mini-apps
│   └── ui/             # composants partagés, tokens de la DA
├── contracts/          # Foundry : BuybackBurner + tests
├── infra/              # Dockerfiles, docker-compose, config du déploiement
└── .github/workflows/  # CI

Comptes et clés à créer (jalon M0)#

ServicePour quoiVariable
Alchemy (Robinhood Chain)RPC principal mainnet et testnetRPC_URL_MAINNET, RPC_URL_TESTNET
Second fournisseur RPCsecoursRPC_URL_MAINNET_FALLBACK
Surplus Intelligenceinférence des agentsSURPLUS_API_KEY, SURPLUS_BASE_URL
Générateur d'images (via Surplus si disponible, sinon un fournisseur dédié)DesignerIMAGE_API_KEY
API X (offre payante en écriture)posts du compte Vivra et des tokens CTOX_API_KEY, X_API_SECRET, puis un jeton OAuth par compte stocké en base, chiffré
Telegram (@BotFather)bot Vivra et TG BotTELEGRAM_BOT_TOKEN, TELEGRAM_ALERTS_CHAT_ID
Service d'emails (Resend ou Postmark)lien magique et codeEMAIL_API_KEY, EMAIL_FROM
Captcha invisible (Cloudflare Turnstile)inscriptionTURNSTILE_SECRET
Cloudflare Pages (ou Vercel)sites des tokens CTOPAGES_API_TOKEN, PAGES_ACCOUNT_ID
DNS du domaine Vivra (Cloudflare)sous-domaines <ticker>.<domaine>DNS_ZONE_ID
Stockage objet (Cloudflare R2 ou S3)visuels et memesS3_ENDPOINT, S3_BUCKET, S3_ACCESS_KEY, S3_SECRET_KEY
Hébergeur de conteneurs (Railway, Fly.io ou Render)API et workerscôté hébergeur
Postgres managé + Redis managédonnées et filesDATABASE_URL, REDIS_URL
Coffre de secrets (celui de l'hébergeur ou Doppler)clés des hot walletsvoir ci-dessous
SentryerreursSENTRY_DSN

Variables d'environnement#

Un fichier .env.example commité, sans aucune valeur secrète. Les vraies valeurs vivent dans le coffre de secrets.

bash
# Général
NODE_ENV=development
APP_URL=http://localhost:3000
API_URL=http://localhost:4000
CHAIN_ENV=testnet                     # testnet | fork | mainnet

# Données
DATABASE_URL=postgres://vivra:vivra@localhost:5432/vivra
REDIS_URL=redis://localhost:6379

# Sécurité
SESSION_SECRET=                       # 32 octets aléatoires
EMAIL_HMAC_KEY=                       # pour users.email_hash
EMAIL_ENC_KEY=                        # AES-256-GCM pour users.email_enc
SLICE_SCHEDULE_KEY=                   # chiffre les horaires des tranches

# Chaîne
RPC_URL_TESTNET=
RPC_URL_MAINNET=
RPC_URL_MAINNET_FALLBACK=
BUYBACK_BURNER_ADDRESS=
BUYBACK_HOT_WALLET_KEY_REF=           # référence dans le coffre, jamais la clé elle-même
AI_HOT_WALLET_KEY_REF=
TREASURY_OPERATOR_KEY_REF=            # signe les claims de l'escrow (wallets Collecte et Frais CTO)

# Inférence et services
SURPLUS_BASE_URL=https://api.surplusintelligence.ai/v1
SURPLUS_API_KEY=
IMAGE_API_KEY=
X_API_KEY=
X_API_SECRET=
TELEGRAM_BOT_TOKEN=
TELEGRAM_ALERTS_CHAT_ID=
EMAIL_API_KEY=
EMAIL_FROM=vote@<domaine-vivra>
TURNSTILE_SECRET=
PAGES_API_TOKEN=
PAGES_ACCOUNT_ID=
DNS_ZONE_ID=
S3_ENDPOINT=
S3_BUCKET=
S3_ACCESS_KEY=
S3_SECRET_KEY=
SENTRY_DSN=

Les clés privées des hot wallets ne sont jamais dans une variable d'environnement lisible par tous les services : seul le worker concerné lit sa clé depuis le coffre, au démarrage.

Lancer en local#

bash
pnpm install
docker compose -f infra/docker-compose.yml up -d     # Postgres 16 + Redis 7
pnpm db:migrate && pnpm db:seed                      # seed : 30 tokens fictifs, 1 cycle, 1 opération de démo
pnpm dev                                             # web :3000, admin :3001, api :4000, workers
cd contracts && forge test                           # tests du BuybackBurner
forge test --fork-url $RPC_URL_MAINNET               # tests sur un fork du mainnet

pnpm dev lance les workers en mode CHAIN_ENV=testnet : aucune écriture mainnet n'est possible tant que CHAIN_ENV ne vaut pas mainnet.

Files et tâches planifiées (BullMQ)#

FileDéclencheurRôle
projects.analyzeà la soumission d'une adresse par l'équipe, ou relanceanalyse complète d'un token par le Scanner
tracking.candidatestoutes les 15 min, les 5 candidats du vote en coursmarché en direct, score de reprise en direct
tracking.liveen continu, le token CTO en opération seulement (events de son pool ou de sa courbe)chart, tranches, war room
tracking.followuptoutes les heures, tokens repris jusqu'à J+30suivi, verdict, passation
cycles.clocktoutes les minutesouvrir et fermer les votes, créer l'opération à J0
orchestrator.ticktoutes les minuteslancer les étapes dues (annexe C)
agents.runà la demande de l'orchestrateurexécuter un agent, concurrence 3
tg.updateswebhook Telegramanti-spam et réponses du TG Bot
buyback.slicesjob différé par tranche, à l'horaire tiréexécuter une tranche
buyback.refill1 fois par jourrecharger le hot wallet depuis la réserve
treasury.daily1 fois par jour, 00:30 UTCbalayage, claim, répartition, recharge Surplus, registre
social.publishtoutes les minutespublier les posts validés dont l'heure est passée
alerts.checktoutes les minutesseuils de la page Sécurité

Chaque job est idempotent : un job relancé après un crash ne refait pas une transaction déjà envoyée (on vérifie tx_hash en base avant d'envoyer).

Déploiement#

EnvironnementOùQuand
Previewune URL par pull request (front)à chaque PR
Staginghébergeur de conteneurs + testnet Robinhood Chainà chaque merge sur main
Pré-productionstaging pointé sur un fork du mainnetavant le lancement (jalon M5)
Productionhébergeur de conteneurs + mainnettag v*, déclenché à la main

CI (GitHub Actions) à chaque PR : lint, types, tests unitaires, forge test, build des apps, scan de secrets (gitleaks). Un merge est bloqué si une étape échoue.

Ordre de travail conseillé#

Le plan de développement donne les jalons. Dans le code, l'ordre qui évite de se bloquer :

  1. packages/db et packages/chain (schéma, config, ABI).
  2. Analyse à la demande et score de reprise, avec le back-office de soumission et de relecture (jalon M1).
  3. Orchestrateur avec des agents « factices » qui renvoient des sorties fixes, puis les vrais agents un par un (jalon M2).
  4. BuybackBurner sur testnet, puis Buyback Bot et trésorerie (jalon M3).
  5. Vote, back-office, dapp complète, bots (jalon M4).
  6. Répétition d'un cycle entier sur le fork (jalon M5).
↑ ↓ pour parcourir · Entrée pour ouvrirVIVRA DOCS