Trade Mining Overview
How DepthSight nodes mint $DEPTH by submitting anonymous trade telemetry — node identity, scoring, mining epochs and reward distribution.
Trade Mining is the federated incentive layer of the DepthSight ecosystem. Every node in the federation — the central master hub or any self-hosted mining server — mines tokens by reporting anonymous telemetry about the real trades it executes. Verified trades earn $DEPTH from a fixed daily emission budget, distributed across the nodes that contribute activity.
Telemetry is anonymous: no API keys, orders or secrets are shared. A node only sends trade facts (symbol, direction, entry, exit, duration, exit reason, strategy blocks, volume). Rewards follow the node identity, not the exchange account.
1. Concepts
| Term | Meaning |
|---|---|
| Central Hub | The central deployment (IS_CENTRAL_HUB=true). Hosts the hub API, verifies trades, finalizes epochs and mints rewards. |
| HubNode | A node identity (node_uuid + node_secret) registered on the hub. Every miner and every mining server is a HubNode. |
| Mining server | A HubNode flagged is_mining_server=True. Hosts external miners and earns a commission on trades mined through it (source_node_uuid). |
| Miner node | The HubNode a specific trade is attributed to (node_uuid on the report). |
| Wallet-bound node | A node owned by an EVM wallet. Its node_uuid = UUIDv5(NAMESPACE_DNS, "evm:<address>") is deterministic, so the same identity reproduces on any server and history follows the wallet. |
| HubServerConfig | Per-server override of the user/server reward share (default 75%). |
| $DEPTH | The reward token minted by mining epochs. |
Key modules: api/hub_router.py (hub endpoints), api/routes/config.py (local mining endpoints), bot_module/controller.py (telemetry dispatch), bot_module/node_identity.py (exchange-agnostic identity readers), api/hub_proxy_router.py (node → hub transparent proxy of /api/v1/hub/*), tasks.py (epoch processing), telemetry_sync.py (offline resync), api/models.py (mining schema).
2. Node Identity & Wallet Binding
Before any telemetry can be attributed, a node must exist on the hub and prove who it is.
Node credentials
node_uuid— unique 36-char identity.node_secret— the telemetry write credential. The hub stores onlysha256(node_secret)and verifies every payload with an HMAC-SHA256 signature keyed by the raw secret. The raw secret is never persisted and travels only over TLS.
Local nodes read their identity from the HUB_NODE_UUID / HUB_NODE_SECRET env vars or from a node_identity.json / identity.json file. Wallet-bound users read their identity from AppConfig.exchange_settings through the exchange-agnostic collectors in bot_module/node_identity.py (find_identity_pair, primary_mining_node_uuid): the legacy weex section is tried first, then every other exchange section and finally the top-level keys — mining_node_uuid and mining_node_secret are always taken from the same section so credentials can never be mixed.
Wallet binding & ownership
POST /api/v1/config/node/wallet/nonce— returns a self-verifying, expiring SIWE-style ownership message (embeds the address, purpose, a unique nonce and an absolute expiry — verification needs no shared server state, safe across uvicorn workers). Each consumed message is recorded inused_ownership_messages, so an intercepted signature cannot be replayed even inside its 5-minute TTL.POST /api/v1/config/node/wallet/verify— verifies the signature and binds the wallet:- stores
node_uuid = UUIDv5("evm:<address>"), a freshmining_node_secret,wallet_addressandwallet_configured=truein both theweexsection and the top level ofexchange_settings, enables mining for the account (is_mining_enabled = true); - migrates any legacy
mining_node_uuid/virtual-<user_id>history (telemetry, ledger,total_mined, referral links) onto the new EVM node via_transfer_node_data— nothing is lost; - purges any legacy mnemonic.
- stores
- A legacy nonce-based flow is still accepted for older frontends; its in-process nonce cache is additionally routed through the same single-use registry. On a central hub the registry is consumed at verify; on ordinary nodes it is consumed during the forwarded
/nodes/register, so local and hub deployments sharing one database never double-consume a signature.
The EVM wallet is the ownership credential: creating, claiming, re-keying, revoking, or changing an existing referrer link requires a valid wallet signature. A node that has no referrer yet may bind its first one with the node secret alone (register or ping); re-binding or altering an existing link still requires the wallet signature. Binding the same wallet from a second platform account joins the existing mining node (audit-logged; the account's referral code is synced to the node's code) rather than splitting its data.
Hub registration
Nodes register via POST /api/v1/hub/nodes/register:
- stores
sha256(node_secret), IP, geolocation, version, the exchange UIDs (weex_uid/okx_uid/bybit_uid/bitget_uid), optionalpublic_domain/public_plans; - assigns a unique referral code (
DSN-REF-...) if absent and binds the referrer whenreferrer_codeis provided; - may flag the node as a mining server and record its
user_reward_share_percentinhub_server_configs; - adopts legacy random-UUID nodes onto their deterministic wallet UUID (FK-safe re-key of telemetry/rewards/server-config children);
- guard rails:
virtual-*UUIDs are reserved; a legacy node's secret hash is never overwritten with a different value; wallet signatures are mandatory for wallet-bound nodes — preventing pre-registration hijack.
POST /api/v1/hub/nodes/ping is the heartbeat: it refreshes last_ping, latency, version, public domain, public_plans, auto-updates geolocation, upserts the server's reward share and binds referrer_code the first time one is presented. The live network is exposed by GET /api/v1/hub/nodes: non-banned, non-wallet-bound nodes with a ping in the last 5 minutes.
Wallet-bound nodes may revoke their telemetry credential via POST /api/v1/hub/nodes/revoke-telemetry (wallet signature required; secret_hash is cleared and the node can no longer report until re-keyed).
3. Telemetry Dispatch
When a position closes and the user has either is_mining_enabled or shareTelemetry set (auto-asserted when mining is active), the bot controller (_dispatch_telemetry_to_hub) performs:
- Saves a local
LOCAL_ONLYcopy (visible in the "Trades" UI tab). On a central hub (IS_CENTRAL_HUB=true) the report is evaluated in-process and the HTTP post is skipped entirely. - Computes
HMAC-SHA256over the exact serialized body (sort_keys=True). POSTs the report to the hub at/api/v1/hub/telemetry/reportwithX-Node-UUID,X-Node-Secret,X-Node-SignatureandX-Timestamp(epoch milliseconds; the hub rejects drift > 300 s with400) headers. The local exchange check is a no-op: eligibility is enforced solely by the hub against the publishedMiningConfig.- Marks the local copy
SENTwhen the hub acknowledges (a409duplicate is also treated as success).
The full payload schema, headers and signing rules are documented on the Telemetry Report API page.
If the node goes offline, telemetry_sync.py / the sync_pending_telemetry_task re-uploads any LOCAL_ONLY records later.
4. Scoring & Eligibility
On ingestion the hub computes an anti-abuse score and an estimated rebate.
Eligibility — a report is eligible only when:
- mining is enabled in
MiningConfigand the exchange is ineligibleExchanges; tradeModeisLIVE— paper/sandbox telemetry is stored but is excluded from mining, node trade views and promo quests (legacy rows without a recorded mode count as live);- hold time is at least
minTradeDurationSec(default 30 s) — anti-wash; - price movement ≥
minPriceMovementPercent(default0.15%of entry) — anti-instant-exit; the two conditions are combined withqualityGateOperator(AND, default, orOR= at least one must pass); a failed gate stores the reason inverification_errorand forcesscore = 0; - entry and exit prices are set and positive.
Score (score_trade_with_reason, of which _score_trade is the thin wrapper) — a hard gate plus a 0.5–1.0 weight (longer holds score higher, duration capped at 1 h). A score of 0 blocks mining; a score > 0 is stored on the report but does not change payout, which is proportional to rebate only.
Estimated rebate (_estimate_rebate) — tradeVolumeUsdt × 0.0005 (fee rate) × rebateRate[exchange_market], falling back to the bare exchange id and then to 0.60; the value is later replaced by the verified broker commission when a verifier covers that exchange. Volume is the notional open+close (|qty × entry| + |qty × exit|).
The report row stores score, is_mining_eligible, estimated_rebate_usdt, the exchange multiplier stamped at submission, and the initial verification status (PENDING / SKIPPED).
5. Verification Statuses
| Status | Meaning |
|---|---|
PENDING | Awaiting broker verification (exchange in the verifiable set: weex, bybit, okx, bitget). |
VERIFIED | Broker-verified; eligible to be credited by a mining epoch. |
SKIPPED | Terminal non-payable status: the submission quality gate rejected it, or no broker verifier covers the exchange. SKIPPED rows keep epoch_date IS NULL and are never credited by an epoch. |
REJECTED | Broker verification failed (no commission, wrong account, or unconfirmed after the grace window). Never mined. |
LOCAL_ONLY | Saved locally, not yet uploaded to the hub. |
SENT | Local copy acknowledged by the hub. |
Verification of PENDING reports happens in the daily epoch processor on the hub (closed-source broker verification in a private module). The open source manages the status columns (verification_status, verified_volume_usdt, verification_error, verified_at).
6. Mining Epochs
Rewards are minted once per UTC day by the Celery task process_mining_epoch_task (tasks.py; same logic behind POST /api/v1/hub/mining/process-epoch). The only private step is the broker verification pass; the persisted state is:
- Epoch day —
today − MINING_EPOCH_LAG_DAYS(default 1 → yesterday, UTC), unless forced. A day that has not fully ended is never finalized; the scheduled task runs a catch-up loop that settles every open past date oldest-first (max 10 per run, 30-day report lookback, 7-day calendar window), and a per-epoch Postgres advisory lock guarantees a day is finalized exactly once. Late-arriving reports for a past day are credited to the next epoch viaepoch_date IS NULL. - Verification pass over the epoch window (closed-source verifier).
- Eligible reports —
VERIFIED, eligible,created_at <= end-of-day,epoch_date IS NULL. Already-attributed reports are never re-added, so re-processing is idempotent.- If
PENDINGreports remain, the epoch is not finalized and re-queued.
- If
- Emission with halving:
daily_emission = daily_emission_base / 2**halvings. - Points — base points = Σ(
estimated_rebate_usdt × exchangeMultiplier[exchange]); referral points = base ×referral_mining_boost(credited to the referrer node). Tokens-per-point =daily_emission / total_points. - Reward per node — base reward + referral bonus, plus a one-time welcome bonus milestone when the node's cumulative
total_rebate_usdtreachesMIN_WELCOME_REBATE_USDT(default 1.0 USDT).- Welcome bonuses come from a dedicated 100M $DEPTH pool with progressive stages (1000 / 500 / 250 / 125 $DEPTH) and a per-UID claim cap.
- Per-report server commission — the reporting server keeps
(1 − share)of each report's gross base reward (shared_fromitshub_server_configs; otherwise global 75% default); the miner keepsshare.NULL/banned source routes the commission to the hub operator root (is_operator, else the first admin, by registration, who bound a wallet node); if no root exists the fee is not taken and the miner keeps the gross reward. Welcome and referral bonuses are emission-pool bonuses and are not subject to server commission. - Persist — upsert
MiningLedgerper node+epoch; incrementHubNode.total_mined; trackMiningConfig.total_operator_fee_collected.
The $DEPTH reward formula
dailyEmission = dailyEmissionBase / 2^(daysSinceLaunch / halvingIntervalDays)
tokenPerPoint = dailyEmission / Σ(basePoints + referralPoints)
baseReward(node) = Σ(estRebate(node) × multiplier) × tokenPerPoint
referralReward(node)= Σ(estRebate(referrals) × multiplier) × boost × tokenPerPoint
gross(perReport)= baseReward(node) × (weightedRebate / nodeTotalWeighted)
netBase = Σ gross × serverShareOf(source_server)
totalReward = netBase + referralReward + welcomeBonus
Every report is stamped with exchangeMultiplier[exchange] at submission; points (and therefore each report's share of the operator fee) are computed on the multiplied rebate. Default: bitget* 2.0, everything else 1.0.
Referral model
A node's referrer is resolved in priority order: explicit referrer_node_uuid → the owner user's referred_by relationship resolved to that user's mining node. Referrers earn boost × base points on every eligible trade of their referred nodes, plus a matching welcome grant at mint time. A node's referrer is bound once; changing an existing link requires a wallet signature or an admin POST /api/v1/hub/promo/admin/relink-node (hub only, audit-logged).
Promo campaigns & quests
Time-limited promo campaigns run on the hub: GET /api/v1/hub/promo/status shows the active campaign and per-quest progress; POST /api/v1/hub/promo/claim claims a completed quest. Quest progress derives from LIVE volume/trades only (paper rows never count); quest volume for a physical server only sticks while its node has pinged within 48 h, otherwise it is credited to the central server. Admin campaign management (/promo/admin/*) is hub-only.
Gamification
Mining achievements (api/gamification.py, MINING_ACHIEVEMENTS) — top-miner ranks, halving survivor, streaks, volume tiers — are granted after each epoch from the ledger, not from the report itself.
7. Configuration
Public mining settings: GET /api/v1/hub/mining/config (public), POST /api/v1/hub/mining/config (admin). Node-wide: GET/PUT /api/v1/config/mining/node-config (admin, on every deployment — one NodeMiningConfig row per instance).
Setting (MiningConfig) | Default | Meaning |
|---|---|---|
is_mining_enabled | false | Global switch |
eligibleExchanges | ["weex","weex_futures","weex_spot","okx","okx_futures","okx_spot","bybit","bybit_futures","bybit_spot","bitget","bitget_futures","bitget_spot"] | Eligible exchanges + market keys |
dailyEmissionBase | 547945.21 | Initial daily $DEPTH emission |
halvingIntervalDays | 365 | Days between halvings |
launchDate | NULL | Start date for the halving countdown |
minTradeDurationSec | 30 | Minimum hold time for eligibility |
minPriceMovementPercent | 0.15 | Min ` |
qualityGateOperator | "AND" | AND/OR combination of the duration & movement gates |
minTradePnlAbs | 0.0 | Not an active gate |
referralMiningBoost | 0.10 | Referral multiplier on base points |
rebateRates | see below | Rebate fraction per exchange_market |
exchangeMultipliers | {"bitget": 2.0, …} | Point multiplier stamped on the report and applied in every epoch/estimate |
Rebate rate defaults: weex_futures 0.60, weex_spot 0.45, weex 0.60, okx_futures / okx_spot / okx 0.30, bybit_futures / bybit_spot / bybit 0.50, binance_futures 0.25, bitget_futures / bitget_spot / bitget 0.35. A missing key falls back to the bare exchange id, then to 0.60.
NodeMiningConfig: is_global_mining_enabled (False by default — mining status stays dark until an admin flips it) and user_reward_share_percent (75% — positive values only; non-positive legacy values are treated as 75% in the epoch so rewards are never silently zeroed). Per-server: hub_server_configs.user_reward_share_percent.
8. Environment Variables
| Variable | Purpose |
|---|---|
IS_CENTRAL_HUB | true on the hub (no outbound reporting, owns the mining DB). |
FEDERATION_HUB_URL | Hub base URL for telemetry posts, mining status and the epoch proxy (falls back to VITE_HUB_API_URL, then API_URL). |
HUB_NODE_UUID / HUB_NODE_SECRET | Local node identity (non-wallet nodes). |
HUB_ADMIN_API_KEY | Admin key for hub config, epoch trigger and operator designation. |
MINING_EPOCH_LAG_DAYS | Epoch day = today − N (default 1). |
ALLOW_INSECURE_HUB_URL | Allows a non-HTTPS FEDERATION_HUB_URL (default false; localhost always allowed). |
WELCOME_BONUS_MAX_POOL | Welcome bonus total supply (default 100000000.0). |
MIN_WELCOME_REBATE_USDT | Cumulative rebate (USDT) milestone for the welcome bonus (default 1.0). |
MAX_NODES_PER_UID | Max welcome grants per Weex UID (default 1). |
Only IS_CENTRAL_HUB and VITE_HUB_API_URL ship in .env.example; every other variable here must be set explicitly on a hub/node deployment.
9. Operations Tooling
| Tool | Purpose |
|---|---|
POST /api/v1/hub/mining/process-epoch | Re-runs the epoch processor for a completed past day (admin; pass an explicit past epochDate). |
telemetry_sync.py + sync_pending_telemetry_task | Re-uploads LOCAL_ONLY reports to the hub after connectivity is restored. |
10. Security Model
X-Node-Secretis only sent over TLS; the hub stores only its SHA-256 hash and the raw secret is needed to compute the HMAC, so a leaked DB never exposes a usable signing key.- Payload tampering → HMAC mismatch →
403; duplicatebroker_trade_idon another node, or resubmission of a row already verified / epoch-attributed →409; a present-but-staleX-Timestamp(> 300 s drift) →400. - Attribution is restricted to the caller's own node or a node of the same owner (referral code / exchange UID on any supported exchange / bound EVM wallet), so trades can't be misattributed.
source_node_uuidmust point to a node flaggedis_mining_server.- No double-counting: reports carry
epoch_date, ledger upserts are additive and epochs are finalized exactly once. - Privacy: report carries no API keys, order IDs, risk config or private data.
The closed-source verifier is the only private component; telemetry intake, scoring, attribution, epoch math and the ledger all ship open-source.
Dynamic Risk Management
Comprehensive analysis of the 12-stage signal assessment pipeline, automatic blacklisting, dynamic trade size scaling, and portfolio-level risk limits inside the DepthSight RiskManager.
Telemetry Report API
The exact trade telemetry payload, node authentication headers, HMAC signature and the complete mining REST API surface of the central hub and local nodes.