@unloc-xyz/unloc-sdk
Version:
1,014 lines • 45.9 kB
JavaScript
"use strict";
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 (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.MINT_LAYOUT = exports.ACCOUNT_LAYOUT = exports.NFTMetadata = exports.MultipleNFT = exports.getOfferBalance = exports.logObject = exports.checkWalletATA = exports.addTokenAccountInstruction = exports.getLoanSubOffersKeysByState = exports.SubOfferState = exports.OfferState = exports.claimExpiredCollateral = exports.claimLoanCollateral = exports.repayLoan = exports.acceptLoanOffer = exports.acceptLoanOfferByVoting = exports.cancelLoanSubOffer = exports.updateLoanSubOfferByStaking = exports.updateLoanSubOffer = exports.createLoanSubOfferByStaking = exports.createLoanSubOffer = exports.cancelLoanOffer = exports.setLoanOffer = exports.claimRewards = exports.depositRewards = exports.setLoanInternalInfo = exports.setLoanGlobalState = exports.getLoanSubOfferMultiple = exports.getAllLoanSubOffers = exports.getLoanSubOfferList = exports.getLoanSubOffer = exports.getLoanOffersBy = exports.getLoanOffer = exports.getLoanOfferMultiple = exports.getLoanOfferList = exports.getCurrentVotingKey = exports.getLoanGlobalState = exports.initLoanProgram = exports.programId = exports.programProvider = exports.program = void 0;
const anchor = __importStar(require("@project-serum/anchor"));
const borsh_1 = require("@project-serum/borsh");
const spl_token_1 = require("@solana/spl-token");
const unloc_loan_1 = require("../types/unloc_loan");
const global_config_1 = require("../global-config");
const web3_js_1 = require("@solana/web3.js");
const bytes_1 = require("@project-serum/anchor/dist/cjs/utils/bytes");
const mpl_token_metadata_1 = require("@metaplex-foundation/mpl-token-metadata");
const axios_1 = __importDefault(require("axios"));
const voting_1 = require("./../voting");
const utils_1 = require("./../utils");
exports.program = null;
exports.programProvider = null;
exports.programId = null;
const GLOBAL_STATE_TAG = Buffer.from('GLOBAL_STATE_SEED');
const OFFER_TAG = Buffer.from('OFFER_SEED');
const SUB_OFFER_TAG = Buffer.from('SUB_OFFER_SEED');
const NFT_VAULT_TAG = Buffer.from('NFT_VAULT_SEED');
const OFFER_VAULT_TAG = Buffer.from('OFFER_VAULT_SEED');
const TREASURY_VAULT_TAG = Buffer.from('TREASURY_VAULT_SEED');
const REWARD_VAULT_TAG = Buffer.from('REWARD_VAULT_SEED');
const USER_REWARD_TAG = Buffer.from('LENDER_REWARD_SEED');
const WSOL_MINT = new anchor.web3.PublicKey('So11111111111111111111111111111111111111112');
// This command makes an Lottery
const initLoanProgram = (wallet, connection = utils_1.SOLANA_CONNECTION, pid = global_config_1.NFT_LOAN_PID) => {
if (exports.program != null) {
return;
}
exports.programId = pid;
const provider = new anchor.AnchorProvider(connection, wallet, { skipPreflight: true });
exports.programProvider = provider;
// Generate the program client from IDL.
exports.program = new anchor.Program(unloc_loan_1.IDL, exports.programId, provider);
};
exports.initLoanProgram = initLoanProgram;
// initLoanProgram(SOLANA_CONNECTION, Keypair.generate())
const getLoanGlobalState = async () => {
const globalState = await (0, utils_1.pda)([GLOBAL_STATE_TAG], exports.programId);
return await exports.program.account.globalState.fetchNullable(globalState);
};
exports.getLoanGlobalState = getLoanGlobalState;
const getCurrentVotingKey = async () => {
const globalState = await (0, utils_1.pda)([GLOBAL_STATE_TAG], exports.programId);
const globalStateData = await exports.program.account.globalState.fetch(globalState);
const currentVotingNum = globalStateData === null || globalStateData === void 0 ? void 0 : globalStateData.currentVotingNum;
const votingPid = globalStateData === null || globalStateData === void 0 ? void 0 : globalStateData.votingPid;
const voting = await (0, utils_1.pda)([voting_1.VOTING_TAG, currentVotingNum.toArrayLike(Buffer, "be", 8)], votingPid);
return voting;
};
exports.getCurrentVotingKey = getCurrentVotingKey;
const getLoanOfferList = async () => {
return await exports.program.account.offer.all();
};
exports.getLoanOfferList = getLoanOfferList;
const getLoanOfferMultiple = async (keys) => {
return await exports.program.account.offer.fetchMultiple(keys);
};
exports.getLoanOfferMultiple = getLoanOfferMultiple;
const getLoanOffer = async (key) => {
return await exports.program.account.offer.fetchNullable(key);
};
exports.getLoanOffer = getLoanOffer;
const getLoanOffersBy = async (owner, nftMint, state) => {
const filters = [];
if (owner) {
const filter = {
memcmp: {
offset: utils_1.discriminatorLen,
bytes: owner.toBase58()
}
};
filters.push(filter);
}
if (nftMint) {
const filter = {
memcmp: {
offset: utils_1.discriminatorLen + 32,
bytes: nftMint.toBase58()
}
};
filters.push(filter);
}
if (state) {
const filter = {
memcmp: {
offset: utils_1.discriminatorLen + 96,
bytes: bytes_1.bs58.encode([state])
}
};
filters.push(filter);
}
return await exports.program.account.offer.all(filters);
};
exports.getLoanOffersBy = getLoanOffersBy;
const getLoanSubOffer = async (key) => {
const subOffer = await exports.program.account.subOffer.fetchNullable(key);
if (subOffer) {
const offerKey = subOffer.offer;
const offerData = await exports.program.account.offer.fetch(offerKey);
if (offerData.startSubOfferNum.toNumber() > subOffer.subOfferNumber.toNumber()) {
return null;
}
}
return subOffer;
};
exports.getLoanSubOffer = getLoanSubOffer;
const getLoanSubOfferList = async (offer, nftMint, state) => {
const accountName = 'subOffer';
const filters = [];
if (offer) {
const filter = {
memcmp: {
offset: utils_1.discriminatorLen + 97,
bytes: offer.toBase58()
}
};
filters.push(filter);
}
if (nftMint) {
const filter = {
memcmp: {
offset: utils_1.discriminatorLen + 32,
bytes: nftMint.toBase58()
}
};
filters.push(filter);
}
if (state) {
const filter = {
memcmp: {
offset: utils_1.discriminatorLen + 96,
bytes: bytes_1.bs58.encode([state])
}
};
filters.push(filter);
}
const subOffers = await exports.program.account.subOffer.all(filters);
const result = [];
for (let i = 0; i < subOffers.length; i++) {
const offerKey = subOffers[i].account.offer;
const offerData = await exports.program.account.offer.fetch(offerKey);
if (offerData.startSubOfferNum.toNumber() <= subOffers[i].account.subOfferNumber.toNumber()) {
result.push(subOffers[i]);
}
}
return result;
};
exports.getLoanSubOfferList = getLoanSubOfferList;
const getAllLoanSubOffers = async () => {
const subOffers = await exports.program.account.subOffer.all();
const result = [];
for (let i = 0; i < subOffers.length; i++) {
const offerKey = subOffers[i].account.offer;
const offerData = await exports.program.account.offer.fetch(offerKey);
if (offerData.startSubOfferNum.toNumber() <= subOffers[i].account.subOfferNumber.toNumber()) {
result.push(subOffers[i]);
}
}
return result;
};
exports.getAllLoanSubOffers = getAllLoanSubOffers;
const getLoanSubOfferMultiple = async (keys, offerState) => {
const subOffers = await exports.program.account.subOffer.fetchMultiple(keys);
// Filter for nulls and get the offer address
const offerAddresses = subOffers.filter((subOffer) => subOffer).map((subOffer) => subOffer.offer);
// Get all offer data in a single call instead of a loop, filter for nulls
const offers = (await exports.program.account.offer.fetchMultiple(offerAddresses)).filter((data) => data);
const result = [];
for (let i = 0; i < subOffers.length; i++) {
if (subOffers[i]) {
const offerKey = subOffers[i].offer;
const offerKeyIndex = offerAddresses.findIndex((address) => address.equals(offerKey));
const offerData = offers[offerKeyIndex];
// If we want to, check the offer state too.
// Suboffer can be proposed when the offer isn't, so that's why we check the state on the offer, not just the suboffer.
// Be careful, offerState = 0 can coerce to false.
if (typeof offerState === 'number') {
if (offerData.startSubOfferNum.toNumber() <= subOffers[i].subOfferNumber.toNumber() && offerData.state === offerState) {
result.push({ ...subOffers[i], subOfferKey: keys[i] });
}
}
else {
if (offerData.startSubOfferNum.toNumber() <= subOffers[i].subOfferNumber.toNumber()) {
result.push({ ...subOffers[i], subOfferKey: keys[i] });
}
}
}
}
return result;
};
exports.getLoanSubOfferMultiple = getLoanSubOfferMultiple;
const setLoanGlobalState = async (accruedInterestNumerator, denominator, aprNumerator, expireLoanDuration, rewardPerSol, rewardPerUsdc, lenderRewardsPercentage, rewardMint, treasury, signer = exports.programProvider.wallet.publicKey, signers = []) => {
const globalState = await (0, utils_1.pda)([GLOBAL_STATE_TAG], exports.programId);
const rewardVault = await (0, utils_1.pda)([REWARD_VAULT_TAG], exports.programId);
const superOwner = signer;
try {
const tx = await exports.program.rpc.setGlobalState(accruedInterestNumerator, denominator, aprNumerator, expireLoanDuration, rewardPerSol, rewardPerUsdc, lenderRewardsPercentage, {
accounts: {
superOwner,
globalState,
rewardMint,
rewardVault,
newSuperOwner: superOwner,
treasuryWallet: treasury,
...utils_1.defaults
},
signers
});
// eslint-disable-next-line no-console
console.log('setGlobalState tx = ', tx);
}
catch (e) {
console.log(e);
}
};
exports.setLoanGlobalState = setLoanGlobalState;
const setLoanInternalInfo = async (unlocStakingPid, unlocStakingPoolId, votingPid, tokenMetadataPid, currentVotingNum, signer = exports.programProvider.wallet.publicKey, signers = []) => {
const globalState = await (0, utils_1.pda)([GLOBAL_STATE_TAG], exports.programId);
const superOwner = signer;
try {
const tx = await exports.program.rpc.setInternalInfo(unlocStakingPid, unlocStakingPoolId, votingPid, tokenMetadataPid, currentVotingNum, {
accounts: {
superOwner,
globalState,
},
signers
});
// eslint-disable-next-line no-console
console.log('setInternalInfo tx = ', tx);
}
catch (e) {
console.log(e);
}
};
exports.setLoanInternalInfo = setLoanInternalInfo;
const depositRewards = async (amount, signer = exports.programProvider.wallet.publicKey, signers = []) => {
const rewardMint = global_config_1.UNLOC_MINT;
const rewardVault = await (0, utils_1.pda)([REWARD_VAULT_TAG], exports.programId);
const authority = signer;
const userRewardVault = await (0, exports.checkWalletATA)(rewardMint.toBase58(), exports.programProvider.connection, authority);
const tx = await exports.program.rpc.depositRewards(amount, {
accounts: {
authority,
rewardVault,
userRewardVault,
...utils_1.defaults
},
signers
});
// eslint-disable-next-line no-console
console.log('deposit rewards tx = ', tx);
};
exports.depositRewards = depositRewards;
const claimRewards = async (userReward, signer = exports.programProvider.wallet.publicKey, signers = []) => {
const globalState = await (0, utils_1.pda)([GLOBAL_STATE_TAG], exports.programId);
const rewardMint = global_config_1.UNLOC_MINT;
const rewardVault = await (0, utils_1.pda)([REWARD_VAULT_TAG], exports.programId);
const authority = signer;
let userRewardVault = await (0, exports.checkWalletATA)(rewardMint.toBase58(), exports.programProvider.connection, authority);
const preInstructions = [];
if (!userRewardVault) {
userRewardVault = await (0, exports.addTokenAccountInstruction)(rewardMint, authority, preInstructions, signer, signers);
}
const tx = await exports.program.rpc.claimRewards({
accounts: {
authority,
globalState,
rewardVault,
userReward,
userRewardVault,
...utils_1.defaults
},
preInstructions,
signers
});
// eslint-disable-next-line no-console
console.log('claim rewards tx = ', tx);
};
exports.claimRewards = claimRewards;
const setLoanOffer = async (nftMint, signer = exports.programProvider.wallet.publicKey, signers = []) => {
const globalState = await (0, utils_1.pda)([GLOBAL_STATE_TAG], exports.programId);
const borrowerNftVault = await (0, exports.checkWalletATA)(nftMint.toBase58(), exports.programProvider.connection, signer);
const borrower = signer;
const offer = await (0, utils_1.pda)([OFFER_TAG, borrower.toBuffer(), nftMint.toBuffer()], exports.programId);
const nftMetadata = await mpl_token_metadata_1.Metadata.getPDA(nftMint);
const edition = await mpl_token_metadata_1.Edition.getPDA(nftMint);
try {
const tx = await exports.program.rpc.setOffer({
accounts: {
borrower,
globalState,
offer,
nftMint,
nftMetadata,
edition,
userVault: borrowerNftVault,
metadataProgram: global_config_1.TOKEN_META_PID,
...utils_1.defaults
},
signers
});
// eslint-disable-next-line no-console
console.log('setOffer tx = ', tx);
}
catch (e) {
console.log(e);
}
};
exports.setLoanOffer = setLoanOffer;
const cancelLoanOffer = async (nftMint, signer = exports.programProvider.wallet.publicKey, signers = []) => {
const borrower = signer;
const offer = await (0, utils_1.pda)([OFFER_TAG, borrower.toBuffer(), nftMint.toBuffer()], exports.programId);
let borrowerNftVault = await (0, exports.checkWalletATA)(nftMint.toBase58(), exports.programProvider.connection, borrower);
const preInstructions = [];
if (!borrowerNftVault) {
borrowerNftVault = await (0, exports.addTokenAccountInstruction)(nftMint, borrower, preInstructions, signer, signers);
}
const edition = await mpl_token_metadata_1.Edition.getPDA(nftMint);
try {
const tx = await exports.program.rpc.cancelOffer({
accounts: {
borrower,
offer,
nftMint,
edition,
userVault: borrowerNftVault,
metadataProgram: global_config_1.TOKEN_META_PID,
...utils_1.defaults
},
preInstructions,
signers
});
// eslint-disable-next-line no-console
console.log('cancelOffer tx = ', tx);
}
catch (e) {
console.log(e);
}
};
exports.cancelLoanOffer = cancelLoanOffer;
const createLoanSubOffer = async (offerAmount, loanDuration, minRepaidNumerator, aprNumerator, nftMint, offerMint, signer = exports.programProvider.wallet.publicKey, signers = []) => {
if (offerMint.equals(spl_token_1.NATIVE_MINT)) {
offerMint = WSOL_MINT;
}
const globalState = await (0, utils_1.pda)([GLOBAL_STATE_TAG], exports.programId);
const borrower = signer;
const offer = await (0, utils_1.pda)([OFFER_TAG, borrower.toBuffer(), nftMint.toBuffer()], exports.programId);
const offerData = await exports.program.account.offer.fetch(offer);
const subOfferNumer = offerData.subOfferCount;
const subOffer = await (0, utils_1.pda)([SUB_OFFER_TAG, offer.toBuffer(), subOfferNumer.toArrayLike(Buffer, 'be', 8)], exports.programId);
const treasuryVault = await (0, utils_1.pda)([TREASURY_VAULT_TAG, offerMint.toBuffer()], exports.programId);
const globalStateData = await exports.program.account.globalState.fetch(globalState);
const treasuryWallet = globalStateData.treasuryWallet;
try {
const tx = await exports.program.rpc.setSubOffer(offerAmount, subOfferNumer, loanDuration, minRepaidNumerator, aprNumerator, {
accounts: {
borrower,
globalState,
offer,
subOffer,
offerMint,
treasuryWallet,
treasuryVault,
...utils_1.defaults
},
signers
});
// eslint-disable-next-line no-console
console.log('createSubOffer tx = ', tx);
}
catch (e) {
console.log(e);
}
};
exports.createLoanSubOffer = createLoanSubOffer;
const createLoanSubOfferByStaking = async (offerAmount, loanDuration, minRepaidNumerator, aprNumerator, nftMint, offerMint, signer = exports.programProvider.wallet.publicKey, signers = []) => {
if (offerMint.equals(spl_token_1.NATIVE_MINT)) {
offerMint = WSOL_MINT;
}
const globalState = await (0, utils_1.pda)([GLOBAL_STATE_TAG], exports.programId);
const borrower = signer;
const offer = await (0, utils_1.pda)([OFFER_TAG, borrower.toBuffer(), nftMint.toBuffer()], exports.programId);
const offerData = await exports.program.account.offer.fetch(offer);
const subOfferNumer = offerData.subOfferCount;
const subOffer = await (0, utils_1.pda)([SUB_OFFER_TAG, offer.toBuffer(), subOfferNumer.toArrayLike(Buffer, 'be', 8)], exports.programId);
const treasuryVault = await (0, utils_1.pda)([TREASURY_VAULT_TAG, offerMint.toBuffer()], exports.programId);
const globalStateData = await exports.program.account.globalState.fetch(globalState);
const stakingUser = await (0, utils_1.pda)([globalStateData.unlocStakingPoolId.toBuffer(), borrower.toBuffer()], globalStateData.unlocStakingPid);
const treasuryWallet = globalStateData.treasuryWallet;
try {
const tx = await exports.program.rpc.setSubOfferByStaking(offerAmount, subOfferNumer, loanDuration, minRepaidNumerator, aprNumerator, {
accounts: {
borrower,
globalState,
offer,
subOffer,
stakingUser,
offerMint,
treasuryWallet,
treasuryVault,
...utils_1.defaults
},
signers
});
// eslint-disable-next-line no-console
console.log('createSubOffer tx = ', tx);
}
catch (e) {
console.log(e);
}
};
exports.createLoanSubOfferByStaking = createLoanSubOfferByStaking;
const updateLoanSubOffer = async (offerAmount, loanDuration, minRepaidNumerator, aprNumerator, subOffer, signer = exports.programProvider.wallet.publicKey, signers = []) => {
const globalState = await (0, utils_1.pda)([GLOBAL_STATE_TAG], exports.programId);
const borrower = signer;
const subOfferData = await exports.program.account.subOffer.fetch(subOffer);
const offer = await (0, utils_1.pda)([OFFER_TAG, borrower.toBuffer(), subOfferData.nftMint.toBuffer()], exports.programId);
const subOfferNumer = subOfferData.subOfferNumber;
const offerMint = subOfferData.offerMint;
const treasuryVault = await (0, utils_1.pda)([TREASURY_VAULT_TAG, subOfferData.offerMint.toBuffer()], exports.programId);
const globalStateData = await exports.program.account.globalState.fetch(globalState);
const treasuryWallet = globalStateData.treasuryWallet;
try {
const tx = await exports.program.rpc.setSubOffer(offerAmount, subOfferNumer, loanDuration, minRepaidNumerator, aprNumerator, {
accounts: {
borrower,
globalState,
offer,
subOffer,
offerMint,
treasuryWallet,
treasuryVault,
...utils_1.defaults
},
signers
});
// eslint-disable-next-line no-console
console.log('updateSubOffer tx = ', tx);
}
catch (e) {
console.log(e);
}
};
exports.updateLoanSubOffer = updateLoanSubOffer;
const updateLoanSubOfferByStaking = async (offerAmount, loanDuration, minRepaidNumerator, aprNumerator, subOffer, signer = exports.programProvider.wallet.publicKey, signers = []) => {
const globalState = await (0, utils_1.pda)([GLOBAL_STATE_TAG], exports.programId);
const borrower = signer;
const subOfferData = await exports.program.account.subOffer.fetch(subOffer);
const offer = await (0, utils_1.pda)([OFFER_TAG, borrower.toBuffer(), subOfferData.nftMint.toBuffer()], exports.programId);
const subOfferNumer = subOfferData.subOfferNumber;
const offerMint = subOfferData.offerMint;
const treasuryVault = await (0, utils_1.pda)([TREASURY_VAULT_TAG, subOfferData.offerMint.toBuffer()], exports.programId);
const globalStateData = await exports.program.account.globalState.fetch(globalState);
const stakingUser = await (0, utils_1.pda)([globalStateData.unlocStakingPoolId.toBuffer(), borrower.toBuffer()], globalStateData.unlocStakingPid);
const treasuryWallet = globalStateData.treasuryWallet;
try {
const tx = await exports.program.rpc.setSubOfferByStaking(offerAmount, subOfferNumer, loanDuration, minRepaidNumerator, aprNumerator, {
accounts: {
borrower,
globalState,
offer,
subOffer,
stakingUser,
offerMint,
treasuryWallet,
treasuryVault,
...utils_1.defaults
},
signers
});
// eslint-disable-next-line no-console
console.log('updateSubOffer tx = ', tx);
}
catch (e) {
console.log(e);
}
};
exports.updateLoanSubOfferByStaking = updateLoanSubOfferByStaking;
const cancelLoanSubOffer = async (subOffer, signer = exports.programProvider.wallet.publicKey, signers = []) => {
const borrower = signer;
const subOfferData = await exports.program.account.subOffer.fetch(subOffer);
const offer = await (0, utils_1.pda)([OFFER_TAG, borrower.toBuffer(), subOfferData.nftMint.toBuffer()], exports.programId);
try {
const tx = await exports.program.rpc.cancelSubOffer({
accounts: {
borrower,
offer,
subOffer
},
signers
});
// eslint-disable-next-line no-console
console.log('cancelSubOffer tx = ', tx);
}
catch (e) {
console.log(e);
}
};
exports.cancelLoanSubOffer = cancelLoanSubOffer;
const acceptLoanOfferByVoting = async (subOffer, signer = exports.programProvider.wallet.publicKey, signers = []) => {
const lender = signer;
const subOfferData = await exports.program.account.subOffer.fetch(subOffer);
const offer = subOfferData.offer;
const offerMint = subOfferData.offerMint;
const offerData = await exports.program.account.offer.fetch(subOfferData.offer);
const borrower = offerData.borrower;
let borrowerOfferVault = await (0, exports.checkWalletATA)(offerMint.toBase58(), exports.programProvider.connection, borrower);
let lenderOfferVault = await (0, exports.checkWalletATA)(offerMint.toBase58(), exports.programProvider.connection, lender);
const preInstructions = [];
const postInstructions = [];
if (offerMint.equals(WSOL_MINT)) {
const treasuryVault = await (0, utils_1.pda)([TREASURY_VAULT_TAG, offerMint.toBuffer()], exports.programId);
lenderOfferVault = treasuryVault;
borrowerOfferVault = treasuryVault;
}
else {
if (!borrowerOfferVault) {
console.log("borrower doesn't have offer token account!");
borrowerOfferVault = await (0, exports.addTokenAccountInstruction)(offerMint, borrower, preInstructions, signer, signers);
}
if (!lenderOfferVault) {
console.log("lender doesn't have offer token!");
return;
}
}
const globalState = await (0, utils_1.pda)([GLOBAL_STATE_TAG], exports.programId);
const globalStateData = await exports.program.account.globalState.fetch(globalState);
const userReward = await (0, utils_1.pda)([USER_REWARD_TAG, lender.toBuffer(), borrower.toBuffer(), subOffer.toBuffer()], exports.programId);
const votingPid = globalStateData.votingPid;
const currentVotingKey = await (0, exports.getCurrentVotingKey)();
const votingItemKey = await (0, utils_1.pda)([voting_1.VOTING_ITEM_TAG, currentVotingKey.toBuffer(), offerData.collection.toBuffer()], votingPid);
try {
const tx = await exports.program.rpc.acceptOfferByVoting({
accounts: {
lender,
borrower,
globalState,
offer,
subOffer,
offerMint,
userReward,
voting: currentVotingKey,
votingItem: votingItemKey,
borrowerOfferVault,
lenderOfferVault,
...utils_1.defaults
},
preInstructions,
postInstructions,
signers
});
// eslint-disable-next-line no-console
console.log('acceptOffer tx = ', tx);
}
catch (e) {
console.log(e);
}
};
exports.acceptLoanOfferByVoting = acceptLoanOfferByVoting;
const acceptLoanOffer = async (subOffer, signer = exports.programProvider.wallet.publicKey, signers = []) => {
const lender = signer;
const subOfferData = await exports.program.account.subOffer.fetch(subOffer);
const offer = subOfferData.offer;
const offerMint = subOfferData.offerMint;
const offerData = await exports.program.account.offer.fetch(subOfferData.offer);
const borrower = offerData.borrower;
let borrowerOfferVault = await (0, exports.checkWalletATA)(offerMint.toBase58(), exports.programProvider.connection, borrower);
let lenderOfferVault = await (0, exports.checkWalletATA)(offerMint.toBase58(), exports.programProvider.connection, lender);
const preInstructions = [];
const postInstructions = [];
if (offerMint.equals(WSOL_MINT)) {
const treasuryVault = await (0, utils_1.pda)([TREASURY_VAULT_TAG, offerMint.toBuffer()], exports.programId);
lenderOfferVault = treasuryVault;
borrowerOfferVault = treasuryVault;
}
else {
if (!borrowerOfferVault) {
console.log("borrower doesn't have offer token account!");
borrowerOfferVault = await (0, exports.addTokenAccountInstruction)(offerMint, borrower, preInstructions, signer, signers);
}
if (!lenderOfferVault) {
console.log("lender doesn't have offer token!");
return;
}
}
const globalState = await (0, utils_1.pda)([GLOBAL_STATE_TAG], exports.programId);
const userReward = await (0, utils_1.pda)([USER_REWARD_TAG, lender.toBuffer(), borrower.toBuffer(), subOffer.toBuffer()], exports.programId);
try {
const tx = await exports.program.rpc.acceptOffer({
accounts: {
lender,
borrower,
globalState,
offer,
subOffer,
offerMint,
userReward,
borrowerOfferVault,
lenderOfferVault,
...utils_1.defaults
},
preInstructions,
postInstructions,
signers
});
// eslint-disable-next-line no-console
console.log('acceptOffer tx = ', tx);
}
catch (e) {
console.log(e);
}
};
exports.acceptLoanOffer = acceptLoanOffer;
const repayLoan = async (subOffer, signer = exports.programProvider.wallet.publicKey, signers = []) => {
const globalState = await (0, utils_1.pda)([GLOBAL_STATE_TAG], exports.programId);
const borrower = signer;
const globalStateData = await exports.program.account.globalState.fetch(globalState);
const treasuryWallet = globalStateData.treasuryWallet;
const subOfferData = await exports.program.account.subOffer.fetch(subOffer);
const offer = subOfferData.offer;
const lender = subOfferData.lender;
const offerData = await exports.program.account.offer.fetch(offer);
const offerMint = subOfferData.offerMint;
const nftMint = offerData.nftMint;
const treasuryVault = await (0, utils_1.pda)([TREASURY_VAULT_TAG, offerMint.toBuffer()], exports.programId);
let borrowerOfferVault = await (0, exports.checkWalletATA)(offerMint.toBase58(), exports.programProvider.connection, borrower);
let borrowerNftVault = await (0, exports.checkWalletATA)(nftMint.toBase58(), exports.programProvider.connection, borrower);
let lenderOfferVault = await (0, exports.checkWalletATA)(offerMint.toBase58(), exports.programProvider.connection, lender);
const preInstructions = [];
const postInstructions = [];
if (offerMint.equals(WSOL_MINT)) {
const treasuryVault = await (0, utils_1.pda)([TREASURY_VAULT_TAG, offerMint.toBuffer()], exports.programId);
lenderOfferVault = treasuryVault;
borrowerOfferVault = treasuryVault;
}
if (!borrowerOfferVault) {
console.log("borrower doesn't have offer token!");
return;
}
if (!borrowerNftVault) {
console.log("borrower doesn't have nft token token account!");
borrowerNftVault = await (0, exports.addTokenAccountInstruction)(nftMint, borrower, preInstructions, signer, signers);
}
if (!lenderOfferVault) {
console.log("lender doesn't have offer token account!", lender.toBase58());
lenderOfferVault = await (0, exports.addTokenAccountInstruction)(offerMint, lender, preInstructions, signer, signers);
}
const userReward = await (0, utils_1.pda)([USER_REWARD_TAG, lender.toBuffer(), borrower.toBuffer(), subOffer.toBuffer()], exports.programId);
const edition = await mpl_token_metadata_1.Edition.getPDA(nftMint);
try {
const tx = await exports.program.rpc.repayLoan({
accounts: {
borrower,
lender,
globalState,
treasuryWallet,
offer,
subOffer,
nftMint,
edition,
userReward,
borrowerNftVault,
lenderOfferVault,
borrowerOfferVault,
treasuryVault,
metadataProgram: global_config_1.TOKEN_META_PID,
...utils_1.defaults
},
preInstructions,
postInstructions,
signers
});
// eslint-disable-next-line no-console
console.log('repayLoan tx = ', tx);
}
catch (e) {
console.log(e);
}
};
exports.repayLoan = repayLoan;
const claimLoanCollateral = async (subOffer, signer = exports.programProvider.wallet.publicKey, signers = []) => {
const globalState = await (0, utils_1.pda)([GLOBAL_STATE_TAG], exports.programId);
const lender = signer;
const globalStateData = await exports.program.account.globalState.fetch(globalState);
const treasuryWallet = globalStateData.treasuryWallet;
const subOfferData = await exports.program.account.subOffer.fetch(subOffer);
const offer = subOfferData.offer;
const offerData = await exports.program.account.offer.fetch(offer);
const offerMint = subOfferData.offerMint;
const nftMint = offerData.nftMint;
const treasuryVault = await (0, utils_1.pda)([TREASURY_VAULT_TAG, offerMint.toBuffer()], exports.programId);
let borrowerNftVault = await (0, exports.checkWalletATA)(nftMint.toBase58(), exports.programProvider.connection, offerData.borrower);
let lenderNftVault = await (0, exports.checkWalletATA)(nftMint.toBase58(), exports.programProvider.connection, lender);
let lenderOfferVault = await (0, exports.checkWalletATA)(offerMint.toBase58(), exports.programProvider.connection, lender);
const preInstructions = [];
const postInstructions = [];
if (offerMint.equals(WSOL_MINT)) {
const treasuryVault = await (0, utils_1.pda)([TREASURY_VAULT_TAG, offerMint.toBuffer()], exports.programId);
lenderOfferVault = treasuryVault;
}
if (!lenderNftVault) {
console.log("lender doesn't have nft token token account!");
lenderNftVault = await (0, exports.addTokenAccountInstruction)(nftMint, lender, preInstructions, signer, signers);
}
if (!lenderOfferVault) {
console.log("lender doesn't have offer token account!", lender.toBase58());
lenderOfferVault = await (0, exports.addTokenAccountInstruction)(offerMint, lender, preInstructions, signer, signers);
}
const edition = await mpl_token_metadata_1.Edition.getPDA(nftMint);
try {
const tx = await exports.program.rpc.claimCollateral({
accounts: {
lender,
globalState,
treasuryWallet,
offer,
subOffer,
nftMint,
edition,
lenderNftVault,
borrowerNftVault,
lenderOfferVault,
treasuryVault,
metadataProgram: global_config_1.TOKEN_META_PID,
...utils_1.defaults
},
preInstructions,
postInstructions,
signers
});
// eslint-disable-next-line no-console
console.log('claimCollateral tx = ', tx);
}
catch (e) {
console.log(e);
}
};
exports.claimLoanCollateral = claimLoanCollateral;
// super owner can call this function
const claimExpiredCollateral = async (subOffer, signer = exports.programProvider.wallet.publicKey, signers = []) => {
const globalState = await (0, utils_1.pda)([GLOBAL_STATE_TAG], exports.programId);
const globalStateData = await exports.program.account.globalState.fetch(globalState);
const treasuryWallet = globalStateData.treasuryWallet;
const subOfferData = await exports.program.account.subOffer.fetch(subOffer);
const offer = subOfferData.offer;
const offerData = await exports.program.account.offer.fetch(offer);
const nftMint = offerData.nftMint;
let userNftVault = await (0, exports.checkWalletATA)(nftMint.toBase58(), exports.programProvider.connection, signer);
const preInstructions = [];
if (!userNftVault) {
userNftVault = await (0, exports.addTokenAccountInstruction)(nftMint, signer, preInstructions, signer, signers);
}
let borrowerNftVault = await (0, exports.checkWalletATA)(nftMint.toBase58(), exports.programProvider.connection, offerData.borrower);
const edition = await mpl_token_metadata_1.Edition.getPDA(nftMint);
try {
const tx = await exports.program.rpc.claimExpiredCollateral({
accounts: {
superOwner: signer,
globalState,
treasuryWallet,
offer,
subOffer,
nftMint,
edition,
userNftVault,
borrowerNftVault,
metadataProgram: global_config_1.TOKEN_META_PID,
...utils_1.defaults
},
preInstructions,
signers
});
// eslint-disable-next-line no-console
console.log('claimExpiredCollateral tx = ', tx);
}
catch (e) {
console.log(e);
}
};
exports.claimExpiredCollateral = claimExpiredCollateral;
var OfferState;
(function (OfferState) {
OfferState[OfferState["Proposed"] = 0] = "Proposed";
OfferState[OfferState["Accepted"] = 1] = "Accepted";
OfferState[OfferState["Expired"] = 2] = "Expired";
OfferState[OfferState["Fulfilled"] = 3] = "Fulfilled";
OfferState[OfferState["NFTClaimed"] = 4] = "NFTClaimed";
OfferState[OfferState["Canceled"] = 5] = "Canceled";
})(OfferState = exports.OfferState || (exports.OfferState = {}));
var SubOfferState;
(function (SubOfferState) {
SubOfferState[SubOfferState["Proposed"] = 0] = "Proposed";
SubOfferState[SubOfferState["Accepted"] = 1] = "Accepted";
SubOfferState[SubOfferState["Expired"] = 2] = "Expired";
SubOfferState[SubOfferState["Fulfilled"] = 3] = "Fulfilled";
SubOfferState[SubOfferState["LoanPaymentClaimed"] = 4] = "LoanPaymentClaimed";
SubOfferState[SubOfferState["Canceled"] = 5] = "Canceled";
})(SubOfferState = exports.SubOfferState || (exports.SubOfferState = {}));
const getLoanSubOffersKeysByState = async (state) => {
try {
const accountName = 'subOffer';
const data = await exports.programProvider.connection.getProgramAccounts(exports.programId, {
dataSlice: { offset: 0, length: 0 },
filters: [
{ memcmp: exports.program.account.subOffer.coder.accounts.memcmp(accountName) },
{ memcmp: { offset: utils_1.discriminatorLen + 96, bytes: bytes_1.bs58.encode(state) } } // add filters for nftMint, APR, Duration, Amount and this function will be glorious
]
});
return data.map((offer) => offer.pubkey);
}
catch (e) {
console.log(e);
}
};
exports.getLoanSubOffersKeysByState = getLoanSubOffersKeysByState;
const addTokenAccountInstruction = async (mint, owner, instructions, signer, signers, rent = 0) => {
const newKeypair = web3_js_1.Keypair.generate();
const rentForTokenAccount = await spl_token_1.Token.getMinBalanceRentForExemptAccount(exports.programProvider.connection);
instructions.push(web3_js_1.SystemProgram.createAccount({
fromPubkey: signer,
newAccountPubkey: newKeypair.publicKey,
lamports: rent > 0 ? rent : rentForTokenAccount,
space: exports.ACCOUNT_LAYOUT.span,
programId: spl_token_1.TOKEN_PROGRAM_ID
}));
const instruction = spl_token_1.Token.createInitAccountInstruction(spl_token_1.TOKEN_PROGRAM_ID, mint, newKeypair.publicKey, owner);
instructions.push(instruction);
signers.push(newKeypair);
return newKeypair.publicKey;
};
exports.addTokenAccountInstruction = addTokenAccountInstruction;
const checkWalletATA = async (mint, connection = exports.programProvider.connection, walletPubkey = exports.programProvider.wallet.publicKey) => {
const parsedTokenAccounts = await connection.getParsedTokenAccountsByOwner(walletPubkey, {
programId: spl_token_1.TOKEN_PROGRAM_ID
}, 'confirmed');
let result = null;
let maxAmount = 0;
parsedTokenAccounts.value.forEach(async (tokenAccountInfo) => {
const tokenAccountPubkey = tokenAccountInfo.pubkey;
const parsedInfo = tokenAccountInfo.account.data.parsed.info;
const mintAddress = parsedInfo.mint;
const amount = parsedInfo.tokenAmount.uiAmount;
if (mintAddress === mint && amount >= maxAmount) {
result = tokenAccountPubkey;
maxAmount = amount;
}
});
return result;
};
exports.checkWalletATA = checkWalletATA;
const logObject = (title, obj) => {
console.log(title, obj);
};
exports.logObject = logObject;
const getOfferBalance = async (subOffer, connection = exports.programProvider.connection, walletPubkey = exports.programProvider.wallet.publicKey) => {
try {
const tokenAccount = await (0, utils_1.pda)([OFFER_VAULT_TAG, subOffer.toBuffer()], exports.programId);
const balance = (await connection.getTokenAccountBalance(tokenAccount)).value.uiAmount;
return balance;
}
catch (e) {
console.log(e);
}
return 0;
};
exports.getOfferBalance = getOfferBalance;
// --------------------utilities---------------------
class MultipleNFT {
constructor(keys) {
this.metadatas = [];
this.mints = keys;
}
async initialize() {
if (this.metadatas.length == 0) {
const metadataPDAs = [];
for (let i = 0; i < this.mints.length; i++) {
const metadataPDA = await mpl_token_metadata_1.Metadata.getPDA(this.mints[i]);
metadataPDAs.push(metadataPDA);
}
let i = 0;
const metaInfos = await mpl_token_metadata_1.Metadata.getInfos(exports.programProvider.connection, metadataPDAs);
metaInfos.forEach((value, key, map) => {
const metadata = mpl_token_metadata_1.MetadataData.deserialize(value.data);
const nftMetadata = new NFTMetadata(this.mints[i], metadataPDAs[i], metadata);
this.metadatas.push(nftMetadata);
i++;
});
}
}
getNftMeta(mint) {
for (let i = 0; i < this.metadatas.length; i++) {
if (this.metadatas[i].mint === mint.toBase58()) {
return this.metadatas[i];
}
}
return null;
}
async initArweavedata() {
for (let i = 0; i < this.metadatas.length; i++) {
await this.metadatas[i].getAreaveMetadata();
}
}
}
exports.MultipleNFT = MultipleNFT;
class NFTMetadata {
constructor(mint, metadataPDA, onChainMetadata) {
this.mint = '';
this.metadataPDA = '';
this.onChainMetadata = null;
this.arweaveMetadata = null;
this.masterEdition = null;
this.mint = mint.toBase58();
this.metadataPDA = metadataPDA.toBase58();
this.onChainMetadata = onChainMetadata;
}
async getAreaveMetadata() {
if (this.arweaveMetadata === null) {
try {
const arweaveData = await axios_1.default.get(this.onChainMetadata.data.uri);
if (arweaveData) {
this.arweaveMetadata = arweaveData.data;
}
}
catch (e) {
// eslint-disable-next-line no-console
console.log(e);
}
}
return this.arweaveMetadata;
}
currentAreaveMetadata() {
return this.arweaveMetadata;
}
async getMasterEdition() {
if (this.arweaveMetadata === null) {
const masterEditionPDA = await mpl_token_metadata_1.Edition.getPDA(new web3_js_1.PublicKey(this.mint));
const editionAccountInfo = await exports.programProvider.connection.getAccountInfo(masterEditionPDA);
if (editionAccountInfo) {
const key = editionAccountInfo === null || editionAccountInfo === void 0 ? void 0 : editionAccountInfo.data[0];
let masterEditionData;
let data;
switch (key) {
case mpl_token_metadata_1.MetadataKey.MasterEditionV1:
case mpl_token_metadata_1.MetadataKey.MasterEditionV2:
;
({ data } = new mpl_token_metadata_1.MasterEdition(masterEditionPDA, editionAccountInfo));
masterEditionData = data;
break;
default:
masterEditionData = undefined;
break;
}
this.masterEdition = {
masterEditionPDA: masterEditionPDA.toString(),
masterEditionData
};
}
}
return this.masterEdition;
}
}
exports.NFTMetadata = NFTMetadata;
exports.ACCOUNT_LAYOUT = (0, borsh_1.struct)([
(0, borsh_1.publicKey)('mint'),
(0, borsh_1.publicKey)('owner'),
(0, borsh_1.u64)('amount'),
(0, borsh_1.u32)('delegateOption'),
(0, borsh_1.publicKey)('delegate'),
(0, borsh_1.u8)('state'),
(0, borsh_1.u32)('isNativeOption'),
(0, borsh_1.u64)('isNative'),
(0, borsh_1.u64)('delegatedAmount'),
(0, borsh_1.u32)('closeAuthorityOption'),
(0, borsh_1.publicKey)('closeAuthority')
]);
exports.MINT_LAYOUT = (0, borsh_1.struct)([
(0, borsh_1.u32)('mintAuthorityOption'),
(0, borsh_1.publicKey)('mintAuthority'),
(0, borsh_1.u64)('supply'),
(0, borsh_1.u8)('decimals'),
(0, borsh_1.bool)('initialized'),
(0, borsh_1.u32)('freezeAuthorityOption'),
(0, borsh_1.publicKey)('freezeAuthority')
]);
//# sourceMappingURL=index.js.map