# ──────────────────────────────────────────────────────────────────────────── # canary — configuration # Copy this file to `.env` and fill in the blanks. `.env` is git-ignored. # NOTHING here is ever sent to the browser; the dashboard only sees the backend # over a local WebSocket. Never commit your real .env or keypair. # ──────────────────────────────────────────────────────────────────────────── # ── Mode ────────────────────────────────────────────────────────────────────── # replay : fully simulated. No real transaction, no spend. Fires a scripted # fill a few seconds after start. Re-run the trigger infinitely for # free while you rehearse / re-shoot. (Safe default — needs no keys.) # armed : places a REAL Jupiter trigger order at TARGET_PRICE_USD (set it below # spot — this is a buy-the-dip canary) and genuinely waits for the # market to trade down to your level. Cancels the resting order on exit. # live : places a REAL order at ~current spot so it fills within seconds on # camera, proving the genuine end-to-end pipeline. MODE=replay # ── Quicknode Solana gRPC (the hero — required for armed/live) ──────────────── # Enable the "Solana gRPC" add-on on a Quicknode Solana Mainnet endpoint. # gRPC runs on a dedicated port 10000 (this is NOT your https RPC URL). # Given an HTTP endpoint like: # https://example-name.solana-mainnet.quiknode.pro/abc123token/ # split it into host:10000 and the token segment: QUICKNODE_GRPC_ENDPOINT=https://example-name.solana-mainnet.quiknode.pro:10000 QUICKNODE_GRPC_TOKEN=abc123token # ── Wallet (required for armed/live; ignored in replay) ─────────────────────── # A funded mainnet keypair with a little USDC (>= the order size below) and some # SOL for fees. Accepts EITHER a base58 secret-key string OR a path to a Solana # CLI keypair JSON file (the `[12,34,...]` byte-array format). # Use SOLANA_KEYPAIR or PRIVATE_KEY — whichever you prefer. SOLANA_KEYPAIR= # PRIVATE_KEY= # ── Order ────────────────────────────────────────────────────────────────────── # BTC on Solana = cbBTC (Coinbase Wrapped BTC), redeemable 1:1 for BTC. 8 decimals. # Pre-filled. (To use a different BTC, confirm its decimals first — see the README.) BTC_MINT=cbbtcf3aa214zXHbiAZQwf4122FBYbraNdFqgw4iMij # armed mode only: the USD price to rest at and wait for. The canary picks its # direction automatically from this vs. spot (BTC trades around $60k–$70k): # • target BELOW spot → buy-the-dip canary (spend USDC, fires on a dip). # • target ABOVE spot → breakout canary (sells BTC, fires when it breaks up). # For the sell side we first market-buy a little BTC so there's something # to sell (see SOLANA_RPC_URL below). Leftover BTC dust stays in the wallet. # A target more than ~15% from spot is flagged as a likely misconfiguration (it # may never fill) but still placed. Leave blank in live mode — it auto-targets ~spot. # e.g. TARGET_PRICE_USD=64000 rests ~2% under a ~$65,660 spot (a buy-the-dip canary). TARGET_PRICE_USD= # Notional size of the canary order in USD. Jupiter Trigger V1 enforces a ~$5 # minimum, so "tiny" means about $5 (not $1–2). At ~$65k BTC, $5 ≈ 0.00007615 BTC. ORDER_SIZE_USD=5 # ── Strategy hook (what runs when the canary fires — see src/server/onTrigger.ts) ─ # log : (default) just print the fill. No side effects, no funds move. # webhook : POST the fill JSON to TRIGGER_WEBHOOK_URL (Slack/Discord/Telegram-ready). # swap : a REAL, small Jupiter spot swap (buys TRIGGER_SWAP_USD more BTC). # Moves real money — gated behind I_UNDERSTAND_REAL_MONEY=true, capped at $25. TRIGGER_ACTION=log # TRIGGER_WEBHOOK_URL= # TRIGGER_SWAP_USD=2 # I_UNDERSTAND_REAL_MONEY=false # ── Optional ─────────────────────────────────────────────────────────────────── # HTTP RPC, used ONLY by a sell-side (breakout) canary to check the BTC balance # and market-buy the small amount it needs to sell. If you leave this blank it is # derived automatically from your Quicknode gRPC endpoint + token above. A plain # buy-the-dip canary (and replay/live) never touches it. # SOLANA_RPC_URL= # Jupiter API key. Without one we use the keyless lite-api host (fine for this # demo's request volume). With one, set JUP_TRIGGER_BASE to the api.jup.ag host. # JUP_API_KEY= # JUP_TRIGGER_BASE=https://lite-api.jup.ag/trigger/v1 # Local dashboard WebSocket port (must match the browser; 8787 by default). # WS_PORT=8787