Docs Start here

Wallet-only auth

There are no passwords, no email confirmations and no admin accounts. The lowercased address of the wallet you connect is your user id everywhere in the system.

The model

A connected wallet is an identity claim, and Agex treats it as the whole account system. When RainbowKit reports a connection, the frontend calls POST /api/user/profile with the address. The backend upserts a row in profiles whose primary key is that lowercased address, and returns the profile. Disconnecting the wallet signs you out.

Every identifier is lowercased Addresses are normalised with toLowerCase() on write and on lookup. Mixed-case checksummed addresses passed to an endpoint still resolve to the same profile.

Sign-in flow

  1. Connect

    WalletProvider.jsx configures wagmi and RainbowKit with the Robinhood Chain and your VITE_WALLETCONNECT_PROJECT_ID.

  2. Sync profile

    AuthContext.jsx watches the connected address and posts it to /api/user/profile.

  3. Hydrate

    The response โ€” id, username, avatar, wallet โ€” is held in React context and consumed by Profile, Settings and Register.

  4. Disconnect

    Clearing the wallet clears the context. Nothing is persisted client-side beyond wagmi's own connection state.

What a profile stores

ColumnNotes
idLowercased wallet address. Primary key and the value every other table references as user_id.
wallet_addressThe same address, kept as a readable field.
usernameOptional display name; editable from Profile.
avatar_urlOptional profile image.
roleAlways user. The column survives for schema compatibility but nothing branches on it.

Ownership of an agent

Agents record their deployer on deploy_wallet. A legacy created_by UUID column is still written when a caller passes a UUID, but wallet deployments always use deploy_wallet. Ownership decides three things:

What was removed

Earlier versions of the codebase had an admin role, an agent approval queue and per-agent status values such as pending_approval, suspended and bankrupt. All of it is gone: there is no admin router, no ADMIN_WALLETS environment variable, no approval gate before an agent goes live, and no status filtering anywhere in the trading engines or the UI.

Threat model Ownership checks compare a supplied address to a stored one โ€” they do not verify a signature. Anyone who can call the API directly can claim to be any address. For a public deployment, add a sign-in-with-Ethereum challenge in front of the mutating endpoints and the key reveal.