From f354fbd6c69a23b9f1b8459e96b7d950265e985f Mon Sep 17 00:00:00 2001 From: MarcoMandar Date: Tue, 19 Nov 2024 07:28:00 +0200 Subject: [PATCH] token balance, transactions, data simulation update on buys and sells Signed-off-by: MarcoMandar --- .../src/providers/trustScoreProvider.ts | 40 ++++++ .../src/adapters/trustScoreDatabase.ts | 120 ++++++++++++++++++ 2 files changed, 160 insertions(+) diff --git a/packages/plugin-solana/src/providers/trustScoreProvider.ts b/packages/plugin-solana/src/providers/trustScoreProvider.ts index 88c2b97df01..fcb98d394e4 100644 --- a/packages/plugin-solana/src/providers/trustScoreProvider.ts +++ b/packages/plugin-solana/src/providers/trustScoreProvider.ts @@ -351,10 +351,14 @@ export class TrustScoreManager { new PublicKey(Wallet!) ); + let tokensBalance = 0; const prices = await wallet.fetchPrices(runtime); const solPrice = prices.solana.usd; const buySol = data.buy_amount / parseFloat(solPrice); const buy_value_usd = data.buy_amount * processedData.tradeData.price; + const token = await this.tokenProvider.fetchTokenTradeData(); + const tokenPrice = token.price; + tokensBalance = buy_value_usd / tokenPrice; const creationData = { token_address: tokenAddress, @@ -383,6 +387,23 @@ export class TrustScoreManager { rapidDump: false, }; this.trustScoreDb.addTradePerformance(creationData, data.is_simulation); + + if (data.is_simulation) { + // If the trade is a simulation update the balance + this.trustScoreDb.updateTokenBalance(tokenAddress, tokensBalance); + // generate some random hash for simulations + const hash = Math.random().toString(36).substring(7); + const transaction = { + tokenAddress: tokenAddress, + type: "buy", + transactionHash: hash, + amount: data.buy_amount, + price: processedData.tradeData.price, + isSimulation: true, + timestamp: new Date().toISOString(), + }; + this.trustScoreDb.addTransaction(transaction); + } // api call to update trade performance this.createTradeInBe(tokenAddress, recommenderId, data); return creationData; @@ -507,6 +528,25 @@ export class TrustScoreManager { sellDetailsData, isSimulation ); + if (isSimulation) { + // If the trade is a simulation update the balance + const oldBalance = this.trustScoreDb.getTokenBalance(tokenAddress); + const tokenBalance = oldBalance - sellDetails.sell_amount; + this.trustScoreDb.updateTokenBalance(tokenAddress, tokenBalance); + // generate some random hash for simulations + const hash = Math.random().toString(36).substring(7); + const transaction = { + tokenAddress: tokenAddress, + type: "sell", + transactionHash: hash, + amount: sellDetails.sell_amount, + price: processedData.tradeData.price, + isSimulation: true, + timestamp: new Date().toISOString(), + }; + this.trustScoreDb.addTransaction(transaction); + } + return sellDetailsData; } diff --git a/packages/plugin-trustdb/src/adapters/trustScoreDatabase.ts b/packages/plugin-trustdb/src/adapters/trustScoreDatabase.ts index 51b44b9eb25..5fd6e3d8bb7 100644 --- a/packages/plugin-trustdb/src/adapters/trustScoreDatabase.ts +++ b/packages/plugin-trustdb/src/adapters/trustScoreDatabase.ts @@ -40,6 +40,7 @@ export interface TokenPerformance { rapidDump: boolean; suspiciousVolume: boolean; validationTrust: number; + balance: number; lastUpdated: Date; } @@ -120,9 +121,20 @@ interface TokenPerformanceRow { rapid_dump: number; suspicious_volume: number; validation_trust: number; + balance: number; last_updated: string; } +interface Transaction { + tokenAddress: string; + transactionHash: string; + type: "buy" | "sell"; + amount: number; + price: number; + isSimulation: boolean; + timestamp: string; +} + export class TrustScoreDatabase { private db: Database; @@ -192,6 +204,7 @@ export class TrustScoreDatabase { rapid_dump BOOLEAN DEFAULT FALSE, suspicious_volume BOOLEAN DEFAULT FALSE, validation_trust REAL DEFAULT 0, + balance REAL DEFAULT 0, last_updated DATETIME DEFAULT CURRENT_TIMESTAMP ); `); @@ -289,6 +302,20 @@ export class TrustScoreDatabase { FOREIGN KEY (recommender_id) REFERENCES recommenders(id) ON DELETE CASCADE ); `); + + // create transactions table + this.db.exec(` + CREATE TABLE IF NOT EXISTS transactions ( + token_address TEXT NOT NULL, + transaction_hash TEXT PRIMARY KEY, + type TEXT NOT NULL, + amount REAL NOT NULL, + price REAL NOT NULL, + timestamp TEXT NOT NULL, + is_simulation BOOLEAN DEFAULT FALSE, + FOREIGN KEY (token_address) REFERENCES token_performance(token_address) ON DELETE CASCADE + ); + `); } /** @@ -749,6 +776,25 @@ export class TrustScoreDatabase { } } + // update token balance + + updateTokenBalance(tokenAddress: string, balance: number): boolean { + const sql = ` + UPDATE token_performance + SET balance = ?, + last_updated = CURRENT_TIMESTAMP + WHERE token_address = ?; + `; + try { + this.db.prepare(sql).run(balance, tokenAddress); + console.log(`Updated token balance for ${tokenAddress}`); + return true; + } catch (error) { + console.error("Error updating token balance:", error); + return false; + } + } + /** * Retrieves token performance metrics. * @param tokenAddress Token's address @@ -776,6 +822,7 @@ export class TrustScoreDatabase { rapidDump: row.rapid_dump === 1, suspiciousVolume: row.suspicious_volume === 1, validationTrust: row.validation_trust, + balance: row.balance, lastUpdated: new Date(row.last_updated), }; } @@ -1247,6 +1294,79 @@ export class TrustScoreDatabase { }; } + // ----- Transactions Methods ----- + /** + * Adds a new transaction to the database. + * @param transaction Transaction object + * @returns boolean indicating success + */ + + addTransaction(transaction: Transaction): boolean { + const sql = ` + INSERT INTO transactions ( + token_address, + transaction_hash, + type, + amount, + price, + is_simulation, + timestamp + ) VALUES (?, ?, ?, ?, ?, ?); + `; + try { + this.db + .prepare(sql) + .run( + transaction.tokenAddress, + transaction.transactionHash, + transaction.type, + transaction.amount, + transaction.price, + transaction.isSimulation, + transaction.timestamp + ); + return true; + } catch (error) { + console.error("Error adding transaction:", error); + return false; + } + } + + /** + * Retrieves all transactions for a specific token. + * @param tokenAddress Token's address + * @returns Array of Transaction objects + */ + getTransactionsByToken(tokenAddress: string): Transaction[] { + const sql = `SELECT * FROM transactions WHERE token_address = ? ORDER BY timestamp DESC;`; + const rows = this.db.prepare(sql).all(tokenAddress) as Array<{ + token_address: string; + transaction_hash: string; + type: string; + amount: number; + price: number; + is_simulation: boolean; + timestamp: string; + }>; + + return rows.map((row) => { + // Validate and cast 'type' to ensure it matches the expected union type + if (row.type !== "buy" && row.type !== "sell") { + throw new Error(`Unexpected transaction type: ${row.type}`); + } + + return { + tokenAddress: row.token_address, + transactionHash: row.transaction_hash, + type: row.type as "buy" | "sell", + amount: row.amount, + price: row.price, + isSimulation: row.is_simulation, + timestamp: new Date(row.timestamp).toISOString(), + }; + }); + } + /** * Close the database connection gracefully. */