Skip to content

Commit

Permalink
Merge pull request #182 from vu3th/feat/useAutoConnect
Browse files Browse the repository at this point in the history
feat: useAutoConnect
  • Loading branch information
johnson86tw authored May 9, 2024
2 parents d4a3716 + 4d83edb commit a26834d
Show file tree
Hide file tree
Showing 15 changed files with 212 additions and 240 deletions.
12 changes: 10 additions & 2 deletions app/app.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import '@vue-dapp/modal/dist/style.css'
// import { CoinbaseWalletConnector } from '@vue-dapp/coinbase'
import { darkTheme, lightTheme, type GlobalThemeOverrides } from 'naive-ui'
import { useAppStore } from './stores/appStore'
const lightThemeOverrides: GlobalThemeOverrides = {
common: {
Expand All @@ -21,7 +22,7 @@ useHead({
},
})
const { addConnectors, watchConnect, watchDisconnect } = useVueDapp()
const { addConnectors, watchConnect, watchDisconnect, onDisconnect, onAccountsChanged } = useVueDapp()
if (process.client) {
addConnectors([
new BrowserWalletConnector(),
Expand All @@ -46,6 +47,11 @@ if (process.client) {
// }),
])
}
if (process.client) {
onAccountsChanged(() => {
console.log('Disconnected')
})
}
const { setWallet, resetWallet } = useEthers()
Expand All @@ -67,6 +73,8 @@ const hideConnectingModal = computed(() => {
if (route.path === '/eip-6963') return true
return false
})
const { darkMode } = storeToRefs(useAppStore())
</script>

<template>
Expand All @@ -76,7 +84,7 @@ const hideConnectingModal = computed(() => {

<NuxtPage />

<VueDappModal :hideConnectingModal="hideConnectingModal"> </VueDappModal>
<VueDappModal :dark="darkMode" :hideConnectingModal="hideConnectingModal" />
</NuxtLayout>
</n-config-provider>
</template>
48 changes: 47 additions & 1 deletion app/layouts/default.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
import { Icon, NuxtLink } from '#components'
import packageJsonCore from '../../packages/core/package.json'
import { sidebarMenu } from '~/core/sidebar'
import { NPopselect, NButton } from 'naive-ui'
import { NPopselect, NButton, NSwitch } from 'naive-ui'
import type { CSSProperties } from 'vue'
import { useAppStore } from '~/stores/appStore'
const headerLeftMenu = [
{
Expand All @@ -28,7 +30,45 @@ const localeOptions = computed(() => {
}))
})
const { darkMode } = storeToRefs(useAppStore())
function toggleDarkMode() {
darkMode.value = !darkMode.value
}
const darkModeRailStyle = ({ focused, checked }: { focused: boolean; checked: boolean }) => {
const style: CSSProperties = {}
if (checked) {
// dark mode
style.background = '#2f2f2f'
} else {
// light mode
style.background = '#f1f1f1'
}
return style
}
const headerRightMenu = [
{
label: () =>
h(
NSwitch,
{
value: darkMode.value,
'onUpdate:value': toggleDarkMode,
size: 'medium',
'rail-style': darkModeRailStyle,
},
{
default: () =>
h(
NButton,
{ size: 'small', text: true, class: 'flex justify-center items-center', focusable: false },
{ default: () => h(Icon, { name: 'i-ion-language', class: 'w-5 h-5' }) },
),
},
),
key: 'language',
},
{
label: () =>
h(
Expand Down Expand Up @@ -172,6 +212,12 @@ watch(
</template>

<style scoped>
/* dark mode switcher box-shadow remove green box-shadow */
:deep(.n-switch:focus .n-switch__rail) {
box-shadow: 0 0 0 0.5px rgba(0, 0, 0, 0.1);
}
/* override header-right-menu padding */
:deep(#header-right-menu .n-menu-item-content) {
padding: 10px;
}
Expand Down
9 changes: 9 additions & 0 deletions app/stores/appStore.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { defineStore } from 'pinia'

export const useAppStore = defineStore('appStore', () => {
const darkMode = ref(false)

return {
darkMode,
}
})
7 changes: 0 additions & 7 deletions packages/core/src/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,13 +128,6 @@ export class ConnectError extends Error {
}
}

export class AutoConnectError extends Error {
name = 'AutoConnectError'
constructor(msg: string) {
super(msg)
}
}

export class AssertConnectedError extends Error {
name = 'AssertConnectedError'
constructor(msg?: string) {
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export * from './utils'
export * from './errors'
export * from './types'
export * from './useVueDapp'
export * from './useAutoConnect'

import VueDappProvider from './VueDappProvider.vue'
export { VueDappProvider }
47 changes: 5 additions & 42 deletions packages/core/src/services/connect.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
import { computed, provide, readonly } from 'vue'
import { computed, readonly } from 'vue'
import { useStore } from '../store'
import { ConnectOptions, ConnectorName, ProviderTarget } from '../types'
import { AutoConnectError, ConnectError, ConnectorNotFoundError } from '../errors'
import { normalizeChainId } from '../utils'
import {
getLastConnectedBrowserWallet,
removeLastConnectedBrowserWallet,
setLastConnectedBrowserWallet,
} from './localStorage'
import { ConnectOptions, ConnectorName } from '../types'
import { ConnectError, ConnectorNotFoundError } from '../errors'
import { isWindowEthereumAvailable, normalizeChainId } from '../utils'
import { removeLastConnectedBrowserWallet, setLastConnectedBrowserWallet } from './localStorage'

export function useConnect(pinia?: any) {
const walletStore = useStore(pinia)
Expand Down Expand Up @@ -105,38 +101,6 @@ export function useConnect(pinia?: any) {
}
}

const isWindowEthereumAvailable = typeof window !== 'undefined' && !!window.ethereum

async function autoConnect(target: ProviderTarget) {
const browserWallet = walletStore.connectors.find(conn => conn.name === 'BrowserWallet')
if (!browserWallet) return

let options: ConnectOptions<'BrowserWallet'>

switch (target) {
case 'window.ethereum':
if (!isWindowEthereumAvailable) return
options = {
target: 'window.ethereum',
}
break
case 'rdns':
const lastRdns = getLastConnectedBrowserWallet()
if (!lastRdns) return

options = { target: 'rdns', rdns: lastRdns }
break
default:
throw new Error('target is required')
}

try {
await connectTo('BrowserWallet', options)
} catch (err: any) {
throw new AutoConnectError(err)
}
}

function onDisconnect(callback: (...args: any[]) => void) {
walletStore.onDisconnectCallback = callback
}
Expand Down Expand Up @@ -169,7 +133,6 @@ export function useConnect(pinia?: any) {
resetWallet,
connectTo,
disconnect,
autoConnect,

onDisconnect,
onAccountsChanged,
Expand Down
84 changes: 84 additions & 0 deletions packages/core/src/useAutoConnect.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { onMounted, ref } from 'vue'
import { useConnect } from './services/connect'
import { ConnectOptions, ProviderTarget } from './types'
import { useConnectors } from './services/connectors'
import { getLastConnectedBrowserWallet } from './services/localStorage'
import { isWindowEthereumAvailable } from './utils'

export function useAutoConnect(pinia?: any) {
const isAutoConnecting = ref(false)
const error = ref<Error | null>(null)

const { connectors } = useConnectors(pinia)
const { connectTo } = useConnect(pinia)

onMounted(async () => {
try {
isAutoConnecting.value = true
if (isMobileAppBrowser()) {
await autoConnect('window.ethereum')
} else {
await autoConnect('rdns')
}
} catch (err: any) {
error.value = err
} finally {
isAutoConnecting.value = false
}
})

async function autoConnect(target: ProviderTarget) {
const browserWallet = connectors.value.find(conn => conn.name === 'BrowserWallet')
if (!browserWallet) return

let options: ConnectOptions<'BrowserWallet'>

switch (target) {
case 'window.ethereum':
if (!isWindowEthereumAvailable) return
options = {
target: 'window.ethereum',
}
break
case 'rdns':
const lastRdns = getLastConnectedBrowserWallet()
if (!lastRdns) return

options = { target: 'rdns', rdns: lastRdns }
break
default:
const err = new Error('target is required')
error.value = err
throw err
}

try {
await connectTo('BrowserWallet', options)
} catch (err: any) {
error.value = err
throw err
}
}

return { isAutoConnecting, error }
}

/**
* Check whether the browser is within a mobile app (such as a WebView) rather than a standalone mobile browser like Chrome App
* @returns boolean
*/
export function isMobileAppBrowser() {
const userAgent = navigator.userAgent

// for ios
if (!userAgent.includes('Safari/') && userAgent.includes('Mobile/')) {
return true
}

// for android
if (userAgent.includes('wv') || userAgent.includes('WebView')) {
return true
}

return false
}
4 changes: 0 additions & 4 deletions packages/core/src/utils/assert.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,6 @@ export function assertConnected(wallet: Wallet, errMsg?: string): asserts wallet
if (wallet.status !== 'connected') throw new AssertConnectedError(errMsg + ' - status')
if (!wallet.connectorName) throw new AssertConnectedError(errMsg + ' - connectorName')
if (!wallet.provider) throw new AssertConnectedError(errMsg + ' - provider')

// if (wallet.connectorName === 'BrowserWallet') {
// if (!wallet.providerInfo) throw new AssertConnectedError(errMsg + ' - providerInfo')
// }
if (!wallet.connector) throw new AssertConnectedError(errMsg + ' - connector')
if (!wallet.address) throw new AssertConnectedError(errMsg + ' - address')
if (!wallet.chainId) throw new AssertConnectedError(errMsg + ' - chainId')
Expand Down
23 changes: 0 additions & 23 deletions packages/core/src/utils/check.ts

This file was deleted.

11 changes: 0 additions & 11 deletions packages/core/src/utils/format.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// import { checkChainId } from './check'

/**
* Convert a number to a hexadecimal value
*/
Expand All @@ -12,15 +10,6 @@ export function shortenAddress(address: string): string {
return address.slice(0, 6) + '...' + address.slice(-4)
}

// export function displayChainName(chainId: number) {
// if (!checkChainId(chainId)) {
// return ''
// }
// // dev
// // const { availableNetworks } = useEthers()
// // return availableNetworks.value[chainId].chainName.toLowerCase()
// }

export function normalizeChainId(chainId: string | number | bigint) {
if (typeof chainId === 'string') return Number.parseInt(chainId, chainId.trim().substring(0, 2) === '0x' ? 16 : 10)
if (typeof chainId === 'bigint') return Number(chainId)
Expand Down
4 changes: 3 additions & 1 deletion packages/core/src/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
export * from './format'
export * from './check'
export * from './assert'

export const isWindowEthereumAvailable = typeof window !== 'undefined' && !!window.ethereum
2 changes: 1 addition & 1 deletion packages/modal/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ function autoConnectErrorHandler(err: any) {
<VueDappModal
dark
v-model="isModalOpen"
autoConnect
auto-connect
autoConnectBrowserWalletIfSolo
@connectError="connectErrorHandler"
@autoConnectError="autoConnectErrorHandler"
Expand Down
Loading

0 comments on commit a26834d

Please sign in to comment.