saepenatus
Version:
Web3-Onboard makes it simple to connect Ethereum hardware and software wallets to your dapp. Features standardised spec compliant web3 providers for all supported wallets, framework agnostic modern javascript UI with code splitting, CSS customization, mul
139 lines (114 loc) • 4.21 kB
text/typescript
import Web3Onboard from '@web3-onboard/core'
import type {
InitOptions,
OnboardAPI,
ConnectOptions,
DisconnectOptions,
WalletState,
ConnectedChain
} from '@web3-onboard/core'
// Not sure why it can't be imported directly without passing for dist
import type { AppState } from '@web3-onboard/core/dist/types'
// We use vue-demi to automatically use the correct reactivity API for both Vue 2 and Vue 3
import { ref, computed, readonly, shallowRef } from 'vue-demi'
import type { SetChainOptions, OnboardComposable } from './types.js'
// Vueuse helper to use the localstorage as a reactive variable
import { useStorage } from '@vueuse/core'
// Vueuse helper to streamline the use of rxjs observables as vue refs
import { useSubscription } from '@vueuse/rxjs'
// Onboard will be kept here to be reused every time that we access the composable
let web3Onboard: OnboardAPI | null = null
// Useful data about the previously connected wallets that will synced with the localstorage
const alreadyConnectedWallets = useStorage<string[]>(
'alreadyConnectedWallets',
[]
)
const lastConnectionTimestamp = useStorage<number>(
'lastWalletConnectionTimestamp',
0
)
// We store the internal onboard state as a shallowRef to have reactivity but with a smaller computational cost compared to a full ref
// Because it is shallow, we must update it every time replacing the entire object
const onboardState = shallowRef<AppState>({} as AppState)
const updateAlreadyConnectedWallets = () => {
alreadyConnectedWallets.value = onboardState.value.wallets.map(
(w: WalletState) => w.label
)
}
const init = (options: InitOptions): OnboardAPI => {
web3Onboard = Web3Onboard(options)
onboardState.value = web3Onboard.state.get()
// To avoid memory leaks, we use only one rxjs subscription to update the internal onboard state
// This subscription will be automatically destroyed when the context is destroyed
useSubscription(
web3Onboard.state.select().subscribe(update => {
onboardState.value = update
updateAlreadyConnectedWallets()
})
)
return web3Onboard
}
const useOnboard = (): OnboardComposable => {
// Raise an error if init() wasn't called
if (!web3Onboard) {
throw new Error('web3Onboard is not initialized')
}
// Wallet related functions and variables
const connectingWallet = ref<boolean>(false)
const wallets = computed(() => onboardState.value.wallets)
const connectedWallet = computed<WalletState | null>(() =>
wallets.value.length > 0 ? wallets.value[0] : null
)
const connectWallet = async (options?: ConnectOptions) => {
connectingWallet.value = true
await (web3Onboard as OnboardAPI).connectWallet(options)
lastConnectionTimestamp.value = Date.now()
connectingWallet.value = false
}
const disconnectWallet = async (wallet: DisconnectOptions) => {
connectingWallet.value = true
await (web3Onboard as OnboardAPI).disconnectWallet(wallet)
updateAlreadyConnectedWallets()
connectingWallet.value = false
}
const disconnectConnectedWallet = async () => {
if (connectedWallet.value) {
await disconnectWallet({ label: connectedWallet.value.label })
}
}
// Chain related functions and variables
const settingChain = ref<boolean>(false)
const connectedChain = computed<ConnectedChain | null>(
() =>
(connectedWallet &&
connectedWallet.value &&
connectedWallet.value.chains[0]) ||
null
)
const getChain = (walletLabel: string) => {
const wallet = onboardState.value.wallets.find(
(w: WalletState) => w.label === walletLabel
)
return (wallet && wallet.chains[0]) || null
}
const setChain = async (options: SetChainOptions) => {
settingChain.value = true
await (web3Onboard as OnboardAPI).setChain(options)
settingChain.value = false
}
return {
alreadyConnectedWallets,
connectWallet,
connectedChain,
connectedWallet,
connectingWallet: readonly(connectingWallet),
disconnectConnectedWallet,
disconnectWallet,
getChain,
lastConnectionTimestamp,
setChain,
settingChain: readonly(settingChain),
wallets
}
}
export { init, useOnboard }