From 861219133e82d21a4905c2ed56050a1cb8ba0126 Mon Sep 17 00:00:00 2001 From: xuwen Date: Fri, 28 May 2021 10:23:27 +0800 Subject: [PATCH] injected web3 support multinetwork --- app/scripts/controllers/alert.js | 3 +- app/scripts/controllers/permissions/index.js | 40 +++++++++++++++---- app/scripts/metamask-controller.js | 3 +- .../account-menu/account-menu.component.js | 5 ++- .../connected-status-indicator.container.js | 3 +- .../loading-network-screen.component.js | 24 +++++++++++ ui/app/selectors/permissions.js | 23 +++++++++-- ui/app/store/actions.js | 21 ++++++---- yarn.lock | 31 ++++++++++---- 9 files changed, 122 insertions(+), 31 deletions(-) diff --git a/app/scripts/controllers/alert.js b/app/scripts/controllers/alert.js index 7fdddcd..95da918 100644 --- a/app/scripts/controllers/alert.js +++ b/app/scripts/controllers/alert.js @@ -1,4 +1,5 @@ import ObservableStore from 'obs-store' +import { decodeBech32Address } from '@alayanetwork/ethereumjs-util' /** * @typedef {Object} AlertControllerInitState @@ -53,7 +54,7 @@ export default class AlertController { preferencesStore.subscribe(({ selectedAddress }) => { const currentState = this.store.getState() - if (currentState.unconnectedAccountAlertShownOrigins && this.selectedAddress !== selectedAddress) { + if (currentState.unconnectedAccountAlertShownOrigins && decodeBech32Address(this.selectedAddress) !== decodeBech32Address(selectedAddress)) { this.selectedAddress = selectedAddress this.store.updateState({ unconnectedAccountAlertShownOrigins: {} }) } diff --git a/app/scripts/controllers/permissions/index.js b/app/scripts/controllers/permissions/index.js index 8d07d51..13180f8 100644 --- a/app/scripts/controllers/permissions/index.js +++ b/app/scripts/controllers/permissions/index.js @@ -22,7 +22,7 @@ import { NOTIFICATION_NAMES, CAVEAT_TYPES, } from './enums' -import {decodeBech32Address, toBech32Address} from "@alayanetwork/ethereumjs-util"; +import { isBech32Address, decodeBech32Address, toBech32Address } from '@alayanetwork/ethereumjs-util' export class PermissionsController { @@ -306,9 +306,15 @@ export class PermissionsController { this.validatePermittedAccounts([account]) const oldPermittedAccounts = this._getPermittedAccounts(origin) + const oldPermittedAccountsHex = oldPermittedAccounts.map((acc) => { + if (isBech32Address(acc)) { + return decodeBech32Address(acc) + } + return acc + }) if (!oldPermittedAccounts) { throw new Error(`Origin does not have 'platon_accounts' permission`) - } else if (oldPermittedAccounts.includes(account)) { + } else if (oldPermittedAccountsHex.includes(decodeBech32Address(account))) { throw new Error('Account is already permitted for origin') } @@ -344,15 +350,20 @@ export class PermissionsController { this.validatePermittedAccounts([account]) const oldPermittedAccounts = this._getPermittedAccounts(origin) + const oldPermittedAccountsHex = oldPermittedAccounts.map((acc) => { + if (isBech32Address(acc)) { + return decodeBech32Address(acc) + } + return acc + }) if (!oldPermittedAccounts) { throw new Error(`Origin does not have 'platon_accounts' permission`) - } else if (!oldPermittedAccounts.includes(account)) { + } else if (!oldPermittedAccountsHex.includes(decodeBech32Address(account))) { throw new Error('Account is not permitted for origin') } let newPermittedAccounts = oldPermittedAccounts - .filter((acc) => acc !== account) - + .filter((acc) => decodeBech32Address(acc) !== decodeBech32Address(account)) if (newPermittedAccounts.length === 0) { this.removePermissionsFor({ [origin]: [ 'platon_accounts' ] }) } else { @@ -382,7 +393,16 @@ export class PermissionsController { const domains = this.permissions.getDomains() const connectedOrigins = Object.keys(domains) - .filter((origin) => this._getPermittedAccounts(origin).includes(account)) + .filter((origin) => { + const permittedAccounts = this._getPermittedAccounts(origin) + const permittedAccountsHex = permittedAccounts.map((acc) => { + if (isBech32Address(acc)) { + return decodeBech32Address(acc) + } + return acc + }) + return permittedAccountsHex.includes(decodeBech32Address(account)) + }) await Promise.all(connectedOrigins.map((origin) => this.removePermittedAccount(origin, account))) } @@ -655,7 +675,13 @@ export class PermissionsController { ?.caveats .find((caveat) => caveat.name === 'exposedAccounts') ?.value - return exposedAccounts?.includes(account) + const accounts = exposedAccounts.map((acc) => { + if (isBech32Address(acc)) { + return decodeBech32Address(acc) + } + return acc + }) + return accounts?.includes(decodeBech32Address(account)) }) .map(([domain]) => domain) diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 8a6a304..b24d12a 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -391,11 +391,12 @@ export default class MetamaskController extends EventEmitter { publicConfigStore.putState(selectPublicState(memState)) } - function selectPublicState ({ isUnlocked, network, provider }) { + function selectPublicState ({ isUnlocked, hrp, network, provider }) { return { isUnlocked, networkVersion: network, chainId: selectChainId({ network, provider }), + hrp: provider ? provider.hrp : hrp, } } return publicConfigStore diff --git a/ui/app/components/app/account-menu/account-menu.component.js b/ui/app/components/app/account-menu/account-menu.component.js index cc3a1eb..c5b5df4 100644 --- a/ui/app/components/app/account-menu/account-menu.component.js +++ b/ui/app/components/app/account-menu/account-menu.component.js @@ -21,6 +21,7 @@ import { } from '../../../helpers/constants/routes' import TextField from '../../ui/text-field' import SearchIcon from '../../ui/search-icon' +import { decodeBech32Address } from '@alayanetwork/ethereumjs-util' export default class AccountMenu extends Component { static contextTypes = { @@ -134,12 +135,12 @@ export default class AccountMenu extends Component { return filteredIdentities.map((identity) => { const isSelected = identity.address === selectedAddress - const simpleAddress = identity.address.substring(2).toLowerCase() + const simpleAddress = identity.address.toLowerCase() const keyring = keyrings.find((kr) => { return kr.accounts.includes(simpleAddress) || kr.accounts.includes(identity.address) }) - const addressDomains = addressConnectedDomainMap[identity.address] || {} + const addressDomains = addressConnectedDomainMap[decodeBech32Address(identity.address)] || {} const iconAndNameForOpenDomain = addressDomains[originOfCurrentTab] return ( diff --git a/ui/app/components/app/connected-status-indicator/connected-status-indicator.container.js b/ui/app/components/app/connected-status-indicator/connected-status-indicator.container.js index 9cdaea0..2897031 100644 --- a/ui/app/components/app/connected-status-indicator/connected-status-indicator.container.js +++ b/ui/app/components/app/connected-status-indicator/connected-status-indicator.container.js @@ -11,6 +11,7 @@ import { getOriginOfCurrentTab, getSelectedAddress, } from '../../../selectors' +import { decodeBech32Address } from '@alayanetwork/ethereumjs-util' const mapStateToProps = (state) => { @@ -18,7 +19,7 @@ const mapStateToProps = (state) => { const addressConnectedDomainMap = getAddressConnectedDomainMap(state) const originOfCurrentTab = getOriginOfCurrentTab(state) - const selectedAddressDomainMap = addressConnectedDomainMap[selectedAddress] + const selectedAddressDomainMap = addressConnectedDomainMap[decodeBech32Address(selectedAddress)] const currentTabIsConnectedToSelectedAddress = Boolean(selectedAddressDomainMap && selectedAddressDomainMap[originOfCurrentTab]) let status diff --git a/ui/app/components/app/loading-network-screen/loading-network-screen.component.js b/ui/app/components/app/loading-network-screen/loading-network-screen.component.js index 413a06d..aed6095 100644 --- a/ui/app/components/app/loading-network-screen/loading-network-screen.component.js +++ b/ui/app/components/app/loading-network-screen/loading-network-screen.component.js @@ -6,6 +6,7 @@ import Button from '../../ui/button' export default class LoadingNetworkScreen extends PureComponent { state = { showErrorScreen: false, + showWarnScreen: true, } static contextTypes = { @@ -69,6 +70,26 @@ export default class LoadingNetworkScreen extends PureComponent { ) } + renderWarnScreenContent = () => { + return ( +
+ { this.context.t('Important Notes') } + Currently Switchd to [] + Do not transfer assets from other networks to the current wallet address! +
+ +
+
+ ) + } + renderErrorScreenContent = () => { const { showNetworkDropdown, setProviderArgs, setProviderType } = this.props @@ -107,7 +128,10 @@ export default class LoadingNetworkScreen extends PureComponent { const { isLoadingNetwork } = this.props if (isLoadingNetwork) { + this.setState({ showWarnScreen: false }) this.setState({ showErrorScreen: true }) + } else { + this.setState({ showWarnScreen: true }) } } diff --git a/ui/app/selectors/permissions.js b/ui/app/selectors/permissions.js index 2053847..dac475c 100644 --- a/ui/app/selectors/permissions.js +++ b/ui/app/selectors/permissions.js @@ -3,6 +3,7 @@ import { getMetaMaskAccountsOrdered, getOriginOfCurrentTab, getSelectedAddress } import { CAVEAT_NAMES, } from '../../../app/scripts/controllers/permissions/enums' +import { decodeBech32Address, isBech32Address } from '@alayanetwork/ethereumjs-util' // selectors @@ -96,7 +97,13 @@ export function getConnectedDomainsForSelectedAddress (state) { forOwn(domains, (domainValue, domainKey) => { const exposedAccounts = getAccountsFromDomain(domainValue) - if (!exposedAccounts.includes(selectedAddress)) { + const accounts = exposedAccounts.map((acc) => { + if (isBech32Address(acc)) { + return decodeBech32Address(acc) + } + return acc + }) + if (!accounts.includes(decodeBech32Address(selectedAddress))) { return } @@ -141,7 +148,9 @@ export function getAddressConnectedDomainMap (state) { accountsMap[domainKey].forEach((address) => { const nameToRender = name || domainKey - + if (isBech32Address(address)) { + address = decodeBech32Address(address) + } addressConnectedIconMap[address] = addressConnectedIconMap[address] ? { ...addressConnectedIconMap[address], [domainKey]: { icon, name: nameToRender } } : { [domainKey]: { icon, name: nameToRender } } @@ -199,7 +208,7 @@ export function getAccountToConnectToActiveTab (state) { const numberOfAccounts = Object.keys(identities).length if (connectedAccounts.length && connectedAccounts.length !== numberOfAccounts) { - if (connectedAccounts.findIndex((address) => address === selectedAddress) === -1) { + if (connectedAccounts.findIndex((address) => decodeBech32Address(address) === decodeBech32Address(selectedAddress)) === -1) { return identities[selectedAddress] } } @@ -213,9 +222,15 @@ export function getOrderedConnectedAccountsForActiveTab (state) { const permissionsHistoryByAccount = permissionsHistory[activeTab.origin]?.['platon_accounts']?.accounts const orderedAccounts = getMetaMaskAccountsOrdered(state) const connectedAccounts = getPermittedAccountsForCurrentTab(state) + const connectedAccountsHex = connectedAccounts.map((acc) => { + if (isBech32Address(acc)) { + return decodeBech32Address(acc) + } + return acc + }) return orderedAccounts - .filter((account) => connectedAccounts.includes(account.address)) + .filter((account) => connectedAccountsHex.includes(decodeBech32Address(account.address))) .map((account) => ({ ...account, lastActive: permissionsHistoryByAccount?.[account.address], diff --git a/ui/app/store/actions.js b/ui/app/store/actions.js index e30d22a..e0333fd 100644 --- a/ui/app/store/actions.js +++ b/ui/app/store/actions.js @@ -1,9 +1,8 @@ import abi from 'human-standard-token-abi' import pify from 'pify' import getBuyEthUrl from '../../../app/scripts/lib/buy-eth-url' -import { checksumAddress } from '../helpers/utils/util' +// import { checksumAddress } from '../helpers/utils/util' import { calcTokenBalance, estimateGas } from '../pages/send/send.utils' -import ethUtil from '@alayanetwork/ethereumjs-util' import { fetchLocale, loadRelativeTimeFormatLocaleData } from '../helpers/utils/i18n-helper' import { getMethodDataAsync } from '../helpers/utils/transactions.util' import { fetchSymbolAndDecimals } from '../helpers/utils/token-util' @@ -11,11 +10,10 @@ import switchDirection from '../helpers/utils/switch-direction' import log from 'loglevel' import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../app/scripts/lib/enums' import { hasUnconfirmedTransactions } from '../helpers/utils/confirm-tx.util' -import { setCustomGasLimit } from '../ducks/gas/gas.duck' import txHelper from '../../lib/tx-helper' import { getEnvironmentType } from '../../../app/scripts/lib/util' import * as actionConstants from './actionConstants' -import { decodeBech32Address } from '@alayanetwork/ethereumjs-util' +import { decodeBech32Address, addHexPrefix, isBech32Address } from '@alayanetwork/ethereumjs-util' import { getPermittedAccountsForCurrentTab, getSelectedAddress, @@ -23,6 +21,7 @@ import { import { switchedToUnconnectedAccount } from '../ducks/alerts/unconnected-account' import { getUnconnectedAccountAlertEnabledness } from '../ducks/metamask/metamask' import { + setCustomGasLimit, fetchBasicGasEstimates, fetchBasicGasAndTimeEstimates, } from '../ducks/gas/gas.duck' @@ -766,7 +765,7 @@ export function signTokenTx (tokenAddress, toAddress, amount, txData) { return (dispatch) => { dispatch(showLoadingIndication()) const token = global.eth.contract(abi).at(tokenAddress) - token.transfer(toAddress, ethUtil.addHexPrefix(amount), txData) + token.transfer(toAddress, addHexPrefix(amount), txData) .catch((err) => { dispatch(hideLoadingIndication()) dispatch(displayWarning(err.message)) @@ -1203,8 +1202,14 @@ export function showAccountDetail (address) { const activeTabOrigin = state.activeTab.origin const selectedAddress = getSelectedAddress(state) const permittedAccountsForCurrentTab = getPermittedAccountsForCurrentTab(state) - const currentTabIsConnectedToPreviousAddress = Boolean(activeTabOrigin) && permittedAccountsForCurrentTab.includes(selectedAddress) - const currentTabIsConnectedToNextAddress = Boolean(activeTabOrigin) && permittedAccountsForCurrentTab.includes(address) + const permittedAccountsForCurrentTabHex = permittedAccountsForCurrentTab.map((acc) => { + if (isBech32Address(acc)) { + return decodeBech32Address(acc) + } + return acc + }) + const currentTabIsConnectedToPreviousAddress = Boolean(activeTabOrigin) && permittedAccountsForCurrentTabHex.includes(decodeBech32Address(selectedAddress)) + const currentTabIsConnectedToNextAddress = Boolean(activeTabOrigin) && permittedAccountsForCurrentTabHex.includes(decodeBech32Address(address)) const switchingToUnconnectedAddress = currentTabIsConnectedToPreviousAddress && !currentTabIsConnectedToNextAddress try { @@ -2198,7 +2203,7 @@ export function loadingMethodDataFinished () { export function getContractMethodData (data = '') { return (dispatch, getState) => { - const prefixedData = ethUtil.addHexPrefix(data) + const prefixedData = addHexPrefix(data) const fourBytePrefix = prefixedData.slice(0, 10) const { knownMethodData } = getState().metamask diff --git a/yarn.lock b/yarn.lock index 25c75d7..77e72d4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -300,10 +300,11 @@ integrity sha512-az1IBp25ycqsv1MVJ+iGZEiC4x9571+usvShWy8dc1LxTSUUsbRpxzOF/uENIgFHC84FpvpDAf/sAOLXq/evvg== "@alayanetwork/inpage-provider@^6.1.0": - version "6.1.0" - resolved "https://registry.yarnpkg.com/@alayanetwork/inpage-provider/-/inpage-provider-6.1.0.tgz#cb131b700d969565a1ba47549d47871192b53a27" - integrity sha512-miB9BDbiypTcpSjHm/xAspuSmjxekpZeuEB596YwXO9Fo9jDkO9ZApYf+vYKFFhXlfXrtrlZTv8ezs7BgE6LMg== + version "6.1.1" + resolved "https://registry.yarnpkg.com/@alayanetwork/inpage-provider/-/inpage-provider-6.1.1.tgz#fd6d2f4916ae152fb218a7936e18305a90318364" + integrity sha512-NXEC+sX3TjVQVw/frdwj884FHiyRhTr86NLjOvEgJvoNXu+Bzyc+3k1m1C8yV2SGMNTAzLyPh/EqdKZ3Ltw4Gw== dependencies: + "@alayanetwork/ethereumjs-util" "^5.2.0" eth-json-rpc-errors "^2.0.2" fast-deep-equal "^2.0.1" json-rpc-engine "^5.1.5" @@ -324,16 +325,32 @@ await-semaphore "^0.1.3" "@alayanetwork/rpc-cap@^3.1.0": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@alayanetwork/rpc-cap/-/rpc-cap-3.1.0.tgz#2baac42dc6a09eba5cdc0bf6b034e59b1a394a64" - integrity sha512-oes+DxX2EIHF9f7loo/csav0lVbYiSfr82N5WnJw03fgW57gD07I+ds+c8tzMHaJV5h0bZ9TNX7EhjJDJwGqYQ== + version "3.1.1" + resolved "https://registry.yarnpkg.com/@alayanetwork/rpc-cap/-/rpc-cap-3.1.1.tgz#02fc4207c7868516f75dd7967cd394f8858622c8" + integrity sha512-DL5E4btWIPjM6ock2BN5+HBG+3aVTdY+SoQbF7TFiltIAY+1Z1+KZsnbSLbJDUHUWx1yZTCAYoiSbNIBsUOMtg== dependencies: "@alayanetwork/controllers" "^3.0.1" + "@alayanetwork/web3-utils" "^0.13.3" + "@types/bn.js" "^4.11.6" eth-rpc-errors "^2.1.1" is-subset "^0.1.1" json-rpc-engine "^5.2.0" uuid "^3.3.2" +"@alayanetwork/web3-utils@^0.13.3": + version "0.13.3" + resolved "https://registry.yarnpkg.com/@alayanetwork/web3-utils/-/web3-utils-0.13.3.tgz#f0563fa5fb09334743fde6ddc176134455e7e931" + integrity sha512-T5fWhFO+R5q/RLU7fPPW8FHA9TkQo2znQAGYdw/u9SpfA+vA/ZmYsgWm4yh+DXPzyPZqEI4w4t5tl3nCKJtevg== + dependencies: + bn.js "4.11.8" + eth-lib "0.2.7" + ethereum-bloom-filters "^1.0.6" + ethjs-unit "0.1.6" + number-to-bn "1.7.0" + randombytes "^2.1.0" + underscore "1.9.1" + utf8 "3.0.0" + "@alayanetwork/web3@^0.1.0": version "0.1.0" resolved "https://registry.yarnpkg.com/@alayanetwork/web3/-/web3-0.1.0.tgz#7c5262b17f499010f6b3af2dc3f4170de0a7ac8b" @@ -2743,7 +2760,7 @@ dependencies: bignumber.js "*" -"@types/bn.js@^4.11.3", "@types/bn.js@^4.11.4": +"@types/bn.js@^4.11.3", "@types/bn.js@^4.11.4", "@types/bn.js@^4.11.6": version "4.11.6" resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-4.11.6.tgz#c306c70d9358aaea33cd4eda092a742b9505967c" integrity sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==