Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: reduce block number queries #3511

Merged
merged 8 commits into from
Jun 29, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,3 @@ export * from './EthereumServices/network'
export * from './EthereumServices/provider'
export * from './EthereumServices/tokenList'
export * from './EthereumServices/nonce'
export * from './EthereumServices/chainState'

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@ import { safeUnreachable } from '@dimensiondev/maskbook-shared'
import { createWeb3 } from './web3'
import * as WalletConnect from './providers/WalletConnect'
import { currentAccountSettings, currentProviderSettings } from '../../../plugins/Wallet/settings'
import { addRecentTransaction } from '../../../plugins/Wallet/services'
import { addRecentTransaction, getWallet } from '../../../plugins/Wallet/services'
import { commitNonce, getNonce, resetNonce } from './nonce'
import { getWalletCached } from './wallet'
import { getGasPrice } from './network'
import { EthereumAddress } from 'wallet.ts'

Expand All @@ -26,10 +25,13 @@ export async function INTERNAL_send(
console.log(new Error().stack)
}

const web3 = createWeb3()
const account = currentAccountSettings.value
const provider = web3.currentProvider as HttpProvider | undefined
const providerType = currentProviderSettings.value
const wallet = providerType === ProviderType.Maskbook ? await getWallet() : null
const web3 = createWeb3({
privKeys: wallet?._private_key_ ? [wallet._private_key_] : [],
})
const provider = web3.currentProvider as HttpProvider | undefined

// unable to create provider
if (!provider) {
Expand Down Expand Up @@ -92,7 +94,6 @@ export async function INTERNAL_send(
// send the transaction
switch (providerType) {
case ProviderType.Maskbook:
const wallet = getWalletCached()
const _private_key_ = wallet?._private_key_
if (!wallet || !_private_key_) throw new Error('Unable to sign transaction.')

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,17 @@ import * as Maskbook from './providers/Maskbook'
import * as MetaMask from './providers/MetaMask'
import * as WalletConnect from './providers/WalletConnect'
import { currentChainIdSettings, currentProviderSettings } from '../../../plugins/Wallet/settings'
import { getWalletCached } from './wallet'

export function createWeb3({
chainId = currentChainIdSettings.value,
providerType = currentProviderSettings.value,
privKeys = [] as string[],
} = {}) {
switch (providerType) {
case ProviderType.Maskbook:
const _private_key_ = getWalletCached()?._private_key_
return Maskbook.createWeb3({
chainId,
privKeys: _private_key_ ? [_private_key_] : [],
privKeys,
})
case ProviderType.MetaMask:
return MetaMask.createWeb3()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,9 @@ export async function restoreBackup(json: object, whoAmI?: ProfileIdentifier) {
})
}

for (const x of data.wallets) {
for (const [i, x] of data.wallets.entries()) {
const record = WalletRecordFromJSONFormat(x)
if (record.mnemonic || record._private_key_) await importNewWallet(record)
if (record.mnemonic || record._private_key_) await importNewWallet(record, i !== 0)
}

for (const x of data.posts) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ function ViewDetailed(props: ViewDetailedProps) {
chainId={getChainIdFromName(asset.chain)}
/>
<Typography className={classes.name}>{asset.token.symbol}</Typography>
{asset.chain !== chainDetailed.chain.toLowerCase() ? (
{asset.chain !== chainDetailed.shortName.toLowerCase() ? (
<Chip className={classes.chain} label={asset.chain} size="small" />
) : null}
</Box>,
Expand Down
2 changes: 2 additions & 0 deletions packages/maskbook/src/plugins/Wallet/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@ export const PLUGIN_IDENTIFIER = 'com.maskbook.wallet'

// Private key at m/purpose'/coin_type'/account'/change
export const HD_PATH_WITHOUT_INDEX_ETHEREUM = "m/44'/60'/0'/0"

export const UPDATE_CHAIN_STATE_DELAY = 30 /* seconds */ * 1000 /* milliseconds */
3 changes: 3 additions & 0 deletions packages/maskbook/src/plugins/Wallet/define.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { WalletConnectQRCodeDialog } from './UI/WalletConnectQRCodeDialog'
import { WalletStatusDialog } from './UI/WalletStatusDialog'
import { WalletRenameWalletDialog } from './UI/RenameWalletDialog'
import { ConnectWalletDialog } from './UI/ConnectWalletDialog'
import { useStartWatchChainState } from './hooks/useStartWatchChainState'

export const WalletPluginDefine: PluginConfig = {
id: PLUGIN_IDENTIFIER,
Expand All @@ -19,6 +20,7 @@ export const WalletPluginDefine: PluginConfig = {
stage: PluginStage.Production,
scope: PluginScope.Internal,
PageComponent() {
useStartWatchChainState()
return (
<>
<SelectWalletDialog />
Expand All @@ -34,6 +36,7 @@ export const WalletPluginDefine: PluginConfig = {
)
},
DashboardComponent() {
useStartWatchChainState()
return (
<>
<SelectWalletDialog />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@ import { useAssetsMerged } from './useAssetsMerged'
export function useAssetsFromChain(tokens: FungibleTokenDetailed[]) {
const chainDetailed = useChainDetailed()
const { value: listOfBalance = [], loading, error, retry } = useTokensBalance(tokens.map((y) => y.address))

return {
value: useAssetsMerged(
// the length not matched in case of error occurs
listOfBalance.length === tokens.length
? listOfBalance.map(
(balance, idx): Asset => ({
chain: chainDetailed?.chain.toLowerCase() ?? 'eth',
chain: chainDetailed?.shortName.toLowerCase() ?? 'eth',
token: tokens[idx],
balance,
}),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { useEffect } from 'react'
import { pollingTask } from '../../../utils'
import { UPDATE_CHAIN_STATE_DELAY } from '../constants'
import { WalletRPC } from '../messages'

const task = pollingTask(
async () => {
await WalletRPC.kickToUpdateChainState()
return false
},
{
autoStart: false,
delay: UPDATE_CHAIN_STATE_DELAY,
},
)

export function useStartWatchChainState() {
useEffect(() => {
// emit an updating request immediately
WalletRPC.updateChainState()
}, [])
return useEffect(() => {
// start the polling task
task.reset()
return () => task.cancel()
}, [])
}
75 changes: 75 additions & 0 deletions packages/maskbook/src/plugins/Wallet/services/chain.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { ChainId, getNetworkTypeFromChainId, ProviderType } from '@dimensiondev/web3-shared'
import { getBalance, getBlockNumber, resetAllNonce } from '../../../extension/background-script/EthereumService'
import { pollingTask, startEffects } from '../../../utils'
import {
currentAccountSettings,
currentBalanceSettings,
currentBlockNumberSettings,
currentChainIdSettings,
currentNetworkSettings,
currentProviderSettings,
} from '../settings'
import { UPDATE_CHAIN_STATE_DELAY } from '../constants'
import { getWallet } from './wallet'

const beats: true[] = []

export async function kickToUpdateChainState() {
beats.push(true)
}

export async function updateChainState(chainId?: ChainId) {
// reset the polling task cause it will be called from service call
resetPoolTask()

// forget those passed beats
beats.length = 0

// update network type
if (chainId) currentNetworkSettings.value = getNetworkTypeFromChainId(chainId)

// update chain state
try {
const wallet = await getWallet()
;[currentBlockNumberSettings.value, currentBalanceSettings.value] = await Promise.all([
getBlockNumber(),
wallet ? getBalance(wallet.address) : currentBalanceSettings.value,
])
} catch (error) {
// do nothing
} finally {
// reset the polling if chain state updated successfully
resetPoolTask()
}
}

let resetPoolTask: () => void = () => {}

const effect = startEffects(import.meta.webpackHot)

// poll the newest chain state
effect(() => {
const { reset, cancel } = pollingTask(
async () => {
if (beats.length <= 0) return false
await updateChainState()
return false
},
{
delay: UPDATE_CHAIN_STATE_DELAY,
},
)
resetPoolTask = reset
return cancel
})

// revalidate chain state if the chainId of current provider was changed
effect(() =>
currentChainIdSettings.addListener((chainId) => {
updateChainState(chainId)
if (currentProviderSettings.value === ProviderType.Maskbook) resetAllNonce()
}),
)

// revalidate chain state if the current wallet was changed
effect(() => currentAccountSettings.addListener(() => updateChainState()))
1 change: 1 addition & 0 deletions packages/maskbook/src/plugins/Wallet/services/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ export * from './erc1155'
export * from './assets'
export * from './transactions'
export * from './recentTransactions'
export * from './chain'
9 changes: 6 additions & 3 deletions packages/maskbook/src/plugins/Wallet/services/wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ export function createMnemonicWords() {

export async function importNewWallet(
rec: PartialRequired<Omit<WalletRecord, 'id' | 'eth_balance' | 'createdAt' | 'updatedAt'>, 'name'>,
slient = false,
) {
const { name, path, mnemonic = [], passphrase = '' } = rec
const address = await getWalletAddress()
Expand Down Expand Up @@ -167,9 +168,11 @@ export async function importNewWallet(
else if (!record_.mnemonic.length && !record_._private_key_)
await t.objectStore('Wallet').put(WalletRecordIntoDB(record))
}
WalletMessages.events.walletsUpdated.sendToAll(undefined)
currentAccountSettings.value = record.address
currentProviderSettings.value = ProviderType.Maskbook
if (!slient) {
WalletMessages.events.walletsUpdated.sendToAll(undefined)
currentAccountSettings.value = record.address
currentProviderSettings.value = ProviderType.Maskbook
}
return address
async function getWalletAddress() {
if (rec.address) return rec.address
Expand Down
25 changes: 17 additions & 8 deletions packages/maskbook/src/utils/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,13 +131,16 @@ export function batchReplace(source: string, group: Array<[string | RegExp, stri
export function pollingTask(
task: () => Promise<boolean>,
{
autoStart = true,
delay = 30 * 1000,
}: {
autoStart?: boolean
delay?: number
} = {},
) {
let canceled = false
let canceled = !autoStart
let timer: NodeJS.Timeout

const runTask = async () => {
if (canceled) return
let stop = false
Expand All @@ -146,15 +149,21 @@ export function pollingTask(
} catch (e) {
console.error(e)
}
if (!stop) timer = setTimeout(runTask, delay)
if (!stop) resetTask()
}
const resetTask = () => {
canceled = false
clearTimeout(timer)
timer = setTimeout(runTask, delay)
}
runTask()
const cancelTask = () => {
canceled = true
}

if (!canceled) runTask()
return {
cancel: () => (canceled = true),
reset: () => {
clearTimeout(timer)
timer = setTimeout(runTask, delay)
},
reset: resetTask,
cancel: cancelTask,
}
}
export function addUint8Array(a: ArrayBuffer, b: ArrayBuffer) {
Expand Down
2 changes: 1 addition & 1 deletion packages/web3-shared/src/constants/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export const CONSTANTS = {
[ChainId.Ropsten]: '0xc778417E063141139Fce010982780140Aa0cD5Ab',
[ChainId.Rinkeby]: '0xc778417E063141139Fce010982780140Aa0cD5Ab',
[ChainId.Kovan]: '0xd0A1E359811322d97991E03f863a0C30C2cF029C',
[ChainId.Gorli]: '',
[ChainId.Gorli]: '0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6',
[ChainId.BSC]: '',
[ChainId.BSCT]: '',
[ChainId.Matic]: '',
Expand Down