Generate a permissioned trading key
The wizard in /app/settings creates a fresh on-chain authenticator for the bot to sign trades — without ever touching your mnemonic.
What gets created
On click, the wizard generates a random secp256k1 keypair in your browser. This is the "trading key" — a separate cryptographic identity used solely to sign place/cancel orders.
It then asks Keplr (using your owner wallet) to sign a single MsgAddAuthenticator transaction. That transaction registers the trading key's public part on-chain as a delegated signer with a hardcoded whitelist: place + cancel orders only, only on ETH/SOL/BNB, only on subaccount 0. Nothing else.
Walking through the wizard
Step 1 (Keplr detect): the wizard checks for window.keplr. If missing, you get a link to install. If present, it calls keplr.enable('dydx-mainnet-1') and reads your owner address from getOfflineSigner.
Step 2 (pre-flight): fetches the clob_pair_ids for ETH/SOL/BNB from the public indexer, then checks your bank balance has at least ~0.02 DYDX for gas. If short, you see a "need a small gas top-up" panel with your address shown for top-up.
Step 3 (generate + sign): builds the trading-key + authenticator-data, opens a Keplr popup asking you to sign MsgAddAuthenticator. You approve in Keplr (or on Ledger if you've connected one).
Step 4 (discover): after broadcast, the wizard waits ~8 seconds, queries the REST node for your authenticators, and finds the one it just registered. This gives the authenticator id (a small integer).
Step 5 (persist + display): the trading-key private key is POSTed to /api/permissioned-keys/register, where the server AES-256-GCM encrypts it and stores it in your PermissionedKey DB row. The wizard then shows the .env block — three lines (DYDX_OWNER_ADDRESS, DYDX_API_PRIVATE_KEY, DYDX_AUTHENTICATOR_ID) for you to paste into your bot host.
Saving the .env block
The cleartext private key is shown ONCE, on this success screen. Botely keeps an encrypted copy in DB (for Phase 1 multi-tenant readiness), but cannot decrypt it back to plaintext for you. Save the block in 1Password / Bitwarden / your vault of choice before clicking Done.
If you lose the .env block, you can't recover the private key — but you can cheaply revoke the existing trading key and run the wizard again (~$0.50 of gas). It's not a catastrophe, just an inconvenience.
After the wizard
Phase 0: paste the three env vars into the bot host's .env (typically /etc/botely-saas.env or ~/crypto-bot/.env), then `pm2 restart crypto-bot`. The bot's dydxClient detects the triple at boot and switches signing mode to permissioned automatically — no code change.
Keep DYDX_MNEMONIC in the .env for 48 hours as a rollback parachute. Once you've seen the bot trade successfully under permissioned signing for two days, remove the mnemonic line and restart again.