Skip to content

Commit

Permalink
feat: automatically load MetaMask wallet, close vu3th#80
Browse files Browse the repository at this point in the history
  • Loading branch information
johnson86tw committed Oct 21, 2022
1 parent 7dd5d5d commit 69c17ee
Show file tree
Hide file tree
Showing 7 changed files with 128 additions and 57 deletions.
27 changes: 15 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,20 +42,23 @@ Step 2. By default, VueDapp includes `Mainnet` and `Goerli` networks, but you ca

```javascript
app.use(VueDapp, {
autoConnect: true, // Automatically connect MetaMask wallet when the page is loaded
networks: {
80001: {
chainId: ethers.utils.hexValue(80001),
blockExplorerUrls: ['https://mumbai.polygonscan.com/'],
chainName: 'Mumbai',
rpcUrls: ['https://rpc-mumbai.maticvigil.com/'],
nativeCurrency: {
name: 'Mumbai',
decimals: 18,
symbol: 'MATIC',
},
chainId: ethers.utils.hexValue(80001),
blockExplorerUrls: ['https://mumbai.polygonscan.com/'],
chainName: 'Mumbai',
rpcUrls: ['https://rpc-mumbai.maticvigil.com/'],
nativeCurrency: {
name: 'Mumbai',
decimals: 18,
symbol: 'MATIC',
},
},
42161: {
...
},
1336: {
...
}
},
});

```
Expand Down
41 changes: 22 additions & 19 deletions demo/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,29 @@ import { ethers } from 'ethers'
const app = createApp(App)

app.use(VueDapp, {
80001: {
chainId: ethers.utils.hexValue(80001),
blockExplorerUrls: ['https://mumbai.polygonscan.com/'],
chainName: 'Mumbai',
rpcUrls: ['https://rpc-mumbai.maticvigil.com/'],
nativeCurrency: {
name: 'Mumbai',
decimals: 18,
symbol: 'MATIC',
autoConnect: true,
networks: {
80001: {
chainId: ethers.utils.hexValue(80001),
blockExplorerUrls: ['https://mumbai.polygonscan.com/'],
chainName: 'Mumbai',
rpcUrls: ['https://rpc-mumbai.maticvigil.com/'],
nativeCurrency: {
name: 'Mumbai',
decimals: 18,
symbol: 'MATIC',
},
},
},
42161: {
chainId: ethers.utils.hexValue(42161),
blockExplorerUrls: ['https://arbiscan.io'],
chainName: 'Arbitrum One',
rpcUrls: ['https://arb1.arbitrum.io/rpc'],
nativeCurrency: {
name: 'Arbitrum',
symbol: 'ETH',
decimals: 18,
42161: {
chainId: ethers.utils.hexValue(42161),
blockExplorerUrls: ['https://arbiscan.io'],
chainName: 'Arbitrum One',
rpcUrls: ['https://arb1.arbitrum.io/rpc'],
nativeCurrency: {
name: 'Arbitrum',
symbol: 'ETH',
decimals: 18,
},
},
},
})
Expand Down
27 changes: 15 additions & 12 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,23 @@ Step 2. By default, VueDapp includes `Mainnet` and `Goerli` networks, but you ca

```javascript
app.use(VueDapp, {
autoConnect: true, // Automatically connect MetaMask wallet when the page is loaded
networks: {
80001: {
chainId: ethers.utils.hexValue(80001),
blockExplorerUrls: ['https://mumbai.polygonscan.com/'],
chainName: 'Mumbai',
rpcUrls: ['https://rpc-mumbai.maticvigil.com/'],
nativeCurrency: {
name: 'Mumbai',
decimals: 18,
symbol: 'MATIC',
},
chainId: ethers.utils.hexValue(80001),
blockExplorerUrls: ['https://mumbai.polygonscan.com/'],
chainName: 'Mumbai',
rpcUrls: ['https://rpc-mumbai.maticvigil.com/'],
nativeCurrency: {
name: 'Mumbai',
decimals: 18,
symbol: 'MATIC',
},
},
1336: {
...
}
42161: {
...
},
},
});

```
Expand Down
53 changes: 43 additions & 10 deletions src/components/Board.vue
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
<script lang="ts">
import { computed, defineComponent } from 'vue'
import { computed, defineComponent, inject, onMounted } from 'vue'
import Modal from './Modal.vue'
import Loader from './Loader.vue'
import WalletConnectIcon from './logos/WalletConnect.vue'
import MetaMaskIcon from './logos/MetaMask.vue'
import CoinbaseWallet from './logos/CoinbaseWallet.vue'
import { useBoard } from '../composables/useBoard'
import { useWallet } from '../composables/useWallet'
import { Connector } from '../wallets'
import { Connector, MetaMaskConnector } from '../wallets'
export default defineComponent({
components: {
Expand All @@ -31,20 +31,50 @@ export default defineComponent({
},
setup(props) {
const { boardOpen, close } = useBoard()
const { connectWith, wallet } = useWallet()
const { connectWith, wallet, autoConnect } = useWallet()
const walletItemClass = computed(() =>
props.dark ? 'wallet-item--dark' : 'wallet-item',
)
const connectors = props.connectors as Connector[]
const isAutoConnect = inject('autoConnect')
if (isAutoConnect) {
onMounted(async () => {
const metaMaskConnector = connectors.find(
(connector) => connector.name === 'metaMask',
) as MetaMaskConnector
if (metaMaskConnector) {
try {
await autoConnect(metaMaskConnector)
} catch (err) {
console.error(
'AutoConnectError: Failed to connect to MetaMask',
err,
)
}
} else {
console.error(
'AutoConnectError: MetaMask connector not found (you should add MetaMask connector so theautoConnect can work)',
)
}
})
}
const onClickWallet = (connector: Connector) => {
connectWith(connector)
close()
}
return {
isAutoConnect,
boardOpen,
wallet,
connectors,
walletItemClass,
connectWith,
onClickWallet,
close,
}
},
Expand All @@ -55,10 +85,7 @@ export default defineComponent({
<Modal :modalOpen="boardOpen" @close="close" :dark="dark">
<div v-click-outside="close">
<div v-for="(connector, i) in connectors" :key="connector.name">
<div
:class="walletItemClass"
@click="connectWith(connector) && close()"
>
<div :class="walletItemClass" @click="onClickWallet(connector)">
<div class="item">
<MetaMaskIcon v-if="connector.name === 'metaMask'" class="logo" />
<WalletConnectIcon
Expand Down Expand Up @@ -86,7 +113,10 @@ export default defineComponent({
</Modal>

<slot name="connecting">
<Modal :modalOpen="wallet.status === 'connecting'" :dark="dark">
<Modal
:modalOpen="wallet.status === 'connecting' && !isAutoConnect"
:dark="dark"
>
<div class="loading-modal" v-if="wallet.status === 'connecting'">
<p>Connecting...</p>
<p class="mt-4">Approve or reject request using your wallet</p>
Expand All @@ -95,7 +125,10 @@ export default defineComponent({
</slot>

<slot name="loading">
<Modal :modalOpen="wallet.status === 'loading'" :dark="dark"></Modal>
<Modal
:modalOpen="wallet.status === 'loading' && !isAutoConnect"
:dark="dark"
></Modal>
</slot>
</template>

Expand Down
10 changes: 9 additions & 1 deletion src/composables/useWallet.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { reactive, markRaw } from 'vue'
import { providers } from 'ethers'
import { Connector } from '../wallets'
import { Connector, MetaMaskConnector } from '../wallets'
import { useEthers } from './useEthers'

export type ConnectionStatus = 'none' | 'connecting' | 'loading' | 'connected'
Expand Down Expand Up @@ -133,6 +133,13 @@ export function useWallet(options: useWalletOptions = { useEthers: true }) {
clearWallet()
}

async function autoConnect(metaMaskConnector: MetaMaskConnector) {
const isConnected = await MetaMaskConnector.checkConnection()
if (isConnected) {
await connectWith(metaMaskConnector)
}
}

function onDisconnect(callback: OnDisconnectCallback) {
callbacks.onDisconnectCallback = callback
}
Expand All @@ -150,6 +157,7 @@ export function useWallet(options: useWalletOptions = { useEthers: true }) {

connectWith,
disconnect,
autoConnect,

onDisconnect,
onAccountsChanged,
Expand Down
16 changes: 13 additions & 3 deletions src/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,21 @@ import { AddEthereumChainParameter } from './wallets'
import { useEthers } from './composables/useEthers'
import { NETWORK_DETAILS } from './constants'

type Options = {
autoConnect: boolean
networks: {
[key: number]: AddEthereumChainParameter
}
}

export const VueDapp: Plugin = {
install(app, options: { [key: number]: AddEthereumChainParameter }) {
const { availableNetworks } = useEthers()
availableNetworks.value = { ...NETWORK_DETAILS, ...options }
install(app, options: Options) {
if (options.networks) {
const { availableNetworks } = useEthers()
availableNetworks.value = { ...NETWORK_DETAILS, ...options.networks }
}

app.provide('autoConnect', options.autoConnect || false)
app.directive('click-outside', clickOutside)
app.component('vd-board', Board)
app.component('vd-modal', Modal)
Expand Down
11 changes: 11 additions & 0 deletions src/wallets/metaMask.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export interface MetaMaskProvider extends MetaMaskEthereumProvider {
method: string
params?: any[] | undefined
}) => Promise<any>
selectedAddress: string
}

/**
Expand Down Expand Up @@ -69,6 +70,16 @@ export class MetaMaskConnector extends Connector<
super(options)
}

static async checkConnection() {
if (typeof window !== 'undefined' && !!window.ethereum) {
const provider = window.ethereum as MetaMaskProvider
if (provider.selectedAddress) {
return true
}
}
return false
}

async connect() {
let provider = await this.getProvider()

Expand Down

0 comments on commit 69c17ee

Please sign in to comment.