Configuration
every variable, every setting.
.env starts the process; the Admin console holds everything else. This page lists every variable the code reads, its default and where the same setting lives in the console.
01Two places, one rule
The commands on this page run on your Linux server. From Windows, connect with ssh in Windows Terminal or PowerShell and run them there; for a local trial on your own PC, use WSL 2 with Ubuntu as described in Installation.
In plain words: a small text file called .env tells the program how to start (which port, where the database file is, and the secret key that unlocks the console). Everything you will want to change later (your brand, your bot, your chats, your wallet, the scoring rules, the earning options) is a form in the operator console at /admin, saved with one click. You can run the whole product with four lines in .env and do the rest in the browser. The table below is the technical detail of the same rule.
| Where | What goes there | A change needs |
|---|---|---|
.env | The bootstrap: PORT, HOST, DATABASE_PATH, ADMIN_SECRET_KEY. Every other variable is a starting value. | A restart (sudo systemctl restart verified-calls) |
Admin console (/admin) | Brand, site address, Telegram chats, proof wallet, seal interval, method, earning options, integrations | Save. Most settings apply at once; the public address, log level and method apply after a restart. |
- A value in
.envis used until the same setting is saved in the console, which then wins. The start-up log lists the.envvalues in use. - The three secrets are the exception: when
TELEGRAM_BOT_TOKEN,SOLANA_RPC_URLorHELIUS_API_KEYis set in.env, the console field is locked and the.envvalue wins. - Secrets saved in the console are encrypted with
ADMIN_SECRET_KEYinadmin.sqlite(next to the database). Back the key and that file up together. pnpm start(andpnpm recompute) reads.envfrom the folder you start it in.ENV_FILE=/path/to/fileuses another file. Variables already set in the real environment win over.env.
02Bootstrap variables
| Variable | Default | Purpose |
|---|---|---|
ADMIN_SECRET_KEY Required | empty = console off | 32 random bytes as 64 hex characters (openssl rand -hex 32). Turns on the console and encrypts its secrets. Empty: /admin answers 503 with instructions; the public site and the bot keep running on .env. |
PORT | 8787 | Port the web server listens on. |
HOST | all interfaces | Interface to bind, e.g. 127.0.0.1 behind Caddy or nginx. |
DATABASE_PATH | data/verified-calls.db | The SQLite file. The folder is created if missing. The console keeps admin.sqlite in the same folder. |
ENV_FILE | .env | Read another configuration file. Set it in the real environment, not in .env. |
03Starting values (also in the console)
| Variable | Default | Purpose | Console |
|---|---|---|---|
TELEGRAM_BOT_TOKEN | empty | Your bot. Empty: the site runs read-only, nothing is recorded, seals are not posted. | Get started, Integrations (locked when set here) |
PUBLIC_BASE_URL | http://localhost:8787 | The public address, no trailing slash. Used in bot links and in the wallet-link message. Use https:// in production. | Site |
SITE_NAME | Verified Calls | Name in the header, the bot's /start text and the badge. | Brand → Product name |
ALLOWED_CHAT_IDS | empty | Comma-separated chat ids recorded without approval. Any other chat waits under Monitor → Chats. | Telegram |
SEAL_POST_CHAT_IDS | empty | Comma-separated chat ids the bot posts each seal to. In a channel the bot must be an admin allowed to post. | Telegram |
SOLANA_RPC_URL | https://api.mainnet-beta.solana.com | Builds the unsigned seal memo and checks it after you signed; reads VIP and listing payments. | Integrations (locked when set here) |
OPERATOR_WALLET | empty | The public address you sign seal memos with. Empty: "Sign with wallet" is disabled. | Proof |
SEAL_INTERVAL_MIN | 10 | Minutes between seals (1–10080). A seal is made only when there are new calls or coverage events. Keep it short: until a call is sealed the server owner could still drop it unseen. | Proof |
GECKOTERMINAL_RPM | 25 | Price requests per minute to GeckoTerminal's keyless API. Stay under their free limit. | Data sources |
HELIUS_API_KEY | empty | Enables exit-liquidity checks. Empty: every call shows "not checked", never "clean". | Integrations (locked when set here) |
EXIT_LIQUIDITY_USE_RPC | empty | true = exit-liquidity checks through your own SOLANA_RPC_URL instead of Helius. The public mainnet endpoint is refused. | Data sources |
BUY_URL_TEMPLATE | empty | A link on every call; {mint} becomes the token address. Must be https://. | Trading links → Custom link |
BUY_LABEL | empty = link host | Shown as "Buy on <label>". | Trading links → Custom link label |
LOG_LEVEL | info | debug, info, warn, error or silent (silent only in .env; the console offers the other four). Secrets are redacted from logs. | Data sources |
FRAME_ANCESTORS | empty = never framed | Space-separated https:// origins that may show the public read-only pages in a frame, for example your own website or https://preview.codecanyon.net. Forms, payment pages, /link, /api, /export and the console are never frameable. An invalid origin stops the start with a message. | .env only |
Example of a custom link, with a made-up terminal:
# Example only
BUY_URL_TEMPLATE=https://your-terminal.example/swap?out={mint}
BUY_LABEL=Your Terminal
Source: .env.example, src/core/config.ts, src/settings/schema.ts, src/admin/kit.ts.
04Scoring method
These change every number on the site. /methodology always shows the values in use. Decide before you publish and announce any change. The first five are also in the console under Method; all apply after a restart.
| Variable | Default | Meaning |
|---|---|---|
SCORING_ENTRY_DELAY_SEC | 30 | Seconds after the post a follower is modelled to buy. |
SCORING_FEE_BPS | 100 | Fee per side in basis points (100 = 1 %). |
SCORING_SLIPPAGE_BPS | 150 | Minimum slippage per side; thin pools get more (liquidity-aware). |
SCORING_MIN_CALLS | 5 | Scored calls needed to be ranked. |
SCORING_SHRINKAGE_K | 10 | How strongly a small record is pulled toward the group median. |
SCORING_HIT_THRESHOLD | 0.5 | Net result counted as a hit (+50 %). |
SCORING_RUG_THRESHOLD | -0.9 | Net result counted as a rug (−90 %). Must be lower than the hit threshold, or the app refuses to start. |
SCORING_EXIT_LIQUIDITY_WINDOW_MIN | 60 | Minutes after a call in which a linked wallet's sale is flagged. |
SCORING_MAX_ENTRY_GAP_SEC | 300 | No trade within this time after the entry delay: the call is "unpriceable". |
Advanced (not in .env.example; defaults and formulas in SPEC.md): SCORING_MAX_PRICE_SOURCE_RATIO, SCORING_FOLLOWER_SIZE_USD, SCORING_LIQUIDITY_SLIPPAGE_K, SCORING_MAX_SLIPPAGE_BPS, SCORING_LIQUIDITY_FLOOR_USD, SCORING_PRE_RUNUP_THRESHOLD, SCORING_PRE_RUNUP_WINDOW_MIN, SCORING_EXIT_VWAP_MIN, SCORING_ENTRY_VWAP_MIN.
After changing the method, recompute the stored results so every call is scored the same way:
sudo systemctl stop verified-calls
pnpm build # once, if dist/ is older than the code
pnpm recompute --dry-run # shows what would change
pnpm recompute
sudo systemctl start verified-calls
The script reads only the database and never calls a price API. Calls, seals and proofs are never touched. Exit 0 = done, 1 = some rows could not be recomputed (listed).
05Console-only settings
These have no .env variable: reply cards, the groups directory, integrity rules, API keys and every earning option (trading-link codes, Jupiter swap, VIP plans, paid listings, sponsored slot). See Admin console and Earnings.