diff --git a/README.md b/README.md index 383139dd..4d92ca18 100644 --- a/README.md +++ b/README.md @@ -43,16 +43,16 @@ yarn add bnc-assist #### Script Tag The library uses [semantic versioning](https://semver.org/spec/v2.0.0.html). -The current version is 0.8.9. +The current version is 0.8.10. There are minified and non-minified versions. Put this script at the top of your `
` ```html - + - + ``` ### Initialize the Library @@ -170,7 +170,7 @@ var config = { txSent: Function, // Transaction has been sent to the network txPending: Function, // Transaction is pending and has been detected in the mempool txSendFail: Function, // Transaction failed to be sent to the network - txStall: Function, // Transaction was sent but not received in the mempool after 30 secs + txStall: Function, // Transaction was sent but not confirmed in the blockchain after 30 secs txFailed: Function, // Transaction failed nsfFail: Function, // User doesn't have enough funds to complete transaction txRepeat: Function, // Warning to user that they might be repeating a transaction @@ -194,7 +194,9 @@ var config = { notificationsPosition: Object || String, // Defines where in the viewport notifications will be positioned. See below: 'Notification Positioning' css: String // Custom css string to overide Assist default styles }, - truffleContract: Boolean, // Set to true if contract object has been instantiated with truffle-contract [false] + timeouts: { + txStall: Number // The number of milliseconds after a transaction has been sent before showing a stall notification if not confirmed in the blockchain + } } ``` diff --git a/package.json b/package.json index 2639b6f1..757efc9c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "bnc-assist", - "version": "0.8.9", + "version": "0.8.10", "description": "Blocknative Assist js library for Dapp developers", "main": "lib/assist.min.js", "scripts": { diff --git a/src/__e2e-tests__/index.test.js b/src/__e2e-tests__/index.test.js index e0a2a523..9743f617 100644 --- a/src/__e2e-tests__/index.test.js +++ b/src/__e2e-tests__/index.test.js @@ -3,7 +3,7 @@ import truffleContract from 'truffle-contract' import convertLibJson, { abi } from '~/__tests__/res/ConvertLib.json' import da from '~/js' import * as websockets from '~/js/helpers/websockets' -import { state, initialState, updateState } from '~/js/helpers/state' +import { initialState, updateState } from '~/js/helpers/state' import { convertLibAddress, @@ -117,13 +117,9 @@ multidepRequire.forEachVersion('web3', (version, Web3) => { let decoratedContract let contract beforeAll(async () => { - state.config.truffleContract = true contract = await getTruffleContract(web3) decoratedContract = assistInstance.Contract(contract) }) - afterAll(() => { - state.config.truffleContract = false - }) test('they can estimate gas of a method call from the decorated contract', async () => { const expected = await contract.convert.estimateGas(1, 2) @@ -134,7 +130,6 @@ multidepRequire.forEachVersion('web3', (version, Web3) => { describe('the user makes a contract method call', () => { let res beforeAll(async () => { - state.config.truffleContract = true res = await decoratedContract.convert(2, 5) }) test('results in the expected response', () => { diff --git a/src/__integration-tests__/initialization/initialization.test.js b/src/__integration-tests__/initialization/initialization.test.js index 3fb882cf..cec182fd 100644 --- a/src/__integration-tests__/initialization/initialization.test.js +++ b/src/__integration-tests__/initialization/initialization.test.js @@ -284,7 +284,9 @@ describe('init is called', () => { notificationsPosition: { mobile: 'top', desktop: 'bottomLeft' }, css: '123' }, - truffleContract: true + timeouts: { + txStall: 1 + } } test(`should not throw`, () => { expect(() => { @@ -326,6 +328,12 @@ describe('init is called', () => { }) }) +beforeEach(() => { + jest.spyOn(console, 'error') + // eslint-disable-next-line + console.error.mockImplementation(() => {}) +}) + beforeAll(() => { jest.spyOn(websockets, 'openWebsocketConnection').mockImplementation(() => {}) }) diff --git a/src/__integration-tests__/ui-rendering/__snapshots__/index.test.js.snap b/src/__integration-tests__/ui-rendering/__snapshots__/index.test.js.snap index cba48105..6a933e29 100644 --- a/src/__integration-tests__/ui-rendering/__snapshots__/index.test.js.snap +++ b/src/__integration-tests__/ui-rendering/__snapshots__/index.test.js.snap @@ -515,10 +515,10 @@ exports[`dom-rendering event activePreflight-networkFail should trigger correct - +We’ve detected that you need to be on the local network for this application but you have MetaMask set to local. Please switch to the correct network.
+We’ve detected that you need to be on the local network for this application but you have your wallet set to local. Please switch to the correct network.
@@ -551,10 +551,10 @@ exports[`dom-rendering event activePreflight-networkFail should trigger correct
-
+
We’ve detected that you need to be on the rinkeby network for this application but you have MetaMask set to kovan. Please switch to the correct network.
+We’ve detected that you need to be on the rinkeby network for this application but you have your wallet set to kovan. Please switch to the correct network.
@@ -587,24 +587,26 @@ exports[`dom-rendering event activePreflight-newOnboardComplete should trigger c
Powered by @@ -649,24 +651,26 @@ exports[`dom-rendering event activePreflight-newOnboardComplete should trigger c
Powered by
@@ -791,9 +795,9 @@ exports[`dom-rendering event activePreflight-walletEnable should trigger correct
-
+
-
Connect your wallet to interact with this Dapp
Powered by @@ -859,14 +865,14 @@ exports[`dom-rendering event activePreflight-walletFail should trigger correct D
We use a product called MetaMask to manage everything you need to interact with a blockchain application like this one. MetaMask is free, installs right into your browser, hyper secure, and can be used for any other blockchain application you may want to use. Get MetaMask now
+A wallet is used to manage everything you need to interact with a blockchain application like this one. Wallets are either built into your browser or an extension added to your browser. They are hyper secure, and can be used for any other blockchain application you may want to use.
- CHECK THAT I HAVE METAMASK + CHECK THAT I HAVE A WALLET
@@ -889,10 +895,10 @@ exports[`dom-rendering event activePreflight-walletLogin should trigger correct - +We’ve detected you are not logged into MetaMask. Please log in to continue using the blockchain enabled features of this application.
+We’ve detected you are not logged in to your wallet. Please log in to continue using the blockchain enabled features of this application.
@@ -925,10 +931,10 @@ exports[`dom-rendering event activePreflight-walletLoginEnable should trigger co
-
+
-
We’ve detected you are not logged into MetaMask. Please log in to continue using the blockchain enabled features of this application.
+We’ve detected you are not logged in to your wallet. Please log in to continue using the blockchain enabled features of this application.
@@ -961,24 +967,26 @@ exports[`dom-rendering event activePreflight-welcomeUser should trigger correct
Powered by @@ -1023,24 +1031,26 @@ exports[`dom-rendering event activePreflight-welcomeUser should trigger correct
Powered by
@@ -1634,10 +1644,10 @@ exports[`dom-rendering event onboard-networkFail should trigger correct DOM rend
-
+
We’ve detected that you need to be on the local network for this application but you have MetaMask set to local. Please switch to the correct network.
+We’ve detected that you need to be on the local network for this application but you have your wallet set to local. Please switch to the correct network.
@@ -1670,10 +1680,10 @@ exports[`dom-rendering event onboard-networkFail should trigger correct DOM rend
-
+
We’ve detected that you need to be on the rinkeby network for this application but you have MetaMask set to kovan. Please switch to the correct network.
+We’ve detected that you need to be on the rinkeby network for this application but you have your wallet set to kovan. Please switch to the correct network.
@@ -1706,24 +1716,26 @@ exports[`dom-rendering event onboard-newOnboardComplete should trigger correct D
Powered by @@ -1768,24 +1780,26 @@ exports[`dom-rendering event onboard-newOnboardComplete should trigger correct D
Powered by
@@ -1830,7 +1844,7 @@ exports[`dom-rendering event onboard-nsfFail should trigger correct DOM render [
-
+
Blockchain applications sometimes require Ether to perform various functions. You’ll need at least NaN Ether (ETH) for this application.
@@ -1866,7 +1880,7 @@ exports[`dom-rendering event onboard-nsfFail should trigger correct DOM render [ - +Blockchain applications sometimes require Ether to perform various functions. You’ll need at least 12.3 Ether (ETH) for this application.
@@ -1902,9 +1916,9 @@ exports[`dom-rendering event onboard-walletEnable should trigger correct DOM ren - +Connect your wallet to interact with this Dapp
Powered by @@ -1970,14 +1986,14 @@ exports[`dom-rendering event onboard-walletFail should trigger correct DOM rende
We use a product called MetaMask to manage everything you need to interact with a blockchain application like this one. MetaMask is free, installs right into your browser, hyper secure, and can be used for any other blockchain application you may want to use. Get MetaMask now
+A wallet is used to manage everything you need to interact with a blockchain application like this one. Wallets are either built into your browser or an extension added to your browser. They are hyper secure, and can be used for any other blockchain application you may want to use.
- CHECK THAT I HAVE METAMASK + CHECK THAT I HAVE A WALLET
@@ -2000,10 +2016,10 @@ exports[`dom-rendering event onboard-walletLogin should trigger correct DOM rend - +We’ve detected you are not logged into MetaMask. Please log in to continue using the blockchain enabled features of this application.
+We’ve detected you are not logged in to your wallet. Please log in to continue using the blockchain enabled features of this application.
@@ -2036,10 +2052,10 @@ exports[`dom-rendering event onboard-walletLoginEnable should trigger correct DO
-
+
-
We’ve detected you are not logged into MetaMask. Please log in to continue using the blockchain enabled features of this application.
+We’ve detected you are not logged in to your wallet. Please log in to continue using the blockchain enabled features of this application.
@@ -2072,24 +2088,26 @@ exports[`dom-rendering event onboard-welcomeUser should trigger correct DOM rend
Powered by @@ -2134,24 +2152,26 @@ exports[`dom-rendering event onboard-welcomeUser should trigger correct DOM rend
Powered by diff --git a/src/__integration-tests__/ui-rendering/index.test.js b/src/__integration-tests__/ui-rendering/index.test.js index 6ff3cbd8..ab50956a 100644 --- a/src/__integration-tests__/ui-rendering/index.test.js +++ b/src/__integration-tests__/ui-rendering/index.test.js @@ -133,6 +133,12 @@ describe('dom-rendering', () => { }) }) +beforeEach(() => { + jest.spyOn(console, 'error') + // eslint-disable-next-line + console.error.mockImplementation(() => {}) +}) + // Reset the environment to a specified state and localstorage, // then create a new iframe // (not using beforeEach for this as it was behaiving strangely) diff --git a/src/__tests__/js/contract/index.test.js b/src/__tests__/js/contract/index.test.js index a90dd1f7..04607b9d 100644 --- a/src/__tests__/js/contract/index.test.js +++ b/src/__tests__/js/contract/index.test.js @@ -3,7 +3,7 @@ import { Server } from 'mock-socket' import abi from '~/__tests__/res/dstoken.json' import da from '~/js' import * as web3Helpers from '~/js/helpers/web3' -import { state, initialState, updateState } from '~/js/helpers/state' +import { initialState, updateState } from '~/js/helpers/state' import convertLibJson from '~/__tests__/res/ConvertLib.json' import { convertLibAddress, port } from '../../../../internals/ganacheConfig' @@ -55,12 +55,8 @@ multidepRequire.forEachVersion('web3', (version, Web3) => { contracts.forEach(([name, getContract]) => { describe(`with a ${name} contract`, () => { beforeEach(async () => { - if (name === 'truffle') state.config.truffleContract = true contract = await getContract(web3) }) - afterEach(() => { - if (name === 'truffle') state.config.truffleContract = false - }) test(`it doesn't fail and returns the expected decorated contract`, () => { const decoratedContract = assistInstance.Contract(contract) diff --git a/src/__tests__/js/web3.test.js b/src/__tests__/js/web3.test.js index 35c261c7..83ac1321 100644 --- a/src/__tests__/js/web3.test.js +++ b/src/__tests__/js/web3.test.js @@ -1,7 +1,7 @@ import truffleContract from 'truffle-contract' import da from '~/js' import abi from '~/__tests__/res/dstoken.json' -import { state, initialState, updateState } from '~/js/helpers/state' +import { initialState, updateState } from '~/js/helpers/state' import * as websockets from '~/js/helpers/websockets' import { web3Functions } from '~/js/helpers/web3' import convertLibJson from '~/__tests__/res/ConvertLib' @@ -98,7 +98,6 @@ describe(`web3.js tests`, () => { describe('from a truffle contract', () => { let contractInstance beforeEach(async () => { - state.config.truffleContract = true contract = truffleContract(convertLibJson) contract.setProvider( new Web3v0p20.providers.HttpProvider( @@ -107,9 +106,6 @@ describe(`web3.js tests`, () => { ) contractInstance = await contract.at(convertLibAddress) }) - afterEach(() => { - state.config.truffleContract = false - }) // doesn't seem to work // see https://github.com/blocknative/assist/issues/171 test('should return the expected gas cost', async () => { @@ -117,7 +113,8 @@ describe(`web3.js tests`, () => { const contractMethod = contractInstance.convert const parameters = [5, 10] const contractGas = await web3Functions.contractGas( - simpleVersion + simpleVersion, + true )(contractMethod, parameters) expect(contractGas).toEqual(expected) }) diff --git a/src/css/styles.css b/src/css/styles.css index afb26fbd..8ff1098e 100644 --- a/src/css/styles.css +++ b/src/css/styles.css @@ -274,6 +274,9 @@ body { } .bn-onboard-basic .bn-onboard-sidebar { + display: flex; + flex-flow: column nowrap; + justify-content: space-between; padding: 15px 20px; width: 34%; background: #eeeeee; @@ -365,10 +368,6 @@ img.bn-onboard-img { font-size: 0.79em; } -.bn-onboard-basic .bn-onboarding-branding { - position: absolute; - bottom: 15px; -} .bn-onboard-basic .bn-onboarding-branding img { margin-top: 5px; } diff --git a/src/js/helpers/validation.js b/src/js/helpers/validation.js index 133eb335..d64c0a0d 100644 --- a/src/js/helpers/validation.js +++ b/src/js/helpers/validation.js @@ -57,6 +57,9 @@ export function validateConfig(config) { ), css: ow.optional.string }), + timeouts: ow.optional.object.exactShape({ + txStall: ow.number + }), truffleContract: ow.optional.boolean }) ) diff --git a/src/js/helpers/web3.js b/src/js/helpers/web3.js index 41d5a50c..a7014e03 100644 --- a/src/js/helpers/web3.js +++ b/src/js/helpers/web3.js @@ -38,16 +38,16 @@ export const web3Functions = { return () => Promise.reject(errorObj) } }, - contractGas: version => { + contractGas: (version, truffleContract) => { switch (version) { case '0.2': return (contractMethod, parameters, txObject) => - state.config.truffleContract + truffleContract ? contractMethod.estimateGas(...parameters) : promisify(contractMethod.estimateGas)(...parameters, txObject) case '1.0': return (contractMethod, parameters, txObject) => - state.config.truffleContract + truffleContract ? contractMethod.estimateGas(...parameters) : contractMethod(...parameters).estimateGas(txObject) default: @@ -167,7 +167,8 @@ export function getNetworkId() { export function getTransactionParams( txObject = {}, contractMethod, - contractEventObj + contractEventObj, + truffleContract ) { return new Promise(async resolve => { const version = state.web3Version && state.web3Version.slice(0, 3) @@ -199,7 +200,7 @@ export function getTransactionParams( // Get a gas estimate based on if the tx is a contract method call // or regular transaction gas = contractMethod - ? await web3Functions.contractGas(version)( + ? await web3Functions.contractGas(version, truffleContract)( contractMethod, contractEventObj.parameters, txObject diff --git a/src/js/index.js b/src/js/index.js index 25d791f4..369c1901 100644 --- a/src/js/index.js +++ b/src/js/index.js @@ -220,12 +220,9 @@ function init(config) { // CONTRACT FUNCTION // function Contract(contractObj) { - const { - validApiKey, - supportedNetwork, - web3Instance, - config: { truffleContract } - } = state + const { validApiKey, supportedNetwork, web3Instance } = state + + const truffleContract = contractObj.constructor.name === 'TruffleContract' if (!validApiKey) { const errorObj = new Error('Your API key is not valid') @@ -293,14 +290,14 @@ function init(config) { newContractObj[name] = (...args) => constant - ? legacyCall(method, name, args, argsLength) - : legacySend(method, name, args, argsLength) + ? legacyCall(method, name, args, argsLength, truffleContract) + : legacySend(method, name, args, argsLength, truffleContract) newContractObj[name].call = (...args) => - legacyCall(method, name, args, argsLength) + legacyCall(method, name, args, argsLength, truffleContract) newContractObj[name].sendTransaction = (...args) => - legacySend(method, name, args, argsLength) + legacySend(method, name, args, argsLength, truffleContract) // Add any additional properties onto the method function Object.entries(contractObj[name]).forEach(([k, v]) => { @@ -320,14 +317,14 @@ function init(config) { newContractObj[name][key] = (...args) => constant - ? legacyCall(method, name, args, argsLength) - : legacySend(method, name, args, argsLength) + ? legacyCall(method, name, args, argsLength, truffleContract) + : legacySend(method, name, args, argsLength, truffleContract) newContractObj[name][key].call = (...args) => - legacyCall(method, name, args, argsLength) + legacyCall(method, name, args, argsLength, truffleContract) newContractObj[name][key].sendTransaction = (...args) => - legacySend(method, name, args, argsLength) + legacySend(method, name, args, argsLength, truffleContract) // Add any additional properties onto the method function Object.entries(method).forEach(([k, v]) => { @@ -368,7 +365,7 @@ function init(config) { methodsObj[name] = (...args) => constant ? modernCall(method, name, args) - : modernSend(method, name, args) + : modernSend(method, name, args, truffleContract) // Add any additional properties onto the method function Object.entries(method).forEach(([k, v]) => { @@ -393,7 +390,7 @@ function init(config) { methodsObj[overloadedMethodKey] = (...args) => constant ? modernCall(overloadedMethod, name, args) - : modernSend(overloadedMethod, name, args) + : modernSend(overloadedMethod, name, args, truffleContract) // Add any additional properties onto the method function Object.entries(overloadedMethod).forEach(([k, v]) => { @@ -445,9 +442,10 @@ function init(config) { txObject, sendMethod, callback, - inlineCustomMsgs, + inlineCustomMsgs.messages, undefined, undefined, + false, promiEvent ) return promiEvent @@ -457,7 +455,10 @@ function init(config) { txObject, sendMethod, callback, - inlineCustomMsgs.messages + inlineCustomMsgs.messages, + undefined, + undefined, + false ) } } diff --git a/src/js/logic/contract-methods.js b/src/js/logic/contract-methods.js index be853184..5e1bbdf2 100644 --- a/src/js/logic/contract-methods.js +++ b/src/js/logic/contract-methods.js @@ -39,6 +39,8 @@ export function modernCall(method, name, args) { } } ) + + return } const correctNetwork = await checkNetwork() @@ -90,7 +92,7 @@ export function modernCall(method, name, args) { return returnObject } -export function modernSend(method, name, args) { +export function modernSend(method, name, args, truffleContract) { const originalReturnObject = method(...args) const innerMethod = originalReturnObject.send @@ -111,6 +113,7 @@ export function modernSend(method, name, args) { inlineCustomMsgs, method, { methodName: name, parameters: args }, + truffleContract, promiEvent ) @@ -120,11 +123,11 @@ export function modernSend(method, name, args) { return returnObject } -export function legacyCall(method, name, allArgs, argsLength) { +export function legacyCall(method, name, allArgs, argsLength, truffleContract) { return new Promise(async (resolve, reject) => { const { mobileDevice, - config: { mobileBlocked, headlessMode, truffleContract } + config: { mobileBlocked, headlessMode } } = state const { callback, args, txObject, defaultBlock } = separateArgs( allArgs, @@ -146,21 +149,23 @@ export function legacyCall(method, name, allArgs, argsLength) { } ) - return resolve() + return } const correctNetwork = await checkNetwork() if (!correctNetwork) { if (!headlessMode) { - const result = await getCorrectNetwork('onboard').catch( + const onCorrectNetwork = await getCorrectNetwork('onboard').catch( handleError({ resolve, reject, callback }) ) - if (!result) return + if (!onCorrectNetwork) return } else { const errorObj = new Error('User is on the wrong network') errorObj.eventCode = 'networkFail' handleError({ resolve, reject, callback })(errorObj) + + return } } @@ -187,28 +192,36 @@ export function legacyCall(method, name, allArgs, argsLength) { handleError({ resolve, reject, callback })(errorObj) }) - handleEvent({ - eventCode: 'contractQuery', - categoryCode: 'activeContract', - contract: { - methodName: name, - parameters: args, - result: JSON.stringify(result) - } - }) + if (result != null) { + handleEvent({ + eventCode: 'contractQuery', + categoryCode: 'activeContract', + contract: { + methodName: name, + parameters: args, + result: JSON.stringify(result) + } + }) - callback && callback(null, result) - return resolve(result) + callback && callback(null, result) + resolve(result) + } }) } -export async function legacySend(method, name, allArgs, argsLength) { +export async function legacySend( + method, + name, + allArgs, + argsLength, + truffleContract +) { const { callback, txObject, args, inlineCustomMsgs } = separateArgs( allArgs, argsLength ) - const sendMethod = state.config.truffleContract + const sendMethod = truffleContract ? method.sendTransaction : promisify(method) @@ -222,6 +235,7 @@ export async function legacySend(method, name, allArgs, argsLength) { { methodName: name, parameters: args - } + }, + truffleContract ) } diff --git a/src/js/logic/send-transaction.js b/src/js/logic/send-transaction.js index 315029f1..2f660b8d 100644 --- a/src/js/logic/send-transaction.js +++ b/src/js/logic/send-transaction.js @@ -31,6 +31,7 @@ function sendTransaction( inlineCustomMsgs, contractMethod, contractEventObj, + truffleContract, promiEvent ) { return new Promise(async (resolve, reject) => { @@ -38,7 +39,8 @@ function sendTransaction( const transactionParams = await getTransactionParams( txOptions, contractMethod, - contractEventObj + contractEventObj, + truffleContract ) // Check user is ready to make the transaction @@ -131,16 +133,14 @@ function sendTransaction( let txPromise - if (state.legacyWeb3 || state.config.truffleContract) { - if (contractEventObj) { - txPromise = sendTransactionMethod( - ...contractEventObj.parameters, - txOptions - ) - } else { - txPromise = sendTransactionMethod(txOptions) - } + if ((state.legacyWeb3 || truffleContract) && contractEventObj) { + // legacy contract call + txPromise = sendTransactionMethod( + ...contractEventObj.parameters, + txOptions + ) } else { + // modern contract call or basic transaction txPromise = sendTransactionMethod(txOptions) } @@ -201,7 +201,7 @@ function sendTransaction( onTxError(transactionId, errorObj, categoryCode) handleError({ resolve, reject, callback })(errorObj) }) - } else if (state.config.truffleContract) { + } else if (truffleContract) { txPromise .then(async txObj => { const hash = txObj.tx @@ -270,6 +270,9 @@ function onTxHash(id, hash, categoryCode) { } }) + const customStallTimeout = + state.config.timeouts && state.config.timeouts.txStall + // Check if transaction is in txPool after timeout setTimeout(() => { const txObj = getTxObjFromQueue(id) @@ -299,7 +302,7 @@ function onTxHash(id, hash, categoryCode) { } }) } - }, timeouts.txStall) + }, customStallTimeout || timeouts.txStall) } async function onTxReceipt(id, categoryCode) { diff --git a/src/js/views/content.js b/src/js/views/content.js index 25323230..c20e26b5 100644 --- a/src/js/views/content.js +++ b/src/js/views/content.js @@ -79,27 +79,44 @@ export const notSupported = { } export const onboardHeading = { - mobileNetwork: { advanced: 'Switch to the Correct Network' }, - mobileWalletEnable: { advanced: 'Connect Wallet' }, - '0': { basic: 'Let’s Get You Started' }, - '1': { basic: 'Install MetaMask' }, + mobileNetwork: { advanced: () => 'Switch to the Correct Network' }, + mobileWalletEnable: { advanced: () => 'Connect Wallet' }, + '0': { basic: () => 'Let’s Get You Started' }, + '1': { + basic: () => + `Install ${ + state.currentProvider === 'metamask' ? 'MetaMask' : 'a Wallet' + }` + }, '2': { - basic: 'MetaMask Login', - advanced: 'Login to MetaMask' + basic: () => + `Login to ${ + state.currentProvider === 'metamask' ? 'MetaMask' : 'Your Wallet' + }`, + advanced: () => + `Login to ${ + state.currentProvider === 'metamask' ? 'MetaMask' : 'Your Wallet' + }` }, '3': { - basic: 'MetaMask Connect', - advanced: 'Connect MetaMask' + basic: () => + `Connect to ${ + state.currentProvider === 'metamask' ? 'MetaMask' : 'Your Wallet' + }`, + advanced: () => + `Connect to ${ + state.currentProvider === 'metamask' ? 'MetaMask' : 'Your Wallet' + }` }, '4': { - basic: 'Join the Correct Network', - advanced: 'Wrong Network' + basic: () => 'Join the Correct Network', + advanced: () => 'Wrong Network' }, '5': { - basic: 'Get Some Ether', - advanced: 'Get Some ETH' + basic: () => 'Get Some Ether', + advanced: () => 'Get Some ETH' }, - '6': { basic: 'Ready to Go' } + '6': { basic: () => 'Ready to Go' } } export const onboardDescription = { @@ -121,13 +138,19 @@ export const onboardDescription = { }, '1': { basic: () => - 'We use a product called MetaMask to manage everything you need to interact with a blockchain application like this one. MetaMask is free, installs right into your browser, hyper secure, and can be used for any other blockchain application you may want to use. Get MetaMask now' + state.currentProvider === 'metamask' + ? 'We use a product called MetaMask to manage everything you need to interact with a blockchain application like this one. MetaMask is free, installs right into your browser, hyper secure, and can be used for any other blockchain application you may want to use. Get MetaMask now' + : 'A wallet is used to manage everything you need to interact with a blockchain application like this one. Wallets are either built into your browser or an extension added to your browser. They are hyper secure, and can be used for any other blockchain application you may want to use.' }, '2': { basic: () => - 'Now you have MetaMask installed, you’ll need to log into it. The first time you use it, you may need to set up an account with MetaMask which you can do right from the extension. When you’ve got that set up and you’re logged into MetaMask, let us know.', + `Now you have ${ + state.currentProvider === 'metamask' ? 'MetaMask' : 'a wallet' + } installed, you’ll need to log into it. The first time you use it, you may need to set up an account. When you’ve got that set up and you’re logged in, let us know.`, advanced: () => - 'We’ve detected you are not logged into MetaMask. Please log in to continue using the blockchain enabled features of this application.' + `We’ve detected you are not logged in to ${ + state.currentProvider === 'metamask' ? 'MetaMask' : 'your wallet' + }. Please log in to continue using the blockchain enabled features of this application.` }, '3': { basic: () => 'Please allow connection to your wallet', @@ -137,15 +160,19 @@ export const onboardDescription = { basic: () => `Blockchain applications have different networks they can work on. Think of this like making sure you’re on Netflix vs Hulu to watch your favorite show. We’ve detected that you need to be on the ${networkName( state.config.networkId - ) || - 'mainnet'} network for this application but you have MetaMask set to ${networkName( + ) || 'mainnet'} network for this application but you have ${ + state.currentProvider === 'metamask' ? 'MetaMask' : 'your wallet' + } set to ${networkName( state.userCurrentNetworkId - )}. Switch the network name in MetaMask and you’ll be ready to go.`, + )}. Switch the network name in ${ + state.currentProvider === 'metamask' ? 'MetaMask' : 'your wallet' + } and you’ll be ready to go.`, advanced: () => `We’ve detected that you need to be on the ${networkName( state.config.networkId - ) || - 'mainnet'} network for this application but you have MetaMask set to ${networkName( + ) || 'mainnet'} network for this application but you have ${ + state.currentProvider === 'metamask' ? 'MetaMask' : 'your wallet' + } set to ${networkName( state.userCurrentNetworkId )}. Please switch to the correct network.` }, @@ -171,7 +198,10 @@ export const onboardButton = { mobileWalletEnable: { advanced: 'CHECK THAT I’M CONNECTED' }, '0': { basic: 'I’M READY' }, '1': { - basic: 'CHECK THAT I HAVE METAMASK' + basic: () => + `CHECK THAT I HAVE ${ + state.currentProvider === 'metamask' ? 'METAMASK' : 'A WALLET' + }` }, '2': { basic: 'CHECK THAT I’M LOGGED IN', @@ -193,25 +223,26 @@ export const onboardButton = { } export function onboardWarningMsg(type) { - const { mobileDevice } = state + const { mobileDevice, currentProvider } = state + const isMetaMask = currentProvider === 'metamask' switch (type) { case 'loggedIn': return `You are not currently logged in to ${ - mobileDevice ? 'your wallet' : 'MetaMask' + mobileDevice || !isMetaMask ? 'your wallet' : 'MetaMask' }.` case 'enabled': - return `You have not yet approved the Connect request in ${ - mobileDevice ? 'your wallet' : 'MetaMask' + return `You have not yet approved the connect request in ${ + mobileDevice || !isMetaMask ? 'your wallet' : 'MetaMask' }.` case 'network': return `You currently have ${ - mobileDevice ? 'your wallet' : 'MetaMask' + mobileDevice || !isMetaMask ? 'your wallet' : 'MetaMask' } set to the ${capitalize(networkName(state.userCurrentNetworkId))} ${ state.userCurrentNetworkId === 1 ? 'Ethereum' : 'Test' } Network.` case 'minimumBalance': return `Your current ${ - mobileDevice ? 'wallet' : 'MetaMask' + mobileDevice || !isMetaMask ? 'wallet' : 'MetaMask' } account has less than the necessary minimum balance of ${state.config.minimumBalance / 1000000000000000000} ${capitalize( networkName(state.userCurrentNetworkId) diff --git a/src/js/views/dom.js b/src/js/views/dom.js index 88b05bde..d1696a26 100644 --- a/src/js/views/dom.js +++ b/src/js/views/dom.js @@ -121,8 +121,29 @@ export function createElement(el, className, children, id) { const handleWindowResize = () => resizeIframe({ height: window.innerHeight, width: window.innerWidth }) +let listenerFunc + +function handleKeyPress(onClose) { + function innerFunc(e) { + if (e.key === 'Escape') { + e.preventDefault() + onClose && onClose() + closeModal() + } + } + + listenerFunc = innerFunc + + return listenerFunc +} + export function closeModal() { window.removeEventListener('resize', handleWindowResize) + if (listenerFunc) { + state.iframeWindow.removeEventListener('keydown', listenerFunc) + listenerFunc = null + } + const modal = state.iframeDocument.querySelector('.bn-onboard-modal-shade') modal.style.opacity = '0' removeTouchHandlers(modal) @@ -145,8 +166,13 @@ export function closeModal() { export function openModal(modal, handlers = {}) { const { onClick, onClose } = handlers + window.addEventListener('resize', handleWindowResize) + state.iframeWindow.addEventListener('keydown', handleKeyPress(onClose)) + state.iframeWindow.focus && state.iframeWindow.focus() + state.iframeDocument.body.appendChild(modal) + showIframe() resizeIframe({ height: window.innerHeight, width: window.innerWidth }) @@ -299,51 +325,43 @@ export function notSupportedModal(type) { export function onboardSidebar(step) { return `