UNPKG

@kamino-finance/klend-sdk

Version:

Typescript SDK for interacting with the Kamino Lending (klend) protocol

234 lines 9.85 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getComputeBudgetAndPriorityFeeIxs = exports.getLookupTableAccount = exports.buildVersionedTransactionSync = exports.buildVersionedTransaction = void 0; exports.buildAndSendTxnWithLogs = buildAndSendTxnWithLogs; exports.buildAndSendTxn = buildAndSendTxn; exports.sendAndConfirmVersionedTransaction = sendAndConfirmVersionedTransaction; exports.simulateTxn = simulateTxn; exports.buildComputeBudgetIx = buildComputeBudgetIx; exports.sendTransactionV0 = sendTransactionV0; exports.simulateTransactionV0 = simulateTransactionV0; exports.getLookupTableAccountsFromAddresses = getLookupTableAccountsFromAddresses; exports.getLookupTableAccounts = getLookupTableAccounts; exports.notEmpty = notEmpty; exports.uniqueAccountsWithProgramIds = uniqueAccountsWithProgramIds; exports.removeBudgetIxs = removeBudgetIxs; const web3_js_1 = require("@solana/web3.js"); const errors_1 = require("../idl_codegen/errors"); const utils_1 = require("../classes/utils"); const kliquidity_sdk_1 = require("@kamino-finance/kliquidity-sdk"); const pubkey_1 = require("./pubkey"); async function buildAndSendTxnWithLogs(c, tx, owner, signers, withLogsIfSuccess = false, withDescription = '', throwOnError = false // TODO(error-surfacing): the "recovery" logic is broken/outdated + the "hide error" behavior seems wrong in general - migrate to "just throw" ) { tx.sign([owner, ...signers]); try { const sig = await sendAndConfirmVersionedTransaction(c, tx, 'confirmed', { preflightCommitment: 'processed', }); console.log('Transaction Hash:', withDescription, sig); if (withLogsIfSuccess) { await (0, utils_1.sleep)(1000); const res = await c.getTransaction(sig, { commitment: 'confirmed', maxSupportedTransactionVersion: 6, }); console.log('Transaction Logs:\n', res?.meta?.logMessages); } return sig; } catch (e) { if (throwOnError) { throw e; } console.log(e); process.stdout.write(e.logs.toString()); const sig = e.toString().split(' failed ')[0].split('Transaction ')[1]; const res = await c.getTransaction(sig, { commitment: 'confirmed', maxSupportedTransactionVersion: 6, }); console.log('Txn', res.meta.logMessages); return sig; } } async function buildAndSendTxn(c, owner, ixs, signers, lutAddresses = [], description = '') { const tx = await (0, exports.buildVersionedTransaction)(c, owner.publicKey, ixs, lutAddresses); return await buildAndSendTxnWithLogs(c, tx, owner, signers, true, description); } async function sendAndConfirmVersionedTransaction(c, tx, commitment = 'confirmed', sendTransactionOptions = { preflightCommitment: 'processed' }) { const defaultOptions = { skipPreflight: true }; const txId = await c.sendTransaction(tx, { ...defaultOptions, ...sendTransactionOptions }); const latestBlockHash = await c.getLatestBlockhash('finalized'); const t = await c.confirmTransaction({ blockhash: latestBlockHash.blockhash, lastValidBlockHeight: latestBlockHash.lastValidBlockHeight, signature: txId, }, commitment); if (t.value && t.value.err) { const txDetails = await c.getTransaction(txId, { maxSupportedTransactionVersion: 0, commitment: 'confirmed', }); if (txDetails) { throw { err: txDetails.meta?.err, logs: txDetails.meta?.logMessages || [] }; } throw t.value.err; } return txId; } async function simulateTxn(c, tx, owner, signers) { const { blockhash } = await c.getLatestBlockhash(); tx.recentBlockhash = blockhash; tx.feePayer = owner.publicKey; try { const simulation = await c.simulateTransaction(tx, [owner, ...signers]); console.log('Transaction Hash:', simulation); } catch (e) { console.log(e); process.stdout.write(e.logs.toString()); const sig = e.toString().split(' failed ')[0].split('Transaction ')[1]; const res = await c.getTransaction(sig, { commitment: 'confirmed', }); console.log('Txn', res.meta.logMessages); return sig; } } function buildComputeBudgetIx(units) { return web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({ units }); } /** * Send a transaction with optional address lookup tables * Translates anchor errors into anchor error types * @param connection * @param payer * @param instructions * @param lookupTables */ async function sendTransactionV0(connection, payer, instructions, lookupTables = undefined, options) { const recentBlockhash = (await connection.getLatestBlockhash()).blockhash; const messageV0 = new web3_js_1.TransactionMessage({ payerKey: payer.publicKey, recentBlockhash, instructions, }).compileToV0Message(lookupTables); const tx = new web3_js_1.VersionedTransaction(messageV0); tx.sign([payer]); try { return await connection.sendTransaction(tx, options); } catch (err) { throw (0, errors_1.fromTxError)(err) ?? err; } } async function simulateTransactionV0(connection, payer, instructions, lookupTables = undefined) { const recentBlockhash = (await connection.getLatestBlockhash()).blockhash; const messageV0 = new web3_js_1.TransactionMessage({ payerKey: payer.publicKey, recentBlockhash, instructions, }).compileToV0Message(lookupTables); const tx = new web3_js_1.VersionedTransaction(messageV0); tx.sign([payer]); try { return await connection.simulateTransaction(tx); } catch (err) { throw (0, errors_1.fromTxError)(err) ?? err; } } const buildVersionedTransaction = async (connection, payer, instructions, lookupTables = []) => { const blockhash = await connection.getLatestBlockhash('confirmed').then((res) => res.blockhash); const lookupTablesAccounts = await Promise.all(lookupTables.map((address) => { return (0, exports.getLookupTableAccount)(connection, address); })); const messageV0 = new web3_js_1.TransactionMessage({ payerKey: payer, recentBlockhash: blockhash, instructions, }).compileToV0Message(lookupTablesAccounts.filter(notEmpty)); return new web3_js_1.VersionedTransaction(messageV0); }; exports.buildVersionedTransaction = buildVersionedTransaction; async function getLookupTableAccountsFromAddresses(connection, addresses) { const lookupTablesAccounts = await Promise.all(addresses.map((address) => { return (0, exports.getLookupTableAccount)(connection, address); })); return lookupTablesAccounts.filter((account) => account !== null); } const buildVersionedTransactionSync = (payer, instructions, blockhash, lookupTables = []) => { const messageV0 = new web3_js_1.TransactionMessage({ payerKey: payer, recentBlockhash: blockhash, instructions, }).compileToV0Message(lookupTables.filter(notEmpty)); return new web3_js_1.VersionedTransaction(messageV0); }; exports.buildVersionedTransactionSync = buildVersionedTransactionSync; const getLookupTableAccount = async (connection, address) => { return connection.getAddressLookupTable(address).then((res) => res.value); }; exports.getLookupTableAccount = getLookupTableAccount; async function getLookupTableAccounts(connection, addresses) { const lookupTableAccounts = []; const accountInfos = await (0, kliquidity_sdk_1.batchFetch)(addresses, (batch) => connection.getMultipleAccountsInfo(batch)); for (let i = 0; i < addresses.length; i++) { const info = accountInfos[i]; if (!info) { throw new Error(`Lookup table ${addresses[i]} is not found`); } lookupTableAccounts.push(new web3_js_1.AddressLookupTableAccount({ key: addresses[i], state: web3_js_1.AddressLookupTableAccount.deserialize(info.data), })); } return lookupTableAccounts; } const getComputeBudgetAndPriorityFeeIxs = (units, priorityFeeLamports) => { const ixs = []; ixs.push(web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({ units })); if (priorityFeeLamports && priorityFeeLamports.gt(0)) { const unitPrice = priorityFeeLamports.mul(10 ** 6).div(units); ixs.push(web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({ microLamports: BigInt(unitPrice.floor().toString()) })); } return ixs; }; exports.getComputeBudgetAndPriorityFeeIxs = getComputeBudgetAndPriorityFeeIxs; // filters null values from array and make typescript happy function notEmpty(value) { if (value === null || value === undefined) { return false; } // // eslint-disable-next-line no-unused-vars,@typescript-eslint/no-unused-vars const testDummy = value; return true; } function uniqueAccountsWithProgramIds(ixs, addressLookupTables = []) { let luts; if (addressLookupTables.length > 0 && addressLookupTables[0] instanceof web3_js_1.AddressLookupTableAccount) { luts = addressLookupTables.map((lut) => lut.key); } else { luts = addressLookupTables; } const uniqueAccounts = new pubkey_1.PublicKeySet(luts); ixs.forEach((ix) => { uniqueAccounts.add(ix.programId); ix.keys.forEach((key) => { uniqueAccounts.add(key.pubkey); }); }); return uniqueAccounts.toArray(); } function removeBudgetIxs(ixs) { return ixs.filter((ix) => { const { programId } = ix; if (programId.equals(web3_js_1.ComputeBudgetProgram.programId)) { return false; } return true; }); } //# sourceMappingURL=instruction.js.map