Learn

How a Vectr wallet guards its key

Signing in with X gives you a custodial wallet whose key Vectr's backend holds, so that you, your agent and your scheduled orders can trade without a browser extension. This guide covers how that key is stored, the only code paths that decrypt it, and every rule a transaction must pass first. It is read from the backend source and the live security block of GET /config.

Updated

At rest

How the key is stored

Created
at first X sign-inA fresh random private key, encrypted before the account row is written
Cipher
AES-256-GCMA random 12-byte IV for every encryption and a 16-byte authentication tag: a ciphertext that was altered fails to decrypt
Key that encrypts it
server master keyA 256-bit key held in the server environment, not in the database
In the database
ciphertext, IV, tagNo plaintext key, and nothing that decrypts it on its own
  • Wallet key encrypted with
    KMS envelope
    A 256-bit data key generated by AWS KMS for that wallet
    Master key
    One 256-bit key from the server environment
  • Stored beside the ciphertext
    KMS envelope
    The data key, encrypted by KMS
    Master key
    Nothing
  • To decrypt
    KMS envelope
    A KMS Decrypt call for the data key, then AES-256-GCM
    Master key
    AES-256-GCM with the master key
  • A database dump alone yields
    KMS envelope
    Ciphertext only
    Master key
    Ciphertext only
  • Key-encryption key
    KMS envelope
    Stays inside AWS KMS; decrypting a wallet takes a KMS Decrypt call for its data key
    Master key
    Lives in the server environment; whoever holds it can decrypt every wallet encrypted under it
  • On this deployment
    KMS envelope
    Not enabled
    Master key
    In use here

The mode comes from platform.security.custody.custodialWallet.kmsEnvelope, which the backend sets from its own environment at boot.

Decryption

The four places a key is decrypted

Nothing else in the backend calls the decryption function. In every case the plaintext key lives in memory for that one call.

The signing service
POST /wallet/sign-and-submit

After the calldata whitelist, the API key's own limits and every wallet rule have passed.

A scheduled order fill
limit, stop, DCA, TWAP

When an order you created comes due, after the same wallet rules. The calldata is built by the backend itself.

An auto top-up
FeeCollector.depositPlatformFee()

Only if you turned auto top-up on, after the wallet rules, within the daily cap you set.

A key export
POST /wallet/export-key

Only after a fresh X login, and then only sealed to a key your browser generated. See the export section.

Boundary

What can ask the wallet to sign

With a Vectr wallet, after you confirm, Vectr's wallet service signs the validated transaction from your encrypted custodial wallet, subject to your spending limits and allowlists. That confirmation is per transaction in the Terminal; the other paths below either never sign or were authorised once, up front.

  • Terminal: swap, launch, transfer
    How it signs
    The agent turns your request into a typed intent and builds an unsigned transaction. You review and confirm it before your wallet signs and broadcasts it.
    A click per transaction
    Yes
  • Agent job over API, MCP or CLI
    How it signs
    Through the API, MCP server or CLI, an agent job returns the unsigned transaction and stops there: nothing is signed or broadcast until you submit it yourself.
    A click per transaction
    Nothing signs
  • Limit, stop, DCA and TWAP orders
    How it signs
    Limit, stop, DCA and TWAP orders are authorised once, when you create them in the order form or give the agent their parameters. After that, eligible fills execute automatically from your wallet under the spending, recipient and contract controls you set.
    A click per transaction
    No: authorised once
  • Auto top-up of AI credits
    How it signs
    Off unless you turn it on. When the credit balance cannot cover the next agent turn, or drops under your threshold after one, the backend buys credits with ETH from the wallet, within the daily cap you set.
    A click per transaction
    No: authorised once
  • Read-write API key
    How it signs
    A read-write API key is the automation path: it can submit transactions from your Vectr wallet without a person in the loop, inside the key's limits. A read-only key can never sign, submit or create orders.
    A click per transaction
    No
Pipeline

What a signing request passes, in order

POST /wallet/sign-and-submit, the route the Terminal and read-write keys use. Scheduled fills and auto top-ups never reach this route: the backend builds their calldata itself, and they start at the wallet rules.

  1. 1
    Route guardthrottle and auth
    30 requests a minute per client. The caller needs a session or an active API key, used from an address on the key's IP list if it has one.
  2. 2
    Key scopewallet-mgr.controller
    A request made with a read-only API key is refused with 403 here.
  3. 3
    Signer rate limitper account
    20 signing calls a minute for the account, however many keys or sessions they come from, so a runaway script cannot fire faster than you can react.
  4. 4
    Calldata whitelistvalidateCalldata
    The transaction must declare its type, its 4-byte selector must be on that type's list, and trade, launch and credit-purchase targets must be known contracts. Malformed calldata fails here, before the key is touched.
  5. 5
    The key's recipient listper API key
    If the API key was created with recipient addresses, the transaction's to address must be one of them.
  6. 6
    Wallet rulesSecurityService.enforce
    Pause, contract-call guard, recipient allowlist and cooldown, pricing, per-transaction limit, 24-hour limit, in that order. The first failure ends the request with its reason.
  7. 7
    Decrypt and signCryptoService
    Only now is the key decrypted, for this call alone. If the transaction needs an ERC-20 approval, that is sent and confirmed first.
  8. 8
    Recordaudit log
    The signature is logged with its type, target, USD value and hash, and the USD value is added to the wallet's 24-hour total.
Whitelist

What each transaction type may call

Checked against the calldata before the key is decrypted. A selector that is not on its type's list is refused, whatever produced it.

An approval that travels with a trade may only be an ERC-20 approve, granted to the trade contract itself (or the factory, for a launch), over the token being sold or the pairing asset being spent. Where a target is not pinned, your allowlists and USD limits are what bound the transaction, which is one reason to set them.

Your rules

The controls you set

In the Security tab of your profile. Only a signed-in session can read or change them; an API key cannot. The values on the right are what a wallet that has never saved its settings is checked against.

Pause switch
offStops every signature: Terminal, API keys, scheduled fills, auto top-ups. Keys stay valid
Per-transaction limit
$500USD, from 1 to 1,000,000, or none. A wallet that has never saved its settings is held to $500
24-hour limit
noneUSD over a sliding 24 hours, not a calendar day: no midnight reset to wait for
No price, no signature
fail closedWith either limit on, a transaction whose value cannot be priced is refused
Recipient allowlist
emptyOnce it has entries, every transaction must be sent to one of them, or to the wallet itself
Recipient cooldown
24 h0 to 168 hours. A new entry cannot receive until it has aged; removing and re-adding restarts it
Contract-call guard
offWhen on, refuses buys, sells, launches, fee claims and credit purchases; transfers still pass the other rules
Anomaly flag
log onlyA transfer of $50 or more to a new recipient, above 3x the wallet's recent average, is logged for review. It does not block

USD value is what the transaction spends: ETH sent as value, priced at the ETH rate, or on a buy or launch paid in an ERC-20, the approved amount at that asset's USD price. For a Stock Token that price is Robinhood's quote times the multiplier, as Stock Token pairing explains.

The recipient allowlist checks the address a transaction is sent to, which for a trade is the curve or router it calls, so a wallet that trades with the list switched on needs those contracts on it too. Separately, the agent will only build a transfer to an address already on the list, whether or not the list is otherwise in use. The cooldown exists for the case where someone else has your session: an address they add cannot receive until you have had time to see it and remove it.

The contract-call guard is the lockdown switch for a wallet whose agent or key you no longer trust: trading stops, while transfers still work under your allowlist and limits. The pause switch stops everything.
Export

Taking the key out

The backend's export route is built behind these gates; GET /config does not list export as available yet.

Status on this deployment
not listed as availableGET /config reports exportable: false
Gate
fresh X loginA new X sign-in mints a single-use grant, valid for 5 minutes, bound to the session, IP address and browser that earned it
Attempts
3 per hourEvery attempt from a signed-in session, allowed or refused, is written to the audit log
Delivery
sealed to your browserEncrypted to a one-time key your tab generates (ECDH P-256, HKDF-SHA256, AES-256-GCM), so the plaintext never crosses the wire

An exported key is outside every rule on this page. Whoever holds a copy can sign anything, and the pause switch, limits and allowlists no longer apply to them.

Limits

What custody still means

A custodial wallet is as safe as the servers that hold its ciphertext and the key that decrypts it; the controls above narrow what a stolen session, a leaked API key or a misled agent can do, not what a compromise of those servers could. If you want no one else to hold a key, connect your own wallet: Vectr builds the transaction and your wallet signs it, and none of the custodial paths above exist for you. API keys, which are the widest door into a custodial wallet, have their own guide: read-only and read-write API keys. The signing pipeline from the model's side is in how an AI agent trades, the summary of every control on the security page, and the risks in the risk disclosure.

FAQ

Wallet security questions

Does Vectr store my wallet's private key?

It stores it encrypted. The key is generated when you first sign in with X and encrypted with AES-256-GCM before it is written to the database, under a 256-bit key-encryption key held in the server environment, not in the database. It is decrypted only inside four code paths, each after its own checks.

Can an AI agent drain my Vectr wallet?

The model never sees a key or writes raw calldata; it produces typed intents, and the backend builds the transaction. Anything that reaches the signer still has to pass the calldata whitelist and your wallet rules. The exposure is what you have authorised to run without a click: scheduled orders, auto top-up if it is on, and any read-write API key you gave out, each capped by your USD limits and allowlists.

What does the pause switch stop?

Every signature for the wallet: Terminal confirmations, read-write API keys, scheduled order fills and auto top-ups. It does not revoke anything, so turning it off resumes where you left off.

Is the 24-hour limit a calendar day?

No. It is a sliding 24-hour window, so there is no midnight reset for anyone to wait for. The running total is the USD value of what the signing service has signed for the wallet in the last 24 hours.

What happens if the price feed is down?

If a per-transaction or 24-hour limit is on and the transaction's value cannot be priced, it is refused. With no USD limit set, pricing is not needed and the other rules still apply.

Can an API key change my security settings?

No. Reading and changing the pause switch, limits, allowlist and cooldown takes a signed-in session. So do creating and revoking keys and exporting the wallet key. An API key can only use the wallet inside the rules the session set.