Skip to content

Commit

Permalink
recommender, token performane integration to swap
Browse files Browse the repository at this point in the history
Signed-off-by: MarcoMandar <[email protected]>
  • Loading branch information
MarcoMandar committed Nov 5, 2024
1 parent 7e85609 commit 0b16744
Show file tree
Hide file tree
Showing 3 changed files with 184 additions and 9 deletions.
75 changes: 72 additions & 3 deletions core/src/actions/swap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ import settings from "../core/settings.ts";
import { bs58 } from "@coral-xyz/anchor/dist/cjs/utils/bytes/index.js";
import BigNumber from "bignumber.js";
import { WalletProvider } from "../providers/wallet.ts";
import { TrustScoreProvider } from "../providers/trustScoreProvider";
import { TokenProvider } from "../providers/token";
import { TrustScoreDatabase } from "../adapters/trustScoreDatabase";
import { v4 as uuidv4 } from "uuid";

async function swapToken(
connection: Connection,
Expand Down Expand Up @@ -155,7 +159,7 @@ async function getTokensInWallet(runtime: IAgentRuntime) {
}

// check if the token symbol is in the wallet
async function checkTokenInWallet(runtime: IAgentRuntime, tokenSymbol: string) {
async function getTokenFromWallet(runtime: IAgentRuntime, tokenSymbol: string) {
try {
const items = await getTokensInWallet(runtime);
const token = items.find((item) => item.symbol === tokenSymbol);
Expand Down Expand Up @@ -212,6 +216,8 @@ export const executeSwap: Action = {
});

console.log("Response:", response);
const type =
response.inputTokenSymbol?.toUpperCase() === "SOL" ? "buy" : "sell";

// Add SOL handling logic
if (response.inputTokenSymbol?.toUpperCase() === "SOL") {
Expand All @@ -227,7 +233,7 @@ export const executeSwap: Action = {
console.log(
`Attempting to resolve CA for input token symbol: ${response.inputTokenSymbol}`
);
response.inputTokenCA = await checkTokenInWallet(
response.inputTokenCA = await getTokenFromWallet(
runtime,
response.inputTokenSymbol
);
Expand All @@ -247,7 +253,7 @@ export const executeSwap: Action = {
console.log(
`Attempting to resolve CA for output token symbol: ${response.outputTokenSymbol}`
);
response.outputTokenCA = await checkTokenInWallet(
response.outputTokenCA = await getTokenFromWallet(
runtime,
response.outputTokenSymbol
);
Expand Down Expand Up @@ -387,6 +393,69 @@ export const executeSwap: Action = {
);
}

if (type === "buy") {
const tokenProvider = new TokenProvider(response.outputTokenCA);
const module = await import("better-sqlite3");
const Database = module.default;
const trustScoreDb = new TrustScoreDatabase(
new Database(":memory:")
);
// add or get recommender
const uuid = uuidv4();
const recommender = await trustScoreDb.getOrCreateRecommender({
id: uuid,
address: walletPublicKey.toString(),
solanaPubkey: walletPublicKey.toString(),
});

const trustScoreDatabase = new TrustScoreProvider(
tokenProvider,
trustScoreDb
);
// save the trade
const tradeData = {
buy_amount: response.amount,
is_simulation: false,
};
await trustScoreDatabase.createTradePerformance(
response.outputTokenCA,
recommender.id,
tradeData
);
} else if (type === "sell") {
const tokenProvider = new TokenProvider(response.inputTokenCA);
const module = await import("better-sqlite3");
const Database = module.default;
const trustScoreDb = new TrustScoreDatabase(
new Database(":memory:")
);
// add or get recommender
const uuid = uuidv4();
const recommender = await trustScoreDb.getOrCreateRecommender({
id: uuid,
address: walletPublicKey.toString(),
solanaPubkey: walletPublicKey.toString(),
});

const trustScoreDatabase = new TrustScoreProvider(
tokenProvider,
trustScoreDb
);
// save the trade
const sellDetails = {
sell_amount: response.amount,
sell_recommender_id: recommender.id,
};
const sellTimeStamp = new Date().getTime().toString();
await trustScoreDatabase.updateSellDetails(
response.inputTokenCA,
recommender.id,
sellTimeStamp,
sellDetails,
false
);
}

console.log("Swap completed successfully!");
console.log(`Transaction ID: ${txid}`);

Expand Down
111 changes: 109 additions & 2 deletions core/src/adapters/trustScoreDatabase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ export class TrustScoreDatabase {
risk_score REAL DEFAULT 0,
consistency_score REAL DEFAULT 0,
virtual_confidence REAL DEFAULT 0,
last_active_date DATETIME DEFAULT CURRENT_TIMESTAMP
last_active_date DATETIME DEFAULT CURRENT_TIMESTAMP,
trust_decay REAL DEFAULT 0,
last_updated DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (recommender_id) REFERENCES recommenders(id) ON DELETE CASCADE
Expand Down Expand Up @@ -349,6 +349,61 @@ export class TrustScoreDatabase {
return recommender || null;
}

/**
* Retrieves an existing recommender or creates a new one if not found.
* Also initializes metrics for the recommender if they haven't been initialized yet.
* @param recommender Recommender object containing at least one identifier
* @returns Recommender object with all details, or null if failed
*/
getOrCreateRecommender(recommender: Recommender): Recommender | null {
try {
// Begin a transaction
const transaction = this.db.transaction(() => {
// Attempt to retrieve the recommender
const existingRecommender = this.getRecommender(
recommender.address
);
if (existingRecommender) {
// Recommender exists, ensure metrics are initialized
this.initializeRecommenderMetrics(existingRecommender.id!);
return existingRecommender;
}

// Recommender does not exist, create a new one
const newRecommenderId = this.addRecommender(recommender);
if (!newRecommenderId) {
throw new Error("Failed to add new recommender.");
}

// Initialize metrics for the new recommender
const metricsInitialized =
this.initializeRecommenderMetrics(newRecommenderId);
if (!metricsInitialized) {
throw new Error(
"Failed to initialize recommender metrics."
);
}

// Retrieve and return the newly created recommender
const newRecommender = this.getRecommender(newRecommenderId);
if (!newRecommender) {
throw new Error(
"Failed to retrieve the newly created recommender."
);
}

return newRecommender;
});

// Execute the transaction and return the recommender
const recommenderResult = transaction();
return recommenderResult;
} catch (error) {
console.error("Error in getOrCreateRecommender:", error);
return null;
}
}

/**
* Initializes metrics for a recommender if not present.
* @param recommenderId Recommender's UUID
Expand Down Expand Up @@ -548,6 +603,8 @@ export class TrustScoreDatabase {
performance.tokenAddress,
performance.priceChange24h,
performance.volumeChange24h,
performance.trade_24h_change,
performance.liquidity,
performance.liquidityChange24h,
performance.holderChange24h, // Ensure column name matches schema
performance.rugPull ? 1 : 0,
Expand Down Expand Up @@ -916,7 +973,7 @@ export class TrustScoreDatabase {
market_cap_change = ?,
sell_liquidity = ?,
liquidity_change = ?,
rapidDump = ?
rapidDump = ?,
sell_recommender_id = ?
WHERE
token_address = ?
Expand Down Expand Up @@ -1016,6 +1073,56 @@ export class TrustScoreDatabase {
};
}

/**
* Retrieves the latest trade performance metrics without requiring buyTimeStamp.
* @param tokenAddress Token's address
* @param recommenderId Recommender's UUID
* @param isSimulation Whether the trade is a simulation. If true, retrieves from simulation_trade; otherwise, from trade.
* @returns TradePerformance object or null
*/
getLatestTradePerformance(
tokenAddress: string,
recommenderId: string,
isSimulation: boolean
): TradePerformance | null {
const tableName = isSimulation ? "simulation_trade" : "trade";
const sql = `
SELECT * FROM ${tableName}
WHERE token_address = ? AND recommender_id = ?
ORDER BY buy_timeStamp DESC
LIMIT 1;
`;
const row = this.db.prepare(sql).get(tokenAddress, recommenderId) as
| TradePerformance
| undefined;
if (!row) return null;

return {
token_address: row.token_address,
recommender_id: row.recommender_id,
buy_price: row.buy_price,
sell_price: row.sell_price,
buy_timeStamp: row.buy_timeStamp,
sell_timeStamp: row.sell_timeStamp,
buy_amount: row.buy_amount,
sell_amount: row.sell_amount,
buy_sol: row.buy_sol,
received_sol: row.received_sol,
buy_value_usd: row.buy_value_usd,
sell_value_usd: row.sell_value_usd,
profit_usd: row.profit_usd,
profit_percent: row.profit_percent,
buy_market_cap: row.buy_market_cap,
sell_market_cap: row.sell_market_cap,
market_cap_change: row.market_cap_change,
buy_liquidity: row.buy_liquidity,
sell_liquidity: row.sell_liquidity,
liquidity_change: row.liquidity_change,
last_updated: row.last_updated,
rapidDump: row.rapidDump,
};
}

/**
* Close the database connection gracefully.
*/
Expand Down
7 changes: 3 additions & 4 deletions core/src/providers/trustScoreProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -363,8 +363,7 @@ export class TrustScoreProvider {
recommenderId: string,
sellTimeStamp: string,
sellDetails: sellDetails,
isSimulation: boolean,
buyTimeStamp: string
isSimulation: boolean
) {
const processedData: ProcessedTokenData =
await this.tokenProvider.getProcessedTokenData();
Expand All @@ -377,12 +376,12 @@ export class TrustScoreProvider {
const sellSol = sellDetails.sell_amount / parseFloat(solPrice);
const sell_value_usd =
sellDetails.sell_amount * processedData.tradeData.price;
const trade = await this.trustScoreDb.getTradePerformance(
const trade = await this.trustScoreDb.getLatestTradePerformance(
tokenAddress,
recommenderId,
buyTimeStamp,
isSimulation
);
const buyTimeStamp = trade.buy_timeStamp;
const marketCap =
processedData.dexScreenerData.pairs[0]?.marketCap || 0;
const liquidity =
Expand Down

0 comments on commit 0b16744

Please sign in to comment.