Database Schema
This document outlines the database schema for the NextNonce backend. The schema is defined and managed using Prisma, which serves as the single source of truth for data models.
While the underlying database is PostgreSQL, the models are defined in a database-agnostic way. This abstraction is key to this architecture, as it allows for potential migration to other supported databases (like CockroachDB, MySQL, MongoDB, etc.) in the future without altering the application's data access logic. The types defined in schema.prisma
are what matters, not the specific PostgreSQL column types.
The schema is logically divided into two main parts:
-
User, Portfolio, and Wallet Data: Manages user accounts, their portfolios, and the wallets they track.
-
Chain, Token, and Market Data: Stores information about blockchains, tokens, and their market prices.
1. User, Portfolio, and Wallet Data
This part of the schema is centered around the User
and the entities they own and manage within the application.
Model Explanations
Auth
-
Purpose: Stores user authentication credentials. This model is crucial for decoupling the application from any single authentication provider. A new
Auth
record is created when a user signs up, linking their external authentication method (theprovider
, e.g., Supabase) to an internalUser
record. -
Key Fields:
-
provider
: The name of the authentication service (e.g., "supabase-email"). -
providerUid
: The user's unique identifier from the external auth provider.
-
-
Relations:
- Has a one-to-one relationship with
User
. A user has one auth record, and an auth record belongs to one user. TheonDelete: Cascade
ensures that if aUser
is deleted, their associatedAuth
record is also removed. This design means we are not coupled to the auth provider's ID system; internalUser.id
is the primary identifier, allowing us to change auth providers in the future with minimal friction.
- Has a one-to-one relationship with
User
-
Purpose: The central model representing an application user.
-
Key Fields:
-
id
: The primary unique identifier for a user within the system. -
email
: The user's email address.
-
-
Relations:
-
Has a one-to-one relationship with
Auth
. -
Has a one-to-one relationship with
Watchlist
. -
Has a one-to-many relationship with
Portfolio
(a user can own multiple portfolios).
-
Portfolio
-
Purpose: Represents a user-created collection of wallets. This is the primary organizational unit for tracking assets. The schema supports a user having multiple portfolios, allowing for flexible asset organization (e.g., "DeFi", "Long-term", "Trading").
-
Note: While the backend and schema support multiple portfolios per user, the mobile application currently implements a single default portfolio for simplicity.
-
Key Fields:
-
name
: A user-defined name for the portfolio (e.g., "DeFi Holdings", "Trading Wallet"). -
portfolioAccess
: An enum (PRIVATE
,PUBLIC
,UNLISTED
) that controls the visibility of the portfolio.
-
-
Relations:
-
Belongs to one
User
(the owner).onDelete: Cascade
ensures that deleting a user also deletes all of their portfolios. -
Has a one-to-many relationship with
PortfolioWallet
(a portfolio can contain links to many wallets).
-
Wallet
-
Purpose: Represents a unique blockchain wallet, identified by its address. This is a globally unique entity.
-
Key Fields:
-
address
: The wallet's public address (e.g.,0x...
). This is the primary unique identifier. -
walletType
: An enum (SIMPLE
for EOA,SMART
for smart contract wallets). -
chainType
: An enum (EVM
,CAIROVM
, etc.) indicating the wallet's underlying blockchain technology.
-
-
Relations:
-
Has a many-to-many relationship with
Portfolio
via thePortfolioWallet
join table. -
Has a many-to-many relationship with
Watchlist
.
-
PortfolioWallet
-
Purpose: This is a join table that links a
Wallet
to aPortfolio
. It allows a singleWallet
to be included in multiple portfolios and for aPortfolio
to contain multiple wallets. -
Key Fields:
name
: An optional, user-defined alias for the wallet within the context of a specific portfolio.
-
Relations:
-
Belongs to one
Portfolio
.onDelete: Cascade
ensures that if a portfolio is deleted, all its wallet links are also removed. -
Belongs to one
Wallet
.
-
Watchlist
-
Purpose: Represents a user's list of wallets they want to monitor without necessarily grouping them into a portfolio.
-
Note: This feature is fully supported by the database schema but has not yet been implemented in the application.
-
Relations:
-
Belongs to one
User
. -
Has a many-to-many relationship with
Wallet
. A user can watch many wallets, and a wallet can be watched by many users.
-
2. Chain, Token, and Market Data
This part of the schema stores all the public, non-user-specific data related to blockchains, cryptographic tokens, and their financial value.
Model Explanations
Chain
-
Purpose: Represents a specific blockchain supported by the application.
-
Key Fields:
-
name
: The unique name of the chain (e.g., "Ethereum", "Polygon"). -
chainType
: An enum (EVM
, etc.) classifying the blockchain. -
logo
: A URL to the chain's logo.
-
-
Relations:
- Has a one-to-many relationship with
Token
(a chain can have many tokens).
- Has a one-to-many relationship with
TokenMetadata
-
Purpose: Stores the static, chain-agnostic metadata for a token, such as its name, symbol, and logo. This data can be shared by multiple
Token
records across different chains. -
Key Fields:
-
symbol
: The token's ticker symbol (e.g., "USDC"). -
name
: The full name of the token (e.g., "USD Coin"). -
decimals
: The number of decimal places the token uses.
-
-
Relations:
-
Has a one-to-many relationship with
Token
(one set of metadata can apply to tokens on multiple chains). -
Has a one-to-one relationship with
UnifiedToken
.
-
Token
-
Purpose: Represents a specific token contract on a specific blockchain.
-
Key Fields:
address
: The contract address of the token on its chain. A special value of"native"
is used for the chain's native currency (e.g., ETH on Ethereum).
-
Relations:
-
Belongs to one
Chain
. -
Belongs to one
TokenMetadata
. This links the on-chain token to its shared metadata. -
Optionally belongs to one
UnifiedToken
. This is the link that groups this specific token into a unified asset view. -
Has a one-to-many relationship with
TokenPrice
.
-
UnifiedToken
-
Purpose: The core of token aggregation feature. This model groups multiple
Token
records (e.g., USDC on Ethereum, USDC on Polygon) into a single, logical entity. -
Relations:
-
Belongs to one
TokenMetadata
. -
Has a one-to-many relationship with
Token
.
-
TokenPrice
-
Purpose: Stores historical price data for a specific token.
-
Key Fields:
-
priceUsd
: The token's price in USD at a given time. -
timestamp
: The timestamp for when the price was recorded.
-
-
Relations:
- Belongs to one
Token
.
- Belongs to one