assembly/composables/protocols/useMakerdaoPosition.ts
Georges KABBOUCHI fe9ba6d716 wip
2021-08-31 22:23:47 +03:00

324 lines
8.2 KiB
TypeScript

import { computed, Ref, ref, watch } from "@nuxtjs/composition-api";
import BigNumber from "bignumber.js";
BigNumber.config({ POW_PRECISION: 200 });
import abis from "~/constant/abis";
import addresses from "~/constant/addresses";
import makerVaults from "~/constant/tokens/vaults";
import { useBigNumber } from "~/composables/useBigNumber";
import { useDSA } from "~/composables/useDSA";
import { useToken } from "~/composables/useToken";
import { useWeb3 } from "@kabbouchi/vue-web3";
import { AbiItem } from "web3-utils";
const defaultVault = {
id: null,
tokenKey: "eth",
token: "ETH",
collateralName: "ETH-A",
collateral: "0",
debt: "0",
liquidatedCollateral: "0",
status: "0",
rate: "0",
liquidation: "0",
price: "0",
netvalue: "0"
};
const vaultId = ref(null);
const vaults = ref([]);
const isNewVault = ref(false);
const vaultTypes = ref([]);
const vaultType = ref("");
const vault = computed(() => {
const vlt = vaults.value.find(v => v.id === vaultId.value);
if (!isNewVault.value && !!vlt) {
return vlt;
}
const vt = vaultTypes.value.find(vt => vt.type === vaultType.value);
if (vt) {
return { ...defaultVault, ...vt };
}
const defaultVaultType = vaultTypes.value[0];
if (defaultVaultType) {
return { ...defaultVault, ...defaultVaultType };
}
return defaultVault;
});
export function useMakerdaoPosition(
collateralAmountRef: Ref = null,
debtAmountRef: Ref = null
) {
const { library } = useWeb3();
const { activeAccount } = useDSA();
const { isZero, ensureValue, times, div, max, gt } = useBigNumber();
const { getTokenByKey } = useToken();
const vaultTokenType = computed(() => vault.value.vaultTokenType);
const price = computed(() => ensureValue(vault.value.price).toFixed());
const collateralUsd = computed(() =>
times(collateral.value, price.value).toFixed()
);
const collateral = computed(() =>
ensureValue(vault.value.collateral).toFixed()
);
const liquidation = computed(() =>
ensureValue(vault.value.liquidation).toFixed()
);
const tokenKey = computed(() => vault.value.tokenKey);
const token = computed(() => getTokenByKey(tokenKey.value));
const symbol = computed(() => token.value.symbol ?? "ETH");
const rate = computed(() => ensureValue(vault.value.rate).toFixed());
const netValue = computed(() => ensureValue(vault.value.netValue).toFixed());
const status = computed(() => {
if (!collateralAmountRef || !debtAmountRef)
return ensureValue(vault.value.status).toFixed();
return isZero(collateralAmountRef.value) && !isZero(debtAmountRef.value)
? "1.1"
: div(
debtAmountRef.value,
times(collateralAmountRef.value, price.value)
).toFixed();
});
const liquidationPrice = computed(() => {
if (!collateralAmountRef || !debtAmountRef)
return max(
div(div(debt.value, collateral.value), liquidation.value),
"0"
).toFixed();
return isZero(collateralAmountRef.value) && !isZero(debtAmountRef.value)
? times(price.value, "1.1").toFixed()
: max(
div(
div(debtAmountRef.value, collateralAmountRef.value),
liquidation.value
),
"0"
).toFixed();
});
const debt = computed(() => ensureValue(vault.value.debt).toFixed());
const minDebt = computed(() => vaultTypes.value[0]?.totalFloor.toString() || "5000");
const debtCeilingReached = computed(() =>
vaultTypes.value?.some(v =>
gt(v.overallTotalDebt, v.overallTotalDebtCeiling)
)
);
const fetchPosition = async () => {
if (!library.value) {
return;
}
vaultTypes.value = await getVaultTypes(library.value);
if (!activeAccount.value) {
return;
}
vaults.value = await getVaults(activeAccount.value.address, library.value);
if (vaults.value.length > 0 && !vaultId.value) {
vaultId.value = vaults.value[0].id;
}
};
watch(
library,
async val => {
if (val) {
fetchPosition();
}
},
{ immediate: true }
);
watch(
activeAccount,
async val => {
if (val) {
fetchPosition();
}
},
{ immediate: true }
);
const selectVault = vid => {
if (vid === vaultId.value && !isNewVault.value) return;
vaultId.value = vid;
isNewVault.value = false;
};
return {
fetchPosition,
vaultId: computed(() => (isNewVault.value ? "0" : vaultId.value || "0")),
selectVault,
vaultTokenType,
vault,
vaults,
vaultType,
vaultTypes,
isNewVault,
collateralUsd,
collateral,
price,
liquidation,
tokenKey,
token,
symbol,
rate,
netValue,
status,
liquidationPrice,
liquidationMaxPrice: price,
debt,
minDebt,
debtCeilingReached
};
}
async function getVaultTypes(web3) {
const makerResolveABI = abis.resolver.maker;
const makerResolveAddr = addresses.mainnet.resolver.maker;
const makerResolverInstance = new web3.eth.Contract(
makerResolveABI as AbiItem[],
makerResolveAddr
);
try {
const rawData: any[] = await makerResolverInstance.methods
.getColInfo(makerVaults.types)
.call();
return makerVaults.allVaults.map(
({ type, token, key: tokenKey, disabled, vaultTokenType }, i) => {
const [
rate,
price,
ratioCbyD,
debtCeiling,
totalFloor,
totalDebt,
overallTotalDebtCeiling,
overallTotalDebt
] = rawData[i];
return {
type,
token,
tokenKey,
disabled,
vaultTokenType,
rate: calRate(rate),
price: new BigNumber(price).dividedBy(1e27).toFixed(),
liquidation: new BigNumber(1)
.dividedBy(new BigNumber(ratioCbyD).dividedBy(1e27))
.toFixed(),
debtCeiling: debtCeiling,
totalDebt: new BigNumber(totalFloor)
.dividedBy(1e18)
.multipliedBy(1.00002)
.toFixed(),
totalFloor: new BigNumber(totalDebt).dividedBy(1e45),
overallTotalDebtCeiling: new BigNumber(
overallTotalDebtCeiling
).dividedBy(1e45),
overallTotalDebt: new BigNumber(overallTotalDebt).dividedBy(1e45)
};
}
);
} catch (error) {
console.error(error);
return [];
}
}
async function getVaults(user, web3) {
try {
const makerResolveABI = abis.resolver.maker;
const makerResolveAddr = addresses.mainnet.resolver.maker;
const makerResolverInstance = new web3.eth.Contract(
makerResolveABI as AbiItem[],
makerResolveAddr
);
const rawData: any[] = await makerResolverInstance.methods
.getVaults(user)
.call();
return rawData.map(
([
id,
owner,
type,
collInWei,
,
debtInWei,
liquidatedColInWei,
ratePerBlock,
priceInWei,
liquidationRatioCbyD,
urn
]) => {
const collateral = new BigNumber(collInWei).dividedBy(1e18);
const debt = new BigNumber(debtInWei).dividedBy(1e18);
const price = new BigNumber(priceInWei).dividedBy(1e27);
const vault = makerVaults.getVaultByType(type);
return {
id,
owner,
type,
tokenKey: vault.key,
token: vault.token,
vaultTokenType: vault.vaultTokenType,
collateral: collateral.toFixed(),
debt: debt.toFixed(),
liquidatedCollateral: new BigNumber(liquidatedColInWei)
.dividedBy(1e18)
.toFixed(),
rate: calRate(ratePerBlock),
price: price.toFixed(),
liquidation: new BigNumber(1)
.dividedBy(new BigNumber(liquidationRatioCbyD).dividedBy(1e27))
.toFixed(),
urn,
netValue: collateral
.multipliedBy(price)
.minus(debt)
.toFixed(),
status: collateral.isZero()
? "0"
: debt.dividedBy(collateral.multipliedBy(price)).toFixed()
};
}
);
} catch (error) {
console.error(error);
return [];
}
}
function calRate(ilkRate) {
try {
return new BigNumber(ilkRate)
.dividedBy(1e27)
.pow(31545000)
.minus(1)
.toFixed(18);
} catch (error) {
console.log("error", error);
}
}