comments + contract update +

smaller design issues
This commit is contained in:
EmberSpirit
2023-10-12 20:01:11 +02:00
parent 68cd720c59
commit b5c6f8af33
37 changed files with 714 additions and 1480 deletions
+14 -33
View File
@@ -20,7 +20,12 @@
<swiper-slide class="blood-chart-element" v-for="coin in token" :key="coin.name">
<div class="blood-chart-element-header">
<div class="blood-chart-coin">
<img :src="getImageUrl(coin.vamplogo)" alt="logo" />
<template v-if="cycleStore.getCycleWinner.contractAddress === coin.contractAddress">
<img :src="coin.vampwinner2" alt="logo" />
</template>
<template v-else>
<img :src="coin.vamplogo" alt="logo" />
</template>
</div>
<div class="blood-chart-coin-title low-mid-text">{{ coin.name }}</div>
</div>
@@ -67,8 +72,7 @@
</div>
<div class="blood-chart-element-footer">
<div class="blood-chart-amount">
<!-- {{ compactNumber(coin.amount) }} -->
{{ coin.amountInBLD.toFixed(2) }}
{{ formatNumber(coin.amountInBLD) }}
</div>
<div>$BLOOD</div>
</div>
@@ -91,7 +95,9 @@
<script setup>
import { computed, ref, inject, onMounted } from "vue";
import { getPercentage, compactNumber } from "@/helper/helper.js";
import { getPercentage, compactNumber, formatNumber } from "@/helper/helper.js";
import { useCycleStore } from "@/stores/cycles";
import { useMemeburnerStore } from "@/stores/memeburner";
import { Swiper, SwiperSlide } from "swiper/vue";
@@ -100,8 +106,7 @@ import "swiper/css";
import "swiper/css/navigation";
import "swiper/css/pagination";
// import required modules
const memeBurnerStore = useMemeburnerStore();
const cycleStore = useCycleStore();
const props = defineProps({
data: Object,
@@ -111,38 +116,15 @@ onMounted(() => {
console.log("bloodchart-data", props.data);
});
const isMobile = inject("isMobile");
const swiperInstance = ref();
function onSwiper(swiper) {
swiperInstance.value = swiper;
}
function getImageUrl(url) {
return new URL(url, import.meta.url).href;
}
const token = computed(() => props.data?.token);
// const dataPoints = [
// {
// name: "$PEPE",
// percentage: 62.2,
// icon: "/assets/img/token/pepevamp.png",
// },
// {
// name: "$SHIB",
// percentage: 31.2,
// icon: "/assets/img/token/shibvamp.png",
// },
// {
// name: "$ELON",
// percentage: 54.5,
// icon: "/assets/img/token/elonvamp.png",
// },
// ];
//start with visual 5% of the filled bar, because otherwise the percentage number is not visible
function getPercentageBloodChart(amount, goal) {
let returnNumber = 5;
if ((Number(amount) / Number(goal)) * 100 < 5) {
@@ -183,7 +165,6 @@ function getPercentageBloodChart(amount, goal) {
.blood-chart-element-header
flex: 0 0 100px
.blood-chart-coin
border-radius: 80px
margin-left: auto
margin-right: auto
position: relative
@@ -192,8 +173,8 @@ function getPercentageBloodChart(amount, goal) {
height: 80px
width: 80px
@media (min-width: 992px)
height: 60px
width: 60px
height: 72px
width: 72px
img
height: 100%
width: 100%
+1 -24
View File
@@ -1,4 +1,3 @@
<!-- zukünftig card component -->
<template>
<div
class="connected-stake bloodline-border card"
@@ -21,14 +20,6 @@
</div>
<slot name="actions"></slot>
<slot></slot>
<!-- <div class="connected-stake-buttons" v-if="!stakeMenu">
<div class="btn btn-immortal" @click="openStake">Stake</div>
<div v-if="walletStore.memeToken?.staked === 0 && !stakeonly" class="btn btn-immortal btn--disabled">
Unstake
</div>
<div v-else-if="!stakeonly" class="btn btn-immortal" @click="openUnstake">Unstake</div>
</div> -->
</div>
</template>
@@ -38,8 +29,6 @@ import { useWalletStoreV2 } from "@/stores/walletV2";
import { ref } from "vue";
import { useSlots } from "vue";
const walletStore = useWalletStoreV2();
const tokenStore = useTokenStore();
const slots = useSlots();
const props = defineProps({
@@ -54,19 +43,6 @@ const props = defineProps({
default: false,
},
});
const stakeMenu = ref(false);
const stake = ref(null);
function openStake() {
stake.value = true;
stakeMenu.value = true;
}
function openUnstake() {
stake.value = false;
stakeMenu.value = true;
}
</script>
<style lang="sass">
@@ -100,6 +76,7 @@ function openUnstake() {
display: flex
text-align: center
gap: 16px
justify-content: center
// div
// flex: 1 1 50%
</style>
+11 -48
View File
@@ -37,7 +37,7 @@
<div
class="btn btn-immortal stake-button"
v-else-if="stateClaimComp === 1"
@click="stakeAndClaimAllRounds"
@click="stakeAndClaimAllCycles"
>
Stake & Claim Rest
</div>
@@ -55,7 +55,9 @@
</div>
</template>
<template v-slot:message-end>
<div class="input-balance">Balance: {{ walletStore.memeToken?.unclaimedRewards }}</div>
<div class="input-balance">
Balance: {{ formatNumber(walletStore.memeToken?.unclaimedRewards) }}
</div>
</template>
</stake-menu>
</Transition>
@@ -88,6 +90,8 @@ import { useTokenStore } from "@/stores/tokens";
import { useRewardLockerStore } from "@/stores/rewardlocker";
import { useRouter } from "vue-router";
import { useToast } from "vue-toastification";
import { formatNumber } from "@/helper/helper.js";
import { showSuccessToast } from "@/helper/toast.js";
const toast = useToast();
const rewardLockerStore = useRewardLockerStore();
@@ -121,17 +125,12 @@ function openStake() {
stakeMenu.value = true;
}
function openUnstake() {
stake.value = false;
stakeMenu.value = true;
}
async function stakeAndClaimAllRounds() {
async function stakeAndClaimAllCycles() {
try {
const unclaimedRewards = walletStore.memeToken?.unclaimedRewards;
stateClaim.value = 2;
const coefficient = (10000 * tokenNumber.value) / unclaimedRewards;
var hash = await rewardLockerStore.stakeAndClaimAllRounds(coefficient);
var hash = await rewardLockerStore.stakeAndClaimAllCycles(coefficient);
stateClaim.value = 3;
const data = await waitForTransaction({
hash: hash,
@@ -147,7 +146,7 @@ async function stakeAndClaimAllRounds() {
//ClaimedReward (address staker, uint256 reward)
const outputClaim = Number(rewardData.topics[2]) / Math.pow(10, tokenStore.memeToken.decimals);
showSuccessToast(
outputClaim.toFixed(5),
formatNumber(outputClaim),
"Success!",
"You just claimed and staked",
"Join the next cycle to increase your rewards and win with your clan"
@@ -178,7 +177,7 @@ async function claimAll() {
//ClaimedReward (address staker, uint256 reward)
const outputClaim = Number(rewardData.topics[2]) / Math.pow(10, tokenStore.memeToken.decimals);
showSuccessToast(
outputClaim.toFixed(5),
formatNumber(outputClaim),
"Success!",
"You just claimed",
"Join the next cycle to increase your rewards and win with your clan."
@@ -220,42 +219,6 @@ const stateClaimComp = computed(() => {
}
return returnState;
});
function showSuccessToast(value, header, subheader, info) {
// Define the content object with the component, props and listeners
const content = {
component: StakeSuccessToast,
// Any prop can be passed, but don't expect them to be reactive
props: {
// counter: this.counter,
// value: tokenStore.activeToken.rewards?.toFixed(5),
value: value,
header: header,
subheader: subheader,
info: info,
},
// Listen and react to events using callbacks. In this case we listen for
// the "click" event emitted when clicking the toast button
listeners: {},
};
// Render the toast and its contents
toast(content, {
position: "top-center",
icon: false,
closeOnClick: false,
toastClassName: "modal-overlay",
closeButton: false,
hideProgressBar: true,
timeout: false,
});
}
</script>
<style lang="sass">
// .smooth-enter-active, .smooth-leave-active
// transition: opacity 0.1s
// .smooth-enter, .smooth-leave-to
// height: 0
</style>
<style lang="sass"></style>
+6 -15
View File
@@ -67,10 +67,8 @@
import { ref, toRaw, onMounted, onUnmounted, getCurrentInstance } from "vue";
import { useWalletStoreV2 } from "@/stores/walletV2";
import { useTokenStore } from "@/stores/tokens";
import Meme1Json from "@/assets/contracts/Meme1.json";
import TokenNamePrice from "./TokenNamePrice.vue";
import TokenLogo from "./TokenLogo.vue";
import TokenInput from "./TokenInput.vue";
import StakeComponentV1 from "@/components/StakeComponentV1.vue";
import { getAddressShortName, getblocky } from "@/helper/helper.js";
@@ -83,21 +81,15 @@ const router = useRouter();
const walletStore = useWalletStoreV2();
const tokenStore = useTokenStore();
const goerliKey = import.meta.env.VITE_GOERLI_KEY;
// const goerliKey = import.meta.env.VITE_GOERLI_KEY;
const fromAddress = ref(null);
const accountSub = ref(null);
const metaMaskInstalled = ref(false);
const instance = getCurrentInstance();
async function disconnectWallet() {
console.log("disconnectWallet");
try {
instance.parent.emit("update:modelValue", false);
await disconnect();
// walletStore.connected = false;
// walletStore.address = null;
} catch (error) {
console.log("error", error);
}
@@ -112,10 +104,12 @@ function isMetaMaskInstalled() {
return false;
}
//go to the sacrifice-page and select the clicked token
//if contract === bloodline show buy
//we could also show buy, if there is no pepe
function badgeClick(token) {
var tokenData = tokenStore.getToken(token.contractAddress);
tokenStore.activeToken = tokenData;
// router.push({ name: "home", hash: `#${tokenData.name}` });
if (tokenStore.memeToken.contractAddress === token.contractAddress) {
//buy
window.open(
@@ -128,6 +122,7 @@ function badgeClick(token) {
}
}
//special case for metaMask, but I think that is the most used wallet
async function connectWallet(connector) {
if (connector.id === "metaMask" && !isMetaMaskInstalled()) {
window.open(" https://metamask.io/", "_blank");
@@ -136,10 +131,6 @@ async function connectWallet(connector) {
instance.parent.emit("update:modelValue", false);
await walletStore.connectWallet(toRaw(connector));
}
onMounted(async () => {
console.log("window.ethereum", window.ethereum);
});
</script>
<style lang="sass">
+4 -6
View File
@@ -26,9 +26,7 @@
</div>
</div>
<div v-if="!isMobile">
<!-- <div v-if="!connected" class="btn btn-immortal" @click="walletStore.connectWallet">connect</div> -->
<div v-if="!address" class="btn btn-immortal mid-text" @click="showPanel = true">connect</div>
<!-- <span v-else @click="showPanel = true"> test</span> -->
<div v-if="!address" class="btn btn-immortal mid-text" @click="showPanel = true">Connect</div>
<div class="login-icon-desktop mid-text" v-else @click="showPanel = true">
<img :src="getblocky(address)" alt="avatar" />
<div>{{ getAddressShortName(walletStore.address) }}</div>
@@ -58,7 +56,7 @@ import { useRoute, useRouter } from "vue-router";
const emit = defineEmits(["showPanel"]);
const walletStore = useWalletStoreV2();
const { connected, address } = storeToRefs(walletStore);
const { address } = storeToRefs(walletStore);
const isMobile = inject("isMobile");
const showPanel = inject("showPanel");
@@ -117,7 +115,7 @@ onBeforeUnmount(() => {
transition: transform .3s ease,visibility 0s .3s linear
height: 82px
@media (min-width: 992px)
height: 96px
height: 80px
// &.navbar--hidden
// transform: translate3d(0,-100%,0)
.navbar-inner
@@ -143,7 +141,7 @@ onBeforeUnmount(() => {
letter-spacing: 0.138em
line-height: 73.107px
@media (min-width: 992px)
font-size: 48px
font-size: 42px
a
text-decoration: none
color: white
+72 -239
View File
@@ -1,6 +1,5 @@
<template>
<div class="sacrifice-wrapper card card--glow bloodline-wrapper">
<!-- {{ activeToken.allowance }} -->
<div class="sacrifice-headline">Select Sacrifice</div>
<div class="sacrifice-select-tokens">
<div class="sacrifice-tokens">
@@ -35,11 +34,11 @@
}"
>
<token-input
:modelValue="tokenNumber"
:modelValue="sacrificeStore.sacrificeNumber"
@input="
($event) => {
tokenNumber = $event.target.value;
return processChange($event.target.value);
sacrificeStore.sacrificeNumber = $event.target.value;
processChange($event.target.value);
}
"
:max="activeWalletToken?.balanceOf"
@@ -50,7 +49,7 @@
<div class="sacrifice-adder-step bloodline-badge" @click="addTokens(100000000)">+100m</div>
<div class="sacrifice-adder-step bloodline-badge" @click="addTokens(1000000000)">+1b</div>
</template>
<template v-slot:message-end>
<template v-slot:message-end v-if="activeWalletToken?.balanceOf">
<div class="input-balance tiny-text">
Balance:
{{ activeWalletToken?.balanceOf }}
@@ -71,8 +70,8 @@
}"
>
<div class="sacrifice-to-body">
<token-name-price name="$BLOOD" :price="`≈${output?.toFixed(5)}`"></token-name-price>
<token-logo img="/assets/img/token/bloodline.png" :alt="'bloodline logo'"></token-logo>
<token-name-price name="$BLOOD" :price="`≈${formatNumber(output)}`"></token-name-price>
<token-logo :img="activeToken.vamp.logo" :size="64" :alt="activeToken.vamp.name"></token-logo>
</div>
<div class="sacrifice-staking-bonus">
@@ -84,7 +83,14 @@
}
"
>
<div class="mid-mid-text">+ Staking Bonus</div>
<div class="mid-mid-text" v-if="!walletStore.connected">+ Staking Bonus</div>
<div
class="mid-mid-text"
v-else-if="walletStore.memeToken?.staked === 0 || cycleStore.currentCycle === 1"
>
No Staking Bonus
</div>
<div class="mid-mid-text" v-else>+ TODO Staking Bonus</div>
<div class="icon">
<font-awesome-icon icon="chevron-down" />
</div>
@@ -106,7 +112,7 @@
<div
class="btn btn-immortal sub-header"
disabled
v-else-if="tokenNumber > activeWalletToken?.balanceOf"
v-else-if="sacrificeStore.sacrificeNumber > activeWalletToken?.balanceOf"
>
Insufficient Balance
</div>
@@ -114,25 +120,27 @@
class="btn btn-immortal sub-header"
v-else-if="
activeToken.allowance > 0 &&
activeToken.allowance >= tokenNumber &&
activeToken.allowance >= sacrificeStore.sacrificeNumber &&
(stateComputed === 1 || stateComputed === 4)
"
@click="sacrificeToken(tokenNumber)"
@click="sacrificeToken"
>
Sacrifice 🩸
</div>
<div
class="btn btn-immortal sub-header"
v-else-if="
(!activeToken.allowance || activeToken.allowance < tokenNumber) &&
(!activeToken.allowance || activeToken.allowance < sacrificeStore.sacrificeNumber) &&
(stateComputed === 1 || stateComputed === 4)
"
@click="approveToken(tokenNumber)"
@click="approveToken(sacrificeStore.sacrificeNumber)"
>
Approve Token
</div>
<div class="btn btn-immortal sub-header" disabled v-if="stateComputed === 2">Sign Transaction</div>
<div class="btn btn-immortal sub-header" disabled v-if="stateComputed === 3">
<div class="btn btn-immortal sub-header" disabled v-else-if="stateComputed === 2">
Sign Transaction
</div>
<div class="btn btn-immortal sub-header" disabled v-else-if="stateComputed === 3">
<loading-component></loading-component>
</div>
</template>
@@ -147,52 +155,42 @@
<script setup>
import { ref, defineProps, watch, inject, nextTick, onMounted, onBeforeUnmount, computed, markRaw } from "vue";
import { useWalletStoreV2 } from "@/stores/walletV2";
import { useRoundsStore } from "@/stores/rounds";
import { useCycleStore } from "@/stores/cycles";
import { useTokenStore } from "@/stores/tokens";
import { useMemeburnerStore } from "@/stores/memeburner";
import { useUniswapStore } from "@/stores/uniswap";
import { useSacrificeStore } from "@/stores/sacrifice";
import StakeComponentV1 from "@/components/StakeComponentV1.vue";
import LoadingComponent from "@/components/LoadingComponent.vue";
import TokenInput from "@/components/TokenInput.vue";
import TokenNamePrice from "@/components/TokenNamePrice.vue";
import TokenLogo from "@/components/TokenLogo.vue";
import StakeSuccessToast from "@/components/toasts/StakeSuccessToast.vue";
import ApprovedToast from "@/components/toasts/ApprovedToast.vue";
import { useToast } from "vue-toastification";
const roundStore = useRoundsStore();
const toast = useToast();
import { storeToRefs } from "pinia";
import { waitForTransaction, readContract, watchBlockNumber, multicall } from "@wagmi/core";
import Helper from "@/utils/helper.js";
const cycleStore = useCycleStore();
const sacrificeStore = useSacrificeStore();
const toast = useToast();
import { debounce, formatNumber } from "@/helper/helper.js";
const isMobile = inject("isMobile");
const showPanel = inject("showPanel");
const walletStore = useWalletStoreV2();
// const { connected } = storeToRefs(walletStore);
const tokenStore = useTokenStore();
const { activeToken } = storeToRefs(tokenStore);
const memeburnerStore = useMemeburnerStore();
const uniswapStore = useUniswapStore();
const props = defineProps({
data: Array,
});
// watch(
// activeToken,
// () => {
// tokenNumber.value = null;
// },
// { deep: true }
// );
const tokenNumber = ref(null);
const output = ref(0);
const loading = ref(false);
const blockEvent = ref(null);
const approveToast = ref(null);
/**
* state 0 enter amount
* state 1 rdy to go
@@ -200,7 +198,6 @@ const blockEvent = ref(null);
* state 3 loading
* state 4 sacrificed
*/
const state = ref(0);
const showStakingMenu = ref(false);
const approvalData = ref(null);
@@ -214,18 +211,29 @@ const activeWalletToken = computed(() => {
const stateComputed = computed(() => {
let returnState = 0;
if (tokenNumber.value === null || tokenNumber.value === "" || tokenNumber.value === 0) {
if (
sacrificeStore.sacrificeNumber === null ||
sacrificeStore.sacrificeNumber === "" ||
sacrificeStore.sacrificeNumber === 0
) {
returnState = 0;
} else if (state.value === 2) {
} else if (sacrificeStore.sacrificeState === 2) {
returnState = 2;
} else if (state.value === 3) {
} else if (sacrificeStore.sacrificeState === 3) {
returnState = 3;
} else if (tokenNumber.value !== null || tokenNumber.value !== "" || tokenNumber.value > 0) {
} else if (
sacrificeStore.sacrificeNumber !== null ||
sacrificeStore.sacrificeNumber !== "" ||
sacrificeStore.sacrificeNumber > 0
) {
returnState = 1;
}
return returnState;
});
const processChange = Helper.debounce((value) => getRewardsFor(value));
const processChange = debounce(async (value) => {
const returnValue = await sacrificeStore.getRewardsFor(value, activeToken.value);
output.value = returnValue.output;
});
onMounted(() => {
blockEvent.value = watchBlockNumber(
@@ -234,37 +242,10 @@ onMounted(() => {
},
async (blockNumber) => {
console.log("blockNumber", blockNumber);
await getRewardsFor(tokenNumber.value);
// if (tokenNumber.value && tokenNumber.value > 0) {
// console.log("tokenNumber.value", tokenNumber.value);
// var quoteRewards = await uniswapStore.quoteExactInputSingle(
// tokenNumber.value * Math.pow(10, tokenStore.activeToken.decimals)
// );
// const quoteRewards1 = Number(quoteRewards) / Math.pow(10, tokenStore.activeToken.decimals);
// console.log("quoteRewards", quoteRewards);
// const rewardsForResult = await memeburnerStore.getRewardFor(
// tokenNumber.value * Math.pow(10, tokenStore.activeToken.decimals)
// );
// const rewardsForResult1 = Number(rewardsForResult) / Math.pow(10, tokenStore.activeToken.decimals);
// console.log("rewardsForResult1", rewardsForResult1);
// console.log("quoteRewards1", quoteRewards1);
// console.log("compare", quoteRewards1 * 0.995);
// console.log("ifcompare1", quoteRewards1 * 0.995 > rewardsForResult1);
// //return bigger number
// if (quoteRewards1 * 0.995 > rewardsForResult1) {
// //sacrificememe
// output.value = quoteRewards1;
// // const hash = await memeburnerStore.sacrificeMeme(tokenNumber.value);
// } else {
// output.value = rewardsForResult1;
// //sacrificeMemeAndBuyBLOOD
// // const hash = await memeburnerStore.sacrificeMeme(tokenNumber.value);
// }
// }
//
var rewardValue = await sacrificeStore.getRewardsFor(sacrificeStore.sacrificeNumber, activeToken.value);
output.value = rewardValue.output;
}
);
console.log("blockEvent.value", blockEvent.value);
});
onBeforeUnmount(() => {
@@ -272,196 +253,42 @@ onBeforeUnmount(() => {
blockEvent.value();
});
async function sacrificeToken(amount) {
console.log("sacrificeToken");
try {
state.value = 2;
const getRewards = await getRewardsFor(amount);
let hash = null;
if (getRewards.variant === "sacrifice") {
console.log("sacrifice");
hash = await memeburnerStore.sacrificeMeme(amount);
console.log("hash", hash);
} else {
console.log("buy");
hash = await memeburnerStore.sacrificeMemeAndBuyBLOOD(amount);
console.log("hash", hash);
}
state.value = 3;
const data = await waitForTransaction({
hash: hash,
onReplaced: (transaction) => console.log("check transaction canceled", transaction),
});
console.log("data", data);
var rewardData = data.logs.find((logObject) => {
return logObject.topics.find(
(topic) => topic === "0x5e60ccd3c81486143d815dce24867a494d7fee585a0a44282cf479b19a5186ee"
);
});
const outputSacrifice = Number(rewardData.data) / Math.pow(10, activeToken.value.decimals);
//activeToken is bad here, because it could change during async request
activeToken.value.allowance = await tokenStore.allowance();
state.value = 4;
console.log("state.value = 4");
showSuccessToast(
outputSacrifice?.toFixed(5),
"Success!",
"You turned your meme into:",
"You can claim once the current cycle is finished and your clan bonus was calculated."
);
await walletStore.loadWalletData();
await roundStore.fillRound(roundStore.currentRound, true);
} catch (error) {
state.value = 0;
console.error(error);
throw new Error(error);
}
}
async function approveToken(amount) {
try {
state.value = 2;
sacrificeStore.sacrificeState = 2;
const hash = await tokenStore.approveToken(amount);
state.value = 3;
sacrificeStore.sacrificeState = 3;
const data = await waitForTransaction({
hash: hash,
});
console.log("data", data);
activeToken.value.allowance = await tokenStore.allowance();
state.value = 1;
sacrificeStore.sacrificeState = 1;
approveToast.value = showApprovedToast();
} catch (error) {
console.error(error);
throw new Error(error);
} finally {
state.value = 0;
}
}
async function getRewardsFor(value) {
console.log("getRewardsFor", value);
loading.value = true;
let variant = null;
let newOutput = 0;
try {
if (!value || isNaN(value)) {
output.value = 0;
state.value = 0;
return;
}
const rewardsForResult = await memeburnerStore.getRewardFor(
BigInt(value * Math.pow(10, activeToken.value.decimals))
);
// const rewardsForResultNumber = Number(rewardsForResult[0]) / Math.pow(10, tokenStore.activeToken.decimals) + Number(rewardsForResult[1]) / Math.pow(10, tokenStore.activeToken.decimals);
const rewardsForResultNumber = rewardsForResult.reduce((x, y) => {
return x + Number(y) / Math.pow(10, tokenStore.activeToken.decimals);
}, 0);
var quoteRewards = await uniswapStore.quoteExactInputSingle(
tokenNumber.value * Math.pow(10, tokenStore.activeToken.decimals)
);
console.log("quoteRewards", quoteRewards);
let variant = "sacrifice";
if (quoteRewards.result) {
console.log("quoteRewards", quoteRewards);
const quoteRewardsNumber = Number(quoteRewards.amount) / Math.pow(10, tokenStore.activeToken.decimals);
if (quoteRewardsNumber * 0.995 > rewardsForResultNumber) {
variant = "buy";
console.log("use Buy-function", { quoteRewardsNumber: quoteRewardsNumber, rewardsForResultNumber });
} else {
console.log("use sacrifice-function", {
quoteRewardsNumber: quoteRewardsNumber,
rewardsForResultNumber,
});
}
} else {
/**
* case 4
* quoter threw an error
*/
//
newOutput = rewardsForResultNumber;
}
console.log("variant", variant);
const amountDecimal = BigInt(value * Math.pow(10, tokenStore.activeToken.decimals));
console.log("amountDecimal", amountDecimal);
if (!walletStore.connected || (walletStore.connected && activeToken.value.allowance < tokenNumber.value)) {
/**
* case 1
* user is not logged in or Allowance is less than Input, then I show getRewardsForSacrifice Value
* variante not relevant
*/
newOutput = rewardsForResultNumber;
} else if (walletStore.connected && variant === "sacrifice") {
/**
* case 2
* user is logged in and allowance is greater or equal input and variant is sacrifice
*/
newOutput = rewardsForResultNumber;
} else if (walletStore.connected && variant === "buy") {
/**
* case 3
* user is logged in and allowance is greater or equal input and variant is buy
* compare sacrificeMeme-result and sacrificeMemeAndBuyBLOOD-result
*/
const amountSacrifice = await readContract({
address: memeburnerStore.contract.address,
abi: memeburnerStore.contract.abi,
functionName: "sacrificeMeme",
args: [tokenStore.activeToken.contractAddress, amountDecimal.toString(), 0],
account: walletStore.address,
});
const amountBuy = await readContract({
address: memeburnerStore.contract.address,
abi: memeburnerStore.contract.abi,
functionName: "sacrificeMemeAndBuyBLOOD",
args: [tokenStore.activeToken.contractAddress, amountDecimal.toString(), 0],
account: walletStore.address,
});
const amountBuyNumber = Number(amountBuy) / Math.pow(10, tokenStore.activeToken.decimals);
const amountSacrificeNumber = Number(amountSacrifice) / Math.pow(10, tokenStore.activeToken.decimals);
console.log("sacrificeMemeAndBuyBLOOD", amountBuyNumber);
console.log("sacrificeMeme", amountSacrificeNumber);
if (amountBuyNumber * 0.995 > amountSacrificeNumber) {
variant = "buy";
newOutput = amountBuyNumber;
console.log("use buy after comparison sacrificeMemeAndBuyBLOOD and sacrificeMeme");
} else {
variant = "sacrifice";
newOutput = amountSacrificeNumber;
console.log("use sacrifice after comparison sacrificeMemeAndBuyBLOOD and sacrificeMeme");
}
}
output.value = newOutput;
return { ouput: newOutput, variant: variant };
} catch (error) {
console.error("getRewardsFor", error);
} finally {
loading.value = false;
sacrificeStore.sacrificeState = 0;
}
}
async function addTokens(value) {
tokenNumber.value = Number(tokenNumber.value) + Number(value);
output.value = await getRewardsFor(tokenNumber.value).output;
sacrificeStore.sacrificeNumber = Number(sacrificeStore.sacrificeNumber) + Number(value);
output.value = await sacrificeStore.getRewardsFor(sacrificeStore.sacrificeNumber, activeToken.value).output;
}
async function addMaxTokens() {
tokenNumber.value = activeWalletToken.value.balanceOf;
output.value = await getRewardsFor(tokenNumber.value).output;
sacrificeStore.sacrificeNumber = activeWalletToken.value.balanceOf;
output.value = await sacrificeStore.getRewardsFor(sacrificeStore.sacrificeNumber, activeToken.value).output;
}
function showSuccessToast(value, header, subheader, info) {
function showApprovedToast(value, header, subheader, info) {
// Define the content object with the component, props and listeners
const content = {
component: StakeSuccessToast,
component: ApprovedToast,
// Any prop can be passed, but don't expect them to be reactive
props: {
// counter: this.counter,
// value: tokenStore.activeToken.rewards?.toFixed(5),
value: value,
header: header,
subheader: subheader,
@@ -473,16 +300,21 @@ function showSuccessToast(value, header, subheader, info) {
};
// Render the toast and its contents
toast(content, {
position: "top-center",
return toast(content, {
position: "top-right",
icon: false,
closeOnClick: false,
toastClassName: "modal-overlay",
closeButton: false,
// toastClassName: "modal-overlay",
hideProgressBar: true,
timeout: false,
toastClassName: "approve-toast toast-card",
});
}
//call function in the store and remove icon,
async function sacrificeToken() {
await sacrificeStore.sacrificeToken(sacrificeStore.sacrificeNumber, activeToken.value);
toast.dismiss(approveToast.value);
}
</script>
<style lang="sass">
@@ -654,6 +486,7 @@ function showSuccessToast(value, header, subheader, info) {
.input-max
color: var(--grey, #858585)
font-weight: bold
&:hover, &:active, &:focus
color: var(--grey-light, #858585)
cursor: pointer
+37 -46
View File
@@ -32,23 +32,47 @@
<slot name="body">
<token-name-price
:name="tokenStore.getToken(walletStore.memeToken?.contractAddress)?.name"
:price="walletStore.memeToken?.staked"
:price="formatNumber(walletStore.memeToken?.staked)"
></token-name-price>
<token-logo img="/assets/img/token/bloodline.png" :alt="'^y '"></token-logo>
<token-logo img="/assets/img/token/bloodline.png" :alt="'bloodline-token'"></token-logo>
<token-name-price class="stake-reward" name="Extra Reward" price="+25%"></token-name-price>
</slot>
</div>
<slot name="actions">
<div class="connected-stake-buttons" v-if="!stakeMenu">
<div class="btn btn-immortal mid-mid-text" disabled v-if="roundStore.currentRound === 1">Stake</div>
<div class="btn btn-immortal mid-mid-text" v-else @click="openStake">Stake</div>
<div class="mid-mid-text text-center" disabled v-if="!walletStore.connected">
Please Connect Your Wallet
</div>
<div
v-if="(walletStore.memeToken?.staked === 0 && !stakeonly) || roundStore.currentRound === 1"
class="btn btn-immortal mid-mid-text"
disabled
v-if="walletStore.connected && cycleStore.currentCycle === 1"
>
Stake
</div>
<div
class="btn btn-immortal mid-mid-text"
v-else-if="walletStore.connected && cycleStore.currentCycle > 1"
@click="openStake"
>
Stake
</div>
<div
v-if="
walletStore.connected &&
((walletStore.memeToken?.staked === 0 && !stakeonly) || cycleStore.currentCycle === 1)
"
class="btn btn-immortal btn--disabled mid-mid-text"
>
Unstake
</div>
<div v-else-if="!stakeonly" class="btn btn-immortal mid-mid-text" @click="openUnstake">Unstake</div>
<div
v-else-if="walletStore.connected && !stakeonly"
class="btn btn-immortal mid-mid-text"
@click="openUnstake"
>
Unstake
</div>
</div>
<Transition name="smooth">
<stake-menu
@@ -106,12 +130,9 @@
</div>
</div>
</Transition>
<div class="connected-stake-first-round small-text text-center" v-if="roundStore.currentRound === 0">
<div class="connected-stake-first-round small-text text-center" v-if="cycleStore.currentCycle === 0">
No $BLOOD on the market. Staking is activated after the first cycle is finished.
</div>
<div class="connected-stake-claim-info low-mid-text text-center">
You can claim your stake next cycle.
</div>
</slot>
<slot></slot>
</div>
@@ -120,25 +141,25 @@
<script setup>
import { ref, useSlots, computed } from "vue";
import CardComponent from "@/components/CardComponent.vue";
import StakeSuccessToast from "@/components/toasts/StakeSuccessToast.vue";
import StakeMenu from "@/components/StakeMenu.vue";
import TokenNamePrice from "@/components/TokenNamePrice.vue";
import TokenLogo from "@/components/TokenLogo.vue";
import { waitForTransaction } from "@wagmi/core";
import LoadingComponent from "@/components/LoadingComponent.vue";
import { showSuccessToast } from "@/helper/toast.js";
import { useRoundsStore } from "@/stores/rounds";
import { useCycleStore } from "@/stores/cycles";
import { useRewardLockerStore } from "@/stores/rewardlocker";
import { useWalletStoreV2 } from "@/stores/walletV2";
import { useTokenStore } from "@/stores/tokens";
import { useToast } from "vue-toastification";
import { formatNumber } from "@/helper/helper.js";
const toast = useToast();
const walletStore = useWalletStoreV2();
const tokenStore = useTokenStore();
const rewardLockerStore = useRewardLockerStore();
const roundStore = useRoundsStore();
const cycleStore = useCycleStore();
const slots = useSlots();
const props = defineProps({
stakeonly: {
@@ -198,7 +219,7 @@ async function orderUnstake() {
const outputClaim = Number(rewardData.topics[2]) / Math.pow(10, tokenStore.memeToken.decimals);
showSuccessToast(
outputClaim.toFixed(5),
formatNumber(outputClaim),
"Success!",
"You just unstaked",
"You can claim your stake next cycle."
@@ -232,7 +253,7 @@ async function stakeToken() {
state.value = 4;
await walletStore.loadWalletData();
showSuccessToast(
outputClaim.toFixed(5),
formatNumber(outputClaim),
"Success!",
"You just staked",
"Your next sacrifice will get an extra staking bonus as a reward."
@@ -259,36 +280,6 @@ const stateStake = computed(() => {
}
return returnState;
});
function showSuccessToast(value, header, subheader, info) {
// Define the content object with the component, props and listeners
const content = {
component: StakeSuccessToast,
// Any prop can be passed, but don't expect them to be reactive
props: {
// counter: this.counter,
// value: tokenStore.activeToken.rewards?.toFixed(5),
value: value,
header: header,
subheader: subheader,
info: info,
},
// Listen and react to events using callbacks. In this case we listen for
// the "click" event emitted when clicking the toast button
listeners: {},
};
// Render the toast and its contents
toast(content, {
position: "top-center",
icon: false,
closeOnClick: false,
toastClassName: "modal-overlay",
closeButton: false,
hideProgressBar: true,
timeout: false,
});
}
</script>
<style lang="sass">
+37 -30
View File
@@ -60,44 +60,51 @@ async function addTokensPercent(value) {
}
async function unstakeBloodline() {
const fromAddress = walletStore.address;
try {
const fromAddress = walletStore.address;
var test1 = await rewardLockerStore.contract.read.unstakeOrdered([4, fromAddress]);
console.log("test1", test1);
var test = true;
if (test) {
return;
var unstakedOrdered = await rewardLockerStore.contract.read.unstakeOrdered([4, fromAddress]);
//check if states needed here
var hash = await rewardLockerStore.contract.write.orderUnstake();
console.log("hash", hash);
const data = await waitForTransaction({
hash: hash,
});
console.log("data", data);
} catch (error) {
console.error("unstakeBloodline", error);
}
var hash = await rewardLockerStore.contract.write.orderUnstake();
console.log("hash", hash);
const data = await waitForTransaction({
hash: hash,
});
console.log("data", data);
}
async function stakeBloodline() {
const fromAddress = walletStore.address;
const spender = rewardLockerStore.config.contractAddress;
const deadline = Date.now() + 20 * 60;
const decimals = tokenStore.getToken(walletStore.memeToken.contractAddress).decimals;
const value = (tokenNumber.value * Math.pow(10, decimals)).toString();
const nonce = await tokenStore.memeToken.contract.read.nonces([fromAddress]);
console.log("nonce", nonce);
const { types, message, domain, primaryType } = createPermitObject(fromAddress, spender, nonce, deadline, value);
try {
const fromAddress = walletStore.address;
const spender = rewardLockerStore.config.contractAddress;
const deadline = Date.now() + 20 * 60;
const decimals = tokenStore.getToken(walletStore.memeToken.contractAddress).decimals;
const value = (tokenNumber.value * Math.pow(10, decimals)).toString();
const nonce = await tokenStore.memeToken.contract.read.nonces([fromAddress]);
const { types, message, domain, primaryType } = createPermitObject(
fromAddress,
spender,
nonce,
deadline,
value
);
const signature = await signTypedData({
domain: domain,
message: message,
primaryType: primaryType,
types: types,
});
const signature = await signTypedData({
domain: domain,
message: message,
primaryType: primaryType,
types: types,
});
const { r, s, v } = getSignatureRSV(signature);
const { r, s, v } = getSignatureRSV(signature);
var resultStake = await rewardLockerStore.contract.write.stakeToBeSecured([value, deadline, v, r, s]);
console.log("resultStake", resultStake);
var resultStake = await rewardLockerStore.contract.write.stakeToBeSecured([value, deadline, v, r, s]);
} catch (error) {
console.error("stakeBloodline", error);
}
}
</script>
+80 -39
View File
@@ -1,12 +1,12 @@
<template>
<div class="claim bloodline-border bloodline-border__thin grey">
<div class="claim-headline sub-header">You Cycle Rewards</div>
<div class="claim-headline sub-header">Your Cycle Rewards</div>
<!-- <div class="rewards-wrapper" v-if="!isMobile">
<rewards-wrapper
title="Sacrafice Reward"
coin="$BLOOD"
:amount="getCurrentRoundData?.rewards_sacrifice"
:amount="getCurrentCycleData?.rewards_sacrifice"
image="/assets/img/vampir.png"
/>
<div class="rewards-divider bloodline-devider">
@@ -15,7 +15,7 @@
<rewards-wrapper
title="Clan Reward"
coin="$BLOOD"
:amount="getCurrentRoundData?.rewards_clan"
:amount="getCurrentCycleData?.rewards_clan"
image="/assets/img/vampir.png"
/>
</div> -->
@@ -23,46 +23,41 @@
<rewards-wrapper
title="Sacrafice Reward"
coin="$BLOOD"
:amount="getCurrentRoundData?.rewards_sacrifice.toFixed(2)"
:amount="formatNumber(getCurrentCycleData?.rewards_sacrifice)"
image="/assets/img/vampir.png"
/>
<rewards-wrapper
title="Staking Bonus"
coin="$BLOOD"
:amount="getCurrentRoundData?.rewards_staking.toFixed(2)"
:amount="formatNumber(getCurrentCycleData?.rewards_staking)"
info="max: 312m"
image="/assets/img/vampir.png"
/>
<rewards-wrapper
title="Clan Bonus"
coin="$BLOOD"
:amount="getCurrentRoundData?.rewards_clan.toFixed(2)"
:amount="formatNumber(getCurrentCycleData?.rewards_clan)"
image="/assets/img/vampir.png"
/>
</div>
<div class="rewards-total-wrapper">
<div class="rewards-total-headline low-mid-text">Total Reward</div>
<div class="rewards-total-headline sub-header">Total Reward</div>
<div class="rewards-total-inner bloodline-border bloodline-border--variant1">
<token-name-price
name="$BLOOD"
:price="getCurrentRoundData?.rewards_total?.toFixed(5)"
:price="formatNumber(getCurrentCycleData?.rewards_total)"
></token-name-price>
<token-logo img="/assets/img/vampir.png" :alt="'vampire'"></token-logo>
<!-- <div class="rewards-coin low-mid-text">$BLOOD</div>
<div class="rewards-amount header" v-if="activeRound === currentRound">0</div>
<div class="rewards-amount header" v-else>{{ getCurrentRoundData?.rewards_total.toFixed(5) }}</div> -->
<!-- </div> -->
<!-- <img class="bloodline-token" src="/assets/img/token/bloodline.png" alt="vampir" /> -->
</div>
</div>
<div class="claim-button">
<template v-if="!walletStore.connected">
<button class="btn btn-immortal sub-header" @click="showPanel = true">Connect</button>
</template>
<template v-else-if="activeRound === currentRound">
<template v-else-if="activeCycle === currentCycle">
<button class="btn btn-immortal sub-header" @click="router.push({ name: 'home' })">Sacrifice</button>
</template>
<template v-else-if="getCurrentRoundData?.rewards_total > 0">
<template v-else-if="getCurrentCycleData?.rewards_total > 0">
<Transition name="smooth">
<div class="stake-buttons" v-show="!stakeMenu">
<div class="btn btn-immortal" v-if="stateClaimedComp === 0" @click="claimRewards">Claim</div>
@@ -78,11 +73,28 @@
v-model="tokenNumber"
@close="stakeMenu = false"
:stake="stake"
:amount="getCurrentRoundData?.rewards_total"
:amount="getCurrentCycleData?.rewards_total"
v-if="stakeMenu"
>
<template v-slot:body>
<div class="btn btn-immortal stake-button" @click="stakeAndClaim">Stake & Claim Rest</div>
{{ stateStakeClaimComp }}
{{ stateStakeClaim }}
<div class="btn btn-immortal stake-button" disabled v-if="stateStakeClaimComp === 0">
Enter Amount
</div>
<div
class="btn btn-immortal stake-button"
v-else-if="stateStakeClaimComp === 1"
@click="stakeAndClaim"
>
Stake & Claim Rest
</div>
<div class="btn btn-immortal stake-button" disabled v-if="stateStakeClaimComp === 2">
Sign Transaction
</div>
<div class="btn btn-immortal stake-button" disabled v-if="stateStakeClaimComp === 3">
<loading-component></loading-component>
</div>
<div
class="btn transparent small-text cancel-button text-center"
@click="stakeMenu = false"
@@ -107,61 +119,71 @@ import { inject, ref, onMounted, computed } from "vue";
import { useRewardLockerStore } from "@/stores/rewardlocker";
import { useWalletStoreV2 } from "@/stores/walletV2";
import { useTokenStore } from "@/stores/tokens";
import { useRoundsStore } from "@/stores/rounds";
import { useCycleStore } from "@/stores/cycles";
import { useRouter } from "vue-router";
import StakeMenu from "@/components/StakeMenu.vue";
import { waitForTransaction } from "@wagmi/core";
import LoadingComponent from "@/components/LoadingComponent.vue";
import TokenNamePrice from "@/components/TokenNamePrice.vue";
import TokenLogo from "@/components/TokenLogo.vue";
import { formatNumber } from "@/helper/helper.js";
import { showSuccessToast } from "@/helper/toast.js";
const clanRewards = ref(0);
const rewards = ref(0);
const isMobile = inject("isMobile");
const showPanel = inject("showPanel");
const rewardLockerStore = useRewardLockerStore();
const walletStore = useWalletStoreV2();
const tokenStore = useTokenStore();
const roundStore = useRoundsStore();
const { address } = storeToRefs(walletStore);
const cycleStore = useCycleStore();
const router = useRouter();
const { activeRound, currentRound, getCurrentRoundData } = storeToRefs(roundStore);
const { activeCycle, currentCycle, getCurrentCycleData } = storeToRefs(cycleStore);
const stakeMenu = ref(false);
const stake = ref(null);
const tokenNumber = ref(null);
const stateClaim = ref(0);
const stateStakeClaim = ref(0);
async function stakeAndClaim() {
try {
console.log(tokenNumber.value);
console.log(getCurrentRoundData.value.rewards_total);
const coefficient = (10000 * tokenNumber.value) / getCurrentRoundData.value.rewards_total;
var hash = await rewardLockerStore.stakeAndClaimRound(coefficient, roundStore.activeRound);
console.log(getCurrentCycleData.value.rewards_total);
const coefficient = (10000 * tokenNumber.value) / getCurrentCycleData.value.rewards_total;
console.log("hier");
stateStakeClaim.value = 2;
console.log("hier2");
console.log("coefficient", coefficient);
console.log("cycleStore.activeCycle", cycleStore.activeCycle);
var hash = await rewardLockerStore.stakeAndClaimCycle(coefficient, cycleStore.activeCycle);
console.log("hash");
stateStakeClaim.value = 3;
const data = await waitForTransaction({
hash: hash,
});
console.log("data", data);
stateStakeClaim.value = 4;
//ClaimedReward (address staker, uint256 reward)
var rewardData = data.logs.find((logObject) => {
return logObject.topics.find(
(topic) => topic === "0xf86340d97020c624010a208b733db95795281fbc45cb6e6a40d161f91fa3e4a0"
(topic) => topic === "0xd0813ff03c470dcc7baa9ce36914dc2febdfd276d639deffaac383fd3db42ba3"
);
});
//
console.log("rewardData", rewardData);
const outputClaim = Number(rewardData.topics[2]) / Math.pow(10, tokenStore.memeToken.decimals);
const outputClaim = Number(rewardData?.topics[2]) / Math.pow(10, tokenStore.memeToken.decimals);
showSuccessToast(
outputClaim.toFixed(5),
formatNumber(outputClaim),
"Success!",
"You just claimed and staked",
"Join the next cycle to increase your rewards and win with your clan."
);
const walletStore = useWalletStoreV2();
await walletStore.loadWalletData();
} catch (error) {
console.error("stakeAndClaim", error);
} finally {
const walletStore = useWalletStoreV2();
await walletStore.loadWalletData();
stateStakeClaim.value = 1;
}
}
@@ -175,9 +197,9 @@ onMounted(async () => {});
async function claimRewards() {
try {
stateClaim.value = 2;
console.log("getCurrentRoundData", getCurrentRoundData);
console.log("activeRound.value", activeRound.value);
var hash = await rewardLockerStore.claim([activeRound.value]);
console.log("getCurrentCycleData", getCurrentCycleData);
console.log("activeCycle.value", activeCycle.value);
var hash = await rewardLockerStore.claim([activeCycle.value]);
stateClaim.value = 3;
console.log("hash", hash);
const data = await waitForTransaction({
@@ -195,18 +217,17 @@ async function claimRewards() {
const outputClaim = Number(rewardData.topics[2]) / Math.pow(10, tokenStore.memeToken.decimals);
showSuccessToast(
outputClaim.toFixed(5),
formatNumber(outputClaim),
"Success!",
"You just claimed",
"Join the next cycle to increase your rewards and win with your clan."
);
await roundStore.fillRound(activeRound.value, true);
await cycleStore.fillCycle(activeCycle.value, true);
await walletStore.loadWalletData();
} catch (error) {
stateClaim.value = 0;
console.error(error);
throw new Error(error);
throw Error(error);
}
}
@@ -219,6 +240,26 @@ const stateClaimedComp = computed(() => {
}
return returnState;
});
const stateStakeClaimComp = computed(() => {
let returnState = 0;
console.log("tokenNumber.value", tokenNumber.value);
if (
tokenNumber.value === null ||
tokenNumber.value === "" ||
tokenNumber.value === 0 ||
tokenNumber.value > walletStore.memeToken?.unclaimedRewards
) {
returnState = 0;
} else if (stateStakeClaim.value === 2) {
returnState = 2;
} else if (stateStakeClaim.value === 3) {
returnState = 3;
} else if (tokenNumber.value !== null || tokenNumber.value !== "" || tokenNumber.value > 0) {
returnState = 1;
}
return returnState;
});
</script>
<style lang="sass">
-4
View File
@@ -15,10 +15,6 @@
</div>
<div class="right-side">
<token-logo :img="props.logo" :alt="'vampir'"></token-logo>
<!-- <div class="sacrifice-logo" v-if="props.logo">
<img :src="props.logo" alt="vampir" />
</div> -->
</div>
</div>
</div>
+5 -3
View File
@@ -1,6 +1,6 @@
<template>
<div class="token-logo">
<img :src="props.img" :alt="props.alt" />
<img :src="props.img" :alt="props.alt" :style="{ height: `${size}px`, width: `${size}px` }" />
</div>
</template>
@@ -8,6 +8,10 @@
const props = defineProps({
img: String,
alt: Number,
size: {
type: Number,
default: 45,
},
});
</script>
@@ -15,8 +19,6 @@ const props = defineProps({
.token-logo
height: 100%
img
width: 45px
height: 45px
border-radius: 50%
pointer-events: none
@media (min-width: 992px)
-88
View File
@@ -1,88 +0,0 @@
<script>
export default {
name: `TransitionExpand`,
functional: true,
render(createElement, context) {
const data = {
props: {
name: `expand`,
},
on: {
afterEnter(element) {
// eslint-disable-next-line no-param-reassign
element.style.height = `auto`;
},
enter(element) {
const { width } = getComputedStyle(element);
/* eslint-disable no-param-reassign */
element.style.width = width;
element.style.position = `absolute`;
element.style.visibility = `hidden`;
element.style.height = `auto`;
/* eslint-enable */
const { height } = getComputedStyle(element);
/* eslint-disable no-param-reassign */
element.style.width = null;
element.style.position = null;
element.style.visibility = null;
element.style.height = 0;
/* eslint-enable */
// Force repaint to make sure the
// animation is triggered correctly.
// eslint-disable-next-line no-unused-expressions
getComputedStyle(element).height;
requestAnimationFrame(() => {
// eslint-disable-next-line no-param-reassign
element.style.height = height;
});
},
leave(element) {
const { height } = getComputedStyle(element);
// eslint-disable-next-line no-param-reassign
element.style.height = height;
// Force repaint to make sure the
// animation is triggered correctly.
// eslint-disable-next-line no-unused-expressions
getComputedStyle(element).height;
requestAnimationFrame(() => {
// eslint-disable-next-line no-param-reassign
element.style.height = 0;
});
},
},
};
return createElement(`transition`, data, context.children);
},
};
</script>
<style scoped>
* {
will-change: height;
transform: translateZ(0);
backface-visibility: hidden;
perspective: 1000px;
}
</style>
<style>
.expand-enter-active,
.expand-leave-active {
transition: height 1s ease-in-out;
overflow: hidden;
}
.expand-enter,
.expand-leave-to {
height: 0;
}
</style>