13 Commits
28 changed files with 840 additions and 306 deletions
+27 -1
View File
@@ -23,7 +23,8 @@
"vue": "^3.3.2", "vue": "^3.3.2",
"vue-collapsed": "^1.2.8", "vue-collapsed": "^1.2.8",
"vue-router": "^4.2.0", "vue-router": "^4.2.0",
"vue-toastification": "^2.0.0-rc.5" "vue-toastification": "^2.0.0-rc.5",
"vue3-lottie": "^3.2.0"
}, },
"devDependencies": { "devDependencies": {
"@esbuild-plugins/node-globals-polyfill": "^0.2.3", "@esbuild-plugins/node-globals-polyfill": "^0.2.3",
@@ -3941,6 +3942,11 @@
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"dev": true "dev": true
}, },
"node_modules/lodash-es": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
"integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
},
"node_modules/lodash.isequal": { "node_modules/lodash.isequal": {
"version": "4.5.0", "version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
@@ -3964,6 +3970,11 @@
"loose-envify": "cli.js" "loose-envify": "cli.js"
} }
}, },
"node_modules/lottie-web": {
"version": "5.12.2",
"resolved": "https://registry.npmjs.org/lottie-web/-/lottie-web-5.12.2.tgz",
"integrity": "sha512-uvhvYPC8kGPjXT3MyKMrL3JitEAmDMp30lVkuq/590Mw9ok6pWcFCwXJveo0t5uqYw1UREQHofD+jVpdjBv8wg=="
},
"node_modules/lru-cache": { "node_modules/lru-cache": {
"version": "6.0.0", "version": "6.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
@@ -5822,6 +5833,21 @@
"vue": "^3.0.2" "vue": "^3.0.2"
} }
}, },
"node_modules/vue3-lottie": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/vue3-lottie/-/vue3-lottie-3.2.0.tgz",
"integrity": "sha512-PtNXbv7iD4XGmK8CXd71aLWmILIR6P6VzLMDw6ZzmDAeuJZuJ0MdOVnn50LOARgq+cOFJsn/2z+7tZh0F9T9qw==",
"dependencies": {
"lodash-es": "^4.17.21",
"lottie-web": "5.12.2"
},
"engines": {
"node": ">=12"
},
"peerDependencies": {
"vue": "^3.2"
}
},
"node_modules/web3-eth-abi": { "node_modules/web3-eth-abi": {
"version": "1.10.1", "version": "1.10.1",
"resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.10.1.tgz", "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.10.1.tgz",
+2 -1
View File
@@ -24,7 +24,8 @@
"vue": "^3.3.2", "vue": "^3.3.2",
"vue-collapsed": "^1.2.8", "vue-collapsed": "^1.2.8",
"vue-router": "^4.2.0", "vue-router": "^4.2.0",
"vue-toastification": "^2.0.0-rc.5" "vue-toastification": "^2.0.0-rc.5",
"vue3-lottie": "^3.2.0"
}, },
"devDependencies": { "devDependencies": {
"@esbuild-plugins/node-globals-polyfill": "^0.2.3", "@esbuild-plugins/node-globals-polyfill": "^0.2.3",
+21 -3
View File
@@ -13,11 +13,12 @@ import { useCycleStore } from "@/stores/cycles";
import SlideoutPanel from "./components/SlideoutPanel.vue"; import SlideoutPanel from "./components/SlideoutPanel.vue";
import ConnectWallet from "./components/ConnectWallet.vue"; import ConnectWallet from "./components/ConnectWallet.vue";
import BloodSplash from "./components/BloodSplash.vue";
import { getNetwork, fetchTransaction } from "@wagmi/core"; import { getNetwork, fetchTransaction } from "@wagmi/core";
const isMobile = ref(false); const isMobile = ref(false);
const showPanel = ref(false); const showPanel = ref(false);
const splashBlood = ref(0);
const router = useRouter(); const router = useRouter();
const route = useRoute(); const route = useRoute();
@@ -32,8 +33,14 @@ watch(showPanel, (newValue, oldValue) => {
console.log("document.body", document.body); console.log("document.body", document.body);
if (newValue) { if (newValue) {
document.body.classList.add("sideoutpanel-open"); document.body.classList.add("sideoutpanel-open");
if (isMobile) {
document.body.classList.add("mobile");
}
} else { } else {
document.body.classList.remove("sideoutpanel-open"); document.body.classList.remove("sideoutpanel-open");
if (isMobile) {
document.body.classList.remove("mobile");
}
} }
}); });
@@ -58,6 +65,7 @@ function changeRoute(name) {
} }
provide("isMobile", isMobile); provide("isMobile", isMobile);
provide("showPanel", showPanel); provide("showPanel", showPanel);
provide("splashBlood", splashBlood);
onMounted(async () => { onMounted(async () => {
window.addEventListener("resize", handleWindowSizeChange); window.addEventListener("resize", handleWindowSizeChange);
@@ -76,6 +84,7 @@ onMounted(async () => {
cycleStore.activeCycle = cycleStore.currentCycle; cycleStore.activeCycle = cycleStore.currentCycle;
} }
console.log("cycleStore.activeCycle", cycleStore.activeCycle);
await cycleStore.fillCycle(cycleStore.activeCycle); await cycleStore.fillCycle(cycleStore.activeCycle);
}); });
</script> </script>
@@ -88,9 +97,12 @@ onMounted(async () => {
<div class="main" :class="{ 'no-scroll': showPanel, mobile: isMobile }"> <div class="main" :class="{ 'no-scroll': showPanel, mobile: isMobile }">
<RouterView /> <RouterView />
</div> </div>
<blood-splash :key="splashBlood"></blood-splash>
<div class="footer"> <div class="footer">
<div class="footer-inner"> <div class="footer-inner">
<div class="footer-headline">Join Bloodline</div> <div class="footer-headline">Join Bloodline</div>
<div class="footer-social-links"> <div class="footer-social-links">
<div class="social-bloodline-badge"> <div class="social-bloodline-badge">
<div class="social-bloodline-badge-icon"> <div class="social-bloodline-badge-icon">
@@ -139,7 +151,7 @@ onMounted(async () => {
font-size: 24px font-size: 24px
display: flex display: flex
flex-direction: column flex-direction: column
gap: 8px gap: 16px
align-items: center align-items: center
@media (min-width: 992px) @media (min-width: 992px)
justify-content: center justify-content: center
@@ -152,7 +164,7 @@ onMounted(async () => {
border-radius: 14px border-radius: 14px
background: var(--grey, #858585) background: var(--grey, #858585)
display: flex display: flex
padding: 0px 16px padding: 6px 20px
align-items: center align-items: center
flex: 0 1 0 flex: 0 1 0
color: black color: black
@@ -248,4 +260,10 @@ body:hover::-webkit-scrollbar-thumb
.toast-header, .toast-body .toast-header, .toast-body
font-size: 16px font-size: 16px
.Vue-Toastification__container
&.bloodline-toast-container
&.top-right
@media (min-width: 992px)
top: 100px
</style> </style>
File diff suppressed because one or more lines are too long
+4 -5
View File
@@ -72,7 +72,7 @@
</div> </div>
<div class="blood-chart-element-footer"> <div class="blood-chart-element-footer">
<div class="blood-chart-amount"> <div class="blood-chart-amount">
{{ formatNumber(coin.amountInBLD) }} {{ formatNumber(coin.amountInBLD / 10n ** tokenStore.memeToken.decimals) }}
</div> </div>
<div>$BLOOD</div> <div>$BLOOD</div>
</div> </div>
@@ -99,6 +99,8 @@ import { getPercentage, compactNumber, formatNumber } from "@/helper/helper.js";
import { useCycleStore } from "@/stores/cycles"; import { useCycleStore } from "@/stores/cycles";
import { useMemeburnerStore } from "@/stores/memeburner"; import { useMemeburnerStore } from "@/stores/memeburner";
import { useTokenStore } from "@/stores/tokens";
import { Swiper, SwiperSlide } from "swiper/vue"; import { Swiper, SwiperSlide } from "swiper/vue";
// Import Swiper styles // Import Swiper styles
@@ -107,6 +109,7 @@ import "swiper/css/navigation";
import "swiper/css/pagination"; import "swiper/css/pagination";
const cycleStore = useCycleStore(); const cycleStore = useCycleStore();
const tokenStore = useTokenStore();
const props = defineProps({ const props = defineProps({
data: Object, data: Object,
@@ -213,10 +216,6 @@ function getPercentageBloodChart(amount, goal) {
.swiper-slide .swiper-slide
width: 80px width: 80px
.swiper-test
display: flex
flex-direction: column
.blood-arrow .blood-arrow
min-width: 30px min-width: 30px
File diff suppressed because one or more lines are too long
+10 -8
View File
@@ -4,12 +4,12 @@
<template v-slot:body> <template v-slot:body>
<token-name-price <token-name-price
:name="tokenStore.getToken(walletStore.memeToken?.contractAddress)?.name" :name="tokenStore.getToken(walletStore.memeToken?.contractAddress)?.name"
:price="walletStore.memeToken?.unclaimedRewards" :price="formatNumber(walletStore.unclaimedRewards)"
></token-name-price> ></token-name-price>
<token-logo img="/assets/img/token/bloodline.png" :alt="'bloodline logo'"></token-logo> <token-logo img="/assets/img/token/bloodline.png" :alt="'bloodline logo'"></token-logo>
</template> </template>
<template v-slot:actions> <template v-slot:actions>
<template v-if="walletStore.memeToken?.unclaimedRewards > 0"> <template v-if="walletStore.unclaimedRewards > 0">
<Transition name="smooth"> <Transition name="smooth">
<div class="connected-stake-buttons" v-show="!stakeMenu"> <div class="connected-stake-buttons" v-show="!stakeMenu">
<div class="btn btn-immortal mid-mid-text" @click="claimAll" v-if="stateStake === 0">Claim</div> <div class="btn btn-immortal mid-mid-text" @click="claimAll" v-if="stateStake === 0">Claim</div>
@@ -26,7 +26,7 @@
<stake-menu <stake-menu
v-model="tokenNumber" v-model="tokenNumber"
@close="stakeMenu = false" @close="stakeMenu = false"
:amount="walletStore.memeToken?.unclaimedRewards" :amount="walletStore.unclaimedRewards"
:stake="stake" :stake="stake"
v-if="stakeMenu" v-if="stakeMenu"
> >
@@ -56,7 +56,8 @@
</template> </template>
<template v-slot:message-end> <template v-slot:message-end>
<div class="input-balance"> <div class="input-balance">
Balance: {{ formatNumber(walletStore.memeToken?.unclaimedRewards) }} Balance:
{{ formatNumber(walletStore.unclaimedRewards) }}
</div> </div>
</template> </template>
</stake-menu> </stake-menu>
@@ -127,9 +128,10 @@ function openStake() {
async function stakeAndClaimAllCycles() { async function stakeAndClaimAllCycles() {
try { try {
const unclaimedRewards = walletStore.memeToken?.unclaimedRewards; const unclaimedRewards = walletStore.memeToken?.unclaimedRewards / 10n ** tokenStore.memeToken.decimals;
stateClaim.value = 2; stateClaim.value = 2;
const coefficient = (10000 * tokenNumber.value) / unclaimedRewards; console.log("unclaimedRewards", unclaimedRewards);
const coefficient = BigInt(10000 * tokenNumber.value) / unclaimedRewards;
var hash = await rewardLockerStore.stakeAndClaimAllCycles(coefficient); var hash = await rewardLockerStore.stakeAndClaimAllCycles(coefficient);
stateClaim.value = 3; stateClaim.value = 3;
const data = await waitForTransaction({ const data = await waitForTransaction({
@@ -144,7 +146,7 @@ async function stakeAndClaimAllCycles() {
// //
console.log("rewardData", rewardData); console.log("rewardData", rewardData);
//ClaimedReward (address staker, uint256 reward) //ClaimedReward (address staker, uint256 reward)
const outputClaim = Number(rewardData.topics[2]) / Math.pow(10, tokenStore.memeToken.decimals); const outputClaim = BigInt(rewardData.topics[2]) / 10n ** tokenStore.memeToken.decimals;
showSuccessToast( showSuccessToast(
formatNumber(outputClaim), formatNumber(outputClaim),
"Success!", "Success!",
@@ -175,7 +177,7 @@ async function claimAll() {
// //
console.log("rewardData", rewardData); console.log("rewardData", rewardData);
//ClaimedReward (address staker, uint256 reward) //ClaimedReward (address staker, uint256 reward)
const outputClaim = Number(rewardData.topics[2]) / Math.pow(10, tokenStore.memeToken.decimals); const outputClaim = rewardData.topics[2] / 10n ** tokenStore.memeToken.decimals;
showSuccessToast( showSuccessToast(
formatNumber(outputClaim), formatNumber(outputClaim),
"Success!", "Success!",
+24 -9
View File
@@ -5,15 +5,24 @@
<div class="connectors-wrapper"> <div class="connectors-wrapper">
<div <div
class="connectors-element card" class="connectors-element card"
:class="[[connector.id]]"
v-for="connector in walletStore.config?.connectors" v-for="connector in walletStore.config?.connectors"
@click="connectWallet(connector)" @click="connectWallet(connector)"
> >
<div class="connector-icon"> <div class="connector-icon">
<img :src="`/assets/img/connectors/${connector.id}.svg`" :alt="`${connector.name} Logo`" /> <template v-if="connector.id === 'injected'">
<font-awesome-icon :icon="['fas', 'wallet']" />
</template>
<template v-else>
<img :src="`/assets/img/connectors/${connector.id}.svg`" :alt="`${connector.name} Logo`" />
</template>
</div> </div>
<div class="connector-name"> <div class="connector-name">
<template <template
v-if="connector.id !== 'metaMask' || (connector.id === 'metaMask' && isMetaMaskInstalled())" v-if="
connector.id !== 'metaMask' ||
(connector.id === 'metaMask' && isMetaMaskInstalled(connector))
"
> >
{{ connector.name }} {{ connector.name }}
</template> </template>
@@ -42,7 +51,7 @@
<div class="connected-token" v-for="token in walletStore.token"> <div class="connected-token" v-for="token in walletStore.token">
<token-name-price <token-name-price
:name="tokenStore.getToken(token.contractAddress).name" :name="tokenStore.getToken(token.contractAddress).name"
:price="token.balanceOf" :price="token.balanceOf / 10n ** tokenStore.getToken(token.contractAddress).decimals"
></token-name-price> ></token-name-price>
<div class="connected-token-button"> <div class="connected-token-button">
<div class="bloodline-badge grey" @click="badgeClick(token)"> <div class="bloodline-badge grey" @click="badgeClick(token)">
@@ -95,10 +104,9 @@ async function disconnectWallet() {
} }
} }
function isMetaMaskInstalled() { function isMetaMaskInstalled(connector) {
//metamask is not installed but showing true, is that a bug? const metamaskInstalled = connector?.options?.getProvider();
if (typeof window.ethereum !== "undefined" && window.ethereum?.isMetaMask && !window.ethereum.isBraveWallet) { if (metamaskInstalled) {
console.log("MetaMask is installed!", window.ethereum);
return true; return true;
} }
return false; return false;
@@ -109,7 +117,6 @@ function isMetaMaskInstalled() {
//we could also show buy, if there is no pepe //we could also show buy, if there is no pepe
function badgeClick(token) { function badgeClick(token) {
var tokenData = tokenStore.getToken(token.contractAddress); var tokenData = tokenStore.getToken(token.contractAddress);
tokenStore.activeToken = tokenData;
if (tokenStore.memeToken.contractAddress === token.contractAddress) { if (tokenStore.memeToken.contractAddress === token.contractAddress) {
//buy //buy
window.open( window.open(
@@ -124,7 +131,7 @@ function badgeClick(token) {
//special case for metaMask, but I think that is the most used wallet //special case for metaMask, but I think that is the most used wallet
async function connectWallet(connector) { async function connectWallet(connector) {
if (connector.id === "metaMask" && !isMetaMaskInstalled()) { if (connector.id === "metaMask" && !isMetaMaskInstalled(connector)) {
window.open(" https://metamask.io/", "_blank"); window.open(" https://metamask.io/", "_blank");
return; return;
} }
@@ -151,6 +158,14 @@ async function connectWallet(connector) {
&:hover, &:active, &:focus &:hover, &:active, &:focus
background-color: lighten(#858585, 20%) background-color: lighten(#858585, 20%)
cursor: pointer cursor: pointer
&.injected
.connector-icon
background-color: white
display: flex
justify-content: center
align-items: center
svg
font-size: 25px
.connector-icon .connector-icon
border-radius: 12px border-radius: 12px
width: 40px width: 40px
-15
View File
@@ -147,21 +147,6 @@ onBeforeUnmount(() => {
color: white color: white
.navbar-center .navbar-center
display: flex display: flex
margin-left: auto
.navbar-social-links
display: flex
gap: 18px
.social-bloodline-badge
font-size: 16px
padding: 8px 16px 8px 16px
border-radius: 14px
background-color: #0F0F0F
display: flex
&:hover,&:active,&:focus
background-color: lighten(#0F0F0F, 10%)
cursor: pointer
.social-bloodline-badge-icon
margin-right: 8px
.navbar-end .navbar-end
display: flex display: flex
margin-left: auto margin-left: auto
+1 -1
View File
@@ -17,7 +17,7 @@ import TokenLogo from "@/components/TokenLogo.vue";
const props = defineProps({ const props = defineProps({
title: String, title: String,
info: String, info: String,
amount: String, amount: [String, Number],
image: String, image: String,
}); });
</script> </script>
+58 -27
View File
@@ -1,6 +1,6 @@
<template> <template>
<div class="sacrifice-wrapper card card--glow bloodline-wrapper"> <div class="sacrifice-wrapper card card--glow">
<div class="sacrifice-headline">Select Sacrifice</div> <div class="sacrifice-headline">Select Sacrifice {{ splashBlood }}</div>
<div class="sacrifice-select-tokens"> <div class="sacrifice-select-tokens">
<div class="sacrifice-tokens"> <div class="sacrifice-tokens">
<div <div
@@ -25,34 +25,41 @@
</div> </div>
</div> </div>
<div class="sacrifice-from-to-wrapper" v-if="activeToken.contractAddress"> <div class="sacrifice-from-to-wrapper" v-if="activeToken.contractAddress">
<div <div class="sacrifice-from-wrapper bloodline-border bloodline-border--variant1 purple">
:class="{
'sacrifice-from-wrapper': true,
'bloodline-border': true,
'bloodline-border--variant1': true,
purple: true,
}"
>
<token-input <token-input
:modelValue="sacrificeStore.sacrificeNumber" :modelValue="sacrificeStore.sacrificeNumber / 10n ** activeToken.decimals"
@input=" @input="
($event) => { ($event) => {
sacrificeStore.sacrificeNumber = $event.target.value; const value = BigInt($event.target.value) * 10n ** 18n;
processChange($event.target.value); sacrificeStore.sacrificeNumber = value;
processChange(value);
} }
" "
:max="activeWalletToken?.balanceOf" :max="activeWalletToken?.balanceOf"
:logo="activeToken.logo" :logo="activeToken.logo"
> >
<template v-slot:message> <template v-slot:message>
<div class="sacrifice-adder-step bloodline-badge" @click="addTokens(10000000)">+10m</div> <div
<div class="sacrifice-adder-step bloodline-badge" @click="addTokens(100000000)">+100m</div> class="sacrifice-adder-step bloodline-badge"
<div class="sacrifice-adder-step bloodline-badge" @click="addTokens(1000000000)">+1b</div> v-for="steps in activeToken.addSteps"
:key="steps.name"
@click="addTokens(steps.amount)"
>
<template
v-if="
!walletStore.connected ||
sacrificeStore.sacrificeNumber < activeWalletToken?.balanceOf
"
>
+{{ steps.name }}
</template>
<template v-else> -{{ steps.name }} </template>
</div>
</template> </template>
<template v-slot:message-end v-if="activeWalletToken?.balanceOf"> <template v-slot:message-end v-if="activeWalletToken?.balanceOf">
<div class="input-balance tiny-text"> <div class="input-balance tiny-text">
Balance: Balance:
{{ activeWalletToken?.balanceOf }} {{ BigInt(activeWalletToken?.balanceOf) / 10n ** activeToken.decimals }}
</div> </div>
<div class="input-max tiny-text" @click="addMaxTokens">Max</div> <div class="input-max tiny-text" @click="addMaxTokens">Max</div>
</template> </template>
@@ -178,6 +185,7 @@ import { debounce, formatNumber } from "@/helper/helper.js";
const isMobile = inject("isMobile"); const isMobile = inject("isMobile");
const showPanel = inject("showPanel"); const showPanel = inject("showPanel");
const splashBlood = inject("splashBlood");
const walletStore = useWalletStoreV2(); const walletStore = useWalletStoreV2();
@@ -192,6 +200,8 @@ const output = ref(0);
const stakingOutput = ref(null); const stakingOutput = ref(null);
const blockEvent = ref(null); const blockEvent = ref(null);
const approveToast = ref(null); const approveToast = ref(null);
const addOperator = ref(true);
const splashesUsed = ref([]);
/** /**
* state 0 enter amount * state 0 enter amount
* state 1 rdy to go * state 1 rdy to go
@@ -215,7 +225,7 @@ const stateComputed = computed(() => {
if ( if (
sacrificeStore.sacrificeNumber === null || sacrificeStore.sacrificeNumber === null ||
sacrificeStore.sacrificeNumber === "" || sacrificeStore.sacrificeNumber === "" ||
sacrificeStore.sacrificeNumber === 0 sacrificeStore.sacrificeNumber === 0n
) { ) {
returnState = 0; returnState = 0;
} else if (sacrificeStore.sacrificeState === 2) { } else if (sacrificeStore.sacrificeState === 2) {
@@ -258,6 +268,7 @@ onBeforeUnmount(() => {
async function approveToken(amount) { async function approveToken(amount) {
try { try {
console.log("amount", amount);
sacrificeStore.sacrificeState = 2; sacrificeStore.sacrificeState = 2;
const hash = await tokenStore.approveToken(amount); const hash = await tokenStore.approveToken(amount);
sacrificeStore.sacrificeState = 3; sacrificeStore.sacrificeState = 3;
@@ -277,15 +288,25 @@ async function approveToken(amount) {
} }
async function addTokens(value) { async function addTokens(value) {
sacrificeStore.sacrificeNumber = Number(sacrificeStore.sacrificeNumber) + Number(value); if (!walletStore.connected || sacrificeStore.sacrificeNumber < activeWalletToken.value?.balanceOf) {
sacrificeStore.sacrificeNumber = BigInt(sacrificeStore.sacrificeNumber) + value;
} else {
sacrificeStore.sacrificeNumber = sacrificeStore.sacrificeNumber - value;
if (sacrificeStore.sacrificeNumber < 0n) {
sacrificeStore.sacrificeNumber = 0n;
}
}
const rewardValue = await sacrificeStore.getRewardsFor(sacrificeStore.sacrificeNumber, activeToken.value); const rewardValue = await sacrificeStore.getRewardsFor(sacrificeStore.sacrificeNumber, activeToken.value);
output.value = rewardValue.output; output.value = rewardValue.output;
stakingOutput.value = rewardValue.staking; stakingOutput.value = rewardValue.staking;
} }
async function addMaxTokens() { async function addMaxTokens() {
sacrificeStore.sacrificeNumber = activeWalletToken.value.balanceOf; addOperator.value = !addOperator.value;
sacrificeStore.sacrificeNumber = activeWalletToken.value?.balanceOf;
const rewardValue = await sacrificeStore.getRewardsFor(sacrificeStore.sacrificeNumber, activeToken.value); const rewardValue = await sacrificeStore.getRewardsFor(sacrificeStore.sacrificeNumber, activeToken.value);
console.log("rewardValue", rewardValue);
output.value = rewardValue.output; output.value = rewardValue.output;
stakingOutput.value = rewardValue.staking; stakingOutput.value = rewardValue.staking;
} }
@@ -303,7 +324,9 @@ function showApprovedToast(value, header, subheader, info) {
}, },
// Listen and react to events using callbacks. In this case we listen for // Listen and react to events using callbacks. In this case we listen for
// the "click" event emitted when clicking the toast button // the "click" event emitted when clicking the toast button
listeners: {}, listeners: {
sacrificed: showSplash,
},
}; };
// Render the toast and its contents // Render the toast and its contents
@@ -318,9 +341,16 @@ function showApprovedToast(value, header, subheader, info) {
}); });
} }
function showSplash() {
splashBlood.value++;
}
//call function in the store and remove icon, //call function in the store and remove icon,
async function sacrificeToken() { async function sacrificeToken() {
await sacrificeStore.sacrificeToken(sacrificeStore.sacrificeNumber, activeToken.value); var result = await sacrificeStore.sacrificeToken(sacrificeStore.sacrificeNumber, activeToken.value);
if (result) {
showSplash();
}
toast.dismiss(approveToast.value); toast.dismiss(approveToast.value);
} }
@@ -328,8 +358,8 @@ async function changeActiveToken(token) {
console.log("changeActiveToken"); console.log("changeActiveToken");
tokenStore.activeToken = token; tokenStore.activeToken = token;
if (walletStore.connected) { if (walletStore.connected) {
//TODO, wenn connected, dann all diese Daten laden? // //TODO, wenn connected, dann all diese Daten laden?
tokenStore.activeToken.balance = await walletStore.getTokenBalance(token); // tokenStore.activeToken.balance = await walletStore.getTokenBalance(token);
tokenStore.activeToken.allowance = Number(await tokenStore.allowance()); tokenStore.activeToken.allowance = Number(await tokenStore.allowance());
} }
var rewards = await sacrificeStore.getRewardsFor(sacrificeStore.sacrificeNumber, token); var rewards = await sacrificeStore.getRewardsFor(sacrificeStore.sacrificeNumber, token);
@@ -454,7 +484,8 @@ async function changeActiveToken(token) {
display: flex display: flex
gap: 6px gap: 6px
.sacrifice-adder-step .sacrifice-adder-step
font-size: 14px font-size: 12px
align-items: center
background: var(--grey, #858585) background: var(--grey, #858585)
color: var(--midnight-black, #0F0F0F) color: var(--midnight-black, #0F0F0F)
&:hover, &:hover,
@@ -462,8 +493,8 @@ async function changeActiveToken(token) {
&:focus &:focus
background-color: var(--grey-light) background-color: var(--grey-light)
cursor: pointer cursor: pointer
@media (min-width: 992px) // @media (min-width: 992px)
font-size: 12px // font-size: 12px
// .sacrifice-adder-balance // .sacrifice-adder-balance
// margin-left: auto // margin-left: auto
// .sacrifice-adder-max // .sacrifice-adder-max
+24 -6
View File
@@ -31,8 +31,9 @@
<div class="connected-stake-body"> <div class="connected-stake-body">
<slot name="body"> <slot name="body">
<token-name-price <token-name-price
v-if="walletStore.memeToken?.staked"
:name="tokenStore.getToken(walletStore.memeToken?.contractAddress)?.name" :name="tokenStore.getToken(walletStore.memeToken?.contractAddress)?.name"
:price="formatNumber(walletStore.memeToken?.staked)" :price="formatNumber(walletStore.memeToken?.staked / 10n ** tokenStore.memeToken.decimals)"
></token-name-price> ></token-name-price>
<token-logo img="/assets/img/token/bloodline.png" :alt="'bloodline-token'"></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> <token-name-price class="stake-reward" name="Extra Reward" price="+25%"></token-name-price>
@@ -79,7 +80,7 @@
v-model="tokenNumber" v-model="tokenNumber"
@close="stakeMenu = false" @close="stakeMenu = false"
:stake="stake" :stake="stake"
:amount="walletStore.memeToken?.balanceOf" :amount="balanceOf"
v-if="stakeMenu & !unstakeMenu" v-if="stakeMenu & !unstakeMenu"
> >
<template v-slot:body> <template v-slot:body>
@@ -103,7 +104,7 @@
</div> </div>
</template> </template>
<template v-slot:message-end> <template v-slot:message-end>
<div class="input-balance">Balance: {{ walletStore.memeToken?.balanceOf }}</div> <div class="input-balance">Balance: {{ formatNumber(balanceOf) }}</div>
</template> </template>
</stake-menu> </stake-menu>
<div class="unstake-menu" v-else-if="stakeMenu & unstakeMenu"> <div class="unstake-menu" v-else-if="stakeMenu & unstakeMenu">
@@ -133,6 +134,9 @@
<div class="connected-stake-first-round small-text text-center" v-if="cycleStore.currentCycle === 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. No $BLOOD on the market. Staking is activated after the first cycle is finished.
</div> </div>
<div class="connected-stake-first-round small-text text-center" v-else>
You can claim your stake next cycle
</div>
</slot> </slot>
<slot></slot> <slot></slot>
</div> </div>
@@ -172,6 +176,11 @@ const props = defineProps({
required: false, required: false,
default: null, default: null,
}, },
dense: {
type: Boolean,
required: false,
default: false,
},
}); });
const stakeMenu = ref(false); const stakeMenu = ref(false);
@@ -217,7 +226,7 @@ async function orderUnstake() {
}); });
console.log("rewardData", rewardData); console.log("rewardData", rewardData);
const outputClaim = Number(rewardData.topics[2]) / Math.pow(10, tokenStore.memeToken.decimals); const outputClaim = Number(rewardData.topics[2]) / 10n ** tokenStore.memeToken.decimals;
showSuccessToast( showSuccessToast(
formatNumber(outputClaim), formatNumber(outputClaim),
"Success!", "Success!",
@@ -234,6 +243,7 @@ async function orderUnstake() {
async function stakeToken() { async function stakeToken() {
try { try {
console.log("stakeToken");
state.value = 2; state.value = 2;
const hash = await rewardLockerStore.stakeBloodline(tokenNumber.value); const hash = await rewardLockerStore.stakeBloodline(tokenNumber.value);
state.value = 3; state.value = 3;
@@ -248,9 +258,9 @@ async function stakeToken() {
// //
console.log("rewardData", rewardData); console.log("rewardData", rewardData);
const outputClaim = Number(rewardData.topics[3]) / Math.pow(10, tokenStore.memeToken.decimals); const outputClaim = BigInt(rewardData.topics[3]) / 10n ** tokenStore.memeToken.decimals;
console.log("data", data); console.log("data", data);
state.value = 4; state.value = 0;
await walletStore.loadWalletData(); await walletStore.loadWalletData();
showSuccessToast( showSuccessToast(
formatNumber(outputClaim), formatNumber(outputClaim),
@@ -267,6 +277,14 @@ async function stakeToken() {
} }
} }
const balanceOf = computed(() => {
if (!walletStore.memeToken?.balanceOf) {
return 0n;
} else {
return walletStore.memeToken?.balanceOf / 10n ** tokenStore.memeToken.decimals;
}
});
const stateStake = computed(() => { const stateStake = computed(() => {
let returnState = 0; let returnState = 0;
if (state.value === 2) { if (state.value === 2) {
+14 -11
View File
@@ -2,10 +2,10 @@
<div class="stake-menu"> <div class="stake-menu">
<token-input :modelValue="props.modelValue" @input="emit('update:modelValue', Number($event.target.value))"> <token-input :modelValue="props.modelValue" @input="emit('update:modelValue', Number($event.target.value))">
<template v-slot:message> <template v-slot:message>
<div class="stake-adder-step bloodline-badge grey" @click="addTokensPercent(25)">25%</div> <div class="stake-adder-step bloodline-badge grey" @click="addTokensPercent(25n)">25%</div>
<div class="stake-adder-step bloodline-badge grey" @click="addTokensPercent(50)">50%</div> <div class="stake-adder-step bloodline-badge grey" @click="addTokensPercent(50n)">50%</div>
<div class="stake-adder-step bloodline-badge grey" @click="addTokensPercent(75)">75%</div> <div class="stake-adder-step bloodline-badge grey" @click="addTokensPercent(75n)">75%</div>
<div class="stake-adder-step bloodline-badge grey" @click="addTokensPercent(100)">100%</div> <div class="stake-adder-step bloodline-badge grey" @click="addTokensPercent(100n)">100%</div>
</template> </template>
<template v-slot:message-end> <template v-slot:message-end>
<slot name="message-end"> </slot> <slot name="message-end"> </slot>
@@ -39,23 +39,25 @@ const tokenStore = useTokenStore();
const props = defineProps({ const props = defineProps({
stake: Boolean, stake: Boolean,
modelValue: Number, modelValue: [Number, BigInt],
amount: Number, amount: [Number, BigInt],
}); });
const emit = defineEmits(["close", "update:modelValue"]); const emit = defineEmits(["close", "update:modelValue"]);
async function addTokensPercent(value) { async function addTokensPercent(value) {
console.log("value", value); console.log("value", value);
console.log(walletStore.memeToken.balanceOf); console.log("props.amount", props.amount);
let amount; let amount;
if (props.amount !== undefined || props.amount !== null) { if (props.amount !== undefined || props.amount !== null) {
amount = (props.amount * value) / 100; console.log("props.amount", props.amount);
amount = (props.amount * value) / 100n;
} else if (props.stake) { } else if (props.stake) {
amount = (walletStore.memeToken.balanceOf * value) / 100; amount = (walletStore.memeToken.balanceOf * value) / 100n;
} else { } else {
amount = (walletStore.memeToken.staked * value) / 100; amount = (walletStore.memeToken.staked * value) / 100n;
} }
console.log("amount", amount);
emit("update:modelValue", Number(amount)); emit("update:modelValue", Number(amount));
} }
@@ -78,11 +80,12 @@ async function unstakeBloodline() {
async function stakeBloodline() { async function stakeBloodline() {
try { try {
console.log("stakeBloodline");
const fromAddress = walletStore.address; const fromAddress = walletStore.address;
const spender = rewardLockerStore.config.contractAddress; const spender = rewardLockerStore.config.contractAddress;
const deadline = Date.now() + 20 * 60; const deadline = Date.now() + 20 * 60;
const decimals = tokenStore.getToken(walletStore.memeToken.contractAddress).decimals; const decimals = tokenStore.getToken(walletStore.memeToken.contractAddress).decimals;
const value = (tokenNumber.value * Math.pow(10, decimals)).toString(); const value = BigInt(tokenNumber.value) * 10n ** decimals;
const nonce = await tokenStore.memeToken.contract.read.nonces([fromAddress]); const nonce = await tokenStore.memeToken.contract.read.nonces([fromAddress]);
const { types, message, domain, primaryType } = createPermitObject( const { types, message, domain, primaryType } = createPermitObject(
fromAddress, fromAddress,
+33 -27
View File
@@ -23,30 +23,29 @@
<rewards-wrapper <rewards-wrapper
title="Sacrafice Reward" title="Sacrafice Reward"
coin="$BLOOD" coin="$BLOOD"
:amount="formatNumber(getCurrentCycleData?.rewards_sacrifice)" :amount="formatNumber(rewardsSacrifice)"
image="/assets/img/vampir.png" image="/assets/img/vampir.png"
/> />
<rewards-wrapper <rewards-wrapper
title="Staking Bonus" title="Staking Bonus"
coin="$BLOOD" coin="$BLOOD"
:amount="formatNumber(getCurrentCycleData?.rewards_staking)" :amount="formatNumber(rewardsStaking)"
info="max: 312m"
image="/assets/img/vampir.png" image="/assets/img/vampir.png"
/> />
<rewards-wrapper <rewards-wrapper
title="Clan Bonus" title="Clan Bonus"
coin="$BLOOD" coin="$BLOOD"
:amount="formatNumber(getCurrentCycleData?.rewards_clan)" :amount="formatNumber(rewardsClan)"
image="/assets/img/vampir.png" image="/assets/img/vampir.png"
/> />
</div> </div>
<div class="rewards-total-wrapper"> <div class="rewards-total-wrapper">
<div class="rewards-total-headline sub-header">Total Reward</div> <div class="rewards-total-headline sub-header">Total Reward</div>
<div class="rewards-total-inner bloodline-border bloodline-border--variant1"> <div
<token-name-price class="rewards-total-inner bloodline-border bloodline-border--variant1"
name="$BLOOD" :class="{ purple: rewardsTotal > 0 && activeCycle !== currentCycle }"
:price="formatNumber(getCurrentCycleData?.rewards_total)" >
></token-name-price> <token-name-price name="$BLOOD" :price="formatNumber(rewardsTotal)"></token-name-price>
<token-logo img="/assets/img/vampir.png" :alt="'vampire'"></token-logo> <token-logo img="/assets/img/vampir.png" :alt="'vampire'"></token-logo>
</div> </div>
</div> </div>
@@ -57,7 +56,7 @@
<template v-else-if="activeCycle === currentCycle"> <template v-else-if="activeCycle === currentCycle">
<button class="btn btn-immortal sub-header" @click="router.push({ name: 'home' })">Sacrifice</button> <button class="btn btn-immortal sub-header" @click="router.push({ name: 'home' })">Sacrifice</button>
</template> </template>
<template v-else-if="getCurrentCycleData?.rewards_total > 0"> <template v-else-if="rewardsTotal > 0">
<Transition name="smooth"> <Transition name="smooth">
<div class="stake-buttons" v-show="!stakeMenu"> <div class="stake-buttons" v-show="!stakeMenu">
<div class="btn btn-immortal" v-if="stateClaimedComp === 0" @click="claimRewards">Claim</div> <div class="btn btn-immortal" v-if="stateClaimedComp === 0" @click="claimRewards">Claim</div>
@@ -73,7 +72,7 @@
v-model="tokenNumber" v-model="tokenNumber"
@close="stakeMenu = false" @close="stakeMenu = false"
:stake="stake" :stake="stake"
:amount="getCurrentCycleData?.rewards_total" :amount="rewardsTotal"
v-if="stakeMenu" v-if="stakeMenu"
> >
<template v-slot:body> <template v-slot:body>
@@ -135,7 +134,8 @@ const tokenStore = useTokenStore();
const cycleStore = useCycleStore(); const cycleStore = useCycleStore();
const router = useRouter(); const router = useRouter();
const { activeCycle, currentCycle, getCurrentCycleData } = storeToRefs(cycleStore); const { activeCycle, currentCycle, getCurrentCycleData, rewardsSacrifice, rewardsStaking, rewardsClan, rewardsTotal } =
storeToRefs(cycleStore);
const stakeMenu = ref(false); const stakeMenu = ref(false);
const stake = ref(null); const stake = ref(null);
@@ -145,13 +145,16 @@ const stateStakeClaim = ref(0);
async function stakeAndClaim() { async function stakeAndClaim() {
try { try {
console.log("stakeAndClaim");
console.log(tokenNumber.value); console.log(tokenNumber.value);
console.log(getCurrentCycleData.value.rewards_total); console.log(rewardsTotal.value);
const coefficient = (10000 * tokenNumber.value) / getCurrentCycleData.value.rewards_total;
stateStakeClaim.value = 2; stateStakeClaim.value = 2;
console.log("hier1");
const coefficient = (10000n * BigInt(tokenNumber.value)) / rewardsTotal.value;
var hash = await rewardLockerStore.stakeAndClaimCycle(coefficient, cycleStore.activeCycle); var hash = await rewardLockerStore.stakeAndClaimCycle(coefficient, cycleStore.activeCycle);
console.log("hash"); console.log("hier2");
stateStakeClaim.value = 3; stateStakeClaim.value = 3;
console.log("hash");
const data = await waitForTransaction({ const data = await waitForTransaction({
hash: hash, hash: hash,
}); });
@@ -171,8 +174,9 @@ async function stakeAndClaim() {
}); });
// //
console.log("rewardData", rewardData); console.log("rewardData", rewardData);
const outputClaim = Number(rewardData?.topics[2]) / Math.pow(10, tokenStore.memeToken.decimals); console.log("stakeData", stakeData);
const outputStaked = Number(stakeData?.topics[3]) / Math.pow(10, tokenStore.memeToken.decimals); const outputClaim = BigInt(rewardData?.topics[2]) / 10n ** tokenStore.memeToken.decimals;
const outputStaked = BigInt(stakeData?.topics[3]) / 10n ** tokenStore.memeToken.decimals;
showSuccessToast( showSuccessToast(
formatNumber(outputClaim + outputStaked), formatNumber(outputClaim + outputStaked),
"Success!", "Success!",
@@ -181,13 +185,15 @@ async function stakeAndClaim() {
); );
tokenNumber.value = 0; tokenNumber.value = 0;
stakeMenu.value = false; stakeMenu.value = false;
await cycleStore.fillCycle(activeCycle.value, true);
await walletStore.loadWalletData(); await walletStore.loadWalletData();
} catch (error) { } catch (error) {
console.error("stakeAndClaim", error); console.error("stakeAndClaim", error);
} finally { } finally {
const walletStore = useWalletStoreV2(); const walletStore = useWalletStoreV2();
await walletStore.loadWalletData(); await walletStore.loadWalletData();
console.log("finally1");
await cycleStore.fillCycle(activeCycle.value, true);
console.log("finally2");
stateStakeClaim.value = 1; stateStakeClaim.value = 1;
} }
} }
@@ -220,7 +226,7 @@ async function claimRewards() {
// //
console.log("rewardData", rewardData); console.log("rewardData", rewardData);
const outputClaim = Number(rewardData.topics[2]) / Math.pow(10, tokenStore.memeToken.decimals); const outputClaim = BigInt(rewardData.topics[2]) / 10n ** tokenStore.memeToken.decimals;
showSuccessToast( showSuccessToast(
formatNumber(outputClaim), formatNumber(outputClaim),
"Success!", "Success!",
@@ -249,19 +255,19 @@ const stateClaimedComp = computed(() => {
const stateStakeClaimComp = computed(() => { const stateStakeClaimComp = computed(() => {
console.log("stateStakeClaimComp"); console.log("stateStakeClaimComp");
let returnState = 0; let returnState = 0;
if ( if (stateStakeClaim.value === 2) {
tokenNumber.value === null ||
tokenNumber.value === "" ||
tokenNumber.value === 0 ||
tokenNumber.value > walletStore.memeToken?.unclaimedRewards
) {
returnState = 0;
} else if (stateStakeClaim.value === 2) {
returnState = 2; returnState = 2;
} else if (stateStakeClaim.value === 3) { } else if (stateStakeClaim.value === 3) {
returnState = 3; returnState = 3;
} else if (tokenNumber.value !== null || tokenNumber.value !== "" || tokenNumber.value > 0) { } else if (tokenNumber.value !== null || tokenNumber.value !== "" || tokenNumber.value > 0) {
returnState = 1; returnState = 1;
} else if (
tokenNumber.value === null ||
tokenNumber.value === "" ||
tokenNumber.value === 0 ||
tokenNumber.value > walletStore.unclaimedRewards
) {
returnState = 0;
} }
return returnState; return returnState;
}); });
+4 -2
View File
@@ -14,7 +14,7 @@
</div> </div>
</div> </div>
<div class="right-side"> <div class="right-side">
<token-logo :img="props.logo" :alt="'vampir'"></token-logo> <token-logo img="/assets/img/vampir.png" :alt="'vampir'"></token-logo>
</div> </div>
</div> </div>
</div> </div>
@@ -62,10 +62,12 @@ const emit = defineEmits(["update:modelValue"]);
.stake-adder-step .stake-adder-step
padding: 4px 16px padding: 4px 16px
color: var(--black) color: var(--black)
font-size: 14px font-size: 12px
border-width: 1px border-width: 1px
border-color: transparent border-color: transparent
border-style: solid border-style: solid
@media (min-width: 992px)
font-size: 14px
&:hover,&:active, &:focus &:hover,&:active, &:focus
background-color: var(--grey-light) background-color: var(--grey-light)
cursor: pointer cursor: pointer
+1 -1
View File
@@ -7,7 +7,7 @@
<script setup> <script setup>
const props = defineProps({ const props = defineProps({
img: String, img: String,
alt: Number, alt: String,
size: { size: {
type: Number, type: Number,
default: 45, default: 45,
+15 -3
View File
@@ -17,13 +17,15 @@
</template> </template>
<script setup> <script setup>
import LoadingComponent from "@/components/LoadingComponent.vue"; import LoadingComponent from "@/components/LoadingComponent.vue";
import { getCurrentInstance, computed, watch } from "vue"; import { getCurrentInstance, computed, watch, inject } from "vue";
import { useTokenStore } from "@/stores/tokens"; import { useTokenStore } from "@/stores/tokens";
import { useSacrificeStore } from "@/stores/sacrifice"; import { useSacrificeStore } from "@/stores/sacrifice";
import CardComponent from "@/components/CardComponent.vue"; import CardComponent from "@/components/CardComponent.vue";
import { useToast } from "vue-toastification"; import { useToast } from "vue-toastification";
const emit = defineEmits(["sacrificed"]);
const props = defineProps({ const props = defineProps({
value: String, value: String,
header: String, header: String,
@@ -37,6 +39,8 @@ const sacrificeStore = useSacrificeStore();
const instance = getCurrentInstance(); const instance = getCurrentInstance();
const id = instance.attrs["toast-id"]; const id = instance.attrs["toast-id"];
const splashBlood = inject("splashBlood");
function closeToast() { function closeToast() {
toast.dismiss(id); toast.dismiss(id);
} }
@@ -64,8 +68,16 @@ const stateComputed = computed(() => {
}); });
async function sacrificeClick() { async function sacrificeClick() {
await sacrificeStore.sacrificeToken(sacrificeStore.sacrificeNumber, tokenStore.activeToken); try {
closeToast(); var result = await sacrificeStore.sacrificeToken(sacrificeStore.sacrificeNumber, tokenStore.activeToken);
if (result) {
emit("sacrificed");
}
} catch (error) {
console.error("error", error);
} finally {
closeToast();
}
} }
</script> </script>
<style lang="sass"> <style lang="sass">
+9
View File
@@ -29,6 +29,15 @@ export function formatNumber(number) {
return formattedWithOptions; return formattedWithOptions;
} }
// input type bigint
export function formatBigIntDivision(nominator, denominator) {
const integer = (nominator / denominator).toString();
// pick how much digits after point to show
const fraction = (nominator % denominator).toString().substring(0,10);
// output type string
return integer + '.' + fraction;
}
export function getAddressShortName(address) { export function getAddressShortName(address) {
// const address = "0x66422602B2f4885c57EE794174f98d9E4DDBBBC6"; // const address = "0x66422602B2f4885c57EE794174f98d9E4DDBBBC6";
const addressBegin = address.substring(0, 6); const addressBegin = address.substring(0, 6);
+22 -6
View File
@@ -38,7 +38,7 @@ import { library } from '@fortawesome/fontawesome-svg-core'
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome' import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
/* import specific icons */ /* import specific icons */
import { faArrowDown, faArrowRight, faSpinner, faPlus, faCaretLeft, faCaretRight, faBars, faAnglesRight, faChevronDown, faChevronUp, faArrowRightToBracket, faArrowRightFromBracket, faDroplet, faMoon, faPerson } from "@fortawesome/free-solid-svg-icons"; import { faArrowDown, faArrowRight, faSpinner, faPlus, faCaretLeft, faCaretRight, faBars, faAnglesRight, faChevronDown, faChevronUp, faArrowRightToBracket, faArrowRightFromBracket, faDroplet, faMoon, faPerson, faWallet } from "@fortawesome/free-solid-svg-icons";
import { faDiscord, faTwitter, faTelegram } from "@fortawesome/free-brands-svg-icons"; import { faDiscord, faTwitter, faTelegram } from "@fortawesome/free-brands-svg-icons";
@@ -65,9 +65,20 @@ library.add(
faChevronUp, faChevronUp,
faDroplet, faDroplet,
faMoon, faMoon,
faPerson faPerson,
faWallet
); );
var logging = localStorage.getItem("LOGGING");
if (logging === "true") {
} else {
if (!window.console) window.console = {};
var methods = ["log", "debug", "warn", "info"];
for (let i = 0; i < methods.length; i++) {
console[methods[i]] = function () {};
}
}
const app = createApp(App) const app = createApp(App)
@@ -80,6 +91,7 @@ app.use(pinia);
app.use(Toast, { app.use(Toast, {
transition: "Vue-Toastification__fade", transition: "Vue-Toastification__fade",
containerClassName: "bloodline-toast-container",
}); });
@@ -109,7 +121,10 @@ try {
}, },
}), }),
new MetaMaskConnector({ chains }), new MetaMaskConnector({ chains }),
// new InjectedConnector({ chains }), new InjectedConnector({
chains,
getProvider: () => (typeof window !== "undefined" ? window.myInjectedWallet : undefined),
}),
new WalletConnectConnector({ new WalletConnectConnector({
chains, chains,
options: { options: {
@@ -150,9 +165,9 @@ try {
}, },
async (log) => { async (log) => {
console.log("CycleCompleted", log); console.log("CycleCompleted", log);
await cycleStore.fillCycle(cycleStore.currentCycle); await cycleStore.fillCycle(cycleStore.currentCycle, true);
cycleStore.currentCycle++; cycleStore.currentCycle++;
await cycleStore.fillCycle(cycleStore.currentCycle); await cycleStore.fillCycle(cycleStore.currentCycle, true);
} }
); );
@@ -179,7 +194,8 @@ try {
await tokenStore.initV2(); await tokenStore.initV2();
await rewardLockerStore.init(); await rewardLockerStore.init();
await walletStore.loadWalletData(); await walletStore.loadWalletData();
await cycleStore.fillCycle(cycleStore.currentCycle); // console.log("cycleStore.currentCycle", cycleStore.currentCycle);
// await cycleStore.fillCycle(cycleStore.currentCycle);
await uniswapStore.init(); await uniswapStore.init();
} else { } else {
walletStore.address = null; walletStore.address = null;
+94 -61
View File
@@ -12,9 +12,9 @@ export const useCycleStore = defineStore("cycles", {
activeCycle: null, activeCycle: null,
currentCycle: null, currentCycle: null,
}), }),
getters: { getters: {
//cycle winner is the token who reached the goal //cycle winner is the token who reached the goal
//todo winner is now in the cycle object, no reason for that function anymore //todo winner is now in the cycle object, no reason for that function anymore
getCycleWinner() { getCycleWinner() {
const goal = this.getCurrentCycleData?.goal; const goal = this.getCurrentCycleData?.goal;
if (!goal) { if (!goal) {
@@ -30,9 +30,37 @@ export const useCycleStore = defineStore("cycles", {
getCurrentCycleData() { getCurrentCycleData() {
return this.cycles[this.activeCycle]; return this.cycles[this.activeCycle];
}, },
rewardsSacrifice() {
const tokenStore = useTokenStore();
if (!this.cycles[this.activeCycle]?.rewards_sacrifice) {
return 0n;
}
return this.cycles[this.activeCycle]?.rewards_sacrifice / 10n ** tokenStore.memeToken.decimals;
},
rewardsStaking() {
const tokenStore = useTokenStore();
if (!this.cycles[this.activeCycle]?.rewards_staking) {
return 0n;
}
return this.cycles[this.activeCycle]?.rewards_staking / 10n ** tokenStore.memeToken.decimals;
},
rewardsClan() {
const tokenStore = useTokenStore();
if (!this.cycles[this.activeCycle]?.rewards_clan) {
return 0n;
}
return this.cycles[this.activeCycle]?.rewards_clan / 10n ** tokenStore.memeToken.decimals;
},
rewardsTotal() {
const tokenStore = useTokenStore();
if (!this.cycles[this.activeCycle]?.rewards_total) {
return 0n;
}
return this.cycles[this.activeCycle]?.rewards_total / 10n ** tokenStore.memeToken.decimals;
},
}, },
actions: { actions: {
//todo check if still needed //todo check if still needed
// async loadRewardsCycles() { // async loadRewardsCycles() {
// const walletStore = useWalletStoreV2(); // const walletStore = useWalletStoreV2();
// const rewardLockerStore = useRewardLockerStore(); // const rewardLockerStore = useRewardLockerStore();
@@ -56,31 +84,34 @@ export const useCycleStore = defineStore("cycles", {
// const element = data[index]; // const element = data[index];
// if (!this.cycles[index]) { // if (!this.cycles[index]) {
// this.cycles[index] = {}; // this.cycles[index] = {};
// } // }
// } // }
// }, // },
//todo check if needed, or use fillcycle //todo check if needed, or use fillcycle
async updateCurrentCycle(sacrificedToken) { async updateCurrentCycle(sacrificedToken) {
console.log("updateCurrentCycle"); console.log("updateCurrentCycle");
const tokenStore = useTokenStore();
const memeBurnerStore = useMemeburnerStore(); const memeBurnerStore = useMemeburnerStore();
var data = await memeBurnerStore.getSacrificedCycle(this.currentCycle); const rewardLockerStore = useRewardLockerStore();
console.log("this.currentCycle", this.currentCycle); // TODO: Could be combined in one multicall and could be simplified to request data only for sacrificedToken
console.log("this.cycles", this.cycles); var data = await memeBurnerStore.getSacrificedCycle(this.currentCycle);
var tokenIndex = this.cycles[this.currentCycle]?.token.findIndex( var tokenTotalSacrificed = await rewardLockerStore.getTotalSacrificeRewardsForAllToken(this.currentCycle);
(tokenData) => tokenData.contractAddress === sacrificedToken console.log("this.currentCycle", this.currentCycle);
); console.log("this.cycles", this.cycles);
console.log("tokenIndex", tokenIndex); if (this.cycles[this.currentCycle]) {
const token = tokenStore.getToken(sacrificedToken); var tokenIndex = this.cycles[this.currentCycle].token.findIndex(
this.cycles[this.currentCycle].token[tokenIndex].amount = (tokenData) => tokenData.contractAddress === sacrificedToken
Number(data[tokenIndex].result[1]) / Math.pow(10, token.decimals) );
}, this.cycles[this.currentCycle].token[tokenIndex].amount = data[tokenIndex].result[1];
/** // was missed update totalSacrificeRewards for sacrificedToken
* main function to fill a round, will not be filled when already loaded this.cycles[this.currentCycle].token[tokenIndex].amountInBLD = tokenTotalSacrificed[tokenIndex].result;
* you can use the refillcycle to overwrite information, because if you claim or stake the values will change }
*/ },
/**
* main function to fill a round, will not be filled when already loaded
* you can use the refillcycle to overwrite information, because if you claim or stake the values will change
*/
async fillCycle(cycleNumber, refillCycle = false) { async fillCycle(cycleNumber, refillCycle = false) {
console.log("fillCycle"); console.log("fillCycle", cycleNumber);
const memeBurnerStore = useMemeburnerStore(); const memeBurnerStore = useMemeburnerStore();
const tokenStore = useTokenStore(); const tokenStore = useTokenStore();
const walletStore = useWalletStoreV2(); const walletStore = useWalletStoreV2();
@@ -97,78 +128,79 @@ export const useCycleStore = defineStore("cycles", {
rewardData = await rewardLockerStore.getRewardsForAllToken(cycleNumber); rewardData = await rewardLockerStore.getRewardsForAllToken(cycleNumber);
} }
console.log("hier");
//getTotalSacrificeRewardsForToken multicall for all tokens //getTotalSacrificeRewardsForToken multicall for all tokens
const tokenTotalSacrificed = await rewardLockerStore.getTotalSacrificeRewardsForAllToken(cycleNumber); const tokenTotalSacrificed = await rewardLockerStore.getTotalSacrificeRewardsForAllToken(cycleNumber);
console.log("hier1");
var goal = await memeBurnerStore.getGoal(cycleNumber); var goal = await memeBurnerStore.getGoal(cycleNumber);
console.log("hier123");
var tokenArray = []; var tokenArray = [];
var rewards_clan = 0; var rewards_clan = 0n;
var rewards_sacrifice = 0; var rewards_sacrifice = 0n;
var rewards_staking = 0; var rewards_staking = 0n;
console.log("hier123");
for (let index = 0; index < data.length; index++) { for (let index = 0; index < data.length; index++) {
var tokenData = {}; var tokenData = {};
const token = tokenStore.token[index]; const token = tokenStore.token[index];
//why no multicall? todo //why no multicall? todo
var coefficent = await rewardLockerStore.getSacrificedTokenCoefficient( var coefficent = await rewardLockerStore.getSacrificedTokenCoefficient(
cycleNumber, cycleNumber,
token.contractAddress token.contractAddress
); );
console.log("coefficent", coefficent); console.log("coefficent", coefficent);
tokenData.name = token.name; tokenData.name = token.name;
tokenData.contractAddress = token.contractAddress; tokenData.contractAddress = token.contractAddress;
tokenData.vamplogo = token.vamp.logo; tokenData.vamplogo = token.vamp.logo;
tokenData.vampwinner = token.vamp.winner; tokenData.vampwinner = token.vamp.winner;
tokenData.vampwinner2 = token.vamp.winner2; tokenData.vampwinner2 = token.vamp.winner2;
tokenData.vampname = token.vamp.name; tokenData.vampname = token.vamp.name;
tokenData.amount = Number(data[index].result[1]) / Math.pow(10, token.decimals); tokenData.amount = data[index].result[1];
tokenData.amountInBLD = Number(tokenTotalSacrificed[index].result) / Math.pow(10, token.decimals); tokenData.amountInBLD = tokenTotalSacrificed[index].result;
if (walletStore.connected) { if (walletStore.connected) {
//if user is connected fill user specific data for the token //if user is connected fill user specific data for the token
const sacrificeClanReward = Number(rewardData[index].result[1]); const sacrificeClanReward = rewardData[index].result[1];
let clanwin = 0; let clanwin = 0n;
if (cycleNumber !== this.currentCycle) { if (cycleNumber !== this.currentCycle) {
clanwin = (Number(coefficent) / 10000 - 1) * sacrificeClanReward; // previous version would not work due to missing remainder
clanwin = (sacrificeClanReward * coefficent / 10000n) - sacrificeClanReward;
console.log("clanwin", clanwin); console.log("clanwin", clanwin);
} }
const sacrificeRewards = Number(sacrificeClanReward); const sacrificeRewards = sacrificeClanReward;
tokenData.rewards_ges = Number( tokenData.rewards_ges = rewardData[index].result[1] + rewardData[index].result[0];
rewardData[index].result[1] / BigInt(Math.pow(10, token.decimals)) +
rewardData[index].result[0] / BigInt(Math.pow(10, token.decimals))
);
tokenData.rewards_clan = clanwin / Math.pow(10, token.decimals); tokenData.rewards_clan = clanwin;
tokenData.rewards_staking = Number( tokenData.rewards_staking = rewardData[index].result[0];
rewardData[index].result[0] / BigInt(Math.pow(10, token.decimals)) tokenData.rewards_sacrifice = sacrificeRewards;
);
tokenData.rewards_sacrifice = sacrificeRewards / Math.pow(10, token.decimals);
console.log("rewards_clan", rewards_clan);
console.log("tokenData.rewards_clan", tokenData.rewards_clan);
console.log("tokenData.rewards_sacrifice", tokenData.rewards_sacrifice);
rewards_clan = rewards_clan + tokenData.rewards_clan; rewards_clan = rewards_clan + tokenData.rewards_clan;
rewards_sacrifice = rewards_sacrifice + tokenData.rewards_sacrifice; rewards_sacrifice = rewards_sacrifice + tokenData.rewards_sacrifice;
rewards_staking = rewards_staking + tokenData.rewards_staking; rewards_staking = rewards_staking + tokenData.rewards_staking;
} }
tokenArray.push(tokenData); tokenArray.push(tokenData);
} }
const goalDecimal = Number(goal[0]) / Math.pow(10, tokenStore.memeToken.decimals); const goalDecimal = goal[0];
const winner = tokenArray.find((token) => token.amount === goalDecimal); const winner = tokenArray.find((token) => token.amount === goalDecimal);
const goalInBLD = await memeBurnerStore.getGoalInBLOOD(cycleNumber); const goalInBLD = await memeBurnerStore.getGoalInBLOOD(cycleNumber);
//replace vamplogo cause it will automatically change the token for the cycle view (new design) //replace vamplogo cause it will automatically change the token for the cycle view (new design)
if (winner) { if (winner) {
winner.vamplogo = winner.vampwinner; winner.vamplogo = winner.vampwinner;
} }
this.cycles[cycleNumber] = { this.cycles[cycleNumber] = {
goal: Number(goal[0]) / Math.pow(10, tokenStore.memeToken.decimals), goal: goal[0],
goalInBLD: Number(goalInBLD / BigInt(Math.pow(10, tokenStore.memeToken.decimals))), goalInBLD: goalInBLD,
expirationTimestamp: Number(goal[2]), expirationTimestamp: goal[2],
rewards_clan: Number(rewards_clan), rewards_clan: rewards_clan,
rewards_staking: Number(rewards_staking), rewards_staking: rewards_staking,
rewards_sacrifice: Number(rewards_sacrifice), rewards_sacrifice: rewards_sacrifice,
rewards_total: Number(rewards_clan) + Number(rewards_sacrifice) + Number(rewards_staking), rewards_total: rewards_clan + rewards_sacrifice + rewards_staking,
token: tokenArray, token: tokenArray,
connected: walletStore.connected, connected: walletStore.connected,
winner: winner, winner: winner,
@@ -181,10 +213,11 @@ export const useCycleStore = defineStore("cycles", {
async getFinshedCycleNumbers() { async getFinshedCycleNumbers() {
const array = []; const array = [];
const rewardLockerStore = useRewardLockerStore(); const rewardLockerStore = useRewardLockerStore();
const lastCompletedCycle = await rewardLockerStore.lastCompletedCycle(); const lastCompletedCycle = await rewardLockerStore.lastCompletedCycle();
// Question: cycle 0 doesn't exist, does it make sense to start from index 1?
for (let index = 0; index <= Number(lastCompletedCycle); index++) { for (let index = 0; index <= Number(lastCompletedCycle); index++) {
array.push(index); array.push(index);
} }
return array; return array;
}, },
}, },
+5 -5
View File
@@ -40,7 +40,8 @@ export const useMemeburnerStore = defineStore("memeburner", {
async getCurrentCycle() { async getCurrentCycle() {
return await this.contract.read.currentCycle(); return await this.contract.read.currentCycle();
}, },
async getGoal(cycleNumber) { async getGoal(cycleNumber) {
console.log("hier123", cycleNumber);
return await this.contract.read.cycles([cycleNumber]); return await this.contract.read.cycles([cycleNumber]);
}, },
//returns participated, amount achieved //returns participated, amount achieved
@@ -79,12 +80,11 @@ export const useMemeburnerStore = defineStore("memeburner", {
return; return;
} }
this.loading = true; this.loading = true;
// TODO: store all integer values as one type: BigInt
const amountDecimal = BigInt(amount) * 10n ** BigInt(tokenStore.activeToken.decimals);
var hash = await this.contract.write.sacrificeMeme([ var hash = await this.contract.write.sacrificeMeme([
tokenStore.activeToken.contractAddress, tokenStore.activeToken.contractAddress,
amountDecimal.toString(), amount,
minETH.toString() minETH
]); ]);
return hash; return hash;
} catch (error) { } catch (error) {
+13 -11
View File
@@ -32,7 +32,8 @@ export const useRewardLockerStore = defineStore("rewardlocker", {
*/ */
async getRewards(walletAddress, cycleNumber, tokenAddress) { async getRewards(walletAddress, cycleNumber, tokenAddress) {
try { try {
return await this.contract.read.rewards([walletAddress, cycleNumber, tokenAddress]); // rewards function doesn't exist, getRewards instead
return await this.contract.read.getRewards([walletAddress, cycleNumber, tokenAddress]);
} catch (error) { } catch (error) {
console.error("getRewards", error); console.error("getRewards", error);
} }
@@ -50,9 +51,9 @@ export const useRewardLockerStore = defineStore("rewardlocker", {
functionName: "getRewards", functionName: "getRewards",
args: [walletStore.address, cycleNumber, token.contractAddress], args: [walletStore.address, cycleNumber, token.contractAddress],
}); });
} }
const data = await multicall({ const data = await multicall({
contracts, contracts,
}); });
return data; return data;
}, },
@@ -117,6 +118,10 @@ export const useRewardLockerStore = defineStore("rewardlocker", {
async getStaked(address) { async getStaked(address) {
return await this.contract.read.staked([address]); return await this.contract.read.staked([address]);
}, },
async getUnstakeOrdered(address, cycleNumber) {
// returns unstake amount of BDL ordered and ready to be unstaked in a cycleNumber
return await this.contract.read.unstakeOrdered([cycleNumber,address]);
},
async orderUnstake() { async orderUnstake() {
return await this.contract.write.orderUnstake(); return await this.contract.write.orderUnstake();
}, },
@@ -130,9 +135,10 @@ export const useRewardLockerStore = defineStore("rewardlocker", {
const fromAddress = walletStore.address; const fromAddress = walletStore.address;
const spender = this.config.contractAddress; const spender = this.config.contractAddress;
const deadline = Date.now() + 20 * 60; // timestamp is denominated in seconds
const deadline = BigInt(Date.now()) / 1000n + 1200n;
const decimals = tokenStore.getToken(walletStore.memeToken.contractAddress).decimals; const decimals = tokenStore.getToken(walletStore.memeToken.contractAddress).decimals;
const value = BigInt(tokenNumber * Math.pow(10, decimals)); const value = BigInt(tokenNumber) * 10n ** decimals;
const nonce = await tokenStore.memeToken.contract.read.nonces([fromAddress]); const nonce = await tokenStore.memeToken.contract.read.nonces([fromAddress]);
console.log("nonce", nonce); console.log("nonce", nonce);
const { types, message, domain, primaryType } = createPermitObject( const { types, message, domain, primaryType } = createPermitObject(
@@ -160,19 +166,15 @@ export const useRewardLockerStore = defineStore("rewardlocker", {
const tokenStore = useTokenStore(); const tokenStore = useTokenStore();
const addresses = tokenStore.sacrificeToken.map((obj) => obj.contractAddress); const addresses = tokenStore.sacrificeToken.map((obj) => obj.contractAddress);
const hash = await this.contract.write.stakeAndClaim([stakeCoefficient, [cycle], addresses]); const hash = await this.contract.write.stakeAndClaim([stakeCoefficient, [cycle], addresses]);
const data = await waitForTransaction({
hash: hash,
});
return hash; return hash;
}, },
async stakeAndClaimAllCycles(stakeCoefficient) { async stakeAndClaimAllCycles(stakeCoefficient) {
console.log("stakeAndClaimAllCycles"); console.log("stakeAndClaimAllCycles", stakeCoefficient);
const tokenStore = useTokenStore(); const tokenStore = useTokenStore();
const cycleStore = useCycleStore(); const cycleStore = useCycleStore();
const cycles = await cycleStore.getFinshedCycleNumbers(); const cycles = await cycleStore.getFinshedCycleNumbers();
const addresses = tokenStore.sacrificeToken.map((obj) => obj.contractAddress); const addresses = tokenStore.sacrificeToken.map((obj) => obj.contractAddress);
var stakeCoefficientInt = Math.round(stakeCoefficient); const hash = await this.contract.write.stakeAndClaim([stakeCoefficient, cycles, addresses]);
const hash = await this.contract.write.stakeAndClaim([stakeCoefficientInt, cycles, addresses]);
return hash; return hash;
}, },
}, },
+43 -37
View File
@@ -9,7 +9,7 @@ import { useRewardLockerStore } from "@/stores/rewardlocker";
import { useTokenStore } from "@/stores/tokens"; import { useTokenStore } from "@/stores/tokens";
import { waitForTransaction, readContract, watchBlockNumber, multicall } from "@wagmi/core"; import { waitForTransaction, readContract, watchBlockNumber, multicall } from "@wagmi/core";
import { showSuccessToast } from "@/helper/toast.js"; import { showSuccessToast } from "@/helper/toast.js";
import { formatNumber } from "@/helper/helper.js"; import { formatNumber, formatBigIntDivision } from "@/helper/helper.js";
export const useSacrificeStore = defineStore("sacrifice", { export const useSacrificeStore = defineStore("sacrifice", {
state: () => ({ state: () => ({
@@ -19,7 +19,8 @@ export const useSacrificeStore = defineStore("sacrifice", {
getters: {}, getters: {},
actions: { actions: {
async sacrificeToken(amount, token) { async sacrificeToken(amount, token) {
console.log("sacrificeToken", {amount, token}); console.log("sacrificeToken", { amount, token });
const memeburnerStore = useMemeburnerStore(); const memeburnerStore = useMemeburnerStore();
const walletStore = useWalletStoreV2(); const walletStore = useWalletStoreV2();
const tokenStore = useTokenStore(); const tokenStore = useTokenStore();
@@ -27,8 +28,10 @@ export const useSacrificeStore = defineStore("sacrifice", {
try { try {
this.sacrificeState = 2; this.sacrificeState = 2;
console.log("hier");
const getRewards = await this.getRewardsFor(amount, token); const getRewards = await this.getRewardsFor(amount, token);
console.log("hier1");
console.log("getRewards", getRewards); console.log("getRewards", getRewards);
let hash = null; let hash = null;
if (getRewards.variant === "sacrifice") { if (getRewards.variant === "sacrifice") {
@@ -55,27 +58,31 @@ export const useSacrificeStore = defineStore("sacrifice", {
// }); // });
var rewardData = data.logs.filter((logObject) => { var rewardData = data.logs.filter((logObject) => {
return logObject.topics.filter( return logObject.topics.find(
(topic) => topic === "0x5e60ccd3c81486143d815dce24867a494d7fee585a0a44282cf479b19a5186ee" (topic) => topic === "0x5e60ccd3c81486143d815dce24867a494d7fee585a0a44282cf479b19a5186ee"
); );
}); });
console.log("rewardData", rewardData); console.log("rewardData", rewardData);
const outputSacrifice = rewardData.reduce((x, y) => { //output
return x + Number(y.data) / Math.pow(10, token.decimals); let outputSacrifice = rewardData.reduce((x, y) => {
}, 0); return x + BigInt(y.data);
}, 0n);
outputSacrifice = formatBigIntDivision(outputSacrifice, 10n ** token.decimals);
console.log("outputSacrifice", outputSacrifice); console.log("outputSacrifice", outputSacrifice);
// const outputSacrifice = Number(rewardData.data) / Math.pow(10, token.decimals);
token.allowance = await tokenStore.allowance(); token.allowance = await tokenStore.allowance();
this.sacrificeState = 4; this.sacrificeState = 4;
showSuccessToast( showSuccessToast(
formatNumber(outputSacrifice), outputSacrifice,
"Success!", "Success!",
"You turned your meme into:", "You turned your meme into:",
"You can claim once the current cycle is finished and your clan bonus was calculated." "You can claim once the current cycle is finished and your clan bonus was calculated."
); );
await walletStore.loadWalletData(); await walletStore.loadWalletData();
console.log("cycleStore.currentCycle", cycleStore.currentCycle);
await cycleStore.fillCycle(cycleStore.currentCycle, true); await cycleStore.fillCycle(cycleStore.currentCycle, true);
return; return true;
} catch (error) { } catch (error) {
//we should show the user an issue //we should show the user an issue
throw new Error(error); throw new Error(error);
@@ -83,31 +90,30 @@ export const useSacrificeStore = defineStore("sacrifice", {
this.sacrificeState = 0; this.sacrificeState = 0;
} }
}, },
async getRewardsFor(value, token) { async getRewardsFor(amount, token) {
console.log("getRewardsFor", {value, token}); console.log("getRewardsFor", {amount, token});
const memeburnerStore = useMemeburnerStore(); const memeburnerStore = useMemeburnerStore();
const uniswapStore = useUniswapStore(); const uniswapStore = useUniswapStore();
const walletStore = useWalletStoreV2(); const walletStore = useWalletStoreV2();
const rewardLockerStore = useRewardLockerStore(); const rewardLockerStore = useRewardLockerStore();
// what is value here? i thought amount and value are same
const amountDecimal = BigInt(value) * 10n ** BigInt(token.decimals == undefined ? 18n : token.decimals);
let output = 0; let output = 0;
const amountETHBase = await memeburnerStore.getAmountETHBase(amountDecimal);
// take 99.5% of amount ETH got for selling meme, 0.5% allowed slippage
const minETH = amountETHBase[1] * 995n / 1000n;
let minBLOOD; let minBLOOD;
try { try {
if (!value || isNaN(value)) {
if (!amount) {
this.sacrificeState = 0; this.sacrificeState = 0;
return output; return output;
} }
const amountETHBase = await memeburnerStore.getAmountETHBase(amount);
// take 99.5% of amount ETH got for selling meme, 0.5% allowed slippage
const minETH = (amountETHBase[1] * 995n) / 1000n;
const rewardsForResult = await memeburnerStore.getRewardFor(amountDecimal); const rewardsForResult = await memeburnerStore.getRewardFor(amount);
const rewardsForResultSum = rewardsForResult[0] + rewardsForResult[1]; const rewardsForResultSum = rewardsForResult[0] + rewardsForResult[1];
// quote blood amount against ETH base amount // quote blood amount against ETH base amount
var quoteRewards = await uniswapStore.quoteExactInputSingle(amountDecimal, amountETHBase[0]); var quoteRewards = await uniswapStore.quoteExactInputSingle(amount, amountETHBase[0]);
let variant = "sacrifice"; let variant = "sacrifice";
if (quoteRewards.result) { if (quoteRewards.result) {
@@ -135,9 +141,8 @@ export const useSacrificeStore = defineStore("sacrifice", {
output = rewardsForResultSum; output = rewardsForResultSum;
} }
console.log("variant", variant); console.log("variant", variant);
console.log("amountDecimal", amountDecimal); console.log("amount", amount);
// TODO: when token.allowance become BigInt with decimals, value must be amountDecimal if (!walletStore.connected || (walletStore.connected && token.allowance < amount)) {
if (!walletStore.connected || (walletStore.connected && token.allowance < value)) {
/** /**
* case 1 * case 1
* user is not logged in or Allowance is less than Input, then I show getRewardsForSacrifice Value * user is not logged in or Allowance is less than Input, then I show getRewardsForSacrifice Value
@@ -163,7 +168,7 @@ export const useSacrificeStore = defineStore("sacrifice", {
address: memeburnerStore.contract.address, address: memeburnerStore.contract.address,
abi: memeburnerStore.contract.abi, abi: memeburnerStore.contract.abi,
functionName: "sacrificeMeme", functionName: "sacrificeMeme",
args: [token.contractAddress, amountDecimal.toString(), minETH.toString()], args: [token.contractAddress, amount.toString(), minETH.toString()],
account: walletStore.address, account: walletStore.address,
}); });
@@ -171,7 +176,7 @@ export const useSacrificeStore = defineStore("sacrifice", {
address: memeburnerStore.contract.address, address: memeburnerStore.contract.address,
abi: memeburnerStore.contract.abi, abi: memeburnerStore.contract.abi,
functionName: "sacrificeMemeAndBuyBLOOD", functionName: "sacrificeMemeAndBuyBLOOD",
args: [token.contractAddress, amountDecimal.toString(), minBLOOD.toString()], args: [token.contractAddress, amount.toString(), minBLOOD.toString()],
account: walletStore.address, account: walletStore.address,
}); });
@@ -187,14 +192,15 @@ export const useSacrificeStore = defineStore("sacrifice", {
} }
//potential staking rewards //potential staking rewards
let stakingRewardsNumber = 0; let stakingRewardsNumber = 0;
if (output > 0n && walletStore.connected) { if (output > 0 && walletStore.connected) {
const stakingReward = await rewardLockerStore.getStakeRewardForSacrificeReward( const stakingReward = await rewardLockerStore.getStakeRewardForSacrificeReward(
token.contractAddress, token.contractAddress,
output output
); );
stakingRewardsNumber = (Number(stakingReward / 10n ** BigInt(token.decimals))).toFixed(2); stakingRewardsNumber = stakingReward / 10n ** token.decimals
} }
return { output: output, variant: variant, minETH: minETH, minBLOOD: minBLOOD, staking: stakingRewardsNumber }; const outputNumber = output / 10n ** BigInt(token.decimals);
return { output: outputNumber, variant: variant, minETH: minETH, minBLOOD: minBLOOD, staking: stakingRewardsNumber };
} catch (error) { } catch (error) {
console.error("getRewardsFor", error); console.error("getRewardsFor", error);
} }
+56 -15
View File
@@ -12,8 +12,8 @@ import { multicall, getContract, fetchToken, getWalletClient, waitForTransaction
export const useTokenStore = defineStore("token", { export const useTokenStore = defineStore("token", {
state: () => ({ state: () => ({
//some static data for the coin //some static data for the coin
token: [ token: [
{ {
name: "$PEPE", name: "$PEPE",
@@ -28,6 +28,20 @@ export const useTokenStore = defineStore("token", {
backgroundColor: "#4b8501", backgroundColor: "#4b8501",
abi: Meme1Json.abi, abi: Meme1Json.abi,
contractAddress: Meme1Json.contractAddress, contractAddress: Meme1Json.contractAddress,
addSteps: [
{
amount: 10000000000000000000000000n,
name: "10m",
},
{
amount: 100000000000000000000000000n,
name: "100m",
},
{
amount: 1000000000000000000000000000n,
name: "1b",
},
],
}, },
{ {
name: "$SHIB", name: "$SHIB",
@@ -41,6 +55,20 @@ export const useTokenStore = defineStore("token", {
}, },
abi: Meme2Json.abi, abi: Meme2Json.abi,
contractAddress: Meme2Json.contractAddress, contractAddress: Meme2Json.contractAddress,
addSteps: [
{
amount: 1000000000000000000000000n,
name: "10m",
},
{
amount: 10000000000000000000000000n,
name: "100m",
},
{
amount: 100000000000000000000000000n,
name: "1b",
},
],
}, },
{ {
name: "$ELON", name: "$ELON",
@@ -54,6 +82,20 @@ export const useTokenStore = defineStore("token", {
}, },
abi: Meme3Json.abi, abi: Meme3Json.abi,
contractAddress: Meme3Json.contractAddress, contractAddress: Meme3Json.contractAddress,
addSteps: [
{
amount: 10000000000000000000000000n,
name: "10m",
},
{
amount: 100000000000000000000000000n,
name: "100m",
},
{
amount: 1000000000000000000000000000n,
name: "1b",
},
],
}, },
// { // {
// name: "$BITCOIN", // name: "$BITCOIN",
@@ -62,8 +104,8 @@ export const useTokenStore = defineStore("token", {
// vamp: { // vamp: {
// logo: "/assets/img/token/bitcoin.png", // logo: "/assets/img/token/bitcoin.png",
// name: "$ELON Vamp Token", // name: "$ELON Vamp Token",
// winner: "/assets/img/token/bitcoinwinner.png" // winner: "/assets/img/token/bitcoinwinner.png"
// winner2: "/assets/img/token/bitcoinwinnerborder.png" // winner2: "/assets/img/token/bitcoinwinnerborder.png"
// }, // },
// abi: Meme4Json.abi, // abi: Meme4Json.abi,
// contractAddress: Meme4Json.contractAddress, // contractAddress: Meme4Json.contractAddress,
@@ -79,7 +121,8 @@ export const useTokenStore = defineStore("token", {
// abi: Meme5Json.abi, // abi: Meme5Json.abi,
// contractAddress: Meme5Json.contractAddress, // contractAddress: Meme5Json.contractAddress,
// }, // },
{ {
name: "$BLOOD",
abi: BloodlineJson.abi, abi: BloodlineJson.abi,
contractAddress: BloodlineJson.contractAddress, contractAddress: BloodlineJson.contractAddress,
logo: "/assets/img/token/bloodline.png", logo: "/assets/img/token/bloodline.png",
@@ -119,21 +162,21 @@ export const useTokenStore = defineStore("token", {
}); });
contracts.push({ ...token.contract, functionName: "decimals" }); contracts.push({ ...token.contract, functionName: "decimals" });
contracts.push({ ...token.contract, functionName: "name" }); // contracts.push({ ...token.contract, functionName: "name" });
contracts.push({ ...token.contract, functionName: "symbol" }); contracts.push({ ...token.contract, functionName: "symbol" });
contracts.push({ ...token.contract, functionName: "totalSupply" }); contracts.push({ ...token.contract, functionName: "totalSupply" });
const data = await multicall({ const data = await multicall({
contracts, contracts,
}); });
token.decimals = data[0].result; token.decimals = BigInt(data[0].result);
token.name = data[1].result; // token.name = data[1].result;
token.symbol = data[2].result; token.symbol = data[1].result;
token.totalSupply = data[3].result; token.totalSupply = data[2].result;
} }
} catch (error) { } catch (error) {
console.error("initV2", error); console.error("initV2", error);
} }
}, },
async allowance() { async allowance() {
console.log("allowance"); console.log("allowance");
const walletStore = useWalletStoreV2(); const walletStore = useWalletStoreV2();
@@ -142,9 +185,7 @@ export const useTokenStore = defineStore("token", {
walletStore.address, walletStore.address,
memeBurnerStore.config.contractAddress, memeBurnerStore.config.contractAddress,
]); ]);
const decimals = this.activeToken.decimals;
allowance = BigInt(allowance / BigInt(Math.pow(10, decimals)));
console.log("allowance", allowance); console.log("allowance", allowance);
return allowance; return allowance;
}, },
@@ -155,7 +196,7 @@ export const useTokenStore = defineStore("token", {
const memeBurnerStore = useMemeburnerStore(); const memeBurnerStore = useMemeburnerStore();
var approveHash = await this.activeToken.contract.write.approve([ var approveHash = await this.activeToken.contract.write.approve([
memeBurnerStore.config.contractAddress, memeBurnerStore.config.contractAddress,
amount * Math.pow(10, this.activeToken.decimals), amount,
]); ]);
console.log("approveHash", approveHash); console.log("approveHash", approveHash);
+7 -4
View File
@@ -4,6 +4,7 @@ import QuoterJson from "@/assets/contracts/Quoter.json";
import UniswapPoolJson from "@/assets/contracts/UniswapPool.json"; import UniswapPoolJson from "@/assets/contracts/UniswapPool.json";
import BloodlineJson from "@/assets/contracts/Bloodline.json"; import BloodlineJson from "@/assets/contracts/Bloodline.json";
import { useMemeburnerStore } from "@/stores/memeburner"; import { useMemeburnerStore } from "@/stores/memeburner";
import { useTokenStore } from "@/stores/tokens";
import { getContract, multicall } from "@wagmi/core"; import { getContract, multicall } from "@wagmi/core";
@@ -42,9 +43,10 @@ export const useUniswapStore = defineStore("uniswap", {
async quoteExactInputSingle(amount, ethBase) { async quoteExactInputSingle(amount, ethBase) {
try { try {
console.log("quoteExactInputSingle"); console.log("quoteExactInputSingle");
const memeBurnerStore = useMemeburnerStore(); const memeBurnerStore = useMemeburnerStore();
// TODO: change it in your style const tokenStore = useTokenStore();
const tokenOut = BloodlineJson.contractAddress;
const tokenOut = tokenStore.memeToken.contractAddress;
// tokenIn - WETH // tokenIn - WETH
const tokenIn = BigInt(this.poolData.token0) == BigInt(tokenOut) ? this.poolData.token1 : this.poolData.token0; const tokenIn = BigInt(this.poolData.token0) == BigInt(tokenOut) ? this.poolData.token1 : this.poolData.token0;
console.log("quoteExactInputSingle-parameter", { console.log("quoteExactInputSingle-parameter", {
@@ -61,7 +63,8 @@ export const useUniswapStore = defineStore("uniswap", {
this.poolData.fee, this.poolData.fee,
ethBase, ethBase,
0, //sqrtPriceLimitX96 0, //sqrtPriceLimitX96
]); ]);
console.log("quotedAmountOut", quotedAmountOut);
return {result: true, amount: quotedAmountOut}; return {result: true, amount: quotedAmountOut};
} catch (error) { } catch (error) {
+49 -44
View File
@@ -38,35 +38,43 @@ export const useWalletStoreV2 = defineStore("walletV2", {
walletClient: null, walletClient: null,
config: null, config: null,
chain: null, chain: null,
token: [], token: [],
}), }),
getters: { getters: {
sacrificeToken: (state) => state.token.filter((obj) => { sacrificeToken: (state) =>
const tokenStore = useTokenStore(); state.token.filter((obj) => {
const tokenStore = useTokenStore();
return obj.contractAddress !== tokenStore.memeToken.contractAddress;
}), return obj.contractAddress !== tokenStore.memeToken.contractAddress;
memeToken: (state) => state.token.find((obj) => { }),
const tokenStore = useTokenStore(); memeToken: (state) =>
state.token.find((obj) => {
return obj.contractAddress === tokenStore.memeToken.contractAddress; const tokenStore = useTokenStore();
}),
return obj.contractAddress === tokenStore.memeToken.contractAddress;
}),
unclaimedRewards() {
const tokenStore = useTokenStore();
if (!this.memeToken?.unclaimedRewards) {
return 0n;
}
return this.memeToken.unclaimedRewards / 10n ** tokenStore.memeToken.decimals;
},
}, },
actions: { actions: {
async init() { async init() {
console.log("wallet init"); console.log("wallet init");
const account = getAccount();
if (account.address) { const account = getAccount();
this.address = account.address;
this.connected = true; if (account.address) {
} this.address = account.address;
this.connected = true;
}
}, },
async connectWallet(connector) { async connectWallet(connector) {
try { try {
console.log("connector.name", connector.name); console.log("connector.name", connector.name);
// if (!account.isConnected) { // if (!account.isConnected) {
const connection = await connect({ const connection = await connect({
chainId: goerli.id, chainId: goerli.id,
@@ -74,12 +82,12 @@ export const useWalletStoreV2 = defineStore("walletV2", {
}); });
console.log("connection", connection); console.log("connection", connection);
} catch (error) { } catch (error) {
if (error.message.includes("Connector not found")) { if (error.message.includes("Connector not found")) {
console.warn("Connector not found"); console.warn("Connector not found");
} }
console.error(error); console.error(error);
} }
// this.address = connection.account; // this.address = connection.account;
}, },
async getTokenBalance(token) { async getTokenBalance(token) {
@@ -87,8 +95,8 @@ export const useWalletStoreV2 = defineStore("walletV2", {
return result; return result;
}, },
async getTokenBalances() { async getTokenBalances() {
console.log("getTokenBalances"); console.log("getTokenBalances");
this.token = [] this.token = [];
const tokenStore = useTokenStore(); const tokenStore = useTokenStore();
var contracts = []; var contracts = [];
for (let index = 0; index < tokenStore.token.length; index++) { for (let index = 0; index < tokenStore.token.length; index++) {
@@ -100,31 +108,28 @@ export const useWalletStoreV2 = defineStore("walletV2", {
contracts, contracts,
}); });
for (let index = 0; index < tokenStore.token.length; index++) { for (let index = 0; index < tokenStore.token.length; index++) {
const token = tokenStore.token[index]; const token = tokenStore.token[index];
const balanceOfDecimal = data[index].result / BigInt(Math.pow(10, token.decimals));
this.token.push({ this.token.push({
contractAddress: token.contractAddress, contractAddress: token.contractAddress,
balanceOf: Number(balanceOfDecimal), balanceOf: data[index].result,
}); });
} }
}, },
async loadWalletData() { async loadWalletData() {
if (!this.connected) { if (!this.connected) {
return return;
} }
console.log("loadWalletData"); console.log("loadWalletData");
const rewardlockerStore = useRewardLockerStore(); const rewardlockerStore = useRewardLockerStore();
await this.getTokenBalances();
//MemeToken Staked
const tokenStore = useTokenStore();
const staked = await rewardlockerStore.getStaked(this.address);
this.memeToken.staked = Number(staked) / Math.pow(10, tokenStore.memeToken.decimals);
const unclaimedRewardsArray = await rewardlockerStore.getTotalRewards(this.address);
const unclaimedRewards = unclaimedRewardsArray[0] + unclaimedRewardsArray[1];
this.memeToken.unclaimedRewards = Number(unclaimedRewards) / Math.pow(10, tokenStore.memeToken.decimals)
} await this.getTokenBalances();
//MemeToken Staked
const tokenStore = useTokenStore();
this.memeToken.staked = await rewardlockerStore.getStaked(this.address);
const unclaimedRewardsArray = await rewardlockerStore.getTotalRewards(this.address);
const unclaimedRewards = unclaimedRewardsArray[0] + unclaimedRewardsArray[1];
this.memeToken.unclaimedRewards = unclaimedRewards;
},
}, },
// persist: true, // persist: true,
}); });
+15 -2
View File
@@ -27,7 +27,9 @@
> >
<template v-if="difference > 0"> <template v-if="difference > 0">
<div class="round-finish-info-key">Sacrifice Goal:</div> <div class="round-finish-info-key">Sacrifice Goal:</div>
<div class="round-finish-info-value">{{ cycleStore.getCurrentCycleData?.goalInBLD }} $BDL</div> <div class="round-finish-info-value">
{{ cycleStore.getCurrentCycleData?.goalInBLD / 10n ** tokenStore.memeToken.decimals }} $BDL
</div>
<div class="round-finish-info-key">Time left:</div> <div class="round-finish-info-key">Time left:</div>
<div class="round-finish-info-value">{{ days }} {{ hours }} {{ minutes }}</div> <div class="round-finish-info-value">{{ days }} {{ hours }} {{ minutes }}</div>
</template> </template>
@@ -77,7 +79,12 @@
<div class="bloodline-container"> <div class="bloodline-container">
<div class="bloodline-border purple">Get up to +25% Clan Bonus on your sacrifice.</div> <div class="bloodline-border purple">Get up to +25% Clan Bonus on your sacrifice.</div>
</div> </div>
<blood-chart :data="cycleStore.cycles[cycleStore.activeCycle]"></blood-chart> <template v-if="!cycleStore.cycles[cycleStore.activeCycle]">
<Vue3Lottie :animationData="ChartLoading" :height="400" :width="400" />
</template>
<template v-else>
<blood-chart :data="cycleStore.cycles[cycleStore.activeCycle]"></blood-chart>
</template>
</div> </div>
</div> </div>
</div> </div>
@@ -88,13 +95,19 @@ import { inject, ref, onMounted, onBeforeUnmount } from "vue";
import BloodChart from "@/components/BloodChart.vue"; import BloodChart from "@/components/BloodChart.vue";
import TokenClaim from "@/components/TokenClaim.vue"; import TokenClaim from "@/components/TokenClaim.vue";
import { useTokenStore } from "@/stores/tokens";
import { useMemeburnerStore } from "@/stores/memeburner"; import { useMemeburnerStore } from "@/stores/memeburner";
import LoadingComponent from "@/components/LoadingComponent.vue"; import LoadingComponent from "@/components/LoadingComponent.vue";
import { useCycleStore } from "@/stores/cycles"; import { useCycleStore } from "@/stores/cycles";
import { useRewardLockerStore } from "@/stores/rewardlocker"; import { useRewardLockerStore } from "@/stores/rewardlocker";
import { Vue3Lottie } from "vue3-lottie";
import ChartLoading from "@/assets/lottie/ChartLoading.json";
const cycleStore = useCycleStore(); const cycleStore = useCycleStore();
const tokenStore = useTokenStore();
const days = ref(null); const days = ref(null);
const hours = ref(null); const hours = ref(null);
+19 -1
View File
@@ -2415,6 +2415,11 @@
dependencies: dependencies:
"p-locate" "^5.0.0" "p-locate" "^5.0.0"
"lodash-es@^4.17.21":
"integrity" "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
"resolved" "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz"
"version" "4.17.21"
"lodash.isequal@4.5.0": "lodash.isequal@4.5.0":
"integrity" "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==" "integrity" "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ=="
"resolved" "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz" "resolved" "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz"
@@ -2437,6 +2442,11 @@
dependencies: dependencies:
"js-tokens" "^3.0.0 || ^4.0.0" "js-tokens" "^3.0.0 || ^4.0.0"
"lottie-web@5.12.2":
"integrity" "sha512-uvhvYPC8kGPjXT3MyKMrL3JitEAmDMp30lVkuq/590Mw9ok6pWcFCwXJveo0t5uqYw1UREQHofD+jVpdjBv8wg=="
"resolved" "https://registry.npmjs.org/lottie-web/-/lottie-web-5.12.2.tgz"
"version" "5.12.2"
"lru-cache@^6.0.0": "lru-cache@^6.0.0":
"integrity" "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==" "integrity" "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA=="
"resolved" "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz" "resolved" "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz"
@@ -3288,7 +3298,7 @@
"resolved" "https://registry.npmjs.org/vue-toastification/-/vue-toastification-2.0.0-rc.5.tgz" "resolved" "https://registry.npmjs.org/vue-toastification/-/vue-toastification-2.0.0-rc.5.tgz"
"version" "2.0.0-rc.5" "version" "2.0.0-rc.5"
"vue@^2.6.14 || ^3.3.0", "vue@^3.0.0-0 || ^2.6.0", "vue@^3.0.2", "vue@^3.2.0", "vue@^3.2.25", "vue@^3.3.2", "vue@>= 3.0.0 < 4", "vue@3.3.4": "vue@^2.6.14 || ^3.3.0", "vue@^3.0.0-0 || ^2.6.0", "vue@^3.0.2", "vue@^3.2", "vue@^3.2.0", "vue@^3.2.25", "vue@^3.3.2", "vue@>= 3.0.0 < 4", "vue@3.3.4":
"integrity" "sha512-VTyEYn3yvIeY1Py0WaYGZsXnz3y5UnGi62GjVEqvEGPl6nxbOrCXbVOTQWBEJUqAyTUk2uJ5JLVnYJ6ZzGbrSw==" "integrity" "sha512-VTyEYn3yvIeY1Py0WaYGZsXnz3y5UnGi62GjVEqvEGPl6nxbOrCXbVOTQWBEJUqAyTUk2uJ5JLVnYJ6ZzGbrSw=="
"resolved" "https://registry.npmjs.org/vue/-/vue-3.3.4.tgz" "resolved" "https://registry.npmjs.org/vue/-/vue-3.3.4.tgz"
"version" "3.3.4" "version" "3.3.4"
@@ -3299,6 +3309,14 @@
"@vue/server-renderer" "3.3.4" "@vue/server-renderer" "3.3.4"
"@vue/shared" "3.3.4" "@vue/shared" "3.3.4"
"vue3-lottie@^3.2.0":
"integrity" "sha512-PtNXbv7iD4XGmK8CXd71aLWmILIR6P6VzLMDw6ZzmDAeuJZuJ0MdOVnn50LOARgq+cOFJsn/2z+7tZh0F9T9qw=="
"resolved" "https://registry.npmjs.org/vue3-lottie/-/vue3-lottie-3.2.0.tgz"
"version" "3.2.0"
dependencies:
"lodash-es" "^4.17.21"
"lottie-web" "5.12.2"
"web3-eth-abi@^1.2.1": "web3-eth-abi@^1.2.1":
"integrity" "sha512-hk5NyeGweJYTjes7lBW7gtG7iYoN6HLt6E4FQDrHPdwZjwNmvzaOH9N8zMTCxNFXUlg0bzeTOzWwMA717a+4eg==" "integrity" "sha512-hk5NyeGweJYTjes7lBW7gtG7iYoN6HLt6E4FQDrHPdwZjwNmvzaOH9N8zMTCxNFXUlg0bzeTOzWwMA717a+4eg=="
"resolved" "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.10.1.tgz" "resolved" "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.10.1.tgz"