MakerDAO Collateral

This commit is contained in:
Georges KABBOUCHI 2021-08-10 19:11:15 +03:00
parent e79ad82e84
commit 5410695e47
9 changed files with 292 additions and 21 deletions

View File

@ -0,0 +1,46 @@
<template>
<div ref="menu" class="relative inline-block text-left">
<slot name="trigger" :toggle="toggle" :is-shown="isShown" />
<transition
enter-active-class="transition duration-100 ease-out"
enter-class="transform scale-95 opacity-0"
enter-to-class="transform scale-100 opacity-100"
leave-active-class="transition duration-75 ease-in"
leave-class="transform scale-100 opacity-100"
leave-to-class="transform scale-95 opacity-0"
>
<slot v-if="isShown" name="menu" :close="close" />
</transition>
</div>
</template>
<script>
import { defineComponent, onBeforeUnmount, onMounted, ref } from '@nuxtjs/composition-api'
export default defineComponent({
setup() {
const menu = ref(null)
const isShown = ref(false)
function toggle() {
isShown.value = !isShown.value
}
function close() {
isShown.value = false
}
function closeOnOutsideClick(event) {
if (!isShown.value) return
if (menu.value.contains(event.target)) return
close()
}
onMounted(() => window.addEventListener('click', closeOnOutsideClick))
onBeforeUnmount(() => window.removeEventListener('click', closeOnOutsideClick))
return { toggle, isShown, menu, close }
},
})
</script>

View File

@ -0,0 +1,96 @@
<template>
<dropdown>
<template #trigger="{ toggle, isShown }">
<Button
:class="{
'bg-grey-light': isShown
}"
:large="true"
color="grey"
class="w-20 px-3 xxl:w-23"
aria-label="Makerdao Dropdown"
aria-haspopup="true"
@click="toggle()"
>
<span class="mr-2">#{{ vaultId }}</span>
<SVGChevronUp
class="ml-auto"
:class="{ 'transform rotate-180': !isShown }"
/>
</Button>
</template>
<template #menu="{ close }">
<dropdown-menu style="width: 240px; max-height: 440px">
<div class="flex flex-col overflow-x-hidden overflow-y-auto scrollbar-hover scrollbar">
<button
v-for="vault in vaults"
:key="vault.id"
class="flex items-center w-full px-4 py-2 hover:bg-opacity-50 focus:bg-opacity-50 hover:bg-grey-light dark:hover:bg-dark-300 dark:focus:bg-dark-300 focus:outline-none focus:bg-grey-light"
@click="setVault(vault.id, close)"
>
<div class="mr-2 font-semibold whitespace-no-wrap">
#{{ vault.id }}
</div>
<IconCurrency
:currency="vault.tokenKey"
class="w-6 h-6 ml-auto"
no-height
/>
</button>
</div>
<hr v-if="!!vaults.length" class="w-full my-2" />
<button
class="flex items-center w-full px-4 py-2 font-medium hover:bg-opacity-75 focus:bg-opacity-75 text-ocean-blue-pure hover:bg-ocean-blue-light focus:bg-ocean-blue-light focus:outline-none dark:hover:bg-opacity-17 dark:focus:bg-opacity-17"
@click="openNewVault(close)"
>
New Vault
</button>
</dropdown-menu>
</template>
</dropdown>
</template>
<script>
import { defineComponent, useRouter } from '@nuxtjs/composition-api'
import SVGChevronUp from '@/assets/img/icons/chevron-up.svg?inline'
import { useMakerdaoPosition } from '~/composables/useMakerdaoPosition'
import { useSidebar } from '~/composables/useSidebar'
import Dropdown from '../common/input/Dropdown.vue'
import DropdownMenu from './DropdownMenu.vue'
export default defineComponent({
components: {
SVGChevronUp,
Dropdown,
DropdownMenu,
},
setup() {
const router = useRouter()
const { vaultId, vaults, selectVault, isNewVault } = useMakerdaoPosition()
const { back } = useSidebar()
function openNewVault(cb) {
router.push({ hash: 'collateral' })
cb();
}
function setVault(vaultId, cb) {
selectVault(vaultId)
if (isNewVault.value) {
back()
}
cb()
}
return { vaultId, vaults, openNewVault, setVault }
},
})
</script>

View File

@ -0,0 +1,21 @@
<template>
<div
class="rounded-lg flex-shrink-0 bg-white absolute z-10 flex flex-col py-2 mt-1 overflow-hidden border border-opacity-25 select-none shadow-notification dark:bg-dark-400 dark:border-opacity-20 border-ocean-blue-pure"
:class="{
'right-0 origin-top-right': align === 'right',
'left-0 origin-top-left': align === 'left',
}"
>
<slot />
</div>
</template>
<script>
import { defineComponent } from '@nuxtjs/composition-api'
export default defineComponent({
props: {
align: { type: String, default: 'right' },
},
})
</script>

View File

@ -0,0 +1,83 @@
<template>
<SidebarContextRootContainer>
<template #title>Select Collateral</template>
<div>
<div class="px-8 pb-6 -mt-4">
<SearchInput
v-model.trim="search"
class="mt-1"
placeholder="Search Collateral"
/>
</div>
<div class="bg-[#C5CCE1] bg-opacity-[0.15] px-8 py-6 min-h-screen">
<div
v-for="(vaultType, index) in filteredVaults"
:key="index"
class="flex items-center justify-between px-4 py-4 mt-4 cursor-pointer first:mt-0 group bg-white rounded-lg border border-grey-dark/[0.15] hover:bg-selection"
@click="select(vaultType.type)"
>
<div class="flex flex-col mr-4">
<div class="mb-1 font-semibold whitespace-no-wrap text-12">
{{ vaultType.type }}
</div>
<div
class="mb-1 font-medium whitespace-no-wrap text-12 text-grey-pure"
>
Stability Fee: {{ formatPercent(vaultType.rate) }}
</div>
<div
class="mb-1 font-medium whitespace-no-wrap text-12 text-grey-pure"
>
Liquidation: {{ formatPercent(vaultType.liquidation) }}
</div>
</div>
<IconCurrency :currency="vaultType.tokenKey" />
</div>
</div>
</div>
</SidebarContextRootContainer>
</template>
<script>
import { defineComponent, useContext, computed } from '@nuxtjs/composition-api'
import { useFormatting } from '~/composables/useFormatting'
import { useMakerdaoPosition } from '~/composables/useMakerdaoPosition'
import { useSearchFilter } from '~/composables/useSearchFilter'
import { useSidebar } from '~/composables/useSidebar'
export default defineComponent({
props: {
vaultType: { type: String, default: null },
},
setup(props) {
const { store, app, route } = useContext()
const { formatPercent } = useFormatting()
const { back } = useSidebar()
const { vaultTypes: makerVaultTypes, vaultType, isNewVault } = useMakerdaoPosition()
const vaultTypes = computed(() => {
const shouldFilter = !!props.vaultType && (props.vaultType === 'token' || props.vaultType === 'uniLPT')
const filtered = makerVaultTypes.value.filter((vault) => !vault.disabled)
const final = shouldFilter ? filtered.filter((vault) => vault.vaultTokenType === props.vaultType) : filtered
if (route.value.hash.startsWith('#collateral')) return final
return filtered.filter((vault) => vault.vaultTokenType === 'token')
})
const { filtered: filteredVaults, search } = useSearchFilter(vaultTypes, 'type', 'token')
function select(vt, tokenKey) {
vaultType.value = vt;
isNewVault.value = true
app.router.push({ hash: 'supply' })
}
return {
filteredVaults,
search,
formatPercent,
select,
}
},
})
</script>

View File

@ -25,7 +25,7 @@ const defaultVault = {
netvalue: "0"
};
const vaultId = ref("0");
const vaultId = ref(null);
const vaults = ref([]);
const isNewVault = ref(false);
const vaultTypes = ref([]);
@ -50,7 +50,10 @@ const vault = computed(() => {
return defaultVault;
});
export function useMakerdaoPosition(collateralAmountRef: Ref =null, debtAmountRef: Ref = null) {
export function useMakerdaoPosition(
collateralAmountRef: Ref = null,
debtAmountRef: Ref = null
) {
const { web3, chainId, networkName } = useWeb3();
const { activeAccount } = useDSA();
const { isZero, ensureValue, times, div, max, gt } = useBigNumber();
@ -78,19 +81,32 @@ export function useMakerdaoPosition(collateralAmountRef: Ref =null, debtAmountRe
const netValue = computed(() => ensureValue(vault.value.netValue).toFixed());
const status = computed(() => {
if (!collateralAmountRef || !debtAmountRef) return ensureValue(vault.value.status).toFixed()
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()
})
? "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 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()
})
? 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 || "5000");
@ -136,9 +152,16 @@ export function useMakerdaoPosition(collateralAmountRef: Ref =null, debtAmountRe
{ immediate: true }
);
const selectVault = vid => {
if (vid === vaultId.value && !isNewVault.value) return;
vaultId.value = vid;
isNewVault.value = false;
};
return {
fetchPosition,
vaultId,
vaultId: computed(() => (isNewVault.value ? "0" : vaultId.value || "0")),
selectVault,
vaultTokenType,
vault,
vaults,
@ -245,7 +268,7 @@ async function getVaults(user, web3) {
ratePerBlock,
priceInWei,
liquidationRatioCbyD,
urn,
urn
]) => {
const collateral = new BigNumber(collInWei).dividedBy(1e18);
const debt = new BigNumber(debtInWei).dividedBy(1e18);

View File

@ -23,6 +23,7 @@ import SidebarCompoundSupply from '~/components/sidebar/context/compound/Sidebar
import SidebarCompoundBorrow from '~/components/sidebar/context/compound/SidebarCompoundBorrow.vue'
import SidebarCompoundPayback from '~/components/sidebar/context/compound/SidebarCompoundPayback.vue'
import SidebarMakerdaoCollateral from '~/components/sidebar/context/makerdao/SidebarMakerdaoCollateral.vue'
import SidebarMakerdaoSupply from '~/components/sidebar/context/makerdao/SidebarMakerdaoSupply.vue'
import SidebarMakerdaoWithdraw from '~/components/sidebar/context/makerdao/SidebarMakerdaoWithdraw.vue'
import SidebarMakerdaoBorrow from '~/components/sidebar/context/makerdao/SidebarMakerdaoBorrow.vue'
@ -53,6 +54,7 @@ const sidebars = {
"/mainnet/compound#payback": { component: SidebarCompoundPayback },
"/mainnet/maker": { component: null },
'/mainnet/maker#collateral': { component: SidebarMakerdaoCollateral },
"/mainnet/maker#supply": { component: SidebarMakerdaoSupply },
"/mainnet/maker#withdraw": { component: SidebarMakerdaoWithdraw },
"/mainnet/maker#borrow": { component: SidebarMakerdaoBorrow },

View File

@ -115,10 +115,9 @@ export default defineComponent({
}
}, { immediate: true })
// onErrorCaptured(() => {
// return false
// })
onErrorCaptured(() => {
return false
})
return {
active,

View File

@ -10,8 +10,10 @@
</nuxt-link>
</div>
<div class="mt-10">
<div class="mt-10 flex items-center">
<h1 class="text-primary-black text-2xl font-semibold">MakerDAO</h1>
<dropdown-makerdao class="ml-auto"/>
</div>
<div class="mt-10">
@ -148,6 +150,7 @@ import { useFormatting } from "~/composables/useFormatting";
import { useMakerdaoPosition } from "~/composables/useMakerdaoPosition";
import { useStatus } from "~/composables/useStatus";
import { useNotification } from "~/composables/useNotification";
import DropdownMakerdao from "~/components/protocols/DropdownMakerdao.vue";
export default defineComponent({
components: {
@ -157,7 +160,8 @@ export default defineComponent({
SVGBalance,
SVGEarnings,
SVGArrowRight,
SVGPercent
SVGPercent,
DropdownMakerdao
},
setup() {
const router = useRouter();

View File

@ -1,3 +0,0 @@
<template>
<SidebarMakerdaoWithdraw />
</template>