Skip to content

Commit

Permalink
Merge pull request #183 from vu3th/feat/listeners
Browse files Browse the repository at this point in the history
v1.4.0 Rename listeners
  • Loading branch information
johnson86tw authored May 9, 2024
2 parents 5e83e8c + b628b97 commit 4243800
Show file tree
Hide file tree
Showing 17 changed files with 196 additions and 61 deletions.
21 changes: 21 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# CHANGELOG

## v1.4.0
- Document add Listeners in https://vuedapp.xyz/overview
- Rename listeners
```
onConnected -> watchConnected
onAccountOrChainIdChanged -> watchAddressChainIdChanged
onWalletUpdated,watchConnect -> watchWalletChanged
onDisconnected -> watchDisconnect
```

- Add new listeners
```
watchAddressChanged
watchChainIdChanged
```
- Fix VueDappModal styles

## v1.3.3
- export `useAutoConnect`
4 changes: 2 additions & 2 deletions app/app.vue
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ useHead({
},
})
const { addConnectors, watchConnect, watchDisconnect, onDisconnect, onAccountsChanged } = useVueDapp()
const { addConnectors, watchWalletChanged, watchDisconnect, onDisconnect, onAccountsChanged } = useVueDapp()
if (process.client) {
addConnectors([
new BrowserWalletConnector(),
Expand Down Expand Up @@ -55,7 +55,7 @@ if (process.client) {
const { setWallet, resetWallet } = useEthers()
watchConnect(
watchWalletChanged(
async (wallet: ConnWallet) => {
setWallet(wallet.provider)
},
Expand Down
4 changes: 2 additions & 2 deletions app/components/content/Multicall.vue
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,9 @@ const tokenList = computed(() => {
const balances = ref<{ mainnet: number[]; arbitrum: number[] }>({ mainnet: [], arbitrum: [] })
const { watchConnect, watchDisconnect } = useVueDapp()
const { watchWalletChanged, watchDisconnect } = useVueDapp()
watchConnect(
watchWalletChanged(
async (wallet: ConnWallet) => {
const mainnetBalance = await Promise.all([
mainnetDai.balanceOf(wallet.address),
Expand Down
39 changes: 39 additions & 0 deletions app/content/en/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,45 @@ connectTo("BrowserWallet", {
```


## Listeners

You have two ways to listen to wallet events. If you want to directly listen to EIP-1193 events, you can use the following functions. However, please note that these 3 functions are preferably called once in an app. If called a second time, they will overwrite the previous callback.

```ts
const { onDisconnect, onAccountsChanged, onChainChanged } = useVueDapp()

function onDisconnect(callback: (...args: any[]) => void): void
function onAccountsChanged(callback: (accounts: string[]) => void): void
function onChainChanged(callback: (chainId: number) => void): void
```

If you need to call them in multiple components like Vue.js `watch` and automatically clean up after the component is unmounted, you can use the following functions:

```ts
const {
watchConnected,
watchAddressChanged,
watchChainIdChanged,
watchAddressChainIdChanged,
watchWalletChanged,
watchDisconnect,
} = useVueDapp()
```

The most commonly used one is `watchWalletChanged`. This listener triggers when the wallet connects, the address changes, or the network changes.

If `immediate` is set to true, assuming the wallet is already connected on other pages, it will still execute your program when the component is mounted. For example, if the user has connected on the homepage, when they navigate to other pages, certain programs need to be executed immediately. If `immediate` is not used, switching to another page will not trigger the event because the wallet was already connected on the previous page.

```ts
watchWalletChanged(() => {
// exec...
})
watchWalletChanged(() => {
// exec...
}, {
immediate: true
})
```

The prerequisite for the above usage is that you place the listeners at the router-level components (pages/, views/). If you place them in root components (e.g., app.vue, App.vue), you don't need `immediate` to ensure your program runs when the user connects. This is because when the root component is loaded, the user's wallet will definitely transition from `idle` to `connected`, avoiding the scenario where the status is already `connected` when the component is loaded.
44 changes: 44 additions & 0 deletions app/content/zh-TW/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,47 @@ connectTo("BrowserWallet", {
target: "window.ethereum",
})
```


## Listeners

你有兩種方式可以監聽錢包的事件,若你要直接監聽 EIP-1193 的事件,可以使用以下函式,但需要注意的是,這三個函式最好在一個 app 中調用一次,若調用第二次會將之前的 callback 給覆蓋掉。

```ts
const { onDisconnect, onAccountsChanged, onChainChanged } = useVueDapp()

function onDisconnect(callback: (...args: any[]) => void): void
function onAccountsChanged(callback: (accounts: string[]) => void): void
function onChainChanged(callback: (chainId: number) => void): void
```

若你需要像 Vue.js`watch` 一樣能夠在多個元件中調用,並且在元件 unmounted 後自動清除,那你可以使用下面的函式:

```ts
const {
watchConnected,
watchAddressChanged,
watchChainIdChanged,
watchAddressChainIdChanged,
watchWalletChanged,
watchDisconnect,
} = useVueDapp()
```

最常被使用到的是 `watchWalletChanged`,當錢包連線時、地址更動時或網路更動時,都會觸發這個監聽器。

若使用 `immediate`true,假設錢包早已在其他頁面連線了,它仍會在元件 mounted 的時候執行你的程式。例如使用者已經在首頁連線了,當他進入其他頁面時,需要立即執行某些程式,假設沒有使用 `immediate`,使用者切換到別頁時就不會觸發,因為錢包早已在上一個頁面連線了。

```ts
watchWalletChanged(() => {
// exec...
})
watchWalletChanged(() => {
// exec...
}, {
immediate: true
})
```

上述用法的前提是你將 listener 放在路由層級的元件上(pages/, views/),若你將它們放在根元件(ex. app.vue, App.vue),則不需要 `immediate` 就能確保使用者連線時會執行你的程式,原因在於當根元件被載入時,使用者的錢包一定會從未連線轉換成已連線,不會有當元件載入時狀態就已經是 `connected` 的情況發生。
4 changes: 2 additions & 2 deletions app/pages/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ useHead({
const defaultProvider = new ethers.JsonRpcProvider('https://ethereum-rpc.publicnode.com')
const { wallet, isConnected, disconnect, watchConnect, watchDisconnect } = useVueDapp()
const { wallet, isConnected, disconnect, watchWalletChanged, watchDisconnect } = useVueDapp()
const {
ensName,
Expand All @@ -27,7 +27,7 @@ const {
ignorePreviousFetch: ignorePreviousFetchBalance,
} = useBalance(defaultProvider)
watchConnect(
watchWalletChanged(
(wallet: ConnWallet) => {
fetchEnsName(wallet.address)
fetchBalance(wallet.address)
Expand Down
2 changes: 1 addition & 1 deletion lerna.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"$schema": "node_modules/lerna/schemas/lerna-schema.json",
"version": "1.3.3",
"version": "1.4.0-alpha.0",
"npmClient": "pnpm",
"packages": ["packages/*", "demo/*", "docs/*", "app/*"]
}
4 changes: 2 additions & 2 deletions packages/coinbase/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@vue-dapp/coinbase",
"version": "1.3.3",
"version": "1.4.0-alpha.0",
"description": "Empower dapp developers with Vue integration for crypto wallets",
"repository": "https://github.com/vu3th/vue-dapp",
"bugs": {
Expand Down Expand Up @@ -45,7 +45,7 @@
},
"devDependencies": {
"@vitejs/plugin-vue": "5.0.3",
"@vue-dapp/core": "^1.3.3",
"@vue-dapp/core": "^1.4.0-alpha.0",
"typescript": "^5.3.3",
"vite": "5.2.9"
},
Expand Down
2 changes: 1 addition & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@vue-dapp/core",
"version": "1.3.3",
"version": "1.4.0-alpha.0",
"description": "Empower dapp developers with Vue integration for crypto wallets",
"repository": "https://github.com/vu3th/vue-dapp",
"bugs": {
Expand Down
107 changes: 70 additions & 37 deletions packages/core/src/services/listeners.ts
Original file line number Diff line number Diff line change
@@ -1,79 +1,112 @@
import { watch, toRaw, onMounted } from 'vue'
import { OnConnectedCB, OnAccountOrChainIdChangedCB, OnWalletUpdatedCB, OnDisconnectedCB } from '../types'
import { OnConnectedCB, OnDisconnectedCB } from '../types'
import { useConnect } from './connect'
import { assertConnected } from '../utils/assert'

export function useListeners(pinia?: any) {
const { isConnected, address, chainId, wallet } = useConnect(pinia)

function onConnected(callback: OnConnectedCB) {
function watchConnected(callback: OnConnectedCB, options?: { immediate: boolean }) {
if (options?.immediate) {
onMounted(() => {
if (isConnected.value) {
assertConnected(wallet, 'listeners - watchConnected - immediate')
callback && callback(toRaw(wallet))
}
})
}

return watch(isConnected, (val, oldVal) => {
if (val && !oldVal) {
assertConnected(wallet, 'useListeners - onConnected')
assertConnected(wallet, 'listeners - watchConnected - watch')
callback && callback(toRaw(wallet))
}
})
}

function onAccountOrChainIdChanged(callback: OnAccountOrChainIdChangedCB) {
const unwatchAddress = watch(address, (val, oldVal) => {
function watchAddressChanged(callback: OnConnectedCB, options?: { immediate: boolean }) {
if (options?.immediate) {
onMounted(() => {
if (isConnected.value) {
assertConnected(wallet, 'listeners - watchAddressChanged - immediate')
callback && callback(toRaw(wallet))
}
})
}

return watch(address, (val, oldVal) => {
if (oldVal && val) {
assertConnected(wallet, 'useListeners - onAccountOrChainIdChanged - address')
assertConnected(wallet, 'listeners - watchAddressChanged - watch')
callback && callback(toRaw(wallet))
}
})
}

const unwatchChainId = watch(chainId, (val, oldVal) => {
function watchChainIdChanged(callback: OnConnectedCB, options?: { immediate: boolean }) {
if (options?.immediate) {
onMounted(() => {
if (isConnected.value) {
assertConnected(wallet, 'listeners - watchChainIdChanged - immediate')
callback && callback(toRaw(wallet))
}
})
}

return watch(chainId, (val, oldVal) => {
if (val && oldVal) {
assertConnected(wallet, 'useListeners - onAccountOrChainIdChanged - chainId')
assertConnected(wallet, 'listeners - watchChainIdChanged - watch')
callback && callback(toRaw(wallet))
}
})
}

return () => {
unwatchAddress()
unwatchChainId()
function watchAddressChainIdChanged(callback: OnConnectedCB, options?: { immediate: boolean }) {
if (options?.immediate) {
onMounted(() => {
if (isConnected.value) {
assertConnected(wallet, 'listeners - watchAddressChainIdChanged - immediate')
callback && callback(toRaw(wallet))
}
})
}
}

function onWalletUpdated(callback: OnWalletUpdatedCB) {
const unwatchConnected = onConnected(callback)
const unwatchAccountOrChainId = onAccountOrChainIdChanged(callback)
const unwatchAddress = watchAddressChanged(callback)
const unwatchChainId = watchChainIdChanged(callback)

return () => {
unwatchConnected()
unwatchAccountOrChainId()
unwatchAddress()
unwatchChainId()
}
}

function onDisconnected(callback: OnDisconnectedCB) {
return watch(isConnected, (val, oldVal) => {
if (!val && oldVal) {
callback && callback()
}
})
}

function watchConnect(callback: OnWalletUpdatedCB, options?: { immediate: boolean }) {
function watchWalletChanged(callback: OnConnectedCB, options?: { immediate: boolean }) {
if (options?.immediate) {
onMounted(() => {
if (isConnected.value) {
assertConnected(wallet, 'useListeners - watchConnect - immediate')
assertConnected(wallet, 'listeners - watchWalletChanged - immediate')
callback && callback(toRaw(wallet))
}
})
}

const unwatchConnected = onConnected(callback)
const unwatchAccountOrChainId = onAccountOrChainIdChanged(callback)
const unwatch1 = watchConnected(callback)
const unwatch2 = watchAddressChainIdChanged(callback)

return () => {
unwatchConnected()
unwatchAccountOrChainId()
unwatch1()
unwatch2()
}
}

function watchDisconnect(callback: OnDisconnectedCB) {
function watchDisconnect(callback: OnDisconnectedCB, options?: { immediate: boolean }) {
if (options?.immediate) {
onMounted(() => {
if (!isConnected.value) {
callback && callback()
}
})
}

return watch(isConnected, (val, oldVal) => {
if (!val && oldVal) {
callback && callback()
Expand All @@ -82,11 +115,11 @@ export function useListeners(pinia?: any) {
}

return {
onConnected,
onAccountOrChainIdChanged,
onWalletUpdated, // will be deprecated
onDisconnected, // will be deprecated
watchConnect,
watchConnected,
watchAddressChanged,
watchChainIdChanged,
watchAddressChainIdChanged,
watchWalletChanged,
watchDisconnect,
}
}
5 changes: 1 addition & 4 deletions packages/core/src/types/listeners.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,9 @@ export type ConnWallet = {
connector: Connector
address: string
chainId: number
providerInfo: EIP6963ProviderInfo | null // Only available when connectorName is 'BrowserWallet'
providerTarget: ProviderTarget | null // Only available when connectorName is 'BrowserWallet'
providerInfo: EIP6963ProviderInfo | null // Only available when connectorName is 'BrowserWallet' and providerTarget is 'rdns'
}

export type OnConnectedCB = (wallet: ConnWallet) => void
export type OnAccountOrChainIdChangedCB = (wallet: ConnWallet) => void
export type OnDisconnectedCB = () => void

export type OnWalletUpdatedCB = (wallet: ConnWallet) => void
2 changes: 1 addition & 1 deletion packages/core/src/types/wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ export type Wallet = {
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'
providerInfo: EIP6963ProviderInfo | null // Only available when connectorName is 'BrowserWallet' and providerTarget is 'rdns'
}

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

0 comments on commit 4243800

Please sign in to comment.