Skip to content

Commit

Permalink
Add kamino lending
Browse files Browse the repository at this point in the history
  • Loading branch information
peroxy committed Nov 10, 2023
1 parent 3b26c8c commit 586dfe5
Show file tree
Hide file tree
Showing 3 changed files with 3,988 additions and 1 deletion.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
"license": "ISC",
"dependencies": {
"@defillama/sdk": "latest",
"@project-serum/anchor": "^0.25.0",
"@coral-xyz/borsh": "^0.29.0",
"@project-serum/anchor": "^0.26.0",
"@solana/web3.js": "^1.36.0",
"@solendprotocol/solend-sdk": "^0.6.2",
"@supercharge/promise-pool": "^2.1.0",
Expand Down
71 changes: 71 additions & 0 deletions projects/kamino-lending/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
const { PublicKey, Keypair } = require('@solana/web3.js');
const { getConnection, sumTokens } = require('../helper/solana');
const { Program } = require('@project-serum/anchor');
const kaminoIdl = require('./kamino-lending-idl.json');
const { Scope } = require('@hubbleprotocol/scope-sdk');
const { Token, TOKEN_PROGRAM_ID } = require('@solana/spl-token');

async function tvl() {
const connection = getConnection();
const programId = new PublicKey('KLend2g3cP87fffoy8q1mQqGKjrxjC8boSyAYavgmjD');
const markets = ['7u3HeHxYDLhnCoErrtycNokbQYbWGzLs6JSDqGAv5PfF'];
const lendingMarketAuthSeed = 'lma';
const scope = new Scope('mainnet-beta', connection);
const oraclePrices = await scope.getOraclePrices();
const tokensAndOwners = [];
const ktokens = {};

const kaminoLendProgram = new Program(kaminoIdl, programId, { connection, publicKey: PublicKey.unique() });
let tvl = 0;
for (const market of markets) {
const reserves = await kaminoLendProgram.account.reserve.all([
{ dataSize: 8624 },
{ memcmp: { offset: 32, bytes: market } },
]);

for (const reserveData of reserves) {
const reserve = reserveData.account;
if (
ktokens[reserve.liquidity.mintPubkey] ||
(await isKToken(new PublicKey(reserve.liquidity.mintPubkey), connection))
) {
ktokens[reserve.liquidity.mintPubkey] = true;
const liq = Number(reserve.liquidity.availableAmount.toString()) / 10 ** Number(reserve.liquidity.mintDecimals);
const oracle = reserve.config.tokenInfo.scopeConfiguration.priceFeed;
const chain = reserve.config.tokenInfo.scopeConfiguration.priceChain;
if (oracle && chain && Scope.isScopeChainValid(chain)) {
const price = await scope.getPriceFromChain(chain, oraclePrices);
tvl += liq * price.toNumber();
}
} else {
ktokens[reserve.liquidity.mintPubkey] = false;
const [authority] = PublicKey.findProgramAddressSync(
[Buffer.from(lendingMarketAuthSeed), new PublicKey(market).toBuffer()],
programId
);
tokensAndOwners.push([reserve.liquidity.mintPubkey, authority]);
}
}
}
return { tether: tvl, ...(await sumTokens(tokensAndOwners)) };
}

async function isKToken(mint, connection) {
const mintAcc = new Token(connection, mint, TOKEN_PROGRAM_ID, Keypair.generate());
const mintInfo = await mintAcc.getMintInfo();
const KAMINO_PROGRAM_ID = new PublicKey('6LtLpnUFNByNXLyCoK9wA2MykKAmQNZKBdY8s47dehDc');
const [expectedMintAuthority] = PublicKey.findProgramAddressSync(
[Buffer.from('authority'), mint.toBuffer()],
KAMINO_PROGRAM_ID
);
return mintInfo.mintAuthority !== null && mintInfo.mintAuthority.equals(expectedMintAuthority);
}

module.exports = {
timetravel: false,
solana: {
tvl,
},
methodology:
'TVL consists of deposits made to the protocol and like other lending protocols, borrowed tokens are not counted.',
};
Loading

0 comments on commit 586dfe5

Please sign in to comment.