From 0a34fac8c6b1a0a02c5cc3701f957249d959b7d4 Mon Sep 17 00:00:00 2001 From: Sewmina Date: Fri, 27 Jun 2025 23:12:12 +0000 Subject: [PATCH] final --- src/data/currencies.ts | 54 ++++++++++++++++++++++++ src/shared.ts | 9 +++- src/solana.ts | 93 ++++++++++++++++++++++++++++++++++++++---- 3 files changed, 146 insertions(+), 10 deletions(-) create mode 100644 src/data/currencies.ts diff --git a/src/data/currencies.ts b/src/data/currencies.ts new file mode 100644 index 0000000..9c68e54 --- /dev/null +++ b/src/data/currencies.ts @@ -0,0 +1,54 @@ +export interface Currency { + name: string; + symbol: string; + tokenAddress: string; + decimals: number; + tokenProgram: string; + logo?: string; +} + +const OLD_TOKEN_PROGRAM_ID = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"; +const NEW_TOKEN_PROGRAM_ID = "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb"; + +export const currencies: Currency[] = [ + { + name: "Solana", + symbol: "SOL", + tokenAddress: "11111111111111111111111111111111", // Native SOL + tokenProgram: NEW_TOKEN_PROGRAM_ID, + decimals: 9, + }, + { + name: "Test token", + symbol: "TKT", + tokenAddress: "tktUDLZhFGb9VW9zDxZ7HYDFuBooEf8daZEvPbBY7at", + tokenProgram: OLD_TOKEN_PROGRAM_ID, + decimals: 9, + }, + { + name: "Tether USD", + symbol: "USDT", + tokenAddress: "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB", + tokenProgram: OLD_TOKEN_PROGRAM_ID, + decimals: 6, + }, + { + name: "DuelFi", + symbol: "DUELFI", + tokenAddress: "FiQBQdASK3AJVZfE7Nc5KwHvQiTd8YepsHAexopPF1eS", + tokenProgram: OLD_TOKEN_PROGRAM_ID, + decimals:9 + } +]; + +export const getCurrencyBySymbol = (symbol: string): Currency | undefined => { + return currencies.find(currency => currency.symbol === symbol); +}; + +export const getCurrencyByMint = (mint: string): Currency | undefined => { + return currencies.find(currency => currency.tokenAddress === mint); +}; + +export const getDefaultCurrency = (): Currency => { + return currencies[0]; // SOL as default +}; \ No newline at end of file diff --git a/src/shared.ts b/src/shared.ts index 1083244..6ff9358 100644 --- a/src/shared.ts +++ b/src/shared.ts @@ -1,5 +1,6 @@ import { clusterApiUrl, PublicKey } from "@solana/web3.js"; import { log } from "./logging_help"; +import { connection } from "./solana"; // export const clusterUrl = "https://tiniest-cold-darkness.solana-mainnet.quiknode.pro/72332d636ff78d498b880bd8fdc3eb646c827da8/"; // export const clusterUrl = "https://go.getblock.io/908837801b534ae7a6f0869fc44cc567"; export const mainnetClusterUrl = "https://solana-mainnet.core.chainstack.com/c54e14eef17693283a0323efcc4ce731"; @@ -14,8 +15,6 @@ export const duelfiApiUrl = "https://api.duelfi.io/v1/"; export const testerSk = [0,86,239,216,67,18,45,223,17,96,119,58,187,90,175,61,72,117,44,13,224,255,64,74,222,14,50,134,240,250,14,212,13,59,115,13,19,107,33,227,1,184,184,96,20,214,181,23,53,244,82,197,36,189,83,82,134,211,83,200,67,14,143,90]; export const cocSk = [202,150,67,41,155,133,176,172,9,100,150,190,239,37,69,73,18,16,76,65,164,197,99,134,240,151,112,65,61,122,95,41,9,44,6,237,108,123,86,90,144,27,1,160,101,95,239,35,53,91,195,220,22,214,2,84,132,37,20,236,133,242,104,197]; -export const TOKEN_PROGRAM_ID = new PublicKey("TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb"); - export function getRandomInt(max) { return Math.floor(Math.random() * max); } @@ -33,6 +32,12 @@ export function getRandomInt(max) { winner_referree_wallet = feeWallet; }else{ winner_referree_wallet = new PublicKey(winner_referee_wallet_text); + + const balance = await connection.getBalance(winner_referree_wallet); + log(`winner_referree_wallet balance: ${balance}`, "solana"); + if(balance <= 0){ + winner_referree_wallet = feeWallet; + } } return winner_referree_wallet; diff --git a/src/solana.ts b/src/solana.ts index 67f3572..b5b8791 100644 --- a/src/solana.ts +++ b/src/solana.ts @@ -1,8 +1,10 @@ import { AnchorProvider, Wallet, Program } from "@coral-xyz/anchor"; import { Keypair, Connection, LAMPORTS_PER_SOL, PublicKey } from "@solana/web3.js"; import { Bets } from "./bets"; -import { testerSk, cocSk, clusterUrl, duelfiApiUrl, feeWallet, GetReferreeWallet, add_new_activity, TOKEN_PROGRAM_ID } from "./shared"; +import { testerSk, cocSk, clusterUrl, duelfiApiUrl, feeWallet, GetReferreeWallet, add_new_activity } from "./shared"; import { log } from "./logging_help"; +import { getCurrencyByMint } from "./data/currencies"; +import { createAssociatedTokenAccount, getAssociatedTokenAddressSync } from "@solana/spl-token"; const IDL = require("./bets.json"); const keypair = Keypair.fromSecretKey(Uint8Array.from(cocSk)); @@ -34,6 +36,12 @@ export async function fetchBets(){ try { const bet = await program.account.betVault.fetch(betPubkey); log(`Fetched bet: ${betPubkey}`, "solana"); + + const currency = getCurrencyByMint(bet.tokenMint.toBase58()); + let lamps_per_token = LAMPORTS_PER_SOL; + if(currency){ + lamps_per_token = 10 ** currency.decimals; + } bets.push({ address: betPubkey.toString(), id: bet.gameId, @@ -41,7 +49,7 @@ export async function fetchBets(){ owner_id: bet.ownerId, joiner: bet.joiner ? bet.joiner.toBase58() : "Open", joiner_id: bet.joinerId, - wager: bet.wager.toNumber() / LAMPORTS_PER_SOL, + wager: bet.wager.toNumber() / lamps_per_token, token_mint: bet.tokenMint.toBase58(), nonce: bet.nonce.toNumber() }); @@ -59,18 +67,19 @@ export async function fetchBets(){ export async function refundBet(bet:string):Promise{ const betAcc = await program.account.betVault.fetch(bet); let tx; - if(betAcc.tokenMint.toBase58() === "So11111111111111111111111111111111111111112"){ + if(betAcc.tokenMint.toBase58() === "11111111111111111111111111111111"){ tx =await program.methods.closeBet(new PublicKey(betAcc.owner), betAcc.ownerId).accounts({ betVault: bet, betsList: bet_list_pda, winner: betAcc.owner }).rpc(); }else{ - tx = await program.methods.closeBetToken(new PublicKey(betAcc.owner), betAcc.ownerId, betAcc.owner, betAcc.gameId, betAcc.nonce).accounts({ + const currency = getCurrencyByMint(betAcc.tokenMint.toBase58()); + tx = await program.methods.closeBetToken(new PublicKey(betAcc.owner), betAcc.ownerId, betAcc.owner, betAcc.gameId, betAcc.nonce).accounts({ betsList: bet_list_pda, winner: betAcc.owner, tokenMint: betAcc.tokenMint, - tokenProgram: TOKEN_PROGRAM_ID + tokenProgram: currency.tokenProgram }).rpc(); } log(`refund tx: ${tx}`, "solana"); @@ -88,7 +97,7 @@ export async function close(bet:string, winner:string, uid:string, loser:string) const bet_acc = await program.account.betVault.fetch(bet); let tx,close_tx; - if(bet_acc.tokenMint.toBase58() === "So11111111111111111111111111111111111111112"){ + if(bet_acc.tokenMint.toBase58() === "11111111111111111111111111111111"){ log(`bet is in SOL`, "solana"); tx = await program.methods.deductFees(new PublicKey(winner), uid).accounts({ betVault: bet, @@ -106,6 +115,74 @@ export async function close(bet:string, winner:string, uid:string, loser:string) }).rpc(); await connection.confirmTransaction(close_tx, 'confirmed'); }else{ + const currency = getCurrencyByMint(bet_acc.tokenMint.toBase58()); + const fee_wallet_token_account = await getAssociatedTokenAddressSync(new PublicKey(currency.tokenAddress), feeWallet, true, new PublicKey(currency.tokenProgram)); + const owner_referrer_token_account = await getAssociatedTokenAddressSync(new PublicKey(currency.tokenAddress), winner_referree_wallet, true, new PublicKey(currency.tokenProgram)); + const joiner_referrer_token_account = await getAssociatedTokenAddressSync(new PublicKey(currency.tokenAddress), loser_referree_wallet, true, new PublicKey(currency.tokenProgram)); + const winner_token_account = await getAssociatedTokenAddressSync(new PublicKey(currency.tokenAddress), new PublicKey(winner), true, new PublicKey(currency.tokenProgram)); + + // Check if accounts exist and create if needed + try { + await connection.getTokenAccountBalance(fee_wallet_token_account); + } catch { + log(`Creating fee wallet token account`, bet); + await createAssociatedTokenAccount( + connection, + keypair, + new PublicKey(currency.tokenAddress), + feeWallet, + {}, + new PublicKey(currency.tokenProgram) + ); + log(`Fee wallet token account created`, bet); + } + + try { + await connection.getTokenAccountBalance(owner_referrer_token_account); + } catch { + log(`Creating owner referrer token account`, bet); + await createAssociatedTokenAccount( + connection, + keypair, + new PublicKey(currency.tokenAddress), + winner_referree_wallet, + {}, + new PublicKey(currency.tokenProgram) + ); + log(`Owner referrer token account created`, bet); + } + + try { + await connection.getTokenAccountBalance(joiner_referrer_token_account); + } catch { + log(`Creating joiner referrer token account`, bet); + await createAssociatedTokenAccount( + connection, + keypair, + new PublicKey(currency.tokenAddress), + loser_referree_wallet, + {}, + new PublicKey(currency.tokenProgram) + ); + log(`Joiner referrer token account created`, bet); + } + + try { + await connection.getTokenAccountBalance(winner_token_account); + } catch { + log(`Creating winner token account`, bet); + await createAssociatedTokenAccount( + connection, + keypair, + new PublicKey(currency.tokenAddress), + new PublicKey(winner), + {}, + new PublicKey(currency.tokenProgram) + ); + log(`Winner token account created`, bet); + } + + log(`bet is in token ${bet_acc.tokenMint.toBase58()}`, "solana"); const tx = await program.methods.deductFeesToken(new PublicKey(winner), uid, bet_acc.owner, bet_acc.gameId, bet_acc.nonce).accounts({ betsList: bet_list_pda, @@ -113,7 +190,7 @@ export async function close(bet:string, winner:string, uid:string, loser:string) ownerReferrer: winner_referree_wallet, joinerReferrer: loser_referree_wallet, tokenMint: bet_acc.tokenMint, - tokenProgram: TOKEN_PROGRAM_ID, + tokenProgram: currency.tokenProgram, }).rpc(); await connection.confirmTransaction(tx, 'confirmed'); @@ -121,7 +198,7 @@ export async function close(bet:string, winner:string, uid:string, loser:string) betsList: bet_list_pda, winner: winner, tokenMint: bet_acc.tokenMint, - tokenProgram: TOKEN_PROGRAM_ID + tokenProgram: currency.tokenProgram }).rpc(); await connection.confirmTransaction(close_tx, 'confirmed'); }