Skip to content

Commit 8084bc8

Browse files
authored
Merge pull request #175 from MarcoMandar/main
updates to order book and trust score, virtual confidence, last active, decay score, validation trust, multiple recommenders
2 parents bc4c482 + 1989eae commit 8084bc8

File tree

2 files changed

+110
-7
lines changed

2 files changed

+110
-7
lines changed

core/src/adapters/trustScoreDatabase.ts

+47-1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ export interface RecommenderMetrics {
2424
riskScore: number;
2525
consistencyScore: number;
2626
virtualConfidence: number;
27+
lastActiveDate: Date;
28+
trustDecay: number;
2729
lastUpdated: Date;
2830
}
2931

@@ -41,6 +43,7 @@ export interface TokenPerformance {
4143
sustainedGrowth: boolean;
4244
rapidDump: boolean;
4345
suspiciousVolume: boolean;
46+
validationTrust: number;
4447
lastUpdated: Date;
4548
}
4649

@@ -63,6 +66,7 @@ export interface RecommenderMetricsHistory {
6366
riskScore: number;
6467
consistencyScore: number;
6568
virtualConfidence: number;
69+
trustDecay: number;
6670
recordedAt: Date;
6771
}
6872

@@ -100,6 +104,8 @@ interface RecommenderMetricsRow {
100104
risk_score: number;
101105
consistency_score: number;
102106
virtual_confidence: number;
107+
last_active_date: Date;
108+
trust_decay: number;
103109
last_updated: string;
104110
}
105111

@@ -117,6 +123,7 @@ interface TokenPerformanceRow {
117123
sustained_growth: number;
118124
rapid_dump: number;
119125
suspicious_volume: number;
126+
validation_trust: number;
120127
last_updated: string;
121128
}
122129

@@ -165,6 +172,8 @@ export class TrustScoreDatabase {
165172
risk_score REAL DEFAULT 0,
166173
consistency_score REAL DEFAULT 0,
167174
virtual_confidence REAL DEFAULT 0,
175+
last_active_date DATETIME DEFAULT CURRENT_TIMESTAMP
176+
trust_decay REAL DEFAULT 0,
168177
last_updated DATETIME DEFAULT CURRENT_TIMESTAMP,
169178
FOREIGN KEY (recommender_id) REFERENCES recommenders(id) ON DELETE CASCADE
170179
);
@@ -186,6 +195,7 @@ export class TrustScoreDatabase {
186195
sustained_growth BOOLEAN DEFAULT FALSE,
187196
rapid_dump BOOLEAN DEFAULT FALSE,
188197
suspicious_volume BOOLEAN DEFAULT FALSE,
198+
validation_trust REAL DEFAULT 0,
189199
last_updated DATETIME DEFAULT CURRENT_TIMESTAMP
190200
);
191201
`);
@@ -378,6 +388,8 @@ export class TrustScoreDatabase {
378388
riskScore: row.risk_score,
379389
consistencyScore: row.consistency_score,
380390
virtualConfidence: row.virtual_confidence,
391+
lastActiveDate: row.last_active_date,
392+
trustDecay: row.trust_decay,
381393
lastUpdated: new Date(row.last_updated),
382394
};
383395
}
@@ -407,6 +419,7 @@ export class TrustScoreDatabase {
407419
riskScore: currentMetrics.riskScore,
408420
consistencyScore: currentMetrics.consistencyScore,
409421
virtualConfidence: currentMetrics.virtualConfidence,
422+
trustDecay: currentMetrics.trustDecay,
410423
recordedAt: new Date(), // Current timestamp
411424
};
412425

@@ -492,6 +505,10 @@ export class TrustScoreDatabase {
492505
* @param performance TokenPerformance object
493506
*/
494507
upsertTokenPerformance(performance: TokenPerformance): boolean {
508+
const validationTrust = this.calculateValidationTrust(
509+
performance.tokenAddress
510+
);
511+
495512
const sql = `
496513
INSERT INTO token_performance (
497514
token_address,
@@ -507,6 +524,7 @@ export class TrustScoreDatabase {
507524
sustained_growth,
508525
rapid_dump,
509526
suspicious_volume,
527+
validation_trust,
510528
last_updated
511529
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP)
512530
ON CONFLICT(token_address) DO UPDATE SET
@@ -522,6 +540,7 @@ export class TrustScoreDatabase {
522540
sustained_growth = excluded.sustained_growth,
523541
rapid_dump = excluded.rapid_dump,
524542
suspicious_volume = excluded.suspicious_volume,
543+
validation_trust = excluded.validation_trust,
525544
last_updated = CURRENT_TIMESTAMP;
526545
`;
527546
try {
@@ -536,7 +555,8 @@ export class TrustScoreDatabase {
536555
performance.marketCapChange24h,
537556
performance.sustainedGrowth ? 1 : 0,
538557
performance.rapidDump ? 1 : 0,
539-
performance.suspiciousVolume ? 1 : 0
558+
performance.suspiciousVolume ? 1 : 0,
559+
validationTrust
540560
);
541561
console.log(
542562
`Upserted token performance for ${performance.tokenAddress}`
@@ -574,12 +594,36 @@ export class TrustScoreDatabase {
574594
sustainedGrowth: row.sustained_growth === 1,
575595
rapidDump: row.rapid_dump === 1,
576596
suspiciousVolume: row.suspicious_volume === 1,
597+
validationTrust: row.validation_trust,
577598
lastUpdated: new Date(row.last_updated),
578599
};
579600
}
580601

581602
// ----- TokenRecommendations Methods -----
582603

604+
/**
605+
* Calculates the average trust score of all recommenders who have recommended a specific token.
606+
* @param tokenAddress The address of the token.
607+
* @returns The average trust score (validationTrust).
608+
*/
609+
calculateValidationTrust(tokenAddress: string): number {
610+
const sql = `
611+
SELECT rm.trust_score
612+
FROM token_recommendations tr
613+
JOIN recommender_metrics rm ON tr.recommender_id = rm.recommender_id
614+
WHERE tr.token_address = ?;
615+
`;
616+
const rows = this.db.prepare(sql).all(tokenAddress) as Array<{
617+
trust_score: number;
618+
}>;
619+
620+
if (rows.length === 0) return 0; // No recommendations found
621+
622+
const totalTrust = rows.reduce((acc, row) => acc + row.trust_score, 0);
623+
const averageTrust = totalTrust / rows.length;
624+
return averageTrust;
625+
}
626+
583627
/**
584628
* Adds a new token recommendation.
585629
* @param recommendation TokenRecommendation object
@@ -735,6 +779,7 @@ export class TrustScoreDatabase {
735779
risk_score: number;
736780
consistency_score: number;
737781
virtual_confidence: number;
782+
trust_decay: number;
738783
recorded_at: string;
739784
}>;
740785

@@ -748,6 +793,7 @@ export class TrustScoreDatabase {
748793
riskScore: row.risk_score,
749794
consistencyScore: row.consistency_score,
750795
virtualConfidence: row.virtual_confidence,
796+
trustDecay: row.trust_decay,
751797
recordedAt: new Date(row.recorded_at),
752798
}));
753799
}

core/src/providers/trustScoreProvider.ts

+63-6
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
// HolderData,
88
} from "../types/token";
99
import { Connection, PublicKey } from "@solana/web3.js";
10-
10+
import { getAssociatedTokenAddress } from "@solana/spl-token";
1111
import { TokenProvider } from "./token";
1212
import WalletProvider from "./balances";
1313
import {
@@ -30,14 +30,36 @@ interface sellDetails {
3030
export class TrustScoreProvider {
3131
private tokenProvider: TokenProvider;
3232
private trustScoreDb: TrustScoreDatabase;
33-
33+
private connection: Connection = new Connection(process.env.RPC_URL!);
34+
private baseMint: PublicKey = new PublicKey(process.env.BASE_MINT!);
35+
private DECAY_RATE = 0.95;
36+
private MAX_DECAY_DAYS = 30;
3437
constructor(
3538
tokenProvider: TokenProvider,
3639
trustScoreDb: TrustScoreDatabase
3740
) {
3841
this.tokenProvider = tokenProvider;
3942
this.trustScoreDb = trustScoreDb;
4043
}
44+
45+
//getRecommenederBalance
46+
async getRecommenederBalance(recommenderWallet: string): Promise<number> {
47+
try {
48+
const tokenAta = await getAssociatedTokenAddress(
49+
new PublicKey(recommenderWallet),
50+
this.baseMint
51+
);
52+
const tokenBalInfo =
53+
await this.connection.getTokenAccountBalance(tokenAta);
54+
const tokenBalance = tokenBalInfo.value.amount;
55+
const balance = parseFloat(tokenBalance);
56+
return balance;
57+
} catch (error) {
58+
console.error("Error fetching balance", error);
59+
return 0;
60+
}
61+
}
62+
4163
/**
4264
* Generates and saves trust score based on processed token data and user recommendations.
4365
* @param tokenAddress The address of the token to analyze.
@@ -46,7 +68,8 @@ export class TrustScoreProvider {
4668
*/
4769
async generateTrustScore(
4870
tokenAddress: string,
49-
recommenderId: string
71+
recommenderId: string,
72+
recommenderWallet: string
5073
): Promise<{
5174
tokenPerformance: TokenPerformance;
5275
recommenderMetrics: RecommenderMetrics;
@@ -61,6 +84,20 @@ export class TrustScoreProvider {
6184
const isRapidDump = await this.isRapidDump(tokenAddress);
6285
const sustainedGrowth = await this.sustainedGrowth(tokenAddress);
6386
const suspiciousVolume = await this.suspiciousVolume(tokenAddress);
87+
const balance = await this.getRecommenederBalance(recommenderWallet);
88+
const virtualConfidence = balance / 1000000; // TODO: create formula to calculate virtual confidence based on user balance
89+
const lastActive = recommenderMetrics.lastActiveDate;
90+
const now = new Date();
91+
const inactiveDays = Math.floor(
92+
(now.getTime() - lastActive.getTime()) / (1000 * 60 * 60 * 24)
93+
);
94+
const decayFactor = Math.pow(
95+
this.DECAY_RATE,
96+
Math.min(inactiveDays, this.MAX_DECAY_DAYS)
97+
);
98+
const decayedScore = recommenderMetrics.trustScore * decayFactor;
99+
const validationTrustScore =
100+
this.trustScoreDb.calculateValidationTrust(tokenAddress);
64101

65102
return {
66103
tokenPerformance: {
@@ -83,6 +120,7 @@ export class TrustScoreProvider {
83120
sustainedGrowth: sustainedGrowth,
84121
rapidDump: isRapidDump,
85122
suspiciousVolume: suspiciousVolume,
123+
validationTrust: validationTrustScore,
86124
lastUpdated: new Date(),
87125
},
88126
recommenderMetrics: {
@@ -93,15 +131,18 @@ export class TrustScoreProvider {
93131
avgTokenPerformance: recommenderMetrics.avgTokenPerformance,
94132
riskScore: recommenderMetrics.riskScore,
95133
consistencyScore: recommenderMetrics.consistencyScore,
96-
virtualConfidence: recommenderMetrics.virtualConfidence,
134+
virtualConfidence: virtualConfidence,
135+
lastActiveDate: now,
136+
trustDecay: decayedScore,
97137
lastUpdated: new Date(),
98138
},
99139
};
100140
}
101141

102142
async updateRecommenderMetrics(
103143
recommenderId: string,
104-
tokenPerformance: TokenPerformance
144+
tokenPerformance: TokenPerformance,
145+
recommenderWallet: string
105146
): Promise<void> {
106147
const recommenderMetrics =
107148
await this.trustScoreDb.getRecommenderMetrics(recommenderId);
@@ -129,6 +170,20 @@ export class TrustScoreProvider {
129170
tokenPerformance,
130171
recommenderMetrics
131172
);
173+
174+
const balance = await this.getRecommenederBalance(recommenderWallet);
175+
const virtualConfidence = balance / 1000000; // TODO: create formula to calculate virtual confidence based on user balance
176+
const lastActive = recommenderMetrics.lastActiveDate;
177+
const now = new Date();
178+
const inactiveDays = Math.floor(
179+
(now.getTime() - lastActive.getTime()) / (1000 * 60 * 60 * 24)
180+
);
181+
const decayFactor = Math.pow(
182+
this.DECAY_RATE,
183+
Math.min(inactiveDays, this.MAX_DECAY_DAYS)
184+
);
185+
const decayedScore = recommenderMetrics.trustScore * decayFactor;
186+
132187
const newRecommenderMetrics: RecommenderMetrics = {
133188
recommenderId: recommenderId,
134189
trustScore: overallTrustScore,
@@ -137,7 +192,9 @@ export class TrustScoreProvider {
137192
avgTokenPerformance: avgTokenPerformance,
138193
riskScore: riskScore,
139194
consistencyScore: consistencyScore,
140-
virtualConfidence: recommenderMetrics.virtualConfidence,
195+
virtualConfidence: virtualConfidence,
196+
lastActiveDate: new Date(),
197+
trustDecay: decayedScore,
141198
lastUpdated: new Date(),
142199
};
143200

0 commit comments

Comments
 (0)