diff --git a/abis/read/benqi.json b/abis/read/benqi.json new file mode 100644 index 0000000..0b1dac3 --- /dev/null +++ b/abis/read/benqi.json @@ -0,0 +1,397 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address[]", + "name": "qiAddress", + "type": "address[]" + } + ], + "name": "getBenqiData", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "tokenPriceInAvax", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokenPriceInUsd", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "exchangeRateStored", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "balanceOfUser", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowBalanceStoredUser", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalSupplied", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowCap", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "supplyRatePerTimestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowRatePerTimestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "collateralFactor", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "rewardSpeedQi", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "rewardSpeedAvax", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "isQied", + "type": "bool" + }, + { + "internalType": "bool", + "name": "isBorrowPaused", + "type": "bool" + } + ], + "internalType": "struct Helpers.BenqiData[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getComptroller", + "outputs": [ + { + "internalType": "contract ComptrollerLensInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getOracleAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address[]", + "name": "qiAddress", + "type": "address[]" + } + ], + "name": "getPosition", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "tokenPriceInAvax", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokenPriceInUsd", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "exchangeRateStored", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "balanceOfUser", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowBalanceStoredUser", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalSupplied", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowCap", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "supplyRatePerTimestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowRatePerTimestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "collateralFactor", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "rewardSpeedQi", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "rewardSpeedAvax", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "isQied", + "type": "bool" + }, + { + "internalType": "bool", + "name": "isBorrowPaused", + "type": "bool" + } + ], + "internalType": "struct Helpers.BenqiData[]", + "name": "", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "avaxAccrued", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "qiAccrued", + "type": "uint256" + }, + { + "internalType": "address", + "name": "delegate", + "type": "address" + }, + { + "internalType": "uint96", + "name": "votes", + "type": "uint96" + } + ], + "internalType": "struct Helpers.MetadataExt", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract QiTokenInterface", + "name": "qiToken", + "type": "address" + } + ], + "name": "getPriceInAvax", + "outputs": [ + { + "internalType": "uint256", + "name": "priceInAVAX", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "priceInUSD", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getQiAVAXAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getQiToken", + "outputs": [ + { + "internalType": "contract TokenInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "contract ComptrollerLensInterface", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "contract TokenInterface", + "name": "qiToken", + "type": "address" + } + ], + "name": "getRewardsData", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "avaxAccrued", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "qiAccrued", + "type": "uint256" + }, + { + "internalType": "address", + "name": "delegate", + "type": "address" + }, + { + "internalType": "uint96", + "name": "votes", + "type": "uint96" + } + ], + "internalType": "struct Helpers.MetadataExt", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "rewardAvax", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "rewardQi", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + } +] \ No newline at end of file diff --git a/composables/protocols/useBenqiPosition.ts b/composables/protocols/useBenqiPosition.ts new file mode 100644 index 0000000..3e301d2 --- /dev/null +++ b/composables/protocols/useBenqiPosition.ts @@ -0,0 +1,487 @@ +import { AbiItem } from "web3-utils"; + +import benqiABI from "~/abis/read/benqi.json"; +import { computed, ref, watch } from "@nuxtjs/composition-api"; +import { useDSA } from "~/composables/useDSA"; +import { useWeb3 } from "@instadapp/vue-web3"; +import BigNumber from "bignumber.js"; +import tokens from "~/constant/tokens"; +import { Network, useNetwork } from "~/composables/useNetwork"; +import { useBigNumber } from "~/composables/useBigNumber"; +import { usePosition } from "~/composables/usePosition"; +import { useToken } from "~/composables/useToken"; +import addresses from "~/constant/addresses"; +import ctokens from "~/constant/ctokens"; +import tokenIdMapping from "~/constant/tokenIdMapping"; +import { useSorting } from "~/composables/useSorting"; +import useEventBus from "../useEventBus"; + +const { + times, + isZero, + div, + max, + gt, + minus, + ensureValue, + plus +} = useBigNumber(); +const { getType } = usePosition(); + +export const position = ref({ + totalSupplyInEth: new BigNumber(0), + totalBorrowInEth: new BigNumber(0), + totalBorrowStableInEth: new BigNumber(0), + totalBorrowVariableInEth: new BigNumber(0), + maxBorrowLimitInEth: new BigNumber(0), + maxBorrowLiquidityLimitInEth: new BigNumber(0), + ethPriceInUsd: "0", + data: [] +}); +const totalSupply = computed(() => + position.value + ? times( + position.value.totalSupplyInEth, + position.value.ethPriceInUsd + ).toFixed() + : 0 +); + +const totalBorrow = computed(() => + position.value + ? times( + position.value.totalBorrowInEth, + position.value.ethPriceInUsd + ).toFixed() + : 0 +); + +const ethPriceInUsd = computed(() => position.value?.ethPriceInUsd); + +export function useBenqiPosition( + { overridePosition } = { overridePosition: null } +) { + overridePosition = overridePosition || (pos => pos); + + const { library } = useWeb3(); + const { activeNetworkId } = useNetwork() + const { onEvent } = useEventBus() + const { activeAccount } = useDSA(); + const { getTokenByKey } = useToken(); + const { byMaxSupplyOrBorrowDesc } = useSorting() + const resolver = computed(() => addresses.mainnet.resolver.benqi); + + const fetchPosition = async () => { + if (!library.value) { + return; + } + + if (!activeAccount.value) { + return; + } + + const resolverInstance = new library.value.eth.Contract( + benqiABI as AbiItem[], + resolver.value + ); + + const tokensArr = ctokens[activeNetworkId.value].allTokens.map(a => a.address); + + const benqiRawData = await resolverInstance.methods + .getPosition(activeAccount.value.address, tokensArr) + .call(); + + const newPos = calculateBenqiPosition( + benqiRawData, + activeNetworkId.value + ); + + return newPos; + }; + + const refreshPosition = async () => { + position.value = await fetchPosition(); + }; + + onEvent("protocol::benqi::refresh", refreshPosition); + + watch( + library, + async val => { + if (val) { + refreshPosition(); + } + }, + { immediate: true } + ); + + watch( + activeAccount, + async val => { + if (val) { + refreshPosition(); + } + }, + { immediate: true } + ); + + const stats = computed(() => + displayPositions.value.reduce( + (stats, { key, supply, borrow, priceInEth, factor }) => { + if (key === "eth") { + stats.ethSupplied = supply; + } + + stats.totalSupplyInEth = plus( + stats.totalSupplyInEth, + times(supply, priceInEth) + ).toFixed(); + stats.totalBorrowInEth = plus( + stats.totalBorrowInEth, + times(borrow, priceInEth) + ).toFixed(); + stats.totalMaxBorrowLimitInEth = plus( + stats.totalMaxBorrowLimitInEth, + times(supply, times(priceInEth, factor)) + ).toFixed(); + + return stats; + }, + { + totalSupplyInEth: "0", + totalBorrowInEth: "0", + totalMaxBorrowLimitInEth: "0", + ethSupplied: "0" + } + ) + ); + + const rewardTokenPriceInUsd = computed(() => { + return ensureValue( + position.value.data.find(position => position.key === "comp")?.priceInUsd + ); + }); + + const displayPositions = computed(() => { + if (!position.value) { + return []; + } + + return ctokens[activeNetworkId.value].allTokens + .flatMap(ctoken => { + const token = getTokenByKey(ctoken.root); + if (!token) { + return []; + } + + const ctokenPosition = overridePosition( + position.value.data.find(x => x.cTokenId === ctoken.id) + ); + + if (!ctokenPosition) { + return []; + } + + const p = getPositionOrDefaultPosition(token, ctokenPosition); + if (gt(p.supply, "0") && gt(p.borrow, "0")) { + return [ + { ...p, type: "supply" }, + { ...p, type: "borrow" } + ]; + } else { + return [p]; + } + }) + .filter(p => { + if ( + tokenIdMapping.archived.compound.includes(p.tokenId) && + isZero(p.supply) && + isZero(p.borrow) + ) { + return false; + } + return true; + }) + .sort(byMaxSupplyOrBorrowDesc); + }); + + function getPositionOrDefaultPosition(token, pos) { + if (!pos) { + const defaultPosition = { + key: token?.key, + tokenId: `${token.symbol}-A`, + ctknBalance: "0", + cTokenDecimals: "0", + cf: "0", + supply: "0", + supplyUsd: "0", + supplyRate: "0", + supplyYield: "0", + borrow: "0", + borrowUsd: "0", + borrowRate: "0", + borrowYield: "0", + type: "no", + borrowEnabled: true, + supplyRewardRate: "0", + borrowRewardRate: "0", + priceInUsd: "0" + }; + + return defaultPosition; + } + + return { + key: token?.key, + tokenId: pos.cTokenId, + ctknBalance: pos.ctknBalance, + cTokenDecimals: pos.cTokenDecimals, + cf: pos.factor, + supply: pos.supply, + supplyUsd: times(pos.supply, pos.priceInUsd).toFixed(), + supplyRate: pos.supplyRate, + supplyYield: pos.supplyYield, + borrow: pos.borrow, + borrowUsd: times(pos.borrow, pos.priceInUsd).toFixed(), + borrowRate: pos.borrowRate, + borrowYield: pos.borrowYield, + borrowEnabled: pos.borrowEnabled, + type: getType(pos), + supplyRewardRate: times( + pos.compSupplyApy, + rewardTokenPriceInUsd.value + ).toFixed(), + borrowRewardRate: times( + pos.compBorrowApy, + rewardTokenPriceInUsd.value + ).toFixed(), + priceInUsd: pos.priceInUsd, + priceInEth: pos.priceInEth, + factor: pos.factor, + }; + } + + const liquidationPrice = computed(() => { + if (isZero(stats.value.ethSupplied)) return "0"; + + return max( + times( + div( + stats.value.totalBorrowInEth, + stats.value.totalMaxBorrowLimitInEth + ), + ethPriceInUsd.value + ), + "0" + ).toFixed(); + }); + + const status = computed(() => { + if ( + isZero(stats.value.totalSupplyInEth) && + !isZero(stats.value.totalBorrowInEth) + ) + return "1.1"; + if (isZero(stats.value.totalSupplyInEth)) return "0"; + + return max( + div(stats.value.totalBorrowInEth, stats.value.totalSupplyInEth), + "0" + ).toFixed(); + }); + + const liquidation = computed(() => { + if (isZero(stats.value.totalSupplyInEth)) return "0"; + + return max( + div(stats.value.totalMaxBorrowLimitInEth, stats.value.totalSupplyInEth), + "0" + ).toFixed(); + }); + + return { + stats, + displayPositions, + position: position, + fetchPosition, + refreshPosition, + totalSupply, + totalBorrow, + status, + liquidation, + liquidationPrice, + liquidationMaxPrice: ethPriceInUsd + }; +} + +function calculateBenqiPosition( + res: any[], + network: Network = Network.Mainnet +) { + try { + const newPos = { + totalSupplyInEth: new BigNumber(0), + totalBorrowInEth: new BigNumber(0), + totalBorrowStableInEth: new BigNumber(0), + totalBorrowVariableInEth: new BigNumber(0), + maxBorrowLimitInEth: new BigNumber(0), + maxBorrowLiquidityLimitInEth: new BigNumber(0), + tokens: {}, + data: [] + }; + const dataPos = []; + let ethPrice = "0"; + ctokens[network].allTokens.forEach((ctoken, i) => { + const key = ctoken.address; + const [ + priceInEthInWei, + priceInUsdInWei, + exchangeRateInWei, + cBalanceInWei, + borrowInWei, + totalBorrowsInWei, + totalSuppliedInWei, + borrowCapInWei, + supplyRatePerBlock, + borrowRatePerBlock, + collateralFactorInWei, + compSpeed, + isComped, + isBorrowPaused + ] = res[0][i]; + + const decimals = tokens[network].getTokenByKey(ctoken.root).decimals; + const root = ctoken.root; + + const blocksInYear = 2398050; + + const priceInEth = new BigNumber(priceInEthInWei).dividedBy(1e18); + const priceInUsd = new BigNumber(priceInUsdInWei).dividedBy(1e18); + const exchangeRate = new BigNumber(exchangeRateInWei).dividedBy(1e18); + const supply = new BigNumber(cBalanceInWei) + .multipliedBy(exchangeRate) + .dividedBy(10 ** decimals); + const borrow = new BigNumber(borrowInWei).dividedBy(10 ** decimals); + const supplyRate = new BigNumber(supplyRatePerBlock) + .multipliedBy(blocksInYear) + .dividedBy(1e18); + const supplyYield = supplyRate + .dividedBy(365) + .plus(1) + .exponentiatedBy(365) + .minus(1) + .toFixed(18); + const borrowRate = new BigNumber(borrowRatePerBlock) + .multipliedBy(blocksInYear) + .dividedBy(1e18); + const borrowYield = borrowRate + .dividedBy(365) + .plus(1) + .exponentiatedBy(365) + .minus(1) + .toFixed(18); + const totalBorrow = new BigNumber(totalBorrowsInWei).dividedBy( + 10 ** decimals + ); + const borrowCap = new BigNumber(borrowCapInWei) + .dividedBy(10 ** decimals) + .multipliedBy(0.9999) + .toFixed(); + const collateralFactor = new BigNumber(collateralFactorInWei) + .dividedBy(1e18) + .toFixed(); + const totalSupplied = new BigNumber(totalSuppliedInWei) + .dividedBy(10 ** decimals) + .multipliedBy(priceInUsd); + const compSupplyApy = new BigNumber(compSpeed) + .multipliedBy(blocksInYear) + .dividedBy(1e18) + .dividedBy(totalSupplied) + .toFixed(); + const compBorrowApy = new BigNumber(compSpeed) + .multipliedBy(blocksInYear) + .dividedBy(1e18) + .dividedBy(totalBorrow.multipliedBy(priceInUsd)) + .toFixed(); + + newPos.totalSupplyInEth = newPos.totalSupplyInEth.plus( + supply.multipliedBy(priceInEth) + ); + newPos.maxBorrowLimitInEth = newPos.maxBorrowLimitInEth.plus( + supply.multipliedBy(priceInEth).multipliedBy(ctoken.factor) + ); + newPos.totalBorrowInEth = newPos.totalBorrowInEth.plus( + borrow.multipliedBy(priceInEth) + ); + + if (ctoken.root === "eth") ethPrice = priceInUsd.toFixed(); + dataPos.push({ + key: root, + cTokenAddr: key, + cTokenKey: ctoken.key, + cTokenDecimals: ctoken.decimals.toString(), + cTokenId: ctoken.id, + priceInEth: priceInEth.toFixed(), + priceInUsd: priceInUsd.toFixed(), + exchangeRate: exchangeRate.toFixed(), + ctknBalance: cBalanceInWei, + supply: supply.toFixed(), + borrow: borrow.toFixed(), + supplyRate: supplyRate.toFixed(), + supplyYield, + borrowRate: borrowRate.toFixed(), + borrowYield, + factor: collateralFactor, + totalBorrow: totalBorrow.toFixed(), + borrowCap, + isComped, + borrowEnabled: !isBorrowPaused, + compSupplyApy, + compBorrowApy + }); + }); + + const totalSupplyInEthIsZero = newPos.totalSupplyInEth.isZero(); + const status = totalSupplyInEthIsZero + ? 0 + : newPos.totalBorrowInEth.dividedBy(newPos.totalSupplyInEth).toFixed(); + const liquidation = totalSupplyInEthIsZero + ? 0 + : newPos.maxBorrowLimitInEth.dividedBy(newPos.totalSupplyInEth).toFixed(); + //@ts-ignore + newPos.totalSupplyInEth = newPos.totalSupplyInEth.toFixed(); + //@ts-ignore + newPos.totalBorrowInEth = newPos.totalBorrowInEth.toFixed(); + //@ts-ignore + newPos.maxBorrowLimitInEth = newPos.maxBorrowLimitInEth.toFixed(); + + //@ts-ignore + newPos.status = status; + + //@ts-ignore + newPos.liquidation = liquidation; + + //@ts-ignore + newPos.ethPriceInUsd = ethPrice; + + const comp = res[1]; + //@ts-ignore + newPos.compBalance = new BigNumber(comp.balance).dividedBy(1e18).toFixed(); + + //@ts-ignore + newPos.compAccrued = new BigNumber(comp.allocated) + .dividedBy(1e18) + .toFixed(); + //@ts-ignore + newPos.compDelegate = comp.delegate; + //@ts-ignore + newPos.compVotes = comp.votes; + + newPos.data = dataPos; + + return newPos; + } catch (error) { + console.error(error); + return Promise.reject(error); + } +} diff --git a/constant/abi/read/benqi.json b/constant/abi/read/benqi.json new file mode 100644 index 0000000..0b1dac3 --- /dev/null +++ b/constant/abi/read/benqi.json @@ -0,0 +1,397 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address[]", + "name": "qiAddress", + "type": "address[]" + } + ], + "name": "getBenqiData", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "tokenPriceInAvax", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokenPriceInUsd", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "exchangeRateStored", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "balanceOfUser", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowBalanceStoredUser", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalSupplied", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowCap", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "supplyRatePerTimestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowRatePerTimestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "collateralFactor", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "rewardSpeedQi", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "rewardSpeedAvax", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "isQied", + "type": "bool" + }, + { + "internalType": "bool", + "name": "isBorrowPaused", + "type": "bool" + } + ], + "internalType": "struct Helpers.BenqiData[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getComptroller", + "outputs": [ + { + "internalType": "contract ComptrollerLensInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getOracleAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address[]", + "name": "qiAddress", + "type": "address[]" + } + ], + "name": "getPosition", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "tokenPriceInAvax", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokenPriceInUsd", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "exchangeRateStored", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "balanceOfUser", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowBalanceStoredUser", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalSupplied", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowCap", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "supplyRatePerTimestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowRatePerTimestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "collateralFactor", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "rewardSpeedQi", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "rewardSpeedAvax", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "isQied", + "type": "bool" + }, + { + "internalType": "bool", + "name": "isBorrowPaused", + "type": "bool" + } + ], + "internalType": "struct Helpers.BenqiData[]", + "name": "", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "avaxAccrued", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "qiAccrued", + "type": "uint256" + }, + { + "internalType": "address", + "name": "delegate", + "type": "address" + }, + { + "internalType": "uint96", + "name": "votes", + "type": "uint96" + } + ], + "internalType": "struct Helpers.MetadataExt", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract QiTokenInterface", + "name": "qiToken", + "type": "address" + } + ], + "name": "getPriceInAvax", + "outputs": [ + { + "internalType": "uint256", + "name": "priceInAVAX", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "priceInUSD", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getQiAVAXAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getQiToken", + "outputs": [ + { + "internalType": "contract TokenInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "contract ComptrollerLensInterface", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "contract TokenInterface", + "name": "qiToken", + "type": "address" + } + ], + "name": "getRewardsData", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "avaxAccrued", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "qiAccrued", + "type": "uint256" + }, + { + "internalType": "address", + "name": "delegate", + "type": "address" + }, + { + "internalType": "uint96", + "name": "votes", + "type": "uint96" + } + ], + "internalType": "struct Helpers.MetadataExt", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "rewardAvax", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "rewardQi", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + } +] \ No newline at end of file diff --git a/constant/abis.ts b/constant/abis.ts index 29d1364..7e0a08b 100644 --- a/constant/abis.ts +++ b/constant/abis.ts @@ -3,6 +3,7 @@ import aaveV2ABI from "./abi/read/aaveV2.json"; import accountsABI from "./abi/read/accounts.json"; import balanceABI from "./abi/read/balance.json"; import compoundABI from "./abi/read/compound.json"; +import benqiABI from "./abi/read/benqi.json"; import makerABI from "./abi/read/maker.json"; import makerProxyRegistryABI from "./abi/makerProxyRegistry.json"; import unipoolABI from "./abi/read/unipool.json"; @@ -18,6 +19,7 @@ const abis = { accounts: accountsABI, balance: balanceABI, compound: compoundABI, + benqi: benqiABI, maker: makerABI, unipool: unipoolABI, liquity: liquityABI, diff --git a/constant/addresses.ts b/constant/addresses.ts index baf73db..58d55d9 100644 --- a/constant/addresses.ts +++ b/constant/addresses.ts @@ -55,6 +55,7 @@ const addresses = { aave_v2: '0x43c51C24b49f7cF389D043e93533E5179870Eea3', accounts: '0x746e318e179CB0A359C1FeE8331A3F9bE309b3CE', balance: '0xE6F92a3eCAa618FC5D4Bf2a14090787715C115F0', + benqi: "0x1d29756e8f7b091cE6c11a35980dE79c7eDa5D1f", }, }, }; diff --git a/pages/index.vue b/pages/index.vue index f40d3ac..10f4708 100644 --- a/pages/index.vue +++ b/pages/index.vue @@ -57,6 +57,13 @@ const appsPerNetwork = { url: "/mainnet/compound", description: "Money Market" }, + { + id: "benqi", + icon: CompoundIcon, + name: "Benqi", + url: "/mainnet/benqi", + description: "Money Market" + }, { id: "maker", icon: MakerIcon, diff --git a/pages/mainnet/benqi.vue b/pages/mainnet/benqi.vue new file mode 100644 index 0000000..9e6d6d9 --- /dev/null +++ b/pages/mainnet/benqi.vue @@ -0,0 +1,244 @@ + + +