| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351 |
- import { getDb } from './index'
- export type ReferrerMode = 'self' | 'follow_target'
- export interface WatchedAddress {
- id: number
- address: string
- label: string | null
- enabled: number
- copy_multiplier: number | null
- copy_max_usd: number | null
- referrer_mode: ReferrerMode
- created_at: string
- }
- export interface PositionMapping {
- id: number
- target_address: string
- target_nft_mint: string
- target_personal_position: string | null
- our_nft_mint: string | null
- pool_id: string
- tick_lower: number
- tick_upper: number
- status: string
- pnl_usd: string | null
- pnl_percent: string | null
- apr: string | null
- bonus_usd: string | null
- earned_usd: string | null
- liquidity_usd: string | null
- created_at: string
- updated_at: string
- }
- export interface CopyHistoryRow {
- id: number
- target_address: string
- target_tx_sig: string
- operation: string
- target_nft_mint: string | null
- our_nft_mint: string | null
- our_tx_sig: string | null
- pool_id: string | null
- target_amount_a: string | null
- target_amount_b: string | null
- our_amount_a: string | null
- our_amount_b: string | null
- status: string
- error_message: string | null
- swap_tx_sig: string | null
- created_at: string
- }
- // Watched Addresses
- export function getWatchedAddresses(): WatchedAddress[] {
- return getDb()
- .prepare('SELECT * FROM watched_addresses ORDER BY created_at DESC')
- .all() as WatchedAddress[]
- }
- export function getEnabledWatchedAddresses(): WatchedAddress[] {
- return getDb()
- .prepare('SELECT * FROM watched_addresses WHERE enabled = 1')
- .all() as WatchedAddress[]
- }
- export function addWatchedAddress(address: string, label?: string) {
- return getDb()
- .prepare('INSERT OR IGNORE INTO watched_addresses (address, label) VALUES (?, ?)')
- .run(address, label || null)
- }
- export function removeWatchedAddress(id: number) {
- return getDb().prepare('DELETE FROM watched_addresses WHERE id = ?').run(id)
- }
- export function toggleWatchedAddress(id: number, enabled: boolean) {
- return getDb()
- .prepare('UPDATE watched_addresses SET enabled = ? WHERE id = ?')
- .run(enabled ? 1 : 0, id)
- }
- export function getWatchedAddressByAddress(address: string): WatchedAddress | undefined {
- return getDb().prepare('SELECT * FROM watched_addresses WHERE address = ?').get(address) as
- | WatchedAddress
- | undefined
- }
- export function updateWatchedAddressSettings(
- id: number,
- settings: {
- copyMultiplier?: number | null
- copyMaxUsd?: number | null
- referrerMode?: ReferrerMode
- },
- ) {
- const sets: string[] = []
- const values: unknown[] = []
- if (settings.copyMultiplier !== undefined) {
- sets.push('copy_multiplier = ?')
- values.push(settings.copyMultiplier)
- }
- if (settings.copyMaxUsd !== undefined) {
- sets.push('copy_max_usd = ?')
- values.push(settings.copyMaxUsd)
- }
- if (settings.referrerMode !== undefined) {
- sets.push('referrer_mode = ?')
- values.push(settings.referrerMode)
- }
- if (sets.length === 0) return
- values.push(id)
- return getDb()
- .prepare(`UPDATE watched_addresses SET ${sets.join(', ')} WHERE id = ?`)
- .run(...values)
- }
- // Position Mappings
- export function getPositionMappings(status?: string): PositionMapping[] {
- if (status) {
- return getDb()
- .prepare('SELECT * FROM position_mappings WHERE status = ? ORDER BY created_at DESC')
- .all(status) as PositionMapping[]
- }
- return getDb()
- .prepare('SELECT * FROM position_mappings ORDER BY created_at DESC')
- .all() as PositionMapping[]
- }
- export function getPositionMappingByTargetNft(targetNftMint: string): PositionMapping | undefined {
- return getDb()
- .prepare('SELECT * FROM position_mappings WHERE target_nft_mint = ?')
- .get(targetNftMint) as PositionMapping | undefined
- }
- export function getPositionMappingByTargetPosition(
- targetPersonalPosition: string,
- ): PositionMapping | undefined {
- return getDb()
- .prepare('SELECT * FROM position_mappings WHERE target_personal_position = ?')
- .get(targetPersonalPosition) as PositionMapping | undefined
- }
- export function upsertPositionMapping(params: {
- targetAddress: string
- targetNftMint: string
- targetPersonalPosition?: string
- ourNftMint?: string
- poolId: string
- tickLower: number
- tickUpper: number
- status?: string
- }) {
- return getDb()
- .prepare(
- `INSERT INTO position_mappings (target_address, target_nft_mint, target_personal_position, our_nft_mint, pool_id, tick_lower, tick_upper, status)
- VALUES (?, ?, ?, ?, ?, ?, ?, ?)
- ON CONFLICT(target_nft_mint) DO UPDATE SET
- our_nft_mint = COALESCE(excluded.our_nft_mint, our_nft_mint),
- status = COALESCE(excluded.status, status),
- updated_at = datetime('now')`,
- )
- .run(
- params.targetAddress,
- params.targetNftMint,
- params.targetPersonalPosition || null,
- params.ourNftMint || null,
- params.poolId,
- params.tickLower,
- params.tickUpper,
- params.status || 'active',
- )
- }
- export function updatePositionMappingStatus(targetNftMint: string, status: string) {
- return getDb()
- .prepare(
- "UPDATE position_mappings SET status = ?, updated_at = datetime('now') WHERE target_nft_mint = ?",
- )
- .run(status, targetNftMint)
- }
- export function getPositionMappingById(id: number): PositionMapping | undefined {
- return getDb().prepare('SELECT * FROM position_mappings WHERE id = ?').get(id) as
- | PositionMapping
- | undefined
- }
- export function deletePositionMapping(id: number) {
- return getDb().prepare('DELETE FROM position_mappings WHERE id = ?').run(id)
- }
- export function updatePositionMappingSyncData(
- ourNftMint: string,
- data: {
- pnlUsd?: string
- pnlPercent?: string
- apr?: string
- bonusUsd?: string
- earnedUsd?: string
- liquidityUsd?: string
- },
- ) {
- return getDb()
- .prepare(
- `UPDATE position_mappings SET
- pnl_usd = ?, pnl_percent = ?, apr = ?, bonus_usd = ?, earned_usd = ?, liquidity_usd = ?,
- updated_at = datetime('now')
- WHERE our_nft_mint = ?`,
- )
- .run(
- data.pnlUsd || null,
- data.pnlPercent || null,
- data.apr || null,
- data.bonusUsd || null,
- data.earnedUsd || null,
- data.liquidityUsd || null,
- ourNftMint,
- )
- }
- export function getActivePositionNftMints(): string[] {
- const rows = getDb()
- .prepare("SELECT our_nft_mint FROM position_mappings WHERE status = 'active' AND our_nft_mint IS NOT NULL")
- .all() as { our_nft_mint: string }[]
- return rows.map((r) => r.our_nft_mint)
- }
- // Copy History
- export function addCopyHistory(params: {
- targetAddress: string
- targetTxSig: string
- operation: string
- targetNftMint?: string
- poolId?: string
- targetAmountA?: string
- targetAmountB?: string
- status?: string
- }): number {
- const result = getDb()
- .prepare(
- `INSERT INTO copy_history (target_address, target_tx_sig, operation, target_nft_mint, pool_id, target_amount_a, target_amount_b, status)
- VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
- )
- .run(
- params.targetAddress,
- params.targetTxSig,
- params.operation,
- params.targetNftMint || null,
- params.poolId || null,
- params.targetAmountA || null,
- params.targetAmountB || null,
- params.status || 'pending',
- )
- return result.lastInsertRowid as number
- }
- export function updateCopyHistory(
- id: number,
- updates: {
- ourNftMint?: string
- ourTxSig?: string
- ourAmountA?: string
- ourAmountB?: string
- status?: string
- errorMessage?: string
- swapTxSig?: string
- },
- ) {
- const sets: string[] = []
- const values: unknown[] = []
- if (updates.ourNftMint !== undefined) {
- sets.push('our_nft_mint = ?')
- values.push(updates.ourNftMint)
- }
- if (updates.ourTxSig !== undefined) {
- sets.push('our_tx_sig = ?')
- values.push(updates.ourTxSig)
- }
- if (updates.ourAmountA !== undefined) {
- sets.push('our_amount_a = ?')
- values.push(updates.ourAmountA)
- }
- if (updates.ourAmountB !== undefined) {
- sets.push('our_amount_b = ?')
- values.push(updates.ourAmountB)
- }
- if (updates.status !== undefined) {
- sets.push('status = ?')
- values.push(updates.status)
- }
- if (updates.errorMessage !== undefined) {
- sets.push('error_message = ?')
- values.push(updates.errorMessage)
- }
- if (updates.swapTxSig !== undefined) {
- sets.push('swap_tx_sig = ?')
- values.push(updates.swapTxSig)
- }
- if (sets.length === 0) return
- values.push(id)
- return getDb()
- .prepare(`UPDATE copy_history SET ${sets.join(', ')} WHERE id = ?`)
- .run(...values)
- }
- export function getCopyHistory(limit = 50, offset = 0): CopyHistoryRow[] {
- return getDb()
- .prepare('SELECT * FROM copy_history ORDER BY created_at DESC LIMIT ? OFFSET ?')
- .all(limit, offset) as CopyHistoryRow[]
- }
- // Settings
- export function getSetting(key: string): string | undefined {
- const row = getDb().prepare('SELECT value FROM settings WHERE key = ?').get(key) as
- | { value: string }
- | undefined
- return row?.value
- }
- export function setSetting(key: string, value: string) {
- return getDb()
- .prepare(
- `INSERT INTO settings (key, value) VALUES (?, ?)
- ON CONFLICT(key) DO UPDATE SET value = excluded.value, updated_at = datetime('now')`,
- )
- .run(key, value)
- }
- export function getAllSettings(): Record<string, string> {
- const rows = getDb().prepare('SELECT key, value FROM settings').all() as {
- key: string
- value: string
- }[]
- return Object.fromEntries(rows.map((r) => [r.key, r.value]))
- }
- // Check if TX already processed
- export function isTxProcessed(txSig: string): boolean {
- const row = getDb().prepare('SELECT id FROM copy_history WHERE target_tx_sig = ?').get(txSig) as
- | { id: number }
- | undefined
- return !!row
- }
|