UNPKG

@hubbleprotocol/farms-sdk

Version:
198 lines (183 loc) 5.43 kB
import { InitObligationFarmsForReserveAccounts, InitObligationFarmsForReserveArgs, KaminoMarket, KaminoObligation, KaminoReserve, initObligationFarmsForReserve, } from "@kamino-finance/klend-sdk"; import { PublicKey, SYSVAR_RENT_PUBKEY, SystemProgram, TransactionInstruction, } from "@solana/web3.js"; import { Farms } from "../Farms"; import { initializeClient } from "./utils"; import { Env, accountExist, getFarmsProgramId, sleep } from "../utils"; import { TOKEN_PROGRAM_ID } from "@solana/spl-token"; export async function initAllKlendUserObligationFarmsFromFileCommand( market: string, file: string, ) { const admin = process.env.ADMIN; const rpc = process.env.RPC; const klendProgramId = new PublicKey(process.env.KLEND_PROGRAM_ID || ""); const env = initializeClient(rpc!, admin!, getFarmsProgramId(rpc!), false); const c = env.provider.connection; const farmsClient = new Farms(env.provider.connection); const shouldExecute = true; const lendingMarket = new PublicKey(market); const kaminoMarket = await KaminoMarket.load( c, lendingMarket, 450, klendProgramId, ); if (!kaminoMarket) { throw new Error("Kamino market not found"); } let ixns: TransactionInstruction[] = []; const fs = require("fs"); const rawData = fs.readFileSync(file, "utf8"); const obligationAddresses: string[] = JSON.parse(rawData); let startAt = 0; let stopAt = obligationAddresses.length; let i = startAt; for (let i = startAt; i < stopAt; i++) { const obligationAddress = obligationAddresses[i]; console.log( `Running through obligation ${i}/${obligationAddresses.length} ixns ${ixns.length}`, ); let obligation = (await kaminoMarket.getObligationByAddress( new PublicKey(obligationAddress), ))!; if (!obligation) { continue; } for (const deposit of obligation.deposits) { const reserve = kaminoMarket.getReserveByMint(deposit[1].mintAddress)!; const reserveFarms: [PublicKey, number][] = [ [reserve.state.farmCollateral, 0], // [reserve.state.farmDebt, 1], ]; for (const [reserveFarm, mode] of reserveFarms) { if (reserveFarm.equals(PublicKey.default)) { continue; } // For this reserve, do both collateral and debt const userStatePda = getUserFarmPda( reserveFarm, obligation.obligationAddress, farmsClient.getProgramID(), ); // Only init if does not exist if (!(await accountExist(c, userStatePda))) { ixns.push( getInitIxn( env, obligation, kaminoMarket, reserve, reserveFarm, userStatePda, farmsClient.getProgramID(), mode, ), ); } } } } // Execute these first console.log("Executing ixns", ixns.length); let promises: any = []; if (shouldExecute) { let batchSize = 5; let thisBatch: TransactionInstruction[] = []; let maxConcurrent = 20; for (let i = 0; i < ixns.length; i++) { thisBatch.push(ixns[i]); console.log("Executing ixn", i); if (thisBatch.length >= batchSize || i === ixns.length - 1) { promises.push( executeWithoutAwait(env, farmsClient, thisBatch, i, ixns.length).then( (sig) => { console.log(`Init Signature ${sig} for ${i}/${ixns.length}`); }, ), ); thisBatch = []; } if (promises.length >= maxConcurrent || i === ixns.length - 1) { await Promise.all(promises); promises = []; } } } await Promise.all(promises); } const executeWithoutAwait = async ( env: Env, farmsClient: Farms, thisBatch: TransactionInstruction[], i: number, len: number, ) => { let numRetries = 5; let retry = 0; while (retry < numRetries) { try { const sig = await farmsClient.executeTransaction( thisBatch, env.initialOwner, [], ); return sig; } catch (e) { retry += 1; await sleep(1000); } } return null; }; const BASE_SEED_USER_STATE = Buffer.from("user"); const getUserFarmPda = ( farm: PublicKey, obligation: PublicKey, farmsProgramId: PublicKey, ) => PublicKey.findProgramAddressSync( [BASE_SEED_USER_STATE, farm.toBytes(), obligation.toBytes()], farmsProgramId, )[0]; const getInitIxn = ( env: Env, obligation: KaminoObligation, market: KaminoMarket, reserve: KaminoReserve, reserveFarm: PublicKey, userStatePda: PublicKey, farmsProgramId: PublicKey, mode: number, ): TransactionInstruction => { const args = { mode, } as InitObligationFarmsForReserveArgs; const accts = { payer: env.initialOwner.publicKey, owner: obligation.state.owner, obligation: obligation.obligationAddress, lendingMarketAuthority: market.getLendingMarketAuthority(), reserve: reserve.address, reserveFarmState: reserveFarm, obligationFarm: userStatePda, lendingMarket: reserve.state.lendingMarket, farmsProgram: farmsProgramId, rent: SYSVAR_RENT_PUBKEY, tokenProgram: TOKEN_PROGRAM_ID, systemProgram: SystemProgram.programId, } as InitObligationFarmsForReserveAccounts; const ixn = initObligationFarmsForReserve(args, accts, market.programId); return ixn; };