diff --git a/.gitignore b/.gitignore index 3deec0c..1c1d1a1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,2 @@ .github -review.js -.env -node_modules +review.js \ No newline at end of file diff --git a/website/drizzle/0001_heavy_leo.sql b/website/drizzle/0001_heavy_leo.sql deleted file mode 100644 index 52b4b22..0000000 --- a/website/drizzle/0001_heavy_leo.sql +++ /dev/null @@ -1 +0,0 @@ -ALTER TABLE "notification" ADD COLUMN "link" text; \ No newline at end of file diff --git a/website/drizzle/0002_lonely_the_fallen.sql b/website/drizzle/0002_lonely_the_fallen.sql deleted file mode 100644 index 52a1d06..0000000 --- a/website/drizzle/0002_lonely_the_fallen.sql +++ /dev/null @@ -1,2 +0,0 @@ -ALTER TABLE "coin" ADD COLUMN "trading_unlocks_at" timestamp;--> statement-breakpoint -ALTER TABLE "coin" ADD COLUMN "is_locked" boolean DEFAULT true NOT NULL; \ No newline at end of file diff --git a/website/drizzle/meta/0001_snapshot.json b/website/drizzle/meta/0001_snapshot.json deleted file mode 100644 index c173580..0000000 --- a/website/drizzle/meta/0001_snapshot.json +++ /dev/null @@ -1,2199 +0,0 @@ -{ - "id": "947dcf8e-040d-49d0-aba5-271be6750cc8", - "prevId": "08d1623b-7b2d-4777-8b7b-dbfa7884ecfe", - "version": "7", - "dialect": "postgresql", - "tables": { - "public.account": { - "name": "account", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "serial", - "primaryKey": true, - "notNull": true - }, - "account_id": { - "name": "account_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "provider_id": { - "name": "provider_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "user_id": { - "name": "user_id", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "access_token": { - "name": "access_token", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "refresh_token": { - "name": "refresh_token", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "id_token": { - "name": "id_token", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "access_token_expires_at": { - "name": "access_token_expires_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - }, - "refresh_token_expires_at": { - "name": "refresh_token_expires_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - }, - "scope": { - "name": "scope", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "password": { - "name": "password", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "account_user_id_user_id_fk": { - "name": "account_user_id_user_id_fk", - "tableFrom": "account", - "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "public.account_deletion_request": { - "name": "account_deletion_request", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "serial", - "primaryKey": true, - "notNull": true - }, - "user_id": { - "name": "user_id", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "requested_at": { - "name": "requested_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "scheduled_deletion_at": { - "name": "scheduled_deletion_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true - }, - "reason": { - "name": "reason", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "is_processed": { - "name": "is_processed", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - } - }, - "indexes": { - "account_deletion_request_user_id_idx": { - "name": "account_deletion_request_user_id_idx", - "columns": [ - { - "expression": "user_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "account_deletion_request_scheduled_deletion_idx": { - "name": "account_deletion_request_scheduled_deletion_idx", - "columns": [ - { - "expression": "scheduled_deletion_at", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "account_deletion_request_open_idx": { - "name": "account_deletion_request_open_idx", - "columns": [ - { - "expression": "user_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "where": "is_processed = false", - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "account_deletion_request_user_id_user_id_fk": { - "name": "account_deletion_request_user_id_user_id_fk", - "tableFrom": "account_deletion_request", - "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "account_deletion_request_user_id_unique": { - "name": "account_deletion_request_user_id_unique", - "nullsNotDistinct": false, - "columns": [ - "user_id" - ] - } - } - }, - "public.apikey": { - "name": "apikey", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "serial", - "primaryKey": true, - "notNull": true - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "start": { - "name": "start", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "prefix": { - "name": "prefix", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "key": { - "name": "key", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "user_id": { - "name": "user_id", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "refill_interval": { - "name": "refill_interval", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "refill_amount": { - "name": "refill_amount", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "last_refill_at": { - "name": "last_refill_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "enabled": { - "name": "enabled", - "type": "boolean", - "primaryKey": false, - "notNull": false - }, - "rate_limit_enabled": { - "name": "rate_limit_enabled", - "type": "boolean", - "primaryKey": false, - "notNull": false - }, - "rate_limit_time_window": { - "name": "rate_limit_time_window", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "rate_limit_max": { - "name": "rate_limit_max", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "request_count": { - "name": "request_count", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "remaining": { - "name": "remaining", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "last_request": { - "name": "last_request", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "expires_at": { - "name": "expires_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true - }, - "permissions": { - "name": "permissions", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "metadata": { - "name": "metadata", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": { - "idx_apikey_user": { - "name": "idx_apikey_user", - "columns": [ - { - "expression": "user_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "apikey_user_id_user_id_fk": { - "name": "apikey_user_id_user_id_fk", - "tableFrom": "apikey", - "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "public.coin": { - "name": "coin", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "serial", - "primaryKey": true, - "notNull": true - }, - "name": { - "name": "name", - "type": "varchar(255)", - "primaryKey": false, - "notNull": true - }, - "symbol": { - "name": "symbol", - "type": "varchar(10)", - "primaryKey": false, - "notNull": true - }, - "icon": { - "name": "icon", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "creator_id": { - "name": "creator_id", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "initial_supply": { - "name": "initial_supply", - "type": "numeric(30, 8)", - "primaryKey": false, - "notNull": true - }, - "circulating_supply": { - "name": "circulating_supply", - "type": "numeric(30, 8)", - "primaryKey": false, - "notNull": true - }, - "current_price": { - "name": "current_price", - "type": "numeric(20, 8)", - "primaryKey": false, - "notNull": true - }, - "market_cap": { - "name": "market_cap", - "type": "numeric(30, 2)", - "primaryKey": false, - "notNull": true - }, - "volume_24h": { - "name": "volume_24h", - "type": "numeric(30, 2)", - "primaryKey": false, - "notNull": false, - "default": "'0.00'" - }, - "change_24h": { - "name": "change_24h", - "type": "numeric(30, 4)", - "primaryKey": false, - "notNull": false, - "default": "'0.0000'" - }, - "pool_coin_amount": { - "name": "pool_coin_amount", - "type": "numeric(30, 8)", - "primaryKey": false, - "notNull": true, - "default": "'0.00000000'" - }, - "pool_base_currency_amount": { - "name": "pool_base_currency_amount", - "type": "numeric(30, 8)", - "primaryKey": false, - "notNull": true, - "default": "'0.00000000'" - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "is_listed": { - "name": "is_listed", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": true - } - }, - "indexes": { - "coin_symbol_idx": { - "name": "coin_symbol_idx", - "columns": [ - { - "expression": "symbol", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "coin_creator_id_idx": { - "name": "coin_creator_id_idx", - "columns": [ - { - "expression": "creator_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "coin_is_listed_idx": { - "name": "coin_is_listed_idx", - "columns": [ - { - "expression": "is_listed", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "coin_market_cap_idx": { - "name": "coin_market_cap_idx", - "columns": [ - { - "expression": "market_cap", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "coin_current_price_idx": { - "name": "coin_current_price_idx", - "columns": [ - { - "expression": "current_price", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "coin_change24h_idx": { - "name": "coin_change24h_idx", - "columns": [ - { - "expression": "change_24h", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "coin_volume24h_idx": { - "name": "coin_volume24h_idx", - "columns": [ - { - "expression": "volume_24h", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "coin_created_at_idx": { - "name": "coin_created_at_idx", - "columns": [ - { - "expression": "created_at", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "coin_creator_id_user_id_fk": { - "name": "coin_creator_id_user_id_fk", - "tableFrom": "coin", - "tableTo": "user", - "columnsFrom": [ - "creator_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "set null", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "coin_symbol_unique": { - "name": "coin_symbol_unique", - "nullsNotDistinct": false, - "columns": [ - "symbol" - ] - } - } - }, - "public.comment": { - "name": "comment", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "serial", - "primaryKey": true, - "notNull": true - }, - "user_id": { - "name": "user_id", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "coin_id": { - "name": "coin_id", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "content": { - "name": "content", - "type": "varchar(500)", - "primaryKey": false, - "notNull": true - }, - "likes_count": { - "name": "likes_count", - "type": "integer", - "primaryKey": false, - "notNull": true, - "default": 0 - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "is_deleted": { - "name": "is_deleted", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - } - }, - "indexes": { - "comment_user_id_idx": { - "name": "comment_user_id_idx", - "columns": [ - { - "expression": "user_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "comment_coin_id_idx": { - "name": "comment_coin_id_idx", - "columns": [ - { - "expression": "coin_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "comment_user_id_user_id_fk": { - "name": "comment_user_id_user_id_fk", - "tableFrom": "comment", - "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "set null", - "onUpdate": "no action" - }, - "comment_coin_id_coin_id_fk": { - "name": "comment_coin_id_coin_id_fk", - "tableFrom": "comment", - "tableTo": "coin", - "columnsFrom": [ - "coin_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "public.comment_like": { - "name": "comment_like", - "schema": "", - "columns": { - "user_id": { - "name": "user_id", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "comment_id": { - "name": "comment_id", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "comment_like_user_id_user_id_fk": { - "name": "comment_like_user_id_user_id_fk", - "tableFrom": "comment_like", - "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "comment_like_comment_id_comment_id_fk": { - "name": "comment_like_comment_id_comment_id_fk", - "tableFrom": "comment_like", - "tableTo": "comment", - "columnsFrom": [ - "comment_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": { - "comment_like_user_id_comment_id_pk": { - "name": "comment_like_user_id_comment_id_pk", - "columns": [ - "user_id", - "comment_id" - ] - } - }, - "uniqueConstraints": {} - }, - "public.notification": { - "name": "notification", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "serial", - "primaryKey": true, - "notNull": true - }, - "user_id": { - "name": "user_id", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "type": { - "name": "type", - "type": "notification_type", - "typeSchema": "public", - "primaryKey": false, - "notNull": true - }, - "title": { - "name": "title", - "type": "varchar(200)", - "primaryKey": false, - "notNull": true - }, - "message": { - "name": "message", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "link": { - "name": "link", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "is_read": { - "name": "is_read", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": { - "notification_user_id_idx": { - "name": "notification_user_id_idx", - "columns": [ - { - "expression": "user_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "notification_type_idx": { - "name": "notification_type_idx", - "columns": [ - { - "expression": "type", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "notification_is_read_idx": { - "name": "notification_is_read_idx", - "columns": [ - { - "expression": "is_read", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "notification_created_at_idx": { - "name": "notification_created_at_idx", - "columns": [ - { - "expression": "created_at", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "notification_user_id_user_id_fk": { - "name": "notification_user_id_user_id_fk", - "tableFrom": "notification", - "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "public.prediction_bet": { - "name": "prediction_bet", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "serial", - "primaryKey": true, - "notNull": true - }, - "user_id": { - "name": "user_id", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "question_id": { - "name": "question_id", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "side": { - "name": "side", - "type": "boolean", - "primaryKey": false, - "notNull": true - }, - "amount": { - "name": "amount", - "type": "numeric(20, 8)", - "primaryKey": false, - "notNull": true - }, - "actual_winnings": { - "name": "actual_winnings", - "type": "numeric(20, 8)", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "settled_at": { - "name": "settled_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - } - }, - "indexes": { - "prediction_bet_user_id_idx": { - "name": "prediction_bet_user_id_idx", - "columns": [ - { - "expression": "user_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "prediction_bet_question_id_idx": { - "name": "prediction_bet_question_id_idx", - "columns": [ - { - "expression": "question_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "prediction_bet_user_question_idx": { - "name": "prediction_bet_user_question_idx", - "columns": [ - { - "expression": "user_id", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "question_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "prediction_bet_created_at_idx": { - "name": "prediction_bet_created_at_idx", - "columns": [ - { - "expression": "created_at", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "prediction_bet_user_id_user_id_fk": { - "name": "prediction_bet_user_id_user_id_fk", - "tableFrom": "prediction_bet", - "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "set null", - "onUpdate": "no action" - }, - "prediction_bet_question_id_prediction_question_id_fk": { - "name": "prediction_bet_question_id_prediction_question_id_fk", - "tableFrom": "prediction_bet", - "tableTo": "prediction_question", - "columnsFrom": [ - "question_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "public.prediction_question": { - "name": "prediction_question", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "serial", - "primaryKey": true, - "notNull": true - }, - "creator_id": { - "name": "creator_id", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "question": { - "name": "question", - "type": "varchar(200)", - "primaryKey": false, - "notNull": true - }, - "status": { - "name": "status", - "type": "prediction_market_status", - "typeSchema": "public", - "primaryKey": false, - "notNull": true, - "default": "'ACTIVE'" - }, - "resolution_date": { - "name": "resolution_date", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true - }, - "ai_resolution": { - "name": "ai_resolution", - "type": "boolean", - "primaryKey": false, - "notNull": false - }, - "total_yes_amount": { - "name": "total_yes_amount", - "type": "numeric(20, 8)", - "primaryKey": false, - "notNull": true, - "default": "'0.00000000'" - }, - "total_no_amount": { - "name": "total_no_amount", - "type": "numeric(20, 8)", - "primaryKey": false, - "notNull": true, - "default": "'0.00000000'" - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "resolved_at": { - "name": "resolved_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - }, - "requires_web_search": { - "name": "requires_web_search", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "validation_reason": { - "name": "validation_reason", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": { - "prediction_question_creator_id_idx": { - "name": "prediction_question_creator_id_idx", - "columns": [ - { - "expression": "creator_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "prediction_question_status_idx": { - "name": "prediction_question_status_idx", - "columns": [ - { - "expression": "status", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "prediction_question_resolution_date_idx": { - "name": "prediction_question_resolution_date_idx", - "columns": [ - { - "expression": "resolution_date", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "prediction_question_status_resolution_idx": { - "name": "prediction_question_status_resolution_idx", - "columns": [ - { - "expression": "status", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "resolution_date", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "prediction_question_creator_id_user_id_fk": { - "name": "prediction_question_creator_id_user_id_fk", - "tableFrom": "prediction_question", - "tableTo": "user", - "columnsFrom": [ - "creator_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "set null", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "public.price_history": { - "name": "price_history", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "serial", - "primaryKey": true, - "notNull": true - }, - "coin_id": { - "name": "coin_id", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "price": { - "name": "price", - "type": "numeric(20, 8)", - "primaryKey": false, - "notNull": true - }, - "timestamp": { - "name": "timestamp", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "price_history_coin_id_coin_id_fk": { - "name": "price_history_coin_id_coin_id_fk", - "tableFrom": "price_history", - "tableTo": "coin", - "columnsFrom": [ - "coin_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "public.promo_code": { - "name": "promo_code", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "serial", - "primaryKey": true, - "notNull": true - }, - "code": { - "name": "code", - "type": "varchar(50)", - "primaryKey": false, - "notNull": true - }, - "description": { - "name": "description", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "reward_amount": { - "name": "reward_amount", - "type": "numeric(20, 8)", - "primaryKey": false, - "notNull": true - }, - "max_uses": { - "name": "max_uses", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "is_active": { - "name": "is_active", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": true - }, - "expires_at": { - "name": "expires_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "created_by": { - "name": "created_by", - "type": "integer", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "promo_code_created_by_user_id_fk": { - "name": "promo_code_created_by_user_id_fk", - "tableFrom": "promo_code", - "tableTo": "user", - "columnsFrom": [ - "created_by" - ], - "columnsTo": [ - "id" - ], - "onDelete": "set null", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "promo_code_code_unique": { - "name": "promo_code_code_unique", - "nullsNotDistinct": false, - "columns": [ - "code" - ] - } - } - }, - "public.promo_code_redemption": { - "name": "promo_code_redemption", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "serial", - "primaryKey": true, - "notNull": true - }, - "user_id": { - "name": "user_id", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "promo_code_id": { - "name": "promo_code_id", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "reward_amount": { - "name": "reward_amount", - "type": "numeric(20, 8)", - "primaryKey": false, - "notNull": true - }, - "redeemed_at": { - "name": "redeemed_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "promo_code_redemption_user_id_user_id_fk": { - "name": "promo_code_redemption_user_id_user_id_fk", - "tableFrom": "promo_code_redemption", - "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "promo_code_redemption_promo_code_id_promo_code_id_fk": { - "name": "promo_code_redemption_promo_code_id_promo_code_id_fk", - "tableFrom": "promo_code_redemption", - "tableTo": "promo_code", - "columnsFrom": [ - "promo_code_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "promo_code_redemption_user_id_promo_code_id_unique": { - "name": "promo_code_redemption_user_id_promo_code_id_unique", - "nullsNotDistinct": false, - "columns": [ - "user_id", - "promo_code_id" - ] - } - } - }, - "public.session": { - "name": "session", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "serial", - "primaryKey": true, - "notNull": true - }, - "expires_at": { - "name": "expires_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true - }, - "token": { - "name": "token", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "ip_address": { - "name": "ip_address", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "user_agent": { - "name": "user_agent", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "user_id": { - "name": "user_id", - "type": "integer", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "session_user_id_user_id_fk": { - "name": "session_user_id_user_id_fk", - "tableFrom": "session", - "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "session_token_unique": { - "name": "session_token_unique", - "nullsNotDistinct": false, - "columns": [ - "token" - ] - } - } - }, - "public.transaction": { - "name": "transaction", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "serial", - "primaryKey": true, - "notNull": true - }, - "user_id": { - "name": "user_id", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "coin_id": { - "name": "coin_id", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "type": { - "name": "type", - "type": "transaction_type", - "typeSchema": "public", - "primaryKey": false, - "notNull": true - }, - "quantity": { - "name": "quantity", - "type": "numeric(30, 8)", - "primaryKey": false, - "notNull": true - }, - "price_per_coin": { - "name": "price_per_coin", - "type": "numeric(20, 8)", - "primaryKey": false, - "notNull": true - }, - "total_base_currency_amount": { - "name": "total_base_currency_amount", - "type": "numeric(30, 8)", - "primaryKey": false, - "notNull": true - }, - "timestamp": { - "name": "timestamp", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "recipient_user_id": { - "name": "recipient_user_id", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "sender_user_id": { - "name": "sender_user_id", - "type": "integer", - "primaryKey": false, - "notNull": false - } - }, - "indexes": { - "transaction_user_id_idx": { - "name": "transaction_user_id_idx", - "columns": [ - { - "expression": "user_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "transaction_coin_id_idx": { - "name": "transaction_coin_id_idx", - "columns": [ - { - "expression": "coin_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "transaction_type_idx": { - "name": "transaction_type_idx", - "columns": [ - { - "expression": "type", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "transaction_timestamp_idx": { - "name": "transaction_timestamp_idx", - "columns": [ - { - "expression": "timestamp", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "transaction_user_coin_idx": { - "name": "transaction_user_coin_idx", - "columns": [ - { - "expression": "user_id", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "coin_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "transaction_coin_type_idx": { - "name": "transaction_coin_type_idx", - "columns": [ - { - "expression": "coin_id", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "type", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "transaction_user_id_user_id_fk": { - "name": "transaction_user_id_user_id_fk", - "tableFrom": "transaction", - "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "set null", - "onUpdate": "no action" - }, - "transaction_coin_id_coin_id_fk": { - "name": "transaction_coin_id_coin_id_fk", - "tableFrom": "transaction", - "tableTo": "coin", - "columnsFrom": [ - "coin_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "transaction_recipient_user_id_user_id_fk": { - "name": "transaction_recipient_user_id_user_id_fk", - "tableFrom": "transaction", - "tableTo": "user", - "columnsFrom": [ - "recipient_user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "set null", - "onUpdate": "no action" - }, - "transaction_sender_user_id_user_id_fk": { - "name": "transaction_sender_user_id_user_id_fk", - "tableFrom": "transaction", - "tableTo": "user", - "columnsFrom": [ - "sender_user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "set null", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "public.user": { - "name": "user", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "serial", - "primaryKey": true, - "notNull": true - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "email": { - "name": "email", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "email_verified": { - "name": "email_verified", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "image": { - "name": "image", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "is_admin": { - "name": "is_admin", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "is_banned": { - "name": "is_banned", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "ban_reason": { - "name": "ban_reason", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "base_currency_balance": { - "name": "base_currency_balance", - "type": "numeric(20, 8)", - "primaryKey": false, - "notNull": true, - "default": "'100.00000000'" - }, - "bio": { - "name": "bio", - "type": "varchar(160)", - "primaryKey": false, - "notNull": false, - "default": "'Hello am 48 year old man from somalia. Sorry for my bed england. I selled my wife for internet connection for play “conter stirk”'" - }, - "username": { - "name": "username", - "type": "varchar(30)", - "primaryKey": false, - "notNull": true - }, - "volume_master": { - "name": "volume_master", - "type": "numeric(3, 2)", - "primaryKey": false, - "notNull": true, - "default": "'0.70'" - }, - "volume_muted": { - "name": "volume_muted", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "last_reward_claim": { - "name": "last_reward_claim", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - }, - "total_rewards_claimed": { - "name": "total_rewards_claimed", - "type": "numeric(20, 8)", - "primaryKey": false, - "notNull": true, - "default": "'0.00000000'" - }, - "login_streak": { - "name": "login_streak", - "type": "integer", - "primaryKey": false, - "notNull": true, - "default": 0 - }, - "prestige_level": { - "name": "prestige_level", - "type": "integer", - "primaryKey": false, - "notNull": false, - "default": 0 - } - }, - "indexes": { - "user_username_idx": { - "name": "user_username_idx", - "columns": [ - { - "expression": "username", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "user_is_banned_idx": { - "name": "user_is_banned_idx", - "columns": [ - { - "expression": "is_banned", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "user_is_admin_idx": { - "name": "user_is_admin_idx", - "columns": [ - { - "expression": "is_admin", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "user_created_at_idx": { - "name": "user_created_at_idx", - "columns": [ - { - "expression": "created_at", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "user_updated_at_idx": { - "name": "user_updated_at_idx", - "columns": [ - { - "expression": "updated_at", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "user_email_unique": { - "name": "user_email_unique", - "nullsNotDistinct": false, - "columns": [ - "email" - ] - }, - "user_username_unique": { - "name": "user_username_unique", - "nullsNotDistinct": false, - "columns": [ - "username" - ] - } - } - }, - "public.user_portfolio": { - "name": "user_portfolio", - "schema": "", - "columns": { - "user_id": { - "name": "user_id", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "coin_id": { - "name": "coin_id", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "quantity": { - "name": "quantity", - "type": "numeric(30, 8)", - "primaryKey": false, - "notNull": true - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "user_portfolio_user_id_user_id_fk": { - "name": "user_portfolio_user_id_user_id_fk", - "tableFrom": "user_portfolio", - "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "user_portfolio_coin_id_coin_id_fk": { - "name": "user_portfolio_coin_id_coin_id_fk", - "tableFrom": "user_portfolio", - "tableTo": "coin", - "columnsFrom": [ - "coin_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": { - "user_portfolio_user_id_coin_id_pk": { - "name": "user_portfolio_user_id_coin_id_pk", - "columns": [ - "user_id", - "coin_id" - ] - } - }, - "uniqueConstraints": {} - }, - "public.verification": { - "name": "verification", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "serial", - "primaryKey": true, - "notNull": true - }, - "identifier": { - "name": "identifier", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "value": { - "name": "value", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "expires_at": { - "name": "expires_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - } - }, - "enums": { - "public.notification_type": { - "name": "notification_type", - "schema": "public", - "values": [ - "HOPIUM", - "SYSTEM", - "TRANSFER", - "RUG_PULL" - ] - }, - "public.prediction_market_status": { - "name": "prediction_market_status", - "schema": "public", - "values": [ - "ACTIVE", - "RESOLVED", - "CANCELLED" - ] - }, - "public.transaction_type": { - "name": "transaction_type", - "schema": "public", - "values": [ - "BUY", - "SELL", - "TRANSFER_IN", - "TRANSFER_OUT" - ] - } - }, - "schemas": {}, - "_meta": { - "columns": {}, - "schemas": {}, - "tables": {} - } -} \ No newline at end of file diff --git a/website/drizzle/meta/0002_snapshot.json b/website/drizzle/meta/0002_snapshot.json deleted file mode 100644 index bbdcbaf..0000000 --- a/website/drizzle/meta/0002_snapshot.json +++ /dev/null @@ -1,2212 +0,0 @@ -{ - "id": "a121175f-03e9-4a31-866a-9af04fa805b6", - "prevId": "947dcf8e-040d-49d0-aba5-271be6750cc8", - "version": "7", - "dialect": "postgresql", - "tables": { - "public.account": { - "name": "account", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "serial", - "primaryKey": true, - "notNull": true - }, - "account_id": { - "name": "account_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "provider_id": { - "name": "provider_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "user_id": { - "name": "user_id", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "access_token": { - "name": "access_token", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "refresh_token": { - "name": "refresh_token", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "id_token": { - "name": "id_token", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "access_token_expires_at": { - "name": "access_token_expires_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - }, - "refresh_token_expires_at": { - "name": "refresh_token_expires_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - }, - "scope": { - "name": "scope", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "password": { - "name": "password", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "account_user_id_user_id_fk": { - "name": "account_user_id_user_id_fk", - "tableFrom": "account", - "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "public.account_deletion_request": { - "name": "account_deletion_request", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "serial", - "primaryKey": true, - "notNull": true - }, - "user_id": { - "name": "user_id", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "requested_at": { - "name": "requested_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "scheduled_deletion_at": { - "name": "scheduled_deletion_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true - }, - "reason": { - "name": "reason", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "is_processed": { - "name": "is_processed", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - } - }, - "indexes": { - "account_deletion_request_user_id_idx": { - "name": "account_deletion_request_user_id_idx", - "columns": [ - { - "expression": "user_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "account_deletion_request_scheduled_deletion_idx": { - "name": "account_deletion_request_scheduled_deletion_idx", - "columns": [ - { - "expression": "scheduled_deletion_at", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "account_deletion_request_open_idx": { - "name": "account_deletion_request_open_idx", - "columns": [ - { - "expression": "user_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "where": "is_processed = false", - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "account_deletion_request_user_id_user_id_fk": { - "name": "account_deletion_request_user_id_user_id_fk", - "tableFrom": "account_deletion_request", - "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "account_deletion_request_user_id_unique": { - "name": "account_deletion_request_user_id_unique", - "nullsNotDistinct": false, - "columns": [ - "user_id" - ] - } - } - }, - "public.apikey": { - "name": "apikey", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "serial", - "primaryKey": true, - "notNull": true - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "start": { - "name": "start", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "prefix": { - "name": "prefix", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "key": { - "name": "key", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "user_id": { - "name": "user_id", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "refill_interval": { - "name": "refill_interval", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "refill_amount": { - "name": "refill_amount", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "last_refill_at": { - "name": "last_refill_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "enabled": { - "name": "enabled", - "type": "boolean", - "primaryKey": false, - "notNull": false - }, - "rate_limit_enabled": { - "name": "rate_limit_enabled", - "type": "boolean", - "primaryKey": false, - "notNull": false - }, - "rate_limit_time_window": { - "name": "rate_limit_time_window", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "rate_limit_max": { - "name": "rate_limit_max", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "request_count": { - "name": "request_count", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "remaining": { - "name": "remaining", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "last_request": { - "name": "last_request", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "expires_at": { - "name": "expires_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true - }, - "permissions": { - "name": "permissions", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "metadata": { - "name": "metadata", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": { - "idx_apikey_user": { - "name": "idx_apikey_user", - "columns": [ - { - "expression": "user_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "apikey_user_id_user_id_fk": { - "name": "apikey_user_id_user_id_fk", - "tableFrom": "apikey", - "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "public.coin": { - "name": "coin", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "serial", - "primaryKey": true, - "notNull": true - }, - "name": { - "name": "name", - "type": "varchar(255)", - "primaryKey": false, - "notNull": true - }, - "symbol": { - "name": "symbol", - "type": "varchar(10)", - "primaryKey": false, - "notNull": true - }, - "icon": { - "name": "icon", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "creator_id": { - "name": "creator_id", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "initial_supply": { - "name": "initial_supply", - "type": "numeric(30, 8)", - "primaryKey": false, - "notNull": true - }, - "circulating_supply": { - "name": "circulating_supply", - "type": "numeric(30, 8)", - "primaryKey": false, - "notNull": true - }, - "current_price": { - "name": "current_price", - "type": "numeric(20, 8)", - "primaryKey": false, - "notNull": true - }, - "market_cap": { - "name": "market_cap", - "type": "numeric(30, 2)", - "primaryKey": false, - "notNull": true - }, - "volume_24h": { - "name": "volume_24h", - "type": "numeric(30, 2)", - "primaryKey": false, - "notNull": false, - "default": "'0.00'" - }, - "change_24h": { - "name": "change_24h", - "type": "numeric(30, 4)", - "primaryKey": false, - "notNull": false, - "default": "'0.0000'" - }, - "pool_coin_amount": { - "name": "pool_coin_amount", - "type": "numeric(30, 8)", - "primaryKey": false, - "notNull": true, - "default": "'0.00000000'" - }, - "pool_base_currency_amount": { - "name": "pool_base_currency_amount", - "type": "numeric(30, 8)", - "primaryKey": false, - "notNull": true, - "default": "'0.00000000'" - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "is_listed": { - "name": "is_listed", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": true - }, - "trading_unlocks_at": { - "name": "trading_unlocks_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "is_locked": { - "name": "is_locked", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": true - } - }, - "indexes": { - "coin_symbol_idx": { - "name": "coin_symbol_idx", - "columns": [ - { - "expression": "symbol", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "coin_creator_id_idx": { - "name": "coin_creator_id_idx", - "columns": [ - { - "expression": "creator_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "coin_is_listed_idx": { - "name": "coin_is_listed_idx", - "columns": [ - { - "expression": "is_listed", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "coin_market_cap_idx": { - "name": "coin_market_cap_idx", - "columns": [ - { - "expression": "market_cap", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "coin_current_price_idx": { - "name": "coin_current_price_idx", - "columns": [ - { - "expression": "current_price", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "coin_change24h_idx": { - "name": "coin_change24h_idx", - "columns": [ - { - "expression": "change_24h", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "coin_volume24h_idx": { - "name": "coin_volume24h_idx", - "columns": [ - { - "expression": "volume_24h", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "coin_created_at_idx": { - "name": "coin_created_at_idx", - "columns": [ - { - "expression": "created_at", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "coin_creator_id_user_id_fk": { - "name": "coin_creator_id_user_id_fk", - "tableFrom": "coin", - "tableTo": "user", - "columnsFrom": [ - "creator_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "set null", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "coin_symbol_unique": { - "name": "coin_symbol_unique", - "nullsNotDistinct": false, - "columns": [ - "symbol" - ] - } - } - }, - "public.comment": { - "name": "comment", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "serial", - "primaryKey": true, - "notNull": true - }, - "user_id": { - "name": "user_id", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "coin_id": { - "name": "coin_id", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "content": { - "name": "content", - "type": "varchar(500)", - "primaryKey": false, - "notNull": true - }, - "likes_count": { - "name": "likes_count", - "type": "integer", - "primaryKey": false, - "notNull": true, - "default": 0 - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "is_deleted": { - "name": "is_deleted", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - } - }, - "indexes": { - "comment_user_id_idx": { - "name": "comment_user_id_idx", - "columns": [ - { - "expression": "user_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "comment_coin_id_idx": { - "name": "comment_coin_id_idx", - "columns": [ - { - "expression": "coin_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "comment_user_id_user_id_fk": { - "name": "comment_user_id_user_id_fk", - "tableFrom": "comment", - "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "set null", - "onUpdate": "no action" - }, - "comment_coin_id_coin_id_fk": { - "name": "comment_coin_id_coin_id_fk", - "tableFrom": "comment", - "tableTo": "coin", - "columnsFrom": [ - "coin_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "public.comment_like": { - "name": "comment_like", - "schema": "", - "columns": { - "user_id": { - "name": "user_id", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "comment_id": { - "name": "comment_id", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "comment_like_user_id_user_id_fk": { - "name": "comment_like_user_id_user_id_fk", - "tableFrom": "comment_like", - "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "comment_like_comment_id_comment_id_fk": { - "name": "comment_like_comment_id_comment_id_fk", - "tableFrom": "comment_like", - "tableTo": "comment", - "columnsFrom": [ - "comment_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": { - "comment_like_user_id_comment_id_pk": { - "name": "comment_like_user_id_comment_id_pk", - "columns": [ - "user_id", - "comment_id" - ] - } - }, - "uniqueConstraints": {} - }, - "public.notification": { - "name": "notification", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "serial", - "primaryKey": true, - "notNull": true - }, - "user_id": { - "name": "user_id", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "type": { - "name": "type", - "type": "notification_type", - "typeSchema": "public", - "primaryKey": false, - "notNull": true - }, - "title": { - "name": "title", - "type": "varchar(200)", - "primaryKey": false, - "notNull": true - }, - "message": { - "name": "message", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "link": { - "name": "link", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "is_read": { - "name": "is_read", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": { - "notification_user_id_idx": { - "name": "notification_user_id_idx", - "columns": [ - { - "expression": "user_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "notification_type_idx": { - "name": "notification_type_idx", - "columns": [ - { - "expression": "type", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "notification_is_read_idx": { - "name": "notification_is_read_idx", - "columns": [ - { - "expression": "is_read", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "notification_created_at_idx": { - "name": "notification_created_at_idx", - "columns": [ - { - "expression": "created_at", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "notification_user_id_user_id_fk": { - "name": "notification_user_id_user_id_fk", - "tableFrom": "notification", - "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "public.prediction_bet": { - "name": "prediction_bet", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "serial", - "primaryKey": true, - "notNull": true - }, - "user_id": { - "name": "user_id", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "question_id": { - "name": "question_id", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "side": { - "name": "side", - "type": "boolean", - "primaryKey": false, - "notNull": true - }, - "amount": { - "name": "amount", - "type": "numeric(20, 8)", - "primaryKey": false, - "notNull": true - }, - "actual_winnings": { - "name": "actual_winnings", - "type": "numeric(20, 8)", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "settled_at": { - "name": "settled_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - } - }, - "indexes": { - "prediction_bet_user_id_idx": { - "name": "prediction_bet_user_id_idx", - "columns": [ - { - "expression": "user_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "prediction_bet_question_id_idx": { - "name": "prediction_bet_question_id_idx", - "columns": [ - { - "expression": "question_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "prediction_bet_user_question_idx": { - "name": "prediction_bet_user_question_idx", - "columns": [ - { - "expression": "user_id", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "question_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "prediction_bet_created_at_idx": { - "name": "prediction_bet_created_at_idx", - "columns": [ - { - "expression": "created_at", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "prediction_bet_user_id_user_id_fk": { - "name": "prediction_bet_user_id_user_id_fk", - "tableFrom": "prediction_bet", - "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "set null", - "onUpdate": "no action" - }, - "prediction_bet_question_id_prediction_question_id_fk": { - "name": "prediction_bet_question_id_prediction_question_id_fk", - "tableFrom": "prediction_bet", - "tableTo": "prediction_question", - "columnsFrom": [ - "question_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "public.prediction_question": { - "name": "prediction_question", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "serial", - "primaryKey": true, - "notNull": true - }, - "creator_id": { - "name": "creator_id", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "question": { - "name": "question", - "type": "varchar(200)", - "primaryKey": false, - "notNull": true - }, - "status": { - "name": "status", - "type": "prediction_market_status", - "typeSchema": "public", - "primaryKey": false, - "notNull": true, - "default": "'ACTIVE'" - }, - "resolution_date": { - "name": "resolution_date", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true - }, - "ai_resolution": { - "name": "ai_resolution", - "type": "boolean", - "primaryKey": false, - "notNull": false - }, - "total_yes_amount": { - "name": "total_yes_amount", - "type": "numeric(20, 8)", - "primaryKey": false, - "notNull": true, - "default": "'0.00000000'" - }, - "total_no_amount": { - "name": "total_no_amount", - "type": "numeric(20, 8)", - "primaryKey": false, - "notNull": true, - "default": "'0.00000000'" - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "resolved_at": { - "name": "resolved_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - }, - "requires_web_search": { - "name": "requires_web_search", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "validation_reason": { - "name": "validation_reason", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": { - "prediction_question_creator_id_idx": { - "name": "prediction_question_creator_id_idx", - "columns": [ - { - "expression": "creator_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "prediction_question_status_idx": { - "name": "prediction_question_status_idx", - "columns": [ - { - "expression": "status", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "prediction_question_resolution_date_idx": { - "name": "prediction_question_resolution_date_idx", - "columns": [ - { - "expression": "resolution_date", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "prediction_question_status_resolution_idx": { - "name": "prediction_question_status_resolution_idx", - "columns": [ - { - "expression": "status", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "resolution_date", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "prediction_question_creator_id_user_id_fk": { - "name": "prediction_question_creator_id_user_id_fk", - "tableFrom": "prediction_question", - "tableTo": "user", - "columnsFrom": [ - "creator_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "set null", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "public.price_history": { - "name": "price_history", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "serial", - "primaryKey": true, - "notNull": true - }, - "coin_id": { - "name": "coin_id", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "price": { - "name": "price", - "type": "numeric(20, 8)", - "primaryKey": false, - "notNull": true - }, - "timestamp": { - "name": "timestamp", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "price_history_coin_id_coin_id_fk": { - "name": "price_history_coin_id_coin_id_fk", - "tableFrom": "price_history", - "tableTo": "coin", - "columnsFrom": [ - "coin_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "public.promo_code": { - "name": "promo_code", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "serial", - "primaryKey": true, - "notNull": true - }, - "code": { - "name": "code", - "type": "varchar(50)", - "primaryKey": false, - "notNull": true - }, - "description": { - "name": "description", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "reward_amount": { - "name": "reward_amount", - "type": "numeric(20, 8)", - "primaryKey": false, - "notNull": true - }, - "max_uses": { - "name": "max_uses", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "is_active": { - "name": "is_active", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": true - }, - "expires_at": { - "name": "expires_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "created_by": { - "name": "created_by", - "type": "integer", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "promo_code_created_by_user_id_fk": { - "name": "promo_code_created_by_user_id_fk", - "tableFrom": "promo_code", - "tableTo": "user", - "columnsFrom": [ - "created_by" - ], - "columnsTo": [ - "id" - ], - "onDelete": "set null", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "promo_code_code_unique": { - "name": "promo_code_code_unique", - "nullsNotDistinct": false, - "columns": [ - "code" - ] - } - } - }, - "public.promo_code_redemption": { - "name": "promo_code_redemption", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "serial", - "primaryKey": true, - "notNull": true - }, - "user_id": { - "name": "user_id", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "promo_code_id": { - "name": "promo_code_id", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "reward_amount": { - "name": "reward_amount", - "type": "numeric(20, 8)", - "primaryKey": false, - "notNull": true - }, - "redeemed_at": { - "name": "redeemed_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "promo_code_redemption_user_id_user_id_fk": { - "name": "promo_code_redemption_user_id_user_id_fk", - "tableFrom": "promo_code_redemption", - "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "promo_code_redemption_promo_code_id_promo_code_id_fk": { - "name": "promo_code_redemption_promo_code_id_promo_code_id_fk", - "tableFrom": "promo_code_redemption", - "tableTo": "promo_code", - "columnsFrom": [ - "promo_code_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "promo_code_redemption_user_id_promo_code_id_unique": { - "name": "promo_code_redemption_user_id_promo_code_id_unique", - "nullsNotDistinct": false, - "columns": [ - "user_id", - "promo_code_id" - ] - } - } - }, - "public.session": { - "name": "session", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "serial", - "primaryKey": true, - "notNull": true - }, - "expires_at": { - "name": "expires_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true - }, - "token": { - "name": "token", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "ip_address": { - "name": "ip_address", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "user_agent": { - "name": "user_agent", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "user_id": { - "name": "user_id", - "type": "integer", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "session_user_id_user_id_fk": { - "name": "session_user_id_user_id_fk", - "tableFrom": "session", - "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "session_token_unique": { - "name": "session_token_unique", - "nullsNotDistinct": false, - "columns": [ - "token" - ] - } - } - }, - "public.transaction": { - "name": "transaction", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "serial", - "primaryKey": true, - "notNull": true - }, - "user_id": { - "name": "user_id", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "coin_id": { - "name": "coin_id", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "type": { - "name": "type", - "type": "transaction_type", - "typeSchema": "public", - "primaryKey": false, - "notNull": true - }, - "quantity": { - "name": "quantity", - "type": "numeric(30, 8)", - "primaryKey": false, - "notNull": true - }, - "price_per_coin": { - "name": "price_per_coin", - "type": "numeric(20, 8)", - "primaryKey": false, - "notNull": true - }, - "total_base_currency_amount": { - "name": "total_base_currency_amount", - "type": "numeric(30, 8)", - "primaryKey": false, - "notNull": true - }, - "timestamp": { - "name": "timestamp", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "recipient_user_id": { - "name": "recipient_user_id", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "sender_user_id": { - "name": "sender_user_id", - "type": "integer", - "primaryKey": false, - "notNull": false - } - }, - "indexes": { - "transaction_user_id_idx": { - "name": "transaction_user_id_idx", - "columns": [ - { - "expression": "user_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "transaction_coin_id_idx": { - "name": "transaction_coin_id_idx", - "columns": [ - { - "expression": "coin_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "transaction_type_idx": { - "name": "transaction_type_idx", - "columns": [ - { - "expression": "type", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "transaction_timestamp_idx": { - "name": "transaction_timestamp_idx", - "columns": [ - { - "expression": "timestamp", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "transaction_user_coin_idx": { - "name": "transaction_user_coin_idx", - "columns": [ - { - "expression": "user_id", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "coin_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "transaction_coin_type_idx": { - "name": "transaction_coin_type_idx", - "columns": [ - { - "expression": "coin_id", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "type", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "transaction_user_id_user_id_fk": { - "name": "transaction_user_id_user_id_fk", - "tableFrom": "transaction", - "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "set null", - "onUpdate": "no action" - }, - "transaction_coin_id_coin_id_fk": { - "name": "transaction_coin_id_coin_id_fk", - "tableFrom": "transaction", - "tableTo": "coin", - "columnsFrom": [ - "coin_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "transaction_recipient_user_id_user_id_fk": { - "name": "transaction_recipient_user_id_user_id_fk", - "tableFrom": "transaction", - "tableTo": "user", - "columnsFrom": [ - "recipient_user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "set null", - "onUpdate": "no action" - }, - "transaction_sender_user_id_user_id_fk": { - "name": "transaction_sender_user_id_user_id_fk", - "tableFrom": "transaction", - "tableTo": "user", - "columnsFrom": [ - "sender_user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "set null", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "public.user": { - "name": "user", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "serial", - "primaryKey": true, - "notNull": true - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "email": { - "name": "email", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "email_verified": { - "name": "email_verified", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "image": { - "name": "image", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "is_admin": { - "name": "is_admin", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "is_banned": { - "name": "is_banned", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "ban_reason": { - "name": "ban_reason", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "base_currency_balance": { - "name": "base_currency_balance", - "type": "numeric(20, 8)", - "primaryKey": false, - "notNull": true, - "default": "'100.00000000'" - }, - "bio": { - "name": "bio", - "type": "varchar(160)", - "primaryKey": false, - "notNull": false, - "default": "'Hello am 48 year old man from somalia. Sorry for my bed england. I selled my wife for internet connection for play “conter stirk”'" - }, - "username": { - "name": "username", - "type": "varchar(30)", - "primaryKey": false, - "notNull": true - }, - "volume_master": { - "name": "volume_master", - "type": "numeric(3, 2)", - "primaryKey": false, - "notNull": true, - "default": "'0.70'" - }, - "volume_muted": { - "name": "volume_muted", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "last_reward_claim": { - "name": "last_reward_claim", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - }, - "total_rewards_claimed": { - "name": "total_rewards_claimed", - "type": "numeric(20, 8)", - "primaryKey": false, - "notNull": true, - "default": "'0.00000000'" - }, - "login_streak": { - "name": "login_streak", - "type": "integer", - "primaryKey": false, - "notNull": true, - "default": 0 - }, - "prestige_level": { - "name": "prestige_level", - "type": "integer", - "primaryKey": false, - "notNull": false, - "default": 0 - } - }, - "indexes": { - "user_username_idx": { - "name": "user_username_idx", - "columns": [ - { - "expression": "username", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "user_is_banned_idx": { - "name": "user_is_banned_idx", - "columns": [ - { - "expression": "is_banned", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "user_is_admin_idx": { - "name": "user_is_admin_idx", - "columns": [ - { - "expression": "is_admin", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "user_created_at_idx": { - "name": "user_created_at_idx", - "columns": [ - { - "expression": "created_at", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "user_updated_at_idx": { - "name": "user_updated_at_idx", - "columns": [ - { - "expression": "updated_at", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "user_email_unique": { - "name": "user_email_unique", - "nullsNotDistinct": false, - "columns": [ - "email" - ] - }, - "user_username_unique": { - "name": "user_username_unique", - "nullsNotDistinct": false, - "columns": [ - "username" - ] - } - } - }, - "public.user_portfolio": { - "name": "user_portfolio", - "schema": "", - "columns": { - "user_id": { - "name": "user_id", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "coin_id": { - "name": "coin_id", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "quantity": { - "name": "quantity", - "type": "numeric(30, 8)", - "primaryKey": false, - "notNull": true - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "user_portfolio_user_id_user_id_fk": { - "name": "user_portfolio_user_id_user_id_fk", - "tableFrom": "user_portfolio", - "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "user_portfolio_coin_id_coin_id_fk": { - "name": "user_portfolio_coin_id_coin_id_fk", - "tableFrom": "user_portfolio", - "tableTo": "coin", - "columnsFrom": [ - "coin_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": { - "user_portfolio_user_id_coin_id_pk": { - "name": "user_portfolio_user_id_coin_id_pk", - "columns": [ - "user_id", - "coin_id" - ] - } - }, - "uniqueConstraints": {} - }, - "public.verification": { - "name": "verification", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "serial", - "primaryKey": true, - "notNull": true - }, - "identifier": { - "name": "identifier", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "value": { - "name": "value", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "expires_at": { - "name": "expires_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - } - }, - "enums": { - "public.notification_type": { - "name": "notification_type", - "schema": "public", - "values": [ - "HOPIUM", - "SYSTEM", - "TRANSFER", - "RUG_PULL" - ] - }, - "public.prediction_market_status": { - "name": "prediction_market_status", - "schema": "public", - "values": [ - "ACTIVE", - "RESOLVED", - "CANCELLED" - ] - }, - "public.transaction_type": { - "name": "transaction_type", - "schema": "public", - "values": [ - "BUY", - "SELL", - "TRANSFER_IN", - "TRANSFER_OUT" - ] - } - }, - "schemas": {}, - "_meta": { - "columns": {}, - "schemas": {}, - "tables": {} - } -} \ No newline at end of file diff --git a/website/drizzle/meta/_journal.json b/website/drizzle/meta/_journal.json index 64e3751..964b39d 100644 --- a/website/drizzle/meta/_journal.json +++ b/website/drizzle/meta/_journal.json @@ -8,20 +8,6 @@ "when": 1750863600119, "tag": "0000_chief_korath", "breakpoints": true - }, - { - "idx": 1, - "version": "7", - "when": 1752593600974, - "tag": "0001_heavy_leo", - "breakpoints": true - }, - { - "idx": 2, - "version": "7", - "when": 1752597309305, - "tag": "0002_lonely_the_fallen", - "breakpoints": true } ] } \ No newline at end of file diff --git a/website/package-lock.json b/website/package-lock.json index 4aa83e0..c2675db 100644 --- a/website/package-lock.json +++ b/website/package-lock.json @@ -1,12 +1,12 @@ { "name": "website", - "version": "2.0.0.a0", + "version": "0.0.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "website", - "version": "2.0.0.a0", + "version": "0.0.1", "dependencies": { "@aws-sdk/client-s3": "^3.815.0", "@aws-sdk/s3-request-presigner": "^3.815.0", diff --git a/website/package.json b/website/package.json index c1daafb..cccea7a 100644 --- a/website/package.json +++ b/website/package.json @@ -1,7 +1,7 @@ { "name": "website", "private": true, - "version": "2.0.0.a0", + "version": "0.0.1", "type": "module", "scripts": { "dev": "vite dev", @@ -16,54 +16,53 @@ "db:studio": "drizzle-kit studio" }, "devDependencies": { - "@internationalized/date": "^3.8.2", - "@lucide/svelte": "^0.539.0", - "@sveltejs/adapter-auto": "^6.1.0", - "@sveltejs/adapter-node": "^5.2.14", - "@sveltejs/kit": "^2.29.1", - "@sveltejs/vite-plugin-svelte": "^6.1.2", + "@internationalized/date": "^3.8.1", + "@lucide/svelte": "^0.482.0", + "@sveltejs/adapter-auto": "^3.0.0", + "@sveltejs/adapter-node": "^5.2.12", + "@sveltejs/kit": "^2.0.0", + "@sveltejs/vite-plugin-svelte": "^4.0.0", "@types/canvas-confetti": "^1.9.0", - "@types/node": "^24.2.1", - "autoprefixer": "^10.4.21", - "bits-ui": "^2.9.2", + "@types/node": "^22.15.21", + "autoprefixer": "^10.4.20", + "bits-ui": "^2.5.0", "clsx": "^2.1.1", - "dotenv": "^17.2.1", - "drizzle-kit": "^0.31.4", - "prettier": "^3.6.2", - "prettier-plugin-svelte": "^3.4.0", - "prettier-plugin-tailwindcss": "^0.6.14", - "svelte": "^5.38.1", - "svelte-apexcharts": "^1.0.2", - "svelte-check": "^4.3.1", - "svelte-confetti": "^2.3.2", - "svelte-lightweight-charts": "^2.2.0", - "svelte-sonner": "^1.0.5", - "tailwind-merge": "^3.3.1", - "tailwind-variants": "^2.1.0", - "tailwindcss": "^4.1.11", - "tw-animate-css": "^1.3.6", - "typescript": "^5.9.2", - "vite": "^7.1.2", - "vite-plugin-iso-import": "^1.3.0" + "drizzle-kit": "^0.22.0", + "prettier": "^3.3.2", + "prettier-plugin-svelte": "^3.2.6", + "prettier-plugin-tailwindcss": "^0.6.11", + "svelte": "^5.0.0", + "svelte-check": "^4.0.0", + "svelte-sonner": "^1.0.2", + "tailwind-merge": "^3.0.2", + "tailwind-variants": "^0.2.1", + "tailwindcss": "^4.1.7", + "tw-animate-css": "^1.3.0", + "typescript": "^5.0.0", + "vite": "^5.4.11", + "vite-plugin-iso-import": "^1.2.0" }, "dependencies": { - "@aws-sdk/client-s3": "^3.864.0", - "@aws-sdk/s3-request-presigner": "^3.864.0", - "@tailwindcss/postcss": "^4.1.11", + "@aws-sdk/client-s3": "^3.815.0", + "@aws-sdk/s3-request-presigner": "^3.815.0", + "@tailwindcss/postcss": "^4.1.7", "@tailwindcss/typography": "^0.5.16", "@visx/scale": "^3.12.0", - "apexcharts": "^5.3.3", - "better-auth": "^1.3.6", + "apexcharts": "^4.7.0", + "better-auth": "^1.2.8", "canvas-confetti": "^1.9.3", - "drizzle-orm": "^0.44.4", + "drizzle-orm": "^0.33.0", "express": "^5.1.0", - "lightweight-charts": "^5.0.8", - "lucide-svelte": "^0.539.0", - "mode-watcher": "^1.1.0", - "openai": "^5.12.2", - "postgres": "^3.4.7", - "redis": "^5.8.1", - "sharp": "^0.34.3" + "lightweight-charts": "^5.0.7", + "lucide-svelte": "^0.511.0", + "mode-watcher": "^1.0.7", + "openai": "^4.103.0", + "postgres": "^3.4.4", + "redis": "^5.1.0", + "sharp": "^0.34.2", + "svelte-apexcharts": "^1.0.2", + "svelte-confetti": "^2.3.1", + "svelte-lightweight-charts": "^2.2.0" }, "optionalDependencies": { "@rollup/rollup-linux-x64-gnu": "*", diff --git a/website/src/app.html b/website/src/app.html index 685e40b..d0273c8 100644 --- a/website/src/app.html +++ b/website/src/app.html @@ -10,11 +10,11 @@ - CoinStorge + Rugplay - + - + @@ -23,10 +23,12 @@ - + - + %sveltekit.head% diff --git a/website/src/lib/auth.ts b/website/src/lib/auth.ts index a700fac..b53adf9 100644 --- a/website/src/lib/auth.ts +++ b/website/src/lib/auth.ts @@ -16,10 +16,11 @@ if (!publicEnv.PUBLIC_BETTER_AUTH_URL) throw new Error('PUBLIC_BETTER_AUTH_URL i export const auth = betterAuth({ baseURL: publicEnv.PUBLIC_BETTER_AUTH_URL, secret: privateEnv.PRIVATE_BETTER_AUTH_SECRET, - appName: "CoinStorge", + appName: "Rugplay", trustedOrigins: [ publicEnv.PUBLIC_BETTER_AUTH_URL, + "http://rugplay.com", "http://localhost:5173", ], diff --git a/website/src/lib/components/self/AppSidebar.svelte b/website/src/lib/components/self/AppSidebar.svelte index 051c55a..c54d63e 100644 --- a/website/src/lib/components/self/AppSidebar.svelte +++ b/website/src/lib/components/self/AppSidebar.svelte @@ -174,7 +174,7 @@
twoblade
- CoinStorge + Rugplay {#if $USER_DATA?.isAdmin} | Admin {/if} diff --git a/website/src/lib/components/self/DataTable.svelte b/website/src/lib/components/self/DataTable.svelte index abb38a6..709671f 100644 --- a/website/src/lib/components/self/DataTable.svelte +++ b/website/src/lib/components/self/DataTable.svelte @@ -191,7 +191,7 @@ {:else if cellData.type === 'coin'}
- {cellData.name} + {cellData.name}
{:else if cellData.type === 'rank'}
diff --git a/website/src/lib/components/self/SEO.svelte b/website/src/lib/components/self/SEO.svelte index 0f5c1e9..ea94e3b 100644 --- a/website/src/lib/components/self/SEO.svelte +++ b/website/src/lib/components/self/SEO.svelte @@ -2,13 +2,13 @@ import { page } from '$app/stores'; let { - title = 'CoinStorge', + title = 'Rugplay', description = 'Experience realistic cryptocurrency trading simulation game with AI-powered markets, rug pull mechanics, and virtual currencies. Learn crypto trading without financial risk in this educational game.', type = 'website', image = '/apple-touch-icon.png', - imageAlt = 'CoinStorge Logo', + imageAlt = 'Rugplay Logo', keywords = '', - author = 'Outpoot (with modifications)', + author = 'Outpoot', canonicalUrl = '', noindex = false, twitterCard = 'summary_large_image' @@ -29,7 +29,7 @@ let canonical = $derived(canonicalUrl || currentUrl); let fullImageUrl = $derived( - image?.startsWith('http') ? image : `${$page?.url?.origin || 'https://localhost'}${image}` + image?.startsWith('http') ? image : `${$page?.url?.origin || 'https://rugplay.com'}${image}` ); let defaultKeywords = @@ -62,7 +62,7 @@ - + diff --git a/website/src/lib/components/self/SignInConfirmDialog.svelte b/website/src/lib/components/self/SignInConfirmDialog.svelte index f97eaf5..56ee8bd 100644 --- a/website/src/lib/components/self/SignInConfirmDialog.svelte +++ b/website/src/lib/components/self/SignInConfirmDialog.svelte @@ -25,7 +25,7 @@ - Sign in to CoinStorge + Sign in to Rugplay Choose a service to sign in with. Your account will be created automatically if you don't have one. diff --git a/website/src/lib/components/self/UserManualModal.svelte b/website/src/lib/components/self/UserManualModal.svelte index 73deaac..3772ed3 100644 --- a/website/src/lib/components/self/UserManualModal.svelte +++ b/website/src/lib/components/self/UserManualModal.svelte @@ -30,9 +30,9 @@ const tips: Tip[] = [ { id: 1, - title: 'Welcome to CoinStorge!', + title: 'Welcome to Rugplay!', description: - 'CoinStorge is a cryptocurrency trading simulator where you can practice trading without real financial risk. Start with virtual money, create coins, bet on prediction markets, and most importantly, rugpull!', + 'Rugplay is a cryptocurrency trading simulator where you can practice trading without real financial risk. Start with virtual money, create coins, bet on prediction markets, and most importantly, rugpull!', icon: BookOpen, image: '/tips/cover.avif' }, @@ -56,7 +56,7 @@ id: 4, title: 'AMM - Automated Market Maker', description: - 'CoinStorge, like Rugplay, uses an AMM system where prices are calculated automatically based on supply and demand. The more you buy, the higher the price goes. The more you sell, the lower it drops. Large trades create "slippage" - the price change during your trade.', + 'Rugplay uses an AMM system where prices are calculated automatically based on supply and demand. The more you buy, the higher the price goes. The more you sell, the lower it drops. Large trades create "slippage" - the price change during your trade.', icon: BarChart3, image: '/tips/amm.avif' }, @@ -205,11 +205,11 @@
{#each tips as tip, index} {/each} diff --git a/website/src/lib/server/ai.ts b/website/src/lib/server/ai.ts index f3d4c4d..9f50772 100644 --- a/website/src/lib/server/ai.ts +++ b/website/src/lib/server/ai.ts @@ -3,7 +3,7 @@ import { zodResponseFormat } from 'openai/helpers/zod'; import { z } from 'zod'; import { OPENROUTER_API_KEY } from '$env/static/private'; import { db } from './db'; -import { coin, user, transaction, priceHistory } from './db/schema'; +import { coin, user, transaction } from './db/schema'; import { eq, desc, sql, gte } from 'drizzle-orm'; if (!OPENROUTER_API_KEY) { @@ -88,14 +88,7 @@ async function getCoinData(coinSymbol: string) { return null; } - const [priceStats] = await db - .select({ - maxPrice: sql`MAX(CAST(${priceHistory.price} AS NUMERIC))`, - minPrice: sql`MIN(CAST(${priceHistory.price} AS NUMERIC))`, - }) - .from(priceHistory) - .where(eq(priceHistory.coinId, coinData.id)); - + // Get recent trading activity for this coin const recentTrades = await db .select({ type: transaction.type, @@ -120,10 +113,6 @@ async function getCoinData(coinSymbol: string) { poolCoinAmount: Number(coinData.poolCoinAmount), poolBaseCurrencyAmount: Number(coinData.poolBaseCurrencyAmount), circulatingSupply: Number(coinData.circulatingSupply), - pricing: { - peak: Number(priceStats?.maxPrice || 0), - lowest: Number(priceStats?.minPrice || 0), - }, recentTrades: recentTrades.map(trade => ({ ...trade, quantity: Number(trade.quantity), @@ -245,11 +234,11 @@ export async function validateQuestion(question: string, description?: string): } const prompt = ` -You are evaluating whether a prediction market question is valid and answerable for CoinStorge, a cryptocurrency trading simulation platform. +You are evaluating whether a prediction market question is valid and answerable for Rugplay, a cryptocurrency trading simulation platform. Question: "${question}" -Current CoinStorge Market Context: +Current Rugplay Market Context: - Platform currency: $ (or *BUSS) - Total listed coins: ${marketOverview?.marketStats.totalCoins || 0} - Total market cap: $${marketOverview?.marketStats.totalMarketCap.toFixed(2) || '0'} @@ -271,8 +260,8 @@ Determine the optimal resolution date based on the question type: - If the question explicitly states the date, use that as the resolution date Also determine: -- Whether this question requires web search (external events, real-world data, non-CoinStorge information) -- If the question is related to the CoinStorge market, and contains what appears to be a coin name, ensure it's properly formatted (e.g. *BTC, *DOGE). Invalid question example: "will BTC reach $100,000 in 1 hour?" (invalid coin format, should be *BTC). +- Whether this question requires web search (external events, real-world data, non-Rugplay information) +- If the question is related to the Rugplay market, and contains what appears to be a coin name, ensure it's properly formatted (e.g. *BTC, *DOGE). Invalid question example: "will BTC reach $100,000 in 1 hour?" (invalid coin format, should be *BTC). - Provide a specific resolution date with time (suggest times between 12:00-20:00 UTC for good global coverage) The current date and time is ${new Date().toISOString()}. Note: All coins use *SYMBOL format (e.g., *BTC, *DOGE). All trading is simulated with *BUSS currency. @@ -336,11 +325,11 @@ export async function resolveQuestion( const rugplayData = customRugplayData || await getRugplayData(question); const prompt = ` -You are resolving a prediction market question with a definitive YES or NO answer for CoinStorge. +You are resolving a prediction market question with a definitive YES or NO answer for Rugplay. Question: "${question}" -Current CoinStorge Platform Data: +Current Rugplay Platform Data: ${rugplayData} Instructions: @@ -348,10 +337,10 @@ Instructions: 2. Give your confidence level (0-100) in this resolution 3. Provide clear reasoning for your decision with specific data references 4. For coin-specific questions that mention non-existent coins, answer NO (the coin doesn't exist, so it can't reach any price) -5. For coin-specific questions about existing coins, reference actual market data from CoinStorge +5. For coin-specific questions about existing coins, reference actual market data from Rugplay 6. For external events, use web search if enabled -Context about CoinStorge: +Context about Rugplay: - Cryptocurrency trading simulation platform with fake money (*BUSS) - All coins use *SYMBOL format (e.g., *BTC, *DOGE, *SHIB) - Features AMM liquidity pools, rug pull mechanics, and real market dynamics @@ -421,7 +410,7 @@ export async function getRugplayData(question?: string): Promise { coinSpecificData = '\n\nCoin Analysis for Question:'; if (nonExistentCoins.length > 0) { - coinSpecificData += `\nNON-EXISTENT COINS: ${nonExistentCoins.map(symbol => `*${symbol}`).join(', ')} - These coins do not exist on the CoinStorge platform`; + coinSpecificData += `\nNON-EXISTENT COINS: ${nonExistentCoins.map(symbol => `*${symbol}`).join(', ')} - These coins do not exist on the Rugplay platform`; } if (existingCoins.length > 0) { @@ -430,8 +419,6 @@ export async function getRugplayData(question?: string): Promise { return ` *${coin.symbol} (${coin.name}): - Current Price: $${coin.currentPrice.toFixed(8)} -- Peak Price: $${coin.pricing.peak.toFixed(8)} -- Lowest Price: $${coin.pricing.lowest.toFixed(8)} - Market Cap: $${coin.marketCap.toFixed(2)} - 24h Change: ${coin.change24h >= 0 ? '+' : ''}${coin.change24h.toFixed(2)}% - 24h Volume: $${coin.volume24h.toFixed(2)} @@ -450,7 +437,7 @@ ${coin.recentTrades.slice(0, 3).map(trade => return ` Current Timestamp: ${new Date().toISOString()} -Platform: CoinStorge - Cryptocurrency Trading Simulation +Platform: Rugplay - Cryptocurrency Trading Simulation Market Overview: - Total Listed Coins: ${marketOverview?.marketStats.totalCoins || 0} @@ -473,7 +460,7 @@ Platform Details: - Coins use *SYMBOL format (e.g., *BTC, *DOGE, *SHIB)${coinSpecificData} `; } catch (error) { - console.error('Error generating CoinStorge data:', error); + console.error('Error generating Rugplay data:', error); return `Couldn't retrieve data, please try again later.`; } } diff --git a/website/src/lib/server/amm.ts b/website/src/lib/server/amm.ts deleted file mode 100644 index 92c7c1c..0000000 --- a/website/src/lib/server/amm.ts +++ /dev/null @@ -1,142 +0,0 @@ -import { db } from '$lib/server/db'; -import { coin, transaction, priceHistory, userPortfolio } from '$lib/server/db/schema'; -import { eq, and, gte } from 'drizzle-orm'; -import { createNotification } from '$lib/server/notification'; - -export async function calculate24hMetrics(coinId: number, currentPrice: number) { - const twentyFourHoursAgo = new Date(Date.now() - 24 * 60 * 60 * 1000); - - const [priceData] = await db - .select({ price: priceHistory.price }) - .from(priceHistory) - .where(and( - eq(priceHistory.coinId, coinId), - gte(priceHistory.timestamp, twentyFourHoursAgo) - )) - .orderBy(priceHistory.timestamp) - .limit(1); - - let change24h = 0; - if (priceData) { - const priceFrom24hAgo = Number(priceData.price); - if (priceFrom24hAgo > 0) { - change24h = ((currentPrice - priceFrom24hAgo) / priceFrom24hAgo) * 100; - } - } - - const volumeData = await db - .select({ totalBaseCurrencyAmount: transaction.totalBaseCurrencyAmount }) - .from(transaction) - .where(and( - eq(transaction.coinId, coinId), - gte(transaction.timestamp, twentyFourHoursAgo) - )); - - const volume24h = volumeData.reduce((sum, tx) => sum + Number(tx.totalBaseCurrencyAmount), 0); - - return { change24h: Number(change24h.toFixed(4)), volume24h: Number(volume24h.toFixed(4)) }; -} - -export async function executeSellTrade( - tx: any, - coinData: any, - userId: number, - quantity: number -) { - const poolCoinAmount = Number(coinData.poolCoinAmount); - const poolBaseCurrencyAmount = Number(coinData.poolBaseCurrencyAmount); - const currentPrice = Number(coinData.currentPrice); - - if (poolCoinAmount <= 0 || poolBaseCurrencyAmount <= 0) { - throw new Error('Liquidity pool is not properly initialized or is empty'); - } - - const k = poolCoinAmount * poolBaseCurrencyAmount; - const newPoolCoin = poolCoinAmount + quantity; - const newPoolBaseCurrency = k / newPoolCoin; - const baseCurrencyReceived = poolBaseCurrencyAmount - newPoolBaseCurrency; - const newPrice = newPoolBaseCurrency / newPoolCoin; - - if (baseCurrencyReceived <= 0 || newPoolBaseCurrency < 1) { - const fallbackValue = quantity * currentPrice; - return { - success: false, - fallbackValue, - newPrice: currentPrice, - priceImpact: 0 - }; - } - - const priceImpact = ((newPrice - currentPrice) / currentPrice) * 100; - - await tx.insert(transaction).values({ - userId, - coinId: coinData.id, - type: 'SELL', - quantity: quantity.toString(), - pricePerCoin: (baseCurrencyReceived / quantity).toString(), - totalBaseCurrencyAmount: baseCurrencyReceived.toString(), - timestamp: new Date() - }); - - await tx.insert(priceHistory).values({ - coinId: coinData.id, - price: newPrice.toString() - }); - - const metrics = await calculate24hMetrics(coinData.id, newPrice); - - await tx.update(coin) - .set({ - currentPrice: newPrice.toString(), - marketCap: (Number(coinData.circulatingSupply) * newPrice).toString(), - poolCoinAmount: newPoolCoin.toString(), - poolBaseCurrencyAmount: newPoolBaseCurrency.toString(), - change24h: metrics.change24h.toString(), - volume24h: metrics.volume24h.toString(), - updatedAt: new Date() - }) - .where(eq(coin.id, coinData.id)); - - const isRugPull = priceImpact < -20 && baseCurrencyReceived > 1000; - if (isRugPull) { - (async () => { - try { - const affectedUsers = await db - .select({ - userId: userPortfolio.userId, - quantity: userPortfolio.quantity - }) - .from(userPortfolio) - .where(eq(userPortfolio.coinId, coinData.id)); - - for (const holder of affectedUsers) { - if (holder.userId === userId) continue; - - const holdingValue = Number(holder.quantity) * newPrice; - if (holdingValue > 10) { - await createNotification( - holder.userId.toString(), - 'RUG_PULL', - 'Coin rugpulled!', - `A coin you owned, ${coinData.name} (*${coinData.symbol}), crashed ${Math.abs(priceImpact).toFixed(1)}%!`, - `/coin/${coinData.symbol}` - ); - } - } - } catch (error) { - console.error('Error sending rug pull notifications:', error); - } - })(); - } - - return { - success: true, - baseCurrencyReceived, - newPrice, - priceImpact, - newPoolCoin, - newPoolBaseCurrency, - metrics - }; -} diff --git a/website/src/lib/server/db/schema.ts b/website/src/lib/server/db/schema.ts index f5ff472..40abe7e 100644 --- a/website/src/lib/server/db/schema.ts +++ b/website/src/lib/server/db/schema.ts @@ -96,8 +96,6 @@ export const coin = pgTable("coin", { createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(), updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(), isListed: boolean("is_listed").default(true).notNull(), - tradingUnlocksAt: timestamp("trading_unlocks_at"), - isLocked: boolean("is_locked").default(true).notNull(), }, (table) => { return { symbolIdx: index("coin_symbol_idx").on(table.symbol), @@ -267,7 +265,6 @@ export const notifications = pgTable("notification", { type: notificationTypeEnum("type").notNull(), title: varchar("title", { length: 200 }).notNull(), message: text("message").notNull(), - link: text("link"), isRead: boolean("is_read").notNull().default(false), createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(), }, (table) => { diff --git a/website/src/lib/server/job.ts b/website/src/lib/server/job.ts index 04ba42a..9f3a61a 100644 --- a/website/src/lib/server/job.ts +++ b/website/src/lib/server/job.ts @@ -120,7 +120,6 @@ export async function resolveExpiredQuestions() { 'HOPIUM', title, message, - `/hopium/${question.id}` ); } }); @@ -220,7 +219,6 @@ export async function resolveExpiredQuestions() { 'HOPIUM', title, message, - `/hopium/${question.id}` ); } }); diff --git a/website/src/lib/server/notification.ts b/website/src/lib/server/notification.ts index abf7428..a5dd010 100644 --- a/website/src/lib/server/notification.ts +++ b/website/src/lib/server/notification.ts @@ -9,14 +9,12 @@ export async function createNotification( type: NotificationType, title: string, message: string, - link?: string, ): Promise { await db.insert(notifications).values({ userId: parseInt(userId), type, title, - message, - link + message }); try { @@ -29,7 +27,6 @@ export async function createNotification( notificationType: type, title, message, - link }; await redis.publish(channel, JSON.stringify(payload)); diff --git a/website/src/lib/stores/notifications.ts b/website/src/lib/stores/notifications.ts index 3618d72..a5a00b9 100644 --- a/website/src/lib/stores/notifications.ts +++ b/website/src/lib/stores/notifications.ts @@ -2,10 +2,9 @@ import { writable, derived } from 'svelte/store'; export interface Notification { id: number; - type: 'HOPIUM' | 'TRANSFER' | 'RUG_PULL' | 'SYSTEM'; + type: string; title: string; message: string; - link?: string; data: any; isRead: boolean; createdAt: string; @@ -24,10 +23,10 @@ export async function fetchNotifications(unreadOnly = false) { if (!response.ok) throw new Error('Failed to fetch notifications'); const data = await response.json(); - + NOTIFICATIONS.set(data.notifications); UNREAD_COUNT.set(data.unreadCount); - + return data; } catch (error) { console.error('Failed to fetch notifications:', error); @@ -35,21 +34,23 @@ export async function fetchNotifications(unreadOnly = false) { } } -export async function markNotificationsAsRead() { +export async function markNotificationsAsRead(ids: number[]) { try { const response = await fetch('/api/notifications', { method: 'PATCH', headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ markAsRead: true }) + body: JSON.stringify({ ids, markAsRead: true }) }); if (!response.ok) throw new Error('Failed to mark notifications as read'); - NOTIFICATIONS.update(notifications => - notifications.map(notif => ({ ...notif, isRead: true })) + NOTIFICATIONS.update(notifications => + notifications.map(notif => + ids.includes(notif.id) ? { ...notif, isRead: true } : notif + ) ); - UNREAD_COUNT.set(0); + UNREAD_COUNT.update(count => Math.max(0, count - ids.length)); } catch (error) { console.error('Failed to mark notifications as read:', error); @@ -57,4 +58,4 @@ export async function markNotificationsAsRead() { } } -export const hasUnreadNotifications = derived(UNREAD_COUNT, count => count > 0); \ No newline at end of file +export const hasUnreadNotifications = derived(UNREAD_COUNT, count => count > 0); diff --git a/website/src/lib/stores/websocket.ts b/website/src/lib/stores/websocket.ts index 7e26a26..54d38b2 100644 --- a/website/src/lib/stores/websocket.ts +++ b/website/src/lib/stores/websocket.ts @@ -197,7 +197,6 @@ function handleWebSocketMessage(event: MessageEvent): void { type: message.notificationType, title: message.title, message: message.message, - link: message.link, isRead: false, createdAt: message.timestamp, data: message.amount ? { amount: message.amount } : null diff --git a/website/src/lib/utils.ts b/website/src/lib/utils.ts index 919c9a3..f5b1e30 100644 --- a/website/src/lib/utils.ts +++ b/website/src/lib/utils.ts @@ -123,7 +123,7 @@ export function formatRelativeTime(timestamp: string | Date): string { if (hours < 24) { const extraMinutes = minutes % 60; - return extraMinutes === 0 ? `${hours}h` : `${hours}h ${extraMinutes}m`; + return extraMinutes === 0 ? `${hours}hr` : `${hours}hr ${extraMinutes}m`; } if (days < 7) return `${days}d`; @@ -145,11 +145,11 @@ export function formatRelativeTime(timestamp: string | Date): string { tempDate.setMonth(tempDate.getMonth() + adjustedMonths); const remainingDays = Math.floor((now.getTime() - tempDate.getTime()) / (1000 * 60 * 60 * 24)); const weeks = Math.floor(remainingDays / 7); - return weeks === 0 ? `${adjustedMonths}mo` : `${adjustedMonths}mo ${weeks}w`; + return weeks === 0 ? `${adjustedMonths}m` : `${adjustedMonths}m ${weeks}w`; } const remainingMonths = adjustedMonths % 12; - return remainingMonths === 0 ? `${years}y` : `${years}y ${remainingMonths}mo`; + return remainingMonths === 0 ? `${years}y` : `${years}y ${remainingMonths}m`; } export function formatTimeAgo(date: string) { diff --git a/website/src/routes/+error.svelte b/website/src/routes/+error.svelte index 2503a70..537c6b1 100644 --- a/website/src/routes/+error.svelte +++ b/website/src/routes/+error.svelte @@ -36,7 +36,7 @@ - {status} | CoinStorge + {status} | Rugplay diff --git a/website/src/routes/+page.svelte b/website/src/routes/+page.svelte index ec36eaa..8ee3466 100644 --- a/website/src/routes/+page.svelte +++ b/website/src/routes/+page.svelte @@ -75,7 +75,7 @@ @@ -85,7 +85,7 @@

- {$USER_DATA ? getTimeBasedGreeting($USER_DATA?.name) : 'Welcome to CoinStorge!'} + {$USER_DATA ? getTimeBasedGreeting($USER_DATA?.name) : 'Welcome to Rugplay!'}

{#if $USER_DATA} diff --git a/website/src/routes/about/+page.svelte b/website/src/routes/about/+page.svelte index 78ac4d4..dd5bfdc 100644 --- a/website/src/routes/about/+page.svelte +++ b/website/src/routes/about/+page.svelte @@ -22,18 +22,18 @@ - About - CoinStorge + About - Rugplay

- CoinStorge -

CoinStorge

+ Rugplay +

Rugplay

A crypto trading simulator where you can practice trading without losing real money. Create diff --git a/website/src/routes/api/coin/[coinSymbol]/+server.ts b/website/src/routes/api/coin/[coinSymbol]/+server.ts index 1e8c5af..1f5be80 100644 --- a/website/src/routes/api/coin/[coinSymbol]/+server.ts +++ b/website/src/routes/api/coin/[coinSymbol]/+server.ts @@ -134,9 +134,7 @@ export async function GET({ params, url }) { creatorName: user.name, creatorUsername: user.username, creatorBio: user.bio, - creatorImage: user.image, - tradingUnlocksAt: coin.tradingUnlocksAt, - isLocked: coin.isLocked + creatorImage: user.image }) .from(coin) .leftJoin(user, eq(coin.creatorId, user.id)) @@ -187,9 +185,7 @@ export async function GET({ params, url }) { poolCoinAmount: Number(coinData.poolCoinAmount), poolBaseCurrencyAmount: Number(coinData.poolBaseCurrencyAmount), circulatingSupply: Number(coinData.circulatingSupply), - initialSupply: Number(coinData.initialSupply), - tradingUnlocksAt: coinData.tradingUnlocksAt, - isLocked: coinData.isLocked + initialSupply: Number(coinData.initialSupply) }, candlestickData, volumeData, diff --git a/website/src/routes/api/coin/[coinSymbol]/trade/+server.ts b/website/src/routes/api/coin/[coinSymbol]/trade/+server.ts index a51b140..821e93e 100644 --- a/website/src/routes/api/coin/[coinSymbol]/trade/+server.ts +++ b/website/src/routes/api/coin/[coinSymbol]/trade/+server.ts @@ -5,7 +5,43 @@ import { coin, userPortfolio, user, transaction, priceHistory } from '$lib/serve import { eq, and, gte } from 'drizzle-orm'; import { redis } from '$lib/server/redis'; import { createNotification } from '$lib/server/notification'; -import { calculate24hMetrics, executeSellTrade } from '$lib/server/amm'; + +async function calculate24hMetrics(coinId: number, currentPrice: number) { + const twentyFourHoursAgo = new Date(Date.now() - 24 * 60 * 60 * 1000); + + // Get price from 24h ago + const [priceData] = await db + .select({ price: priceHistory.price }) + .from(priceHistory) + .where(and( + eq(priceHistory.coinId, coinId), + gte(priceHistory.timestamp, twentyFourHoursAgo) + )) + .orderBy(priceHistory.timestamp) + .limit(1); + + // Calculate 24h change + let change24h = 0; + if (priceData) { + const priceFrom24hAgo = Number(priceData.price); + if (priceFrom24hAgo > 0) { + change24h = ((currentPrice - priceFrom24hAgo) / priceFrom24hAgo) * 100; + } + } + + // Calculate 24h volume + const volumeData = await db + .select({ totalBaseCurrencyAmount: transaction.totalBaseCurrencyAmount }) + .from(transaction) + .where(and( + eq(transaction.coinId, coinId), + gte(transaction.timestamp, twentyFourHoursAgo) + )); + + const volume24h = volumeData.reduce((sum, tx) => sum + Number(tx.totalBaseCurrencyAmount), 0); + + return { change24h: Number(change24h.toFixed(4)), volume24h: Number(volume24h.toFixed(4)) }; +} export async function POST({ params, request }) { const session = await auth.api.getSession({ @@ -40,20 +76,7 @@ export async function POST({ params, request }) { } return await db.transaction(async (tx) => { - const [coinData] = await tx.select({ - id: coin.id, - symbol: coin.symbol, - name: coin.name, - icon: coin.icon, - currentPrice: coin.currentPrice, - poolCoinAmount: coin.poolCoinAmount, - poolBaseCurrencyAmount: coin.poolBaseCurrencyAmount, - circulatingSupply: coin.circulatingSupply, - isListed: coin.isListed, - creatorId: coin.creatorId, - tradingUnlocksAt: coin.tradingUnlocksAt, - isLocked: coin.isLocked - }).from(coin).where(eq(coin.symbol, normalizedSymbol)).for('update').limit(1); + const [coinData] = await tx.select().from(coin).where(eq(coin.symbol, normalizedSymbol)).for('update').limit(1); if (!coinData) { throw error(404, 'Coin not found'); @@ -63,18 +86,6 @@ export async function POST({ params, request }) { throw error(400, 'This coin is delisted and cannot be traded'); } - if (coinData.isLocked && coinData.tradingUnlocksAt && userId !== coinData.creatorId) { - const unlockTime = new Date(coinData.tradingUnlocksAt); - if (new Date() < unlockTime) { - const remainingSeconds = Math.ceil((unlockTime.getTime() - Date.now()) / 1000); - throw error(400, `Trading is locked. Unlocks in ${remainingSeconds} seconds.`); - } - - await tx.update(coin) - .set({ isLocked: false }) - .where(eq(coin.id, coinData.id)); - } - const [userData] = await tx.select({ baseCurrencyBalance: user.baseCurrencyBalance, username: user.username, @@ -243,21 +254,24 @@ export async function POST({ params, request }) { } // Allow more aggressive selling for rug pull simulation - prevent only mathematical breakdown - const maxSellable = Math.floor(Number(coinData.poolCoinAmount) * 0.995); + const maxSellable = Math.floor(poolCoinAmount * 0.995); if (amount > maxSellable) { throw error(400, `Cannot sell more than 99.5% of pool tokens. Max sellable: ${maxSellable} tokens`); } - const sellResult = await executeSellTrade(tx, coinData, userId, amount); + const k = poolCoinAmount * poolBaseCurrencyAmount; + const newPoolCoin = poolCoinAmount + amount; + const newPoolBaseCurrency = k / newPoolCoin; + const baseCurrencyReceived = poolBaseCurrencyAmount - newPoolBaseCurrency; - if (!sellResult.success) { - throw error(400, 'Trade failed - insufficient liquidity or invalid parameters'); + totalCost = baseCurrencyReceived; + newPrice = newPoolBaseCurrency / newPoolCoin; + priceImpact = ((newPrice - currentPrice) / currentPrice) * 100; + + if (newPoolBaseCurrency < 10) { + throw error(400, `Trade would drain pool below minimum liquidity (*10 BUSS). Try selling fewer tokens.`); } - totalCost = sellResult.baseCurrencyReceived ?? 0; - newPrice = sellResult.newPrice; - priceImpact = sellResult.priceImpact; - if (totalCost <= 0) { throw error(400, 'Trade amount results in zero base currency received'); } @@ -288,15 +302,71 @@ export async function POST({ params, request }) { )); } - const metrics = sellResult.metrics || await calculate24hMetrics(coinData.id, newPrice); + await tx.insert(transaction).values({ + userId, + coinId: coinData.id, + type: 'SELL', + quantity: amount.toString(), + pricePerCoin: (totalCost / amount).toString(), + totalBaseCurrencyAmount: totalCost.toString() + }); + + await tx.insert(priceHistory).values({ + coinId: coinData.id, + price: newPrice.toString() + }); + + const metrics = await calculate24hMetrics(coinData.id, newPrice); + + await tx.update(coin) + .set({ + currentPrice: newPrice.toString(), + marketCap: (Number(coinData.circulatingSupply) * newPrice).toString(), + poolCoinAmount: newPoolCoin.toString(), + poolBaseCurrencyAmount: newPoolBaseCurrency.toString(), + change24h: metrics.change24h.toString(), + volume24h: metrics.volume24h.toString(), + updatedAt: new Date() + }) + .where(eq(coin.id, coinData.id)); + + const isRugPull = priceImpact < -20 && totalCost > 1000; + + // Send rug pull notifications to affected users + if (isRugPull) { + (async () => { + const affectedUsers = await db + .select({ + userId: userPortfolio.userId, + quantity: userPortfolio.quantity + }) + .from(userPortfolio) + .where(eq(userPortfolio.coinId, coinData.id)); + + for (const holder of affectedUsers) { + if (holder.userId === userId) continue; + + const holdingValue = Number(holder.quantity) * newPrice; + if (holdingValue > 10) { + const lossAmount = Number(holder.quantity) * (currentPrice - newPrice); + await createNotification( + holder.userId.toString(), + 'RUG_PULL', + 'Coin rugpulled!', + `A coin you owned, ${coinData.name} (*${normalizedSymbol}), crashed ${Math.abs(priceImpact).toFixed(1)}%!`, + ); + } + } + })(); + } const priceUpdateData = { currentPrice: newPrice, marketCap: Number(coinData.circulatingSupply) * newPrice, change24h: metrics.change24h, volume24h: metrics.volume24h, - poolCoinAmount: sellResult.newPoolCoin, - poolBaseCurrencyAmount: sellResult.newPoolBaseCurrency + poolCoinAmount: newPoolCoin, + poolBaseCurrencyAmount: newPoolBaseCurrency }; const tradeData = { @@ -338,4 +408,4 @@ export async function POST({ params, request }) { }); } }); -} \ No newline at end of file +} diff --git a/website/src/routes/api/coin/create/+server.ts b/website/src/routes/api/coin/create/+server.ts index 02ac0aa..c89bee3 100644 --- a/website/src/routes/api/coin/create/+server.ts +++ b/website/src/routes/api/coin/create/+server.ts @@ -114,9 +114,7 @@ export async function POST({ request }) { currentPrice: STARTING_PRICE.toString(), marketCap: (FIXED_SUPPLY * STARTING_PRICE).toString(), poolCoinAmount: FIXED_SUPPLY.toString(), - poolBaseCurrencyAmount: INITIAL_LIQUIDITY.toString(), - tradingUnlocksAt: new Date(Date.now() + 60 * 1000), // 1 minute from now - isLocked: true + poolBaseCurrencyAmount: INITIAL_LIQUIDITY.toString() }).returning(); createdCoin = newCoin; diff --git a/website/src/routes/api/notifications/+server.ts b/website/src/routes/api/notifications/+server.ts index 08a6443..1438ef1 100644 --- a/website/src/routes/api/notifications/+server.ts +++ b/website/src/routes/api/notifications/+server.ts @@ -25,7 +25,6 @@ export const GET: RequestHandler = async ({ url, request }) => { type: notifications.type, title: notifications.title, message: notifications.message, - link: notifications.link, isRead: notifications.isRead, createdAt: notifications.createdAt, }) @@ -55,22 +54,24 @@ export const PATCH: RequestHandler = async ({ request }) => { if (!session?.user) throw error(401, 'Not authenticated'); const userId = Number(session.user.id); - const { markAsRead } = await request.json(); + const { ids, markAsRead } = await request.json(); - if (typeof markAsRead !== 'boolean') { + if (!Array.isArray(ids) || typeof markAsRead !== 'boolean') { throw error(400, 'Invalid request body'); } try { - if (markAsRead) { - await db.update(notifications) - .set({ isRead: true }) - .where(eq(notifications.userId, userId)); - } + await db + .update(notifications) + .set({ isRead: markAsRead }) + .where(and( + eq(notifications.userId, userId), + inArray(notifications.id, ids) + )); return json({ success: true }); } catch (e) { console.error('Failed to update notifications:', e); throw error(500, 'Failed to update notifications'); } -}; \ No newline at end of file +}; diff --git a/website/src/routes/api/prestige/+server.ts b/website/src/routes/api/prestige/+server.ts index e60bb73..4564278 100644 --- a/website/src/routes/api/prestige/+server.ts +++ b/website/src/routes/api/prestige/+server.ts @@ -5,7 +5,6 @@ import { user, userPortfolio, transaction, notifications, coin } from '$lib/serv import { eq, sql } from 'drizzle-orm'; import type { RequestHandler } from './$types'; import { formatValue, getPrestigeCost, getPrestigeName } from '$lib/utils'; -import { executeSellTrade } from '$lib/server/amm'; export const POST: RequestHandler = async ({ request, locals }) => { const session = await auth.api.getSession({ headers: request.headers }); @@ -45,10 +44,7 @@ export const POST: RequestHandler = async ({ request, locals }) => { coinId: userPortfolio.coinId, quantity: userPortfolio.quantity, currentPrice: coin.currentPrice, - symbol: coin.symbol, - poolCoinAmount: coin.poolCoinAmount, - poolBaseCurrencyAmount: coin.poolBaseCurrencyAmount, - circulatingSupply: coin.circulatingSupply + symbol: coin.symbol }) .from(userPortfolio) .leftJoin(coin, eq(userPortfolio.coinId, coin.id)) @@ -62,37 +58,18 @@ export const POST: RequestHandler = async ({ request, locals }) => { for (const holding of holdings) { const quantity = Number(holding.quantity); - const currentPrice = Number(holding.currentPrice); + const price = Number(holding.currentPrice); + const saleValue = quantity * price; + totalSaleValue += saleValue; - if (Number(holding.poolCoinAmount) <= 0 || Number(holding.poolBaseCurrencyAmount) <= 0) { - const fallbackValue = quantity * currentPrice; - totalSaleValue += fallbackValue; - - await tx.insert(transaction).values({ - userId, - coinId: holding.coinId!, - type: 'SELL', - quantity: holding.quantity, - pricePerCoin: holding.currentPrice || '0', - totalBaseCurrencyAmount: fallbackValue.toString(), - timestamp: new Date() - }); - continue; - } - - const sellResult = await executeSellTrade(tx, { - id: holding.coinId, - poolCoinAmount: holding.poolCoinAmount, - poolBaseCurrencyAmount: holding.poolBaseCurrencyAmount, - currentPrice: holding.currentPrice, - circulatingSupply: holding.circulatingSupply - }, userId, quantity); - - if (sellResult.success && sellResult.baseCurrencyReceived) { - totalSaleValue += sellResult.baseCurrencyReceived; - } else { - totalSaleValue += sellResult.fallbackValue || (quantity * currentPrice); - } + await tx.insert(transaction).values({ + coinId: holding.coinId!, + type: 'SELL', + quantity: holding.quantity, + pricePerCoin: holding.currentPrice || '0', + totalBaseCurrencyAmount: saleValue.toString(), + timestamp: new Date() + }); } await tx @@ -117,7 +94,6 @@ export const POST: RequestHandler = async ({ request, locals }) => { type: 'SYSTEM', title: `${prestigeName} Achieved!`, message: `Congratulations! You have successfully reached ${prestigeName}. Your portfolio has been reset, daily reward cooldown has been cleared, and you can now start fresh with your new prestige badge and enhanced daily rewards.`, - link: `/user/${userId}` }); return json({ diff --git a/website/src/routes/api/rewards/claim/+server.ts b/website/src/routes/api/rewards/claim/+server.ts index 1b34447..58994a1 100644 --- a/website/src/routes/api/rewards/claim/+server.ts +++ b/website/src/routes/api/rewards/claim/+server.ts @@ -13,32 +13,10 @@ const REWARD_TIERS = [ 1500, // Day 2 1800, // Day 3 2100, // Day 4 - 2500, // Day 5 - 3000, // Day 6 - 3500, // Day 7 - 4000, // Day 8 - 4200, // Day 9 - 4400, // Day 10 - 4600, // Day 11 - 4800, // Day 12 - 5000, // Day 13 - 5200, // Day 14 - 5400, // Day 15 - 5600, // Day 16 - 5800, // Day 17 - 6000, // Day 18 - 6200, // Day 19 - 6400, // Day 20 - 6600, // Day 21 - 6800, // Day 22 - 7000, // Day 23 - 7200, // Day 24 - 7400, // Day 25 - 7600, // Day 26 - 7800, // Day 27 - 8000, // Day 28 - 8200, // Day 29 - 8500 // Day 30+ + 2500, // Day 5 + 3000, // Day 6 + 3500, // Day 7 + 4000, // Day 8+ ]; const PRESTIGE_MULTIPLIERS = { diff --git a/website/src/routes/api/transfer/+server.ts b/website/src/routes/api/transfer/+server.ts index 7c1f225..726d345 100644 --- a/website/src/routes/api/transfer/+server.ts +++ b/website/src/routes/api/transfer/+server.ts @@ -131,7 +131,6 @@ export const POST: RequestHandler = async ({ request }) => { 'TRANSFER', 'Money received!', `You received ${formatValue(amount)} from @${senderData.username}`, - `/user/${senderData.id}` ); })(); @@ -265,7 +264,6 @@ export const POST: RequestHandler = async ({ request }) => { 'TRANSFER', 'Coins received!', `You received ${amount.toFixed(6)} *${coinData.symbol} from @${senderData.username}`, - `/coin/${normalizedSymbol}` ); })(); diff --git a/website/src/routes/coin/[coinSymbol]/+page.svelte b/website/src/routes/coin/[coinSymbol]/+page.svelte index bcdb565..980159f 100644 --- a/website/src/routes/coin/[coinSymbol]/+page.svelte +++ b/website/src/routes/coin/[coinSymbol]/+page.svelte @@ -43,8 +43,6 @@ let shouldSignIn = $state(false); let previousCoinSymbol = $state(null); - let countdown = $state(null); - let countdownInterval = $state(null); const timeframeOptions = [ { value: '1m', label: '1 minute' }, @@ -91,41 +89,6 @@ } }); - $effect(() => { - if (coin?.isLocked && coin?.tradingUnlocksAt) { - const unlockTime = new Date(coin.tradingUnlocksAt).getTime(); - - const updateCountdown = () => { - const now = Date.now(); - const remaining = Math.max(0, Math.ceil((unlockTime - now) / 1000)); - countdown = remaining; - - if (remaining === 0 && countdownInterval) { - clearInterval(countdownInterval); - countdownInterval = null; - if (coin) { - coin = { ...coin, isLocked: false }; - } - } - }; - - updateCountdown(); - countdownInterval = setInterval(updateCountdown, 1000); - } else { - countdown = null; - if (countdownInterval) { - clearInterval(countdownInterval); - countdownInterval = null; - } - } - - return () => { - if (countdownInterval) { - clearInterval(countdownInterval); - } - }; - }); - async function loadCoinData() { try { loading = true; @@ -393,17 +356,6 @@ }; }); } - - function formatCountdown(seconds: number): string { - const mins = Math.floor(seconds / 60); - const secs = seconds % 60; - return `${mins}:${secs.toString().padStart(2, '0')}`; - } - - let isCreator = $derived(coin && $USER_DATA && coin.creatorId === Number($USER_DATA.id)); - let isTradingLocked = $derived(coin?.isLocked && countdown !== null && countdown > 0); - let canTrade = $derived(!isTradingLocked || isCreator); - {/if} - {#if isTradingLocked} - - 🔒 LOCKED {countdown !== null ? formatCountdown(countdown) : ''} - - {/if} {#if !coin.isListed} Delisted {/if} @@ -582,15 +529,6 @@ {coin.symbol}

{/if} - {#if isTradingLocked} -

- {#if isCreator} - 🔒 Creator-only period: {countdown !== null ? formatCountdown(countdown) : ''} remaining - {:else} - 🔒 Trading unlocks in: {countdown !== null ? formatCountdown(countdown) : ''} - {/if} -

- {/if} {#if $USER_DATA} @@ -600,7 +538,7 @@ variant="default" size="lg" onclick={() => (buyModalOpen = true)} - disabled={!coin.isListed || !canTrade} + disabled={!coin.isListed} > Buy {coin.symbol} @@ -610,7 +548,7 @@ variant="outline" size="lg" onclick={() => (sellModalOpen = true)} - disabled={!coin.isListed || userHolding <= 0 || !canTrade} + disabled={!coin.isListed || userHolding <= 0} > Sell {coin.symbol} diff --git a/website/src/routes/coin/create/+page.svelte b/website/src/routes/coin/create/+page.svelte index 38fbe9b..f8c463f 100644 --- a/website/src/routes/coin/create/+page.svelte +++ b/website/src/routes/coin/create/+page.svelte @@ -238,9 +238,9 @@

• Starting Price: $0.000001 per token

• You receive 100% of the supply

• Initial Market Cap: $1,000

-

• Trading Lock: 1 minute creator-only period

- After creation, you'll have 1 minute of exclusive trading time before others can trade. This allows you to purchase your initial supply. + These settings ensure a fair start for all traders. The price will increase + naturally as people buy tokens.

diff --git a/website/src/routes/gambling/+page.svelte b/website/src/routes/gambling/+page.svelte index 1ad6f35..996aeb4 100644 --- a/website/src/routes/gambling/+page.svelte +++ b/website/src/routes/gambling/+page.svelte @@ -40,8 +40,8 @@ diff --git a/website/src/routes/hopium/[id]/+page.svelte b/website/src/routes/hopium/[id]/+page.svelte index ff92890..2e54c3a 100644 --- a/website/src/routes/hopium/[id]/+page.svelte +++ b/website/src/routes/hopium/[id]/+page.svelte @@ -224,7 +224,7 @@
-

{question.question}

+

{question.question}

{#if question.status === 'ACTIVE'}

{formatTimeUntil(question.resolutionDate).startsWith('Ended') diff --git a/website/src/routes/legal/privacy/+page.svelte b/website/src/routes/legal/privacy/+page.svelte index 6b769c2..4697285 100644 --- a/website/src/routes/legal/privacy/+page.svelte +++ b/website/src/routes/legal/privacy/+page.svelte @@ -13,8 +13,8 @@ @@ -50,7 +50,7 @@ it, and what happens when you delete your account.

- Platform Note: CoinStorge is a simulated trading environment using virtual currency + Platform Note: Rugplay is a simulated trading environment using virtual currency ("*BUSS" or "$") with no real monetary value.

@@ -74,7 +74,7 @@
-

2.2 Simulated Trading and Simulated Financial Data

+

2.2 Trading and Financial Data (Simulated)

  • Transaction history (buy/sell orders, amounts, prices, timestamps)
  • Portfolio holdings and balances
  • @@ -107,7 +107,7 @@
  • Platform analytics and improvements
  • Resolving disputes and maintaining system integrity
  • - Operating and resolving prediction markets, which may involve AI-assisted decision-making + Operating and resolving prediction markets, which may involve automated decision-making as detailed below.
@@ -241,6 +241,9 @@
  • 14 days later: Complete deletion process executed automatically
  • +
  • + Cancellation: Contact support within 14 days to cancel deletion +
  • @@ -260,7 +263,7 @@

    6. Your Data Protection Rights

    - You have rights regarding your personal data, + Depending on your location, you may have certain rights regarding your personal data, including:

      @@ -295,8 +298,8 @@

    To exercise these rights, please contact us at privacy@ndspir.it{CONTACT_EMAIL}.

    @@ -324,8 +327,7 @@

    8. Data Sharing

    -

    We do not sell your personal data.

    -

    We might be forced to share your personal data with third parties:

    +

    We do not sell or share your personal data with third parties, except:

    • When required by law or legal process
    • To prevent fraud or protect platform security
    • @@ -357,8 +359,8 @@

      For privacy-related questions or to exercise your rights:

      • - Email: privacy@ndspir.it{CONTACT_EMAIL}
      • To cancel account deletion: Contact us immediately at the above email
      • @@ -380,7 +382,7 @@ Contact: {CONTACT_EMAIL}

        -

        Platform: CoinStorge - virtual cryptocurrency trading simulation

        +

        Platform: Rugplay - virtual cryptocurrency trading simulation

    diff --git a/website/src/routes/legal/terms/+page.svelte b/website/src/routes/legal/terms/+page.svelte index 593600d..6af532f 100644 --- a/website/src/routes/legal/terms/+page.svelte +++ b/website/src/routes/legal/terms/+page.svelte @@ -9,13 +9,14 @@ import { goto } from '$app/navigation'; import SEO from '$lib/components/self/SEO.svelte'; - const LAST_UPDATED = 'September 1, 2025'; - const CONTACT_EMAIL = '[REDACTED]'; + const LAST_UPDATED = 'May 29, 2025'; + const CONTACT_EMAIL = 'contact@outpoot.com'; + const MINIMUM_AGE = 18; @@ -35,7 +36,7 @@ Virtual Currency Simulation Only - CoinStorge uses only virtual currency (*BUSS or "$") with no real monetary value. All trading, + Rugplay uses only virtual currency (*BUSS or "$") with no real monetary value. All trading, including rug pulls, is simulated for educational purposes only. @@ -46,14 +47,13 @@

    1. Acceptance of Terms

    - By accessing and using CoinStorge ("the Platform", "we", "us", "our"), you accept and agree + By accessing and using Rugplay ("the Platform", "we", "us", "our"), you accept and agree to be bound by these Terms of Service ("Terms"). If you do not agree to these Terms, you may not use the Platform.

    - These Terms constitute a legally binding agreement between you and CoinStorge regarding your - use of our cryptocurrency trading simulation platform. If you are not of the age required to sign - a binding contract, you may not use the Platform. + These Terms constitute a legally binding agreement between you and Rugplay regarding your + use of our cryptocurrency trading simulation platform.

    @@ -61,7 +61,7 @@

    2. Platform Description

    - CoinStorge is a simulated cryptocurrency trading platform designed for educational + Rugplay is a simulated cryptocurrency trading platform designed for educational and entertainment purposes. The Platform allows users to:

      @@ -77,7 +77,7 @@ No Real Financial Value - All currency on CoinStorge (*BUSS, "$", and created coins) is virtual and has no + All currency on Rugplay (*BUSS, "$", and created coins) is virtual and has no real-world monetary value. No real cryptocurrency or money is involved in any transactions. @@ -91,12 +91,11 @@

      3.1 Age Requirements

      - You must be at least 18 years old to use CoinStorge. + You must be at least {MINIMUM_AGE} years old to use Rugplay due to the presence of gambling-style + features (coinflip and slots), even though they use only virtual currency.

      - Due to the presence of gambling-style - features (coinflip and slots), even though they use only virtual currency, and while our platform - uses only virtual currency with no real-world value, we maintain an 18+ + While our platform uses virtual currency with no real-world value, we maintain an 18+ age requirement to ensure responsible engagement with simulated gambling mechanics.

      @@ -114,7 +113,7 @@

      3.3 Prohibited Users

      -

      You may not use CoinStorge if you are:

      +

      You may not use Rugplay if you are:

      • Located in a jurisdiction where use is prohibited
      • Previously banned from the Platform
      • @@ -133,7 +132,7 @@ Rug Pull Risk Simulation - CoinStorge deliberately simulates rug pull scenarios where coin creators or large holders + Rugplay deliberately simulates rug pull scenarios where coin creators or large holders can crash prices by selling significant holdings. This is a core educational feature. @@ -155,7 +154,7 @@

        4.2 Trading Mechanics

        -

        Trading on CoinStorge includes realistic mechanics such as:

        +

        Trading on Rugplay includes realistic mechanics such as:

        • Slippage: Large trades affect prices based on liquidity pool ratios @@ -203,7 +202,7 @@

          5.1 Acceptable Use

          - You agree to use CoinStorge only for lawful purposes and in accordance with these Terms. + You agree to use Rugplay only for lawful purposes and in accordance with these Terms. You will not:

            @@ -255,13 +254,13 @@ Terms, your investments may be forfeited. This includes:

              -
            • Holdings in coins with names, symbols, or descriptions which are inappropriate or prohibited by applicable law
            • +
            • Holdings in coins with inappropriate names, symbols, or descriptions
            • Bets placed on prediction markets with offensive or prohibited content
            • Investments in content that violates intellectual property rights
            • Any virtual currency associated with content we remove for Terms violations

            - No Compensation: There is no refund of + No Compensation: We will not provide alternative compensation or restore virtual balances lost due to investments in prohibited content. You invest at your own risk.

            @@ -314,7 +313,7 @@

            7.1 Virtual Gambling Games

            -

            CoinStorge includes simulated gambling features:

            +

            Rugplay includes simulated gambling features:

            • Coinflip: Binary outcome betting with virtual currency
            • @@ -413,7 +412,7 @@ Important Legal Disclaimers - CoinStorge is provided "as is" without warranties. We are not liable for virtual losses, + Rugplay is provided "as is" without warranties. We are not liable for virtual losses, rug pulls, or any platform-related damages. @@ -449,7 +448,7 @@

              9.3 Educational Purpose

              -

              CoinStorge is designed for educational and entertainment purposes. It is not:

              +

              Rugplay is designed for educational and entertainment purposes. It is not:

              • Financial advice or investment guidance
              • A substitute for professional financial education
              • @@ -470,6 +469,7 @@

                • Is scheduled 14 days after your request
                • +
                • Can be cancelled during the 14-day period by contacting support
                • Results in permanent loss of all virtual currency and account data
                • May leave some anonymized data as described in our Privacy Policy
                @@ -504,8 +504,7 @@

                11.1 Platform Ownership

                -

                CoinStorge is based on Rugplay, licensed under CC BY-NC by OutPoot (FaceDev).

                -

                CoinStorge and all related intellectual property are owned by either us or OutPoot, including:

                +

                Rugplay and all related intellectual property are owned by us, including:

                • Software, code, algorithms, and technical systems
                • Trademarks, logos, and branding
                • @@ -518,7 +517,7 @@

                  11.2 Past Project Assets and Themes

                  - CoinStorge incorporates intellectual property from creators' past projects, including: + Rugplay incorporates intellectual property from creator's past projects, including:

                  • Characters, artwork, and visual themes from previous projects
                  • @@ -526,7 +525,7 @@
                  • Any derivative works or adaptations of existing intellectual property

                  - All past project assets used in CoinStorge are owned by the platform creators or used + All past project assets used in Rugplay are owned by the platform creators or used with proper authorization.

                  @@ -551,7 +550,7 @@ in our Privacy Policy, which is incorporated into these Terms by reference.

                  - By using CoinStorge, you consent to our data practices as described in the Privacy Policy, + By using Rugplay, you consent to our data practices as described in the Privacy Policy, including the retention of anonymized data after account deletion.

                  @@ -562,8 +561,8 @@

                  13.1 Entire Agreement

                  - These Terms, along with our Privacy Policy — incorporated in these Terms by reference —, constitute the entire agreement between - you and CoinStorge regarding use of the Platform. + These Terms, along with our Privacy Policy, constitute the entire agreement between + you and Rugplay regarding use of the Platform.

                  @@ -579,18 +578,27 @@

                  13.3 Updates to Terms

                  We may update these Terms periodically. Material changes will be communicated via - email and platform notifications, on a best-effort basis. Continued use after changes constitutes acceptance. - Failure to communicate does not automatically terminate our Agreement. + email and platform notifications. Continued use after changes constitutes acceptance.

                - +
                +

                13.4 Contact Information

                +

                + For questions about these Terms, contact us at: + {CONTACT_EMAIL} +

                +

                Last Updated: {LAST_UPDATED}

                -

                Platform: CoinStorge

                +

                + Contact: + {CONTACT_EMAIL} +

                +

                Platform: Rugplay

              diff --git a/website/src/routes/market/+page.svelte b/website/src/routes/market/+page.svelte index e507d95..836bc22 100644 --- a/website/src/routes/market/+page.svelte +++ b/website/src/routes/market/+page.svelte @@ -445,7 +445,7 @@
              -

              {coin.name}

              +

              {coin.name}

              *{coin.symbol}

              diff --git a/website/src/routes/notifications/+page.svelte b/website/src/routes/notifications/+page.svelte index 3e1eea4..7a8ba6a 100644 --- a/website/src/routes/notifications/+page.svelte +++ b/website/src/routes/notifications/+page.svelte @@ -16,7 +16,6 @@ import { formatTimeAgo, formatValue } from '$lib/utils'; import { goto } from '$app/navigation'; import { toast } from 'svelte-sonner'; - import NotificationItem from './NotificationItem.svelte'; let loading = $state(true); let newNotificationIds = $state([]); @@ -33,7 +32,9 @@ const unreadIds = ($NOTIFICATIONS || []).filter((n) => !n.isRead).map((n) => n.id); newNotificationIds = unreadIds; - await markNotificationsAsRead(); + if (unreadIds.length > 0) { + await markNotificationsAsRead(unreadIds); + } } catch (error) { toast.error('Failed to load notifications'); } finally { @@ -131,7 +132,13 @@ {#each $NOTIFICATIONS as notification, index (notification.id)} {@const IconComponent = getNotificationIcon(notification.type)} {@const isNewNotification = newNotificationIds.includes(notification.id)} - + {#if index < $NOTIFICATIONS.length - 1} diff --git a/website/src/routes/notifications/NotificationItem.svelte b/website/src/routes/notifications/NotificationItem.svelte deleted file mode 100644 index d28943e..0000000 --- a/website/src/routes/notifications/NotificationItem.svelte +++ /dev/null @@ -1,46 +0,0 @@ - - -{#if notification.link} - - - -{:else} -
              - -
              -{/if} \ No newline at end of file