@frakters/nft-lending-v2
Version:
Client library for interacting with nft lenging solana program
356 lines (355 loc) • 15.7 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getFilteredTokenAccountsByOwner = exports.getMintDecimals = exports.mergeTransactions = exports.sendTransaction = exports.signTransaction = exports.getMultipleAccounts = exports.getFilteredProgramAccountsAmmOrMarketCache = exports.getFilteredProgramAccounts = exports.createAssociatedTokenAccount = exports.createProgramAccountIfNotExist = exports.createAtaSolIfNotExistAndWrap = exports.createAssociatedTokenAccountIfNotExist = exports.createTokenAccountIfNotExist = exports.findAssociatedStakeInfoAddress = exports.findAssociatedTokenAddress = exports.createAssociatedId = exports.createAmmAuthority = exports.findProgramAddress = exports.commitment = exports.web3Config = void 0;
const token_instructions_1 = require("@project-serum/serum/lib/token-instructions");
// @ts-ignore without ts ignore, yarn build will failed
const spl_token_1 = require("@solana/spl-token");
const web3_js_1 = require("@solana/web3.js");
const ids_1 = require("./ids");
const layouts_1 = require("./layouts");
const tokens_1 = require("./tokens");
exports.web3Config = {
strategy: 'speed',
rpcs: [
{ url: 'https://api.devnet.solana.com', weight: 10 },
{ url: 'https://api.devnet.solana.com', weight: 10 },
{ url: 'https://api.devnet.solana.com', weight: 10 },
{ url: 'https://api.devnet.solana.com', weight: 10 },
{ url: 'https://api.devnet.solana.com', weight: 50 },
{ url: 'https://api.mainnet-beta.solana.com', weight: 10 },
],
};
// export const commitment: Commitment = 'processed'
exports.commitment = 'confirmed';
// export const commitment: Commitment = 'finalized'
function findProgramAddress(seeds, programId) {
return __awaiter(this, void 0, void 0, function* () {
const [publicKey, nonce] = yield web3_js_1.PublicKey.findProgramAddress(seeds, programId);
return { publicKey, nonce };
});
}
exports.findProgramAddress = findProgramAddress;
function createAmmAuthority(programId) {
return __awaiter(this, void 0, void 0, function* () {
return yield findProgramAddress([new Uint8Array(Buffer.from('amm authority'.replace('\u00A0', ' '), 'utf-8'))], programId);
});
}
exports.createAmmAuthority = createAmmAuthority;
function createAssociatedId(infoId, marketAddress, bufferKey) {
return __awaiter(this, void 0, void 0, function* () {
const { publicKey } = yield findProgramAddress([infoId.toBuffer(), marketAddress.toBuffer(), Buffer.from(bufferKey)], infoId);
return publicKey;
});
}
exports.createAssociatedId = createAssociatedId;
function findAssociatedTokenAddress(walletAddress, tokenMintAddress) {
return __awaiter(this, void 0, void 0, function* () {
const { publicKey } = yield findProgramAddress([walletAddress.toBuffer(), ids_1.TOKEN_PROGRAM_ID.toBuffer(), tokenMintAddress.toBuffer()], ids_1.ASSOCIATED_TOKEN_PROGRAM_ID);
return publicKey;
});
}
exports.findAssociatedTokenAddress = findAssociatedTokenAddress;
function findAssociatedStakeInfoAddress(poolId, walletAddress, programId) {
return __awaiter(this, void 0, void 0, function* () {
const { publicKey } = yield findProgramAddress([poolId.toBuffer(), walletAddress.toBuffer(), Buffer.from('staker_info_v2_associated_seed')], programId);
return publicKey;
});
}
exports.findAssociatedStakeInfoAddress = findAssociatedStakeInfoAddress;
function createTokenAccountIfNotExist(connection, account, owner, mintAddress, lamports, transaction, signer) {
return __awaiter(this, void 0, void 0, function* () {
let publicKey;
if (account) {
publicKey = new web3_js_1.PublicKey(account);
}
else {
publicKey = yield createProgramAccountIfNotExist(connection, account, owner, ids_1.TOKEN_PROGRAM_ID, lamports, layouts_1.ACCOUNT_LAYOUT, transaction, signer);
transaction.add(token_instructions_1.initializeAccount({
account: publicKey,
mint: new web3_js_1.PublicKey(mintAddress),
owner,
}));
}
return publicKey;
});
}
exports.createTokenAccountIfNotExist = createTokenAccountIfNotExist;
function createAssociatedTokenAccountIfNotExist(account, owner, mintAddress, transaction, atas = []) {
return __awaiter(this, void 0, void 0, function* () {
let publicKey;
if (account) {
publicKey = new web3_js_1.PublicKey(account);
}
const mint = new web3_js_1.PublicKey(mintAddress);
// @ts-ignore without ts ignore, yarn build will failed
const ata = yield spl_token_1.Token.getAssociatedTokenAddress(ids_1.ASSOCIATED_TOKEN_PROGRAM_ID, ids_1.TOKEN_PROGRAM_ID, mint, owner, true);
if ((!publicKey || !ata.equals(publicKey)) && !atas.includes(ata.toBase58())) {
transaction.add(spl_token_1.Token.createAssociatedTokenAccountInstruction(ids_1.ASSOCIATED_TOKEN_PROGRAM_ID, ids_1.TOKEN_PROGRAM_ID, mint, ata, owner, owner));
atas.push(ata.toBase58());
}
return ata;
});
}
exports.createAssociatedTokenAccountIfNotExist = createAssociatedTokenAccountIfNotExist;
function createAtaSolIfNotExistAndWrap(connection, account, owner, transaction, signers, amount) {
return __awaiter(this, void 0, void 0, function* () {
let publicKey;
if (account) {
publicKey = new web3_js_1.PublicKey(account);
}
const mint = new web3_js_1.PublicKey(tokens_1.TOKENS.WSOL.mintAddress);
// @ts-ignore without ts ignore, yarn build will failed
const ata = yield spl_token_1.Token.getAssociatedTokenAddress(ids_1.ASSOCIATED_TOKEN_PROGRAM_ID, ids_1.TOKEN_PROGRAM_ID, mint, owner, true);
if (!publicKey) {
const rent = yield spl_token_1.Token.getMinBalanceRentForExemptAccount(connection);
transaction.add(web3_js_1.SystemProgram.transfer({ fromPubkey: owner, toPubkey: ata, lamports: amount + rent }), spl_token_1.Token.createAssociatedTokenAccountInstruction(ids_1.ASSOCIATED_TOKEN_PROGRAM_ID, ids_1.TOKEN_PROGRAM_ID, mint, ata, owner, owner));
}
else {
const rent = yield spl_token_1.Token.getMinBalanceRentForExemptAccount(connection);
const wsol = yield createTokenAccountIfNotExist(connection, null, owner, tokens_1.TOKENS.WSOL.mintAddress, amount + rent, transaction, signers);
transaction.add(spl_token_1.Token.createTransferInstruction(ids_1.TOKEN_PROGRAM_ID, wsol, ata, owner, [], amount), spl_token_1.Token.createCloseAccountInstruction(ids_1.TOKEN_PROGRAM_ID, wsol, owner, owner, []));
}
});
}
exports.createAtaSolIfNotExistAndWrap = createAtaSolIfNotExistAndWrap;
function createProgramAccountIfNotExist(connection, account, owner, programId, lamports, layout, transaction, signer) {
return __awaiter(this, void 0, void 0, function* () {
let publicKey;
if (account) {
publicKey = new web3_js_1.PublicKey(account);
}
else {
const newAccount = new web3_js_1.Account();
publicKey = newAccount.publicKey;
transaction.add(web3_js_1.SystemProgram.createAccount({
fromPubkey: owner,
newAccountPubkey: publicKey,
lamports: lamports !== null && lamports !== void 0 ? lamports : (yield connection.getMinimumBalanceForRentExemption(layout.span)),
space: layout.span,
programId,
}));
signer.push(newAccount);
}
return publicKey;
});
}
exports.createProgramAccountIfNotExist = createProgramAccountIfNotExist;
function createAssociatedTokenAccount(tokenMintAddress, owner, transaction) {
return __awaiter(this, void 0, void 0, function* () {
const associatedTokenAddress = yield findAssociatedTokenAddress(owner, tokenMintAddress);
const keys = [
{
pubkey: owner,
isSigner: true,
isWritable: false,
},
{
pubkey: associatedTokenAddress,
isSigner: false,
isWritable: true,
},
{
pubkey: owner,
isSigner: false,
isWritable: false,
},
{
pubkey: tokenMintAddress,
isSigner: false,
isWritable: false,
},
{
pubkey: ids_1.SYSTEM_PROGRAM_ID,
isSigner: false,
isWritable: false,
},
{
pubkey: ids_1.TOKEN_PROGRAM_ID,
isSigner: false,
isWritable: false,
},
{
pubkey: ids_1.RENT_PROGRAM_ID,
isSigner: false,
isWritable: false,
},
];
transaction.add(new web3_js_1.TransactionInstruction({
keys,
programId: ids_1.ASSOCIATED_TOKEN_PROGRAM_ID,
data: Buffer.from([]),
}));
return associatedTokenAddress;
});
}
exports.createAssociatedTokenAccount = createAssociatedTokenAccount;
function getFilteredProgramAccounts(connection, programId, filters) {
return __awaiter(this, void 0, void 0, function* () {
// @ts-ignore
const resp = yield connection._rpcRequest('getProgramAccounts', [
programId.toBase58(),
{
commitment: connection.commitment,
filters,
encoding: 'base64',
},
]);
if (resp.error) {
throw new Error(resp.error.message);
}
// @ts-ignore
return resp.result.map(({ pubkey, account: { data, executable, owner, lamports } }) => ({
publicKey: new web3_js_1.PublicKey(pubkey),
accountInfo: {
data: Buffer.from(data[0], 'base64'),
executable,
owner: new web3_js_1.PublicKey(owner),
lamports,
},
}));
});
}
exports.getFilteredProgramAccounts = getFilteredProgramAccounts;
function getFilteredProgramAccountsAmmOrMarketCache(cacheName, connection, programId, filters) {
return __awaiter(this, void 0, void 0, function* () {
try {
if (!cacheName) {
throw new Error('cacheName error');
}
const resp = yield (yield fetch('https://api.raydium.io/cache/rpc/' + cacheName)).json();
if (resp.error) {
throw new Error(resp.error.message);
}
// @ts-ignore
return resp.result.map(({ pubkey, account: { data, executable, owner, lamports } }) => ({
publicKey: new web3_js_1.PublicKey(pubkey),
accountInfo: {
data: Buffer.from(data[0], 'base64'),
executable,
owner: new web3_js_1.PublicKey(owner),
lamports,
},
}));
}
catch (e) {
return getFilteredProgramAccounts(connection, programId, filters);
}
});
}
exports.getFilteredProgramAccountsAmmOrMarketCache = getFilteredProgramAccountsAmmOrMarketCache;
// getMultipleAccounts
function getMultipleAccounts(connection, publicKeys, commitment) {
return __awaiter(this, void 0, void 0, function* () {
const keys = [];
let tempKeys = [];
publicKeys.forEach((k) => {
if (tempKeys.length >= 100) {
keys.push(tempKeys);
tempKeys = [];
}
tempKeys.push(k);
});
if (tempKeys.length > 0) {
keys.push(tempKeys);
}
const accounts = [];
const resArray = {};
yield Promise.all(keys.map((key, index) => __awaiter(this, void 0, void 0, function* () {
const res = yield connection.getMultipleAccountsInfo(key, commitment);
resArray[index] = res;
})));
Object.keys(resArray)
.sort((a, b) => parseInt(a) - parseInt(b))
.forEach((itemIndex) => {
const res = resArray[parseInt(itemIndex)];
for (const account of res) {
accounts.push(account);
}
});
return accounts.map((account, idx) => {
if (account === null) {
return null;
}
return {
publicKey: publicKeys[idx],
account,
};
});
});
}
exports.getMultipleAccounts = getMultipleAccounts;
// transaction
function signTransaction(connection, wallet, transaction, signers = []) {
return __awaiter(this, void 0, void 0, function* () {
transaction.recentBlockhash = (yield connection.getRecentBlockhash()).blockhash;
transaction.setSigners(wallet.publicKey, ...signers.map((s) => s.publicKey));
if (signers.length > 0) {
transaction.partialSign(...signers);
}
return yield wallet.signTransaction(transaction);
});
}
exports.signTransaction = signTransaction;
function sendTransaction(connection, wallet, transaction, signers = []) {
return __awaiter(this, void 0, void 0, function* () {
const txid = yield wallet.sendTransaction(transaction, connection, {
signers,
skipPreflight: true,
preflightCommitment: exports.commitment,
});
return txid;
});
}
exports.sendTransaction = sendTransaction;
function mergeTransactions(transactions) {
const transaction = new web3_js_1.Transaction();
transactions
.filter((t) => t !== undefined)
.forEach((t) => {
transaction.add(t);
});
return transaction;
}
exports.mergeTransactions = mergeTransactions;
function throwIfNull(value, message = 'account not found') {
if (value === null) {
throw new Error(message);
}
return value;
}
function getMintDecimals(connection, mint) {
return __awaiter(this, void 0, void 0, function* () {
const { data } = throwIfNull(yield connection.getAccountInfo(mint), 'mint not found');
const { decimals } = layouts_1.MINT_LAYOUT.decode(data);
return decimals;
});
}
exports.getMintDecimals = getMintDecimals;
function getFilteredTokenAccountsByOwner(connection, programId, mint) {
return __awaiter(this, void 0, void 0, function* () {
// @ts-ignore
const resp = yield connection._rpcRequest('getTokenAccountsByOwner', [
programId.toBase58(),
{
mint: mint.toBase58(),
},
{
encoding: 'jsonParsed',
},
]);
if (resp.error) {
throw new Error(resp.error.message);
}
return resp.result;
});
}
exports.getFilteredTokenAccountsByOwner = getFilteredTokenAccountsByOwner;