Trade Mining

Trade Mining Overview

How DepthSight nodes mint $DEPTH by submitting anonymous trade telemetry — node identity, scoring, mining epochs and reward distribution.

⏱️ 12 min read📊 Level: Intermediate

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

TermMeaning
Central HubThe central deployment (IS_CENTRAL_HUB=true). Hosts the hub API, verifies trades, finalizes epochs and mints rewards.
HubNodeA node identity (node_uuid + node_secret) registered on the hub. Every miner and every mining server is a HubNode.
Mining serverA HubNode flagged is_mining_server=True. Hosts external miners and earns a commission on trades mined through it (source_node_uuid).
Miner nodeThe HubNode a specific trade is attributed to (node_uuid on the report).
Wallet-bound nodeA 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.
HubServerConfigPer-server override of the user/server reward share (default 75%).
$DEPTHThe 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).

Rendering diagram...

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 only sha256(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 in used_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 fresh mining_node_secret, wallet_address and wallet_configured=true in both the weex section and the top level of exchange_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.
  • 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), optional public_domain / public_plans;
  • assigns a unique referral code (DSN-REF-...) if absent and binds the referrer when referrer_code is provided;
  • may flag the node as a mining server and record its user_reward_share_percent in hub_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:

  1. Saves a local LOCAL_ONLY copy (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.
  2. Computes HMAC-SHA256 over the exact serialized body (sort_keys=True).
  3. POSTs the report to the hub at /api/v1/hub/telemetry/report with X-Node-UUID, X-Node-Secret, X-Node-Signature and X-Timestamp (epoch milliseconds; the hub rejects drift > 300 s with 400) headers. The local exchange check is a no-op: eligibility is enforced solely by the hub against the published MiningConfig.
  4. Marks the local copy SENT when the hub acknowledges (a 409 duplicate 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 MiningConfig and the exchange is in eligibleExchanges;
  • tradeMode is LIVE — 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 (default 0.15% of entry) — anti-instant-exit; the two conditions are combined with qualityGateOperator (AND, default, or OR = at least one must pass); a failed gate stores the reason in verification_error and forces score = 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

StatusMeaning
PENDINGAwaiting broker verification (exchange in the verifiable set: weex, bybit, okx, bitget).
VERIFIEDBroker-verified; eligible to be credited by a mining epoch.
SKIPPEDTerminal 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.
REJECTEDBroker verification failed (no commission, wrong account, or unconfirmed after the grace window). Never mined.
LOCAL_ONLYSaved locally, not yet uploaded to the hub.
SENTLocal 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:

  1. 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 via epoch_date IS NULL.
  2. Verification pass over the epoch window (closed-source verifier).
  3. 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 PENDING reports remain, the epoch is not finalized and re-queued.
  4. Emission with halving: daily_emission = daily_emission_base / 2**halvings.
  5. 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.
  6. Reward per node — base reward + referral bonus, plus a one-time welcome bonus milestone when the node's cumulative total_rebate_usdt reaches MIN_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.
  7. Per-report server commission — the reporting server keeps (1 − share) of each report's gross base reward (shared_from its hub_server_configs; otherwise global 75% default); the miner keeps share. 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.
  8. Persist — upsert MiningLedger per node+epoch; increment HubNode.total_mined; track MiningConfig.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)DefaultMeaning
is_mining_enabledfalseGlobal 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
dailyEmissionBase547945.21Initial daily $DEPTH emission
halvingIntervalDays365Days between halvings
launchDateNULLStart date for the halving countdown
minTradeDurationSec30Minimum hold time for eligibility
minPriceMovementPercent0.15Min `
qualityGateOperator"AND"AND/OR combination of the duration & movement gates
minTradePnlAbs0.0Not an active gate
referralMiningBoost0.10Referral multiplier on base points
rebateRatessee belowRebate 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

VariablePurpose
IS_CENTRAL_HUBtrue on the hub (no outbound reporting, owns the mining DB).
FEDERATION_HUB_URLHub 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_SECRETLocal node identity (non-wallet nodes).
HUB_ADMIN_API_KEYAdmin key for hub config, epoch trigger and operator designation.
MINING_EPOCH_LAG_DAYSEpoch day = today − N (default 1).
ALLOW_INSECURE_HUB_URLAllows a non-HTTPS FEDERATION_HUB_URL (default false; localhost always allowed).
WELCOME_BONUS_MAX_POOLWelcome bonus total supply (default 100000000.0).
MIN_WELCOME_REBATE_USDTCumulative rebate (USDT) milestone for the welcome bonus (default 1.0).
MAX_NODES_PER_UIDMax 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

ToolPurpose
POST /api/v1/hub/mining/process-epochRe-runs the epoch processor for a completed past day (admin; pass an explicit past epochDate).
telemetry_sync.py + sync_pending_telemetry_taskRe-uploads LOCAL_ONLY reports to the hub after connectivity is restored.

10. Security Model

  • X-Node-Secret is 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; duplicate broker_trade_id on another node, or resubmission of a row already verified / epoch-attributed → 409; a present-but-stale X-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_uuid must point to a node flagged is_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.