assembly/composables/protocols/useReflexerPosition.ts
2021-09-07 21:35:52 +03:00

347 lines
9.0 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 reflexerSafes from "~/constant/tokens/safes";
import { useBigNumber } from "~/composables/useBigNumber";
import { useDSA } from "~/composables/useDSA";
import { useToken } from "~/composables/useToken";
import { useWeb3 } from "@instadapp/vue-web3";
import { AbiItem } from "web3-utils";
import { useBalances } from "../useBalances";
const defaultSafe = {
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 oracleRelayerAddress = "0x4ed9C0dCa0479bC64d8f4EB3007126D5791f7851";
const safeId = ref(null);
const safes = ref([]);
const isNewSafe = ref(false);
const safeTypes = ref([]);
const safeType = ref("");
const safe = computed(() => {
const vlt = safes.value.find(v => v.id === safeId.value);
if (!isNewSafe.value && !!vlt) {
return vlt;
}
const vt = safeTypes.value.find(vt => vt.type === safeType.value);
if (vt) {
return { ...defaultSafe, ...vt };
}
const defaultSafeType = safeTypes.value[0];
if (defaultSafeType) {
return { ...defaultSafe, ...defaultSafeType };
}
return defaultSafe;
});
export function useReflexerPosition(
collateralAmountRef: Ref = null,
debtAmountRef: Ref = null
) {
const { library } = useWeb3();
const { activeAccount } = useDSA();
const { isZero, ensureValue, times, div, max, gt, toBN } = useBigNumber();
const { getTokenByKey } = useToken();
const { prices } = useBalances();
const raiToken = computed(() => getTokenByKey("rai"));
const raiInUsd = computed(() =>
raiToken.value ? prices.mainnet[raiToken.value.address] || "0" : "0"
);
const safeTokenType = computed(() => safe.value.safeTokenType);
const price = computed(() => ensureValue(safe.value.price).toFixed());
const spotPrice = computed(() => ensureValue(safe.value.spotPrice).toFixed());
const collateralUsd = computed(() =>
times(collateral.value, price.value).toFixed()
);
const collateral = computed(() =>
ensureValue(safe.value.collateral).toFixed()
);
const liquidation = computed(() =>
ensureValue(safe.value.liquidation).toFixed()
);
const tokenKey = computed(() => safe.value.tokenKey);
const token = computed(() => getTokenByKey(tokenKey.value));
const symbol = computed(() => token.value.symbol ?? "ETH");
const rate = computed(() => ensureValue(safe.value.rate).toFixed());
const netValue = computed(() => ensureValue(safe.value.netValue).toFixed());
const status = computed(() => {
if (!collateralAmountRef || !debtAmountRef)
return ensureValue(safe.value.status).toFixed();
return isZero(collateralAmountRef.value) && !isZero(debtAmountRef.value)
? "1.1"
: div(
debtAmountRef.value,
times(collateralAmountRef.value, spotPrice.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),
toBN(liquidation.value)
.multipliedBy(spotPrice.value)
.dividedBy(price.value)
),
"0"
).toFixed();
});
const debt = computed(() => ensureValue(safe.value.debt).toFixed());
const debtUsd = computed(() =>
times(debt.value, raiInUsd.value).toFixed()
);
const minDebt = computed(
() => safeTypes.value[0]?.totalDebt?.toString() || "699"
);
const debtCeilingReached = computed(() =>
safeTypes.value?.some(v =>
gt(v.overallTotalDebt, v.overallTotalDebtCeiling)
)
);
const fetchPosition = async () => {
if (!library.value) {
return;
}
safeTypes.value = await getSafeTypes(library.value);
if (!activeAccount.value) {
return;
}
safes.value = await getSafes(activeAccount.value.address, library.value);
if (safes.value.length > 0 && !safeId.value) {
safeId.value = safes.value[0].id;
}
};
watch(
library,
async val => {
if (val) {
fetchPosition();
}
},
{ immediate: true }
);
watch(
activeAccount,
async val => {
if (val) {
fetchPosition();
}
},
{ immediate: true }
);
const selectSafe = vid => {
if (vid === safeId.value && !isNewSafe.value) return;
safeId.value = vid;
isNewSafe.value = false;
};
return {
fetchPosition,
safeId: computed(() => (isNewSafe.value ? "0" : safeId.value || "0")),
selectSafe,
safeTokenType,
safe,
safes,
safeType,
safeTypes,
isNewSafe,
collateralUsd,
collateral,
price,
raiInUsd,
liquidation,
tokenKey,
token,
symbol,
rate,
netValue,
status,
liquidationPrice,
liquidationMaxPrice: price,
debt,
debtUsd,
minDebt,
debtCeilingReached
};
}
async function getSafeTypes(web3) {
const reflexerResolveABI = abis.resolver.reflexer;
const reflexerResolveAddr = addresses.mainnet.resolver.reflexer;
const reflexerResolverInstance = new web3.eth.Contract(
reflexerResolveABI as AbiItem[],
reflexerResolveAddr
);
try {
const rawData: any[] = await reflexerResolverInstance.methods
.getColInfo(reflexerSafes.types)
.call();
const rawRedemptionPrice = await web3.eth.getStorageAt(
oracleRelayerAddress,
4
);
return reflexerSafes.allSafes.map(
({ type, token, key: tokenKey, disabled, safeTokenType }, i) => {
const [rate, price, ratioCbyD, debtCeiling, totalDebt] = rawData[i];
return {
type,
token,
tokenKey,
disabled,
safeTokenType,
rate: calRate(rate),
redemptionPrice: new BigNumber(rawRedemptionPrice)
.dividedBy(1e27)
.toFixed(),
spotPrice: new BigNumber(price).dividedBy(1e27).toFixed(),
price: new BigNumber(price)
.times(rawRedemptionPrice)
.dividedBy(1e54)
.toFixed(),
liquidation: new BigNumber(1)
.dividedBy(new BigNumber(ratioCbyD).dividedBy(1e27))
.toFixed(),
debtCeiling: debtCeiling,
totalDebt: new BigNumber(totalDebt).multipliedBy(1.00002).toFixed()
};
}
);
} catch (error) {
console.error(error);
return [];
}
}
async function getSafes(user, web3) {
try {
const reflexerResolveABI = abis.resolver.reflexer;
const reflexerResolveAddr = addresses.mainnet.resolver.reflexer;
const reflexerResolverInstance = new web3.eth.Contract(
reflexerResolveABI as AbiItem[],
reflexerResolveAddr
);
const rawData: any[] = await reflexerResolverInstance.methods
.getSafes(user)
.call();
const rawRedemptionPrice = await web3.eth.getStorageAt(
oracleRelayerAddress,
4
);
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 spotPrice = new BigNumber(priceInWei).dividedBy(1e27);
const price = new BigNumber(priceInWei)
.times(rawRedemptionPrice)
.dividedBy(1e54);
const safe = reflexerSafes.getSafeByType(type);
return {
id,
owner,
type,
tokenKey: safe.key,
token: safe.token,
safeTokenType: safe.safeTokenType,
collateral: collateral.toFixed(),
debt: debt.toFixed(),
liquidatedCollateral: new BigNumber(liquidatedColInWei)
.dividedBy(1e18)
.toFixed(),
rate: calRate(ratePerBlock),
price: price.toFixed(),
spotPrice,
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(spotPrice)).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);
}
}