Merge branch 'master' into development

This commit is contained in:
Michel Fromme
2023-07-28 12:19:40 +02:00
10 changed files with 4201 additions and 12 deletions
+3
View File
@@ -27,3 +27,6 @@ coverage
*.njsproj *.njsproj
*.sln *.sln
*.sw? *.sw?
# we want to force specific versions of dependencies to prevent malware injections
# yarn.lock
+4
View File
@@ -56,6 +56,10 @@ function showPanelTest(bla) {
console.log("bla", bla); console.log("bla", bla);
} }
function showPanelTest(bla) {
console.log("bla", bla);
}
function isMobileFunc() { function isMobileFunc() {
if (screen.width <= 760) { if (screen.width <= 760) {
return true; return true;
+1 -1
View File
@@ -117,7 +117,7 @@
import { ref, defineProps, watch, inject, computed } from "vue"; import { ref, defineProps, watch, inject, computed } from "vue";
import { useWalletStore } from "@/stores/wallet"; import { useWalletStore } from "@/stores/wallet";
import { useTokenStore } from "@/stores/tokens"; import { useTokenStore } from "@/stores/tokens";
import { useMemeburnerStore } from "@/stores/memeBurner"; import { useMemeburnerStore } from "@/stores/memeburner";
import { storeToRefs } from "pinia"; import { storeToRefs } from "pinia";
import Helper from "@/utils/helper.js"; import Helper from "@/utils/helper.js";
const isMobile = inject("isMobile"); const isMobile = inject("isMobile");
+13 -2
View File
@@ -14,12 +14,23 @@ 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, faSpinner ,faPlus, faCaretLeft, faCaretRight, faBars } from "@fortawesome/free-solid-svg-icons"; import { faArrowDown, faSpinner ,faPlus, faCaretLeft, faCaretRight, faBars, faAnglesRight } 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";
/* add icons to the library */ /* add icons to the library */
library.add(faArrowDown, faDiscord, faTwitter, faTelegram, faSpinner, faPlus, faCaretLeft, faCaretRight, faBars); library.add(
faArrowDown,
faDiscord,
faTwitter,
faTelegram,
faSpinner,
faPlus,
faCaretLeft,
faCaretRight,
faBars,
faAnglesRight
);
const app = createApp(App) const app = createApp(App)
+10
View File
@@ -22,6 +22,16 @@ const router = createRouter({
name: "Test", name: "Test",
component: () => import("../views/TestView.vue"), component: () => import("../views/TestView.vue"),
}, },
{
path: "/walletconnect",
name: "WalletConnect",
component: () => import("../views/WalletConnectView.vue"),
},
{
path: "/wagmi",
name: "Wagmi",
component: () => import("../views/WagmiView.vue"),
},
], ],
}); });
+3 -2
View File
@@ -47,9 +47,10 @@ export const useWalletStore = defineStore("wallet", {
new Web3.providers.WebsocketProvider(`wss://eth-goerli.g.alchemy.com/v2/${goerliKey}`) new Web3.providers.WebsocketProvider(`wss://eth-goerli.g.alchemy.com/v2/${goerliKey}`)
); );
}, },
// connectWalletV2(connector) {
// this.address = data[0];
// },
connectWallet() { connectWallet() {
const tokenStore = useTokenStore();
// if (window.ethereum) {
window.ethereum window.ethereum
.request({ method: "eth_requestAccounts" }) .request({ method: "eth_requestAccounts" })
.then((data) => { .then((data) => {
+184 -6
View File
@@ -5,6 +5,8 @@
<button @click="sacrificeMeme">sacrifice Meme</button> <button @click="sacrificeMeme">sacrifice Meme</button>
<button @click="approveMeme1">approve Meme1</button> <button @click="approveMeme1">approve Meme1</button>
<button @click="tokenStore.approveToken(MemeBurnerJson, 10)">wallet approve</button> <button @click="tokenStore.approveToken(MemeBurnerJson, 10)">wallet approve</button>
<button @click="stake">stake</button>
<button @click="">unstake</button>
</div> </div>
</template> </template>
@@ -34,6 +36,8 @@ const web3 = ref(null);
const contractMeme2 = ref(null); const contractMeme2 = ref(null);
const contractMeme1 = ref(null); const contractMeme1 = ref(null);
const contractBurner = ref(null); const contractBurner = ref(null);
const contractBloodline = ref(null);
const rewardlocker = ref(null);
onMounted(async () => { onMounted(async () => {
web3.value = new Web3(window.ethereum); web3.value = new Web3(window.ethereum);
@@ -43,9 +47,27 @@ onMounted(async () => {
console.log("accounts", accounts); console.log("accounts", accounts);
web3.value.eth.Contract.defaultAccount = accounts[0]; web3.value.eth.Contract.defaultAccount = accounts[0];
contractMeme1.value = new web3.value.eth.Contract(Meme1Json.abi, Meme1Json.contractAddress); contractMeme1.value = new web3.value.eth.Contract(
contractMeme2.value = new web3.value.eth.Contract(Meme2Json.abi, Meme2Json.contractAddress); Meme1Json.abi,
contractBurner.value = new web3.value.eth.Contract(MemeBurnerJson.abi, MemeBurnerJson.contractAddress); Meme1Json.contractAddress
);
contractMeme2.value = new web3.value.eth.Contract(
Meme2Json.abi,
Meme2Json.contractAddress
);
contractBloodline.value = new web3.value.eth.Contract(
MemeTokenJson.abi,
MemeTokenJson.contractAddress
);
contractBurner.value = new web3.value.eth.Contract(
MemeBurnerJson.abi,
MemeBurnerJson.contractAddress
);
rewardlocker.value = new web3.value.eth.Contract(
RewardLockerJson.abi,
RewardLockerJson.contractAddress
);
}); });
async function approveMeme1() { async function approveMeme1() {
@@ -60,6 +82,8 @@ async function approveMeme1() {
// console.log("approve", approve); // console.log("approve", approve);
// } // }
// change this value to make yourself rich quick
async function mintToken() { async function mintToken() {
try { try {
var mint = await contractMeme1.value.methods var mint = await contractMeme1.value.methods
@@ -90,15 +114,169 @@ async function mintToken2() {
// console.log("totalSupply", totalSupply); // console.log("totalSupply", totalSupply);
} }
// 100 Meme will be sacrificed
async function sacrificeMeme() { async function sacrificeMeme() {
const allowance = await contractMeme1.value.methods const allowance = await contractMeme1.value.methods
.allowance(web3.value.eth.Contract.defaultAccount, MemeBurnerJson.contractAddress) .allowance(
web3.value.eth.Contract.defaultAccount,
MemeBurnerJson.contractAddress
)
.call(); .call();
console.log("allowance", allowance); console.log("allowance", allowance);
var reward = await contractBurner.value.methods var reward = await contractBurner.value.methods
.sacrificeMeme(Meme1Json.contractAddress, "100000000000000000") .sacrificeMeme(Meme1Json.contractAddress, "100000000000000000000")
.call({ from: web3.value.eth.Contract.defaultAccount }); .send({ from: web3.value.eth.Contract.defaultAccount });
console.log("reward", reward); console.log("reward", reward);
} }
async function stake() {
const SECOND = 1000;
const fromAddress = "0x66422602B2f4885c57EE794174f98d9E4DDBBBC6";
// JavaScript dates have millisecond resolution
const deadline = Date.now() + 20 * 60;
const spender = "0x7C3D5a19878d550D0c6c2b0BFC884ef410F6e440";
console.log("deadline", deadline);
var nonceTest = await contractBloodline.value.methods
.nonces(fromAddress)
.call();
console.log("type", typeof nonceTest);
console.log("nonceTest", nonceTest);
const value = (1 * Math.pow(10, 18)).toString();
console.log("value", value);
const messageData = createPermitMessageData(
fromAddress,
spender,
nonceTest,
deadline,
value
);
console.log("messageData", messageData);
// const sig = await signData(fromAddress, messageData.typedData);
const signature = await signTyped(fromAddress, messageData.typedData);
// console.log("sig", sig);
console.log("signature", signature);
const split = splitSig(signature);
console.log("split", split);
var resultStake = await rewardlocker.value.methods
.stakeToBeSecured(value, deadline, split.v, split.r, split.s)
.send({ from: fromAddress });
console.log("resultStake", resultStake);
var allowance = await contractBloodline.value.methods
.allowance(fromAddress, spender)
.call();
console.log("allowance", allowance);
// return Object.assign({}, sig, messageData.message);
}
const signTyped = (fromAddress, dataToSign) => {
// call this method to sign EIP 712 data
return new Promise((resolve, reject) => {
web3.value.currentProvider.sendAsync(
{
method: "eth_signTypedData_v4",
params: [fromAddress, dataToSign],
from: fromAddress,
},
(err, result) => {
if (err) return reject(err);
resolve(result.result);
}
);
});
};
const splitSig = (sig) => {
// splits the signature to r, s, and v values.
// const pureSig = sig.replace("0x", "");
const r = sig.slice(0, 66);
const s = "0x" + sig.slice(66, 130);
const v = Number("0x" + sig.slice(130, 132));
return { v, r, s };
};
const signData = async function (fromAddress, typeData) {
const result = await window.ethereum.request({
id: 1,
method: "eth_signTypedData_v4",
params: [fromAddress, typeData],
from: fromAddress,
});
const r = result.slice(0, 66);
const s = "0x" + result.slice(66, 130);
const v = Number("0x" + result.slice(130, 132));
return { v, r, s };
};
const createPermitMessageData = function (
fromAddress,
spender,
nonce,
deadline,
value
) {
const message = {
owner: fromAddress,
spender: spender,
nonce: nonce,
deadline: deadline,
value: value,
};
const domainType = [
{ name: "name", type: "string" },
{ name: "version", type: "string" },
{ name: "chainId", type: "uint256" },
{ name: "verifyingContract", type: "address" },
];
const typedData = JSON.stringify({
types: {
EIP712Domain: domainType,
Permit: [
{
name: "owner",
type: "address",
},
{
name: "spender",
type: "address",
},
{
name: "value",
type: "uint256",
},
{
name: "nonce",
type: "uint256",
},
{
name: "deadline",
type: "uint256",
},
],
},
primaryType: "Permit",
domain: {
name: "Bloodline",
version: "1",
chainId: 5,
verifyingContract: "0x9dcD7Cd83ED0Fe69DDfE3c2A265a1207F2Bc3219",
},
message: message,
});
return {
typedData,
message,
};
};
// console.log("balanceOf", contract.mint(10)); // console.log("balanceOf", contract.mint(10));
</script> </script>
+126
View File
@@ -0,0 +1,126 @@
<template>
<div>
<div v-if="!fromAddress" @click="showConnectors = true">Connect</div>
<div v-if="showConnectors">
<div v-for="connector in config.connectors" @click="connectWallet(connector)">
{{ connector.name}}
</div>
</div>
<div v-if="fromAddress" @click="disconnectWallet">Disconnect</div>
</div>
</template>
<script setup >
import { ref, toRaw, onMounted, onUnmounted } from "vue";
import Meme1Json from "@/assets/contracts/Meme1.json";
import { useWalletStore } from "@/stores/wallet";
const walletStore = useWalletStore();
const fromAddress = ref(null);
const showConnectors = ref(false);
import {
createConfig,
configureChains,
mainnet,
getAccount,
getContract,
connect,
disconnect,
InjectedConnector,
getWalletClient,
watchAccount,
} from "@wagmi/core";
import { WalletConnectConnector } from "@wagmi/core/connectors/walletConnect";
import { MetaMaskConnector } from "@wagmi/core/connectors/metaMask";
import { goerli } from "@wagmi/core/chains";
import { publicProvider } from "@wagmi/core/providers/public";
import { alchemyProvider } from "@wagmi/core/providers/alchemy";
const goerliKey = import.meta.env.VITE_GOERLI_KEY;
console.log("goerliKey", goerliKey);
const { chains, publicClient, webSocketPublicClient } = configureChains(
[goerli],
[alchemyProvider({ apiKey: goerliKey }), publicProvider()]
);
const projectId = "d8e5ecb0353c02e21d4c0867d4473ac5";
const config = ref(null);
const accountSub = ref(null);
// onMounted(() => {
// const account = getAccount();
// console.log("account", account);
// if (account.isConnected) {
// fromAddress.value = account.address;
// }
// accountSub.value = watchAccount((account) => {
// console.log("account123", account);
// fromAddress.value = account.address;
// walletStore.address = account.address;
// });
// });
// onUnmounted(() => {
// accountSub.value();
// console.log("unsubscribe");
// });
config.value = createConfig({
autoConnect: true,
connectors: [
new MetaMaskConnector({ chains }),
new WalletConnectConnector({
chains,
options: {
projectId: projectId,
showQrModal: true,
metadata: {
name: "Bloodline-App",
description: "TODO Bloodline Description",
url: "https://gitea.loseyourip.com/",
icons: [
"https://gitea.loseyourip.com/assets/img/vampir.png",
],
},
},
}),
],
publicClient,
webSocketPublicClient,
});
console.log("config", config);
const walletClient = await getWalletClient();
console.log("walletClient", walletClient);
async function disconnectWallet() {
try {
await disconnect();
} catch (error) {
console.log("error", error);
}
}
async function connectWallet(connector) {
console.log("connector.name", connector.name);
const rawConnector = toRaw(connector);
// if (!account.isConnected) {
const connection = await connect({
chainId: goerli.id,
connector: rawConnector,
});
console.log("Connecting to:", connection);
fromAddress.value = connection.account;
showConnectors.value = false;
}
async function connect1() {
const connection = await connect({
chainId: goerli.id,
connector: new InjectedConnector(),
});
console.log("Connecting to:", connection);
}
async function getAccount1() {
const account = getAccount();
console.log("account", account);
}
</script>
+223
View File
@@ -0,0 +1,223 @@
<template>
{{ activeWallet }}
{{ fromAddressWC }}
<div class="connect-overview" v-if="!activeWallet && !fromAddressWC">
<div v-for="wallet in wallets">
<img :src="wallet.icon" :alt="wallet.name" @click="connectWallet($event, wallet)">
</div>
</div>
<div v-else>
<button @click="disconnectWallet">disconnect</button>
</div>
</template>
<script setup>
import { ref, onMounted } from "vue";
import { WalletConnectModalSign } from "@walletconnect/modal-sign-html";
import {
EthereumProvider,
OPTIONAL_EVENTS,
REQUIRED_EVENTS,
REQUIRED_METHODS,
OPTIONAL_METHODS,
} from "@walletconnect/ethereum-provider";
import Web3 from "web3";
// const modal = new WalletConnectModal({
// projectId: "d8e5ecb0353c02e21d4c0867d4473ac5",
// chains: ["goerli"],
// });
const activeWallet = ref(null);
const fromAddressWC = ref(null);
const provider = ref(null);
const wallets = [
{
name: "MetaMask",
icon: "https://cdn.iconscout.com/icon/free/png-512/metamask-2728406-2261817.png",
},
{
name: "WalletConnect",
icon: "https://time.com/img/icons/wallet-connect.png",
},
];
const disableConnectButton = ref(false);
// const web3Modal = new WalletConnectModalSign({
// projectId,
// metadata: {
// name: "Bloodline-App",
// description: "TODO Bloodline Description",
// url: "https://gitea.loseyourip.com/",
// icons: ["https://gitea.loseyourip.com/assets/img/vampir.png"],
// },
// });
onMounted(async () => {
const projectId = "d8e5ecb0353c02e21d4c0867d4473ac5";
const showQrModal = true;
const metadata = {
name: "Bloodline-App",
description: "TODO Bloodline Description",
url: "https://gitea.loseyourip.com/",
icons: ["https://gitea.loseyourip.com/assets/img/vampir.png"],
};
provider.value = await EthereumProvider.init({
projectId, // REQUIRED your projectId
chains: [1], // chains added to required namespaces
optionalChains: [5], // chains added to optional namespaces
showQrModal, // REQUIRED set to "true" to use @walletconnect/modal
REQUIRED_METHODS, // REQUIRED ethereum methods
OPTIONAL_METHODS, // OPTIONAL ethereum methods
REQUIRED_EVENTS, // REQUIRED ethereum events
OPTIONAL_EVENTS, // OPTIONAL ethereum events
// rpcMap, // OPTIONAL rpc urls for each chain
metadata, // OPTIONAL metadata of your app
// qrModalOptions, // OPTIONAL - `undefined` by default, see https://docs.walletconnect.com/2.0/web3modal/options
});
console.log("provider.value", provider.value);
if (provider.value.accounts.length > 0) {
fromAddressWC.value = provider.value.accounts[0];
} else {
fromAddressWC.value = null;
}
});
async function disconnectWallet() {
activeWallet.value = null;
fromAddressWC.value = null;
provider.value.disconnect();
}
async function connectWallet(event, wallet) {
try {
disableConnectButton.value = true;
if (wallet.name === "MetaMask") {
window.ethereum
.request({ method: "eth_requestAccounts" })
.then((data) => {
console.log("data", data);
activeWallet.value = { ...wallet, address: data };
})
.catch((error) => {
if (error.code === 4001) {
// EIP-1193 userRejectedRequest error
console.log("Please connect to MetaMask.");
} else {
console.error(error);
}
});
} else if (wallet.name === "WalletConnect") {
const methods = [
"eth_signTypedData",
"eth_signTypedData_v4",
"eth_sign",
];
const optionalMethods = [];
const events = [];
console.log("OPTIONAL_EVENTS", OPTIONAL_EVENTS);
console.log("REQUIRED_EVENTS", REQUIRED_EVENTS);
console.log("REQUIRED_METHODS", REQUIRED_METHODS);
console.log("OPTIONAL_METHODS", OPTIONAL_METHODS);
console.log("provider", provider.value);
// await provider.value.connect();
await provider.value.enable();
provider.value.on("accountsChanged", function (account) {
console.log("accountschanged", { account });
fromAddressWC.value = account;
});
const result = await provider.value.request({
method: "eth_requestAccounts",
});
console.log("result", result);
fromAddressWC.value = result[0];
// const session = await web3Modal.connect({
// requiredNamespaces: {
// eip155: {
// methods: ["eth_sendTransaction", "personal_sign"],
// chains: ["eip155:1"],
// events: ["chainChanged", "accountsChanged"],
// },
// },
// });
// console.log("session", session);
// const web3 = new Web3(session);
// console.log("web3", web3);
// try {
// // console.log("web3Modal", web3Modal);
// // var test = await web3Modal.request({
// // method: "eth_requestAccounts",
// // });
// // console.log("test", test);
// console.log("getAccounts");
// const accounts = await web3.eth.getAccounts();
// console.log("Got accounts", accounts);
// } catch (error) {
// console.log("error", error);
// }
// // MetaMask does not give you all accounts, only the selected account
// const fromAddress = session.namespaces.eip155.accounts[0].slice(9);
// console.log("Web3 instance is", web3);
// try {
// var balance = web3.eth.getBalance(fromAddress);
// console.log("balance", balance);
// } catch (error) {
// console.log("error", error);
// }
// // var accounts = await web3.eth.getAccounts();
// console.log("accounts", accounts);
// var userAccount = accounts[0];
// console.log("userAccount", userAccount);
// session.on("accountsChanged", (accounts) => {
// console.log("ACCOUNTS CHANGED" + accounts[0]);
// });
}
} catch (error) {
} finally {
disableConnectButton.value = false;
}
}
async function onConnect() {
try {
disableConnectButton.value = true;
const session = await web3Modal.connect({
requiredNamespaces: {
eip155: {
methods: ["eth_sendTransaction", "personal_sign"],
chains: ["eip155:1"],
events: ["chainChanged", "accountsChanged"],
},
},
});
console.info(session);
} catch (err) {
console.error(err);
} finally {
disableConnectButton.value = false;
}
}
async function disconnect() {
modal.closeModal();
}
</script>
<style lang="sass">
.connect-overview
display: flex
div
background-color: black
width: 100px
height: auto
img
width: 100%
height: auto
</style>
+3633
View File
File diff suppressed because it is too large Load Diff