Your keys. Your machine. Your call.
AES-256-GCM encrypted vault · scrypt key derivation · explicit approval at every financial edge · zero plaintext in logs or memory dumps.
The vault
API credentials live encrypted — per user, per session.
scrypt key derivation against a per-user salt means the same secret decrypts nothing across users. No shared-state attack surface.
CredentialVault.ts
Format: salt:iv:authTag:ciphertext · base64 · colon-separated
// Key derivation
derivedKey = scrypt(
ENCRYPTION_SECRET + ':' + userId,
salt, // 16 random bytes, per credential
32 // bytes = AES-256 key
)
// Encrypt
iv = randomBytes(12) // 96-bit IV, required for GCM
cipher = createCipheriv('aes-256-gcm', derivedKey, iv)
ct = cipher.update(plaintext) + cipher.final()
authTag = cipher.getAuthTag() // 16 bytes — tamper protection
// Storage
row = [salt, iv, authTag, ct]
.map(b => b.toString('base64'))
.join(':')AES-256-GCM
Authenticated encryption — any tampering fails the auth tag check
Per-user salt
Compromising one user's key does not compromise anyone else's
Plaintext never logged
Scrubbed from Pino logs and Sentry breadcrumbs at the source
3-gate approval
Cross-exchange trades never fire without you.
Three explicit checkpoints — any of them you can walk away from. No auto-submit, no hidden defaults, no dark patterns.
Gate 1 · Buy
User reviews price, fees, and balance, then approves the buy order on the source exchange.
Order placed · balance decremented · source exchange confirms fill
Gate 2 · Withdraw
After buy fills, user enters the destination address, verifies the network, and approves withdrawal.
Address whitelist · network fee preview · 2FA at exchange edge
Gate 3 · Sell
Once crypto lands on the destination exchange, user approves the final sell. Profit is realized.
Re-quote before execution · slippage check · predicted vs actual logged
Ghost liquidity defense
Four-layer suspended-coin filter
Delisted or frozen coins look liquid on the surface — they'll happily show a last price. We filter at every layer so you never try to route through them.
Gate.io public API
Every coin with deposit_disabled or withdraw_disabled is skipped at fetch time.
Graph route engine
Requires real bid AND ask to build an edge — no fallback to last price, no ghost liquidity.
Arbitrage scanner
Same bid/ask guard applies. Any pair missing real quotes is dropped from the scan window.
UI filter
Client-side spread sanity check (< 2%) removes the last stragglers before we ever offer them to you.
Risk manager
Seven defaults. Every one overridable.
Opinionated out of the box, adjustable to your mandate. Every threshold below applies before a trade is ever submitted.
| Threshold | Default | Effect |
|---|---|---|
| maxLossPerCyclePct | 2% | Pre-trade rejection if projected loss exceeds 2% of the session balance. |
| maxDailyLossPct | 5% | Hard stop for the day. Sessions auto-pause and require user reset. |
| maxPositionSizePct | 50% | Single trade capped at half the current balance. |
| minProfitThresholdPct | 0.3% | Trades below this expected edge never fire. |
| consecutiveLossLimit | 3 | Three losses in a row triggers an auto-pause. |
| cooldownAfterLossSeconds | 300s | Five-minute wait after a losing cycle before the bot resumes. |
| maxOpenPositions | 1 | One concurrent position per session — no pyramiding. |
Local-first
Keys never leave your machine. Full stop.
The Tauri desktop app runs the Node sidecar locally. API credentials are encrypted client-side and stored on your disk. The auth server sees user sessions — never exchange keys.
Desktop
Bundled Node sidecar handles every signed request. Exchange traffic goes direct from your IP — nothing transits our infrastructure.
Web
Encrypted vault syncs with your account, decryption happens on-device at trade time. Secret rotation means revoking a leaked vault secret is a one-click op.
Trust is a stack, not a slogan.
Every layer above is in production today. Ask hard questions — we ship the answers in code.