From 73564bcd7e55bfd7e852df712a2a5704c808e62a Mon Sep 17 00:00:00 2001 From: MarcoMandar Date: Fri, 1 Nov 2024 23:19:37 +0200 Subject: [PATCH] fix types Signed-off-by: MarcoMandar --- core/src/providers/token.ts | 106 +++- core/src/providers/trustScoreProvider.ts | 627 ++++++++++++----------- 2 files changed, 401 insertions(+), 332 deletions(-) diff --git a/core/src/providers/token.ts b/core/src/providers/token.ts index 62739d8f..ac44d728 100644 --- a/core/src/providers/token.ts +++ b/core/src/providers/token.ts @@ -1,18 +1,19 @@ +import { Connection } from "@solana/web3.js"; // import fetch from "cross-fetch"; +import { IAgentRuntime, Memory, Provider, State } from "../core/types"; +import settings from "../core/settings"; import BigNumber from "bignumber.js"; -import * as fs from "fs"; -import NodeCache from "node-cache"; -import * as path from "path"; -import settings from "../core/settings.ts"; -import { IAgentRuntime, Memory, Provider, State } from "../core/types.ts"; import { - DexScreenerData, - HolderData, ProcessedTokenData, TokenSecurityData, TokenTradeData, -} from "../types/token.ts"; -import { fileURLToPath } from "url"; + DexScreenerData, + // DexScreenerPair, + HolderData, +} from "../types/token"; +import NodeCache from "node-cache"; +import * as fs from "fs"; +import * as path from "path"; const PROVIDER_CONFIG = { BIRDEYE_API: "https://public-api.birdeye.so", @@ -39,11 +40,7 @@ export class TokenProvider { private tokenAddress: string ) { this.cache = new NodeCache({ stdTTL: 300 }); // 5 minutes cache - const __filename = fileURLToPath(import.meta.url); - - const __dirname = path.dirname(__filename); - - this.cacheDir = path.join(__dirname, "../../tokencache"); + this.cacheDir = path.join(__dirname, "cache"); if (!fs.existsSync(this.cacheDir)) { fs.mkdirSync(this.cacheDir); } @@ -51,13 +48,20 @@ export class TokenProvider { private readCacheFromFile(cacheKey: string): T | null { const filePath = path.join(this.cacheDir, `${cacheKey}.json`); + console.log({ filePath }); if (fs.existsSync(filePath)) { const fileContent = fs.readFileSync(filePath, "utf-8"); const parsed = JSON.parse(fileContent); const now = Date.now(); if (now < parsed.expiry) { + console.log( + `Reading cached data from file for key: ${cacheKey}` + ); return parsed.data as T; } else { + console.log( + `Cache expired for key: ${cacheKey}. Deleting file.` + ); fs.unlinkSync(filePath); } } @@ -71,6 +75,7 @@ export class TokenProvider { expiry: Date.now() + 300000, // 5 minutes in milliseconds }; fs.writeFileSync(filePath, JSON.stringify(cacheData), "utf-8"); + console.log(`Cached data written to file for key: ${cacheKey}`); } private getCachedData(cacheKey: string): T | null { @@ -102,6 +107,7 @@ export class TokenProvider { private async fetchWithRetry( url: string, options: RequestInit = {} + // eslint-disable-next-line @typescript-eslint/no-explicit-any ): Promise { let lastError: Error; @@ -127,9 +133,11 @@ export class TokenProvider { const data = await response.json(); return data; } catch (error) { + console.error(`Attempt ${i + 1} failed:`, error); lastError = error as Error; if (i < PROVIDER_CONFIG.MAX_RETRIES - 1) { const delay = PROVIDER_CONFIG.RETRY_DELAY * Math.pow(2, i); + console.log(`Waiting ${delay}ms before retrying...`); await new Promise((resolve) => setTimeout(resolve, delay)); continue; } @@ -147,6 +155,9 @@ export class TokenProvider { const cacheKey = `tokenSecurity_${this.tokenAddress}`; const cachedData = this.getCachedData(cacheKey); if (cachedData) { + console.log( + `Returning cached token security data for ${this.tokenAddress}.` + ); return cachedData; } const url = `${PROVIDER_CONFIG.BIRDEYE_API}${PROVIDER_CONFIG.TOKEN_SECURITY_ENDPOINT}${this.tokenAddress}`; @@ -165,14 +176,18 @@ export class TokenProvider { top10HolderPercent: data.data.top10HolderPercent, }; this.setCachedData(cacheKey, security); + console.log(`Token security data cached for ${this.tokenAddress}.`); return security; } - async fetchTokenTradeData(runtime: IAgentRuntime): Promise { + async fetchTokenTradeData(): Promise { const cacheKey = `tokenTradeData_${this.tokenAddress}`; const cachedData = this.getCachedData(cacheKey); if (cachedData) { + console.log( + `Returning cached token trade data for ${this.tokenAddress}.` + ); return cachedData; } @@ -181,7 +196,7 @@ export class TokenProvider { method: "GET", headers: { accept: "application/json", - "X-API-KEY": runtime.getSetting("BIRDEYE_API_KEY") || "", + "X-API-KEY": settings.BIRDEYE_API_KEY || "", }, }; @@ -405,11 +420,15 @@ export class TokenProvider { const cacheKey = `dexScreenerData_${this.tokenAddress}`; const cachedData = this.getCachedData(cacheKey); if (cachedData) { + console.log("Returning cached DexScreener data."); return cachedData; } const url = `https://api.dexscreener.com/latest/dex/search?q=${this.tokenAddress}`; try { + console.log( + `Fetching DexScreener data for token: ${this.tokenAddress}` + ); const data = await fetch(url) .then((res) => res.json()) .catch((err) => { @@ -488,6 +507,7 @@ export class TokenProvider { const cacheKey = `holderList_${this.tokenAddress}`; const cachedData = this.getCachedData(cacheKey); if (cachedData) { + console.log("Returning cached holder list."); return cachedData; } @@ -497,8 +517,10 @@ export class TokenProvider { let cursor; //HELIOUS_API_KEY needs to be added const url = `https://mainnet.helius-rpc.com/?api-key=${settings.HELIOUS_API_KEY || ""}`; + console.log({ url }); try { + // eslint-disable-next-line no-constant-condition while (true) { const params = { limit: limit, @@ -509,7 +531,7 @@ export class TokenProvider { if (cursor != undefined) { params.cursor = cursor; } - + console.log(`Fetching holders - Page ${page}`); if (page > 2) { break; } @@ -534,9 +556,17 @@ export class TokenProvider { !data.result.token_accounts || data.result.token_accounts.length === 0 ) { + console.log( + `No more holders found. Total pages fetched: ${page - 1}` + ); break; } + console.log( + `Processing ${data.result.token_accounts.length} holders from page ${page}` + ); + + // eslint-disable-next-line @typescript-eslint/no-explicit-any data.result.token_accounts.forEach((account: any) => { const owner = account.owner; const balance = parseFloat(account.amount); @@ -561,6 +591,8 @@ export class TokenProvider { balance: balance.toString(), })); + console.log(`Total unique holders fetched: ${holders.length}`); + // Cache the result this.setCachedData(cacheKey, holders); @@ -620,27 +652,47 @@ export class TokenProvider { } } - async getProcessedTokenData( - runtime: IAgentRuntime - ): Promise { + async getProcessedTokenData(): Promise { try { + console.log( + `Fetching security data for token: ${this.tokenAddress}` + ); const security = await this.fetchTokenSecurity(); - const tradeData = await this.fetchTokenTradeData(runtime); + console.log(`Fetching trade data for token: ${this.tokenAddress}`); + const tradeData = await this.fetchTokenTradeData(); + console.log( + `Fetching DexScreener data for token: ${this.tokenAddress}` + ); const dexData = await this.fetchDexScreenerData(); + console.log( + `Analyzing holder distribution for token: ${this.tokenAddress}` + ); const holderDistributionTrend = await this.analyzeHolderDistribution(tradeData); + console.log( + `Filtering high-value holders for token: ${this.tokenAddress}` + ); const highValueHolders = await this.filterHighValueHolders(tradeData); + console.log( + `Checking recent trades for token: ${this.tokenAddress}` + ); const recentTrades = await this.checkRecentTrades(tradeData); + console.log( + `Counting high-supply holders for token: ${this.tokenAddress}` + ); const highSupplyHoldersCount = await this.countHighSupplyHolders(security); + console.log( + `Determining DexScreener listing status for token: ${this.tokenAddress}` + ); const isDexScreenerListed = dexData.pairs.length > 0; const isDexScreenerPaid = dexData.pairs.some( (pair) => pair.boosts && pair.boosts.active > 0 @@ -658,6 +710,7 @@ export class TokenProvider { isDexScreenerPaid, }; + // console.log("Processed token data:", processedData); return processedData; } catch (error) { console.error("Error processing token data:", error); @@ -725,12 +778,14 @@ export class TokenProvider { } output += `\n`; + console.log("Formatted token data:", output); return output; } - async getFormattedTokenReport(runtime: IAgentRuntime): Promise { + async getFormattedTokenReport(): Promise { try { - const processedData = await this.getProcessedTokenData(runtime); + console.log("Generating formatted token report..."); + const processedData = await this.getProcessedTokenData(); return this.formatTokenData(processedData); } catch (error) { console.error("Error generating token report:", error); @@ -740,15 +795,18 @@ export class TokenProvider { } const tokenAddress = PROVIDER_CONFIG.TOKEN_ADDRESSES.Example; +// eslint-disable-next-line @typescript-eslint/no-unused-vars +const connection = new Connection(PROVIDER_CONFIG.DEFAULT_RPC); const tokenProvider: Provider = { get: async ( + // eslint-disable-next-line @typescript-eslint/no-unused-vars runtime: IAgentRuntime, _message: Memory, _state?: State ): Promise => { try { const provider = new TokenProvider(tokenAddress); - return provider.getFormattedTokenReport(runtime); + return provider.getFormattedTokenReport(); } catch (error) { console.error("Error fetching token data:", error); return "Unable to fetch token information. Please try again later."; diff --git a/core/src/providers/trustScoreProvider.ts b/core/src/providers/trustScoreProvider.ts index 7c60b1ac..db20dc52 100644 --- a/core/src/providers/trustScoreProvider.ts +++ b/core/src/providers/trustScoreProvider.ts @@ -1,355 +1,366 @@ import { - ProcessedTokenData, - TokenSecurityData, - TokenTradeData, - DexScreenerData, - DexScreenerPair, - HolderData, + ProcessedTokenData, + TokenSecurityData, + // TokenTradeData, + // DexScreenerData, + // DexScreenerPair, + // HolderData, } from "../types/token"; import { Connection, PublicKey } from "@solana/web3.js"; import { TokenProvider } from "./token"; import WalletProvider from "./balances"; import { - TrustScoreDatabase, - RecommenderMetrics, - TokenPerformance, - TradePerformance, + TrustScoreDatabase, + RecommenderMetrics, + TokenPerformance, + TradePerformance, } from "../adapters/trustScoreDatabase"; import settings from "../core/settings"; const Wallet = settings.MAIN_WALLET_ADDRESS; interface TradeData { - buy_amount: number; - is_simulation: boolean; + buy_amount: number; + is_simulation: boolean; } interface sellDetails { - sell_amount: number; - sell_recommender_id: string | null; + sell_amount: number; + sell_recommender_id: string | null; } export class TrustScoreProvider { - private tokenProvider: TokenProvider; - private trustScoreDb: TrustScoreDatabase; + private tokenProvider: TokenProvider; + private trustScoreDb: TrustScoreDatabase; - constructor(tokenProvider: TokenProvider, trustScoreDb: TrustScoreDatabase) { - this.tokenProvider = tokenProvider; - this.trustScoreDb = trustScoreDb; - } - /** - * Generates and saves trust score based on processed token data and user recommendations. - * @param tokenAddress The address of the token to analyze. - * @param recommenderId The UUID of the recommender. - * @returns An object containing TokenPerformance and RecommenderMetrics. - */ - async generateTrustScore( - tokenAddress: string, - recommenderId: string - ): Promise<{ - tokenPerformance: TokenPerformance; - recommenderMetrics: RecommenderMetrics; - }> { - const processedData: ProcessedTokenData = - await this.tokenProvider.getProcessedTokenData(); - console.log(`Fetched processed token data for token: ${tokenAddress}`); - - const recommenderMetrics = - await this.trustScoreDb.getRecommenderMetrics(recommenderId); + constructor( + tokenProvider: TokenProvider, + trustScoreDb: TrustScoreDatabase + ) { + this.tokenProvider = tokenProvider; + this.trustScoreDb = trustScoreDb; + } + /** + * Generates and saves trust score based on processed token data and user recommendations. + * @param tokenAddress The address of the token to analyze. + * @param recommenderId The UUID of the recommender. + * @returns An object containing TokenPerformance and RecommenderMetrics. + */ + async generateTrustScore( + tokenAddress: string, + recommenderId: string + ): Promise<{ + tokenPerformance: TokenPerformance; + recommenderMetrics: RecommenderMetrics; + }> { + const processedData: ProcessedTokenData = + await this.tokenProvider.getProcessedTokenData(); + console.log(`Fetched processed token data for token: ${tokenAddress}`); - const isRapidDump = await this.isRapidDump(tokenAddress); - const sustainedGrowth = await this.sustainedGrowth(tokenAddress); - const suspiciousVolume = await this.suspiciousVolume(tokenAddress); + const recommenderMetrics = + await this.trustScoreDb.getRecommenderMetrics(recommenderId); - return { - tokenPerformance: { - tokenAddress: - processedData.dexScreenerData.pairs[0]?.baseToken.address || "", - priceChange24h: processedData.tradeData.price_change_24h_percent, - volumeChange24h: processedData.tradeData.volume_24h, - trade_24h_change: processedData.tradeData.trade_24h_change_percent, - liquidity: processedData.dexScreenerData.pairs[0]?.liquidity.usd || 0, - liquidityChange24h: 0, - holderChange24h: - processedData.tradeData.unique_wallet_24h_change_percent, - rugPull: false, // TODO: Implement rug pull detection - isScam: false, // TODO: Implement scam detection - marketCapChange24h: 0, // TODO: Implement market cap change - sustainedGrowth: sustainedGrowth, - rapidDump: isRapidDump, - suspiciousVolume: suspiciousVolume, - lastUpdated: new Date(), - }, - recommenderMetrics: { - recommenderId: recommenderId, - trustScore: recommenderMetrics.trustScore, - totalRecommendations: recommenderMetrics.totalRecommendations, - successfulRecs: recommenderMetrics.successfulRecs, - avgTokenPerformance: recommenderMetrics.avgTokenPerformance, - riskScore: recommenderMetrics.riskScore, - consistencyScore: recommenderMetrics.consistencyScore, - virtualConfidence: recommenderMetrics.virtualConfidence, - lastUpdated: new Date(), - }, - }; - } + const isRapidDump = await this.isRapidDump(tokenAddress); + const sustainedGrowth = await this.sustainedGrowth(tokenAddress); + const suspiciousVolume = await this.suspiciousVolume(tokenAddress); - async updateRecommenderMetrics( - recommenderId: string, - tokenPerformance: TokenPerformance - ): Promise { - const recommenderMetrics = - await this.trustScoreDb.getRecommenderMetrics(recommenderId); + return { + tokenPerformance: { + tokenAddress: + processedData.dexScreenerData.pairs[0]?.baseToken.address || + "", + priceChange24h: + processedData.tradeData.price_change_24h_percent, + volumeChange24h: processedData.tradeData.volume_24h, + trade_24h_change: + processedData.tradeData.trade_24h_change_percent, + liquidity: + processedData.dexScreenerData.pairs[0]?.liquidity.usd || 0, + liquidityChange24h: 0, + holderChange24h: + processedData.tradeData.unique_wallet_24h_change_percent, + rugPull: false, // TODO: Implement rug pull detection + isScam: false, // TODO: Implement scam detection + marketCapChange24h: 0, // TODO: Implement market cap change + sustainedGrowth: sustainedGrowth, + rapidDump: isRapidDump, + suspiciousVolume: suspiciousVolume, + lastUpdated: new Date(), + }, + recommenderMetrics: { + recommenderId: recommenderId, + trustScore: recommenderMetrics.trustScore, + totalRecommendations: recommenderMetrics.totalRecommendations, + successfulRecs: recommenderMetrics.successfulRecs, + avgTokenPerformance: recommenderMetrics.avgTokenPerformance, + riskScore: recommenderMetrics.riskScore, + consistencyScore: recommenderMetrics.consistencyScore, + virtualConfidence: recommenderMetrics.virtualConfidence, + lastUpdated: new Date(), + }, + }; + } - const totalRecommendations = recommenderMetrics.totalRecommendations + 1; - const successfulRecs = tokenPerformance.rugPull - ? recommenderMetrics.successfulRecs - : recommenderMetrics.successfulRecs + 1; - const avgTokenPerformance = - (recommenderMetrics.avgTokenPerformance * - recommenderMetrics.totalRecommendations + - tokenPerformance.priceChange24h) / - totalRecommendations; + async updateRecommenderMetrics( + recommenderId: string, + tokenPerformance: TokenPerformance + ): Promise { + const recommenderMetrics = + await this.trustScoreDb.getRecommenderMetrics(recommenderId); - const overallTrustScore = this.calculateTrustScore( - tokenPerformance, - recommenderMetrics - ); - const riskScore = this.calculateOverallRiskScore( - tokenPerformance, - recommenderMetrics - ); - const consistencyScore = this.calculateConsistencyScore( - tokenPerformance, - recommenderMetrics - ); - const newRecommenderMetrics: RecommenderMetrics = { - recommenderId: recommenderId, - trustScore: overallTrustScore, - totalRecommendations: totalRecommendations, - successfulRecs: successfulRecs, - avgTokenPerformance: avgTokenPerformance, - riskScore: riskScore, - consistencyScore: consistencyScore, - virtualConfidence: recommenderMetrics.virtualConfidence, - lastUpdated: new Date(), - }; + const totalRecommendations = + recommenderMetrics.totalRecommendations + 1; + const successfulRecs = tokenPerformance.rugPull + ? recommenderMetrics.successfulRecs + : recommenderMetrics.successfulRecs + 1; + const avgTokenPerformance = + (recommenderMetrics.avgTokenPerformance * + recommenderMetrics.totalRecommendations + + tokenPerformance.priceChange24h) / + totalRecommendations; - await this.trustScoreDb.updateRecommenderMetrics(newRecommenderMetrics); - } + const overallTrustScore = this.calculateTrustScore( + tokenPerformance, + recommenderMetrics + ); + const riskScore = this.calculateOverallRiskScore( + tokenPerformance, + recommenderMetrics + ); + const consistencyScore = this.calculateConsistencyScore( + tokenPerformance, + recommenderMetrics + ); + const newRecommenderMetrics: RecommenderMetrics = { + recommenderId: recommenderId, + trustScore: overallTrustScore, + totalRecommendations: totalRecommendations, + successfulRecs: successfulRecs, + avgTokenPerformance: avgTokenPerformance, + riskScore: riskScore, + consistencyScore: consistencyScore, + virtualConfidence: recommenderMetrics.virtualConfidence, + lastUpdated: new Date(), + }; - calculateTrustScore( - tokenPerformance: TokenPerformance, - recommenderMetrics: RecommenderMetrics - ): number { - const riskScore = this.calculateRiskScore(tokenPerformance); - const consistencyScore = this.calculateConsistencyScore( - tokenPerformance, - recommenderMetrics - ); + await this.trustScoreDb.updateRecommenderMetrics(newRecommenderMetrics); + } - return (riskScore + consistencyScore) / 2; - } + calculateTrustScore( + tokenPerformance: TokenPerformance, + recommenderMetrics: RecommenderMetrics + ): number { + const riskScore = this.calculateRiskScore(tokenPerformance); + const consistencyScore = this.calculateConsistencyScore( + tokenPerformance, + recommenderMetrics + ); - calculateOverallRiskScore( - tokenPerformance: TokenPerformance, - recommenderMetrics: RecommenderMetrics - ) { - const riskScore = this.calculateRiskScore(tokenPerformance); - const consistencyScore = this.calculateConsistencyScore( - tokenPerformance, - recommenderMetrics - ); + return (riskScore + consistencyScore) / 2; + } - return (riskScore + consistencyScore) / 2; - } + calculateOverallRiskScore( + tokenPerformance: TokenPerformance, + recommenderMetrics: RecommenderMetrics + ) { + const riskScore = this.calculateRiskScore(tokenPerformance); + const consistencyScore = this.calculateConsistencyScore( + tokenPerformance, + recommenderMetrics + ); - calculateRiskScore(tokenPerformance: TokenPerformance): number { - let riskScore = 0; - if (tokenPerformance.rugPull) { - riskScore += 10; - } - if (tokenPerformance.isScam) { - riskScore += 10; + return (riskScore + consistencyScore) / 2; } - if (tokenPerformance.rapidDump) { - riskScore += 5; - } - if (tokenPerformance.suspiciousVolume) { - riskScore += 5; + + calculateRiskScore(tokenPerformance: TokenPerformance): number { + let riskScore = 0; + if (tokenPerformance.rugPull) { + riskScore += 10; + } + if (tokenPerformance.isScam) { + riskScore += 10; + } + if (tokenPerformance.rapidDump) { + riskScore += 5; + } + if (tokenPerformance.suspiciousVolume) { + riskScore += 5; + } + return riskScore; } - return riskScore; - } - calculateConsistencyScore( - tokenPerformance: TokenPerformance, - recommenderMetrics: RecommenderMetrics - ): number { - const avgTokenPerformance = recommenderMetrics.avgTokenPerformance; - const priceChange24h = tokenPerformance.priceChange24h; + calculateConsistencyScore( + tokenPerformance: TokenPerformance, + recommenderMetrics: RecommenderMetrics + ): number { + const avgTokenPerformance = recommenderMetrics.avgTokenPerformance; + const priceChange24h = tokenPerformance.priceChange24h; - return Math.abs(priceChange24h - avgTokenPerformance); - } + return Math.abs(priceChange24h - avgTokenPerformance); + } - async suspiciousVolume(tokenAddress: string): Promise { - const processedData: ProcessedTokenData = - await this.tokenProvider.getProcessedTokenData(); - const unique_wallet_24h = processedData.tradeData.unique_wallet_24h; - const volume_24h = processedData.tradeData.volume_24h; - const suspiciousVolume = unique_wallet_24h / volume_24h > 0.5; - console.log(`Fetched processed token data for token: ${tokenAddress}`); - return suspiciousVolume; - } + async suspiciousVolume(tokenAddress: string): Promise { + const processedData: ProcessedTokenData = + await this.tokenProvider.getProcessedTokenData(); + const unique_wallet_24h = processedData.tradeData.unique_wallet_24h; + const volume_24h = processedData.tradeData.volume_24h; + const suspiciousVolume = unique_wallet_24h / volume_24h > 0.5; + console.log(`Fetched processed token data for token: ${tokenAddress}`); + return suspiciousVolume; + } - async sustainedGrowth(tokenAddress: string): Promise { - const processedData: ProcessedTokenData = - await this.tokenProvider.getProcessedTokenData(); - console.log(`Fetched processed token data for token: ${tokenAddress}`); + async sustainedGrowth(tokenAddress: string): Promise { + const processedData: ProcessedTokenData = + await this.tokenProvider.getProcessedTokenData(); + console.log(`Fetched processed token data for token: ${tokenAddress}`); - return processedData.tradeData.volume_24h_change_percent > 50; - } + return processedData.tradeData.volume_24h_change_percent > 50; + } - async isRapidDump(tokenAddress: string): Promise { - const processedData: ProcessedTokenData = - await this.tokenProvider.getProcessedTokenData(); - console.log(`Fetched processed token data for token: ${tokenAddress}`); + async isRapidDump(tokenAddress: string): Promise { + const processedData: ProcessedTokenData = + await this.tokenProvider.getProcessedTokenData(); + console.log(`Fetched processed token data for token: ${tokenAddress}`); - return processedData.tradeData.trade_24h_change_percent < -50; - } + return processedData.tradeData.trade_24h_change_percent < -50; + } - async checkTrustScore(tokenAddress: string): Promise { - const processedData: ProcessedTokenData = - await this.tokenProvider.getProcessedTokenData(); - console.log(`Fetched processed token data for token: ${tokenAddress}`); + async checkTrustScore(tokenAddress: string): Promise { + const processedData: ProcessedTokenData = + await this.tokenProvider.getProcessedTokenData(); + console.log(`Fetched processed token data for token: ${tokenAddress}`); - return { - ownerBalance: processedData.security.ownerBalance, - creatorBalance: processedData.security.creatorBalance, - ownerPercentage: processedData.security.ownerPercentage, - creatorPercentage: processedData.security.creatorPercentage, - top10HolderBalance: processedData.security.top10HolderBalance, - top10HolderPercent: processedData.security.top10HolderPercent, - }; - } + return { + ownerBalance: processedData.security.ownerBalance, + creatorBalance: processedData.security.creatorBalance, + ownerPercentage: processedData.security.ownerPercentage, + creatorPercentage: processedData.security.creatorPercentage, + top10HolderBalance: processedData.security.top10HolderBalance, + top10HolderPercent: processedData.security.top10HolderPercent, + }; + } - /** - * Creates a TradePerformance object based on token data and recommender. - * @param tokenAddress The address of the token. - * @param recommenderId The UUID of the recommender. - * @param data ProcessedTokenData. - * @returns TradePerformance object. - */ - async createTradePerformance( - tokenAddress: string, - recommenderId: string, - data: TradeData - ): Promise { - const processedData: ProcessedTokenData = - await this.tokenProvider.getProcessedTokenData(); - const wallet = new WalletProvider( - new Connection("https://api.mainnet-beta.solana.com"), - new PublicKey(Wallet!) - ); - const prices = await wallet.fetchPrices(); - const solPrice = prices.solana.usd; - const buySol = data.buy_amount / parseFloat(solPrice); - const buy_value_usd = data.buy_amount * processedData.tradeData.price; + /** + * Creates a TradePerformance object based on token data and recommender. + * @param tokenAddress The address of the token. + * @param recommenderId The UUID of the recommender. + * @param data ProcessedTokenData. + * @returns TradePerformance object. + */ + async createTradePerformance( + tokenAddress: string, + recommenderId: string, + data: TradeData + ): Promise { + const processedData: ProcessedTokenData = + await this.tokenProvider.getProcessedTokenData(); + const wallet = new WalletProvider( + new Connection("https://api.mainnet-beta.solana.com"), + new PublicKey(Wallet!) + ); + const prices = await wallet.fetchPrices(); + const solPrice = prices.solana.usd; + const buySol = data.buy_amount / parseFloat(solPrice); + const buy_value_usd = data.buy_amount * processedData.tradeData.price; - const creationData = { - token_address: tokenAddress, - recommender_id: recommenderId, - buy_price: processedData.tradeData.price, - sell_price: 0, - buy_timeStamp: new Date().toISOString(), - sell_timeStamp: "", - buy_amount: data.buy_amount, - sell_amount: 0, - buy_sol: buySol, - received_sol: 0, - buy_value_usd: buy_value_usd, - sell_value_usd: 0, - profit_usd: 0, - profit_percent: 0, - buy_market_cap: processedData.dexScreenerData.pairs[0]?.marketCap || 0, - sell_market_cap: 0, - market_cap_change: 0, - buy_liquidity: processedData.dexScreenerData.pairs[0]?.liquidity.usd || 0, - sell_liquidity: 0, - liquidity_change: 0, - last_updated: new Date().toISOString(), - rapidDump: false, - }; - this.trustScoreDb.addTradePerformance(creationData, data.is_simulation); - return creationData; - } + const creationData = { + token_address: tokenAddress, + recommender_id: recommenderId, + buy_price: processedData.tradeData.price, + sell_price: 0, + buy_timeStamp: new Date().toISOString(), + sell_timeStamp: "", + buy_amount: data.buy_amount, + sell_amount: 0, + buy_sol: buySol, + received_sol: 0, + buy_value_usd: buy_value_usd, + sell_value_usd: 0, + profit_usd: 0, + profit_percent: 0, + buy_market_cap: + processedData.dexScreenerData.pairs[0]?.marketCap || 0, + sell_market_cap: 0, + market_cap_change: 0, + buy_liquidity: + processedData.dexScreenerData.pairs[0]?.liquidity.usd || 0, + sell_liquidity: 0, + liquidity_change: 0, + last_updated: new Date().toISOString(), + rapidDump: false, + }; + this.trustScoreDb.addTradePerformance(creationData, data.is_simulation); + return creationData; + } - /** - * Updates a trade with sell details. - * @param tokenAddress The address of the token. - * @param recommenderId The UUID of the recommender. - * @param buyTimeStamp The timestamp when the buy occurred. - * @param sellDetails An object containing sell-related details. - * @param isSimulation Whether the trade is a simulation. If true, updates in simulation_trade; otherwise, in trade. - * @returns boolean indicating success. - */ + /** + * Updates a trade with sell details. + * @param tokenAddress The address of the token. + * @param recommenderId The UUID of the recommender. + * @param buyTimeStamp The timestamp when the buy occurred. + * @param sellDetails An object containing sell-related details. + * @param isSimulation Whether the trade is a simulation. If true, updates in simulation_trade; otherwise, in trade. + * @returns boolean indicating success. + */ - async updateSellDetails( - tokenAddress: string, - recommenderId: string, - sellTimeStamp: string, - sellDetails: sellDetails, - isSimulation: boolean, - buyTimeStamp: string - ) { - const processedData: ProcessedTokenData = - await this.tokenProvider.getProcessedTokenData(); - const wallet = new WalletProvider( - new Connection("https://api.mainnet-beta.solana.com"), - new PublicKey(Wallet!) - ); - const prices = await wallet.fetchPrices(); - const solPrice = prices.solana.usd; - const sellSol = sellDetails.sell_amount / parseFloat(solPrice); - const sell_value_usd = - sellDetails.sell_amount * processedData.tradeData.price; - const trade = await this.trustScoreDb.getTradePerformance( - tokenAddress, - recommenderId, - buyTimeStamp, - isSimulation - ); - const marketCap = processedData.dexScreenerData.pairs[0]?.marketCap || 0; - const liquidity = - processedData.dexScreenerData.pairs[0]?.liquidity.usd || 0; - const sell_price = processedData.tradeData.price; - const profit_usd = sell_value_usd - trade.buy_value_usd; - const profit_percent = (profit_usd / trade.buy_value_usd) * 100; + async updateSellDetails( + tokenAddress: string, + recommenderId: string, + sellTimeStamp: string, + sellDetails: sellDetails, + isSimulation: boolean, + buyTimeStamp: string + ) { + const processedData: ProcessedTokenData = + await this.tokenProvider.getProcessedTokenData(); + const wallet = new WalletProvider( + new Connection("https://api.mainnet-beta.solana.com"), + new PublicKey(Wallet!) + ); + const prices = await wallet.fetchPrices(); + const solPrice = prices.solana.usd; + const sellSol = sellDetails.sell_amount / parseFloat(solPrice); + const sell_value_usd = + sellDetails.sell_amount * processedData.tradeData.price; + const trade = await this.trustScoreDb.getTradePerformance( + tokenAddress, + recommenderId, + buyTimeStamp, + isSimulation + ); + const marketCap = + processedData.dexScreenerData.pairs[0]?.marketCap || 0; + const liquidity = + processedData.dexScreenerData.pairs[0]?.liquidity.usd || 0; + const sell_price = processedData.tradeData.price; + const profit_usd = sell_value_usd - trade.buy_value_usd; + const profit_percent = (profit_usd / trade.buy_value_usd) * 100; - const market_cap_change = marketCap - trade.buy_market_cap; - const liquidity_change = liquidity - trade.buy_liquidity; + const market_cap_change = marketCap - trade.buy_market_cap; + const liquidity_change = liquidity - trade.buy_liquidity; - const isRapidDump = await this.isRapidDump(tokenAddress); + const isRapidDump = await this.isRapidDump(tokenAddress); - const sellDetailsData = { - sell_price: sell_price, - sell_timeStamp: sellTimeStamp, - sell_amount: sellDetails.sell_amount, - received_sol: sellSol, - sell_value_usd: sell_value_usd, - profit_usd: profit_usd, - profit_percent: profit_percent, - sell_market_cap: marketCap, - market_cap_change: market_cap_change, - sell_liquidity: liquidity, - liquidity_change: liquidity_change, - rapidDump: isRapidDump, - sell_recommender_id: sellDetails.sell_recommender_id || null, - }; - this.trustScoreDb.updateTradePerformanceOnSell( - tokenAddress, - recommenderId, - buyTimeStamp, - sellDetailsData, - isSimulation - ); - return sellDetailsData; - } + const sellDetailsData = { + sell_price: sell_price, + sell_timeStamp: sellTimeStamp, + sell_amount: sellDetails.sell_amount, + received_sol: sellSol, + sell_value_usd: sell_value_usd, + profit_usd: profit_usd, + profit_percent: profit_percent, + sell_market_cap: marketCap, + market_cap_change: market_cap_change, + sell_liquidity: liquidity, + liquidity_change: liquidity_change, + rapidDump: isRapidDump, + sell_recommender_id: sellDetails.sell_recommender_id || null, + }; + this.trustScoreDb.updateTradePerformanceOnSell( + tokenAddress, + recommenderId, + buyTimeStamp, + sellDetailsData, + isSimulation + ); + return sellDetailsData; + } }