import type { Arguments, CommandBuilder } from "yargs"; import * as anchor from "@project-serum/anchor"; import fs from "fs"; import { Keypair, Transaction } from "@solana/web3.js"; import { Rain } from "@rainfi/rain"; import { handleErrorTx } from "../utils/utils"; export const command = "create_pool"; export const desc = "Create a pool"; type Options = { loanToValue: number maxAmount: number interestType: string interestRate: number maxDuration: number interestCurve: number; interestGap: number; compound: string amount: number collections: string keypair: string simulate: string network: string } export const builder: CommandBuilder = (yargs) => { return yargs .options({ 'ltv': { alias: 'loanToValue', describe: 'Loan to value for loans (in %)', demandOption: true }, 'rate': { alias: 'interestRate', describe: 'Interest rate, if Interest Type set to manual', demandOption: true }, 'type': { alias: 'interestType', describe: 'Interest Type, dynamic or manual', demandOption: true }, 'gap': { alias: 'interestGap', describe: 'Interest gap, number, see docs', demandOption: true }, 'curve': { alias: 'interestCurve', describe: 'Interest curve, number, see docs', demandOption: true }, 'maxAmount': { describe: 'Max amount per loan', demandOption: false }, 'maxDuration': { describe: 'Max duration (in days) per loan', demandOption: true }, 'compound': { describe: 'Enable compound of fees or not, boolean', demandOption: true, }, 'amount': { describe: 'Amount of SOL to put in pool', demandOption: true }, 'collections': { describe: 'Collections that you accept to lend SOL to', demandOption: true }, 'k': { alias: 'keypair', describe: 'Keypair used to send/sign the transaction', demandOption: true, default: `${process.env.HOME}/.config/solana/id.json` }, 'simulate': { describe: 'Simulate the transaction instead of submit to network', default: "false", demandOption: false }, 'n': { alias: 'network', describe: 'Network to use', default: 'https://api.mainnet-beta.solana.com', demandOption: false } }) }; export const handler = async (argv: Arguments): Promise => { var { loanToValue, interestCurve, interestGap, maxAmount, interestType, interestRate, maxDuration, compound, amount, collections, keypair, simulate, network } = argv; const isSimulate = simulate === 'true' maxAmount = maxAmount || amount const connection = new anchor.web3.Connection(network); const rain = new Rain() const mainWalletParsed: number[] = JSON.parse( fs.readFileSync(keypair, "utf8") ); const wallet = Keypair.fromSecretKey(new Uint8Array(mainWalletParsed)); console.log("[i] - Using RPC:", network); console.log("[i] - Using keypair:", wallet.publicKey.toBase58()); console.log("[i] - Using program:", rain.PUBKEY.toBase58()); console.log("[i] - Create Pool"); const walletWrapper = new anchor.Wallet(wallet); const provider = new anchor.AnchorProvider(connection, walletWrapper, { preflightCommitment: "recent", }); const args = { loanToValue: loanToValue * 1000, maxAmount: maxAmount, interestType: interestType === 'dynamic' ? 1 : 0, interestRate: interestType === 'dynamic' ? 0 : interestRate * 100, interestCurve: interestCurve, interestGap: interestGap, maxDuration: maxDuration, compound: compound === 'true' ? true : false, amount: amount, collections: JSON.parse(collections) } const instruction = await rain.instructions.createPool(wallet.publicKey, args) const tx = new Transaction().add(instruction) tx.recentBlockhash = (await connection.getLatestBlockhash()).blockhash tx.feePayer = wallet.publicKey if (isSimulate) { const simulation = await provider.simulate(tx, [wallet], "processed") console.log("Encoded Transaction Message:", tx.serializeMessage().toString("base64")); console.log("[i] - Simulation:", simulation); } else { try { const signature = await provider.sendAndConfirm(tx, [wallet]) console.log("[i] - Signature:", signature); } catch(e: any) { const errorMessage = handleErrorTx(e) throw new Error(errorMessage || e) } } };