@moonwell-fi/moonwell-sdk
Version:
TypeScript Interface for Moonwell
210 lines • 9.69 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.transformVaultFromIndexer = transformVaultFromIndexer;
exports.transformVaultsFromIndexer = transformVaultsFromIndexer;
exports.fetchTokenMap = fetchTokenMap;
exports.fetchVaultsFromIndexer = fetchVaultsFromIndexer;
exports.fetchVaultFromIndexer = fetchVaultFromIndexer;
exports.fetchVaultSnapshotsFromIndexer = fetchVaultSnapshotsFromIndexer;
exports.getV1VaultKey = getV1VaultKey;
exports.transformVaultSnapshotsFromIndexer = transformVaultSnapshotsFromIndexer;
const amount_js_1 = require("../../../common/amount.js");
function buildTokenConfig(token) {
return {
address: token.address,
symbol: token.symbol,
name: token.name,
decimals: token.decimals,
};
}
function buildVaultTokenConfig(vault) {
return {
address: vault.address,
symbol: vault.symbol,
name: vault.name,
decimals: vault.decimals,
};
}
function transformMarket(market, underlyingDecimals, totalAssets, tokenMap) {
const collateralToken = tokenMap.get(market.marketCollateral.toLowerCase());
const vaultSupplied = Number.parseFloat(market.vaultSupplied);
const allocation = totalAssets > 0 ? vaultSupplied / totalAssets : 0;
return {
marketId: market.marketId,
allocation,
marketApy: Number.parseFloat(market.marketApy),
marketLoanToValue: Number.parseFloat(market.marketLltv),
marketCollateral: collateralToken
? buildTokenConfig(collateralToken)
: {
address: market.marketCollateral,
symbol: market.marketCollateralSymbol,
name: market.marketCollateralName,
decimals: 18,
},
marketLiquidity: new amount_js_1.Amount(Number.parseFloat(market.marketLiquidity), underlyingDecimals),
marketLiquidityUsd: Number.parseFloat(market.marketLiquidityUsd),
totalSupplied: new amount_js_1.Amount(vaultSupplied, underlyingDecimals),
totalSuppliedUsd: Number.parseFloat(market.vaultSuppliedUsd),
rewards: [],
};
}
function transformRewards(rewards, tokenMap) {
return rewards.map((reward) => {
const token = tokenMap.get(reward.token.toLowerCase());
return {
asset: token
? buildTokenConfig(token)
: {
address: reward.token,
symbol: reward.tokenSymbol,
name: reward.tokenSymbol,
decimals: 18,
},
supplyApr: Number.parseFloat(reward.apr),
supplyAmount: 0,
borrowApr: 0,
borrowAmount: 0,
};
});
}
function findVaultConfigByAddress(environment, address) {
const vaultKey = Object.keys(environment.config.vaults).find((key) => environment.config.tokens[key]?.address.toLowerCase() ===
address.toLowerCase());
return {
key: vaultKey,
config: vaultKey ? environment.config.vaults[vaultKey] : undefined,
};
}
function transformVaultFromIndexer(indexerVault, environment, tokenMap) {
const underlyingToken = indexerVault.underlyingToken ||
tokenMap.get(indexerVault.underlyingTokenAddress.toLowerCase());
if (!underlyingToken) {
throw new Error(`Underlying token not found: ${indexerVault.underlyingTokenAddress}`);
}
const underlyingDecimals = underlyingToken.decimals;
const { key: vaultKey, config: vaultConfig } = findVaultConfigByAddress(environment, indexerVault.address);
const sdkVaultTokenConfig = vaultConfig
? environment.config.tokens[vaultConfig.vaultToken]
: undefined;
const sdkUnderlyingTokenConfig = vaultConfig
? environment.config.tokens[vaultConfig.underlyingToken]
: undefined;
const version = vaultConfig?.version ?? 1;
const totalAssetsValue = Number.parseFloat(indexerVault.totalAssets);
const totalLiquidityValue = Number.parseFloat(indexerVault.totalLiquidity);
const vaultSupplyValue = Math.max(0, totalAssetsValue - totalLiquidityValue);
const markets = indexerVault.markets.map((market) => transformMarket(market, underlyingDecimals, totalAssetsValue, tokenMap));
const rewards = transformRewards(indexerVault.rewards, tokenMap);
const vault = {
chainId: indexerVault.chainId,
vaultKey: vaultKey || `unknown_${indexerVault.address}`,
version,
deprecated: vaultConfig?.deprecated ?? false,
vaultToken: sdkVaultTokenConfig ?? buildVaultTokenConfig(indexerVault),
underlyingToken: sdkUnderlyingTokenConfig ?? buildTokenConfig(underlyingToken),
totalSupply: new amount_js_1.Amount(totalAssetsValue, underlyingDecimals),
totalLiquidity: new amount_js_1.Amount(totalLiquidityValue, underlyingDecimals),
vaultSupply: new amount_js_1.Amount(vaultSupplyValue, underlyingDecimals),
totalSupplyUsd: Number.parseFloat(indexerVault.totalAssetsUsd),
totalLiquidityUsd: Number.parseFloat(indexerVault.totalLiquidityUsd),
underlyingPrice: Number.parseFloat(indexerVault.underlyingPrice),
baseApy: Number.parseFloat(indexerVault.baseApy),
rewardsApy: Number.parseFloat(indexerVault.rewardsApy),
totalApy: Number.parseFloat(indexerVault.totalApy),
performanceFee: Number.parseFloat(indexerVault.performanceFee) / 100,
timelock: Number.parseInt(indexerVault.timelock) / (60 * 60),
curators: indexerVault.curators || [],
markets,
rewards,
totalStaked: new amount_js_1.Amount(0n, underlyingDecimals),
totalStakedUsd: 0,
stakingRewardsApr: 0,
totalStakingApr: Number.parseFloat(indexerVault.baseApy),
stakingRewards: [],
};
return vault;
}
function transformVaultsFromIndexer(indexerVaults, environment, tokenMap) {
return indexerVaults.map((vault) => transformVaultFromIndexer(vault, environment, tokenMap));
}
async function fetchTokenMap(lunarIndexerUrl, chainId) {
const url = `${lunarIndexerUrl}/api/v1/vaults/tokens/${chainId}`;
const response = await fetch(url, { signal: AbortSignal.timeout(10_000) });
if (!response.ok) {
throw new Error(`Failed to fetch tokens from Lunar Indexer: ${response.status} ${response.statusText}`);
}
const data = await response.json();
const tokenMap = new Map();
for (const token of data.results) {
tokenMap.set(token.address.toLowerCase(), token);
}
return tokenMap;
}
async function fetchVaultsFromIndexer(lunarIndexerUrl, chainId, options) {
const params = new URLSearchParams();
if (options?.limit)
params.set("limit", options.limit.toString());
if (options?.cursor)
params.set("cursor", options.cursor);
if (options?.includeRewards)
params.set("includeRewards", "true");
const url = `${lunarIndexerUrl}/api/v1/vaults/vaults/${chainId}${params.toString() ? `?${params.toString()}` : ""}`;
const response = await fetch(url, { signal: AbortSignal.timeout(10_000) });
if (!response.ok) {
throw new Error(`Failed to fetch vaults from Lunar Indexer: ${response.status} ${response.statusText}`);
}
return response.json();
}
async function fetchVaultFromIndexer(lunarIndexerUrl, vaultId) {
const url = `${lunarIndexerUrl}/api/v1/vaults/vault/${vaultId}`;
const response = await fetch(url, { signal: AbortSignal.timeout(10_000) });
if (!response.ok) {
throw new Error(`Failed to fetch vault from Lunar Indexer: ${response.status} ${response.statusText}`);
}
return response.json();
}
async function fetchVaultSnapshotsFromIndexer(lunarIndexerUrl, vaultId, options) {
const params = new URLSearchParams();
if (options?.cursor)
params.set("cursor", options.cursor);
if (options?.limit)
params.set("limit", options.limit.toString());
if (options?.granularity)
params.set("granularity", options.granularity);
if (options?.startTime)
params.set("startTime", options.startTime.toString());
if (options?.endTime)
params.set("endTime", options.endTime.toString());
const queryString = params.toString();
const url = `${lunarIndexerUrl}/api/v1/vaults/vault/${vaultId}/snapshots${queryString ? `?${queryString}` : ""}`;
const response = await fetch(url, { signal: AbortSignal.timeout(10_000) });
if (!response.ok) {
throw new Error(`Failed to fetch vault snapshots from Lunar Indexer: ${response.status} ${response.statusText}`);
}
return response.json();
}
function getV1VaultKey(environment, vaultKey) {
const rawKey = environment.config.vaults[vaultKey]?.v1VaultKey;
return typeof rawKey === "string" ? rawKey : undefined;
}
function transformVaultSnapshotsFromIndexer(snapshots, chainId) {
return snapshots.map((snapshot) => {
const totalAssets = Number.parseFloat(snapshot.totalAssets);
const totalAssetsUsd = Number.parseFloat(snapshot.totalAssetsUsd);
const totalLiquidity = Number.parseFloat(snapshot.totalLiquidity);
const totalLiquidityUsd = Number.parseFloat(snapshot.totalLiquidityUsd);
return {
chainId,
vaultAddress: snapshot.vaultAddress.toLowerCase(),
totalSupply: totalAssets,
totalSupplyUsd: totalAssetsUsd,
totalBorrows: totalAssets - totalLiquidity,
totalBorrowsUsd: totalAssetsUsd - totalLiquidityUsd,
totalLiquidity,
totalLiquidityUsd,
timestamp: snapshot.timestamp * 1000,
};
});
}
//# sourceMappingURL=lunarIndexerTransform.js.map