UNPKG

@augustdigital/vaults

Version:

JS SDK for web3 interactions with the August Digital Lending Pools

586 lines 26.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.AugustVaults = void 0; const utils_1 = require("@augustdigital/utils"); const utils_2 = require("./utils"); const rpc_config_1 = require("./rpc-config"); const ethers_1 = require("ethers"); const getters_1 = require("./getters"); const services_1 = require("@augustdigital/services"); const user_actions_1 = require("./user-actions"); class AugustVaults extends utils_1.AugustBase { constructor(baseConfig, solana) { super(baseConfig); this.solanaService = solana; } async getVaults(options) { const allVaults = await (0, utils_1.fetchTokenizedVaults)(undefined, { 'x-environment': this.monitoring?.['x-environment'], 'x-user-id': this.monitoring?.['x-user-id'], }); const vaultsPerAvailableProviders = allVaults.filter((v) => !!this.providers?.[v?.chain] ? true : false); const vaultsPerChainId = options?.chainIds ? vaultsPerAvailableProviders.filter((v) => options.chainIds.includes(v.chain)) : vaultsPerAvailableProviders; const vaultFetchResult = await (0, utils_2.fetchVaultsComprehensive)(vaultsPerChainId, async (vault) => { const rpcUrl = vault.fallbackRpc || this.providers?.[vault.chain]; const shouldFetchLoans = !vault.minimal && (typeof options?.loans !== 'undefined' ? options?.loans : true); const shouldFetchAllocations = !vault.minimal && (typeof options?.allocations !== 'undefined' ? options?.allocations : true); const isSolana = services_1.Solana.utils.isSolanaAddress(vault.address) ? true : false; const v = (0, getters_1.getVault)({ vault: vault.address, loans: isSolana ? false : shouldFetchLoans, allocations: isSolana ? false : shouldFetchAllocations, options: { rpcUrl, solanaService: this.solanaService, env: this.monitoring?.env, augustKey: this.keys?.august, subgraphKey: this.keys?.graph, }, }); return v; }, { maxRetries: 5, baseDelay: 2000, batchSize: 15, parallelLimit: 8, includeClosed: true, includeInvisible: false, timeout: 60000, fallbackRpcUrls: { 1: (0, rpc_config_1.getFallbackRpcUrls)(1), 56: (0, rpc_config_1.getFallbackRpcUrls)(56), 43114: (0, rpc_config_1.getFallbackRpcUrls)(43114), 8453: (0, rpc_config_1.getFallbackRpcUrls)(8453), 42161: (0, rpc_config_1.getFallbackRpcUrls)(42161), 137: (0, rpc_config_1.getFallbackRpcUrls)(137), }, }); console.log(`Vault fetching results:`); console.log(`- Total vaults: ${vaultFetchResult.coverageReport.totalVaults}`); console.log(`- Successfully fetched: ${vaultFetchResult.coverageReport.successfulVaults}`); console.log(`- Failed to fetch: ${vaultFetchResult.coverageReport.failedVaults}`); console.log(`- Success rate: ${vaultFetchResult.successRate.toFixed(2)}%`); if (vaultFetchResult.coverageReport.failedVaults > 0) { console.warn('Failed vaults:', vaultFetchResult.failed.map((f) => ({ address: f.address, chain: f.chain, error: f.error.message, attempts: f.attempts, }))); } const vaultResponses = vaultFetchResult.successful .sort((a, b) => a.index - b.index) .map((item) => item.data); const filteredResults = (0, utils_2.filterVaultsIntelligently)(vaultResponses, { includeClosed: true, includeInvisible: true, minStatus: ['active', 'closed'], }); if (this.monitoring?.env === 'DEV') { console.log(`Vault filtering results:`); console.log(`- Active vaults: ${filteredResults.summary.active}`); console.log(`- Closed vaults: ${filteredResults.summary.closed}`); console.log(`- Invisible vaults: ${filteredResults.summary.invisible}`); console.log(`- Filtered out: ${filteredResults.summary.failed}`); console.log(`- Overall success rate: ${filteredResults.summary.successRate.toFixed(2)}%`); } const filteredResponses = filteredResults.active; if ((options.wallet && (0, ethers_1.isAddress)(options.wallet)) || (options.solanaWallet && services_1.Solana.utils.isSolanaAddress(options.solanaWallet))) { const vaultResponses = await (0, utils_2.promiseSettle)(vaultsPerAvailableProviders.map((v) => (0, getters_1.getVaultPositions)({ vault: v.address, wallet: options.wallet, solanaWallet: options.solanaWallet, options: { rpcUrl: this.providers?.[v.chain], solanaService: this.solanaService, env: this.monitoring?.env, augustKey: this.keys?.august, subgraphKey: this.keys?.graph, }, })), 5, 2000); const positions = vaultResponses .flat() .filter((v) => v.status !== 'PENDING'); return filteredResponses.map((r) => ({ ...r, position: positions?.find((pos) => pos.vault?.toLowerCase() === r.address?.toLowerCase()) || null, })); } if (!!options.wallet && !(0, ethers_1.isAddress)(options.wallet)) console.warn('#getVaults: wallet passed is not of type address'); return filteredResponses; } async getVault({ vault, chainId, options, }) { if (!vault) throw new Error('Vault input parameter is undefined.'); if (typeof chainId !== 'undefined') { if (!this.providers?.[chainId]) console.error('#getVault:', 'missing rpcUrl in initialization for chainId', chainId); } const vaultResponse = await (0, getters_1.getVault)({ vault: vault, loans: typeof options?.loans !== 'undefined' ? options?.loans : true, allocations: typeof options?.allocations !== 'undefined' ? options?.allocations : true, options: { rpcUrl: chainId ? this.providers?.[chainId] : this.activeNetwork.rpcUrl, solanaService: this.solanaService, env: this.monitoring?.env, augustKey: this.keys?.august, subgraphKey: this.keys?.graph, headers: { 'x-environment': this.monitoring?.['x-environment'], 'x-user-id': this.monitoring?.['x-user-id'], }, }, }); if ((0, ethers_1.isAddress)(vault) && ((options.wallet && (0, ethers_1.isAddress)(options.wallet)) || (options.solanaWallet && services_1.Solana.utils.isSolanaAddress(options.solanaWallet)))) { const vaultResponses = await (0, getters_1.getVaultPositions)({ vault: vault, solanaWallet: options.solanaWallet, wallet: options.wallet, options: { rpcUrl: chainId ? this.providers?.[chainId] : this.activeNetwork.rpcUrl, solanaService: this.solanaService, env: this.monitoring?.env, augustKey: this.keys?.august, subgraphKey: this.keys?.graph, headers: { 'x-environment': this.monitoring?.['x-environment'], 'x-user-id': this.monitoring?.['x-user-id'], }, }, }); const positions = vaultResponses.filter((v) => v.status !== 'PENDING'); return { ...vaultResponse, position: positions?.find((pos) => pos.vault?.toLowerCase() === vault?.toLowerCase()) || null, }; } if (!!options.wallet && !(0, ethers_1.isAddress)(options.wallet)) console.warn('#getVaults: wallet passed is not of type address'); return vaultResponse; } async getVaultLoans({ vault, chainId, }) { if (!vault) throw new Error('Vault input parameter is undefined.'); if (!(0, ethers_1.isAddress)(vault)) throw new Error(`Vault input parameter is not an address: ${String(vault)}`); if (typeof chainId !== 'undefined') { if (!this.providers?.[chainId]) console.error('#getVaultLoans:', 'missing rpcUrl in initialization for chainId', chainId); } const vaultResponse = await (0, getters_1.getVaultLoans)(vault, { rpcUrl: chainId ? this.providers?.[chainId] : this.activeNetwork.rpcUrl, env: this.monitoring?.env, augustKey: this.keys?.august, subgraphKey: this.keys?.graph, chainId: chainId, solanaService: this.solanaService, headers: { 'x-environment': this.monitoring?.['x-environment'], 'x-user-id': this.monitoring?.['x-user-id'], }, }); return vaultResponse; } async getVaultAllocations({ vault, chainId, }) { if (!vault) throw new Error('Vault input parameter is undefined.'); if (!(0, ethers_1.isAddress)(vault)) throw new Error(`Vault input parameter is not an address: ${String(vault)}`); if (typeof chainId !== 'undefined') { if (!this.providers?.[chainId]) console.error('#getVaultAllocations:', 'missing rpcUrl in initialization for chainId', chainId); } try { const vaultResponse = await (0, getters_1.getVaultAllocations)(vault, { rpcUrl: chainId ? this.providers?.[chainId] : this.activeNetwork.rpcUrl, solanaService: this.solanaService, env: this.monitoring?.env, augustKey: this.keys?.august, subgraphKey: this.keys?.graph, headers: { 'x-environment': this.monitoring?.['x-environment'], 'x-user-id': this.monitoring?.['x-user-id'], }, }); return vaultResponse; } catch (e) { const err = e; if (err.message.includes('debank')) { return { status: 400, message: 'There was an error fetching from debank', }; } return { status: 400, message: 'There was an error fetching vaults', }; } } async getVaultApy(vault) { if (!vault) throw new Error('Vault input parameter is undefined.'); if (!(0, ethers_1.isAddress)(vault)) throw new Error(`Vault input parameter is not an address: ${String(vault)}`); return await (0, getters_1.getVaultApy)({ vault, options: { rpcUrl: this.activeNetwork.rpcUrl, subgraphKey: this.keys?.graph, headers: { 'x-environment': this.monitoring?.['x-environment'], 'x-user-id': this.monitoring?.['x-user-id'], }, }, }); } async getAvailableRedemptions({ vault, chainId, wallet, }) { if (!this.authorized) throw new Error('Not authorized.'); if (!vault) throw new Error('Vault input parameter is undefined.'); if (!(0, ethers_1.isAddress)(vault)) throw new Error(`Vault input parameter is not an address: ${String(vault)}`); return await (0, getters_1.getVaultAvailableRedemptions)({ vault, wallet, options: { rpcUrl: chainId ? this.providers?.[chainId] : this.activeNetwork.rpcUrl, solanaService: this.solanaService, env: this.monitoring?.env, augustKey: this.keys?.august, subgraphKey: this.keys?.graph, headers: { 'x-environment': this.monitoring?.['x-environment'], 'x-user-id': this.monitoring?.['x-user-id'], }, }, }); } async getPositions({ vault, wallet, chainId, showAllVaults, solanaWallet, options, }) { if (!(0, ethers_1.isAddress)(wallet) && !services_1.Solana.utils.isSolanaAddress(solanaWallet)) throw new Error(`Wallet parameter is not an address: ${String(wallet)} && ${String(solanaWallet)}`); if (vault) { return await (0, getters_1.getVaultPositions)({ vault, wallet, solanaWallet: solanaWallet, options: { rpcUrl: chainId ? this.providers?.[chainId] : this.activeNetwork.rpcUrl, solanaService: this.solanaService, env: this.monitoring?.env, augustKey: this.keys?.august, subgraphKey: this.keys?.graph, headers: { 'x-environment': this.monitoring?.['x-environment'], 'x-user-id': this.monitoring?.['x-user-id'], }, }, }); } const allVaults = await (0, utils_1.fetchTokenizedVaults)(undefined, { 'x-environment': this.monitoring?.['x-environment'], 'x-user-id': this.monitoring?.['x-user-id'], }); if (chainId) { const vaultsPerChain = allVaults.filter((v) => v.chain === chainId); const vaultResponses = await Promise.all(vaultsPerChain.map((v) => (0, getters_1.getVaultPositions)({ vault: v.address, solanaWallet: solanaWallet, wallet, options: { rpcUrl: this.providers?.[v.chain], solanaService: this.solanaService, env: this.monitoring?.env, augustKey: this.keys?.august, subgraphKey: this.keys?.graph, headers: { 'x-environment': this.monitoring?.['x-environment'], 'x-user-id': this.monitoring?.['x-user-id'], }, }, }))); const flattened = vaultResponses.flat(); let final; if (showAllVaults) final = flattened; else final = flattened.filter((v) => v?.status !== 'PENDING'); return final; } const vaultsPerAvailableProviders = allVaults.filter((v) => !!this.providers?.[v?.chain] ? true : false); const vaultResponses = await Promise.all(vaultsPerAvailableProviders.map((v) => (0, getters_1.getVaultPositions)({ vault: v.address, solanaWallet: solanaWallet, wallet, options: { rpcUrl: this.providers?.[v.chain], solanaService: this.solanaService, env: this.monitoring?.env, augustKey: this.keys?.august, subgraphKey: this.keys?.graph, headers: { 'x-environment': this.monitoring?.['x-environment'], 'x-user-id': this.monitoring?.['x-user-id'], }, }, }))); const flattened = vaultResponses.flat(); let final; if (showAllVaults) final = flattened; else final = flattened.filter((v) => v?.status !== 'PENDING'); return final; } async getUserHistory({ wallet, chainId, vault, options, }) { if (!(0, ethers_1.isAddress)(wallet)) throw new Error(`Wallet parameter is not an address: ${String(wallet)}`); const _chainId = chainId || this.activeNetwork.chainId; let finalArray = []; function formatHistory(history) { return history.map((h) => ({ timestamp: Number(h.timestamp_), address: h.address, amount: (0, utils_1.toNormalizedBn)(BigInt(h.amount), h.decimals), pool: h.contractId_, chainId: _chainId, type: h.type, transactionHash: h.transactionHash_, })); } if (vault) { const provider = (0, utils_1.createProvider)(this.providers?.[chainId]); const userHistory = await (0, services_1.getSubgraphUserHistory)(wallet, provider, vault); finalArray = formatHistory(userHistory); } else { const allVaults = await (0, utils_1.fetchTokenizedVaults)(undefined, { 'x-environment': this.monitoring?.['x-environment'], 'x-user-id': this.monitoring?.['x-user-id'], }); if (chainId) { const vaultsPerChain = allVaults.filter((v) => v.chain === chainId); const vaultResponses = await Promise.all(vaultsPerChain.map(async (v) => { const provider = (0, utils_1.createProvider)(this.providers?.[v.chain]); const userHistory = await (0, services_1.getSubgraphUserHistory)(wallet, provider, v.address); return formatHistory(userHistory); })); const flattened = vaultResponses.flat(); finalArray = flattened; } else { const vaultsPerAvailableProviders = allVaults.filter((v) => !!this.providers?.[v?.chain] ? true : false); const vaultResponses = await Promise.all(vaultsPerAvailableProviders.map(async (v) => { const provider = (0, utils_1.createProvider)(this.providers?.[v.chain]); const userHistory = await (0, services_1.getSubgraphUserHistory)(wallet, provider, v.address); return formatHistory(userHistory); })); const flattened = vaultResponses.flat(); finalArray = flattened; } } if (this.monitoring?.env === 'DEV') console.log(`#getUserHistory:`, finalArray.slice(0, 1)); return finalArray; } async getUserTransfers({ wallet, chainId, vault, options, }) { if (!(0, ethers_1.isAddress)(wallet)) throw new Error(`Wallet parameter is not an address: ${String(wallet)}`); let finalArray = []; function formatTransfers(transfers) { return transfers.map((t) => ({ id: t.id, value: t.value, to: t.to, from: t.from, pool: t.contractId_, block: Number(t.block_number), timestamp: Number(t.timestamp_), transactionHash: t.transactionHash_, })); } if (vault) { const provider = (0, utils_1.createProvider)(this.providers?.[chainId]); const userHistory = await (0, services_1.getSubgraphUserTransfers)(wallet, provider, vault); finalArray = formatTransfers(userHistory); } else { const allVaults = await (0, utils_1.fetchTokenizedVaults)(undefined, { 'x-environment': this.monitoring?.['x-environment'], 'x-user-id': this.monitoring?.['x-user-id'], }); if (chainId) { const vaultsPerChain = allVaults.filter((v) => v.chain === chainId); const vaultResponses = await Promise.all(vaultsPerChain.map(async (v) => { const provider = (0, utils_1.createProvider)(this.providers?.[v.chain]); const userHistory = await (0, services_1.getSubgraphUserTransfers)(wallet, provider, v.address); return userHistory; })); const flattened = vaultResponses.flat(); finalArray = formatTransfers(flattened); } else { const vaultsPerAvailableProviders = allVaults.filter((v) => !!this.providers?.[v?.chain] ? true : false); const vaultResponses = await Promise.all(vaultsPerAvailableProviders.map(async (v) => { const provider = (0, utils_1.createProvider)(this.providers?.[v.chain]); const userHistory = await (0, services_1.getSubgraphUserTransfers)(wallet, provider, v.address); return userHistory; })); const flattened = vaultResponses.flat(); finalArray = formatTransfers(flattened); } } if (this.monitoring?.env === 'DEV') console.log(`#getUserTransfers:`, finalArray.slice(0, 1)); return finalArray; } async getStakingPositions(wallet, chainId) { if (chainId) { const positions = await (0, getters_1.getRewardsStakingPositions)({ rpcUrl: this.providers?.[chainId] || this.activeNetwork.rpcUrl, wallet, }); return positions; } const positions = await Promise.all(Object.values(this.providers).map((rpcUrl) => { return (0, getters_1.getRewardsStakingPositions)({ rpcUrl: chainId ? this.providers?.[chainId] : rpcUrl || this.activeNetwork.rpcUrl, wallet, }); })); return positions.flat(); } getVaultExposure(debankResponse) { const borrowing_exposure = []; const supplying_exposure = []; const wallet_exposure = []; const positions = debankResponse?.subaccount?.positions ?? []; const tokens = debankResponse?.subaccount?.tokens ?? []; for (const position of positions) { const portfolioItems = position?.portfolio_item_list ?? []; for (const item of portfolioItems) { const borrowTokens = item?.detail?.borrow_token_list ?? []; const supplyTokens = item?.detail?.supply_token_list ?? []; for (const token of tokens) { if (token?.symbol && token?.is_core) { wallet_exposure.push({ symbol: token.symbol, chain: token.chain, amount: token.amount * token.price, }); } } for (const token of borrowTokens) { if (token?.symbol && !token.is_suspicious && !token.is_scam && token?.is_core) { borrowing_exposure.push({ symbol: token.symbol, chain: token.chain, amount: token.amount * token.price, }); } } for (const token of supplyTokens) { if (token?.symbol && !token.is_suspicious && !token.is_scam && token?.is_core) { supplying_exposure.push({ symbol: token.symbol, chain: token.chain, amount: token.amount * token.price, }); } } } } return { borrowing_exposure, supplying_exposure, wallet_exposure }; } async allowance(pool, signer) { if (!(0, ethers_1.isAddress)(pool)) return; const wallet = (await signer.getAddress()); return await (0, user_actions_1.allowance)(signer, { pool, wallet, wait: true }); } async approve(pool, signer, inputParams) { if (!(0, ethers_1.isAddress)(pool)) return; const wallet = (await signer.getAddress()); return await (0, user_actions_1.approve)(signer, { pool, wallet, wait: true, amount: inputParams.amount, }); } async deposit(pool, signer, inputParams, solana) { if (services_1.Solana.utils.isSolanaAddress(pool)) { const vaultState = await this.solanaService.getVaultStateReadOnly(pool, services_1.Solana.constants.vaultIdl); const solanaTx = await this.solanaService.handleDeposit(pool, services_1.Solana.constants.vaultIdl, signer, Number(inputParams.amount), vaultState.vaultState.depositMint, solana?.sendTransaction); return solanaTx; } if (typeof signer === 'string') return; const wallet = (await signer.getAddress()); return await (0, user_actions_1.deposit)(signer, { amount: inputParams.amount, wallet, pool: pool, wait: true, }); } async requestWithdrawal(pool, signer) { const wallet = (await signer.getAddress()); return await (0, user_actions_1.requestRedeem)(signer, { pool, wallet, wait: true }); } async withdraw(pool, signer, inputParams, solana) { if (services_1.Solana.utils.isSolanaAddress(pool)) { const vaultState = await this.solanaService.getVaultStateReadOnly(pool, services_1.Solana.constants.vaultIdl); const solanaTx = await this.solanaService.handleRedeem(pool, services_1.Solana.constants.vaultIdl, signer, Number(inputParams.amount), vaultState.vaultState.depositMint, solana?.sendTransaction); return solanaTx; } if (typeof signer === 'string') return; if (!(inputParams.day && inputParams.month && inputParams.year && inputParams.receiverIndex)) return; const wallet = (await signer.getAddress()); return await (0, user_actions_1.redeem)(signer, { wallet, pool, ...inputParams, wait: true, }); } } exports.AugustVaults = AugustVaults; //# sourceMappingURL=main.js.map