comments + contract update +

smaller design issues fix2
This commit is contained in:
EmberSpirit
2023-10-12 20:05:22 +02:00
parent b5c6f8af33
commit 2b4405579e
18 changed files with 514 additions and 5 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
{
"contractName": "Bloodline",
"contractAddress": "0xB7d11da1922328A10cCb357F571125151e558aFe",
"contractAddress": "0x51bF3df58D123e8EA43fb2189f18027FD36a08Af",
"abi": [
{
"inputs": [
+1 -1
View File
@@ -1,6 +1,6 @@
{
"contractName": "LiquidityOwner",
"contractAddress": "0x6AE9254705216A0d96A4A8d601a9DDB94C234859",
"contractAddress": "0xF8bc4Ce13263DD4e12070e3192be50310eF7C95a",
"abi": [
{
"inputs": [
+1 -1
View File
@@ -1,6 +1,6 @@
{
"contractName": "MemeAltar",
"contractAddress": "0x9612054A85502f2484c93C84eeCd14F65C6E4941",
"contractAddress": "0xE4F42F3f8B0E57b1054D457fe3b49a1A10B1aCEa",
"abi": [
{
"inputs": [
+30 -1
View File
@@ -1,6 +1,6 @@
{
"contractName": "RewardLocker",
"contractAddress": "0x216d1477B7686a0388A8881061FAc9c66469fC9c",
"contractAddress": "0x2952253374973DE0ffbFe35269Ca13FaF28B935F",
"abi": [
{
"inputs": [
@@ -392,6 +392,35 @@
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "user",
"type": "address"
},
{
"internalType": "address",
"name": "sacrificedToken",
"type": "address"
},
{
"internalType": "uint256",
"name": "reward",
"type": "uint256"
}
],
"name": "getStakeRewardForSacrificeReward",
"outputs": [
{
"internalType": "uint256",
"name": "stakeReward",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
File diff suppressed because one or more lines are too long
+88
View File
@@ -0,0 +1,88 @@
<template>
<div class="approve-card">
<div class="left-side low-mid-text">
Transaction<br />
Successful
</div>
<div class="right-side">
<div class="btn btn-immortal tiny-text" v-if="stateComputed === 1" @click="sacrificeClick">
Sacrifice 🩸
</div>
<div class="btn btn-immortal tiny-text" disabled v-if="stateComputed === 2">Sign Transaction</div>
<div class="btn btn-immortal tiny-text" disabled v-if="stateComputed === 3">
<loading-component></loading-component>
</div>
</div>
</div>
</template>
<script setup>
import LoadingComponent from "@/components/LoadingComponent.vue";
import { getCurrentInstance, computed, watch } from "vue";
import { useTokenStore } from "@/stores/tokens";
import { useSacrificeStore } from "@/stores/sacrifice";
import CardComponent from "@/components/CardComponent.vue";
import { useToast } from "vue-toastification";
const props = defineProps({
value: String,
header: String,
subheader: String,
info: String,
});
const toast = useToast();
const tokenStore = useTokenStore();
const sacrificeStore = useSacrificeStore();
const instance = getCurrentInstance();
const id = instance.attrs["toast-id"];
function closeToast() {
toast.dismiss(id);
}
const stateComputed = computed(() => {
let returnState = 0;
if (
sacrificeStore.sacrificeNumber === null ||
sacrificeStore.sacrificeNumber === "" ||
sacrificeStore.sacrificeNumber === 0
) {
returnState = 0;
} else if (sacrificeStore.sacrificeState === 2) {
returnState = 2;
} else if (sacrificeStore.sacrificeState === 3) {
returnState = 3;
} else if (
sacrificeStore.sacrificeNumber !== null ||
sacrificeStore.sacrificeNumber !== "" ||
sacrificeStore.sacrificeNumber > 0
) {
returnState = 1;
}
return returnState;
});
async function sacrificeClick() {
await sacrificeStore.sacrificeToken(sacrificeStore.sacrificeNumber, tokenStore.activeToken);
closeToast();
}
</script>
<style lang="sass">
.Vue-Toastification__container
.Vue-Toastification__toast--default
&.approve-toast
background: transparent
&.toast-card
padding: 24px 16px
border-radius: 10px
border: 2px solid var(--dark-purple, #4B0082)
background: var(--midnight-black, #0F0F0F)
.Vue-Toastification__toast-component-body
.approve-card
display: flex
flex-direction: row
display: flex
align-items: center
gap: 29px
</style>
+32
View File
@@ -0,0 +1,32 @@
import StakeSuccessToast from "@/components/toasts/StakeSuccessToast.vue";
import { useToast } from "vue-toastification";
const toast = useToast();
export 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: {
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,
});
}
+188
View File
@@ -0,0 +1,188 @@
import { defineStore } from "pinia";
import { useMemeburnerStore } from "./memeburner";
import { useTokenStore } from "./tokens";
import { useRewardLockerStore } from "./rewardlocker";
import { useWalletStoreV2 } from "./walletV2";
import { multicall } from "@wagmi/core";
export const useCycleStore = defineStore("cycles", {
state: () => ({
cycles: [],
activeCycle: null,
currentCycle: null,
}),
getters: {
//cycle winner is the token who reached the goal
//todo winner is now in the cycle object, no reason for that function anymore
getCycleWinner() {
const goal = this.getCurrentCycleData?.goal;
if (!goal) {
return;
}
const winnerCoin = this.cycles[this.activeCycle]?.token.find((token) => token.amount === goal);
if (winnerCoin) {
return winnerCoin;
} else {
return false;
}
},
getCurrentCycleData() {
return this.cycles[this.activeCycle];
},
},
actions: {
//todo check if still needed
// async loadRewardsCycles() {
// const walletStore = useWalletStoreV2();
// const rewardLockerStore = useRewardLockerStore();
// console.log("this.currentCycle", this.currentCycle);
// const contracts = [];
// for (let index = 0; index < this.currentCycle; index++) {
// console.log("load cycle: " + index);
// console.log({ index, address: walletStore.address });
// contracts.push({
// ...rewardLockerStore.contract,
// functionName: "getTotalRewardsOf",
// args: [walletStore.address, [index + 1]],
// });
// }
// const data = await multicall({
// contracts,
// });
// for (let index = 0; index < data.length; index++) {
// const element = data[index];
// if (!this.cycles[index]) {
// this.cycles[index] = {};
// }
// }
// },
//todo check if needed, or use fillcycle
async updateCurrentCycle(sacrificedToken) {
console.log("updateCurrentCycle");
const tokenStore = useTokenStore();
const memeBurnerStore = useMemeburnerStore();
var data = await memeBurnerStore.getSacrificedCycle(this.currentCycle);
var tokenIndex = this.cycles[this.currentCycle]?.token.findIndex(
(tokenData) => tokenData.contractAddress === sacrificedToken
);
const token = tokenStore.getToken(sacrificedToken);
this.cycles[this.currentCycle].token[tokenIndex].amount =
Number(data[tokenIndex].result[1]) / Math.pow(10, token.decimals)
},
/**
* 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) {
console.log("fillCycle");
const memeBurnerStore = useMemeburnerStore();
const tokenStore = useTokenStore();
const walletStore = useWalletStoreV2();
const rewardLockerStore = useRewardLockerStore();
if (!this.cycles[cycleNumber]?.goal || refillCycle || !this.cycles[cycleNumber]?.connected) {
console.log("fill cycle");
//multicall getSacrificedMeme for each token for this cycle
var data = await memeBurnerStore.getSacrificedCycle(cycleNumber);
let rewardData = null;
if (walletStore.connected) {
//getRewards multicall for all tokens
rewardData = await rewardLockerStore.getRewardsForAllToken(cycleNumber);
}
//getTotalSacrificeRewardsForToken multicall for all tokens
const tokenTotalSacrificed = await rewardLockerStore.getTotalSacrificeRewardsForAllToken(cycleNumber);
var goal = await memeBurnerStore.getGoal(cycleNumber);
var tokenArray = [];
var rewards_clan = 0;
var rewards_sacrifice = 0;
var rewards_staking = 0;
for (let index = 0; index < data.length; index++) {
var tokenData = {};
const token = tokenStore.token[index];
//why no multicall? todo
var coefficent = await rewardLockerStore.getSacrificedTokenCoefficient(
cycleNumber,
token.contractAddress
);
console.log("coefficent", coefficent);
tokenData.name = token.name;
tokenData.contractAddress = token.contractAddress;
tokenData.vamplogo = token.vamp.logo;
tokenData.vampwinner = token.vamp.winner;
tokenData.vampwinner2 = token.vamp.winner2;
tokenData.vampname = token.vamp.name;
tokenData.amount = Number(data[index].result[1]) / Math.pow(10, token.decimals);
tokenData.amountInBLD = Number(tokenTotalSacrificed[index].result) / Math.pow(10, token.decimals);
if (walletStore.connected) {
//if user is connected fill user specific data for the token
const sacrificeClanReward = Number(rewardData[index].result[1]);
let clanwin = 0;
if (cycleNumber !== this.currentCycle) {
clanwin = (Number(coefficent) / 10000 - 1) * sacrificeClanReward;
console.log("clanwin", clanwin);
}
const sacrificeRewards = Number(sacrificeClanReward);
tokenData.rewards_ges = Number(
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_staking = Number(
rewardData[index].result[0] / BigInt(Math.pow(10, token.decimals))
);
tokenData.rewards_sacrifice = sacrificeRewards / Math.pow(10, token.decimals);
rewards_clan = rewards_clan + tokenData.rewards_clan;
rewards_sacrifice = rewards_sacrifice + tokenData.rewards_sacrifice;
rewards_staking = rewards_staking + tokenData.rewards_staking;
}
tokenArray.push(tokenData);
}
const goalDecimal = Number(goal[0]) / Math.pow(10, tokenStore.memeToken.decimals);
const winner = tokenArray.find((token) => token.amount === goalDecimal);
const goalInBLD = await memeBurnerStore.getGoalInBLOOD(cycleNumber);
//replace vamplogo cause it will automatically change the token for the cycle view (new design)
if (winner) {
winner.vamplogo = winner.vampwinner;
}
this.cycles[cycleNumber] = {
goal: Number(goal[0]) / Math.pow(10, tokenStore.memeToken.decimals),
goalInBLD: Number(goalInBLD / BigInt(Math.pow(10, tokenStore.memeToken.decimals))),
expirationTimestamp: Number(goal[2]),
rewards_clan: Number(rewards_clan),
rewards_staking: Number(rewards_staking),
rewards_sacrifice: Number(rewards_sacrifice),
rewards_total: Number(rewards_clan) + Number(rewards_sacrifice) + Number(rewards_staking),
token: tokenArray,
connected: walletStore.connected,
winner: winner,
};
console.log("this.cycles[cycleNumber]", this.cycles[cycleNumber]);
} else {
console.log("cycle already filled");
}
},
async getFinshedCycleNumbers() {
const array = [];
const rewardLockerStore = useRewardLockerStore();
const lastCompletedCycle = await rewardLockerStore.lastCompletedCycle();
for (let index = 0; index <= Number(lastCompletedCycle); index++) {
array.push(index);
}
return array;
},
},
});
+172
View File
@@ -0,0 +1,172 @@
import { defineStore } from "pinia";
import { useMemeburnerStore } from "@/stores/memeburner";
import { useUniswapStore } from "@/stores/uniswap";
import { useWalletStoreV2 } from "@/stores/walletV2";
import { useCycleStore } from "@/stores/cycles";
import { useTokenStore } from "@/stores/tokens";
import { waitForTransaction, readContract, watchBlockNumber, multicall } from "@wagmi/core";
import { showSuccessToast } from "@/helper/toast.js";
import { formatNumber } from "@/helper/helper.js";
export const useSacrificeStore = defineStore("sacrifice", {
state: () => ({
sacrificeNumber: null,
sacrificeState: 0,
}),
getters: {},
actions: {
async sacrificeToken(amount, token) {
console.log("sacrificeToken", {amount, token});
const memeburnerStore = useMemeburnerStore();
const walletStore = useWalletStoreV2();
const tokenStore = useTokenStore();
const cycleStore = useCycleStore();
try {
this.sacrificeState = 2;
const getRewards = await this.getRewardsFor(amount, token);
console.log("getRewards", getRewards);
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);
}
this.sacrificeState = 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, token.decimals);
token.allowance = await tokenStore.allowance();
this.sacrificeState = 4;
showSuccessToast(
formatNumber(outputSacrifice),
"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 cycleStore.fillCycle(cycleStore.currentCycle, true);
return;
} catch (error) {
//we should show the user an issue
throw new Error(error);
} finally {
this.sacrificeState = 0;
}
},
async getRewardsFor(value, token) {
console.log("getRewardsFor", {value, token});
const memeburnerStore = useMemeburnerStore();
const uniswapStore = useUniswapStore();
const walletStore = useWalletStoreV2();
let output = 0;
try {
if (!value || isNaN(value)) {
this.sacrificeState = 0;
return output;
}
const rewardsForResult = await memeburnerStore.getRewardFor(
BigInt(value * Math.pow(10, token.decimals))
);
const rewardsForResultNumber = rewardsForResult.reduce((x, y) => {
return x + Number(y) / Math.pow(10, token.decimals);
}, 0);
var quoteRewards = await uniswapStore.quoteExactInputSingle(value * Math.pow(10, token.decimals));
let variant = "sacrifice";
if (quoteRewards.result) {
const quoteRewardsNumber = Number(quoteRewards.amount) / Math.pow(10, token.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
*/
//
output = rewardsForResultNumber;
}
console.log("variant", variant);
const amountDecimal = BigInt(value * Math.pow(10, token.decimals));
console.log("amountDecimal", amountDecimal);
if (!walletStore.connected || (walletStore.connected && token.allowance < value)) {
/**
* case 1
* user is not logged in or Allowance is less than Input, then I show getRewardsForSacrifice Value
* variante not relevant
*/
output = rewardsForResultNumber;
} else if (walletStore.connected && variant === "sacrifice") {
/**
* case 2
* user is logged in and allowance is greater or equal input and variant is sacrifice
*/
output = 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: [token.contractAddress, amountDecimal.toString(), 0],
account: walletStore.address,
});
const amountBuy = await readContract({
address: memeburnerStore.contract.address,
abi: memeburnerStore.contract.abi,
functionName: "sacrificeMemeAndBuyBLOOD",
args: [token.contractAddress, amountDecimal.toString(), 0],
account: walletStore.address,
});
const amountBuyNumber = Number(amountBuy) / Math.pow(10, token.decimals);
const amountSacrificeNumber = Number(amountSacrifice) / Math.pow(10, token.decimals);
if (amountBuyNumber * 0.995 > amountSacrificeNumber) {
variant = "buy";
output = amountBuyNumber;
console.log("use buy after comparison sacrificeMemeAndBuyBLOOD and sacrificeMeme");
} else {
variant = "sacrifice";
output = amountSacrificeNumber;
console.log("use sacrifice after comparison sacrificeMemeAndBuyBLOOD and sacrificeMeme");
}
}
return { output: output, variant: variant };
} catch (error) {
console.error("getRewardsFor", error);
}
},
},
});