diff options
42 files changed, 1756 insertions, 168 deletions
diff --git a/app/scripts/lib/config-manager.js b/app/scripts/lib/config-manager.js index 9c0dffe9c..34b603b96 100644 --- a/app/scripts/lib/config-manager.js +++ b/app/scripts/lib/config-manager.js @@ -42,6 +42,17 @@ ConfigManager.prototype.getData = function () { return this.store.getState() } +ConfigManager.prototype.setPasswordForgotten = function (passwordForgottenState) { + const data = this.getData() + data.forgottenPassword = passwordForgottenState + this.setData(data) +} + +ConfigManager.prototype.getPasswordForgotten = function (passwordForgottenState) { + const data = this.getData() + return data.forgottenPassword +} + ConfigManager.prototype.setWallet = function (wallet) { var data = this.getData() data.wallet = wallet diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index db98c9ef5..15a30458a 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -310,6 +310,7 @@ module.exports = class MetamaskController extends EventEmitter { { lostAccounts: this.configManager.getLostAccounts(), seedWords: this.configManager.getSeedWords(), + forgottenPassword: this.configManager.getPasswordForgotten(), } ) } @@ -332,6 +333,8 @@ module.exports = class MetamaskController extends EventEmitter { setCurrentCurrency: this.setCurrentCurrency.bind(this), setUseBlockie: this.setUseBlockie.bind(this), markAccountsFound: this.markAccountsFound.bind(this), + markPasswordForgotten: this.markPasswordForgotten.bind(this), + unMarkPasswordForgotten: this.unMarkPasswordForgotten.bind(this), // coinbase buyEth: this.buyEth.bind(this), @@ -794,6 +797,18 @@ module.exports = class MetamaskController extends EventEmitter { cb(null, this.getState()) } + markPasswordForgotten(cb) { + this.configManager.setPasswordForgotten(true) + this.sendUpdate() + cb() + } + + unMarkPasswordForgotten(cb) { + this.configManager.setPasswordForgotten(false) + this.sendUpdate() + cb() + } + restoreOldVaultAccounts (migratorOutput) { const { serialized } = migratorOutput return this.keyringController.restoreKeyring(serialized) diff --git a/development/backGroundConnectionModifiers.js b/development/backGroundConnectionModifiers.js new file mode 100644 index 000000000..ffbe49d4d --- /dev/null +++ b/development/backGroundConnectionModifiers.js @@ -0,0 +1,26 @@ +module.exports = { + "confirm sig requests": { + signMessage: (msgData, cb) => { + const stateUpdate = { + unapprovedMsgs: {}, + unapprovedMsgCount: 0, + } + return cb(null, stateUpdate) + }, + signPersonalMessage: (msgData, cb) => { + const stateUpdate = { + unapprovedPersonalMsgs: {}, + unapprovedPersonalMsgsCount: 0, + } + return cb(null, stateUpdate) + }, + signTypedMessage: (msgData, cb) => { + const stateUpdate = { + unapprovedTypedMessages: {}, + unapprovedTypedMessagesCount: 0, + } + return cb(null, stateUpdate) + }, + }, +} + diff --git a/development/selector.js b/development/selector.js index c466905ca..fd387df15 100644 --- a/development/selector.js +++ b/development/selector.js @@ -11,7 +11,14 @@ function NewComponent () { NewComponent.prototype.render = function () { const props = this.props - let { states, selectedKey, actions, store } = props + let { + states, + selectedKey, + actions, + store, + modifyBackgroundConnection, + backGroundConnectionModifiers, + } = props const state = this.state || {} const selected = state.selected || selectedKey @@ -23,6 +30,8 @@ NewComponent.prototype.render = function () { value: selected, onChange:(event) => { const selectedKey = event.target.value + const backgroundConnectionModifier = backGroundConnectionModifiers[selectedKey] + modifyBackgroundConnection(backgroundConnectionModifier || {}) store.dispatch(actions.update(selectedKey)) this.setState({ selected: selectedKey }) }, diff --git a/development/states/add-token.json b/development/states/add-token.json new file mode 100644 index 000000000..e78393b7f --- /dev/null +++ b/development/states/add-token.json @@ -0,0 +1,132 @@ +{ + "metamask": { + "isInitialized": true, + "isUnlocked": true, + "featureFlags": {"betaUI": true}, + "rpcTarget": "https://rawtestrpc.metamask.io/", + "identities": { + "0xfdea65c8e26263f6d9a1b5de9555d2931a33b825": { + "address": "0xfdea65c8e26263f6d9a1b5de9555d2931a33b825", + "name": "Send Account 1" + }, + "0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb": { + "address": "0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb", + "name": "Send Account 2" + }, + "0x2f8d4a878cfa04a6e60d46362f5644deab66572d": { + "address": "0x2f8d4a878cfa04a6e60d46362f5644deab66572d", + "name": "Send Account 3" + }, + "0xd85a4b6a394794842887b8284293d69163007bbb": { + "address": "0xd85a4b6a394794842887b8284293d69163007bbb", + "name": "Send Account 4" + } + }, + "unapprovedTxs": {}, + "conversionRate": 1200.88200327, + "conversionDate": 1489013762, + "noActiveNotices": true, + "frequentRpcList": [], + "network": "3", + "accounts": { + "0xfdea65c8e26263f6d9a1b5de9555d2931a33b825": { + "code": "0x", + "balance": "0x47c9d71831c76efe", + "nonce": "0x1b", + "address": "0xfdea65c8e26263f6d9a1b5de9555d2931a33b825" + }, + "0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb": { + "code": "0x", + "balance": "0x37452b1315889f80", + "nonce": "0xa", + "address": "0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb" + }, + "0x2f8d4a878cfa04a6e60d46362f5644deab66572d": { + "code": "0x", + "balance": "0x30c9d71831c76efe", + "nonce": "0x1c", + "address": "0x2f8d4a878cfa04a6e60d46362f5644deab66572d" + }, + "0xd85a4b6a394794842887b8284293d69163007bbb": { + "code": "0x", + "balance": "0x0", + "nonce": "0x0", + "address": "0xd85a4b6a394794842887b8284293d69163007bbb" + } + }, + "addressBook": [ + { + "address": "0x06195827297c7a80a443b6894d3bdb8824b43896", + "name": "Address Book Account 1" + } + ], + "tokens": [], + "transactions": {}, + "selectedAddressTxList": [], + "unapprovedMsgs": {}, + "unapprovedMsgCount": 0, + "unapprovedPersonalMsgs": {}, + "unapprovedPersonalMsgCount": 0, + "keyringTypes": [ + "Simple Key Pair", + "HD Key Tree" + ], + "keyrings": [ + { + "type": "HD Key Tree", + "accounts": [ + "fdea65c8e26263f6d9a1b5de9555d2931a33b825", + "c5b8dbac4c1d3f152cdeb400e2313f309c410acb", + "2f8d4a878cfa04a6e60d46362f5644deab66572d" + ] + }, + { + "type": "Simple Key Pair", + "accounts": [ + "0xd85a4b6a394794842887b8284293d69163007bbb" + ] + } + ], + "selectedAddress": "0xd85a4b6a394794842887b8284293d69163007bbb", + "currentCurrency": "USD", + "provider": { + "type": "testnet" + }, + "shapeShiftTxList": [], + "lostAccounts": [], + "send": { + "gasLimit": null, + "gasPrice": null, + "gasTotal": "0xb451dc41b578", + "tokenBalance": null, + "from": "", + "to": "", + "amount": "0x0", + "memo": "", + "errors": {}, + "maxModeOn": false, + "editingTransactionId": null + } + }, + "appState": { + "menuOpen": false, + "currentView": { + "name": "accountDetail", + "detailView": null, + "context": "0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc" + }, + "accountDetail": { + "subview": "transactions" + }, + "modal": { + "modalState": {}, + "previousModalState": {} + }, + "transForward": true, + "isLoading": false, + "warning": null, + "scrollToBottom": false, + "forgottenPassword": null + }, + "identities": {} +} diff --git a/development/states/confirm-new-ui.json b/development/states/confirm-new-ui.json new file mode 100644 index 000000000..6ea8e64cd --- /dev/null +++ b/development/states/confirm-new-ui.json @@ -0,0 +1,154 @@ +{ + "metamask": { + "isInitialized": true, + "isUnlocked": true, + "featureFlags": {"betaUI": true}, + "rpcTarget": "https://rawtestrpc.metamask.io/", + "identities": { + "0xfdea65c8e26263f6d9a1b5de9555d2931a33b825": { + "address": "0xfdea65c8e26263f6d9a1b5de9555d2931a33b825", + "name": "Send Account 1" + }, + "0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb": { + "address": "0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb", + "name": "Send Account 2" + }, + "0x2f8d4a878cfa04a6e60d46362f5644deab66572d": { + "address": "0x2f8d4a878cfa04a6e60d46362f5644deab66572d", + "name": "Send Account 3" + }, + "0xd85a4b6a394794842887b8284293d69163007bbb": { + "address": "0xd85a4b6a394794842887b8284293d69163007bbb", + "name": "Send Account 4" + } + }, + "unapprovedTxs": {}, + "currentCurrency": "USD", + "conversionRate": 1200.88200327, + "conversionDate": 1489013762, + "noActiveNotices": true, + "frequentRpcList": [], + "network": "3", + "accounts": { + "0xfdea65c8e26263f6d9a1b5de9555d2931a33b825": { + "code": "0x", + "balance": "0x47c9d71831c76efe", + "nonce": "0x1b", + "address": "0xfdea65c8e26263f6d9a1b5de9555d2931a33b825" + }, + "0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb": { + "code": "0x", + "balance": "0x37452b1315889f80", + "nonce": "0xa", + "address": "0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb" + }, + "0x2f8d4a878cfa04a6e60d46362f5644deab66572d": { + "code": "0x", + "balance": "0x30c9d71831c76efe", + "nonce": "0x1c", + "address": "0x2f8d4a878cfa04a6e60d46362f5644deab66572d" + }, + "0xd85a4b6a394794842887b8284293d69163007bbb": { + "code": "0x", + "balance": "0x0", + "nonce": "0x0", + "address": "0xd85a4b6a394794842887b8284293d69163007bbb" + } + }, + "addressBook": [ + { + "address": "0x06195827297c7a80a443b6894d3bdb8824b43896", + "name": "Address Book Account 1" + } + ], + "tokens": [], + "transactions": {}, + "selectedAddressTxList": [], + "unapprovedTxs": { + "4768706228115573": { + "id": 4768706228115573, + "time": 1487363153561, + "status": "unapproved", + "gasMultiplier": 1, + "metamaskNetworkId": "3", + "txParams": { + "from": "0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb", + "to": "0x2f8d4a878cfa04a6e60d46362f5644deab66572d", + "value": "0x1bc16d674ec80000", + "metamaskId": 4768706228115573, + "metamaskNetworkId": "3", + "gas": "0xea60", + "gasPrice": "0xba43b7400" + } + } + }, + "unapprovedMsgs": {}, + "unapprovedMsgCount": 0, + "unapprovedPersonalMsgs": {}, + "unapprovedPersonalMsgCount": 0, + "keyringTypes": [ + "Simple Key Pair", + "HD Key Tree" + ], + "keyrings": [ + { + "type": "HD Key Tree", + "accounts": [ + "fdea65c8e26263f6d9a1b5de9555d2931a33b825", + "c5b8dbac4c1d3f152cdeb400e2313f309c410acb", + "2f8d4a878cfa04a6e60d46362f5644deab66572d" + ] + }, + { + "type": "Simple Key Pair", + "accounts": [ + "0xd85a4b6a394794842887b8284293d69163007bbb" + ] + } + ], + "selectedAddress": "0xd85a4b6a394794842887b8284293d69163007bbb", + "currentCurrency": "USD", + "provider": { + "type": "testnet" + }, + "shapeShiftTxList": [], + "lostAccounts": [], + "send": { + "gasLimit": "0xea60", + "gasPrice": "0xba43b7400", + "gasTotal": "0xb451dc41b578", + "tokenBalance": null, + "from": { + "address": "0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb", + "balance": "0x37452b1315889f80" + }, + "to": "0x2f8d4a878cfa04a6e60d46362f5644deab66572d", + "amount": "0x1bc16d674ec80000", + "memo": "", + "errors": {}, + "maxModeOn": false, + "editingTransactionId": null + } + }, + "appState": { + "menuOpen": false, + "currentView": { + "name": "confTx", + "detailView": null, + "context": 0 + }, + "accountDetail": { + "subview": "transactions" + }, + "modal": { + "modalState": {}, + "previousModalState": {} + }, + "transForward": true, + "isLoading": false, + "warning": null, + "scrollToBottom": false, + "forgottenPassword": null + }, + "identities": {} +} diff --git a/development/states/confirm-sig-requests.json b/development/states/confirm-sig-requests.json new file mode 100644 index 000000000..0a691e948 --- /dev/null +++ b/development/states/confirm-sig-requests.json @@ -0,0 +1,175 @@ +{ + "metamask": { + "isInitialized": true, + "isUnlocked": true, + "featureFlags": {"betaUI": true}, + "rpcTarget": "https://rawtestrpc.metamask.io/", + "identities": { + "0xfdea65c8e26263f6d9a1b5de9555d2931a33b825": { + "address": "0xfdea65c8e26263f6d9a1b5de9555d2931a33b825", + "name": "Send Account 1" + }, + "0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb": { + "address": "0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb", + "name": "Send Account 2" + }, + "0x2f8d4a878cfa04a6e60d46362f5644deab66572d": { + "address": "0x2f8d4a878cfa04a6e60d46362f5644deab66572d", + "name": "Send Account 3" + }, + "0xd85a4b6a394794842887b8284293d69163007bbb": { + "address": "0xd85a4b6a394794842887b8284293d69163007bbb", + "name": "Send Account 4" + } + }, + "unapprovedTxs": {}, + "currentCurrency": "USD", + "conversionRate": 1200.88200327, + "conversionDate": 1489013762, + "noActiveNotices": true, + "frequentRpcList": [], + "network": "3", + "accounts": { + "0xfdea65c8e26263f6d9a1b5de9555d2931a33b825": { + "code": "0x", + "balance": "0x47c9d71831c76efe", + "nonce": "0x1b", + "address": "0xfdea65c8e26263f6d9a1b5de9555d2931a33b825" + }, + "0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb": { + "code": "0x", + "balance": "0x37452b1315889f80", + "nonce": "0xa", + "address": "0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb" + }, + "0x2f8d4a878cfa04a6e60d46362f5644deab66572d": { + "code": "0x", + "balance": "0x30c9d71831c76efe", + "nonce": "0x1c", + "address": "0x2f8d4a878cfa04a6e60d46362f5644deab66572d" + }, + "0xd85a4b6a394794842887b8284293d69163007bbb": { + "code": "0x", + "balance": "0x0", + "nonce": "0x0", + "address": "0xd85a4b6a394794842887b8284293d69163007bbb" + } + }, + "addressBook": [ + { + "address": "0x06195827297c7a80a443b6894d3bdb8824b43896", + "name": "Address Book Account 1" + } + ], + "tokens": [], + "transactions": {}, + "selectedAddressTxList": [], + "unapprovedTxs": {}, + "unapprovedMsgs": { + "8927167822566864": { + "id": 8927167822566864, + "msgParams": { + "data": "0x879a053d4800c6354e76c7985a865d2922c82fb5b3f4577b2fe08b998954f2e0", + "from": "0x0d0c7188d9c72b019a5da9bca0d127680c22e658" + }, + "status": "unapproved", + "time": 1537889069339, + "type": "eth_sign" + } + }, + "unapprovedMsgCount": 1, + "unapprovedPersonalMsgs": { + "8907167822566865": { + "id": 8907167822566865, + "msgParams": { + "data": "0x23205465726d73206f662055736520230a0a2a2a544849532041475245454d454e54204953205355424a45435420544f2042494e44494e47204152424954524154494f4e20414e44204120574149564552204f4620434c41535320414354494f4e205249474854532041532044455441494c454420494e2053454354494f4e2031332e20504c454153452052454144205448452041475245454d454e54204341524546554c4c592e2a2a0a0a5f4f7572205465726d73206f66205573652068617665206265656e2075706461746564206173206f662053657074656d62657220352c20323031365f0a0a232320312e20416363657074616e6365206f66205465726d732023230a0a4d6574614d61736b2070726f7669646573206120706c6174666f726d20666f72206d616e6167696e6720457468657265756d20286f7220224554482229206163636f756e74732c20616e6420616c6c6f77696e67206f7264696e61727920776562736974657320746f20696e74657261637420776974682074686520457468657265756d20626c6f636b636861696e2c207768696c65206b656570696e6720746865207573657220696e20636f6e74726f6c206f7665722077686174207472616e73616374696f6e73207468657920617070726f76652c207468726f756768206f75722077656273697465206c6f63617465642061745b205d28687474703a2f2f6d6574616d61736b2e696f295b68747470733a2f2f6d6574616d61736b2e696f2f5d2868747470733a2f2f6d6574616d61736b2e696f2f2920616e642062726f7773657220706c7567696e2028746865202253697465222920e2809420776869636820696e636c7564657320746578742c20696d616765732c20617564696f2c20636f646520616e64206f74686572206d6174657269616c73202028636f6c6c6563746976656c792c2074686520e2809c436f6e74656e74e2809d2920616e6420616c6c206f66207468652066656174757265732c20616e642073657276696365732070726f76696465642e2054686520536974652c20616e6420616e79206f746865722066656174757265732c20746f6f6c732c206d6174657269616c732c206f72206f74686572207365727669636573206f6666657265642066726f6d2074696d6520746f2074696d65206279204d6574614d61736b2061726520726566657272656420746f20686572652061732074686520e2809c536572766963652ee2809d20506c656173652072656164207468657365205465726d73206f6620557365202874686520e2809c5465726d73e2809d206f7220e2809c5465726d73206f6620557365e2809d29206361726566756c6c79206265666f7265207573696e672074686520536572766963652e204279207573696e67206f72206f746865727769736520616363657373696e67207468652053657276696365732c206f7220636c69636b696e6720746f20616363657074206f7220616772656520746f207468657365205465726d732077686572652074686174206f7074696f6e206973206d61646520617661696c61626c652c20796f75202831292061636365707420616e6420616772656520746f207468657365205465726d732028322920636f6e73656e7420746f2074686520636f6c6c656374696f6e2c207573652c20646973636c6f7375726520616e64206f746865722068616e646c696e67206f6620696e666f726d6174696f6e2061732064657363726962656420696e206f7572205072697661637920506f6c6963792020616e642028332920616e79206164646974696f6e616c207465726d732c2072756c657320616e6420636f6e646974696f6e73206f662070617274696369706174696f6e20697373756564206279204d6574614d61736b2066726f6d2074696d6520746f2074696d652e20496620796f7520646f206e6f7420616772656520746f20746865205465726d732c207468656e20796f75206d6179206e6f7420616363657373206f72207573652074686520436f6e74656e74206f722053657276696365732e0a0a232320322e204d6f64696669636174696f6e206f66205465726d73206f66205573652023230a0a45786365707420666f722053656374696f6e2031332c2070726f766964696e6720666f722062696e64696e67206172626974726174696f6e20616e6420776169766572206f6620636c61737320616374696f6e207269676874732c204d6574614d61736b207265736572766573207468652072696768742c2061742069747320736f6c652064697363726574696f6e2c20746f206d6f64696679206f72207265706c61636520746865205465726d73206f662055736520617420616e792074696d652e20546865206d6f73742063757272656e742076657273696f6e206f66207468657365205465726d732077696c6c20626520706f73746564206f6e206f757220536974652e20596f75207368616c6c20626520726573706f6e7369626c6520666f7220726576696577696e6720616e64206265636f6d696e672066616d696c696172207769746820616e792073756368206d6f64696669636174696f6e732e20557365206f662074686520536572766963657320627920796f7520616674657220616e79206d6f64696669636174696f6e20746f20746865205465726d7320636f6e737469747574657320796f757220616363657074616e6365206f6620746865205465726d73206f6620557365206173206d6f6469666965642e0a0a0a0a232320332e20456c69676962696c6974792023230a0a596f752068657265627920726570726573656e7420616e642077617272616e74207468617420796f75206172652066756c6c792061626c6520616e6420636f6d706574656e7420746f20656e74657220696e746f20746865207465726d732c20636f6e646974696f6e732c206f626c69676174696f6e732c2061666669726d6174696f6e732c20726570726573656e746174696f6e7320616e642077617272616e746965732073657420666f72746820696e207468657365205465726d7320616e6420746f20616269646520627920616e6420636f6d706c792077697468207468657365205465726d732e0a0a4d6574614d61736b206973206120676c6f62616c20706c6174666f726d20616e6420627920616363657373696e672074686520436f6e74656e74206f722053657276696365732c20796f752061726520726570726573656e74696e6720616e642077617272616e74696e6720746861742c20796f7520617265206f6620746865206c6567616c20616765206f66206d616a6f7269747920696e20796f7572206a7572697364696374696f6e20617320697320726571756972656420746f20616363657373207375636820536572766963657320616e6420436f6e74656e…16e79206368616e67657320746f20746869732073656374696f6e2e204368616e6765732077696c6c206265636f6d6520656666656374697665206f6e207468652036307468206461792c20616e642077696c6c206170706c792070726f73706563746976656c79206f6e6c7920746f20616e7920636c61696d732061726973696e67206166746572207468652036307468206461792e0a0a466f7220616e792064697370757465206e6f74207375626a65637420746f206172626974726174696f6e20796f7520616e64204d6574614d61736b20616772656520746f207375626d697420746f2074686520706572736f6e616c20616e64206578636c7573697665206a7572697364696374696f6e206f6620616e642076656e756520696e20746865206665646572616c20616e6420737461746520636f75727473206c6f636174656420696e204e657720596f726b2c204e657720596f726b2e20596f75206675727468657220616772656520746f206163636570742073657276696365206f662070726f63657373206279206d61696c2c20616e642068657265627920776169766520616e7920616e6420616c6c206a7572697364696374696f6e616c20616e642076656e756520646566656e736573206f746865727769736520617661696c61626c652e0a0a546865205465726d7320616e64207468652072656c6174696f6e73686970206265747765656e20796f7520616e64204d6574614d61736b207368616c6c20626520676f7665726e656420627920746865206c617773206f6620746865205374617465206f66204e657720596f726b20776974686f75742072656761726420746f20636f6e666c696374206f66206c61772070726f766973696f6e732e0a0a23232031342e2047656e6572616c20496e666f726d6174696f6e2023230a0a2323232031342e3120456e746972652041677265656d656e74202323230a0a5468657365205465726d732028616e6420616e79206164646974696f6e616c207465726d732c2072756c657320616e6420636f6e646974696f6e73206f662070617274696369706174696f6e2074686174204d6574614d61736b206d617920706f7374206f6e2074686520536572766963652920636f6e737469747574652074686520656e746972652061677265656d656e74206265747765656e20796f7520616e64204d6574614d61736b2077697468207265737065637420746f20746865205365727669636520616e64207375706572736564657320616e79207072696f722061677265656d656e74732c206f72616c206f72207772697474656e2c206265747765656e20796f7520616e64204d6574614d61736b2e20496e20746865206576656e74206f66206120636f6e666c696374206265747765656e207468657365205465726d7320616e6420746865206164646974696f6e616c207465726d732c2072756c657320616e6420636f6e646974696f6e73206f662070617274696369706174696f6e2c20746865206c61747465722077696c6c207072657661696c206f76657220746865205465726d7320746f2074686520657874656e74206f662074686520636f6e666c6963742e0a0a2323232031342e322057616976657220616e642053657665726162696c697479206f66205465726d73202323230a0a546865206661696c757265206f66204d6574614d61736b20746f206578657263697365206f7220656e666f72636520616e79207269676874206f722070726f766973696f6e206f6620746865205465726d73207368616c6c206e6f7420636f6e73746974757465206120776169766572206f662073756368207269676874206f722070726f766973696f6e2e20496620616e792070726f766973696f6e206f6620746865205465726d7320697320666f756e6420627920616e2061726269747261746f72206f7220636f757274206f6620636f6d706574656e74206a7572697364696374696f6e20746f20626520696e76616c69642c207468652070617274696573206e657665727468656c6573732061677265652074686174207468652061726269747261746f72206f7220636f7572742073686f756c6420656e646561766f7220746f20676976652065666665637420746f2074686520706172746965732720696e74656e74696f6e73206173207265666c656374656420696e207468652070726f766973696f6e2c20616e6420746865206f746865722070726f766973696f6e73206f6620746865205465726d732072656d61696e20696e2066756c6c20666f72636520616e64206566666563742e0a0a2323232031342e332053746174757465206f66204c696d69746174696f6e73202323230a0a596f752061677265652074686174207265676172646c657373206f6620616e792073746174757465206f72206c617720746f2074686520636f6e74726172792c20616e7920636c61696d206f72206361757365206f6620616374696f6e2061726973696e67206f7574206f66206f722072656c6174656420746f2074686520757365206f66207468652053657276696365206f7220746865205465726d73206d7573742062652066696c65642077697468696e206f6e65202831292079656172206166746572207375636820636c61696d206f72206361757365206f6620616374696f6e2061726f7365206f7220626520666f7265766572206261727265642e0a0a2323232031342e342053656374696f6e205469746c6573202323230a0a5468652073656374696f6e207469746c657320696e20746865205465726d732061726520666f7220636f6e76656e69656e6365206f6e6c7920616e642068617665206e6f206c6567616c206f7220636f6e747261637475616c206566666563742e0a0a2323232031342e3520436f6d6d756e69636174696f6e73202323230a0a55736572732077697468207175657374696f6e732c20636f6d706c61696e7473206f7220636c61696d732077697468207265737065637420746f207468652053657276696365206d617920636f6e74616374207573207573696e67207468652072656c6576616e7420636f6e7461637420696e666f726d6174696f6e2073657420666f7274682061626f766520616e6420617420636f6d6d756e69636174696f6e73406d6574616d61736b2e696f2e0a0a23232031352052656c61746564204c696e6b732023230a0a2a2a5b5465726d73206f66205573655d2868747470733a2f2f6d6574616d61736b2e696f2f7465726d732e68746d6c292a2a0a0a2a2a5b507269766163795d2868747470733a2f2f6d6574616d61736b2e696f2f707269766163792e68746d6c292a2a0a0a2a2a5b4174747269627574696f6e735d2868747470733a2f2f6d6574616d61736b2e696f2f6174747269627574696f6e732e68746d6c292a2a0a", + "from": "0x0d0c7188d9c72b019a5da9bca0d127680c22e659" + }, + "status": "unapproved", + "time": 1517889069339, + "type": "personal_sign" + } + }, + "unapprovedPersonalMsgCount": 0, + "unapprovedTypedMessages": { + "8997167822566869": { + "id": 8997167822566869, + "msgParams": { + "data": [ + {"type": "string", "name": "Message", "value": "Hi, Alice!"}, + {"type": "uint32", "name": "A number", "value": "1337"} + ], + "from": "0x0d0c7188d9c72b019a5da9bca0d127680c22e659" + }, + "status": "unapproved", + "time": 1617889069339, + "type": "eth_signTypedData" + } + }, + "unapprovedTypedMessagesCount": 1, + "keyringTypes": [ + "Simple Key Pair", + "HD Key Tree" + ], + "keyrings": [ + { + "type": "HD Key Tree", + "accounts": [ + "fdea65c8e26263f6d9a1b5de9555d2931a33b825", + "c5b8dbac4c1d3f152cdeb400e2313f309c410acb", + "2f8d4a878cfa04a6e60d46362f5644deab66572d" + ] + }, + { + "type": "Simple Key Pair", + "accounts": [ + "0xd85a4b6a394794842887b8284293d69163007bbb" + ] + } + ], + "selectedAddress": "0xd85a4b6a394794842887b8284293d69163007bbb", + "currentCurrency": "USD", + "provider": { + "type": "testnet" + }, + "shapeShiftTxList": [], + "lostAccounts": [], + "send": { + "gasLimit": "0xea60", + "gasPrice": "0xba43b7400", + "gasTotal": "0xb451dc41b578", + "tokenBalance": null, + "from": { + "address": "0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb", + "balance": "0x37452b1315889f80" + }, + "to": "0x2f8d4a878cfa04a6e60d46362f5644deab66572d", + "amount": "0x1bc16d674ec80000", + "memo": "", + "errors": {}, + "maxModeOn": false, + "editingTransactionId": null + } + }, + "appState": { + "menuOpen": false, + "currentView": { + "name": "confTx", + "detailView": null, + "context": 0 + }, + "accountDetail": { + "subview": "transactions" + }, + "modal": { + "modalState": {}, + "previousModalState": {} + }, + "transForward": true, + "isLoading": false, + "warning": null, + "scrollToBottom": false, + "forgottenPassword": null + }, + "identities": {} +} diff --git a/development/states/first-time.json b/development/states/first-time.json index 480839d59..6e7435db1 100644 --- a/development/states/first-time.json +++ b/development/states/first-time.json @@ -35,7 +35,8 @@ "type": "testnet" }, "shapeShiftTxList": [], - "lostAccounts": [] + "lostAccounts": [], + "tokens": [] }, "appState": { "menuOpen": false, @@ -48,7 +49,12 @@ }, "transForward": true, "isLoading": false, - "warning": null + "warning": null, + "modal": { + "modalState": {"name": null}, + "open": false, + "previousModalState": {"name": null} + } }, "identities": {}, "computedBalances": {} diff --git a/development/states/send-edit.json b/development/states/send-edit.json new file mode 100644 index 000000000..6ea8e64cd --- /dev/null +++ b/development/states/send-edit.json @@ -0,0 +1,154 @@ +{ + "metamask": { + "isInitialized": true, + "isUnlocked": true, + "featureFlags": {"betaUI": true}, + "rpcTarget": "https://rawtestrpc.metamask.io/", + "identities": { + "0xfdea65c8e26263f6d9a1b5de9555d2931a33b825": { + "address": "0xfdea65c8e26263f6d9a1b5de9555d2931a33b825", + "name": "Send Account 1" + }, + "0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb": { + "address": "0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb", + "name": "Send Account 2" + }, + "0x2f8d4a878cfa04a6e60d46362f5644deab66572d": { + "address": "0x2f8d4a878cfa04a6e60d46362f5644deab66572d", + "name": "Send Account 3" + }, + "0xd85a4b6a394794842887b8284293d69163007bbb": { + "address": "0xd85a4b6a394794842887b8284293d69163007bbb", + "name": "Send Account 4" + } + }, + "unapprovedTxs": {}, + "currentCurrency": "USD", + "conversionRate": 1200.88200327, + "conversionDate": 1489013762, + "noActiveNotices": true, + "frequentRpcList": [], + "network": "3", + "accounts": { + "0xfdea65c8e26263f6d9a1b5de9555d2931a33b825": { + "code": "0x", + "balance": "0x47c9d71831c76efe", + "nonce": "0x1b", + "address": "0xfdea65c8e26263f6d9a1b5de9555d2931a33b825" + }, + "0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb": { + "code": "0x", + "balance": "0x37452b1315889f80", + "nonce": "0xa", + "address": "0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb" + }, + "0x2f8d4a878cfa04a6e60d46362f5644deab66572d": { + "code": "0x", + "balance": "0x30c9d71831c76efe", + "nonce": "0x1c", + "address": "0x2f8d4a878cfa04a6e60d46362f5644deab66572d" + }, + "0xd85a4b6a394794842887b8284293d69163007bbb": { + "code": "0x", + "balance": "0x0", + "nonce": "0x0", + "address": "0xd85a4b6a394794842887b8284293d69163007bbb" + } + }, + "addressBook": [ + { + "address": "0x06195827297c7a80a443b6894d3bdb8824b43896", + "name": "Address Book Account 1" + } + ], + "tokens": [], + "transactions": {}, + "selectedAddressTxList": [], + "unapprovedTxs": { + "4768706228115573": { + "id": 4768706228115573, + "time": 1487363153561, + "status": "unapproved", + "gasMultiplier": 1, + "metamaskNetworkId": "3", + "txParams": { + "from": "0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb", + "to": "0x2f8d4a878cfa04a6e60d46362f5644deab66572d", + "value": "0x1bc16d674ec80000", + "metamaskId": 4768706228115573, + "metamaskNetworkId": "3", + "gas": "0xea60", + "gasPrice": "0xba43b7400" + } + } + }, + "unapprovedMsgs": {}, + "unapprovedMsgCount": 0, + "unapprovedPersonalMsgs": {}, + "unapprovedPersonalMsgCount": 0, + "keyringTypes": [ + "Simple Key Pair", + "HD Key Tree" + ], + "keyrings": [ + { + "type": "HD Key Tree", + "accounts": [ + "fdea65c8e26263f6d9a1b5de9555d2931a33b825", + "c5b8dbac4c1d3f152cdeb400e2313f309c410acb", + "2f8d4a878cfa04a6e60d46362f5644deab66572d" + ] + }, + { + "type": "Simple Key Pair", + "accounts": [ + "0xd85a4b6a394794842887b8284293d69163007bbb" + ] + } + ], + "selectedAddress": "0xd85a4b6a394794842887b8284293d69163007bbb", + "currentCurrency": "USD", + "provider": { + "type": "testnet" + }, + "shapeShiftTxList": [], + "lostAccounts": [], + "send": { + "gasLimit": "0xea60", + "gasPrice": "0xba43b7400", + "gasTotal": "0xb451dc41b578", + "tokenBalance": null, + "from": { + "address": "0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb", + "balance": "0x37452b1315889f80" + }, + "to": "0x2f8d4a878cfa04a6e60d46362f5644deab66572d", + "amount": "0x1bc16d674ec80000", + "memo": "", + "errors": {}, + "maxModeOn": false, + "editingTransactionId": null + } + }, + "appState": { + "menuOpen": false, + "currentView": { + "name": "confTx", + "detailView": null, + "context": 0 + }, + "accountDetail": { + "subview": "transactions" + }, + "modal": { + "modalState": {}, + "previousModalState": {} + }, + "transForward": true, + "isLoading": false, + "warning": null, + "scrollToBottom": false, + "forgottenPassword": null + }, + "identities": {} +} diff --git a/development/states/send-new-ui.json b/development/states/send-new-ui.json new file mode 100644 index 000000000..a0a2c66e4 --- /dev/null +++ b/development/states/send-new-ui.json @@ -0,0 +1,133 @@ +{ + "metamask": { + "isInitialized": true, + "isUnlocked": true, + "featureFlags": {"betaUI": true}, + "rpcTarget": "https://rawtestrpc.metamask.io/", + "identities": { + "0xfdea65c8e26263f6d9a1b5de9555d2931a33b825": { + "address": "0xfdea65c8e26263f6d9a1b5de9555d2931a33b825", + "name": "Send Account 1" + }, + "0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb": { + "address": "0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb", + "name": "Send Account 2" + }, + "0x2f8d4a878cfa04a6e60d46362f5644deab66572d": { + "address": "0x2f8d4a878cfa04a6e60d46362f5644deab66572d", + "name": "Send Account 3" + }, + "0xd85a4b6a394794842887b8284293d69163007bbb": { + "address": "0xd85a4b6a394794842887b8284293d69163007bbb", + "name": "Send Account 4" + } + }, + "unapprovedTxs": {}, + "currentCurrency": "USD", + "conversionRate": 1200.88200327, + "conversionDate": 1489013762, + "noActiveNotices": true, + "frequentRpcList": [], + "network": "3", + "accounts": { + "0xfdea65c8e26263f6d9a1b5de9555d2931a33b825": { + "code": "0x", + "balance": "0x47c9d71831c76efe", + "nonce": "0x1b", + "address": "0xfdea65c8e26263f6d9a1b5de9555d2931a33b825" + }, + "0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb": { + "code": "0x", + "balance": "0x37452b1315889f80", + "nonce": "0xa", + "address": "0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb" + }, + "0x2f8d4a878cfa04a6e60d46362f5644deab66572d": { + "code": "0x", + "balance": "0x30c9d71831c76efe", + "nonce": "0x1c", + "address": "0x2f8d4a878cfa04a6e60d46362f5644deab66572d" + }, + "0xd85a4b6a394794842887b8284293d69163007bbb": { + "code": "0x", + "balance": "0x0", + "nonce": "0x0", + "address": "0xd85a4b6a394794842887b8284293d69163007bbb" + } + }, + "addressBook": [ + { + "address": "0x06195827297c7a80a443b6894d3bdb8824b43896", + "name": "Address Book Account 1" + } + ], + "tokens": [], + "transactions": {}, + "selectedAddressTxList": [], + "unapprovedMsgs": {}, + "unapprovedMsgCount": 0, + "unapprovedPersonalMsgs": {}, + "unapprovedPersonalMsgCount": 0, + "keyringTypes": [ + "Simple Key Pair", + "HD Key Tree" + ], + "keyrings": [ + { + "type": "HD Key Tree", + "accounts": [ + "fdea65c8e26263f6d9a1b5de9555d2931a33b825", + "c5b8dbac4c1d3f152cdeb400e2313f309c410acb", + "2f8d4a878cfa04a6e60d46362f5644deab66572d" + ] + }, + { + "type": "Simple Key Pair", + "accounts": [ + "0xd85a4b6a394794842887b8284293d69163007bbb" + ] + } + ], + "selectedAddress": "0xd85a4b6a394794842887b8284293d69163007bbb", + "currentCurrency": "USD", + "provider": { + "type": "testnet" + }, + "shapeShiftTxList": [], + "lostAccounts": [], + "send": { + "gasLimit": null, + "gasPrice": null, + "gasTotal": "0xb451dc41b578", + "tokenBalance": null, + "from": "", + "to": "", + "amount": "0x0", + "memo": "", + "errors": {}, + "maxModeOn": false, + "editingTransactionId": null + } + }, + "appState": { + "menuOpen": false, + "currentView": { + "name": "accountDetail", + "detailView": null, + "context": "0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc" + }, + "accountDetail": { + "subview": "transactions" + }, + "modal": { + "modalState": {}, + "previousModalState": {} + }, + "transForward": true, + "isLoading": false, + "warning": null, + "scrollToBottom": false, + "forgottenPassword": null + }, + "identities": {} +} diff --git a/mascara/src/app/first-time/create-password-screen.js b/mascara/src/app/first-time/create-password-screen.js index 21d29d72b..0b36c6815 100644 --- a/mascara/src/app/first-time/create-password-screen.js +++ b/mascara/src/app/first-time/create-password-screen.js @@ -58,7 +58,7 @@ class CreatePasswordScreen extends Component { ? <LoadingScreen loadingMessage="Creating your new account" /> : ( <div> - <h2 className="alpha-warning">Warning This is Experemental software and is a Developer BETA </h2> + <h2 className="alpha-warning">Warning: This is Experimental software and is a Developer BETA</h2> <div className="first-view-main"> <div className="mascara-info"> <Mascot diff --git a/mascara/src/app/first-time/import-seed-phrase-screen.js b/mascara/src/app/first-time/import-seed-phrase-screen.js index d9a9dc835..2b01fa75d 100644 --- a/mascara/src/app/first-time/import-seed-phrase-screen.js +++ b/mascara/src/app/first-time/import-seed-phrase-screen.js @@ -67,27 +67,37 @@ class ImportSeedPhraseScreen extends Component { <div className="import-account__selector-label"> Enter your secret twelve word phrase here to restore your vault. </div> - <textarea - className="import-account__secret-phrase" - onChange={e => this.setState({seedPhrase: e.target.value})} - /> + <div className="import-account__input-wrapper"> + <label className="import-account__input-label">Wallet Seed</label> + <textarea + className="import-account__secret-phrase" + onChange={e => this.setState({seedPhrase: e.target.value})} + placeholder="Separate each word with a single space" + /> + </div> <span className="error" > {this.props.warning} </span> - <input - className="first-time-flow__input" - type="password" - placeholder="New Password (min 8 characters)" - onChange={e => this.setState({password: e.target.value})} - /> - <input - className="first-time-flow__input create-password__confirm-input" - type="password" - placeholder="Confirm Password" - onChange={e => this.setState({confirmPassword: e.target.value})} - /> + <div className="import-account__input-wrapper"> + <label className="import-account__input-label">New Password</label> + <input + className="first-time-flow__input" + type="password" + placeholder="New Password (min 8 characters)" + onChange={e => this.setState({password: e.target.value})} + /> + </div> + <div className="import-account__input-wrapper"> + <label className="import-account__input-label">Confirm Password</label> + <input + className="first-time-flow__input" + type="password" + placeholder="Confirm Password" + onChange={e => this.setState({confirmPassword: e.target.value})} + /> + </div> <button className="first-time-flow__button" onClick={this.onClick} diff --git a/mascara/src/app/first-time/index.css b/mascara/src/app/first-time/index.css index f91c72f0e..4314efbe6 100644 --- a/mascara/src/app/first-time/index.css +++ b/mascara/src/app/first-time/index.css @@ -44,10 +44,14 @@ .buy-ether { display: flex; flex-flow: column nowrap; - margin: 67px 0 0 146px; + margin: 67px 0 50px 146px; max-width: 35rem; } +.import-account { + max-width: initial; +} + @media only screen and (max-width: 575px) { .create-password, .unique-image, @@ -135,14 +139,16 @@ .backup-phrase__title, .import-account__title, .buy-ether__title { - width: 280px; color: #1B344D; font-size: 40px; - font-weight: 500; line-height: 51px; margin-bottom: 24px; } +.import-account__title { + margin-bottom: 10px; +} + .tou__title, .backup-phrase__title { width: 480px; @@ -288,9 +294,7 @@ .import-account__back-button:hover { margin-bottom: 18px; color: #22232C; - font-family: Montserrat Regular; font-size: 16px; - font-weight: 500; line-height: 21px; } @@ -311,6 +315,12 @@ button.backup-phrase__reveal-button:hover { .import-account__secret-phrase { font-size: 16px; + margin: initial; +} + +.import-account__secret-phrase::placeholder { + color: #9B9B9B; + font-weight: 200; } .backup-phrase__confirm-seed-options { @@ -350,9 +360,7 @@ button.backup-phrase__confirm-seed-option:hover { .import-account__selector-label { color: #1B344D; - font-family: Montserrat Light; - font-size: 18px; - line-height: 23px; + font-size: 16px; } .import-account__dropdown { @@ -394,7 +402,6 @@ button.backup-phrase__confirm-seed-option:hover { margin-top: 10px; width: 422px; color: #FF001F; - font-family: Montserrat Light; font-size: 16px; line-height: 21px; } @@ -402,10 +409,8 @@ button.backup-phrase__confirm-seed-option:hover { .import-account__input-label { margin-bottom: 9px; color: #1B344D; - font-family: Montserrat Light; font-size: 18px; line-height: 23px; - text-transform: uppercase; } .import-account__input { @@ -549,7 +554,7 @@ button.backup-phrase__confirm-seed-option:hover { width: 350px; font-size: 18px; line-height: 24px; - padding: 15px 28px; + padding: 15px; border: 1px solid #CDCDCD; background-color: #FFFFFF; } diff --git a/mock-dev.js b/mock-dev.js index 8827ddfdd..8b04352cf 100644 --- a/mock-dev.js +++ b/mock-dev.js @@ -20,6 +20,7 @@ const Root = require('./ui/app/root') const configureStore = require('./ui/app/store') const actions = require('./ui/app/actions') const states = require('./development/states') +const backGroundConnectionModifiers = require('./development/backGroundConnectionModifiers') const Selector = require('./development/selector') const MetamaskController = require('./app/scripts/metamask-controller') const firstTimeState = require('./app/scripts/first-time-state') @@ -85,6 +86,11 @@ actions.update = function(stateName) { } } +function modifyBackgroundConnection(backgroundConnectionModifier) { + const modifiedBackgroundConnection = Object.assign({}, controller.getApi(), backgroundConnectionModifier) + actions._setBackgroundConnection(modifiedBackgroundConnection) +} + var css = MetaMaskUiCss() injectCss(css) @@ -113,7 +119,14 @@ function startApp(){ }, }, 'Reset State'), - h(Selector, { actions, selectedKey: selectedView, states, store }), + h(Selector, { + actions, + selectedKey: selectedView, + states, + store, + modifyBackgroundConnection, + backGroundConnectionModifiers, + }), h('#app-content', { style: { diff --git a/package.json b/package.json index 69f590fe0..c5223c333 100644 --- a/package.json +++ b/package.json @@ -148,6 +148,7 @@ "react-redux": "^5.0.5", "react-select": "^1.0.0", "react-simple-file-input": "^2.0.0", + "react-tippy": "^1.2.2", "react-toggle-button": "^2.2.0", "react-tooltip-component": "^0.3.0", "react-transition-group": "^2.2.1", diff --git a/test/integration/lib/add-token.js b/test/integration/lib/add-token.js new file mode 100644 index 000000000..dd4251cc4 --- /dev/null +++ b/test/integration/lib/add-token.js @@ -0,0 +1,153 @@ +const reactTriggerChange = require('react-trigger-change') + +QUnit.module('Add token flow') + +QUnit.test('successful add token flow', (assert) => { + const done = assert.async() + runAddTokenFlowTest(assert) + .then(done) + .catch(err => { + assert.notOk(err, `Error was thrown: ${err.stack}`) + done() + }) +}) + +async function runAddTokenFlowTest (assert, done) { + const selectState = $('select') + selectState.val('add token') + reactTriggerChange(selectState[0]) + + await timeout(2000) + + // Check that no tokens have been added + assert.ok($('.token-list-item').length === 0, 'no tokens added') + + // Go to Add Token screen + let addTokenButton = $('button.btn-clear.wallet-view__add-token-button') + assert.ok(addTokenButton[0], 'add token button present') + addTokenButton[0].click() + + await timeout(1000) + + // Verify Add Token screen + let addTokenWrapper = $('.add-token__wrapper') + assert.ok(addTokenWrapper[0], 'add token wrapper renders') + + let addTokenTitle = $('.add-token__title') + assert.equal(addTokenTitle[0].textContent, 'Add Token', 'add token title is correct') + + // Cancel Add Token + const cancelAddTokenButton = $('button.btn-cancel.add-token__button') + assert.ok(cancelAddTokenButton[0], 'cancel add token button present') + cancelAddTokenButton.click() + + await timeout(1000) + + assert.ok($('.wallet-view')[0], 'cancelled and returned to account detail wallet view') + + // Return to Add Token Screen + addTokenButton = $('button.btn-clear.wallet-view__add-token-button') + assert.ok(addTokenButton[0], 'add token button present') + addTokenButton[0].click() + + await timeout(1000) + + // Verify Add Token Screen + addTokenWrapper = $('.add-token__wrapper') + addTokenTitle = $('.add-token__title') + assert.ok(addTokenWrapper[0], 'add token wrapper renders') + assert.equal(addTokenTitle[0].textContent, 'Add Token', 'add token title is correct') + + // Search for token + const searchInput = $('input.add-token__input') + searchInput.val('a') + reactTriggerChange(searchInput[0]) + + await timeout() + + // Click token to add + const tokenWrapper = $('div.add-token__token-wrapper') + assert.ok(tokenWrapper[0], 'token found') + const tokenImageProp = tokenWrapper.find('.add-token__token-icon').css('background-image') + const tokenImageUrl = tokenImageProp.slice(5, -2) + tokenWrapper[0].click() + + await timeout() + + // Click Next button + let nextButton = $('button.btn-clear.add-token__button') + assert.equal(nextButton[0].textContent, 'Next', 'next button rendered') + nextButton[0].click() + + await timeout() + + // Confirm Add token + assert.equal( + $('.add-token__description')[0].textContent, + 'Would you like to add these tokens?', + 'confirm add token rendered' + ) + assert.ok($('button.btn-clear.add-token__button')[0], 'confirm add token button found') + $('button.btn-clear.add-token__button')[0].click() + + await timeout(2000) + + // Verify added token image + let heroBalance = $('.hero-balance') + assert.ok(heroBalance, 'rendered hero balance') + assert.ok(tokenImageUrl.indexOf(heroBalance.find('img').attr('src')) > -1, 'token added') + + // Return to Add Token Screen + addTokenButton = $('button.btn-clear.wallet-view__add-token-button') + assert.ok(addTokenButton[0], 'add token button present') + addTokenButton[0].click() + + await timeout(1000) + + const addCustom = $('.add-token__add-custom') + assert.ok(addCustom[0], 'add custom token button present') + addCustom[0].click() + + await timeout() + + // Input token contract address + const customInput = $('input.add-token__add-custom-input') + customInput.val('0x177af043D3A1Aed7cc5f2397C70248Fc6cDC056c') + reactTriggerChange(customInput[0]) + + await timeout(1000) + + // Click Next button + nextButton = $('button.btn-clear.add-token__button') + assert.equal(nextButton[0].textContent, 'Next', 'next button rendered') + nextButton[0].click() + + await timeout(1000) + + // Verify symbol length error since contract address won't return symbol + const errorMessage = $('.add-token__add-custom-error-message') + assert.ok(errorMessage[0], 'error rendered') + $('button.btn-cancel.add-token__button')[0].click() + + await timeout(2000) + + // // Confirm Add token + // assert.equal( + // $('.add-token__description')[0].textContent, + // 'Would you like to add these tokens?', + // 'confirm add token rendered' + // ) + // assert.ok($('button.btn-clear.add-token__button')[0], 'confirm add token button found') + // $('button.btn-clear.add-token__button')[0].click() + + // // Verify added token image + // heroBalance = $('.hero-balance') + // assert.ok(heroBalance, 'rendered hero balance') + // assert.ok(heroBalance.find('.identicon')[0], 'token added') +} + +function timeout (time) { + return new Promise((resolve, reject) => { + setTimeout(resolve, time || 1500) + }) +} diff --git a/test/integration/lib/confirm-sig-requests.js b/test/integration/lib/confirm-sig-requests.js new file mode 100644 index 000000000..e49424c37 --- /dev/null +++ b/test/integration/lib/confirm-sig-requests.js @@ -0,0 +1,67 @@ +const reactTriggerChange = require('react-trigger-change') + +const PASSWORD = 'password123' + +QUnit.module('confirm sig requests') + +QUnit.test('successful confirmation of sig requests', (assert) => { + const done = assert.async() + runConfirmSigRequestsTest(assert).then(done).catch((err) => { + assert.notOk(err, `Error was thrown: ${err.stack}`) + done() + }) +}) + +async function runConfirmSigRequestsTest(assert, done) { + let selectState = $('select') + selectState.val('confirm sig requests') + reactTriggerChange(selectState[0]) + + await timeout(2000) + + let confirmSigHeadline = $('.request-signature__headline') + assert.equal(confirmSigHeadline[0].textContent, 'Your signature is being requested') + + let confirmSigRowValue = $('.request-signature__row-value') + assert.ok(confirmSigRowValue[0].textContent.match(/^\#\sTerms\sof\sUse/)) + + let confirmSigSignButton = $('.request-signature__footer__sign-button') + confirmSigSignButton[0].click() + + await timeout(2000) + + confirmSigHeadline = $('.request-signature__headline') + assert.equal(confirmSigHeadline[0].textContent, 'Your signature is being requested') + + let confirmSigMessage = $('.request-signature__notice') + assert.ok(confirmSigMessage[0].textContent.match(/^Signing\sthis\smessage/)) + + confirmSigRowValue = $('.request-signature__row-value') + assert.equal(confirmSigRowValue[0].textContent, '0x879a053d4800c6354e76c7985a865d2922c82fb5b3f4577b2fe08b998954f2e0') + + confirmSigSignButton = $('.request-signature__footer__sign-button') + confirmSigSignButton[0].click() + + await timeout(2000) + + confirmSigHeadline = $('.request-signature__headline') + assert.equal(confirmSigHeadline[0].textContent, 'Your signature is being requested') + + confirmSigRowValue = $('.request-signature__row-value') + assert.equal(confirmSigRowValue[0].textContent, 'Hi, Alice!') + assert.equal(confirmSigRowValue[1].textContent, '1337') + + confirmSigSignButton = $('.request-signature__footer__sign-button') + confirmSigSignButton[0].click() + + await timeout(2000) + + const txView = $('.tx-view') + assert.ok(txView[0], 'Should return to the account details screen after confirming') +} + +function timeout (time) { + return new Promise((resolve, reject) => { + setTimeout(resolve, time || 1500) + }) +}
\ No newline at end of file diff --git a/test/integration/lib/first-time.js b/test/integration/lib/first-time.js index 06325ab98..6e879dcd0 100644 --- a/test/integration/lib/first-time.js +++ b/test/integration/lib/first-time.js @@ -1,3 +1,4 @@ +const reactTriggerChange = require('react-trigger-change') const PASSWORD = 'password123' const runMascaraFirstTimeTest = require('./mascara-first-time') @@ -16,6 +17,12 @@ async function runFirstTimeUsageTest(assert, done) { return runMascaraFirstTimeTest(assert, done) } + const selectState = $('select') + selectState.val('first time') + reactTriggerChange(selectState[0]) + + await timeout(2000) + const app = $('#app-content') // recurse notices diff --git a/test/integration/lib/send-new-ui.js b/test/integration/lib/send-new-ui.js new file mode 100644 index 000000000..3456f2367 --- /dev/null +++ b/test/integration/lib/send-new-ui.js @@ -0,0 +1,225 @@ +const reactTriggerChange = require('react-trigger-change') + +const PASSWORD = 'password123' + +QUnit.module('new ui send flow') + +QUnit.test('successful send flow', (assert) => { + const done = assert.async() + runSendFlowTest(assert).then(done).catch((err) => { + assert.notOk(err, `Error was thrown: ${err.stack}`) + done() + }) +}) + +global.ethQuery = { + sendTransaction: () => {}, +} + +async function runSendFlowTest(assert, done) { + console.log('*** start runSendFlowTest') + const selectState = $('select') + selectState.val('send new ui') + reactTriggerChange(selectState[0]) + + await timeout(2000) + + const sendScreenButton = $('button.btn-clear.hero-balance-button') + assert.ok(sendScreenButton[1], 'send screen button present') + sendScreenButton[1].click() + + await timeout(1000) + + const sendTitle = $('.page-container__title') + assert.equal(sendTitle[0].textContent, 'Send ETH', 'Send screen title is correct') + + const sendCopy = $('.page-container__subtitle') + assert.equal(sendCopy[0].textContent, 'Only send ETH to an Ethereum address.', 'Send screen has copy') + + const sendFromField = $('.send-v2__form-field') + assert.ok(sendFromField[0], 'send screen has a from field') + + let sendFromFieldItemAddress = $('.account-list-item__account-name') + assert.equal(sendFromFieldItemAddress[0].textContent, 'Send Account 4', 'send from field shows correct account name') + + const sendFromFieldItem = $('.account-list-item') + sendFromFieldItem[0].click() + + await timeout() + + const sendFromDropdownList = $('.send-v2__from-dropdown__list') + assert.equal(sendFromDropdownList.children().length, 4, 'send from dropdown shows all accounts') + console.log(`!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! sendFromDropdownList.children()[1]`, sendFromDropdownList.children()[1]); + sendFromDropdownList.children()[1].click() + + await timeout() + + sendFromFieldItemAddress = $('.account-list-item__account-name') + console.log(`!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! sendFromFieldItemAddress[0]`, sendFromFieldItemAddress[0]); + assert.equal(sendFromFieldItemAddress[0].textContent, 'Send Account 2', 'send from field dropdown changes account name') + + let sendToFieldInput = $('.send-v2__to-autocomplete__input') + sendToFieldInput[0].focus() + + await timeout() + + const sendToDropdownList = $('.send-v2__from-dropdown__list') + assert.equal(sendToDropdownList.children().length, 5, 'send to dropdown shows all accounts and address book accounts') + + sendToDropdownList.children()[2].click() + + await timeout() + + const sendToAccountAddress = sendToFieldInput.val() + assert.equal(sendToAccountAddress, '0x2f8d4a878cfa04a6e60d46362f5644deab66572d', 'send to dropdown selects the correct address') + + const sendAmountField = $('.send-v2__form-row:eq(2)') + sendAmountField.find('.currency-display')[0].click() + + await timeout() + + const sendAmountFieldInput = sendAmountField.find('input:text') + sendAmountFieldInput.val('5.1') + reactTriggerChange(sendAmountField.find('input')[0]) + + await timeout() + + let errorMessage = $('.send-v2__error') + assert.equal(errorMessage[0].textContent, 'Insufficient funds.', 'send should render an insufficient fund error message') + + sendAmountFieldInput.val('2.0') + reactTriggerChange(sendAmountFieldInput[0]) + + await timeout() + errorMessage = $('.send-v2__error') + assert.equal(errorMessage.length, 0, 'send should stop rendering amount error message after amount is corrected') + + const sendGasField = $('.send-v2__gas-fee-display') + assert.equal( + sendGasField.find('.currency-display__input-wrapper > input').val(), + '0.000198', + 'send gas field should show estimated gas total' + ) + assert.equal( + sendGasField.find('.currency-display__converted-value')[0].textContent, + '0.24 USD', + 'send gas field should show estimated gas total converted to USD' + ) + + const sendGasOpenCustomizeModalButton = $('.send-v2__sliders-icon-container' + ) + sendGasOpenCustomizeModalButton[0].click() + + await timeout(1000) + + const customizeGasModal = $('.send-v2__customize-gas') + assert.ok(customizeGasModal[0], 'should render the customize gas modal') + + const customizeGasPriceInput = $('.send-v2__gas-modal-card').first().find('input') + customizeGasPriceInput.val(50) + reactTriggerChange(customizeGasPriceInput[0]) + const customizeGasLimitInput = $('.send-v2__gas-modal-card').last().find('input') + customizeGasLimitInput.val(60000) + reactTriggerChange(customizeGasLimitInput[0]) + + await timeout() + + const customizeGasSaveButton = $('.send-v2__customize-gas__save') + customizeGasSaveButton[0].click() + + await timeout() + + assert.equal( + sendGasField.find('.currency-display__input-wrapper > input').val(), + '0.003', + 'send gas field should show customized gas total' + ) + assert.equal( + sendGasField.find('.currency-display__converted-value')[0].textContent, + '3.60 USD', + 'send gas field should show customized gas total converted to USD' + ) + + const sendButton = $('button.btn-clear.page-container__footer-button') + assert.equal(sendButton[0].textContent, 'Next', 'next button rendered') + sendButton[0].click() + + await timeout(2000) + + selectState.val('send edit') + reactTriggerChange(selectState[0]) + + await timeout(2000) + + const confirmFromName = $('.confirm-screen-account-name').first() + assert.equal(confirmFromName[0].textContent, 'Send Account 2', 'confirm screen should show correct from name') + + const confirmToName = $('.confirm-screen-account-name').last() + assert.equal(confirmToName[0].textContent, 'Send Account 3', 'confirm screen should show correct to name') + + const confirmScreenRows = $('.confirm-screen-rows') + const confirmScreenGas = confirmScreenRows.find('.confirm-screen-row-info')[2] + assert.equal(confirmScreenGas.textContent, '3.6 USD', 'confirm screen should show correct gas') + const confirmScreenTotal = confirmScreenRows.find('.confirm-screen-row-info')[3] + assert.equal(confirmScreenTotal.textContent, '2405.36 USD', 'confirm screen should show correct total') + + const confirmScreenBackButton = $('.confirm-screen-back-button') + confirmScreenBackButton[0].click() + + await timeout(1000) + + const sendFromFieldItemInEdit = $('.account-list-item') + sendFromFieldItemInEdit[0].click() + + await timeout() + + const sendFromDropdownListInEdit = $('.send-v2__from-dropdown__list') + sendFromDropdownListInEdit.children()[2].click() + + await timeout() + + const sendToFieldInputInEdit = $('.send-v2__to-autocomplete__input') + sendToFieldInputInEdit[0].focus() + sendToFieldInputInEdit.val('0xd85a4b6a394794842887b8284293d69163007bbb') + + await timeout() + + const sendAmountFieldInEdit = $('.send-v2__form-row:eq(2)') + sendAmountFieldInEdit.find('.currency-display')[0].click() + + await timeout() + + const sendAmountFieldInputInEdit = sendAmountFieldInEdit.find('input:text') + sendAmountFieldInputInEdit.val('1.0') + reactTriggerChange(sendAmountFieldInputInEdit[0]) + + await timeout() + + const sendButtonInEdit = $('.btn-clear.page-container__footer-button') + assert.equal(sendButtonInEdit[0].textContent, 'Next', 'next button in edit rendered') + sendButtonInEdit[0].click() + + await timeout() + + // TODO: Need a way to mock background so that we can test correct transition from editing to confirm + selectState.val('confirm new ui') + reactTriggerChange(selectState[0]) + + await timeout(2000) + const confirmScreenConfirmButton = $('.confirm-screen-confirm-button') + console.log(`+++++++++++++++++++++++++++++++= confirmScreenConfirmButton[0]`, confirmScreenConfirmButton[0]); + confirmScreenConfirmButton[0].click() + + await timeout(2000) + + const txView = $('.tx-view') + console.log(`++++++++++++++++++++++++++++++++ txView[0]`, txView[0]); + + assert.ok(txView[0], 'Should return to the account details screen after confirming') +} + +function timeout (time) { + return new Promise((resolve, reject) => { + setTimeout(resolve, time || 1500) + }) +}
\ No newline at end of file diff --git a/ui/app/account-and-transaction-details.js b/ui/app/account-and-transaction-details.js index 60293de77..03101d37a 100644 --- a/ui/app/account-and-transaction-details.js +++ b/ui/app/account-and-transaction-details.js @@ -13,12 +13,7 @@ function AccountAndTransactionDetails () { } AccountAndTransactionDetails.prototype.render = function () { - return h('div', { - style: { - display: 'flex', - flex: '1 0 auto', - }, - }, [ + return h('div.account-and-transaction-details', [ // wallet h(WalletView, { style: { diff --git a/ui/app/accounts/import/index.js b/ui/app/accounts/import/index.js index 0c901c09b..71eb9ae23 100644 --- a/ui/app/accounts/import/index.js +++ b/ui/app/accounts/import/index.js @@ -37,7 +37,7 @@ AccountImportSubview.prototype.render = function () { h('div.new-account-import-form__select-section', [ - h('div.new-account-import-form__select-label', 'SELECT TYPE'), + h('div.new-account-import-form__select-label', 'Select Type'), h(Select, { className: 'new-account-import-form__select', diff --git a/ui/app/accounts/import/private-key.js b/ui/app/accounts/import/private-key.js index 43afbca87..12f3a6430 100644 --- a/ui/app/accounts/import/private-key.js +++ b/ui/app/accounts/import/private-key.js @@ -32,15 +32,20 @@ PrivateKeyImportView.prototype.render = function () { return ( h('div.new-account-import-form__private-key', [ - h('span.new-account-create-form__instruction', 'Paste your private key string here:'), - h('input.new-account-import-form__input-password', { - type: 'password', - id: 'private-key-box', - onKeyPress: () => this.createKeyringOnEnter(), - }), + h('div.new-account-import-form__private-key-password-container', [ - h('div.new-account-create-form__buttons', {}, [ + h('span.new-account-import-form__instruction', 'Paste your private key string here:'), + + h('input.new-account-import-form__input-password', { + type: 'password', + id: 'private-key-box', + onKeyPress: () => this.createKeyringOnEnter(), + }), + + ]), + + h('div.new-account-import-form__buttons', {}, [ h('button.new-account-create-form__button-cancel', { onClick: () => goHome(), diff --git a/ui/app/accounts/new-account/create-form.js b/ui/app/accounts/new-account/create-form.js index 494726ae4..a6b3bba4b 100644 --- a/ui/app/accounts/new-account/create-form.js +++ b/ui/app/accounts/new-account/create-form.js @@ -7,16 +7,19 @@ const actions = require('../../actions') class NewAccountCreateForm extends Component { constructor (props) { super(props) + const { numberOfExistingAccounts = 0 } = props const newAccountNumber = numberOfExistingAccounts + 1 this.state = { - newAccountName: `Account ${newAccountNumber}`, + newAccountName: '', + defaultAccountName: `Account ${newAccountNumber}`, } } render () { - const { newAccountName } = this.state + const { newAccountName, defaultAccountName } = this.state + return h('div.new-account-create-form', [ @@ -26,8 +29,8 @@ class NewAccountCreateForm extends Component { h('div.new-account-create-form__input-wrapper', {}, [ h('input.new-account-create-form__input', { - value: this.state.newAccountName, - placeholder: 'E.g. My new account', + value: newAccountName, + placeholder: defaultAccountName, onChange: event => this.setState({ newAccountName: event.target.value }), }, []), ]), @@ -41,7 +44,7 @@ class NewAccountCreateForm extends Component { ]), h('button.new-account-create-form__button-create', { - onClick: () => this.props.createAccount(newAccountName), + onClick: () => this.props.createAccount(newAccountName || defaultAccountName), }, [ 'CREATE', ]), diff --git a/ui/app/actions.js b/ui/app/actions.js index 977458023..f930a93c1 100644 --- a/ui/app/actions.js +++ b/ui/app/actions.js @@ -47,6 +47,8 @@ var actions = { SHOW_RESTORE_VAULT: 'SHOW_RESTORE_VAULT', FORGOT_PASSWORD: 'FORGOT_PASSWORD', forgotPassword: forgotPassword, + markPasswordForgotten, + unMarkPasswordForgotten, SHOW_INIT_MENU: 'SHOW_INIT_MENU', SHOW_NEW_VAULT_SEED: 'SHOW_NEW_VAULT_SEED', SHOW_INFO_PAGE: 'SHOW_INFO_PAGE', @@ -55,6 +57,7 @@ var actions = { SET_NEW_ACCOUNT_FORM: 'SET_NEW_ACCOUNT_FORM', unlockMetamask: unlockMetamask, unlockFailed: unlockFailed, + unlockSucceeded, showCreateVault: showCreateVault, showRestoreVault: showRestoreVault, showInitializeMenu: showInitializeMenu, @@ -80,6 +83,7 @@ var actions = { // unlock screen UNLOCK_IN_PROGRESS: 'UNLOCK_IN_PROGRESS', UNLOCK_FAILED: 'UNLOCK_FAILED', + UNLOCK_SUCCEEDED: 'UNLOCK_SUCCEEDED', UNLOCK_METAMASK: 'UNLOCK_METAMASK', LOCK_METAMASK: 'LOCK_METAMASK', tryUnlockMetamask: tryUnlockMetamask, @@ -286,6 +290,7 @@ function tryUnlockMetamask (password) { if (err) { dispatch(actions.unlockFailed(err.message)) } else { + dispatch(actions.unlockSucceeded()) dispatch(actions.transitionForward()) forceUpdateMetamaskState(dispatch) } @@ -832,6 +837,28 @@ function showRestoreVault () { } } +function markPasswordForgotten () { + return (dispatch) => { + dispatch(actions.showLoadingIndication()) + return background.markPasswordForgotten(() => { + dispatch(actions.hideLoadingIndication()) + dispatch(actions.forgotPassword()) + forceUpdateMetamaskState(dispatch) + }) + } +} + +function unMarkPasswordForgotten () { + return (dispatch) => { + dispatch(actions.showLoadingIndication()) + return background.unMarkPasswordForgotten(() => { + dispatch(actions.hideLoadingIndication()) + dispatch(actions.forgotPassword()) + forceUpdateMetamaskState(dispatch) + }) + } +} + function forgotPassword () { return { type: actions.FORGOT_PASSWORD, @@ -906,6 +933,13 @@ function unlockFailed (message) { } } +function unlockSucceeded (message) { + return { + type: actions.UNLOCK_SUCCEEDED, + value: message, + } +} + function unlockMetamask (account) { return { type: actions.UNLOCK_METAMASK, diff --git a/ui/app/app.js b/ui/app/app.js index df9eab03c..20dc65df3 100644 --- a/ui/app/app.js +++ b/ui/app/app.js @@ -80,7 +80,7 @@ function mapStateToProps (state) { menuOpen: state.appState.menuOpen, network: state.metamask.network, provider: state.metamask.provider, - forgottenPassword: state.appState.forgottenPassword, + forgottenPassword: state.metamask.forgottenPassword, lastUnreadNotice: state.metamask.lastUnreadNotice, lostAccounts: state.metamask.lostAccounts, frequentRpcList: state.metamask.frequentRpcList || [], @@ -358,20 +358,12 @@ App.prototype.renderPrimary = function () { }) } - // show initialize screen - if (!props.isInitialized || props.forgottenPassword) { - // show current view - log.debug('rendering an initialize screen') - switch (props.currentView.name) { - - case 'restoreVault': - log.debug('rendering restore vault screen') - return h(HDRestoreVaultScreen, {key: 'HDRestoreVaultScreen'}) - - default: - log.debug('rendering menu screen') - return h(InitializeMenuScreen, {key: 'menuScreenInit'}) - } + if (props.isInitialized && props.forgottenPassword) { + log.debug('rendering restore vault screen') + return h(HDRestoreVaultScreen, {key: 'HDRestoreVaultScreen'}) + } else if (!props.isInitialized) { + log.debug('rendering menu screen') + return h(InitializeMenuScreen, {key: 'menuScreenInit'}) } // show unlock screen diff --git a/ui/app/components/token-cell.js b/ui/app/components/token-cell.js index 59552f4a0..0332fde88 100644 --- a/ui/app/components/token-cell.js +++ b/ui/app/components/token-cell.js @@ -111,20 +111,24 @@ TokenCell.prototype.render = function () { network, }), - h('h.token-list-item__balance-wrapper', null, [ - h('h3.token-list-item__token-balance', `${string || 0} ${symbol}`), + h('div.token-list-item__balance-ellipsis', null, [ + h('div.token-list-item__balance-wrapper', null, [ + h('h3.token-list-item__token-balance', `${string || 0} ${symbol}`), + + showFiat && h('div.token-list-item__fiat-amount', { + style: {}, + }, formattedFiat), + ]), + + h('i.fa.fa-ellipsis-h.fa-lg.token-list-item__ellipsis.cursor-pointer', { + onClick: (e) => { + e.stopPropagation() + this.setState({ tokenMenuOpen: true }) + }, + }), - showFiat && h('div.token-list-item__fiat-amount', { - style: {}, - }, formattedFiat), ]), - h('i.fa.fa-ellipsis-h.fa-lg.token-list-item__ellipsis.cursor-pointer', { - onClick: (e) => { - e.stopPropagation() - this.setState({ tokenMenuOpen: true }) - }, - }), tokenMenuOpen && h(TokenMenuDropdown, { onClose: () => this.setState({ tokenMenuOpen: false }), diff --git a/ui/app/components/tooltip-v2.js b/ui/app/components/tooltip-v2.js new file mode 100644 index 000000000..133a0f16a --- /dev/null +++ b/ui/app/components/tooltip-v2.js @@ -0,0 +1,31 @@ +const Component = require('react').Component +const h = require('react-hyperscript') +const inherits = require('util').inherits +const ReactTippy = require('react-tippy').Tooltip + +module.exports = Tooltip + +inherits(Tooltip, Component) +function Tooltip () { + Component.call(this) +} + +Tooltip.prototype.render = function () { + const props = this.props + const { position, title, children, wrapperClassName } = props + + return h('div', { + className: wrapperClassName, + }, [ + + h(ReactTippy, { + title, + position: position || 'left', + trigger: 'mouseenter', + hideOnClick: false, + size: 'small', + arrow: true, + }, children), + + ]) +} diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js index b1ef83cee..34f27ca2a 100644 --- a/ui/app/components/wallet-view.js +++ b/ui/app/components/wallet-view.js @@ -2,8 +2,10 @@ const Component = require('react').Component const connect = require('react-redux').connect const h = require('react-hyperscript') const inherits = require('util').inherits +const classnames = require('classnames') const Identicon = require('./identicon') // const AccountDropdowns = require('./dropdowns/index.js').AccountDropdowns +const Tooltip = require('./tooltip-v2.js') const copyToClipboard = require('copy-to-clipboard') const actions = require('../actions') const BalanceComponent = require('./balance-component') @@ -45,6 +47,7 @@ function WalletView () { Component.call(this) this.state = { hasCopied: false, + copyToClipboardPressed: false, } } @@ -134,17 +137,30 @@ WalletView.prototype.render = function () { ]), ]), - - h('div.wallet-view__address', { - onClick: () => { - copyToClipboard(selectedAddress) - this.setState({ hasCopied: true }) - setTimeout(() => this.setState({ hasCopied: false }), 3000) - }, + h(Tooltip, { + position: 'bottom', + title: this.state.hasCopied ? 'Copied!' : 'Copy to clipboard', + wrapperClassName: 'wallet-view__tooltip', }, [ - this.state.hasCopied && 'Copied to Clipboard', - !this.state.hasCopied && `${selectedAddress.slice(0, 4)}...${selectedAddress.slice(-4)}`, - h('i.fa.fa-clipboard', { style: { marginLeft: '8px' } }), + h('button.wallet-view__address', { + className: classnames({ + 'wallet-view__address__pressed': this.state.copyToClipboardPressed, + }), + onClick: () => { + copyToClipboard(selectedAddress) + this.setState({ hasCopied: true }) + setTimeout(() => this.setState({ hasCopied: false }), 3000) + }, + onMouseDown: () => { + this.setState({ copyToClipboardPressed: true }) + }, + onMouseUp: () => { + this.setState({ copyToClipboardPressed: false }) + }, + }, [ + `${selectedAddress.slice(0, 4)}...${selectedAddress.slice(-4)}`, + h('i.fa.fa-clipboard', { style: { marginLeft: '8px' } }), + ]), ]), this.renderWalletBalance(), diff --git a/ui/app/css/itcss/components/hero-balance.scss b/ui/app/css/itcss/components/hero-balance.scss index ccc9a0118..4af0c2c55 100644 --- a/ui/app/css/itcss/components/hero-balance.scss +++ b/ui/app/css/itcss/components/hero-balance.scss @@ -71,6 +71,22 @@ font-size: 105%; } } + + @media #{$sub-mid-size-breakpoint-range} { + margin-left: .4em; + margin-right: .4em; + justify-content: flex-start; + align-items: flex-start; + + .token-amount { + font-size: 1rem; + } + + .fiat-amount { + margin-top: .25%; + font-size: 1rem; + } + } } .hero-balance-buttons { @@ -91,4 +107,12 @@ .hero-balance-button { width: 6rem; + + @media #{$sub-mid-size-breakpoint-range} { + padding: 0.4rem; + width: 4rem; + display: flex; + flex: 1; + justify-content: center; + } } diff --git a/ui/app/css/itcss/components/index.scss b/ui/app/css/itcss/components/index.scss index d1b9b6277..0219f9fb2 100644 --- a/ui/app/css/itcss/components/index.scss +++ b/ui/app/css/itcss/components/index.scss @@ -53,3 +53,5 @@ @import './editable-label.scss'; @import './new-account.scss'; + +@import './tooltip.scss'; diff --git a/ui/app/css/itcss/components/new-account.scss b/ui/app/css/itcss/components/new-account.scss index c5e4ea761..81f919df3 100644 --- a/ui/app/css/itcss/components/new-account.scss +++ b/ui/app/css/itcss/components/new-account.scss @@ -55,11 +55,17 @@ } .new-account-import-form { + display: flex; + flex-flow: column; + align-items: center; + padding: 0 30px; + &__select-section { display: flex; - justify-content: space-evenly; + justify-content: space-between; align-items: center; margin-top: 29px; + width: 100%; } &__select-label { @@ -91,19 +97,25 @@ } } + &__private-key-password-container { + display: flex; + flex-flow: column; + align-items: center; + width: 100%; + } + &__instruction { color: $scorpion; font-family: Roboto; font-size: 16px; line-height: 21px; align-self: flex-start; - margin-left: 30px; } &__private-key { display: flex; flex-flow: column; - align-items: center; + align-items: flex-start; margin-top: 34px; } @@ -126,6 +138,13 @@ align-items: center; margin-top: 29px; } + + &__buttons { + margin-top: 39px; + display: flex; + width: 100%; + justify-content: space-between; + } } .new-account-create-form { diff --git a/ui/app/css/itcss/components/newui-sections.scss b/ui/app/css/itcss/components/newui-sections.scss index 1c26882b5..73faebe8b 100644 --- a/ui/app/css/itcss/components/newui-sections.scss +++ b/ui/app/css/itcss/components/newui-sections.scss @@ -1,3 +1,6 @@ +$sub-mid-size-breakpoint: 667px; +$sub-mid-size-breakpoint-range: "screen and (min-width: #{$break-large}) and (max-width: #{$sub-mid-size-breakpoint})"; + /* NewUI Container Elements */ @@ -20,6 +23,12 @@ $wallet-view-bg: $alabaster; display: none; } +//Account and transaction details +.account-and-transaction-details { + display: flex; + flex: 1 0 auto; +} + // tx view .tx-view { @@ -60,6 +69,10 @@ $wallet-view-bg: $alabaster; overflow-x: hidden; } + @media #{$sub-mid-size-breakpoint-range} { + min-width: 160px; + } + .wallet-view-account-details { flex: 0 0 auto; } @@ -89,6 +102,13 @@ $wallet-view-bg: $alabaster; flex: 0 0 auto; } + &__tooltip { + display: flex; + justify-content: center; + align-items: center; + padding: 24px; + } + &__address { border-radius: 3px; background-color: $alto; @@ -96,10 +116,13 @@ $wallet-view-bg: $alabaster; font-size: 14px; line-height: 12px; padding: 4px 12px; - margin: 24px auto; font-weight: 300; cursor: pointer; flex: 0 0 auto; + + &__pressed { + background-color: $manatee, + } } &__sidebar-close { diff --git a/ui/app/css/itcss/components/send.scss b/ui/app/css/itcss/components/send.scss index 7a6e2823b..fd73275e0 100644 --- a/ui/app/css/itcss/components/send.scss +++ b/ui/app/css/itcss/components/send.scss @@ -533,7 +533,6 @@ @media screen and (max-width: $break-small) { padding: 13px 0; margin: 0; - height: 0; overflow-y: auto; flex: 1 1 auto; } diff --git a/ui/app/css/itcss/components/token-list.scss b/ui/app/css/itcss/components/token-list.scss index e24bf812b..9dc4f1055 100644 --- a/ui/app/css/itcss/components/token-list.scss +++ b/ui/app/css/itcss/components/token-list.scss @@ -15,7 +15,7 @@ $wallet-balance-breakpoint-range: "screen and (min-width: #{$break-large}) and ( font-size: 1.5rem; @media #{$wallet-balance-breakpoint-range} { - font-size: 105%; + font-size: 95%; } } @@ -41,17 +41,22 @@ $wallet-balance-breakpoint-range: "screen and (min-width: #{$break-large}) and ( &__identicon { margin-right: 15px; border: '1px solid #dedede'; + min-width: 50px; @media #{$wallet-balance-breakpoint-range} { margin-right: 4%; } } + &__balance-ellipsis { + display: flex; + align-items: center; + width: 100%; + } + &__ellipsis { - // position: absolute; - // top: 20px; - // right: 24px; line-height: 45px; + margin-left: 5px; } &__balance-wrapper { @@ -61,7 +66,7 @@ $wallet-balance-breakpoint-range: "screen and (min-width: #{$break-large}) and ( .token-menu-dropdown { height: 55px; - width: 191px; + width: 80%; border-radius: 4px; background-color: rgba(0, 0, 0, .82); box-shadow: 0 2px 4px 0 rgba(0, 0, 0, .5); @@ -70,6 +75,10 @@ $wallet-balance-breakpoint-range: "screen and (min-width: #{$break-large}) and ( right: 25px; z-index: 2000; + @media #{$wallet-balance-breakpoint-range} { + right: 18px; + } + &__close-area { position: fixed; top: 0; @@ -81,7 +90,7 @@ $wallet-balance-breakpoint-range: "screen and (min-width: #{$break-large}) and ( } &__container { - padding: 16px 34px 32px; + padding: 16px; z-index: 2200; position: relative; } diff --git a/ui/app/css/itcss/components/tooltip.scss b/ui/app/css/itcss/components/tooltip.scss new file mode 100644 index 000000000..78325865e --- /dev/null +++ b/ui/app/css/itcss/components/tooltip.scss @@ -0,0 +1,7 @@ +.metamask-tooltip { + padding: 5px !important; +} + +// needed for react-tippy +// copied from node_modules/react-tippy/dist/tippy.css +.tippy-touch{cursor:pointer!important}.tippy-notransition{transition:none!important}.tippy-popper{max-width:400px;-webkit-perspective:800px;perspective:800px;z-index:9999;outline:0;transition-timing-function:cubic-bezier(.165,.84,.44,1);pointer-events:none}.tippy-popper.html-template{max-width:96%;max-width:calc(100% - 20px)}.tippy-popper[x-placement^=top] [x-arrow]{border-top:7px solid #333;border-right:7px solid transparent;border-left:7px solid transparent;bottom:-7px;margin:0 9px}.tippy-popper[x-placement^=top] [x-arrow].arrow-small{border-top:5px solid #333;border-right:5px solid transparent;border-left:5px solid transparent;bottom:-5px}.tippy-popper[x-placement^=top] [x-arrow].arrow-big{border-top:10px solid #333;border-right:10px solid transparent;border-left:10px solid transparent;bottom:-10px}.tippy-popper[x-placement^=top] [x-circle]{-webkit-transform-origin:0 33%;transform-origin:0 33%}.tippy-popper[x-placement^=top] [x-circle].enter{-webkit-transform:scale(1) translate(-50%,-55%);transform:scale(1) translate(-50%,-55%);opacity:1}.tippy-popper[x-placement^=top] [x-circle].leave{-webkit-transform:scale(.15) translate(-50%,-50%);transform:scale(.15) translate(-50%,-50%);opacity:0}.tippy-popper[x-placement^=top] .tippy-tooltip.light-theme [x-circle]{background-color:#fff}.tippy-popper[x-placement^=top] .tippy-tooltip.light-theme [x-arrow]{border-top:7px solid #fff;border-right:7px solid transparent;border-left:7px solid transparent}.tippy-popper[x-placement^=top] .tippy-tooltip.light-theme [x-arrow].arrow-small{border-top:5px solid #fff;border-right:5px solid transparent;border-left:5px solid transparent}.tippy-popper[x-placement^=top] .tippy-tooltip.light-theme [x-arrow].arrow-big{border-top:10px solid #fff;border-right:10px solid transparent;border-left:10px solid transparent}.tippy-popper[x-placement^=top] .tippy-tooltip.transparent-theme [x-circle]{background-color:rgba(0,0,0,.7)}.tippy-popper[x-placement^=top] .tippy-tooltip.transparent-theme [x-arrow]{border-top:7px solid rgba(0,0,0,.7);border-right:7px solid transparent;border-left:7px solid transparent}.tippy-popper[x-placement^=top] .tippy-tooltip.transparent-theme [x-arrow].arrow-small{border-top:5px solid rgba(0,0,0,.7);border-right:5px solid transparent;border-left:5px solid transparent}.tippy-popper[x-placement^=top] .tippy-tooltip.transparent-theme [x-arrow].arrow-big{border-top:10px solid rgba(0,0,0,.7);border-right:10px solid transparent;border-left:10px solid transparent}.tippy-popper[x-placement^=top] [data-animation=perspective]{-webkit-transform-origin:bottom;transform-origin:bottom}.tippy-popper[x-placement^=top] [data-animation=perspective].enter{opacity:1;-webkit-transform:translateY(-10px) rotateX(0);transform:translateY(-10px) rotateX(0)}.tippy-popper[x-placement^=top] [data-animation=perspective].leave{opacity:0;-webkit-transform:translateY(0) rotateX(90deg);transform:translateY(0) rotateX(90deg)}.tippy-popper[x-placement^=top] [data-animation=fade].enter{opacity:1;-webkit-transform:translateY(-10px);transform:translateY(-10px)}.tippy-popper[x-placement^=top] [data-animation=fade].leave{opacity:0;-webkit-transform:translateY(-10px);transform:translateY(-10px)}.tippy-popper[x-placement^=top] [data-animation=shift].enter{opacity:1;-webkit-transform:translateY(-10px);transform:translateY(-10px)}.tippy-popper[x-placement^=top] [data-animation=shift].leave{opacity:0;-webkit-transform:translateY(0);transform:translateY(0)}.tippy-popper[x-placement^=top] [data-animation=scale].enter{opacity:1;-webkit-transform:translateY(-10px) scale(1);transform:translateY(-10px) scale(1)}.tippy-popper[x-placement^=top] [data-animation=scale].leave{opacity:0;-webkit-transform:translateY(0) scale(0);transform:translateY(0) scale(0)}.tippy-popper[x-placement^=bottom] [x-arrow]{border-bottom:7px solid #333;border-right:7px solid transparent;border-left:7px solid transparent;top:-7px;margin:0 9px}.tippy-popper[x-placement^=bottom] [x-arrow].arrow-small{border-bottom:5px solid #333;border-right:5px solid transparent;border-left:5px solid transparent;top:-5px}.tippy-popper[x-placement^=bottom] [x-arrow].arrow-big{border-bottom:10px solid #333;border-right:10px solid transparent;border-left:10px solid transparent;top:-10px}.tippy-popper[x-placement^=bottom] [x-circle]{-webkit-transform-origin:0 -50%;transform-origin:0 -50%}.tippy-popper[x-placement^=bottom] [x-circle].enter{-webkit-transform:scale(1) translate(-50%,-45%);transform:scale(1) translate(-50%,-45%);opacity:1}.tippy-popper[x-placement^=bottom] [x-circle].leave{-webkit-transform:scale(.15) translate(-50%,-5%);transform:scale(.15) translate(-50%,-5%);opacity:0}.tippy-popper[x-placement^=bottom] .tippy-tooltip.light-theme [x-circle]{background-color:#fff}.tippy-popper[x-placement^=bottom] .tippy-tooltip.light-theme [x-arrow]{border-bottom:7px solid #fff;border-right:7px solid transparent;border-left:7px solid transparent}.tippy-popper[x-placement^=bottom] .tippy-tooltip.light-theme [x-arrow].arrow-small{border-bottom:5px solid #fff;border-right:5px solid transparent;border-left:5px solid transparent}.tippy-popper[x-placement^=bottom] .tippy-tooltip.light-theme [x-arrow].arrow-big{border-bottom:10px solid #fff;border-right:10px solid transparent;border-left:10px solid transparent}.tippy-popper[x-placement^=bottom] .tippy-tooltip.transparent-theme [x-circle]{background-color:rgba(0,0,0,.7)}.tippy-popper[x-placement^=bottom] .tippy-tooltip.transparent-theme [x-arrow]{border-bottom:7px solid rgba(0,0,0,.7);border-right:7px solid transparent;border-left:7px solid transparent}.tippy-popper[x-placement^=bottom] .tippy-tooltip.transparent-theme [x-arrow].arrow-small{border-bottom:5px solid rgba(0,0,0,.7);border-right:5px solid transparent;border-left:5px solid transparent}.tippy-popper[x-placement^=bottom] .tippy-tooltip.transparent-theme [x-arrow].arrow-big{border-bottom:10px solid rgba(0,0,0,.7);border-right:10px solid transparent;border-left:10px solid transparent}.tippy-popper[x-placement^=bottom] [data-animation=perspective]{-webkit-transform-origin:top;transform-origin:top}.tippy-popper[x-placement^=bottom] [data-animation=perspective].enter{opacity:1;-webkit-transform:translateY(10px) rotateX(0);transform:translateY(10px) rotateX(0)}.tippy-popper[x-placement^=bottom] [data-animation=perspective].leave{opacity:0;-webkit-transform:translateY(0) rotateX(-90deg);transform:translateY(0) rotateX(-90deg)}.tippy-popper[x-placement^=bottom] [data-animation=fade].enter{opacity:1;-webkit-transform:translateY(10px);transform:translateY(10px)}.tippy-popper[x-placement^=bottom] [data-animation=fade].leave{opacity:0;-webkit-transform:translateY(10px);transform:translateY(10px)}.tippy-popper[x-placement^=bottom] [data-animation=shift].enter{opacity:1;-webkit-transform:translateY(10px);transform:translateY(10px)}.tippy-popper[x-placement^=bottom] [data-animation=shift].leave{opacity:0;-webkit-transform:translateY(0);transform:translateY(0)}.tippy-popper[x-placement^=bottom] [data-animation=scale].enter{opacity:1;-webkit-transform:translateY(10px) scale(1);transform:translateY(10px) scale(1)}.tippy-popper[x-placement^=bottom] [data-animation=scale].leave{opacity:0;-webkit-transform:translateY(0) scale(0);transform:translateY(0) scale(0)}.tippy-popper[x-placement^=left] [x-arrow]{border-left:7px solid #333;border-top:7px solid transparent;border-bottom:7px solid transparent;right:-7px;margin:6px 0}.tippy-popper[x-placement^=left] [x-arrow].arrow-small{border-left:5px solid #333;border-top:5px solid transparent;border-bottom:5px solid transparent;right:-5px}.tippy-popper[x-placement^=left] [x-arrow].arrow-big{border-left:10px solid #333;border-top:10px solid transparent;border-bottom:10px solid transparent;right:-10px}.tippy-popper[x-placement^=left] [x-circle]{-webkit-transform-origin:50% 0;transform-origin:50% 0}.tippy-popper[x-placement^=left] [x-circle].enter{-webkit-transform:scale(1) translate(-50%,-50%);transform:scale(1) translate(-50%,-50%);opacity:1}.tippy-popper[x-placement^=left] [x-circle].leave{-webkit-transform:scale(.15) translate(-50%,-50%);transform:scale(.15) translate(-50%,-50%);opacity:0}.tippy-popper[x-placement^=left] .tippy-tooltip.light-theme [x-circle]{background-color:#fff}.tippy-popper[x-placement^=left] .tippy-tooltip.light-theme [x-arrow]{border-left:7px solid #fff;border-top:7px solid transparent;border-bottom:7px solid transparent}.tippy-popper[x-placement^=left] .tippy-tooltip.light-theme [x-arrow].arrow-small{border-left:5px solid #fff;border-top:5px solid transparent;border-bottom:5px solid transparent}.tippy-popper[x-placement^=left] .tippy-tooltip.light-theme [x-arrow].arrow-big{border-left:10px solid #fff;border-top:10px solid transparent;border-bottom:10px solid transparent}.tippy-popper[x-placement^=left] .tippy-tooltip.transparent-theme [x-circle]{background-color:rgba(0,0,0,.7)}.tippy-popper[x-placement^=left] .tippy-tooltip.transparent-theme [x-arrow]{border-left:7px solid rgba(0,0,0,.7);border-top:7px solid transparent;border-bottom:7px solid transparent}.tippy-popper[x-placement^=left] .tippy-tooltip.transparent-theme [x-arrow].arrow-small{border-left:5px solid rgba(0,0,0,.7);border-top:5px solid transparent;border-bottom:5px solid transparent}.tippy-popper[x-placement^=left] .tippy-tooltip.transparent-theme [x-arrow].arrow-big{border-left:10px solid rgba(0,0,0,.7);border-top:10px solid transparent;border-bottom:10px solid transparent}.tippy-popper[x-placement^=left] [data-animation=perspective]{-webkit-transform-origin:right;transform-origin:right}.tippy-popper[x-placement^=left] [data-animation=perspective].enter{opacity:1;-webkit-transform:translateX(-10px) rotateY(0);transform:translateX(-10px) rotateY(0)}.tippy-popper[x-placement^=left] [data-animation=perspective].leave{opacity:0;-webkit-transform:translateX(0) rotateY(-90deg);transform:translateX(0) rotateY(-90deg)}.tippy-popper[x-placement^=left] [data-animation=fade].enter{opacity:1;-webkit-transform:translateX(-10px);transform:translateX(-10px)}.tippy-popper[x-placement^=left] [data-animation=fade].leave{opacity:0;-webkit-transform:translateX(-10px);transform:translateX(-10px)}.tippy-popper[x-placement^=left] [data-animation=shift].enter{opacity:1;-webkit-transform:translateX(-10px);transform:translateX(-10px)}.tippy-popper[x-placement^=left] [data-animation=shift].leave{opacity:0;-webkit-transform:translateX(0);transform:translateX(0)}.tippy-popper[x-placement^=left] [data-animation=scale].enter{opacity:1;-webkit-transform:translateX(-10px) scale(1);transform:translateX(-10px) scale(1)}.tippy-popper[x-placement^=left] [data-animation=scale].leave{opacity:0;-webkit-transform:translateX(0) scale(0);transform:translateX(0) scale(0)}.tippy-popper[x-placement^=right] [x-arrow]{border-right:7px solid #333;border-top:7px solid transparent;border-bottom:7px solid transparent;left:-7px;margin:6px 0}.tippy-popper[x-placement^=right] [x-arrow].arrow-small{border-right:5px solid #333;border-top:5px solid transparent;border-bottom:5px solid transparent;left:-5px}.tippy-popper[x-placement^=right] [x-arrow].arrow-big{border-right:10px solid #333;border-top:10px solid transparent;border-bottom:10px solid transparent;left:-10px}.tippy-popper[x-placement^=right] [x-circle]{-webkit-transform-origin:-50% 0;transform-origin:-50% 0}.tippy-popper[x-placement^=right] [x-circle].enter{-webkit-transform:scale(1) translate(-50%,-50%);transform:scale(1) translate(-50%,-50%);opacity:1}.tippy-popper[x-placement^=right] [x-circle].leave{-webkit-transform:scale(.15) translate(-50%,-50%);transform:scale(.15) translate(-50%,-50%);opacity:0}.tippy-popper[x-placement^=right] .tippy-tooltip.light-theme [x-circle]{background-color:#fff}.tippy-popper[x-placement^=right] .tippy-tooltip.light-theme [x-arrow]{border-right:7px solid #fff;border-top:7px solid transparent;border-bottom:7px solid transparent}.tippy-popper[x-placement^=right] .tippy-tooltip.light-theme [x-arrow].arrow-small{border-right:5px solid #fff;border-top:5px solid transparent;border-bottom:5px solid transparent}.tippy-popper[x-placement^=right] .tippy-tooltip.light-theme [x-arrow].arrow-big{border-right:10px solid #fff;border-top:10px solid transparent;border-bottom:10px solid transparent}.tippy-popper[x-placement^=right] .tippy-tooltip.transparent-theme [x-circle]{background-color:rgba(0,0,0,.7)}.tippy-popper[x-placement^=right] .tippy-tooltip.transparent-theme [x-arrow]{border-right:7px solid rgba(0,0,0,.7);border-top:7px solid transparent;border-bottom:7px solid transparent}.tippy-popper[x-placement^=right] .tippy-tooltip.transparent-theme [x-arrow].arrow-small{border-right:5px solid rgba(0,0,0,.7);border-top:5px solid transparent;border-bottom:5px solid transparent}.tippy-popper[x-placement^=right] .tippy-tooltip.transparent-theme [x-arrow].arrow-big{border-right:10px solid rgba(0,0,0,.7);border-top:10px solid transparent;border-bottom:10px solid transparent}.tippy-popper[x-placement^=right] [data-animation=perspective]{-webkit-transform-origin:left;transform-origin:left}.tippy-popper[x-placement^=right] [data-animation=perspective].enter{opacity:1;-webkit-transform:translateX(10px) rotateY(0);transform:translateX(10px) rotateY(0)}.tippy-popper[x-placement^=right] [data-animation=perspective].leave{opacity:0;-webkit-transform:translateX(0) rotateY(90deg);transform:translateX(0) rotateY(90deg)}.tippy-popper[x-placement^=right] [data-animation=fade].enter{opacity:1;-webkit-transform:translateX(10px);transform:translateX(10px)}.tippy-popper[x-placement^=right] [data-animation=fade].leave{opacity:0;-webkit-transform:translateX(10px);transform:translateX(10px)}.tippy-popper[x-placement^=right] [data-animation=shift].enter{opacity:1;-webkit-transform:translateX(10px);transform:translateX(10px)}.tippy-popper[x-placement^=right] [data-animation=shift].leave{opacity:0;-webkit-transform:translateX(0);transform:translateX(0)}.tippy-popper[x-placement^=right] [data-animation=scale].enter{opacity:1;-webkit-transform:translateX(10px) scale(1);transform:translateX(10px) scale(1)}.tippy-popper[x-placement^=right] [data-animation=scale].leave{opacity:0;-webkit-transform:translateX(0) scale(0);transform:translateX(0) scale(0)}.tippy-popper .tippy-tooltip.transparent-theme{background-color:rgba(0,0,0,.7)}.tippy-popper .tippy-tooltip.transparent-theme[data-animatefill]{background-color:transparent}.tippy-popper .tippy-tooltip.light-theme{color:#26323d;box-shadow:0 4px 20px 4px rgba(0,20,60,.1),0 4px 80px -8px rgba(0,20,60,.2);background-color:#fff}.tippy-popper .tippy-tooltip.light-theme[data-animatefill]{background-color:transparent}.tippy-tooltip{position:relative;color:#fff;border-radius:4px;font-size:.95rem;padding:.4rem .8rem;text-align:center;will-change:transform;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;background-color:#333}.tippy-tooltip--small{padding:.25rem .5rem;font-size:.8rem}.tippy-tooltip--big{padding:.6rem 1.2rem;font-size:1.2rem}.tippy-tooltip[data-animatefill]{overflow:hidden;background-color:transparent}.tippy-tooltip[data-interactive]{pointer-events:auto}.tippy-tooltip[data-inertia]{transition-timing-function:cubic-bezier(.53,2,.36,.85)}.tippy-tooltip [x-arrow]{position:absolute;width:0;height:0}.tippy-tooltip [x-circle]{position:absolute;will-change:transform;background-color:#333;border-radius:50%;width:130%;width:calc(110% + 2rem);left:50%;top:50%;z-index:-1;overflow:hidden;transition:all ease}.tippy-tooltip [x-circle]:before{content:"";padding-top:90%;float:left}@media (max-width:450px){.tippy-popper{max-width:96%;max-width:calc(100% - 20px)}} diff --git a/ui/app/css/itcss/generic/index.scss b/ui/app/css/itcss/generic/index.scss index 9d55324e3..75f823320 100644 --- a/ui/app/css/itcss/generic/index.scss +++ b/ui/app/css/itcss/generic/index.scss @@ -69,3 +69,117 @@ textarea.large-input { input.large-input { height: 36px; } + +.page-container { + width: 400px; + background-color: $white; + box-shadow: 0 0 7px 0 rgba(0, 0, 0, .08); + z-index: 25; + display: flex; + flex-flow: column; + + &__header { + display: flex; + flex-flow: column; + border-bottom: 1px solid $geyser; + padding: 1.6rem 1rem; + flex: 0 0 auto; + } + + &__footer { + display: flex; + flex-flow: row; + justify-content: center; + border-top: 1px solid $geyser; + padding: 1.6rem; + flex: 0 0 auto; + } + + &__footer-button { + width: 165px; + height: 60px; + font-size: 1rem; + text-transform: uppercase; + margin-right: 1rem; + + &:last-of-type { + margin-right: 0; + } + } + + &__title { + color: $tundora; + font-family: Roboto; + font-size: 2rem; + font-weight: 500; + line-height: initial; + } + + &__subtitle { + padding-top: .5rem; + line-height: initial; + font-size: .9rem; + } + + &__tabs { + padding: 0 1.3rem; + display: flex; + } + + &__tab { + min-width: 5rem; + padding: .2rem .8rem .9rem; + color: $dusty-gray; + font-family: Roboto; + font-size: 1.1rem; + line-height: initial; + text-align: center; + cursor: pointer; + border-bottom: none; + margin-right: 1rem; + + &:hover { + color: $black; + } + + &:last-of-type { + margin-right: 0; + } + + &--selected { + color: $curious-blue; + border-bottom: 3px solid $curious-blue; + + &:hover { + color: $curious-blue; + } + } + } +} + +@media screen and (max-width: 250px) { + .page-container { + &__footer { + flex-flow: column-reverse; + } + + &__footer-button { + width: 100%; + margin-bottom: 1rem; + margin-right: 0; + + &:first-of-type { + margin-bottom: 0; + } + } + } +} + +@media screen and (max-width: 575px) { + .page-container { + height: 100%; + width: 100%; + overflow-y: auto; + background-color: $white; + } +} diff --git a/ui/app/keychains/hd/restore-vault.js b/ui/app/keychains/hd/restore-vault.js index 24b37a83d..a4ed137f9 100644 --- a/ui/app/keychains/hd/restore-vault.js +++ b/ui/app/keychains/hd/restore-vault.js @@ -107,6 +107,7 @@ RestoreVaultScreen.prototype.render = function () { } RestoreVaultScreen.prototype.showInitializeMenu = function () { + this.props.dispatch(actions.unMarkPasswordForgotten()) if (this.props.forgottenPassword) { this.props.dispatch(actions.backToUnlockView()) } else { @@ -149,6 +150,9 @@ RestoreVaultScreen.prototype.createNewVaultAndRestore = function () { this.warning = null this.props.dispatch(actions.displayWarning(this.warning)) this.props.dispatch(actions.createNewVaultAndRestore(password, seed)) + .then(() => { + this.props.dispatch(actions.unMarkPasswordForgotten()) + }) .catch((err) => { log.error(err.message) }) diff --git a/ui/app/main-container.js b/ui/app/main-container.js index 031f61e84..292abcc3d 100644 --- a/ui/app/main-container.js +++ b/ui/app/main-container.js @@ -2,7 +2,6 @@ const Component = require('react').Component const h = require('react-hyperscript') const inherits = require('util').inherits const AccountAndTransactionDetails = require('./account-and-transaction-details') -const HDRestoreVaultScreen = require('./keychains/hd/restore-vault') const Settings = require('./settings') const UnlockScreen = require('./unlock') @@ -28,13 +27,6 @@ MainContainer.prototype.render = function () { if (this.props.isUnlocked === false) { switch (this.props.currentViewName) { - case 'restoreVault': - log.debug('rendering restore vault screen') - contents = { - component: HDRestoreVaultScreen, - key: 'HDRestoreVaultScreen', - } - break case 'config': log.debug('rendering config screen from unlock screen.') return h(Settings, {key: 'config'}) diff --git a/ui/app/reducers/app.js b/ui/app/reducers/app.js index c3ade5cdc..6885d029a 100644 --- a/ui/app/reducers/app.js +++ b/ui/app/reducers/app.js @@ -484,6 +484,11 @@ function reduceApp (state, action) { warning: action.value || 'Incorrect password. Try again.', }) + case actions.UNLOCK_SUCCEEDED: + return extend(appState, { + warning: '', + }) + case actions.SHOW_LOADING: return extend(appState, { isLoading: true, diff --git a/ui/app/send-v2.js b/ui/app/send-v2.js index 897caf16e..d4e15dfa8 100644 --- a/ui/app/send-v2.js +++ b/ui/app/send-v2.js @@ -5,7 +5,6 @@ const h = require('react-hyperscript') const ethAbi = require('ethereumjs-abi') const ethUtil = require('ethereumjs-util') -const Identicon = require('./components/identicon') const FromDropdown = require('./components/send/from-dropdown') const ToAutoComplete = require('./components/send/to-autocomplete') const CurrencyDisplay = require('./components/send/currency-display') @@ -179,53 +178,20 @@ SendTransactionScreen.prototype.componentDidUpdate = function (prevProps) { } } -SendTransactionScreen.prototype.renderHeaderIcon = function () { - const { selectedToken } = this.props - - return h('div.send-v2__send-header-icon-container', [ - selectedToken - ? h(Identicon, { - diameter: 40, - address: selectedToken.address, - }) - : h('img.send-v2__send-header-icon', { src: '../images/eth_logo.svg' }), - ]) -} - -SendTransactionScreen.prototype.renderTitle = function () { - const { selectedToken } = this.props - - return h('div.send-v2__title', [selectedToken ? 'Send Tokens' : 'Send Funds']) -} - -SendTransactionScreen.prototype.renderCopy = function () { +SendTransactionScreen.prototype.renderHeader = function () { const { selectedToken } = this.props - const tokenText = selectedToken ? 'tokens' : 'ETH' - return h('div.send-v2__form-header-copy', [ - - h('div.send-v2__copy', `Only send ${tokenText} to an Ethereum address.`), + return h('div.page-container__header', [ - h('div.send-v2__copy', 'Sending to a different crytpocurrency that is not Ethereum may result in permanent loss.'), + h('div.page-container__title', selectedToken ? 'Send Tokens' : 'Send ETH'), - ]) -} - -SendTransactionScreen.prototype.renderHeader = function () { - return h('div', [ - h('div.send-v2__header', {}, [ - - this.renderHeaderIcon(), - - h('div.send-v2__arrow-background', [ - h('i.fa.fa-lg.fa-arrow-circle-right.send-v2__send-arrow-icon'), - ]), - - h('div.send-v2__header-tip'), - - ]), + h('div.page-container__subtitle', `Only send ${tokenText} to an Ethereum address.`), + h( + 'div.page-container__subtitle', + 'Sending to a different crytpocurrency that is not Ethereum may result in permanent loss.' + ), ]) } @@ -504,14 +470,6 @@ SendTransactionScreen.prototype.renderMemoRow = function () { SendTransactionScreen.prototype.renderForm = function () { return h('div.send-v2__form', {}, [ - h('div.sendV2__form-header', [ - - this.renderTitle(), - - this.renderCopy(), - - ]), - this.renderFromRow(), this.renderToRow(), @@ -535,14 +493,14 @@ SendTransactionScreen.prototype.renderFooter = function () { const noErrors = !amountError && toError === null - return h('div.send-v2__footer', [ - h('button.btn-cancel.send-v2__cancel-btn', { + return h('div.page-container__footer', [ + h('button.btn-cancel.page-container__footer-button', { onClick: () => { clearSend() goHome() }, }, 'Cancel'), - h('button.btn-clear.send-v2__next-btn', { + h('button.btn-clear.page-container__footer-button', { disabled: !noErrors || !gasTotal, onClick: event => this.onSubmit(event), }, 'Next'), @@ -552,7 +510,7 @@ SendTransactionScreen.prototype.renderFooter = function () { SendTransactionScreen.prototype.render = function () { return ( - h('div.send-v2__container', [ + h('div.page-container', [ this.renderHeader(), diff --git a/ui/app/unlock.js b/ui/app/unlock.js index ec97b03bf..e77d17d7b 100644 --- a/ui/app/unlock.js +++ b/ui/app/unlock.js @@ -74,7 +74,10 @@ UnlockScreen.prototype.render = function () { h('.flex-row.flex-center.flex-grow', [ h('p.pointer', { - onClick: () => this.props.dispatch(actions.forgotPassword()), + onClick: () => { + this.props.dispatch(actions.markPasswordForgotten()) + global.platform.openExtensionInBrowser() + }, style: { fontSize: '0.8em', color: 'rgb(247, 134, 28)', @@ -531,7 +531,7 @@ async-eventemitter@^0.2.2: dependencies: async "^2.4.0" -async-eventemitter@ahultgren/async-eventemitter#fa06e39e56786ba541c180061dbf2c0a5bbf951c, "async-eventemitter@github:ahultgren/async-eventemitter#fa06e39e56786ba541c180061dbf2c0a5bbf951c": +async-eventemitter@ahultgren/async-eventemitter#fa06e39e56786ba541c180061dbf2c0a5bbf951c: version "0.2.3" resolved "https://codeload.github.com/ahultgren/async-eventemitter/tar.gz/fa06e39e56786ba541c180061dbf2c0a5bbf951c" dependencies: @@ -2428,6 +2428,24 @@ component-inherit@0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/component-inherit/-/component-inherit-0.0.3.tgz#645fc4adf58b72b649d5cae65135619db26ff143" +compressible@~2.0.11: + version "2.0.12" + resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.12.tgz#c59a5c99db76767e9876500e271ef63b3493bd66" + dependencies: + mime-db ">= 1.30.0 < 2" + +compression@^1.7.1: + version "1.7.1" + resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.1.tgz#eff2603efc2e22cf86f35d2eb93589f9875373db" + dependencies: + accepts "~1.3.4" + bytes "3.0.0" + compressible "~2.0.11" + debug "2.6.9" + on-headers "~1.0.1" + safe-buffer "5.1.1" + vary "~1.1.2" + concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -3783,7 +3801,7 @@ eth-json-rpc-filters@^1.2.5: json-rpc-engine "^3.4.0" lodash.flatmap "^4.5.0" -eth-json-rpc-infura@^2.0.7: +eth-json-rpc-infura@^2.0.11: version "2.0.11" resolved "https://registry.yarnpkg.com/eth-json-rpc-infura/-/eth-json-rpc-infura-2.0.11.tgz#134bf54ff15e96a9116424c0db9b66aa079bfbbe" dependencies: @@ -6335,7 +6353,7 @@ json-rpc-engine@^3.0.1, json-rpc-engine@^3.1.0, json-rpc-engine@^3.4.0: json-rpc-error "^2.0.0" promise-to-callback "^1.0.0" -json-rpc-engine@^3.5.0, json-rpc-engine@^3.6.0: +json-rpc-engine@^3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/json-rpc-engine/-/json-rpc-engine-3.6.0.tgz#0cc673dcb4b71103523fec81d1bba195a457f993" dependencies: @@ -6345,6 +6363,16 @@ json-rpc-engine@^3.5.0, json-rpc-engine@^3.6.0: json-rpc-error "^2.0.0" promise-to-callback "^1.0.0" +json-rpc-engine@^3.6.1: + version "3.6.1" + resolved "https://registry.yarnpkg.com/json-rpc-engine/-/json-rpc-engine-3.6.1.tgz#f53084726dc6dedeead0e2c457eeb997135f1e25" + dependencies: + async "^2.0.1" + babel-preset-env "^1.3.2" + babelify "^7.3.0" + json-rpc-error "^2.0.0" + promise-to-callback "^1.0.0" + json-rpc-error@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/json-rpc-error/-/json-rpc-error-2.0.0.tgz#a7af9c202838b5e905c7250e547f1aff77258a02" @@ -7292,6 +7320,10 @@ miller-rabin@^4.0.0: bn.js "^4.0.0" brorand "^1.0.1" +"mime-db@>= 1.30.0 < 2": + version "1.32.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.32.0.tgz#485b3848b01a3cda5f968b4882c0771e58e09414" + mime-db@~1.30.0: version "1.30.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.30.0.tgz#74c643da2dd9d6a45399963465b26d5ca7d71f01" @@ -7971,6 +8003,10 @@ on-finished@~2.3.0: dependencies: ee-first "1.1.1" +on-headers@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.1.tgz#928f5d0f470d49342651ea6794b0857c100693f7" + once@^1.3.0, once@^1.3.1, once@^1.3.2, once@^1.3.3, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" @@ -8391,6 +8427,10 @@ polyfill-crypto.getrandomvalues@^1.0.0: dependencies: mersenne-twister "^1.0.1" +popper.js@^1.11.1: + version "1.13.0" + resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.13.0.tgz#e1e7ff65cc43f7cf9cf16f1510a75e81f84f4565" + portfinder@~0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-0.2.1.tgz#b2b9b0164f9e17fa3a9c7db2304d0a75140c71ad" @@ -8915,6 +8955,12 @@ react-testutils-additions@^15.2.0: object-assign "3.0.0" sizzle "2.3.3" +react-tippy@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/react-tippy/-/react-tippy-1.2.2.tgz#061467d34d29e7a5a9421822d125c451d6bb5153" + dependencies: + popper.js "^1.11.1" + react-toggle-button@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/react-toggle-button/-/react-toggle-button-2.2.0.tgz#a1b92143aa0df414642fcb141f0879f545bc5a89" @@ -8933,6 +8979,13 @@ react-tooltip-component@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/react-tooltip-component/-/react-tooltip-component-0.3.0.tgz#fb3ec78c3270fe919692bc31f1404108bcf4785e" +react-tooltip@^3.4.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/react-tooltip/-/react-tooltip-3.4.0.tgz#037f38f797c3e6b1b58d2534ccc8c2c76af4f52d" + dependencies: + classnames "^2.2.5" + prop-types "^15.6.0" + react-transition-group@^1.2.0: version "1.2.1" resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-1.2.1.tgz#e11f72b257f921b213229a774df46612346c7ca6" @@ -11423,9 +11476,9 @@ web3-provider-engine@^13.3.2: xhr "^2.2.0" xtend "^4.0.1" -web3-provider-engine@^13.5.0: - version "13.5.6" - resolved "https://registry.yarnpkg.com/web3-provider-engine/-/web3-provider-engine-13.5.6.tgz#a321a2cf40db78fb478c2c20244c3195c48ef048" +web3-provider-engine@^13.5.6: + version "13.6.0" + resolved "https://registry.yarnpkg.com/web3-provider-engine/-/web3-provider-engine-13.6.0.tgz#836f51c4ee48bd7583acf3696033779c704c2214" dependencies: async "^2.5.0" clone "^2.0.0" |