@augustdigital/vaults
Version:
JS SDK for web3 interactions with the August Digital Lending Pools
586 lines • 26.9 kB
JavaScript
"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