Skip to content

Commit 5afbc9c

Browse files
authored
Sync accounts functionality (#1301)
1 parent 305dded commit 5afbc9c

File tree

3 files changed

+83
-14
lines changed

3 files changed

+83
-14
lines changed

packages/core/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@web3-onboard/core",
3-
"version": "2.8.5",
3+
"version": "2.9.0-alpha.1",
44
"description": "Web3-Onboard makes it simple to connect Ethereum hardware and software wallets to your dapp. Features standardized spec compliant web3 providers for all supported wallets, framework agnostic modern javascript UI with code splitting, CSS customization, multi-chain and multi-account support, reactive wallet state subscriptions and real-time transaction state change notifications.",
55
"keywords": [
66
"Ethereum",

packages/core/src/provider.ts

Lines changed: 70 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@ import { fromEventPattern, Observable } from 'rxjs'
22
import { filter, takeUntil, take, share, switchMap } from 'rxjs/operators'
33
import partition from 'lodash.partition'
44
import { providers } from 'ethers'
5+
import { weiToEth } from '@web3-onboard/common'
6+
import { disconnectWallet$ } from './streams.js'
7+
import { updateAccount, updateWallet } from './store/actions.js'
8+
import { validEnsChain } from './utils.js'
9+
import disconnect from './disconnect.js'
10+
import { state } from './store/index.js'
11+
import { getBlocknativeSdk } from './services.js'
512

613
import type {
714
ChainId,
@@ -14,14 +21,14 @@ import type {
1421
SelectAccountsRequest
1522
} from '@web3-onboard/common'
1623

17-
import { weiToEth } from '@web3-onboard/common'
18-
import { disconnectWallet$ } from './streams.js'
19-
import type { Account, Address, Balances, Ens, WalletState } from './types.js'
20-
import { updateAccount, updateWallet } from './store/actions.js'
21-
import { validEnsChain } from './utils.js'
22-
import disconnect from './disconnect.js'
23-
import { state } from './store/index.js'
24-
import { getBlocknativeSdk } from './services.js'
24+
import type {
25+
Account,
26+
Address,
27+
Balances,
28+
Ens,
29+
WalletPermission,
30+
WalletState
31+
} from './types.js'
2532

2633
export const ethersProviders: {
2734
[key: string]: providers.StaticJsonRpcProvider
@@ -112,6 +119,17 @@ export function trackWallet(
112119

113120
// when account changed, set it to first account and subscribe to events
114121
accountsChanged$.subscribe(async ([address]) => {
122+
// sync accounts with internal state
123+
// in the case of an account has been manually disconnected
124+
try {
125+
await syncWalletConnectedAccounts(label)
126+
} catch (error) {
127+
console.warn(
128+
'Web3Onboard: Error whilst trying to sync connected accounts:',
129+
error
130+
)
131+
}
132+
115133
// no address, then no account connected, so disconnect wallet
116134
// this could happen if user locks wallet,
117135
// or if disconnects app from wallet
@@ -180,11 +198,12 @@ export function trackWallet(
180198
const balanceProm = getBalance(address, chain)
181199
const account = accounts.find(account => account.address === address)
182200

183-
const ensProm = account.ens
184-
? Promise.resolve(account.ens)
185-
: validEnsChain(connectedWalletChain.id)
186-
? getEns(address, chain)
187-
: Promise.resolve(null)
201+
const ensProm =
202+
account && account.ens
203+
? Promise.resolve(account.ens)
204+
: validEnsChain(connectedWalletChain.id)
205+
? getEns(address, chain)
206+
: Promise.resolve(null)
188207

189208
return Promise.all([Promise.resolve(address), balanceProm, ensProm])
190209
})
@@ -390,3 +409,41 @@ export function addNewChain(
390409
]
391410
})
392411
}
412+
413+
export async function getPermissions(
414+
provider: EIP1193Provider
415+
): Promise<WalletPermission[]> {
416+
try {
417+
const permissions = (await provider.request({
418+
method: 'wallet_getPermissions'
419+
})) as WalletPermission[]
420+
421+
return Array.isArray(permissions) ? permissions : []
422+
} catch (error) {
423+
return []
424+
}
425+
}
426+
427+
export async function syncWalletConnectedAccounts(
428+
label: WalletState['label']
429+
): Promise<void> {
430+
const wallet = state.get().wallets.find(wallet => wallet.label === label)
431+
const permissions = await getPermissions(wallet.provider)
432+
const accountsPermissions = permissions.find(
433+
({ parentCapability }) => parentCapability === 'eth_accounts'
434+
)
435+
436+
if (accountsPermissions) {
437+
const { value: connectedAccounts } = accountsPermissions.caveats.find(
438+
({ type }) => type === 'restrictReturnedAccounts'
439+
) || { value: null }
440+
441+
if (connectedAccounts) {
442+
const syncedAccounts = wallet.accounts.filter(({ address }) =>
443+
connectedAccounts.includes(address)
444+
)
445+
446+
updateWallet(wallet.label, { ...wallet, accounts: syncedAccounts })
447+
}
448+
}
449+
}

packages/core/src/types.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,3 +343,15 @@ export type DeviceNotBrowser = {
343343
os: null
344344
browser: null
345345
}
346+
347+
export type WalletPermission = {
348+
id: string
349+
parentCapability: string
350+
invoker: string
351+
caveats: {
352+
type: string
353+
value: string[]
354+
}[]
355+
356+
date: number
357+
}

0 commit comments

Comments
 (0)