95 lines
4.4 KiB
SQL
95 lines
4.4 KiB
SQL
-- Migration: Add Linked Wallets for Web3 Integration
|
|
-- Date: 2026-01-02
|
|
-- Description: Enables CryptID users to link Ethereum wallets for
|
|
-- on-chain transactions, voting, and token-gated features.
|
|
-- Related: task-007, doc-001
|
|
|
|
-- =============================================================================
|
|
-- LINKED WALLETS TABLE
|
|
-- =============================================================================
|
|
-- Each CryptID user can link multiple Ethereum wallets (EOA, Safe, hardware)
|
|
-- Linking requires signature verification to prove wallet ownership
|
|
|
|
CREATE TABLE IF NOT EXISTS linked_wallets (
|
|
id TEXT PRIMARY KEY, -- UUID for the link record
|
|
user_id TEXT NOT NULL, -- References users.id (CryptID account)
|
|
wallet_address TEXT NOT NULL, -- Ethereum address (checksummed, 0x-prefixed)
|
|
|
|
-- Wallet metadata
|
|
wallet_type TEXT DEFAULT 'eoa' CHECK (wallet_type IN ('eoa', 'safe', 'hardware', 'contract')),
|
|
chain_id INTEGER DEFAULT 1, -- Primary chain (1 = Ethereum mainnet)
|
|
label TEXT, -- User-provided label (e.g., "Main Wallet")
|
|
|
|
-- Verification proof
|
|
signature_message TEXT NOT NULL, -- The message that was signed
|
|
signature TEXT NOT NULL, -- EIP-191 personal_sign signature
|
|
verified_at TEXT NOT NULL, -- When signature was verified
|
|
|
|
-- ENS integration
|
|
ens_name TEXT, -- Resolved ENS name (if any)
|
|
ens_avatar TEXT, -- ENS avatar URL (if any)
|
|
ens_resolved_at TEXT, -- When ENS was last resolved
|
|
|
|
-- Flags
|
|
is_primary INTEGER DEFAULT 0, -- 1 = primary wallet for this user
|
|
is_active INTEGER DEFAULT 1, -- 0 = soft-deleted
|
|
|
|
-- Timestamps
|
|
created_at TEXT DEFAULT (datetime('now')),
|
|
updated_at TEXT DEFAULT (datetime('now')),
|
|
last_used_at TEXT, -- Last time wallet was used for action
|
|
|
|
-- Constraints
|
|
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
|
|
UNIQUE(user_id, wallet_address) -- Can't link same wallet twice
|
|
);
|
|
|
|
-- Indexes for efficient lookups
|
|
CREATE INDEX IF NOT EXISTS idx_linked_wallets_user ON linked_wallets(user_id);
|
|
CREATE INDEX IF NOT EXISTS idx_linked_wallets_address ON linked_wallets(wallet_address);
|
|
CREATE INDEX IF NOT EXISTS idx_linked_wallets_active ON linked_wallets(is_active);
|
|
CREATE INDEX IF NOT EXISTS idx_linked_wallets_primary ON linked_wallets(user_id, is_primary);
|
|
|
|
-- =============================================================================
|
|
-- WALLET LINKING TOKENS TABLE (for Safe/multisig delayed verification)
|
|
-- =============================================================================
|
|
-- For contract wallets that require on-chain signature verification
|
|
|
|
CREATE TABLE IF NOT EXISTS wallet_link_tokens (
|
|
id TEXT PRIMARY KEY,
|
|
user_id TEXT NOT NULL,
|
|
wallet_address TEXT NOT NULL,
|
|
nonce TEXT NOT NULL, -- Random nonce for signature message
|
|
token TEXT NOT NULL UNIQUE, -- Secret token for verification callback
|
|
expires_at TEXT NOT NULL,
|
|
used INTEGER DEFAULT 0,
|
|
created_at TEXT DEFAULT (datetime('now')),
|
|
|
|
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_wallet_link_tokens_token ON wallet_link_tokens(token);
|
|
CREATE INDEX IF NOT EXISTS idx_wallet_link_tokens_user ON wallet_link_tokens(user_id);
|
|
|
|
-- =============================================================================
|
|
-- TOKEN BALANCES CACHE (optional, for token-gating)
|
|
-- =============================================================================
|
|
-- Cache of token balances for faster permission checks
|
|
-- Updated periodically or on-demand
|
|
|
|
CREATE TABLE IF NOT EXISTS wallet_token_balances (
|
|
id TEXT PRIMARY KEY,
|
|
wallet_address TEXT NOT NULL,
|
|
token_address TEXT NOT NULL, -- ERC-20/721/1155 contract address
|
|
token_type TEXT CHECK (token_type IN ('erc20', 'erc721', 'erc1155')),
|
|
chain_id INTEGER NOT NULL,
|
|
balance TEXT NOT NULL, -- String to handle big numbers
|
|
last_updated TEXT DEFAULT (datetime('now')),
|
|
|
|
UNIQUE(wallet_address, token_address, chain_id)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_token_balances_wallet ON wallet_token_balances(wallet_address);
|
|
CREATE INDEX IF NOT EXISTS idx_token_balances_token ON wallet_token_balances(token_address);
|
|
CREATE INDEX IF NOT EXISTS idx_token_balances_chain ON wallet_token_balances(chain_id);
|