From ecb9779b9b16c67fabb6771ebf5b8127fef9ff65 Mon Sep 17 00:00:00 2001 From: Luke Date: Thu, 10 Apr 2025 15:12:52 -0400 Subject: [PATCH 1/3] Added Loopscale TVL --- projects/loopscale/index.js | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 projects/loopscale/index.js diff --git a/projects/loopscale/index.js b/projects/loopscale/index.js new file mode 100644 index 00000000000..26618f4f040 --- /dev/null +++ b/projects/loopscale/index.js @@ -0,0 +1,30 @@ +const sdk = require('@defillama/sdk') + +const endpoint = 'https://tars.loopscale.com/v1/markets/tvl/balances' +const startTimestamp = 1733072400 // 2024-12-01, 12PM ET + +async function tvl(api) { + const request = { + method: 'GET', + headers: { + accept: 'application/json', + }, + } + + const response = await fetch(`${endpoint}?timestamp=${api.timestamp}`, request) + + const data = await response.json() + + data.map(d => { + api.add(d.mint, d.balance) + }) +} + +module.exports = { + doublecounted: false, + timetravel: true, + start: startTimestamp, + methodology: + 'TVL is calculated by summing up all unused deposits and supplied collateral', + solana: { tvl }, +} From 8a168c4cde940bf78db70a3ff62049d1d503905f Mon Sep 17 00:00:00 2001 From: Luke Date: Mon, 21 Jul 2025 04:15:36 -0400 Subject: [PATCH 2/3] updated loopscale base fetch --- projects/loopscale/index.js | 165 +- projects/loopscale/loopscale.json | 2667 +++++++++++++++++++++++++++++ 2 files changed, 2814 insertions(+), 18 deletions(-) create mode 100644 projects/loopscale/loopscale.json diff --git a/projects/loopscale/index.js b/projects/loopscale/index.js index 26618f4f040..d71dd21b282 100644 --- a/projects/loopscale/index.js +++ b/projects/loopscale/index.js @@ -1,30 +1,159 @@ const sdk = require('@defillama/sdk') - -const endpoint = 'https://tars.loopscale.com/v1/markets/tvl/balances' -const startTimestamp = 1733072400 // 2024-12-01, 12PM ET +const { Connection, PublicKey } = require('@solana/web3.js') +const { Program, AnchorProvider, BN } = require("@coral-xyz/anchor"); +const { getConnection, getProvider, decodeAccount } = require('../helper/solana'); +const loopscaleIdl = require('./loopscale.json'); + +const endpoint = 'https://loopscale-pricing-adapters-109615290061.europe-west2.run.app/decompile_mints' + +const creditbookProgram = (connection) => { + const provider = new AnchorProvider( + connection, + { publicKey: PublicKey.default, signTransaction: (tx) => Promise.resolve(tx), signAllTransactions: (txs) => Promise.resolve(txs) }, + AnchorProvider.defaultOptions() + ); + const program = new Program(loopscaleIdl, provider); + return program; +}; + +async function getLoans(connection) { + const loansBorrowed = await creditbookProgram(connection).account.loan.all(); + return loansBorrowed; +} + +function bytesToNumberLE(bytes) { + let result = 0n; // Start with BigInt 0 + for (let i = bytes.length - 1; i >= 0; i--) { + result = (result << 8n) | BigInt(bytes[i]); -async function tvl(api) { - const request = { - method: 'GET', - headers: { - accept: 'application/json', - }, } - const response = await fetch(`${endpoint}?timestamp=${api.timestamp}`, request) + return Number(result); +} + +function getCollateralValuesForLoans(loans) { + const mintBalances = {}; + for(let i = 0; i < loans.length; i++) { + const collateralData = loans[i].account.collateral[0]; + const collateralMint = collateralData.assetMint; + const totalCollateral = new BN(collateralData.amount[0].reverse()).toNumber(); + + mintBalances[collateralMint] = mintBalances[collateralMint] ? mintBalances[collateralMint] + totalCollateral : totalCollateral; + } + return mintBalances; +} + +function getOutstandingBalanceForStrategy(strategy, currentTimestamp) { + // current_deployed_amount + // plus + // interest_outstanding + // plus + // interest_per_second + // times + // (current_timestamp - last_accrued_timestamp) + const lastAccruedTimestamp = bytesToNumberLE(new Uint8Array(strategy.lastAccruedTimestamp[0])); + const interestPerSecond = bytesToNumberLE(new Uint8Array(strategy.interestPerSecond[0])) / 1e18; + const currentDeployedAmount = bytesToNumberLE(new Uint8Array(strategy.currentDeployedAmount[0])); + const outstandingInterestAmount = bytesToNumberLE(new Uint8Array(strategy.outstandingInterestAmount[0])); + const unaccruedInterest = interestPerSecond * (currentTimestamp - lastAccruedTimestamp); + + return currentDeployedAmount + outstandingInterestAmount + unaccruedInterest; +} + +function getOutstandingDebt(strategies) { + const strategyBalances = {}; + const currentTimestamp = Math.floor(Date.now() / 1000); + + for(let i = 0; i < strategies.length; i++) { + const strategy = strategies[i].account; + const mint = strategy.principalMint.toString(); + const outstandingBalance = getOutstandingBalanceForStrategy(strategy, currentTimestamp); + strategyBalances[mint] = strategyBalances[mint] ? strategyBalances[mint] + outstandingBalance : outstandingBalance; + } + + return strategyBalances; +} + +function getIdleCapital(strategies) { + const strategyBalances = {}; - const data = await response.json() + for(let i = 0; i < strategies.length; i++) { + const strategy = strategies[i].account; + const mint = strategy.principalMint.toString(); + const unusedBalance = getIdleBalanceForStrategy(strategy); + strategyBalances[mint] = strategyBalances[mint] ? strategyBalances[mint] + unusedBalance : unusedBalance; + } + + return strategyBalances; +} + +async function getStrategies(connection) { + const outstandingStrategies = await creditbookProgram(connection).account.strategy.all(); + + return outstandingStrategies; +} + +function getIdleBalanceForStrategy(strategy) { + const amountExternallySupplied = bytesToNumberLE(new Uint8Array(strategy.externalYieldAmount[0])); + const amountHeldByStrategy = bytesToNumberLE(new Uint8Array(strategy.tokenBalance[0])); + + return amountExternallySupplied + amountHeldByStrategy; +} + +async function getDeposits(connection) { + const loans = await getLoans(connection); + const collateralBalances = getCollateralValuesForLoans(loans); + + const strats = await getStrategies(connection); + const outstandingDebt = getOutstandingDebt(strats); + const idleCapitalBalances = getIdleCapital(strats); + + let rawDeposits = {}; + + for (const obj of [collateralBalances, outstandingDebt, idleCapitalBalances]) { + for (const [key, value] of Object.entries(obj)) { + rawDeposits[key] = (rawDeposits[key] || 0) + value; + } + } + + rawDeposits = Object.fromEntries( + Object.entries(rawDeposits).filter(([key, value]) => value !== 0) + ); + + const response = await fetch(endpoint, { + method: "POST", + headers: { + "Content-Type": "application/json" + }, + body: JSON.stringify({ + rawBalances: rawDeposits + }) + }); + + const formattedDeposits = await response.json(); + + return formattedDeposits; +} + +async function tvl(api) { + const connection = getConnection(); + const balances = await getDeposits(connection); + const data = Object.entries(balances).map(([mint, balance]) => ({ mint, balance })); + api.addTokens(data.map(d => d.mint), data.map(d => d.balance)); +} - data.map(d => { - api.add(d.mint, d.balance) - }) +async function borrowed(api) { + const connection = getConnection(); + const strategies = await getStrategies(connection); + const outstandingDebt = getOutstandingDebt(strategies); + const data = Object.entries(outstandingDebt).map(([mint, balance]) => ({ mint, balance })); + api.addTokens(data.map(d => d.mint), data.map(d => d.balance)); } module.exports = { doublecounted: false, - timetravel: true, - start: startTimestamp, + timetravel: false, methodology: - 'TVL is calculated by summing up all unused deposits and supplied collateral', - solana: { tvl }, + 'TVL is calculated by summing up lending deposits and supplied collateral. Borrowed tokens are included.', + solana: { tvl, borrowed }, } diff --git a/projects/loopscale/loopscale.json b/projects/loopscale/loopscale.json new file mode 100644 index 00000000000..9a3979da42f --- /dev/null +++ b/projects/loopscale/loopscale.json @@ -0,0 +1,2667 @@ +{ + "address": "1oopBoJG58DgkUVKkEzKgyG9dvRmpgeEm1AVjoHkF78", + "metadata": { + "name": "loopscale", + "version": "0.1.0", + "spec": "0.1.0", + "description": "Created with Anchor" + }, + "instructions": [], + "accounts": [ + { + "name": "Loan", + "discriminator": [ + 20, + 195, + 70, + 117, + 165, + 227, + 182, + 1 + ] + }, + { + "name": "MarketInformation", + "discriminator": [ + 194, + 154, + 190, + 99, + 64, + 111, + 37, + 205 + ] + }, + { + "name": "Position", + "discriminator": [ + 170, + 188, + 143, + 228, + 122, + 64, + 247, + 208 + ] + }, + { + "name": "Strategy", + "discriminator": [ + 174, + 110, + 39, + 119, + 82, + 106, + 169, + 102 + ] + }, + { + "name": "Timelock", + "discriminator": [ + 189, + 33, + 78, + 75, + 205, + 31, + 4, + 177 + ] + }, + { + "name": "UserRewardsInfo", + "discriminator": [ + 242, + 27, + 82, + 180, + 183, + 119, + 156, + 237 + ] + }, + { + "name": "Vault", + "discriminator": [ + 211, + 8, + 232, + 43, + 2, + 152, + 117, + 119 + ] + }, + { + "name": "VaultRewardsInfo", + "discriminator": [ + 4, + 142, + 66, + 219, + 168, + 11, + 4, + 14 + ] + }, + { + "name": "VaultStake", + "discriminator": [ + 225, + 34, + 128, + 53, + 167, + 239, + 182, + 107 + ] + }, + { + "name": "Whirlpool", + "discriminator": [ + 63, + 149, + 209, + 12, + 225, + 128, + 99, + 9 + ] + } + ], + "events": [], + "errors": [], + "types": [ + { + "name": "AddCollateralTimeLockArgs", + "type": { + "kind": "struct", + "fields": [ + { + "name": "collateral_terms", + "type": { + "defined": { + "name": "CollateralTerms" + } + } + }, + { + "name": "update_market_information_params", + "type": { + "defined": { + "name": "UpdateMarketInformationParams" + } + } + } + ] + } + }, + { + "name": "AssetData", + "serialization": "bytemuck", + "repr": { + "kind": "c", + "packed": true + }, + "type": { + "kind": "struct", + "fields": [ + { + "name": "asset_identifier", + "type": "pubkey" + }, + { + "name": "quote_mint", + "type": "pubkey" + }, + { + "name": "oracle_account", + "type": "pubkey" + }, + { + "name": "oracle_type", + "type": "u8" + }, + { + "name": "max_uncertainty", + "type": { + "defined": { + "name": "PodU32CBPS" + } + } + }, + { + "name": "max_age", + "type": { + "defined": { + "name": "PodU16" + } + } + }, + { + "name": "decimals", + "type": "u8" + }, + { + "name": "ltv", + "type": { + "defined": { + "name": "PodU32CBPS" + } + } + }, + { + "name": "liquidation_threshold", + "type": { + "defined": { + "name": "PodU32CBPS" + } + } + } + ] + } + }, + { + "name": "BorrowPrincipalParams", + "docs": [ + "Remaining accounts:\n\nnum ledgers = L\n\n 1. LTV Write:\n 0: Ledger[ledger_index] Market Information\n\n 2. Healthcheck:\n For each ledger:\n Ledger market information\n Principal oracle accounts + conversion oracle accounts\n Then for each collateral in the loan:\n Collateral oracle accounts + conversion oracle accounts\n\nAsset index guidance:\n\n1. LTV write:\n For ledger[ledger_index]:\n Collateral index for each collateral\n2. Healthcheck:\n For each ledger:\n For each collateral in the loan:\n Principal index\n Collateral index" + ], + "type": { + "kind": "struct", + "fields": [ + { + "name": "amount", + "type": "u64" + }, + { + "name": "asset_index_guidance", + "type": "bytes" + }, + { + "name": "duration", + "type": "u8" + }, + { + "name": "expected_loan_values", + "type": { + "defined": { + "name": "ExpectedLoanValues" + } + } + }, + { + "name": "skip_sol_unwrap", + "type": "bool" + } + ] + } + }, + { + "name": "ClaimVaultFeeParams", + "type": { + "kind": "struct", + "fields": [ + { + "name": "amount", + "type": "u64" + } + ] + } + }, + { + "name": "CollateralData", + "serialization": "bytemuck", + "repr": { + "kind": "c", + "packed": true + }, + "type": { + "kind": "struct", + "fields": [ + { + "name": "asset_mint", + "type": "pubkey" + }, + { + "name": "amount", + "type": { + "defined": { + "name": "PodU64" + } + } + }, + { + "name": "asset_type", + "type": "u8" + }, + { + "name": "asset_identifier", + "type": "pubkey" + } + ] + } + }, + { + "name": "CollateralTerms", + "type": { + "kind": "struct", + "fields": [ + { + "name": "asset_identifier", + "type": "pubkey" + }, + { + "name": "terms", + "type": { + "array": [ + "u64", + 5 + ] + } + } + ] + } + }, + { + "name": "CollateralTermsIndices", + "type": { + "kind": "struct", + "fields": [ + { + "name": "collateral_index", + "type": "u8" + }, + { + "name": "duration_index", + "type": "u8" + } + ] + } + }, + { + "name": "CreateLoanParams", + "type": { + "kind": "struct", + "fields": [ + { + "name": "nonce", + "type": "u64" + } + ] + } + }, + { + "name": "CreateMarketInformationParams", + "type": { + "kind": "struct", + "fields": [ + { + "name": "principal_mint", + "type": "pubkey" + }, + { + "name": "authority", + "type": "pubkey" + } + ] + } + }, + { + "name": "CreateRewardsScheduleParams", + "type": { + "kind": "struct", + "fields": [ + { + "name": "total_weighted_stake_supply", + "type": { + "defined": { + "name": "PodDecimal" + } + } + }, + { + "name": "reward_start_time", + "type": { + "defined": { + "name": "PodU64" + } + } + }, + { + "name": "reward_end_time", + "type": { + "defined": { + "name": "PodU64" + } + } + }, + { + "name": "duration_stake_weights", + "type": { + "array": [ + { + "defined": { + "name": "PodU32CBPS" + } + }, + 5 + ] + } + } + ] + } + }, + { + "name": "CreateStrategyParams", + "type": { + "kind": "struct", + "fields": [ + { + "name": "lender", + "type": "pubkey" + }, + { + "name": "origination_cap", + "type": "u64" + }, + { + "name": "liquidity_buffer", + "type": "u64" + }, + { + "name": "interest_fee", + "type": "u64" + }, + { + "name": "origination_fee", + "type": "u64" + }, + { + "name": "principal_fee", + "type": "u64" + }, + { + "name": "originations_enabled", + "type": "bool" + }, + { + "name": "external_yield_source_args", + "type": { + "option": { + "defined": { + "name": "ExternalYieldSourceArgs" + } + } + } + } + ] + } + }, + { + "name": "CreateVaultParams", + "type": { + "kind": "struct", + "fields": [ + { + "name": "token_name", + "type": "string" + }, + { + "name": "token_symbol", + "type": "string" + }, + { + "name": "token_uri", + "type": "string" + }, + { + "name": "manager", + "type": "pubkey" + }, + { + "name": "create_strategy_params", + "type": { + "defined": { + "name": "CreateStrategyParams" + } + } + } + ] + } + }, + { + "name": "DepositCollateralParams", + "docs": [ + "Remaining accounts:\n\nnum ledgers = L\n\n1. LTV Write:\n 0 -> (L-1): Ledger Market Information\n\nAsset index guidance:\n1. LTV Write:\n 0 -> (L-1): Collateral index for deposited collateral on the ledger market information" + ], + "type": { + "kind": "struct", + "fields": [ + { + "name": "amount", + "type": "u64" + }, + { + "name": "asset_type", + "type": "u8" + }, + { + "name": "asset_index_guidance", + "type": "bytes" + }, + { + "name": "expected_loan_values", + "type": { + "defined": { + "name": "ExpectedLoanValues" + } + } + } + ] + } + }, + { + "name": "Duration", + "serialization": "bytemuck", + "repr": { + "kind": "c", + "packed": true + }, + "type": { + "kind": "struct", + "fields": [ + { + "name": "duration", + "type": { + "defined": { + "name": "PodU32" + } + } + }, + { + "name": "duration_type", + "type": "u8" + } + ] + } + }, + { + "name": "ExactInParams", + "type": { + "kind": "struct", + "fields": [ + { + "name": "amount_in", + "type": "u64" + }, + { + "name": "min_amount_out", + "type": "u64" + } + ] + } + }, + { + "name": "ExactOutParams", + "type": { + "kind": "struct", + "fields": [ + { + "name": "amount_out", + "type": "u64" + }, + { + "name": "max_amount_in", + "type": "u64" + } + ] + } + }, + { + "name": "ExpectedLoanValues", + "type": { + "kind": "struct", + "fields": [ + { + "name": "expected_apy", + "type": "u64" + }, + { + "name": "expected_liquidation_threshold", + "type": { + "array": [ + "u32", + 5 + ] + } + } + ] + } + }, + { + "name": "ExternalYieldAccounts", + "repr": { + "kind": "c", + "packed": true + }, + "type": { + "kind": "struct", + "fields": [ + { + "name": "external_yield_account", + "type": "pubkey" + }, + { + "name": "external_yield_vault", + "type": "pubkey" + } + ] + } + }, + { + "name": "ExternalYieldSourceArgs", + "type": { + "kind": "struct", + "fields": [ + { + "name": "new_external_yield_source", + "type": "u8" + }, + { + "name": "external_yield_vault", + "type": "pubkey" + } + ] + } + }, + { + "name": "Ledger", + "serialization": "bytemuck", + "repr": { + "kind": "c", + "packed": true + }, + "type": { + "kind": "struct", + "fields": [ + { + "name": "status", + "type": "u8" + }, + { + "name": "strategy", + "type": "pubkey" + }, + { + "name": "principal_mint", + "type": "pubkey" + }, + { + "name": "market_information", + "type": "pubkey" + }, + { + "name": "principal_due", + "type": { + "defined": { + "name": "PodU64" + } + } + }, + { + "name": "principal_repaid", + "type": { + "defined": { + "name": "PodU64" + } + } + }, + { + "name": "interest_due", + "type": { + "defined": { + "name": "PodU64" + } + } + }, + { + "name": "interest_repaid", + "type": { + "defined": { + "name": "PodU64" + } + } + }, + { + "name": "duration", + "type": { + "defined": { + "name": "Duration" + } + } + }, + { + "name": "interest_per_second", + "type": { + "defined": { + "name": "PodDecimal" + } + } + }, + { + "name": "start_time", + "type": { + "defined": { + "name": "PodU64" + } + } + }, + { + "name": "end_time", + "type": { + "defined": { + "name": "PodU64" + } + } + }, + { + "name": "apy", + "type": { + "defined": { + "name": "PodU64CBPS" + } + } + } + ] + } + }, + { + "name": "LiquidateLedgerParams", + "type": { + "kind": "struct", + "fields": [ + { + "name": "ledger_index", + "type": "u8" + }, + { + "name": "unwrap_sol", + "type": "bool" + }, + { + "name": "asset_index_guidance", + "type": "bytes" + } + ] + } + }, + { + "name": "Loan", + "serialization": "bytemuck", + "repr": { + "kind": "c", + "packed": true + }, + "type": { + "kind": "struct", + "fields": [ + { + "name": "version", + "type": "u8" + }, + { + "name": "bump", + "type": "u8" + }, + { + "name": "loan_status", + "type": "u8" + }, + { + "name": "borrower", + "type": "pubkey" + }, + { + "name": "nonce", + "type": "u64" + }, + { + "name": "start_time", + "type": { + "defined": { + "name": "PodU64" + } + } + }, + { + "name": "ledgers", + "type": { + "array": [ + { + "defined": { + "name": "Ledger" + } + }, + 5 + ] + } + }, + { + "name": "collateral", + "type": { + "array": [ + { + "defined": { + "name": "CollateralData" + } + }, + 5 + ] + } + }, + { + "name": "weight_matrix", + "type": { + "array": [ + { + "array": [ + { + "defined": { + "name": "PodU32CBPS" + } + }, + 5 + ] + }, + 5 + ] + } + }, + { + "name": "ltv_matrix", + "type": { + "array": [ + { + "array": [ + { + "defined": { + "name": "PodU32CBPS" + } + }, + 5 + ] + }, + 5 + ] + } + }, + { + "name": "lqt_matrix", + "type": { + "array": [ + { + "array": [ + { + "defined": { + "name": "PodU32CBPS" + } + }, + 5 + ] + }, + 5 + ] + } + } + ] + } + }, + { + "name": "LoanUnlockParams", + "type": { + "kind": "struct", + "fields": [ + { + "name": "asset_index_guidance", + "type": "bytes" + } + ] + } + }, + { + "name": "LockLoanParams", + "type": { + "kind": "struct", + "fields": [ + { + "name": "unlock_idx", + "type": "u8" + } + ] + } + }, + { + "name": "LpParams", + "type": { + "kind": "enum", + "variants": [ + { + "name": "ExactIn", + "fields": [ + { + "defined": { + "name": "ExactInParams" + } + } + ] + }, + { + "name": "ExactOut", + "fields": [ + { + "defined": { + "name": "ExactOutParams" + } + } + ] + } + ] + } + }, + { + "name": "ManageOrcaLiquidityParams", + "type": { + "kind": "struct", + "fields": [ + { + "name": "collateral_index", + "type": "u8" + }, + { + "name": "liquidity_amount", + "type": "u128" + }, + { + "name": "transfer_params", + "type": { + "defined": { + "name": "OrcaTransferTypeParams" + } + } + }, + { + "name": "asset_index_guidance", + "type": "bytes" + } + ] + } + }, + { + "name": "MarketInformation", + "serialization": "bytemuck", + "repr": { + "kind": "c", + "packed": true + }, + "type": { + "kind": "struct", + "fields": [ + { + "name": "authority", + "type": "pubkey" + }, + { + "name": "delegate", + "type": "pubkey" + }, + { + "name": "principal_mint", + "type": "pubkey" + }, + { + "name": "asset_data", + "type": { + "array": [ + { + "defined": { + "name": "AssetData" + } + }, + 200 + ] + } + } + ] + } + }, + { + "name": "MultiCollateralTermsUpdateParams", + "type": { + "kind": "struct", + "fields": [ + { + "name": "apy", + "type": "u64" + }, + { + "name": "indices", + "type": { + "vec": { + "defined": { + "name": "CollateralTermsIndices" + } + } + } + } + ] + } + }, + { + "name": "OrcaLiquidityParams", + "type": { + "kind": "struct", + "fields": [ + { + "name": "slippage_tolerance_bps", + "type": "u16" + } + ] + } + }, + { + "name": "OrcaTokenAmountsParams", + "type": { + "kind": "struct", + "fields": [ + { + "name": "token_a_amount", + "type": "u64" + }, + { + "name": "token_b_amount", + "type": "u64" + } + ] + } + }, + { + "name": "OrcaTransferTypeParams", + "type": { + "kind": "enum", + "variants": [ + { + "name": "Liquidity", + "fields": [ + { + "defined": { + "name": "OrcaLiquidityParams" + } + } + ] + }, + { + "name": "TokenAmounts", + "fields": [ + { + "defined": { + "name": "OrcaTokenAmountsParams" + } + } + ] + } + ] + } + }, + { + "name": "PodBool", + "docs": [ + "Represents a bool stored as a byte" + ], + "repr": { + "kind": "transparent" + }, + "type": { + "kind": "struct", + "fields": [ + "u8" + ] + } + }, + { + "name": "PodDecimal", + "docs": [ + "this is the scaled representation of a whole number. The whole number is scaled by 10^18 to avoid floating point errors when performing arithmetic operations." + ], + "repr": { + "kind": "c" + }, + "type": { + "kind": "struct", + "fields": [ + { + "array": [ + "u8", + 24 + ] + } + ] + } + }, + { + "name": "PodU128", + "docs": [ + "Represents a 128-bit unsigned integer stored as bytes (little-endian)" + ], + "repr": { + "kind": "c" + }, + "type": { + "kind": "struct", + "fields": [ + { + "array": [ + "u8", + 16 + ] + } + ] + } + }, + { + "name": "PodU16", + "docs": [ + "Represents a 16-bit unsigned integer stored as bytes (little-endian)" + ], + "repr": { + "kind": "transparent" + }, + "type": { + "kind": "struct", + "fields": [ + { + "array": [ + "u8", + 2 + ] + } + ] + } + }, + { + "name": "PodU32", + "docs": [ + "Represents a 32-bit unsigned integer stored as bytes (little-endian)" + ], + "repr": { + "kind": "transparent" + }, + "type": { + "kind": "struct", + "fields": [ + { + "array": [ + "u8", + 4 + ] + } + ] + } + }, + { + "name": "PodU32CBPS", + "docs": [ + "helper type to store u32 cbps values" + ], + "repr": { + "kind": "c" + }, + "type": { + "kind": "struct", + "fields": [ + { + "array": [ + "u8", + 4 + ] + } + ] + } + }, + { + "name": "PodU64", + "docs": [ + "Represents a 64-bit unsigned integer stored as bytes (little-endian)" + ], + "repr": { + "kind": "transparent" + }, + "type": { + "kind": "struct", + "fields": [ + { + "array": [ + "u8", + 8 + ] + } + ] + } + }, + { + "name": "PodU64CBPS", + "docs": [ + "helper type to store u64 cbps values" + ], + "repr": { + "kind": "c" + }, + "type": { + "kind": "struct", + "fields": [ + { + "array": [ + "u8", + 8 + ] + } + ] + } + }, + { + "name": "Position", + "type": { + "kind": "struct", + "fields": [ + { + "name": "whirlpool", + "type": "pubkey" + }, + { + "name": "position_mint", + "type": "pubkey" + }, + { + "name": "liquidity", + "type": "u128" + }, + { + "name": "tick_lower_index", + "type": "i32" + }, + { + "name": "tick_upper_index", + "type": "i32" + }, + { + "name": "fee_growth_checkpoint_a", + "type": "u128" + }, + { + "name": "fee_owed_a", + "type": "u64" + }, + { + "name": "fee_growth_checkpoint_b", + "type": "u128" + }, + { + "name": "fee_owed_b", + "type": "u64" + }, + { + "name": "reward_infos", + "type": { + "array": [ + { + "defined": { + "name": "PositionRewardInfo" + } + }, + 3 + ] + } + } + ] + } + }, + { + "name": "PositionRewardInfo", + "type": { + "kind": "struct", + "fields": [ + { + "name": "growth_inside_checkpoint", + "type": "u128" + }, + { + "name": "amount_owed", + "type": "u64" + } + ] + } + }, + { + "name": "RefinanceLedgerParams", + "type": { + "kind": "struct", + "fields": [ + { + "name": "ledger_index", + "type": "u8" + }, + { + "name": "duration_index", + "type": "u8" + }, + { + "name": "asset_index_guidance", + "type": "bytes" + } + ] + } + }, + { + "name": "RepayPrincipalParams", + "docs": [ + "No remaining accounts or asset index guidance needed. In full repayment, we zero out the matrix for the specific ledger using default loan values." + ], + "type": { + "kind": "struct", + "fields": [ + { + "name": "amount", + "type": "u64" + }, + { + "name": "ledger_index", + "type": "u8" + }, + { + "name": "repay_all", + "type": "bool" + } + ] + } + }, + { + "name": "RewardsClaimedEvent", + "type": { + "kind": "struct", + "fields": [ + { + "name": "vault_address", + "type": "pubkey" + }, + { + "name": "user_address", + "type": "pubkey" + }, + { + "name": "stake_account_address", + "type": "pubkey" + }, + { + "name": "amount", + "type": "u64" + }, + { + "name": "mint", + "type": "pubkey" + }, + { + "name": "timestamp", + "type": "u64" + } + ] + } + }, + { + "name": "SellLedgerParams", + "type": { + "kind": "struct", + "fields": [ + { + "name": "ledger_index", + "type": "u8" + }, + { + "name": "expected_sale_price", + "type": "u64" + }, + { + "name": "asset_index_guidance", + "type": "bytes" + } + ] + } + }, + { + "name": "StakeEvent", + "docs": [ + "metadata for vault actions" + ], + "type": { + "kind": "struct", + "fields": [ + { + "name": "user", + "type": "pubkey" + }, + { + "name": "address", + "type": "pubkey" + }, + { + "name": "vault_address", + "type": "pubkey" + }, + { + "name": "principal_mint", + "type": "pubkey" + }, + { + "name": "duration_type", + "type": "u8" + }, + { + "name": "amount", + "type": "u64" + }, + { + "name": "action_type", + "type": "u8" + }, + { + "name": "principal_amount", + "type": "u64" + } + ] + } + }, + { + "name": "Strategy", + "serialization": "bytemuck", + "repr": { + "kind": "c", + "packed": true + }, + "type": { + "kind": "struct", + "fields": [ + { + "name": "version", + "type": "u8" + }, + { + "name": "nonce", + "type": "pubkey" + }, + { + "name": "bump", + "type": "u8" + }, + { + "name": "principal_mint", + "type": "pubkey" + }, + { + "name": "lender", + "type": "pubkey" + }, + { + "name": "originations_enabled", + "type": { + "defined": { + "name": "PodBool" + } + } + }, + { + "name": "external_yield_source", + "type": "u8" + }, + { + "name": "interest_per_second", + "type": { + "defined": { + "name": "PodDecimal" + } + } + }, + { + "name": "last_accrued_timestamp", + "docs": [ + "timestamp interest per second's interest was last accrued" + ], + "type": { + "defined": { + "name": "PodU64" + } + } + }, + { + "name": "liquidity_buffer", + "docs": [ + "the is the amount of liquidity % that always needs to be in the strategy" + ], + "type": { + "defined": { + "name": "PodU64CBPS" + } + } + }, + { + "name": "token_balance", + "docs": [ + "amount of principal in the strategy" + ], + "type": { + "defined": { + "name": "PodU64" + } + } + }, + { + "name": "interest_fee", + "docs": [ + "this is the fee charged by and accrued to the manager on the interest accrued via external yield and loans" + ], + "type": { + "defined": { + "name": "PodU64CBPS" + } + } + }, + { + "name": "principal_fee", + "docs": [ + "this is the fee charged by and accrued to the manager on the origination fee" + ], + "type": { + "defined": { + "name": "PodU64CBPS" + } + } + }, + { + "name": "origination_fee", + "docs": [ + "fee charged on origination of new loans" + ], + "type": { + "defined": { + "name": "PodU64CBPS" + } + } + }, + { + "name": "origination_cap", + "docs": [ + "the maximum size of a loan that can be originated" + ], + "type": { + "defined": { + "name": "PodU64" + } + } + }, + { + "name": "external_yield_amount", + "docs": [ + "this is the amount of principal currently in external yield. has to always be updated on any new nav action" + ], + "type": { + "defined": { + "name": "PodU64" + } + } + }, + { + "name": "current_deployed_amount", + "docs": [ + "this is the amount of principal currently deployed in loans" + ], + "type": { + "defined": { + "name": "PodU64" + } + } + }, + { + "name": "outstanding_interest_amount", + "docs": [ + "this is the interest that has not been repaid yet but accrued" + ], + "type": { + "defined": { + "name": "PodU64" + } + } + }, + { + "name": "fee_claimable", + "docs": [ + "this is the amount that has accrued to the manager" + ], + "type": { + "defined": { + "name": "PodU64" + } + } + }, + { + "name": "cumulative_principal_originated", + "type": { + "defined": { + "name": "PodU128" + } + } + }, + { + "name": "cumulative_interest_accrued", + "type": { + "defined": { + "name": "PodU128" + } + } + }, + { + "name": "cumulative_loan_count", + "type": { + "defined": { + "name": "PodU64" + } + } + }, + { + "name": "active_loan_count", + "type": { + "defined": { + "name": "PodU64" + } + } + }, + { + "name": "market_information", + "type": "pubkey" + }, + { + "name": "collateral_map", + "type": { + "array": [ + { + "array": [ + { + "defined": { + "name": "PodU64" + } + }, + 5 + ] + }, + 200 + ] + } + }, + { + "name": "external_yield_accounts", + "type": { + "defined": { + "name": "ExternalYieldAccounts" + } + } + } + ] + } + }, + { + "name": "Timelock", + "type": { + "kind": "struct", + "fields": [ + { + "name": "vault", + "type": "pubkey" + }, + { + "name": "init_timestamp", + "type": "i64" + }, + { + "name": "execution_delay", + "type": "i64" + }, + { + "name": "params", + "type": { + "defined": { + "name": "TimelockUpdateParams" + } + } + } + ] + } + }, + { + "name": "TimelockCanceledEvent", + "type": { + "kind": "struct", + "fields": [ + { + "name": "timelock", + "type": "string" + } + ] + } + }, + { + "name": "TimelockCreatedEvent", + "type": { + "kind": "struct", + "fields": [ + { + "name": "timelock_address", + "type": "string" + }, + { + "name": "vault_address", + "type": "string" + }, + { + "name": "timelock_params", + "type": { + "defined": { + "name": "TimelockUpdateParams" + } + } + }, + { + "name": "timelock_init_timestamp", + "type": "i64" + }, + { + "name": "timelock_execution_delay", + "type": "i64" + } + ] + } + }, + { + "name": "TimelockExecutedEvent", + "type": { + "kind": "struct", + "fields": [ + { + "name": "timelock", + "type": "string" + } + ] + } + }, + { + "name": "TimelockUpdateParams", + "type": { + "kind": "enum", + "variants": [ + { + "name": "AddCollateral", + "fields": [ + { + "defined": { + "name": "AddCollateralTimeLockArgs" + } + } + ] + }, + { + "name": "UpdateLtv", + "fields": [ + { + "defined": { + "name": "UpdateMarketInformationParams" + } + } + ] + }, + { + "name": "RemoveCollateral", + "fields": [ + { + "defined": { + "name": "CollateralTerms" + } + } + ] + }, + { + "name": "UpdateApy", + "fields": [ + { + "defined": { + "name": "CollateralTerms" + } + } + ] + }, + { + "name": "UpdateStrategy", + "fields": [ + { + "defined": { + "name": "UpdateStrategyParams" + } + } + ] + }, + { + "name": "UpdateVault", + "fields": [ + "u64" + ] + } + ] + } + }, + { + "name": "TransferOrcaPositionParams", + "type": { + "kind": "struct", + "fields": [ + { + "name": "liquidity_amount", + "type": "u128" + }, + { + "name": "transfer_params", + "type": { + "defined": { + "name": "OrcaTransferTypeParams" + } + } + }, + { + "name": "tick_lower_index", + "type": "i32" + }, + { + "name": "tick_upper_index", + "type": "i32" + }, + { + "name": "asset_index_guidance", + "type": "bytes" + } + ] + } + }, + { + "name": "UpdateMarketInformationParams", + "type": { + "kind": "struct", + "fields": [ + { + "name": "asset_identifier", + "type": "pubkey" + }, + { + "name": "quote_mint", + "type": { + "option": "pubkey" + } + }, + { + "name": "oracle_account", + "type": { + "option": "pubkey" + } + }, + { + "name": "oracle_type", + "type": { + "option": "u8" + } + }, + { + "name": "max_uncertainty", + "type": { + "option": "u32" + } + }, + { + "name": "max_age", + "type": { + "option": "u16" + } + }, + { + "name": "ltv", + "type": { + "option": "u32" + } + }, + { + "name": "liquidation_threshold", + "type": { + "option": "u32" + } + }, + { + "name": "remove", + "type": { + "option": "bool" + } + } + ] + } + }, + { + "name": "UpdateRewardsScheduleParams", + "type": { + "kind": "struct", + "fields": [ + { + "name": "amount_to_transfer", + "type": "u64" + }, + { + "name": "extend_end_time", + "type": { + "option": "u64" + } + }, + { + "name": "schedule_index", + "type": "u8" + } + ] + } + }, + { + "name": "UpdateStrategyParams", + "type": { + "kind": "struct", + "fields": [ + { + "name": "originations_enabled", + "type": { + "option": "bool" + } + }, + { + "name": "liquidity_buffer", + "type": { + "option": "u64" + } + }, + { + "name": "interest_fee", + "type": { + "option": "u64" + } + }, + { + "name": "origination_fee", + "type": { + "option": "u64" + } + }, + { + "name": "principal_fee", + "type": { + "option": "u64" + } + }, + { + "name": "origination_cap", + "type": { + "option": "u64" + } + }, + { + "name": "market_information", + "type": { + "option": "pubkey" + } + }, + { + "name": "external_yield_source_args", + "type": { + "option": { + "defined": { + "name": "ExternalYieldSourceArgs" + } + } + } + } + ] + } + }, + { + "name": "UpdateVaultParams", + "type": { + "kind": "struct", + "fields": [ + { + "name": "deposits_enabled", + "type": "bool" + }, + { + "name": "init_vault_rewards_info", + "type": "bool" + } + ] + } + }, + { + "name": "UpdateWeightMatrixParams", + "type": { + "kind": "struct", + "fields": [ + { + "name": "asset_index_guidance", + "type": "bytes" + }, + { + "name": "collateral_index", + "type": "u8" + }, + { + "name": "weight_matrix_update", + "type": { + "array": [ + "u32", + 5 + ] + } + } + ] + } + }, + { + "name": "UserRewardsInfo", + "serialization": "bytemuck", + "repr": { + "kind": "c", + "packed": true + }, + "type": { + "kind": "struct", + "fields": [ + { + "name": "vault_address", + "type": "pubkey" + }, + { + "name": "bump", + "type": "u8" + }, + { + "name": "stake_account_address", + "type": "pubkey" + }, + { + "name": "stake_time", + "type": { + "defined": { + "name": "PodU64" + } + } + }, + { + "name": "user", + "type": "pubkey" + }, + { + "name": "lp_amount", + "type": { + "defined": { + "name": "PodU64" + } + } + }, + { + "name": "duration_index", + "type": "u8" + }, + { + "name": "last_reward_indexes", + "type": { + "array": [ + { + "defined": { + "name": "PodDecimal" + } + }, + 5 + ] + } + }, + { + "name": "pending_rewards", + "type": { + "array": [ + { + "defined": { + "name": "PodU64" + } + }, + 5 + ] + } + }, + { + "name": "last_reward_index_update_time", + "type": { + "array": [ + { + "defined": { + "name": "PodU64" + } + }, + 5 + ] + } + } + ] + } + }, + { + "name": "UserRewardsInfoClosed", + "type": { + "kind": "struct", + "fields": [ + { + "name": "address", + "type": "pubkey" + } + ] + } + }, + { + "name": "Vault", + "serialization": "bytemuck", + "repr": { + "kind": "c", + "packed": true + }, + "type": { + "kind": "struct", + "fields": [ + { + "name": "manager", + "type": "pubkey" + }, + { + "name": "nonce", + "type": "pubkey" + }, + { + "name": "bump", + "type": "u8" + }, + { + "name": "lp_supply", + "type": { + "defined": { + "name": "PodU64" + } + } + }, + { + "name": "lp_mint", + "type": "pubkey" + }, + { + "name": "principal_mint", + "type": "pubkey" + }, + { + "name": "cumulative_principal_deposited", + "type": { + "defined": { + "name": "PodU64" + } + } + }, + { + "name": "deposits_enabled", + "type": { + "defined": { + "name": "PodBool" + } + } + }, + { + "name": "max_early_unstake_fee", + "type": { + "defined": { + "name": "PodU64CBPS" + } + } + } + ] + } + }, + { + "name": "VaultRewardsInfo", + "serialization": "bytemuck", + "repr": { + "kind": "c", + "packed": true + }, + "type": { + "kind": "struct", + "fields": [ + { + "name": "vault_address", + "type": "pubkey" + }, + { + "name": "bump", + "type": "u8" + }, + { + "name": "schedules", + "type": { + "array": [ + { + "defined": { + "name": "VaultRewardsSchedule" + } + }, + 5 + ] + } + } + ] + } + }, + { + "name": "VaultRewardsSchedule", + "serialization": "bytemuck", + "repr": { + "kind": "c", + "packed": true + }, + "type": { + "kind": "struct", + "fields": [ + { + "name": "reward_mint", + "type": "pubkey" + }, + { + "name": "total_weighted_stake_supply", + "type": { + "defined": { + "name": "PodDecimal" + } + } + }, + { + "name": "reward_start_time", + "type": { + "defined": { + "name": "PodU64" + } + } + }, + { + "name": "reward_end_time", + "type": { + "defined": { + "name": "PodU64" + } + } + }, + { + "name": "total_emissions_amount", + "type": { + "defined": { + "name": "PodU64" + } + } + }, + { + "name": "emissions_per_second", + "type": { + "defined": { + "name": "PodDecimal" + } + } + }, + { + "name": "reward_index", + "type": { + "defined": { + "name": "PodDecimal" + } + } + }, + { + "name": "last_reward_index_update_time", + "type": { + "defined": { + "name": "PodU64" + } + } + }, + { + "name": "emissions_claimed", + "type": { + "defined": { + "name": "PodU64" + } + } + }, + { + "name": "created_at", + "type": { + "defined": { + "name": "PodU64" + } + } + }, + { + "name": "duration_stake_weights", + "type": { + "array": [ + { + "defined": { + "name": "PodU32CBPS" + } + }, + 5 + ] + } + } + ] + } + }, + { + "name": "VaultStake", + "serialization": "bytemuck", + "repr": { + "kind": "c", + "packed": true + }, + "type": { + "kind": "struct", + "fields": [ + { + "name": "vault", + "type": "pubkey" + }, + { + "name": "nonce", + "type": "pubkey" + }, + { + "name": "bump", + "type": "u8" + }, + { + "name": "user", + "type": "pubkey" + }, + { + "name": "amount", + "type": { + "defined": { + "name": "PodU64" + } + } + }, + { + "name": "duration", + "type": { + "defined": { + "name": "Duration" + } + } + }, + { + "name": "start_time", + "type": { + "defined": { + "name": "PodU64" + } + } + }, + { + "name": "end_time", + "type": { + "defined": { + "name": "PodU64" + } + } + }, + { + "name": "unstake_time", + "type": { + "defined": { + "name": "PodU64" + } + } + }, + { + "name": "unstake_fee_applied", + "type": { + "defined": { + "name": "PodU64" + } + } + } + ] + } + }, + { + "name": "VaultStakeParams", + "type": { + "kind": "struct", + "fields": [ + { + "name": "amount", + "type": "u64" + }, + { + "name": "principal_amount", + "type": "u64" + }, + { + "name": "stake_all", + "type": { + "option": "bool" + } + }, + { + "name": "duration", + "type": "u32" + }, + { + "name": "duration_type", + "type": "u8" + }, + { + "name": "action_type", + "type": "u8" + } + ] + } + }, + { + "name": "VaultUnstakeParams", + "type": { + "kind": "struct", + "fields": [ + { + "name": "action_type", + "type": "u8" + }, + { + "name": "principal_amount", + "type": "u64" + } + ] + } + }, + { + "name": "Whirlpool", + "type": { + "kind": "struct", + "fields": [ + { + "name": "whirlpools_config", + "type": "pubkey" + }, + { + "name": "whirlpool_bump", + "type": { + "array": [ + "u8", + 1 + ] + } + }, + { + "name": "tick_spacing", + "type": "u16" + }, + { + "name": "fee_tier_index_seed", + "type": { + "array": [ + "u8", + 2 + ] + } + }, + { + "name": "fee_rate", + "type": "u16" + }, + { + "name": "protocol_fee_rate", + "type": "u16" + }, + { + "name": "liquidity", + "type": "u128" + }, + { + "name": "sqrt_price", + "type": "u128" + }, + { + "name": "tick_current_index", + "type": "i32" + }, + { + "name": "protocol_fee_owed_a", + "type": "u64" + }, + { + "name": "protocol_fee_owed_b", + "type": "u64" + }, + { + "name": "token_mint_a", + "type": "pubkey" + }, + { + "name": "token_vault_a", + "type": "pubkey" + }, + { + "name": "fee_growth_global_a", + "type": "u128" + }, + { + "name": "token_mint_b", + "type": "pubkey" + }, + { + "name": "token_vault_b", + "type": "pubkey" + }, + { + "name": "fee_growth_global_b", + "type": "u128" + }, + { + "name": "reward_last_updated_timestamp", + "type": "u64" + }, + { + "name": "reward_infos", + "type": { + "array": [ + { + "defined": { + "name": "WhirlpoolRewardInfo" + } + }, + 3 + ] + } + } + ] + } + }, + { + "name": "WhirlpoolRewardInfo", + "docs": [ + "Stores the state relevant for tracking liquidity mining rewards at the `Whirlpool` level.", + "These values are used in conjunction with `PositionRewardInfo`, `Tick.reward_growths_outside`,", + "and `Whirlpool.reward_last_updated_timestamp` to determine how many rewards are earned by open", + "positions." + ], + "type": { + "kind": "struct", + "fields": [ + { + "name": "mint", + "docs": [ + "Reward token mint." + ], + "type": "pubkey" + }, + { + "name": "vault", + "docs": [ + "Reward vault token account." + ], + "type": "pubkey" + }, + { + "name": "authority", + "docs": [ + "Authority account that has permission to initialize the reward and set emissions." + ], + "type": "pubkey" + }, + { + "name": "emissions_per_second_x64", + "docs": [ + "Q64.64 number that indicates how many tokens per second are earned per unit of liquidity." + ], + "type": "u128" + }, + { + "name": "growth_global_x64", + "docs": [ + "Q64.64 number that tracks the total tokens earned per unit of liquidity since the reward", + "emissions were turned on." + ], + "type": "u128" + } + ] + } + }, + { + "name": "WithdrawCollateralParams", + "docs": [ + "Remaining accounts:\n\nnum ledgers = L\n\n1. 0 -> 2L-1: Strategy + MarketInformation for ledger L_i\n\n2. Healthcheck:\n For each ledger:\n Ledger market information\n Principal oracle accounts + conversion oracle accounts\n Then again for each ledger and collateral:\n Collateral oracle accounts + conversion oracle accounts\n\n\nAsset index guidance:\n1. Healthcheck:\n For each ledger:\n For each collateral in the loan:\n Principal index\n Collateral index" + ], + "type": { + "kind": "struct", + "fields": [ + { + "name": "amount", + "type": "u64" + }, + { + "name": "collateral_index", + "type": "u8" + }, + { + "name": "asset_index_guidance", + "type": "bytes" + }, + { + "name": "expected_loan_values", + "type": { + "defined": { + "name": "ExpectedLoanValues" + } + } + }, + { + "name": "close_if_eligible", + "type": "bool" + } + ] + } + } + ] +} \ No newline at end of file From b6a068eb3da26e8c617d82e82c62171f71294220 Mon Sep 17 00:00:00 2001 From: Luke Date: Mon, 21 Jul 2025 11:05:55 -0400 Subject: [PATCH 3/3] Removed borrows from TVL --- projects/loopscale/index.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/projects/loopscale/index.js b/projects/loopscale/index.js index d71dd21b282..57ec1cf798e 100644 --- a/projects/loopscale/index.js +++ b/projects/loopscale/index.js @@ -105,12 +105,11 @@ async function getDeposits(connection) { const collateralBalances = getCollateralValuesForLoans(loans); const strats = await getStrategies(connection); - const outstandingDebt = getOutstandingDebt(strats); const idleCapitalBalances = getIdleCapital(strats); let rawDeposits = {}; - for (const obj of [collateralBalances, outstandingDebt, idleCapitalBalances]) { + for (const obj of [collateralBalances, idleCapitalBalances]) { for (const [key, value] of Object.entries(obj)) { rawDeposits[key] = (rawDeposits[key] || 0) + value; }