diff --git a/src/parachain/vaults.ts b/src/parachain/vaults.ts index dc02c8303..8859698d2 100644 --- a/src/parachain/vaults.ts +++ b/src/parachain/vaults.ts @@ -8,6 +8,7 @@ import { VaultRegistrySystemVault, InterbtcPrimitivesVaultId, VaultRegistryVault, + InterbtcPrimitivesVaultCurrencyPair, } from "@polkadot/types/lookup"; import { @@ -22,6 +23,7 @@ import { currencyIdToMonetaryCurrency, decodeRpcVaultId, addressOrPairAsAccountId, + storageKeyToNthInner, } from "../utils"; import { TokensAPI } from "./tokens"; import { OracleAPI } from "./oracle"; @@ -85,14 +87,13 @@ export interface VaultsAPI { newCollateral?: MonetaryAmount, onlyIssued?: boolean ): Promise; - // /** - // * Get the total system collateralization measured by dividing the value of issued (wrapped) tokens - // * by the value of total locked collateral. - // * - // * @returns The total system collateralization - // */ - // TODO: Uncomment once implemented - // getSystemCollateralization(): Promise; + /** + * Get the total system collateralization measured by dividing the value of issued (wrapped) tokens + * by the value of total locked collateral. + * + * @returns The total system collateralization + */ + getSystemCollateralization(): Promise; /** * Get the amount of collateral required for the given vault to be at the * current SecureCollateralThreshold with the current exchange rate @@ -752,8 +753,23 @@ export class DefaultVaultsAPI implements VaultsAPI { } async getSystemCollateralization(): Promise { - // TODO: Implement once method of calculation is decided on - return Promise.resolve(undefined); + const issuedTokens = await this.tokensAPI.total(this.wrappedCurrency); + const totalCollateralEntries = await this.api.query.vaultRegistry.totalUserVaultCollateral.entries(); + const totalWrappedEntries = await Promise.all(totalCollateralEntries + .map(([key, value]): [InterbtcPrimitivesVaultCurrencyPair, string] => [storageKeyToNthInner(key), value.toString()]) + .map(async ([currencyPair, balance]) => { + const collateralCurrency = await currencyIdToMonetaryCurrency( + this.assetRegistryAPI, + this.loansAPI, + currencyPair.collateral + ); + const collateralAmount = newMonetaryAmount(balance, collateralCurrency); + // TODO: we can probably use multiQuery for this + return this.oracleAPI.convertCollateralToWrapped(collateralAmount); + })); + const totalCollateralAsWrapped = totalWrappedEntries + .reduce((prev, curr) => prev.add(curr), newMonetaryAmount(0, this.wrappedCurrency)); + return totalCollateralAsWrapped.div(issuedTokens.toBig()).toBig(); } async getRequiredCollateralForVault( diff --git a/test/integration/parachain/staging/sequential/vaults.test.ts b/test/integration/parachain/staging/sequential/vaults.test.ts index 64709a7df..2d3fd77a3 100644 --- a/test/integration/parachain/staging/sequential/vaults.test.ts +++ b/test/integration/parachain/staging/sequential/vaults.test.ts @@ -408,4 +408,10 @@ describe("vaultsAPI", () => { await assertVaultStatus(vault_1_id, VaultStatusExt.Active); } }); + + it("should get system collateralization", async () => { + const value = await interBtcAPI.vaults.getSystemCollateralization(); + assert.isDefined(value, "System collateralization is not defined") + assert.isTrue(value!.gt(0), "Invalid collateralization") + }); });