diff --git a/apps/block_scout_web/assets/css/theme/_base_variables.scss b/apps/block_scout_web/assets/css/theme/_base_variables.scss index c24e66b96d..0f1188b319 100644 --- a/apps/block_scout_web/assets/css/theme/_base_variables.scss +++ b/apps/block_scout_web/assets/css/theme/_base_variables.scss @@ -215,6 +215,12 @@ $container-max-widths: ( @include _assert-ascending($container-max-widths, "$container-max-widths"); +@media (min-width: 1200px) { + .container { + max-width: 1180px !important; + } + } + // Grid columns // // Set the number of columns and specify the width of the gutters. diff --git a/apps/block_scout_web/assets/js/lib/smart_contract/functions.js b/apps/block_scout_web/assets/js/lib/smart_contract/functions.js index 5c7b5c9127..77b9399e1f 100644 --- a/apps/block_scout_web/assets/js/lib/smart_contract/functions.js +++ b/apps/block_scout_web/assets/js/lib/smart_contract/functions.js @@ -1,4 +1,5 @@ import $ from 'jquery' +import ethNetProps from 'eth-net-props' import { walletEnabled, getCurrentAccount } from './write.js' import { openErrorModal, openWarningModal, openSuccessModal } from '../modals.js' @@ -49,7 +50,8 @@ const readWriteFunction = (element) => { } $.get(url, data, response => $responseContainer.html(response)) - } else { + } else if (action === 'write') { + const chainId = $form.data('chainId') walletEnabled() .then((isWalletEnabled) => { if (isWalletEnabled) { @@ -63,13 +65,22 @@ const readWriteFunction = (element) => { const contractAddress = $form.data('contract-address') const contractAbi = $form.data('contract-abi') - getCurrentAccount() + window.web3.eth.getChainId() + .then(chainIdFromWallet => { + if (chainId !== chainIdFromWallet) { + const networkDisplayNameFromWallet = ethNetProps.props.getNetworkDisplayName(chainIdFromWallet) + const networkDisplayName = ethNetProps.props.getNetworkDisplayName(chainId) + return Promise.reject(new Error(`You connected to ${networkDisplayNameFromWallet} chain in the wallet, but the current instance of Blockscout is for ${networkDisplayName} chain`)) + } else { + return getCurrentAccount() + } + }) .then(currentAccount => { const TargetContract = new window.web3.eth.Contract(contractAbi, contractAddress) TargetContract.methods[functionName](...args).send({ from: currentAccount }) .on('error', function (error) { - openErrorModal(`Error in sending transaction for method "${functionName}"`, error, false) + openErrorModal(`Error in sending transaction for method "${functionName}"`, formatError(error), false) }) .on('transactionHash', function (txHash) { const getTxReceipt = (txHash) => { @@ -84,14 +95,23 @@ const readWriteFunction = (element) => { const txReceiptPollingIntervalId = setInterval(() => { getTxReceipt(txHash) }, 5 * 1000) }) }) + .catch(error => { + openWarningModal('Unauthorized', formatError(error)) + }) } else { - openWarningModal('Unauthorized', 'You haven\'t approved the reading of account list from your MetaMask/Nifty wallet or MetaMask/Nifty wallet is not installed.') + openWarningModal('Unauthorized', 'You haven\'t approved the reading of account list from your MetaMask or MetaMask/Nifty wallet is locked or is not installed.') } }) } }) } +const formatError = (error) => { + let { message } = error + message = message && message.split('Error: ').length > 1 ? message.split('Error: ')[1] : message + return message +} + const container = $('[data-smart-contract-functions]') if (container.length) { diff --git a/apps/block_scout_web/assets/package-lock.json b/apps/block_scout_web/assets/package-lock.json index c4ebf3ceb8..f7e09418ae 100644 --- a/apps/block_scout_web/assets/package-lock.json +++ b/apps/block_scout_web/assets/package-lock.json @@ -2336,6 +2336,11 @@ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" }, + "assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==" + }, "assign-symbols": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", @@ -3095,6 +3100,19 @@ "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" }, + "chai": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", + "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", + "requires": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.2", + "deep-eql": "^3.0.1", + "get-func-name": "^2.0.0", + "pathval": "^1.1.0", + "type-detect": "^4.0.5" + } + }, "chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", @@ -3138,6 +3156,11 @@ "color-name": "^1.0.0" } }, + "check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=" + }, "chokidar": { "version": "2.1.8", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", @@ -4309,6 +4332,14 @@ "mimic-response": "^1.0.0" } }, + "deep-eql": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", + "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "requires": { + "type-detect": "^4.0.0" + } + }, "deep-is": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", @@ -5141,6 +5172,14 @@ } } }, + "eth-net-props": { + "version": "1.0.33", + "resolved": "https://registry.npmjs.org/eth-net-props/-/eth-net-props-1.0.33.tgz", + "integrity": "sha512-RoqoXkY3+ztjdD9EfbjnMapWqfRjUscPon4Vjt48RLHDDYyNmz7LiQ4Qgb4E41PNS7xRoGkQCWJvJRAI9vDsFQ==", + "requires": { + "chai": "^4.2.0" + } + }, "ethereum-bloom-filters": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/ethereum-bloom-filters/-/ethereum-bloom-filters-1.0.7.tgz", @@ -5998,6 +6037,11 @@ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true }, + "get-func-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=" + }, "get-stdin": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", @@ -10252,6 +10296,11 @@ } } }, + "pathval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", + "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=" + }, "pbkdf2": { "version": "3.0.17", "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz", @@ -14330,8 +14379,7 @@ "type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==" }, "type-fest": { "version": "0.8.1", diff --git a/apps/block_scout_web/assets/package.json b/apps/block_scout_web/assets/package.json index b5692f344c..47b990f54b 100644 --- a/apps/block_scout_web/assets/package.json +++ b/apps/block_scout_web/assets/package.json @@ -25,6 +25,7 @@ "bootstrap": "^4.3.1", "chart.js": "^2.9.3", "clipboard": "^2.0.4", + "eth-net-props": "^1.0.33", "highlight.js": "^9.16.2", "highlightjs-solidity": "^1.0.8", "humps": "^2.0.1", diff --git a/apps/block_scout_web/lib/block_scout_web/templates/smart_contract/_functions.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/smart_contract/_functions.html.eex index f5232c6e36..907bb57997 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/smart_contract/_functions.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/smart_contract/_functions.html.eex @@ -15,7 +15,7 @@ render BlockScoutWeb.CommonComponentsView, "_modal_status.html", status: status end %> -