viem wagmi

This commit is contained in:
Michel Fromme
2023-07-27 11:10:05 +02:00
parent 161262f590
commit b2121a1ca4
18 changed files with 3487 additions and 4160 deletions
+50 -12
View File
@@ -3,14 +3,20 @@ import { onMounted, onUnmounted, provide, ref } from "vue";
import { storeToRefs } from "pinia";
import Navbar from "./components/Navbar.vue";
import { useWalletStore } from "@/stores/wallet";
const walletStore = useWalletStore();
import { useWalletStoreV2 } from "@/stores/walletV2";
const walletStore = useWalletStoreV2();
import { useTokenStore } from "@/stores/tokens";
import { useContractStore } from "@/stores/contracts";
import { useMemeburnerStore } from "@/stores/memeburner";
import { useRewardLockerStore } from "@/stores/rewardlocker";
import { useMultiCallStore } from "@/stores/multicall";
import { useRoundsStore } from "@/stores/rounds";
import SlideoutPanel from "./components/SlideoutPanel.vue";
import ConnectWallet from "./components/ConnectWallet.vue";
import { watchAccount, getPublicClient, getWalletClient } from "@wagmi/core";
const tokenStore = useTokenStore();
const contractStore = useContractStore();
const memeBurnerStore = useMemeburnerStore();
@@ -20,15 +26,25 @@ const roundsStore = useRoundsStore();
const { memeBurner, token } = storeToRefs(tokenStore);
const { list } = storeToRefs(contractStore);
const isMobile = ref(false);
const showPanel = ref(false);
const eventWatch = ref(null);
isMobile.value = isMobileFunc();
onUnmounted(() => {
window.removeEventListener("resize", handleWindowSizeChange);
eventWatch.value();
console.log("unsubscribe");
});
const handleWindowSizeChange = () => {
isMobile.value = isMobileFunc();
// your code
};
function showPanelTest(bla) {
console.log("bla", bla);
}
function isMobileFunc() {
if (screen.width <= 760) {
return true;
@@ -41,25 +57,47 @@ provide("isMobile", isMobile);
onMounted(async () => {
window.addEventListener("resize", handleWindowSizeChange);
handleWindowSizeChange();
// initContracts
await walletStore.init();
await tokenStore.init();
await memeBurnerStore.init();
await rewardLockerStore.init();
await memeBurnerStore.init();
await multiCallStore.init();
// await tokenStore.init();
// await memeBurnerStore.init();
// await rewardLockerStore.init();
// await memeBurnerStore.init();
// await multiCallStore.init();
//Memeburner Contract
//init
roundsStore.currentRound = parseInt(await memeBurnerStore.getCurrentRound());
console.log("roundsStore.currentRound", roundsStore.currentRound);
roundsStore.activeRound = roundsStore.currentRound;
await roundsStore.fillRound(roundsStore.activeRound);
// roundsStore.currentRound = parseInt(
// await memeBurnerStore.getCurrentRound()
// );
// console.log("roundsStore.currentRound", roundsStore.currentRound);
// roundsStore.activeRound = roundsStore.currentRound;
// await roundsStore.fillRound(roundsStore.activeRound);
//events
eventWatch.value = watchAccount(async (account) => {
console.log("account123", account);
const publicClient = getPublicClient();
console.log("publicClient", publicClient);
var walletClient = await getWalletClient();
console.log("walletClient", walletClient);
if (account.address) {
walletStore.address = account.address;
walletStore.connected = true;
} else {
walletStore.address = null;
walletStore.connected = false;
}
});
});
</script>
<template>
<navbar />
<navbar @show-panel="((value) => showPanel = value)"/>
<slideout-panel v-model="showPanel">
<connect-wallet></connect-wallet>
</slideout-panel>
<div class="main">
<RouterView />
</div>
+126
View File
@@ -0,0 +1,126 @@
<template>
<h3>Connect Wallet</h3>
<div class="connectors-wrapper">
<div class="connectors-element" v-for="connector in walletStore.connectors" @click="connectWallet(connector)">
<div class="connector-icon">
<img :src="`/assets/img/connectors/${connector.id}.svg`" :alt="`${connector.name} Logo`">
</div>
<div class="connector-name">{{ connector.name }}</div>
</div>
</div>
<div @click="disconnectWallet">disconnect</div>
<div @click="getWalletClientTest">getwalletclient</div>
<div>Connected: {{ walletStore.connected }}</div>
</template>
<script setup>
import { ref, toRaw, onMounted, onUnmounted, getCurrentInstance } from "vue";
import { useWalletStoreV2 } from "@/stores/walletV2";
import Meme1Json from "@/assets/contracts/Meme1.json";
import {
createConfig,
configureChains,
mainnet,
getAccount,
getContract,
connect,
disconnect,
InjectedConnector,
watchAccount,
getWalletClient,
} from "@wagmi/core";
const walletStore = useWalletStoreV2();
const goerliKey = import.meta.env.VITE_GOERLI_KEY;
const fromAddress = ref(null);
const accountSub = ref(null);
const instance = getCurrentInstance();
// config.value = createConfig({
// autoConnect: true,
// connectors: [
// new CoinbaseWalletConnector({
// chains,
// options: {
// appName: "wagmi demo",
// },
// }),
// 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);
async function disconnectWallet() {
console.log("disconnectWallet");
try {
await disconnect();
} catch (error) {
console.log("error", error);
}
}
async function getWalletClientTest() {
const walletClient = await getWalletClient();
console.log("walletClient", walletClient);
const contract = getContract({
address: Meme1Json.contractAddress,
abi: Meme1Json.abi,
walletClient,
});
const result = await contract.read.totalSupply();
console.log("result", result);
// console.log("obj", obj);
// });
}
async function connectWallet(connector) {
instance.parent.emit("update:modelValue", false);
await walletStore.connectWallet(toRaw(connector));
}
</script>
<style lang="sass">
.connectors-wrapper
display: flex
flex-direction: column
.connectors-element
display: flex
padding: 12px
border: 1px solid rgba(152, 161, 192, 0.24)
background-color: #202020
&:hover, &:active, &:focus
background-color: lighten(#202020, 20%)
cursor: pointer
.connector-icon
border-radius: 12px
width: 40px
overflow: hidden
height: 40px
.connector-name
padding: 0 8px
align-self: center
</style>
+9 -4
View File
@@ -1,11 +1,15 @@
<script setup>
import { storeToRefs } from "pinia";
import { ref, onMounted, onBeforeUnmount, inject } from "vue";
import { useWalletStore } from "@/stores/wallet";
const walletStore = useWalletStore();
import { useWalletStoreV2 } from "@/stores/walletV2";
const emit = defineEmits(["showPanel"]);
const walletStore = useWalletStoreV2();
const { connected, address } = storeToRefs(walletStore);
const isMobile = inject("isMobile");
const showPanel = ref(false);
const showNavbar = ref(true);
const lastScrollPosition = ref(0);
@@ -62,8 +66,9 @@ onBeforeUnmount(() => {
</div>
<div class="navbar-end">
<div v-if="!isMobile">
<div v-if="!connected" class="btn btn-immortal" @click="walletStore.connectWallet">connect</div>
<span v-else> {{ address }}</span>
<!-- <div v-if="!connected" class="btn btn-immortal" @click="walletStore.connectWallet">connect</div> -->
<div v-if="!address" class="btn btn-immortal" @click="$emit('showPanel', true)">connect</div>
<span v-else @click="$emit('showPanel', true)"> {{ address }}</span>
</div>
<div v-else class="hamburger-menu">
<font-awesome-icon :icon="['fas', 'bars']" />
+62
View File
@@ -0,0 +1,62 @@
<template>
<div class="slideout-overlay" :class="{'open': props.modelValue}" @click="$emit('update:modelValue', false)">
<div :class="{'slideout-wrapper': true, 'open': props.modelValue}" >
<div class="slideout-panel" @click="testClick">
<slot></slot>
</div>
</div>
</div>
</template>
<script setup>
import { inject, watchEffect } from "vue";
const props = defineProps({
modelValue: Boolean,
});
defineEmits(["update:modelValue"]);
const showPanel = inject("showPanel");
console.log("showPanel.value", showPanel);
const isMobile = inject("isMobile");
function testClick(e) {
e.preventDefault();
e.stopPropagation();
}
</script>
<style lang="sass">
.slideout-overlay
background-color: rgba(0,0,0,.5)
z-index: 100
&.open
height: 100%
width: 100%
position: fixed
.slideout-wrapper
z-index: 100
height: 100vh
right: 0
position: fixed
display: flex
border: 1px solid rgba(152, 161, 192, 0.24)
box-shadow: rgba(0, 0, 0, 0.24) 12px 16px 24px, rgba(0, 0, 0, 0.24) 12px 8px 12px, rgba(0, 0, 0, 0.32) 4px 4px 8px
transition: margin-right 250ms ease 0s
margin-right: -300px
background-color: #2D2D2D
&.open
margin-right: 0
.slideout-panel
width: 300px
height: 100%
padding: 24px
.slideout-icon
cursor: pointer
&:hover, &:active, &:focus
background-color: lighten(#2D2D2D, 20%)
svg
font-size: 30px
</style>
+13 -2
View File
@@ -14,12 +14,23 @@ import { library } from '@fortawesome/fontawesome-svg-core'
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
/* 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";
/* 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)
+10
View File
@@ -22,6 +22,16 @@ const router = createRouter({
name: "Test",
component: () => import("../views/TestView.vue"),
},
{
path: "/walletconnect",
name: "WalletConnect",
component: () => import("../views/WalletConnectView.vue"),
},
{
path: "/wagmi",
name: "Wagmi",
component: () => import("../views/WagmiView.vue"),
},
],
});
+4 -1
View File
@@ -53,6 +53,9 @@ export const useRewardLockerStore = defineStore("rewardlocker", {
},
async getTotalRewardsOf(address, rounds) {
return await this.contract.methods.getTotalRewardsOf(address, rounds).call();
},
},
async stakeToBeSecured(amount, deadline, v, r, s) {
return await this.contract.methods.stakeToBeSecured(amount, deadline, v,r,s)
}
},
});
+4 -1
View File
@@ -131,6 +131,9 @@ export const useTokenStore = defineStore("token", {
const web3 = new Web3(window.ethereum);
const contract = new web3.eth.Contract(activeToken.abi, contractAddress);
return contract;
},
},
async nonces(userAddress) {
return this.memeToken.contract.methods.nonces(userAddress).call();
}
},
});
+4 -3
View File
@@ -46,10 +46,11 @@ export const useWalletStore = defineStore("wallet", {
this.web3socket = new Web3(
new Web3.providers.WebsocketProvider(`wss://eth-goerli.g.alchemy.com/v2/${goerliKey}`)
);
},
},
// connectWalletV2(connector) {
// this.address = data[0];
// },
connectWallet() {
const tokenStore = useTokenStore();
// if (window.ethereum) {
window.ethereum
.request({ method: "eth_requestAccounts" })
.then((data) => {
+167
View File
@@ -0,0 +1,167 @@
import { defineStore } from "pinia";
import { markRaw } from "vue";
import { useTokenStore } from "./tokens";
import {
createConfig,
configureChains,
mainnet,
getAccount,
getContract,
connect,
getWalletClient,
disconnect,
InjectedConnector,
watchAccount,
} from "@wagmi/core";
import { WalletConnectConnector } from "@wagmi/core/connectors/walletConnect";
import { MetaMaskConnector } from "@wagmi/core/connectors/metaMask";
import { CoinbaseWalletConnector } from "@wagmi/core/connectors/coinbaseWallet";
import { goerli } from "@wagmi/core/chains";
import { publicProvider } from "@wagmi/core/providers/public";
import { alchemyProvider } from "@wagmi/core/providers/alchemy";
export const useWalletStoreV2 = defineStore("walletV2", {
state: () => ({
count: 0,
alchemy: null,
connected: false,
address: null,
web3: null,
provider: null,
client: null,
pubilcClient: null,
walletClient: null,
config: null
}),
getters: {},
actions: {
async init() {
console.log("wallet init");
const goerliKey = import.meta.env.VITE_GOERLI_KEY;
const projectId = "d8e5ecb0353c02e21d4c0867d4473ac5";
const { chains, publicClient, webSocketPublicClient } = configureChains(
[goerli],
[alchemyProvider({ apiKey: goerliKey }), publicProvider()]
);
this.config = createConfig({
autoConnect: true,
connectors: [
new CoinbaseWalletConnector({
chains,
options: {
appName: "wagmi demo",
},
}),
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,
});
// await this.isConnected();
// const goerliKey = import.meta.env.VITE_GOERLI_KEY;
// if (this.connected) {
// const web3 = new Web3(window.ethereum);
// this.web3 = markRaw(web3);
// console.log("hierabc");
// window.ethereum.on("accountsChanged", async (data) => {
// console.log("accountsChanged", data);
// console.log("data", data);
// if (data.length > 0) {
// this.address = data[0];
// this.connected = true;
// } else {
// this.address = null;
// this.connected = false;
// }
// });
// // provider = new ethers.BrowserProvider(window.ethereum);
// } else {
// const url = `https://eth-goerli.g.alchemy.com/v2/${goerliKey}`;
// this.web3 = new Web3(url);
// // provider = new ethers.AlchemyProvider("goerli", goerliKey);
// }
// //Websocket
// this.web3socket = new Web3(
// new Web3.providers.WebsocketProvider(`wss://eth-goerli.g.alchemy.com/v2/${goerliKey}`)
// );
},
// connectWalletV2(connector) {
// this.address = data[0];
// },
async connectWallet(connector) {
console.log("connector.name", connector.name);
// if (!account.isConnected) {
const connection = await connect({
chainId: goerli.id,
connector: connector,
});
// this.address = connection.account;
},
async getTokenBalance(token) {
const tokenStore = useTokenStore();
const contract = tokenStore.getTokenContract(token);
const result = await contract.methods.balanceOf(this.address).call();
return result;
},
async isConnected() {
try {
this.loading = true;
if (!window.ethereum) {
console.warn("Metamask not installed"), (this.connected = false);
return;
}
const accounts = await window.ethereum.request({ method: "eth_accounts" });
if (accounts.length) {
this.connected = true;
this.address = accounts[0];
console.log(`You're connected to: ${accounts[0]}`);
// const web3 = new Web3(window.ethereum);
// const tokenStore = useTokenStore();
// console.log("tokenStore.activeToken", tokenStore.activeToken);
// if (tokenStore.activeToken.contractAddress) {
// tokenStore.activeToken.balance = await this.getTokenBalance(
// tokenStore.activeToken
// );
// tokenStore.activeToken.allowance = await tokenStore.allowance();
// }
// tokenStore.memeBurner.contract = new web3.eth.Contract(
// tokenStore.memeBurner.config.abi,
// tokenStore.memeBurner.config.contractAddress
// );
} else {
console.log("Metamask is not connected");
this.connected = false;
}
} catch (error) {
console.log("error", error);
} finally {
this.loading = false;
return this.connected;
}
},
},
persist: true,
});
+178 -4
View File
@@ -5,6 +5,8 @@
<button @click="sacrificeMeme">sacrifice Meme</button>
<button @click="approveMeme1">approve Meme1</button>
<button @click="tokenStore.approveToken(MemeBurnerJson, 10)">wallet approve</button>
<button @click="stake">stake</button>
<button @click="">unstake</button>
</div>
</template>
@@ -34,6 +36,8 @@ const web3 = ref(null);
const contractMeme2 = ref(null);
const contractMeme1 = ref(null);
const contractBurner = ref(null);
const contractBloodline = ref(null);
const rewardlocker = ref(null);
onMounted(async () => {
web3.value = new Web3(window.ethereum);
@@ -43,9 +47,27 @@ onMounted(async () => {
console.log("accounts", accounts);
web3.value.eth.Contract.defaultAccount = accounts[0];
contractMeme1.value = new web3.value.eth.Contract(Meme1Json.abi, Meme1Json.contractAddress);
contractMeme2.value = new web3.value.eth.Contract(Meme2Json.abi, Meme2Json.contractAddress);
contractBurner.value = new web3.value.eth.Contract(MemeBurnerJson.abi, MemeBurnerJson.contractAddress);
contractMeme1.value = new web3.value.eth.Contract(
Meme1Json.abi,
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() {
@@ -92,7 +114,10 @@ async function mintToken2() {
async function sacrificeMeme() {
const allowance = await contractMeme1.value.methods
.allowance(web3.value.eth.Contract.defaultAccount, MemeBurnerJson.contractAddress)
.allowance(
web3.value.eth.Contract.defaultAccount,
MemeBurnerJson.contractAddress
)
.call();
console.log("allowance", allowance);
var reward = await contractBurner.value.methods
@@ -100,5 +125,154 @@ async function sacrificeMeme() {
.call({ from: web3.value.eth.Contract.defaultAccount });
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));
</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>