@kamino-finance/farms-sdk
Version:
407 lines • 16.6 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseTokenSymbol = exports.getCustomProgramErrorCode = exports.WAD = void 0;
exports.parseKeypairFile = parseKeypairFile;
exports.collToLamportsDecimal = collToLamportsDecimal;
exports.lamportsToCollDecimal = lamportsToCollDecimal;
exports.solAirdrop = solAirdrop;
exports.solAirdropMin = solAirdropMin;
exports.checkIfAccountExists = checkIfAccountExists;
exports.mapAnchorError = mapAnchorError;
exports.getTokenAccountBalance = getTokenAccountBalance;
exports.getSolBalanceInLamports = getSolBalanceInLamports;
exports.getSolBalance = getSolBalance;
exports.getFarmsProgramId = getFarmsProgramId;
exports.pubkeyFromFile = pubkeyFromFile;
exports.createAddExtraComputeUnitsTransaction = createAddExtraComputeUnitsTransaction;
exports.u16ToBytes = u16ToBytes;
exports.accountExist = accountExist;
exports.fetchFarmStateWithRetry = fetchFarmStateWithRetry;
exports.fetchGlobalConfigWithRetry = fetchGlobalConfigWithRetry;
exports.fetchUserStateWithRetry = fetchUserStateWithRetry;
exports.getTreasuryVaultPDA = getTreasuryVaultPDA;
exports.getTreasuryAuthorityPDA = getTreasuryAuthorityPDA;
exports.getFarmAuthorityPDA = getFarmAuthorityPDA;
exports.getFarmVaultPDA = getFarmVaultPDA;
exports.getRewardVaultPDA = getRewardVaultPDA;
exports.getUserStatePDA = getUserStatePDA;
exports.sendAndConfirmInstructions = sendAndConfirmInstructions;
exports.getGlobalConfigValue = getGlobalConfigValue;
exports.createKeypairRentExempt = createKeypairRentExempt;
exports.createKeypairRentExemptIx = createKeypairRentExemptIx;
exports.createGlobalConfigPublicKeyRentExempt = createGlobalConfigPublicKeyRentExempt;
exports.createFarmPublicKeyRentExempt = createFarmPublicKeyRentExempt;
exports.buildAndSendTxnWithLogs = buildAndSendTxnWithLogs;
exports.sleep = sleep;
exports.scaleDownWads = scaleDownWads;
exports.convertStakeToAmount = convertStakeToAmount;
exports.convertAmountToStake = convertAmountToStake;
exports.retryAsync = retryAsync;
exports.noopProfiledFunctionExecution = noopProfiledFunctionExecution;
const anchor = __importStar(require("@coral-xyz/anchor"));
const fs = __importStar(require("fs"));
const FarmsErrors = __importStar(require("../rpc_client/errors"));
const web3_js_1 = require("@solana/web3.js");
const decimal_js_1 = require("decimal.js");
const web3 = __importStar(require("@solana/web3.js"));
const setup_1 = require("./setup");
const accounts_1 = require("../rpc_client/accounts");
const Farms_1 = require("../Farms");
exports.WAD = new decimal_js_1.Decimal("1".concat(Array(18 + 1).join("0")));
function parseKeypairFile(file) {
return web3_js_1.Keypair.fromSecretKey(Buffer.from(JSON.parse(require("fs").readFileSync(file))));
}
function collToLamportsDecimal(amount, decimals) {
let factor = Math.pow(10, decimals);
return amount.mul(factor);
}
function lamportsToCollDecimal(amount, decimals) {
let factor = Math.pow(10, decimals);
return amount.div(factor);
}
async function solAirdrop(provider, account, solAirdrop) {
const airdropTxnId = await provider.connection.requestAirdrop(account, collToLamportsDecimal(solAirdrop, 9).toNumber());
await provider.connection.confirmTransaction(airdropTxnId);
return await getSolBalance(provider, account);
}
async function solAirdropMin(provider, account, minSolAirdrop) {
const airdropBatchAmount = decimal_js_1.Decimal.max(50, minSolAirdrop);
let currentBalance = await getSolBalance(provider, account);
while (currentBalance.lt(minSolAirdrop)) {
try {
await provider.connection.requestAirdrop(account, collToLamportsDecimal(airdropBatchAmount, 9).toNumber());
}
catch (e) {
await sleep(100);
console.log("Error", e);
}
await sleep(100);
currentBalance = await getSolBalance(provider, account);
}
return currentBalance;
}
async function checkIfAccountExists(connection, account) {
return (await connection.getAccountInfo(account)) != null;
}
/**
* Get the custom program error code if there's any in the error message and return parsed error code hex to number string
* @param errMessage string - error message that would contain the word "custom program error:" if it's a customer program error
* @returns [boolean, string] - probably not a custom program error if false otherwise the second element will be the code number in string
*/
const getCustomProgramErrorCode = (errMessage) => {
const index = errMessage.indexOf("Custom program error:");
if (index === -1) {
return [false, "May not be a custom program error"];
}
else {
return [
true,
`${parseInt(errMessage.substring(index + 22, index + 28).replace(" ", ""), 16)}`,
];
}
};
exports.getCustomProgramErrorCode = getCustomProgramErrorCode;
/**
*
* Maps the private Anchor type ProgramError to a normal Error.
* Pass ProgramErr.msg as the Error message so that it can be used with chai matchers
*
* @param fn - function which may throw an anchor ProgramError
*/
async function mapAnchorError(fn) {
try {
return await fn;
}
catch (e) {
let [isCustomProgramError, errorCode] = (0, exports.getCustomProgramErrorCode)(JSON.stringify(e));
if (isCustomProgramError) {
let error;
if (!isNaN(Number(errorCode))) {
error = FarmsErrors.fromCode(Number(errorCode));
throw new Error(error);
}
else if (Number(errorCode) >= 6000 && Number(errorCode) <= 7000) {
errorCode[errorCode.length - 2] === "0"
? (errorCode = errorCode.slice(-1))
: (errorCode = errorCode.slice(-2));
// @ts-ignore
error = FarmsIdl.errors[errorCode].msg;
throw new Error(error);
}
else {
throw new Error(e);
}
}
throw e;
}
}
async function getTokenAccountBalance(provider, tokenAccount) {
const tokenAccountBalance = await provider.connection.getTokenAccountBalance(tokenAccount);
return new decimal_js_1.Decimal(tokenAccountBalance.value.amount).div(decimal_js_1.Decimal.pow(10, tokenAccountBalance.value.decimals));
}
async function getSolBalanceInLamports(provider, account) {
let balance = undefined;
while (balance === undefined) {
balance = (await provider.connection.getAccountInfo(account))?.lamports;
}
return balance;
}
async function getSolBalance(provider, account) {
const balance = new decimal_js_1.Decimal(await getSolBalanceInLamports(provider, account));
return lamportsToCollDecimal(balance, 9);
}
function getFarmsProgramId(cluster) {
return new web3_js_1.PublicKey("FarmsPZpWu9i7Kky8tPN37rs2TpmMrAZrC7S7vJa91Hr");
}
function pubkeyFromFile(filepath) {
const fileContents = fs.readFileSync(filepath, "utf8");
const privateArray = fileContents
.replace("[", "")
.replace("]", "")
.split(",")
.map(function (item) {
return parseInt(item, 10);
});
const array = Uint8Array.from(privateArray);
const keypair = web3_js_1.Keypair.fromSecretKey(array);
return keypair.publicKey;
}
function createAddExtraComputeUnitsTransaction(owner, units) {
return web3.ComputeBudgetProgram.setComputeUnitLimit({ units });
}
function u16ToBytes(num) {
const arr = new ArrayBuffer(2);
const view = new DataView(arr);
view.setUint16(0, num, false);
return new Uint8Array(arr);
}
async function accountExist(connection, account) {
const info = await connection.getAccountInfo(account);
if (info === null || info.data.length === 0) {
return false;
}
return true;
}
async function fetchFarmStateWithRetry(env, address) {
return fetchWithRetry(async () => await accounts_1.FarmState.fetch(env.provider.connection, address), address);
}
async function fetchGlobalConfigWithRetry(env, address) {
return fetchWithRetry(async () => await accounts_1.GlobalConfig.fetch(env.provider.connection, address), address);
}
async function fetchUserStateWithRetry(env, address) {
return fetchWithRetry(async () => await accounts_1.UserState.fetch(env.provider.connection, address), address);
}
function getTreasuryVaultPDA(programId, globalConfig, rewardMint) {
const [treasuryVault, _rewardTreasuryVaultBump] = anchor.web3.PublicKey.findProgramAddressSync([Buffer.from("tvault"), globalConfig.toBuffer(), rewardMint.toBuffer()], programId);
return treasuryVault;
}
function getTreasuryAuthorityPDA(programId, globalConfig) {
const [treasuryAuthority, _treasuryAuthorityBump] = anchor.web3.PublicKey.findProgramAddressSync([Buffer.from("authority"), globalConfig.toBuffer()], programId);
return treasuryAuthority;
}
function getFarmAuthorityPDA(programId, farmState) {
const [farmAuthority, _farmAuthorityBump] = anchor.web3.PublicKey.findProgramAddressSync([Buffer.from("authority"), farmState.toBuffer()], programId);
return farmAuthority;
}
function getFarmVaultPDA(programId, farmState, tokenMint) {
const [farmVault, _farmVaultBump] = anchor.web3.PublicKey.findProgramAddressSync([Buffer.from("fvault"), farmState.toBuffer(), tokenMint.toBuffer()], programId);
return farmVault;
}
function getRewardVaultPDA(programId, farmState, rewardMint) {
const [rewardVault, _rewardVaultBump] = anchor.web3.PublicKey.findProgramAddressSync([Buffer.from("rvault"), farmState.toBuffer(), rewardMint.toBuffer()], programId);
return rewardVault;
}
function getUserStatePDA(programId, farmState, owner) {
const [userState, _userStateBump] = anchor.web3.PublicKey.findProgramAddressSync([Buffer.from("user"), farmState.toBuffer(), owner.toBuffer()], programId);
return userState;
}
async function fetchWithRetry(fetch, address, retries = 3) {
for (let i = 0; i < retries; i++) {
let resp = await fetch();
if (resp !== null) {
return resp;
}
console.log(`[${i + 1}/${retries}] Fetched account ${address} is null. Refetching...`);
}
return null;
}
async function sendAndConfirmInstructions(env, ixns) {
let tx = new web3_js_1.Transaction();
for (let i = 0; i < ixns.length; i++) {
tx.add(ixns[i]);
}
let { blockhash } = await env.provider.connection.getLatestBlockhash();
tx.recentBlockhash = blockhash;
tx.feePayer = env.initialOwner.publicKey;
return await web3.sendAndConfirmTransaction(env.provider.connection, tx, [
env.initialOwner,
]);
}
function getGlobalConfigValue(flagValueType, flagValue) {
let value;
if (flagValueType === "number") {
value = BigInt(flagValue);
}
else if (flagValueType === "bool") {
if (flagValue === "false") {
value = false;
}
else if (flagValue === "true") {
value = true;
}
else {
throw new Error("the provided flag value is not valid bool");
}
}
else if (flagValueType === "publicKey") {
value = new web3_js_1.PublicKey(flagValue);
}
else {
throw new Error("flagValueType must be 'number', 'bool', or 'publicKey'");
}
let buffer;
if (value instanceof web3_js_1.PublicKey) {
buffer = value.toBuffer();
}
else if (typeof value === "boolean") {
buffer = Buffer.alloc(32);
value ? buffer.writeUInt8(1, 0) : buffer.writeUInt8(0, 0);
}
else if (typeof value === "bigint") {
buffer = Buffer.alloc(32);
buffer.writeBigUInt64LE(value); // Because we send 32 bytes and a u64 has 8 bytes, we write it in LE
}
else {
throw Error("wrong type for value");
}
return [...buffer];
}
async function createKeypairRentExempt(provider, programId, address, size) {
const tx = new web3_js_1.Transaction();
tx.add(await createKeypairRentExemptIx(provider.connection, provider.wallet.publicKey, address, size, programId));
await provider.sendAndConfirm(tx, [address]);
return address;
}
async function createKeypairRentExemptIx(connection, payer, account, size, programId = Farms_1.farmsId) {
return web3_js_1.SystemProgram.createAccount({
fromPubkey: payer,
newAccountPubkey: account.publicKey,
space: size,
lamports: await connection.getMinimumBalanceForRentExemption(size),
programId: programId,
});
}
async function createGlobalConfigPublicKeyRentExempt(provider, programId) {
const config = web3_js_1.Keypair.generate();
const key = await createKeypairRentExempt(provider, programId, config, setup_1.SIZE_GLOBAL_CONFIG);
return key;
}
async function createFarmPublicKeyRentExempt(provider, programId) {
const farm = web3_js_1.Keypair.generate();
const key = await createKeypairRentExempt(provider, programId, farm, setup_1.SIZE_FARM_STATE);
return key;
}
async function buildAndSendTxnWithLogs(c, tx, owner, signers) {
const { blockhash } = await c.getLatestBlockhash();
tx.recentBlockhash = blockhash;
tx.feePayer = owner.publicKey;
try {
const sig = await c.sendTransaction(tx, [owner, ...signers]);
console.log("Transaction Hash:", sig);
await sleep(5000);
const res = await c.getTransaction(sig, {
commitment: "confirmed",
});
console.log("Transaction Logs:\n", res.meta.logMessages);
}
catch (e) {
console.log(e);
await sleep(5000);
const sig = e.toString().split(" failed ")[0].split("Transaction ")[1];
const res = await c.getTransaction(sig, {
commitment: "confirmed",
});
console.log("Txn", res.meta.logMessages);
}
}
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
function scaleDownWads(value) {
return new decimal_js_1.Decimal(value.toString()).div(exports.WAD).toNumber();
}
function convertStakeToAmount(stake, totalStaked, totalAmount) {
if (stake === new decimal_js_1.Decimal(0)) {
return new decimal_js_1.Decimal(0);
}
if (totalStaked !== new decimal_js_1.Decimal(0)) {
return stake.mul(totalAmount).div(totalStaked);
}
else {
return stake.add(totalAmount);
}
}
function convertAmountToStake(amount, totalStaked, totalAmount) {
if (amount === new decimal_js_1.Decimal(0)) {
return new decimal_js_1.Decimal(0);
}
if (totalAmount !== new decimal_js_1.Decimal(0)) {
return totalStaked.mul(amount).div(totalAmount);
}
else {
return amount;
}
}
const parseTokenSymbol = (tokenSymbol) => {
return String.fromCharCode(...tokenSymbol.filter((x) => x > 0));
};
exports.parseTokenSymbol = parseTokenSymbol;
async function retryAsync(fn, retriesLeft = 5, interval = 2000) {
try {
return await fn();
}
catch (error) {
if (retriesLeft) {
await new Promise((resolve) => setTimeout(resolve, interval));
return await retryAsync(fn, retriesLeft - 1, interval);
}
throw error;
}
}
function noopProfiledFunctionExecution(promise) {
return promise;
}
//# sourceMappingURL=utils.js.map