Skip to content

Commit

Permalink
implement future metamask multiple accounts feature
Browse files Browse the repository at this point in the history
  • Loading branch information
torztomasz committed Apr 12, 2023
1 parent 5330e86 commit 1d9531b
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 20 deletions.
10 changes: 6 additions & 4 deletions packages/frontend/src/scripts/ethereumAddressRegistration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { EthereumAddress, StarkKey } from '@explorer/types'
import Cookies from 'js-cookie'

import { REGISTER_ETHEREUM_ADDRESS_BUTTON_ID } from '../view/pages/user/components/UserProfile'
import { Registration } from './keys/keys'
import { getUsersInfo } from './metamask'
import { Wallet } from './peripherals/wallet'

export function initEthereumAddressRegistration() {
Expand All @@ -19,17 +19,19 @@ export function initEthereumAddressRegistration() {
e.preventDefault()
const account = Cookies.get('account')
const starkKey = Cookies.get('starkKey')
const registration = localStorage.getItem('registration')
const usersInfo = getUsersInfo()
const userInfo = account ? usersInfo[account] : undefined

const exchangeAddress = registerButton.dataset.exchangeAddress

if (!account || !starkKey || !registration || !exchangeAddress) {
if (!account || !starkKey || !userInfo || !exchangeAddress) {
throw Error('Missing account, starkKey, registration, or exchangeAddress')
}

await Wallet.sendRegistrationTransaction(
EthereumAddress(account),
StarkKey(starkKey),
Registration.parse(JSON.parse(registration)),
userInfo.registration,
EthereumAddress(exchangeAddress)
)

Expand Down
14 changes: 13 additions & 1 deletion packages/frontend/src/scripts/keys/starkKeyRecovery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { EthereumAddress } from '@explorer/types'
import Cookie from 'js-cookie'

import { RECOVER_STARK_KEY_BUTTON_ID } from '../../view'
import { getUsersInfo } from '../metamask'
import { RecoveredKeys, recoverKeysDydx, recoverKeysMyria } from './recovery'

export function initStarkKeyRecovery() {
Expand All @@ -19,11 +20,22 @@ export function initStarkKeyRecovery() {
registerButton.addEventListener('click', async () => {
const keys = await recoverKeys(account, instanceName)
Cookie.set('starkKey', keys.starkKey.toString())
localStorage.setItem('registration', JSON.stringify(keys.registration))
setToLocalStorage(account, keys)
window.location.href = `/users/${keys.starkKey.toString()}`
})
}

const setToLocalStorage = (account: EthereumAddress, keys: RecoveredKeys) => {
const accountsMap = getUsersInfo()

accountsMap[account.toLowerCase()] = {
starkKey: keys.starkKey,
registration: keys.registration,
}

localStorage.setItem('accountsMap', JSON.stringify(accountsMap))
}

const recoverKeys = (
account: EthereumAddress,
instanceName: InstanceName
Expand Down
69 changes: 54 additions & 15 deletions packages/frontend/src/scripts/metamask.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,24 @@
import { stringAs } from '@explorer/shared'
import { StarkKey } from '@explorer/types'
import Cookie from 'js-cookie'
import { z } from 'zod'

import { Registration } from './keys/keys'

export type UsersInfo = z.infer<typeof UsersInfo>
export const UsersInfo = z.record(
z.object({ starkKey: stringAs(StarkKey), registration: Registration })
)

export const getUsersInfo = (): UsersInfo => {
const usersInfoLocalStorage = localStorage.getItem('accountsMap')

if (!usersInfoLocalStorage) {
return {}
}

return UsersInfo.parse(JSON.parse(usersInfoLocalStorage))
}

export function initMetamask() {
const provider = window.ethereum
Expand All @@ -20,12 +40,7 @@ export function initMetamask() {
return
}

provider
.request({ method: 'eth_accounts' })
.then((accounts) => {
updateAccount((accounts as string[])[0])
})
.catch(console.error)
provider.request({ method: 'eth_accounts' }).catch(console.error)

provider
.request({ method: 'eth_chainId' })
Expand All @@ -35,28 +50,52 @@ export function initMetamask() {
.catch(console.error)

provider.on('accountsChanged', (accounts) => {
updateAccount(accounts[0])
updateAccounts(accounts)
})

provider.on('chainChanged', (chainId) => {
updateChainId(chainId)
})

function updateAccount(account: string | undefined) {
const lower = account?.toLowerCase()
const existing = Cookie.get('account')
if (lower !== existing) {
if (lower !== undefined) {
Cookie.set('account', lower)
function updateAccounts(accounts: string[]) {
deleteDisconnectedAccountsFromUsersInfo(accounts)
const connectedAccount = accounts.at(0)
const currentAccount = Cookie.get('account')

const accountsMap = getUsersInfo()

if (connectedAccount !== currentAccount) {
if (connectedAccount) {
Cookie.set('account', connectedAccount.toString())
const accountMap = accountsMap[connectedAccount]
if (accountMap?.starkKey) {
Cookie.set('starkKey', accountMap.starkKey.toString())
} else {
Cookie.remove('starkKey')
}
} else {
localStorage.removeItem('accountsMap')
Cookie.remove('account')
Cookie.remove('starkKey')
}
Cookie.remove('starkKey')
localStorage.removeItem('registration')
location.reload()
}
}

function deleteDisconnectedAccountsFromUsersInfo(
connectedAccounts: string[]
) {
const usersInfo = getUsersInfo()
Object.keys(usersInfo).forEach((userAccount) => {
if (!connectedAccounts.includes(userAccount)) {
//eslint-disable-next-line @typescript-eslint/no-dynamic-delete
delete usersInfo[userAccount]
}
})

localStorage.setItem('accountsMap', JSON.stringify(usersInfo))
}

const MAINNET_CHAIN_ID = '0x1'
const GANACHE_CHAIN_ID = '0x539'
function updateChainId(chainId: string) {
Expand Down

0 comments on commit 1d9531b

Please sign in to comment.