PRAGMA journal_mode= WAL; CREATE TABLE IF NOT EXISTS ledger_internal ( id INTEGER PRIMARY KEY AUTOINCREMENT, creation_time DATETIME DEFAULT CURRENT_TIMESTAMP, cookie_secret TEXT NOT NULL ); INSERT INTO ledger_internal(cookie_secret) VALUES ('aaaabbbbccccddddeeeeffffgggghhhhiiiijjjjkkkk'); CREATE TABLE IF NOT EXISTS users ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL UNIQUE, public_key TEXT NOT NULL, creation_time DATETIME DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE IF NOT EXISTS security_types ( name TEXT PRIMARY KEY ) STRICT; INSERT INTO security_types(name) VALUES ('currency'), ('bond'); CREATE TABLE IF NOT EXISTS securities ( id INTEGER PRIMARY KEY AUTOINCREMENT, security_type TEXT NOT NULL, name TEXT NOT NULL UNIQUE, symbol TEXT NOT NULL UNIQUE, creation_time DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (security_type) REFERENCES security_types (name) ); CREATE TABLE IF NOT EXISTS interest_rates ( id INTEGER PRIMARY KEY AUTOINCREMENT, security_id INTEGER NOT NULL, security_rate_id INTEGER NOT NULL, start_date DATETIME NOT NULL, end_date DATETIME, rate REAL NOT NULL, FOREIGN KEY (security_id) REFERENCES securities(id), CONSTRAINT unique_security_rate_id UNIQUE (security_id, security_rate_id), CHECK (end_date IS NULL OR start_date <= end_date), CHECK ( rate >= 0 ) ); CREATE TABLE IF NOT EXISTS account_types ( name TEXT PRIMARY KEY ) STRICT; INSERT INTO account_types(name) VALUES ('checking'), ('security_emitter'); CREATE TABLE IF NOT EXISTS accounts ( id INTEGER PRIMARY KEY AUTOINCREMENT, version INTEGER NOT NULL CHECK ( version >= 0 ), security INTEGER NOT NULL, account_type TEXT NOT NULL, label TEXT NOT NULL, amount INTEGER NOT NULL, timestamp DATETIME NOT NULL, creation_time DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (security) REFERENCES securities (id), FOREIGN KEY (account_type) REFERENCES account_types (name), CHECK (amount >= 0 OR (account_type = 'security_emitter')) ); CREATE TABLE IF NOT EXISTS accounts_history ( id INTEGER PRIMARY KEY AUTOINCREMENT, account_id INTEGER NOT NULL, account_version INTEGER NOT NULL, amount INTEGER NOT NULL, timestamp DATETIME NOT NULL, FOREIGN KEY (account_id) REFERENCES accounts (id), UNIQUE (account_id, account_version) ); CREATE TABLE IF NOT EXISTS account_user_permissions ( id INTEGER PRIMARY KEY AUTOINCREMENT, account_id INTEGER NOT NULL, user_id INTEGER NOT NULL, creation_time DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (account_id) REFERENCES accounts (id), FOREIGN KEY (user_id) REFERENCES users (id) ); CREATE TABLE IF NOT EXISTS cashed_cheques ( id INTEGER PRIMARY KEY AUTOINCREMENT, drawer_user_id INTEGER NOT NULL, drawer_account_id INTEGER NOT NULL, drawer_account_version INTEGER NOT NULL, cheque_number INTEGER NOT NULL, amount INTEGER NOT NULL, underlying_security INTEGER NOT NULL, payee_user_id INTEGER NOT NULL, payee_account_id INTEGER NOT NULL, payee_account_version INTEGER NOT NULL, creation_time DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (underlying_security) REFERENCES securities (id), FOREIGN KEY (drawer_user_id) REFERENCES users (id), FOREIGN KEY (drawer_account_id) REFERENCES accounts (id), FOREIGN KEY (payee_user_id) REFERENCES users (id), FOREIGN KEY (payee_account_id) REFERENCES accounts (id), CONSTRAINT double_spending UNIQUE (drawer_user_id, cheque_number) -- no double spending ); CREATE TABLE IF NOT EXISTS cached_wire_transfers ( id INTEGER PRIMARY KEY AUTOINCREMENT, drawer_account_id INTEGER NOT NULL, drawer_account_version INTEGER NOT NULL, wire_transfer_request_number INTEGER NOT NULL, amount INTEGER NOT NULL, underlying_security INTEGER NOT NULL, payee_account_id INTEGER NOT NULL, payee_account_version INTEGER NOT NULL, creation_time DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (underlying_security) REFERENCES securities (id), FOREIGN KEY (drawer_account_id) REFERENCES accounts (id), FOREIGN KEY (payee_account_id) REFERENCES accounts (id), CONSTRAINT double_spending UNIQUE (drawer_account_id, wire_transfer_request_number) -- no double spending ); CREATE TABLE IF NOT EXISTS event_processing_statuses ( value TEXT PRIMARY KEY ); INSERT INTO event_processing_statuses(value) VALUES ('processing'), ('completed'), ('error'); CREATE TABLE IF NOT EXISTS event_processing_log ( id TEXT PRIMARY KEY, event JSON, status TEXT NOT NULL, received_time DATETIME NOT NULL, completed_time DATETIME, error_message TEXT NOT NULL DEFAULT '', FOREIGN KEY (status) REFERENCES event_processing_statuses (value) )