diff --git a/assets/icons/b-protocol.svg b/assets/icons/b-protocol.svg new file mode 100644 index 0000000..3331f89 --- /dev/null +++ b/assets/icons/b-protocol.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/components/protocols/bprotocol/CardBprotocolBamm.vue b/components/protocols/bprotocol/CardBprotocolBamm.vue new file mode 100644 index 0000000..5217950 --- /dev/null +++ b/components/protocols/bprotocol/CardBprotocolBamm.vue @@ -0,0 +1,139 @@ + + + diff --git a/components/sidebar/context/bprotocol/SidebarBprotocolDeposit.vue b/components/sidebar/context/bprotocol/SidebarBprotocolDeposit.vue new file mode 100644 index 0000000..44616a6 --- /dev/null +++ b/components/sidebar/context/bprotocol/SidebarBprotocolDeposit.vue @@ -0,0 +1,216 @@ + + + diff --git a/components/sidebar/context/bprotocol/SidebarBprotocolWithdraw.vue b/components/sidebar/context/bprotocol/SidebarBprotocolWithdraw.vue new file mode 100644 index 0000000..6044925 --- /dev/null +++ b/components/sidebar/context/bprotocol/SidebarBprotocolWithdraw.vue @@ -0,0 +1,219 @@ + + + + diff --git a/components/sidebar/context/liquity/SidebarLiquityPoolWithdraw.vue b/components/sidebar/context/liquity/SidebarLiquityPoolWithdraw.vue index 1acf20c..b17c947 100644 --- a/components/sidebar/context/liquity/SidebarLiquityPoolWithdraw.vue +++ b/components/sidebar/context/liquity/SidebarLiquityPoolWithdraw.vue @@ -26,7 +26,7 @@

- Amount to supply + Amount to withdraw

{ + showConfirmedTransaction(receipt.transactionHash); + + await fetchBalances(true); + await fetchUserData(); + } + }); + + showPendingTransaction(tx); + } catch (error) { + console.log(error); + showWarning(error.message); + } + + pendingLqtyClaim.value = false; + } + + + return { + claimLqty, + pendingLqtyClaim, + }; +} diff --git a/composables/protocols/useBprotocolPositions.ts b/composables/protocols/useBprotocolPositions.ts new file mode 100644 index 0000000..15464ad --- /dev/null +++ b/composables/protocols/useBprotocolPositions.ts @@ -0,0 +1,155 @@ +import { computed, Ref, ref, watch } from "@nuxtjs/composition-api"; +import { useBalances } from "../useBalances"; +import { useBigNumber } from "../useBigNumber"; +import { useToken } from "../useToken"; +import { useWeb3 } from "@instadapp/vue-web3"; +import { AbiItem } from "web3-utils"; +import BigNumber from "bignumber.js"; +BigNumber.config({ POW_PRECISION: 200 }); +import abis from "~/constant/abis"; +import addresses from "~/constant/addresses"; +import { useDSA } from "../useDSA"; +import useEventBus from "../useEventBus"; + +export const userData = ref({ + bammTotalSupply: "0", + bammUserBalance: "0", + ethTotal: "0", + ethUserBalance: "0", + lusdPrice: "0", + lusdTotal: "0", + lusdUserBalance: "0", + unclaimedLqty: "0" +}); + +const fromWei = (n) => new BigNumber(n).dividedBy(1e18).toString(); +const toWei = (n) => new BigNumber(n).multipliedBy(1e18).toString(); + +export function useBprotocolPosition (){ + const { activeAccount } = useDSA(); + const { library } = useWeb3(); + const { onEvent } = useEventBus() + const { getTokenByKey } = useToken(); + + const bammToken = computed(() => getTokenByKey('lusd')) + const ethPrice = computed(() => fromWei(userData.value.lusdPrice)) // wrong mapping + const bammTotalSupply = computed(() => fromWei(userData.value.bammTotalSupply)); + const bammUserBalance = computed(() => fromWei(userData.value.bammUserBalance)); + const ethTotal = computed(() => fromWei(userData.value.ethTotal)); + const ethUserBalance = computed(() => fromWei(userData.value.ethUserBalance)); + const lusdTotal = computed(() => fromWei(userData.value.lusdTotal)); + const lusdUserBalance = computed(() => fromWei(userData.value.lusdUserBalance)); + const unclaimedLqty = computed(() => fromWei(userData.value.unclaimedLqty)); + const userBammInUsd = computed(() => { + if(userData.value.bammTotalSupply === "0"){ + return "0" + } + const userEthInUsd = new BigNumber(userData.value.ethUserBalance).multipliedBy(ethPrice.value) + return fromWei(userEthInUsd.plus(userData.value.lusdUserBalance)) + }); + const totalBammSupplyInUsd = computed(() => { + if(userData.value.bammTotalSupply === "0"){ + return "0" + } + const userEthInUsd = new BigNumber(userData.value.ethTotal).multipliedBy(ethPrice.value) + return fromWei(userEthInUsd.plus(userData.value.lusdTotal)) + }); + const userBammInLusd = computed(() => { + if(userData.value.bammTotalSupply === "0"){ + return "0" + } + return fromWei((new BigNumber(userData.value.bammUserBalance).dividedBy(userData.value.bammTotalSupply)).multipliedBy(userData.value.lusdTotal)) + }); + + function lusdWithdrawAmountToBamm (lusd) { + const bammWithdrawRatio = new BigNumber(lusd).dividedBy(userBammInUsd.value) + const res = bammWithdrawRatio.multipliedBy(bammUserBalance.value).toString() + return res + } + + function absolutlWithdrawAmountInEth (lusd) { + const bammWithdrawRatio = new BigNumber(lusd).dividedBy(userBammInUsd.value) + const res = bammWithdrawRatio.multipliedBy(ethUserBalance.value).toString() + return res + } + + function absolutlWithdrawAmountInLusd (lusd) { + const bammWithdrawRatio = new BigNumber(lusd).dividedBy(userBammInUsd.value) + const res = bammWithdrawRatio.multipliedBy(lusdUserBalance.value).toString() + return res + } + + async function fetchUserData (){ + if (!library.value || !activeAccount.value) { + return + } + const struct = await getUserInfo(activeAccount.value.address, library.value) + const data = {} + Object.keys(struct).filter(k=> isNaN(Number(k))).forEach(k=> { + data[k] = struct[k] + }) + userData.value = data + } + + onEvent("protocol::bprotocol::refresh", fetchUserData); + + watch( + library, + async val => { + if (val) { + fetchUserData(); + } + }, + { immediate: true } + ); + + watch( + activeAccount, + async val => { + if (val) { + fetchUserData(); + } + }, + { immediate: true } + ); + + return { + bammTotalSupply, + bammUserBalance, + ethTotal, + ethUserBalance, + ethPrice, + lusdTotal, + lusdUserBalance, + unclaimedLqty, + fetchUserData, + userBammInLusd, + lusdWithdrawAmountToBamm, + bammToken, + absolutlWithdrawAmountInEth, + absolutlWithdrawAmountInLusd, + userBammInUsd, + totalBammSupplyInUsd + } +} + +async function getUserInfo (user, web3){ + try { + const resolveABI = abis.resolver.bprotocol; + const resolveAddr = addresses.mainnet.resolver.bprotocol; + const bammAddr = addresses.mainnet.bprotocolBamm; + const bprotocolInstance = new web3.eth.Contract( + resolveABI as AbiItem[], + resolveAddr + ); + const userInfo = await bprotocolInstance.methods.getUserInfo(user, bammAddr, '0x6DEA81C8171D0bA574754EF6F8b412F2Ed88c54D').call() + debugger + return userInfo + + }catch (e) { + console.error(e); + return {}; + } + + +} \ No newline at end of file diff --git a/composables/useSidebar.ts b/composables/useSidebar.ts index eeb2231..dc2d58f 100644 --- a/composables/useSidebar.ts +++ b/composables/useSidebar.ts @@ -37,6 +37,9 @@ import SidebarLiquityTrovePayback from '~/components/sidebar/context/liquity/Sid import SidebarLiquityPoolSupply from '~/components/sidebar/context/liquity/SidebarLiquityPoolSupply.vue' import SidebarLiquityPoolWithdraw from '~/components/sidebar/context/liquity/SidebarLiquityPoolWithdraw.vue' +import SidebarBprotocolDeposit from '~/components/sidebar/context/bprotocol/SidebarBprotocolDeposit.vue' +import SidebarBprotocolWithdraw from '~/components/sidebar/context/bprotocol/SidebarBprotocolWithdraw.vue' + import SidebarReflexerCollateral from '~/components/sidebar/context/reflexer/SidebarReflexerCollateral.vue' import SidebarReflexerSupply from '~/components/sidebar/context/reflexer/SidebarReflexerSupply.vue' import SidebarReflexerWithdraw from '~/components/sidebar/context/reflexer/SidebarReflexerWithdraw.vue' @@ -80,6 +83,9 @@ const sidebars = { '/mainnet/liquity#pool-supply': { component: SidebarLiquityPoolSupply }, '/mainnet/liquity#pool-withdraw': { component: SidebarLiquityPoolWithdraw }, + "/mainnet/bprotocol#deposit": { component: SidebarBprotocolDeposit }, + "/mainnet/bprotocol#withdraw": { component: SidebarBprotocolWithdraw }, + "/mainnet/reflexer": { component: null }, '/mainnet/reflexer#collateral': { component: SidebarReflexerCollateral }, "/mainnet/reflexer#supply": { component: SidebarReflexerSupply }, diff --git a/constant/abi/read/bprotocol.json b/constant/abi/read/bprotocol.json new file mode 100644 index 0000000..dd47ee1 --- /dev/null +++ b/constant/abi/read/bprotocol.json @@ -0,0 +1 @@ +[{"inputs":[{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"y","type":"uint256"}],"name":"add","outputs":[{"internalType":"uint256","name":"z","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"contract BAMM","name":"bamm","type":"address"},{"internalType":"contract ERC20","name":"token","type":"address"}],"name":"getUnclaimedLqty","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"contract BAMM","name":"bamm","type":"address"},{"internalType":"contract ERC20","name":"lqty","type":"address"}],"name":"getUserInfo","outputs":[{"components":[{"internalType":"uint256","name":"unclaimedLqty","type":"uint256"},{"internalType":"uint256","name":"bammUserBalance","type":"uint256"},{"internalType":"uint256","name":"bammTotalSupply","type":"uint256"},{"internalType":"uint256","name":"lusdUserBalance","type":"uint256"},{"internalType":"uint256","name":"ethUserBalance","type":"uint256"},{"internalType":"uint256","name":"lusdTotal","type":"uint256"},{"internalType":"uint256","name":"ethTotal","type":"uint256"},{"internalType":"uint256","name":"lusdPrice","type":"uint256"}],"internalType":"struct BLens.UserInfo","name":"info","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"y","type":"uint256"}],"name":"mul","outputs":[{"internalType":"uint256","name":"z","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"y","type":"uint256"}],"name":"rdiv","outputs":[{"internalType":"uint256","name":"z","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"y","type":"uint256"}],"name":"rmul","outputs":[{"internalType":"uint256","name":"z","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"y","type":"uint256"}],"name":"rmulup","outputs":[{"internalType":"uint256","name":"z","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"y","type":"uint256"}],"name":"sub","outputs":[{"internalType":"uint256","name":"z","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"y","type":"uint256"}],"name":"wdiv","outputs":[{"internalType":"uint256","name":"z","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"y","type":"uint256"}],"name":"wdivup","outputs":[{"internalType":"uint256","name":"z","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"y","type":"uint256"}],"name":"wmul","outputs":[{"internalType":"uint256","name":"z","type":"uint256"}],"stateMutability":"pure","type":"function"}] \ No newline at end of file diff --git a/constant/abis.ts b/constant/abis.ts index 974c464..29d1364 100644 --- a/constant/abis.ts +++ b/constant/abis.ts @@ -7,7 +7,9 @@ import makerABI from "./abi/read/maker.json"; import makerProxyRegistryABI from "./abi/makerProxyRegistry.json"; import unipoolABI from "./abi/read/unipool.json"; import liquityABI from "./abi/read/liquity.json"; -import reflexerABI from './abi/read/reflexer.json' +import reflexerABI from './abi/read/reflexer.json'; +import bprotocolABI from './abi/read/bprotocol.json'; + const abis = { makerProxyRegistry: makerProxyRegistryABI, resolver: { @@ -19,7 +21,8 @@ const abis = { maker: makerABI, unipool: unipoolABI, liquity: liquityABI, - reflexer: reflexerABI + reflexer: reflexerABI, + bprotocol: bprotocolABI, } }; diff --git a/constant/addresses.ts b/constant/addresses.ts index a1b4ac0..e726b2c 100644 --- a/constant/addresses.ts +++ b/constant/addresses.ts @@ -1,6 +1,7 @@ const addresses = { mainnet: { makerProxyRegistry: "0x4678f0a6958e4D2Bc4F1BAF7Bc52E8F3564f3fE4", + bprotocolBamm: "0x0d3AbAA7E088C2c82f54B2f47613DA438ea8C598", resolver: { aave: "0xA6Dc31dC10f8071c02099B05B76Ba15dfcD2B04c", aave_v2: "0xFb3a1D56eD56F046721B9aCa749895100754578b", @@ -10,7 +11,8 @@ const addresses = { maker: "0x84addce4fac0b6ee4b0cd132120d6d4b700e35c0", unipool: "0x22bddA39D14eD0aafeee36B6e784602fdDE64723", liquity: "0xDAf2A39503463B0F41f899EDD82213b3c96b6Cf8", - reflexer: "0x016ca8d0993d1a7073b01802a2e22fd0df7e633a" + reflexer: "0x016ca8d0993d1a7073b01802a2e22fd0df7e633a", + bprotocol: "0x3843019c19259117ed473947007bcafc5c0c7129" } }, diff --git a/pages/index.vue b/pages/index.vue index 62eb823..148c6fa 100644 --- a/pages/index.vue +++ b/pages/index.vue @@ -37,6 +37,7 @@ import CompoundIcon from "~/assets/icons/compound.svg?inline"; import MakerIcon from "~/assets/icons/makerdao.svg?inline"; import OneInchIcon from "~/assets/icons/1inch.svg?inline"; import LiquityIcon from "~/assets/icons/liquity.svg?inline"; +import BprotocolIcon from "~/assets/icons/b-protocol.svg?inline"; import ReflexerIcon from "~/assets/icons/reflexer.svg?inline"; const appsPerNetwork = { @@ -76,6 +77,13 @@ const appsPerNetwork = { url: "/mainnet/liquity", description: "Collateralized LUSD Debt" }, + { + id: "bprotocol", + icon: BprotocolIcon, + name: "B.Protocol", + url: "/mainnet/bprotocol", + description: "Stake LUSD" + }, { id: "reflexer", icon: ReflexerIcon, @@ -107,7 +115,6 @@ export default defineComponent({ const { activeNetworkId } = useNetwork(); const apps = computed(() => appsPerNetwork[activeNetworkId.value]); - return { apps }; diff --git a/pages/mainnet/bprotocol.vue b/pages/mainnet/bprotocol.vue new file mode 100644 index 0000000..ccdd400 --- /dev/null +++ b/pages/mainnet/bprotocol.vue @@ -0,0 +1,115 @@ + + +