From 4b9e628bea3d8a547c03f857c98b70d98eec66a4 Mon Sep 17 00:00:00 2001 From: "decartes.sol" <123273990+decartesol@users.noreply.github.com> Date: Thu, 8 Feb 2024 08:20:55 +0000 Subject: [PATCH] create initial schema --- packages/database/lib/schema.ts | 67 ++++++++++++++++++++++++++++++++- 1 file changed, 65 insertions(+), 2 deletions(-) diff --git a/packages/database/lib/schema.ts b/packages/database/lib/schema.ts index 75ce04f4..203b2df7 100644 --- a/packages/database/lib/schema.ts +++ b/packages/database/lib/schema.ts @@ -1,5 +1,68 @@ -import { pgTable, text } from 'drizzle-orm/pg-core'; +import { bigint, index, pgTable, primaryKey, smallint, smallserial, varchar } from 'drizzle-orm/pg-core'; + +// TODO: index order book + +// https://docs.rs/solana-program/latest/src/solana_program/pubkey.rs.html#24 +const MAX_PUBKEY_B58_STR_LEN = 44; +const pubkey = (columnName: string) => varchar(columnName, {length: MAX_PUBKEY_B58_STR_LEN}); + +const MAX_TRANSACTION_B58_STR_LEN = 88; +const transaction = (columnName: string) => varchar(columnName, {length: MAX_TRANSACTION_B58_STR_LEN}); + +const tokenAmount = (columnName: string) => bigint(columnName, {mode: 'bigint'}); + +const timestamp = (columnName: string) => bigint(columnName, {mode: 'bigint'}); export const proposals = pgTable('proposals', { - id: text('id').primaryKey(), + proposalId: pubkey('proposal_id').primaryKey(), + autocratVersion: smallint('autocrat_version').notNull() }); + +export enum MarketType { + OPEN_BOOK = 'OPEN_BOOK' +} + +type NonEmptyList = [E, ...E[]]; + +export const markets = pgTable('markets', { + marketId: pubkey('market_id').primaryKey(), + marketType: varchar('market_type', {enum: Object.values(MarketType) as NonEmptyList}).notNull(), + baseCurrencyMint: pubkey('base_currency_mint').references(() => tokens.tokenMint).notNull(), + quoteCurrencyMint: pubkey('quote_currency_mint').references(() => tokens.tokenMint).notNull(), +}); + +export const tokens = pgTable('tokens', { + tokenMint: pubkey('token_mint').primaryKey(), + name: varchar('name', {length: 30}).notNull(), + symbol: varchar('symbol', {length: 10}).notNull(), + decimals: smallserial('decimals').notNull() +}); + +export const trades = pgTable('trades', { + transactionId: transaction('transaction_id').primaryKey(), + slot: bigint('slot', {mode: 'bigint'}).notNull(), + block: bigint('block', {mode: 'bigint'}).notNull(), + time: timestamp('time').notNull(), + marketId: pubkey('market_id').references(() => markets.marketId).notNull(), + takerId: pubkey('taker_id').notNull(), + baseAmount: tokenAmount('base_amount').notNull(), + quotePrice: tokenAmount('quote_price').notNull(), +}, table => ({ + slotIdx: index('slot_index').on(table.marketId, table.slot), + blockIdx: index('block_index').on(table.marketId, table.block), + timeIdx: index('time_index').on(table.marketId, table.time) +})); + +export const candles = pgTable('candles', { + marketId: pubkey('market_id').references(() => markets.marketId).notNull(), + // increments by minute + timestamp: timestamp('timestamp').notNull(), + high: tokenAmount('high'), + low: tokenAmount('low'), + close: tokenAmount('close'), + volume: tokenAmount('volume').notNull(), + // time-weighted average + average: tokenAmount('average'), +}, table => ({ + pk: primaryKey(table.marketId, table.timestamp) +}));