Skip to content

Commit

Permalink
Merge pull request #176 from vu3th/fix/enable-dapp-browser
Browse files Browse the repository at this point in the history
Fix: Enable dapp browser
  • Loading branch information
johnson86tw committed Apr 30, 2024
2 parents 9266f9d + 2e0a70f commit c3929aa
Show file tree
Hide file tree
Showing 11 changed files with 112 additions and 83 deletions.
12 changes: 6 additions & 6 deletions app/components/content/Eip6963.client.vue
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
<script setup lang="ts">
import { useVueDapp, shortenAddress, type ConnectorName, RDNS } from '@vue-dapp/core'
import { useVueDapp, shortenAddress, RdnsEnum, type ConnectorName, type RDNS } from '@vue-dapp/core'
import { useVueDappModal } from '@vue-dapp/modal'
const { providerDetails, wallet, address, status, connectTo, disconnect, error, isConnected } = useVueDapp()
const providerList = computed(() => {
return providerDetails.value.slice().sort((a, b) => {
if (a.info.rdns === RDNS.rabby) return -1
if (b.info.rdns === RDNS.rabby) return 1
if (a.info.rdns === RDNS.metamask) return -1
if (b.info.rdns === RDNS.metamask) return 1
if (a.info.rdns === RdnsEnum.rabby) return -1
if (b.info.rdns === RdnsEnum.rabby) return 1
if (a.info.rdns === RdnsEnum.metamask) return -1
if (b.info.rdns === RdnsEnum.metamask) return 1
return 0
})
})
async function onClickWallet(connName: ConnectorName, rdns?: RDNS | string) {
async function onClickWallet(connName: ConnectorName, rdns?: RDNS) {
useVueDappModal().close()
await connectTo(connName, { rdns })
}
Expand Down
12 changes: 6 additions & 6 deletions app/content/eip-6963.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,22 +28,22 @@ Using window events to announce [EIP-1193](https://eips.ethereum.org/EIPS/eip-11
::code-group

```ts [setup script]
import { useVueDapp, shortenAddress, type ConnectorName, RDNS } from '@vue-dapp/core'
import { useVueDapp, shortenAddress, RdnsEnum, type ConnectorName, type RDNS } from '@vue-dapp/core'
import { useVueDappModal } from '@vue-dapp/modal'

const { providerDetails, wallet, address, status, connectTo, disconnect, error, isConnected } = useVueDapp()

const providerList = computed(() => {
return providerDetails.value.slice().sort((a, b) => {
if (a.info.rdns === RDNS.rabby) return -1
if (b.info.rdns === RDNS.rabby) return 1
if (a.info.rdns === RDNS.metamask) return -1
if (b.info.rdns === RDNS.metamask) return 1
if (a.info.rdns === RdnsEnum.rabby) return -1
if (b.info.rdns === RdnsEnum.rabby) return 1
if (a.info.rdns === RdnsEnum.metamask) return -1
if (b.info.rdns === RdnsEnum.metamask) return 1
return 0
})
})

async function onClickWallet(connName: ConnectorName, rdns?: RDNS | string) {
async function onClickWallet(connName: ConnectorName, rdns?: RDNS) {
useVueDappModal().close()
await connectTo(connName, { rdns })
}
Expand Down
4 changes: 4 additions & 0 deletions app/pages/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ const items = computed<Item[]>(() => [
name: 'Connector',
value: wallet.connectorName ?? 'N/A',
},
{
name: 'Provider Target',
value: wallet.providerTarget ?? 'N/A',
},
{
name: 'Provider Name',
value: wallet.providerInfo?.name ?? 'N/A',
Expand Down
69 changes: 36 additions & 33 deletions packages/core/src/browserWalletConnector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import {
ConnectOptions,
RDNS,
EIP6963ProviderDetail,
ProviderTarget,
EIP6963ProviderInfo,
} from './types'
import {
AddChainError,
Expand Down Expand Up @@ -35,23 +37,10 @@ export class BrowserWalletConnector extends Connector<EIP1193Provider, BrowserWa
useEIP6963().subscribe()
}

async connect(options?: ConnectOptions) {
const { timeout, rdns, isWindowEthereum } = options ?? {
timeout: undefined,
rdns: undefined,
isWindowEthereum: false,
}

let provider, info
async connect(options: ConnectOptions) {
const { target, rdns, timeout } = options

if (isWindowEthereum) {
provider = this.getWindowEthereumProvider()
if (!provider) throw new ProviderNotFoundError('window.ethereum not found')
} else {
const { provider: _provider, info: _info } = this.getProvider(rdns)
provider = _provider
info = _info
}
const { provider, info } = this.getProvider(target, rdns)

let accounts, chainId

Expand Down Expand Up @@ -90,30 +79,44 @@ export class BrowserWalletConnector extends Connector<EIP1193Provider, BrowserWa
}
}

getWindowEthereumProvider(): EIP1193Provider | null {
getProvider(
target?: ProviderTarget,
rdns?: RDNS | string,
): { provider: EIP1193Provider; info?: EIP6963ProviderInfo } {
switch (target) {
case 'window.ethereum':
const provider = this.getProviderByWindowEthereum()
if (!provider) throw new ProviderNotFoundError('No provider found by window.ethereum')
return {
provider,
info: undefined,
}
case 'rdns':
if (!rdns) throw new Error('rdns is required')
const res = this.getProviderByRdns(rdns)
if (!res) throw new ProviderNotFoundError('No provider found by the given rdns')
return {
provider: res.provider,
info: res.info,
}
default:
throw new Error('target is required')
}
}

getProviderByWindowEthereum(): EIP1193Provider | undefined {
if (typeof window !== 'undefined' && !!window.ethereum) {
return window.ethereum
}
return null
return undefined
}

getProvider(rdns?: RDNS | string): EIP6963ProviderDetail {
getProviderByRdns(rdns: RDNS | string): EIP6963ProviderDetail | undefined {
const { providerDetails } = useEIP6963()
if (providerDetails.value.length < 1) throw new ProviderNotFoundError('providerDetails.length < 1')

// without rdns, return the first provider
if (!rdns) {
if (providerDetails.value.length >= 1) {
return providerDetails.value[0]
}
} else {
// with rdns, return the provider with the same rdns
const detail = providerDetails.value.find(({ info }) => info.rdns === rdns)
if (!detail) throw new ProviderNotFoundError('rdns not found')
return detail
if (!providerDetails.value.length) {
throw new ProviderNotFoundError('No providerDetails found')
}

throw new ProviderNotFoundError('getProvider failed')
return providerDetails.value.find(({ info }) => info.rdns === rdns)
}

/**
Expand Down
42 changes: 24 additions & 18 deletions packages/core/src/services/connect.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { computed, readonly } from 'vue'
import { useStore } from '../store'
import { ConnectOptions, ConnectorName, RDNS } from '../types'
import { ConnectOptions, ConnectorName, ProviderTarget, RDNS } from '../types'
import { AutoConnectError, ConnectError, ConnectorNotFoundError } from '../errors'
import { normalizeChainId } from '../utils'
import {
Expand All @@ -17,10 +17,11 @@ export function useConnect(pinia?: any) {
walletStore.wallet.error = null
walletStore.wallet.connectorName = null
walletStore.wallet.provider = null
walletStore.wallet.providerInfo = null
walletStore.wallet.connector = null
walletStore.wallet.address = null
walletStore.wallet.chainId = null
walletStore.wallet.providerInfo = null
walletStore.wallet.providerTarget = null
}

async function connectTo(connectorName: ConnectorName | string, options?: ConnectOptions) {
Expand All @@ -34,10 +35,12 @@ export function useConnect(pinia?: any) {
try {
const { provider, account, chainId, info } = await connector.connect(options)

// console.log('useConnect.connectTo -> account', account)

if (connector.name === 'BrowserWallet') {
walletStore.wallet.providerInfo = info!
if (!info) throw new Error('BrowserWallet connector requires provider info')
if (!options?.target) throw new Error('BrowserWallet connector requires target')

walletStore.wallet.providerInfo = info
walletStore.wallet.providerTarget = options?.target
}

walletStore.wallet.connector = connector
Expand Down Expand Up @@ -107,22 +110,25 @@ export function useConnect(pinia?: any) {

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

async function autoConnect(rdns?: RDNS | string, isWindowEthereum = false) {
async function autoConnect(target: ProviderTarget) {
const browserWallet = walletStore.connectors.find(conn => conn.name === 'BrowserWallet')
if (!browserWallet) return

let options = {}

if (isWindowEthereum) {
if (!isWindowEthereumAvailable) return
options = { isWindowEthereum }
} else {
const lastRdns = getLastConnectedBrowserWallet()

rdns = rdns || lastRdns
if (!rdns) return

options = { rdns }
let options: ConnectOptions

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 {
Expand Down
3 changes: 2 additions & 1 deletion packages/core/src/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,11 @@ export const useStore = defineStore('vd-store', () => {
error: null,
connectorName: null,
provider: null,
providerInfo: null,
connector: null,
address: null,
chainId: null,
providerInfo: null,
providerTarget: null,
})

const onDisconnectCallback = ref<OnDisconnectCallback | null>(null)
Expand Down
10 changes: 6 additions & 4 deletions packages/core/src/types/connector.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { EIP1193Provider } from './eip1193'
import { EIP6963ProviderDetail, EIP6963ProviderInfo, RDNS } from './eip6963'
import { EIP6963ProviderInfo } from './eip6963'

export type ConnectorName = 'BrowserWallet' | 'WalletConnect' | 'CoinbaseWallet'
export type ProviderTarget = 'window.ethereum' | 'rdns' // only for BrowserWalletConnector

export type ConnectorData<Provider = any> = {
provider: Provider
Expand All @@ -11,8 +12,8 @@ export type ConnectorData<Provider = any> = {
}

export type ConnectOptions = {
rdns?: string | RDNS
isWindowEthereum?: boolean
target?: ProviderTarget
rdns?: string
timeout?: number
}

Expand All @@ -28,7 +29,8 @@ export abstract class Connector<Provider = EIP1193Provider, Options = any> {

abstract connect(optionsOrTimeout?: ConnectOptions | number): Promise<ConnectorData>

abstract getProvider(): Promise<Provider> | EIP6963ProviderDetail // EIP6963ProviderDetail is returned by BrowserWalletConnector
abstract getProvider(): Promise<Provider> | { provider: EIP1193Provider; info?: EIP6963ProviderInfo }

abstract disconnect(): Promise<void>
abstract onDisconnect(handler: (...args: any[]) => any): void
abstract onAccountsChanged(handler: (accounts: string[]) => any): void
Expand Down
4 changes: 3 additions & 1 deletion packages/core/src/types/eip6963.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import { EIP1193Provider } from './eip1193'

export enum RDNS {
export enum RdnsEnum {
'rabby' = 'io.rabby',
'metamask' = 'io.metamask',
'brave' = 'com.brave.wallet',
'coinbase' = 'com.coinbase.wallet',
'bitget' = 'com.bitget.web3wallet',
}

export type RDNS = string

export interface EIP6963ProviderInfo {
uuid: string
name: string
Expand Down
5 changes: 3 additions & 2 deletions packages/core/src/types/listeners.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Connector, ConnectorName } from './connector'
import { Connector, ConnectorName, ProviderTarget } from './connector'
import { EIP1193Provider } from './eip1193'
import { EIP6963ProviderInfo } from './eip6963'

Expand All @@ -7,10 +7,11 @@ export type ConnWallet = {
error: null
connectorName: ConnectorName
provider: EIP1193Provider
providerInfo: EIP6963ProviderInfo | null // if the connector is not BrowserWallet, this will be null
connector: Connector
address: string
chainId: number
providerInfo: EIP6963ProviderInfo | null // Only available when connectorName is 'BrowserWallet'
providerTarget: ProviderTarget | null // Only available when connectorName is 'BrowserWallet'
}

export type OnConnectedCB = (wallet: ConnWallet) => void
Expand Down
5 changes: 3 additions & 2 deletions packages/core/src/types/wallet.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Connector, ConnectorName } from './connector'
import { Connector, ConnectorName, ProviderTarget } from './connector'
import { EIP1193Provider } from './eip1193'
import { EIP6963ProviderInfo } from './eip6963'

Expand All @@ -9,10 +9,11 @@ export type Wallet = {
error: string | null
connectorName: ConnectorName | null
provider: EIP1193Provider | null
providerInfo: EIP6963ProviderInfo | null
connector: Connector | null
address: string | null
chainId: number | null
providerInfo: EIP6963ProviderInfo | null // Only available when connectorName is 'BrowserWallet'
providerTarget: ProviderTarget | null // Only available when connectorName is 'BrowserWallet'
}

export type OnDisconnectCallback = (...args: any[]) => void
Expand Down
Loading

0 comments on commit c3929aa

Please sign in to comment.