Skip to main content

Data model

All tables live in Neon Postgres, defined via Drizzle under apps/api/src/db/schema/. Every table has a uuid primary key, createdAt and updatedAt timestamps unless noted.

Entity relationships

Table detail

users

ColumnTypeNotes
iduuidPK
privyDidtextUnique — from Privy user_id
emailtext nullable

wallets

The user typically has both a privy_embedded (EOA) row and a privy_smart_wallet row — the smart wallet is the one funded and sent from.

ColumnTypeNotes
userIduuidFK → users
addresstextUnique — 0x address on Base
signerAddresstextNullable — EOA signer for smart wallets
typeenumprivy_smart_wallet | privy_embedded | external

kyc_verifications

ColumnTypeNotes
userIduuidFK → users
bridgeKycIdtextUnique nullable — Bridge KYC link id
bridgeCustomerIdtextNullable — set once Bridge issues a customer id
statusenumpending | approved | rejected

virtual_accounts

Destination for fiat in (deposits). One per currency per user.

ColumnTypeNotes
userIduuidFK → users
bridgeVaIdtextUnique — Bridge VA id
currencyenumgbp | eur
paymentRailenumfps | sepa
bankNametextNullable
accountHolderNametextNullable
accountNumber / sortCodetextGBP only, nullable
iban / bictextEUR only, nullable
depositInstructionsjsonbRaw Bridge payload
statusenumactive | closed

bank_details

User's own bank account, used as the withdraw destination. Unique on (userId, currency).

ColumnTypeNotes
userIduuidFK → users
currencyenumgbp | eur
accountHolderNametext
accountNumber / sortCodetextGBP only
iban / bictextEUR only
bridgeLiquidationAddresstextNullable — set on first withdraw, reused thereafter

transactions

Ledger of every USDC movement — deposits (inbound), and withdrawals + PIX (outbound).

ColumnTypeNotes
userIduuidFK → users
typeenumdeposit | withdrawal
amountUsdcnumeric6-decimal USDC amount
toAddresstextNullable — the liquidation address for outbound
txHashtextUnique nullable — Base tx hash
bridgeTransferIdtextNullable
liquidationAddresstextNullable
fiatAmountnumericNullable
fiatCurrencyenumgbp | eur | brl — nullable
statusenumpending | completed | confirmed | failed
failureReasontextNullable

Transaction state machine

pix_payments

PIX-specific detail row, linked 1-to-1 with a transaction.

ColumnTypeNotes
userIduuidFK → users
transactionIduuidNullable FK → transactions
amountBrlnumericMerchant-facing amount
amountUsdcnumericUSDC debited from user's wallet
exchangeRatenumericUSD/BRL rate at creation time
pixKeytext
pixKeyTypeenumcpf | cnpj | email | phone | random
recipientNametextNullable
statusenumpending | processing | completed | failed
bridgePaymentIdtextNullable
pixEndToEndIdtextNullable — set once PIX network confirms
failureReasontextNullable

webhook_events

Idempotency ledger for Bridge webhooks — one row per unique bridgeEventId.

ColumnTypeNotes
bridgeEventIdtextUnique
eventTypetexte.g. liquidation_address.drain_completed
payloadjsonbFull raw webhook body
processedAttimestampNullable — set when handler successfully finishes

Zod contract — where to look

Every API endpoint request/response has a Zod schema in packages/shared/src/. See API endpoints for the full list.