mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 01:39:44 +01:00
Merge pull request #1022 from MetaMask/i715-AddImportMenu
Add ability to import private keys
This commit is contained in:
commit
28212d167c
@ -1,5 +1,6 @@
|
||||
{
|
||||
"parserOptions": {
|
||||
"sourceType": "module",
|
||||
"ecmaVersion": 6,
|
||||
"ecmaFeatures": {
|
||||
"experimentalObjectRestSpread": true,
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
## Current Master
|
||||
|
||||
- Add ability to import accounts by private key.
|
||||
- Fixed bug that returned the wrong transaction hashes on private networks that had not implemented EIP 155 replay protection (like TestRPC).
|
||||
|
||||
## 3.0.1 2017-1-17
|
||||
|
@ -234,7 +234,10 @@ module.exports = class KeyringController extends EventEmitter {
|
||||
addNewKeyring (type, opts) {
|
||||
const Keyring = this.getKeyringClassForType(type)
|
||||
const keyring = new Keyring(opts)
|
||||
return keyring.deserialize(opts)
|
||||
.then(() => {
|
||||
return keyring.getAccounts()
|
||||
})
|
||||
.then((accounts) => {
|
||||
this.keyrings.push(keyring)
|
||||
return this.setupAccounts(accounts)
|
||||
|
@ -20,13 +20,19 @@ class SimpleKeyring extends EventEmitter {
|
||||
}
|
||||
|
||||
deserialize (privateKeys = []) {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
this.wallets = privateKeys.map((privateKey) => {
|
||||
const stripped = ethUtil.stripHexPrefix(privateKey)
|
||||
const buffer = new Buffer(stripped, 'hex')
|
||||
const wallet = Wallet.fromPrivateKey(buffer)
|
||||
return wallet
|
||||
})
|
||||
return Promise.resolve()
|
||||
} catch (e) {
|
||||
reject(e)
|
||||
}
|
||||
resolve()
|
||||
})
|
||||
}
|
||||
|
||||
addAccounts (n = 1) {
|
||||
|
@ -115,7 +115,12 @@ module.exports = class MetamaskController extends EventEmitter {
|
||||
.then((newState) => { cb(null, newState) })
|
||||
.catch((reason) => { cb(reason) })
|
||||
},
|
||||
addNewKeyring: nodeify(keyringController.addNewKeyring).bind(keyringController),
|
||||
addNewKeyring: (type, opts, cb) => {
|
||||
keyringController.addNewKeyring(type, opts)
|
||||
.then(() => keyringController.fullUpdate())
|
||||
.then((newState) => { cb(null, newState) })
|
||||
.catch((reason) => { cb(reason) })
|
||||
},
|
||||
addNewAccount: nodeify(keyringController.addNewAccount).bind(keyringController),
|
||||
setSelectedAccount: nodeify(keyringController.setSelectedAccount).bind(keyringController),
|
||||
saveAccountLabel: nodeify(keyringController.saveAccountLabel).bind(keyringController),
|
||||
|
84
development/states/account-list-with-imported.json
Normal file
84
development/states/account-list-with-imported.json
Normal file
@ -0,0 +1,84 @@
|
||||
{
|
||||
"metamask": {
|
||||
"isInitialized": true,
|
||||
"isUnlocked": true,
|
||||
"rpcTarget": "https://rawtestrpc.metamask.io/",
|
||||
"identities": {
|
||||
"0x58bda1f9d87dc7d2bcc6f7c2513efc9d03fca683": {
|
||||
"address": "0x58bda1f9d87dc7d2bcc6f7c2513efc9d03fca683",
|
||||
"name": "Account 1"
|
||||
},
|
||||
"0x9858e7d8b79fc3e6d989636721584498926da38a": {
|
||||
"address": "0x9858e7d8b79fc3e6d989636721584498926da38a",
|
||||
"name": "Imported Account"
|
||||
}
|
||||
},
|
||||
"unconfTxs": {},
|
||||
"currentFiat": "USD",
|
||||
"conversionRate": 10.19458075,
|
||||
"conversionDate": 1484696373,
|
||||
"noActiveNotices": true,
|
||||
"network": "3",
|
||||
"accounts": {
|
||||
"0x58bda1f9d87dc7d2bcc6f7c2513efc9d03fca683": {
|
||||
"code": "0x",
|
||||
"balance": "0x0",
|
||||
"nonce": "0x0",
|
||||
"address": "0x58bda1f9d87dc7d2bcc6f7c2513efc9d03fca683"
|
||||
},
|
||||
"0x9858e7d8b79fc3e6d989636721584498926da38a": {
|
||||
"code": "0x",
|
||||
"balance": "0x0",
|
||||
"nonce": "0x0",
|
||||
"address": "0x9858e7d8b79fc3e6d989636721584498926da38a"
|
||||
}
|
||||
},
|
||||
"transactions": [],
|
||||
"provider": {
|
||||
"type": "testnet"
|
||||
},
|
||||
"selectedAccount": "0x9858e7d8b79fc3e6d989636721584498926da38a",
|
||||
"selectedAccountTxList": [],
|
||||
"isDisclaimerConfirmed": true,
|
||||
"unconfMsgs": {},
|
||||
"messages": [],
|
||||
"shapeShiftTxList": [],
|
||||
"keyringTypes": [
|
||||
"Simple Key Pair",
|
||||
"HD Key Tree"
|
||||
],
|
||||
"keyrings": [
|
||||
{
|
||||
"type": "HD Key Tree",
|
||||
"accounts": [
|
||||
"58bda1f9d87dc7d2bcc6f7c2513efc9d03fca683"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "Simple Key Pair",
|
||||
"accounts": [
|
||||
"0x9858e7d8b79fc3e6d989636721584498926da38a"
|
||||
]
|
||||
}
|
||||
],
|
||||
"lostAccounts": [],
|
||||
"seedWords": null
|
||||
},
|
||||
"appState": {
|
||||
"menuOpen": false,
|
||||
"currentView": {
|
||||
"name": "accounts"
|
||||
},
|
||||
"accountDetail": {
|
||||
"subview": "transactions",
|
||||
"accountExport": "none",
|
||||
"privateKey": ""
|
||||
},
|
||||
"transForward": true,
|
||||
"isLoading": false,
|
||||
"warning": null,
|
||||
"scrollToBottom": false,
|
||||
"forgottenPassword": false
|
||||
},
|
||||
"identities": {}
|
||||
}
|
124
development/states/compilation-bug.json
Normal file
124
development/states/compilation-bug.json
Normal file
@ -0,0 +1,124 @@
|
||||
{
|
||||
"metamask": {
|
||||
"isInitialized": true,
|
||||
"isUnlocked": true,
|
||||
"rpcTarget": "https://rawtestrpc.metamask.io/",
|
||||
"identities": {
|
||||
"0xac39b311dceb2a4b2f5d8461c1cdaf756f4f7ae9": {
|
||||
"address": "0xac39b311dceb2a4b2f5d8461c1cdaf756f4f7ae9",
|
||||
"name": "Account 1"
|
||||
},
|
||||
"0xd7c0cd9e7d2701c710d64fc492c7086679bdf7b4": {
|
||||
"address": "0xd7c0cd9e7d2701c710d64fc492c7086679bdf7b4",
|
||||
"name": "Account 2"
|
||||
},
|
||||
"0x1acfb961c5a8268eac8e09d6241a26cbeff42241": {
|
||||
"address": "0x1acfb961c5a8268eac8e09d6241a26cbeff42241",
|
||||
"name": "Account 3"
|
||||
},
|
||||
"0xabc2bca51709b8615147352c62420f547a63a00c": {
|
||||
"address": "0xabc2bca51709b8615147352c62420f547a63a00c",
|
||||
"name": "Account 4"
|
||||
}
|
||||
},
|
||||
"unconfTxs": {
|
||||
"7992944905869041": {
|
||||
"id": 7992944905869041,
|
||||
"txParams": {
|
||||
"from": "0xac39b311dceb2a4b2f5d8461c1cdaf756f4f7ae9",
|
||||
"value": "0x0",
|
||||
"data": "0x606060405234610000575b60da806100186000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680630dbe671f14603c575b6000565b3460005760466088565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16815600a165627a7a72305820a99dfa6091771f518dd1ae8d1ee347bae3304dffd98fd24b1b99a8380bc60a750029",
|
||||
"gas": "0x1af75",
|
||||
"metamaskId": 7992944905869041,
|
||||
"metamaskNetworkId": "3"
|
||||
},
|
||||
"time": 1482279685589,
|
||||
"status": "unconfirmed",
|
||||
"gasMultiplier": 1,
|
||||
"metamaskNetworkId": "3",
|
||||
"gasLimitSpecified": true,
|
||||
"estimatedGas": "0x1af75",
|
||||
"simulationFails": true
|
||||
}
|
||||
},
|
||||
"currentFiat": "USD",
|
||||
"conversionRate": 7.69158136,
|
||||
"conversionDate": 1482279663,
|
||||
"noActiveNotices": true,
|
||||
"network": "3",
|
||||
"accounts": {
|
||||
"0xac39b311dceb2a4b2f5d8461c1cdaf756f4f7ae9": {
|
||||
"code": "0x",
|
||||
"nonce": "0x3",
|
||||
"balance": "0x11f646fe14c9c000",
|
||||
"address": "0xac39b311dceb2a4b2f5d8461c1cdaf756f4f7ae9"
|
||||
},
|
||||
"0xd7c0cd9e7d2701c710d64fc492c7086679bdf7b4": {
|
||||
"code": "0x",
|
||||
"nonce": "0x0",
|
||||
"balance": "0x0",
|
||||
"address": "0xd7c0cd9e7d2701c710d64fc492c7086679bdf7b4"
|
||||
},
|
||||
"0x1acfb961c5a8268eac8e09d6241a26cbeff42241": {
|
||||
"code": "0x",
|
||||
"balance": "0x0",
|
||||
"nonce": "0x0",
|
||||
"address": "0x1acfb961c5a8268eac8e09d6241a26cbeff42241"
|
||||
},
|
||||
"0xabc2bca51709b8615147352c62420f547a63a00c": {
|
||||
"code": "0x",
|
||||
"balance": "0x0",
|
||||
"nonce": "0x0",
|
||||
"address": "0xabc2bca51709b8615147352c62420f547a63a00c"
|
||||
}
|
||||
},
|
||||
"transactions": [
|
||||
{
|
||||
"id": 7992944905869041,
|
||||
"txParams": {
|
||||
"from": "0xac39b311dceb2a4b2f5d8461c1cdaf756f4f7ae9",
|
||||
"value": "0x0",
|
||||
"data": "0x606060405234610000575b60da806100186000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680630dbe671f14603c575b6000565b3460005760466088565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16815600a165627a7a72305820a99dfa6091771f518dd1ae8d1ee347bae3304dffd98fd24b1b99a8380bc60a750029",
|
||||
"gas": "0x1af75",
|
||||
"metamaskId": 7992944905869041,
|
||||
"metamaskNetworkId": "3"
|
||||
},
|
||||
"time": 1482279685589,
|
||||
"status": "unconfirmed",
|
||||
"gasMultiplier": 1,
|
||||
"metamaskNetworkId": "3",
|
||||
"gasLimitSpecified": true,
|
||||
"estimatedGas": "0x1af75",
|
||||
"simulationFails": true
|
||||
}
|
||||
],
|
||||
"provider": {
|
||||
"type": "testnet"
|
||||
},
|
||||
"selectedAccount": "0xac39b311dceb2a4b2f5d8461c1cdaf756f4f7ae9",
|
||||
"seedWords": false,
|
||||
"isDisclaimerConfirmed": true,
|
||||
"unconfMsgs": {},
|
||||
"messages": [],
|
||||
"shapeShiftTxList": [],
|
||||
"keyringTypes": [
|
||||
"Simple Key Pair",
|
||||
"HD Key Tree"
|
||||
],
|
||||
"lostAccounts": []
|
||||
},
|
||||
"appState": {
|
||||
"menuOpen": false,
|
||||
"currentView": {
|
||||
"name": "confTx",
|
||||
"context": 0
|
||||
},
|
||||
"accountDetail": {
|
||||
"subview": "transactions"
|
||||
},
|
||||
"transForward": true,
|
||||
"isLoading": false,
|
||||
"warning": null
|
||||
},
|
||||
"identities": {}
|
||||
}
|
92
development/states/import-private-key-warning.json
Normal file
92
development/states/import-private-key-warning.json
Normal file
@ -0,0 +1,92 @@
|
||||
{
|
||||
"metamask": {
|
||||
"isInitialized": true,
|
||||
"isUnlocked": true,
|
||||
"rpcTarget": "https://rawtestrpc.metamask.io/",
|
||||
"identities": {
|
||||
"0x01208723ba84e15da2e71656544a2963b0c06d40": {
|
||||
"address": "0x01208723ba84e15da2e71656544a2963b0c06d40",
|
||||
"name": "Account 1"
|
||||
}
|
||||
},
|
||||
"unconfTxs": {},
|
||||
"currentFiat": "USD",
|
||||
"conversionRate": 10.1219126,
|
||||
"conversionDate": 1484695442,
|
||||
"noActiveNotices": true,
|
||||
"network": "3",
|
||||
"accounts": {
|
||||
"0x01208723ba84e15da2e71656544a2963b0c06d40": {
|
||||
"nonce": "0x0",
|
||||
"balance": "0x0",
|
||||
"code": "0x",
|
||||
"address": "0x01208723ba84e15da2e71656544a2963b0c06d40"
|
||||
}
|
||||
},
|
||||
"transactions": [],
|
||||
"provider": {
|
||||
"type": "testnet"
|
||||
},
|
||||
"selectedAccount": "0x01208723ba84e15da2e71656544a2963b0c06d40",
|
||||
"selectedAccountTxList": [],
|
||||
"seedWords": false,
|
||||
"isDisclaimerConfirmed": true,
|
||||
"unconfMsgs": {},
|
||||
"messages": [],
|
||||
"shapeShiftTxList": [],
|
||||
"keyringTypes": [
|
||||
"Simple Key Pair",
|
||||
"HD Key Tree"
|
||||
],
|
||||
"keyrings": [
|
||||
{
|
||||
"type": "Simple Key Pair",
|
||||
"accounts": []
|
||||
},
|
||||
{
|
||||
"type": "Simple Key Pair",
|
||||
"accounts": []
|
||||
},
|
||||
{
|
||||
"type": "Simple Key Pair",
|
||||
"accounts": []
|
||||
},
|
||||
{
|
||||
"type": "Simple Key Pair",
|
||||
"accounts": []
|
||||
},
|
||||
{
|
||||
"type": "Simple Key Pair",
|
||||
"accounts": []
|
||||
},
|
||||
{
|
||||
"type": "Simple Key Pair",
|
||||
"accounts": []
|
||||
},
|
||||
{
|
||||
"type": "Simple Key Pair",
|
||||
"accounts": []
|
||||
},
|
||||
{
|
||||
"type": "HD Key Tree",
|
||||
"accounts": [
|
||||
"01208723ba84e15da2e71656544a2963b0c06d40"
|
||||
]
|
||||
}
|
||||
],
|
||||
"lostAccounts": []
|
||||
},
|
||||
"appState": {
|
||||
"menuOpen": false,
|
||||
"currentView": {
|
||||
"name": "import-menu"
|
||||
},
|
||||
"accountDetail": {
|
||||
"subview": "transactions"
|
||||
},
|
||||
"transForward": true,
|
||||
"isLoading": false,
|
||||
"warning": "Invalid hex string"
|
||||
},
|
||||
"identities": {}
|
||||
}
|
64
development/states/import-private-key.json
Normal file
64
development/states/import-private-key.json
Normal file
@ -0,0 +1,64 @@
|
||||
{
|
||||
"metamask": {
|
||||
"isInitialized": true,
|
||||
"isUnlocked": true,
|
||||
"rpcTarget": "https://rawtestrpc.metamask.io/",
|
||||
"identities": {
|
||||
"0x01208723ba84e15da2e71656544a2963b0c06d40": {
|
||||
"address": "0x01208723ba84e15da2e71656544a2963b0c06d40",
|
||||
"name": "Account 1"
|
||||
}
|
||||
},
|
||||
"unconfTxs": {},
|
||||
"currentFiat": "USD",
|
||||
"conversionRate": 10.10788584,
|
||||
"conversionDate": 1484694362,
|
||||
"noActiveNotices": true,
|
||||
"network": "3",
|
||||
"accounts": {
|
||||
"0x01208723ba84e15da2e71656544a2963b0c06d40": {
|
||||
"balance": "0x0",
|
||||
"code": "0x",
|
||||
"nonce": "0x0",
|
||||
"address": "0x01208723ba84e15da2e71656544a2963b0c06d40"
|
||||
}
|
||||
},
|
||||
"transactions": [],
|
||||
"provider": {
|
||||
"type": "testnet"
|
||||
},
|
||||
"selectedAccount": "0x01208723ba84e15da2e71656544a2963b0c06d40",
|
||||
"selectedAccountTxList": [],
|
||||
"seedWords": null,
|
||||
"isDisclaimerConfirmed": true,
|
||||
"unconfMsgs": {},
|
||||
"messages": [],
|
||||
"shapeShiftTxList": [],
|
||||
"keyringTypes": [
|
||||
"Simple Key Pair",
|
||||
"HD Key Tree"
|
||||
],
|
||||
"keyrings": [
|
||||
{
|
||||
"type": "HD Key Tree",
|
||||
"accounts": [
|
||||
"01208723ba84e15da2e71656544a2963b0c06d40"
|
||||
]
|
||||
}
|
||||
],
|
||||
"lostAccounts": []
|
||||
},
|
||||
"appState": {
|
||||
"menuOpen": false,
|
||||
"currentView": {
|
||||
"name": "import-menu"
|
||||
},
|
||||
"accountDetail": {
|
||||
"subview": "transactions"
|
||||
},
|
||||
"transForward": true,
|
||||
"isLoading": false,
|
||||
"warning": null
|
||||
},
|
||||
"identities": {}
|
||||
}
|
66
development/states/new-account.json
Normal file
66
development/states/new-account.json
Normal file
@ -0,0 +1,66 @@
|
||||
{
|
||||
"metamask": {
|
||||
"isInitialized": true,
|
||||
"isUnlocked": true,
|
||||
"rpcTarget": "https://rawtestrpc.metamask.io/",
|
||||
"identities": {
|
||||
"0xa6ef573d60594731178b7f85d80da13cc2af52dd": {
|
||||
"address": "0xa6ef573d60594731178b7f85d80da13cc2af52dd",
|
||||
"name": "Dan! 1"
|
||||
},
|
||||
"0xf9f52e84ad2c9122caa87478d27041ddaa215666": {
|
||||
"address": "0xf9f52e84ad2c9122caa87478d27041ddaa215666",
|
||||
"name": "Account 2"
|
||||
}
|
||||
},
|
||||
"unconfTxs": {},
|
||||
"currentFiat": "USD",
|
||||
"conversionRate": 10.92067835,
|
||||
"conversionDate": 1478282884,
|
||||
"network": null,
|
||||
"accounts": {
|
||||
"0xa6ef573d60594731178b7f85d80da13cc2af52dd": {
|
||||
"balance": "0x00",
|
||||
"nonce": "0x100000",
|
||||
"code": "0x",
|
||||
"address": "0xa6ef573d60594731178b7f85d80da13cc2af52dd"
|
||||
},
|
||||
"0xf9f52e84ad2c9122caa87478d27041ddaa215666": {
|
||||
"balance": "0x00",
|
||||
"nonce": "0x100000",
|
||||
"code": "0x",
|
||||
"address": "0xf9f52e84ad2c9122caa87478d27041ddaa215666"
|
||||
}
|
||||
},
|
||||
"transactions": [],
|
||||
"provider": {
|
||||
"type": "testnet"
|
||||
},
|
||||
"selectedAccount": "0xa6ef573d60594731178b7f85d80da13cc2af52dd",
|
||||
"isConfirmed": true,
|
||||
"unconfMsgs": {},
|
||||
"messages": [],
|
||||
"selectedAddress": "0xa6ef573d60594731178b7f85d80da13cc2af52dd",
|
||||
"shapeShiftTxList": [],
|
||||
"keyringTypes": [
|
||||
"Simple Key Pair",
|
||||
"HD Key Tree"
|
||||
]
|
||||
},
|
||||
"appState": {
|
||||
"menuOpen": false,
|
||||
"currentView": {
|
||||
"name": "new-account"
|
||||
},
|
||||
"accountDetail": {
|
||||
"subview": "transactions"
|
||||
},
|
||||
"transForward": true,
|
||||
"isLoading": false,
|
||||
"warning": null,
|
||||
"forgottenPassword": null,
|
||||
"detailView": {},
|
||||
"scrollToBottom": false
|
||||
},
|
||||
"identities": {}
|
||||
}
|
@ -83,6 +83,7 @@
|
||||
"react-hyperscript": "^2.2.2",
|
||||
"react-markdown": "^2.3.0",
|
||||
"react-redux": "^4.4.5",
|
||||
"react-select": "^1.0.0-rc.2",
|
||||
"react-tooltip-component": "^0.3.0",
|
||||
"readable-stream": "^2.1.2",
|
||||
"redux": "^3.0.5",
|
||||
|
@ -66,7 +66,8 @@ QUnit.test('agree to terms', function (assert) {
|
||||
}).then(function() {
|
||||
|
||||
var sandwich = app.find('.menu-droppo')[0]
|
||||
var lock = sandwich.children[2]
|
||||
var children = sandwich.children
|
||||
var lock = children[children.length - 2]
|
||||
assert.ok(lock, 'Lock menu item found')
|
||||
lock.click()
|
||||
|
||||
|
91
ui/app/accounts/import/index.js
Normal file
91
ui/app/accounts/import/index.js
Normal file
@ -0,0 +1,91 @@
|
||||
const inherits = require('util').inherits
|
||||
const Component = require('react').Component
|
||||
const h = require('react-hyperscript')
|
||||
const connect = require('react-redux').connect
|
||||
import Select from 'react-select'
|
||||
|
||||
// Subviews
|
||||
const JsonImportView = require('./json.js')
|
||||
const SeedImportView = require('./seed.js')
|
||||
const PrivateKeyImportView = require('./private-key.js')
|
||||
|
||||
const menuItems = [
|
||||
'Private Key',
|
||||
]
|
||||
|
||||
module.exports = connect(mapStateToProps)(AccountImportSubview)
|
||||
|
||||
function mapStateToProps (state) {
|
||||
return {
|
||||
menuItems,
|
||||
}
|
||||
}
|
||||
|
||||
inherits(AccountImportSubview, Component)
|
||||
function AccountImportSubview () {
|
||||
Component.call(this)
|
||||
}
|
||||
|
||||
AccountImportSubview.prototype.render = function () {
|
||||
const props = this.props
|
||||
const state = this.state || {}
|
||||
const { menuItems } = props
|
||||
const { type } = state
|
||||
|
||||
return (
|
||||
h('div', {
|
||||
style: {
|
||||
},
|
||||
}, [
|
||||
h('div', {
|
||||
style: {
|
||||
padding: '10px',
|
||||
color: 'rgb(174, 174, 174)',
|
||||
},
|
||||
}, [
|
||||
|
||||
h('h3', { style: { padding: '3px' } }, 'SELECT TYPE'),
|
||||
|
||||
h('style', `
|
||||
.has-value.Select--single > .Select-control .Select-value .Select-value-label, .Select-value-label {
|
||||
color: rgb(174,174,174);
|
||||
}
|
||||
`),
|
||||
|
||||
h(Select, {
|
||||
name: 'import-type-select',
|
||||
clearable: false,
|
||||
value: type || menuItems[0],
|
||||
options: menuItems.map((type) => {
|
||||
return {
|
||||
value: type,
|
||||
label: type,
|
||||
}
|
||||
}),
|
||||
onChange: (opt) => {
|
||||
this.setState({ type: opt.value })
|
||||
},
|
||||
}),
|
||||
]),
|
||||
|
||||
this.renderImportView(),
|
||||
])
|
||||
)
|
||||
}
|
||||
|
||||
AccountImportSubview.prototype.renderImportView = function() {
|
||||
const props = this.props
|
||||
const state = this.state || {}
|
||||
const { type } = state
|
||||
const { menuItems } = props
|
||||
const current = type || menuItems[0]
|
||||
|
||||
switch (current) {
|
||||
case 'HD Key Tree':
|
||||
return h(SeedImportView)
|
||||
case 'Private Key':
|
||||
return h(PrivateKeyImportView)
|
||||
default:
|
||||
return h(JsonImportView)
|
||||
}
|
||||
}
|
27
ui/app/accounts/import/json.js
Normal file
27
ui/app/accounts/import/json.js
Normal file
@ -0,0 +1,27 @@
|
||||
const inherits = require('util').inherits
|
||||
const Component = require('react').Component
|
||||
const h = require('react-hyperscript')
|
||||
const connect = require('react-redux').connect
|
||||
|
||||
module.exports = connect(mapStateToProps)(JsonImportSubview)
|
||||
|
||||
function mapStateToProps (state) {
|
||||
return {}
|
||||
}
|
||||
|
||||
inherits(JsonImportSubview, Component)
|
||||
function JsonImportSubview () {
|
||||
Component.call(this)
|
||||
}
|
||||
|
||||
JsonImportSubview.prototype.render = function () {
|
||||
return (
|
||||
h('div', {
|
||||
style: {
|
||||
},
|
||||
}, [
|
||||
`Upload your json file here!`,
|
||||
])
|
||||
)
|
||||
}
|
||||
|
69
ui/app/accounts/import/private-key.js
Normal file
69
ui/app/accounts/import/private-key.js
Normal file
@ -0,0 +1,69 @@
|
||||
const inherits = require('util').inherits
|
||||
const Component = require('react').Component
|
||||
const h = require('react-hyperscript')
|
||||
const connect = require('react-redux').connect
|
||||
const type = 'Simple Key Pair'
|
||||
const actions = require('../../actions')
|
||||
|
||||
module.exports = connect(mapStateToProps)(PrivateKeyImportView)
|
||||
|
||||
function mapStateToProps (state) {
|
||||
return {
|
||||
error: state.appState.warning,
|
||||
}
|
||||
}
|
||||
|
||||
inherits(PrivateKeyImportView, Component)
|
||||
function PrivateKeyImportView () {
|
||||
Component.call(this)
|
||||
}
|
||||
|
||||
PrivateKeyImportView.prototype.render = function () {
|
||||
const { error } = this.props
|
||||
|
||||
return (
|
||||
h('div', {
|
||||
style: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
padding: '5px 15px 0px 15px',
|
||||
},
|
||||
}, [
|
||||
h('span', 'Paste your private key string here'),
|
||||
|
||||
h('input.large-input.letter-spacey', {
|
||||
type: 'password',
|
||||
id: 'private-key-box',
|
||||
onKeyPress: this.createKeyringOnEnter.bind(this),
|
||||
style: {
|
||||
width: 260,
|
||||
marginTop: 12,
|
||||
},
|
||||
}),
|
||||
|
||||
h('button.primary', {
|
||||
onClick: this.createNewKeychain.bind(this),
|
||||
style: {
|
||||
margin: 12,
|
||||
},
|
||||
}, 'Import'),
|
||||
|
||||
error ? h('span.warning', error) : null,
|
||||
])
|
||||
)
|
||||
}
|
||||
|
||||
PrivateKeyImportView.prototype.createKeyringOnEnter = function (event) {
|
||||
if (event.key === 'Enter') {
|
||||
event.preventDefault()
|
||||
this.createNewKeychain()
|
||||
}
|
||||
}
|
||||
|
||||
PrivateKeyImportView.prototype.createNewKeychain = function () {
|
||||
const input = document.getElementById('private-key-box')
|
||||
const privateKey = input.value
|
||||
this.props.dispatch(actions.addNewKeyring(type, [ privateKey ]))
|
||||
}
|
||||
|
30
ui/app/accounts/import/seed.js
Normal file
30
ui/app/accounts/import/seed.js
Normal file
@ -0,0 +1,30 @@
|
||||
const inherits = require('util').inherits
|
||||
const Component = require('react').Component
|
||||
const h = require('react-hyperscript')
|
||||
const connect = require('react-redux').connect
|
||||
|
||||
module.exports = connect(mapStateToProps)(SeedImportSubview)
|
||||
|
||||
function mapStateToProps (state) {
|
||||
return {}
|
||||
}
|
||||
|
||||
inherits(SeedImportSubview, Component)
|
||||
function SeedImportSubview () {
|
||||
Component.call(this)
|
||||
}
|
||||
|
||||
SeedImportSubview.prototype.render = function () {
|
||||
return (
|
||||
h('div', {
|
||||
style: {
|
||||
},
|
||||
}, [
|
||||
`Paste your seed phrase here!`,
|
||||
h('textarea'),
|
||||
h('br'),
|
||||
h('button', 'Submit'),
|
||||
])
|
||||
)
|
||||
}
|
||||
|
@ -73,7 +73,8 @@ AccountsScreen.prototype.render = function () {
|
||||
|
||||
const simpleAddress = identity.address.substring(2).toLowerCase()
|
||||
const keyring = keyrings.find((kr) => {
|
||||
return kr.accounts.includes(simpleAddress)
|
||||
return kr.accounts.includes(simpleAddress) ||
|
||||
kr.accounts.includes(identity.address)
|
||||
})
|
||||
|
||||
return h(AccountListItem, {
|
||||
@ -154,6 +155,13 @@ AccountsScreen.prototype.addNewAccount = function () {
|
||||
this.props.dispatch(actions.addNewAccount(0))
|
||||
}
|
||||
|
||||
/* An optional view proposed in this design:
|
||||
* https://consensys.quip.com/zZVrAysM5znY
|
||||
AccountsScreen.prototype.addNewAccount = function () {
|
||||
this.props.dispatch(actions.navigateToNewAccountScreen())
|
||||
}
|
||||
*/
|
||||
|
||||
AccountsScreen.prototype.goHome = function () {
|
||||
this.props.dispatch(actions.goHome())
|
||||
}
|
||||
|
@ -32,16 +32,20 @@ var actions = {
|
||||
SHOW_INIT_MENU: 'SHOW_INIT_MENU',
|
||||
SHOW_NEW_VAULT_SEED: 'SHOW_NEW_VAULT_SEED',
|
||||
SHOW_INFO_PAGE: 'SHOW_INFO_PAGE',
|
||||
SHOW_IMPORT_PAGE: 'SHOW_IMPORT_PAGE',
|
||||
unlockMetamask: unlockMetamask,
|
||||
unlockFailed: unlockFailed,
|
||||
showCreateVault: showCreateVault,
|
||||
showRestoreVault: showRestoreVault,
|
||||
showInitializeMenu: showInitializeMenu,
|
||||
showImportPage,
|
||||
createNewVaultAndKeychain: createNewVaultAndKeychain,
|
||||
createNewVaultAndRestore: createNewVaultAndRestore,
|
||||
createNewVaultInProgress: createNewVaultInProgress,
|
||||
addNewKeyring,
|
||||
addNewAccount,
|
||||
NEW_ACCOUNT_SCREEN: 'NEW_ACCOUNT_SCREEN',
|
||||
navigateToNewAccountScreen,
|
||||
showNewVaultSeed: showNewVaultSeed,
|
||||
showInfoPage: showInfoPage,
|
||||
// seed recovery actions
|
||||
@ -249,7 +253,21 @@ function requestRevealSeed (password) {
|
||||
}
|
||||
|
||||
function addNewKeyring (type, opts) {
|
||||
return callBackgroundThenUpdate(background.addNewKeyring, type, opts)
|
||||
return (dispatch) => {
|
||||
dispatch(actions.showLoadingIndication())
|
||||
background.addNewKeyring(type, opts, (err, newState) => {
|
||||
dispatch(actions.hideLoadingIndication())
|
||||
if (err) return dispatch(actions.displayWarning(err.message))
|
||||
dispatch(actions.updateMetamaskState(newState))
|
||||
dispatch(actions.showAccountsPage())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function navigateToNewAccountScreen() {
|
||||
return {
|
||||
type: this.NEW_ACCOUNT_SCREEN,
|
||||
}
|
||||
}
|
||||
|
||||
function addNewAccount (ringNumber = 0) {
|
||||
@ -376,6 +394,12 @@ function showInitializeMenu () {
|
||||
}
|
||||
}
|
||||
|
||||
function showImportPage () {
|
||||
return {
|
||||
type: actions.SHOW_IMPORT_PAGE,
|
||||
}
|
||||
}
|
||||
|
||||
function agreeToDisclaimer () {
|
||||
return (dispatch) => {
|
||||
dispatch(this.showLoadingIndication())
|
||||
|
@ -20,6 +20,7 @@ const NoticeScreen = require('./components/notice')
|
||||
const generateLostAccountsNotice = require('../lib/lost-accounts-notice')
|
||||
// other views
|
||||
const ConfigScreen = require('./config')
|
||||
const Import = require('./accounts/import')
|
||||
const InfoScreen = require('./info')
|
||||
const LoadingIndicator = require('./components/loading')
|
||||
const SandwichExpando = require('sandwich-expando')
|
||||
@ -304,6 +305,13 @@ App.prototype.renderDropdown = function () {
|
||||
icon: h('i.fa.fa-gear.fa-lg'),
|
||||
}),
|
||||
|
||||
h(DropMenuItem, {
|
||||
label: 'Import Account',
|
||||
closeMenu: () => this.setState({ isMainMenuOpen: !isOpen }),
|
||||
action: () => this.props.dispatch(actions.showImportPage()),
|
||||
icon: h('i.fa.fa-arrow-circle-o-up.fa-lg'),
|
||||
}),
|
||||
|
||||
h(DropMenuItem, {
|
||||
label: 'Lock',
|
||||
closeMenu: () => this.setState({ isMainMenuOpen: !isOpen }),
|
||||
@ -411,6 +419,9 @@ App.prototype.renderPrimary = function () {
|
||||
case 'config':
|
||||
return h(ConfigScreen, {key: 'config'})
|
||||
|
||||
case 'import-menu':
|
||||
return h(Import, {key: 'import-menu'})
|
||||
|
||||
case 'reveal-seed-conf':
|
||||
return h(RevealSeedConfirmation, {key: 'reveal-seed-conf'})
|
||||
|
||||
|
@ -7,6 +7,7 @@ const CoinbaseForm = require('./coinbase-form')
|
||||
const ShapeshiftForm = require('./shapeshift-form')
|
||||
const extension = require('../../../app/scripts/lib/extension')
|
||||
const Loading = require('./loading')
|
||||
const TabBar = require('./tab-bar')
|
||||
|
||||
module.exports = connect(mapStateToProps)(BuyButtonSubview)
|
||||
|
||||
@ -29,7 +30,6 @@ function BuyButtonSubview () {
|
||||
|
||||
BuyButtonSubview.prototype.render = function () {
|
||||
const props = this.props
|
||||
const currentForm = props.buyView.formView
|
||||
const isLoading = props.isSubLoading
|
||||
|
||||
return (
|
||||
@ -53,43 +53,53 @@ BuyButtonSubview.prototype.render = function () {
|
||||
|
||||
h(Loading, { isLoading }),
|
||||
|
||||
h('h3.flex-row.text-transform-uppercase', {
|
||||
style: {
|
||||
background: '#EBEBEB',
|
||||
color: '#AEAEAE',
|
||||
paddingTop: '4px',
|
||||
justifyContent: 'space-around',
|
||||
},
|
||||
}, [
|
||||
h(currentForm.coinbase ? '.activeForm' : '.inactiveForm.pointer', {
|
||||
onClick: () => props.dispatch(actions.coinBaseSubview()),
|
||||
}, 'Coinbase'),
|
||||
h(TabBar, {
|
||||
tabs: [
|
||||
{
|
||||
content: [
|
||||
'Coinbase',
|
||||
h('a', {
|
||||
onClick: (event) => this.navigateTo('https://github.com/MetaMask/faq/blob/master/COINBASE.md'),
|
||||
}, [
|
||||
h('i.fa.fa-question-circle', {
|
||||
style: {
|
||||
position: 'relative',
|
||||
right: '33px',
|
||||
margin: '0px 5px',
|
||||
},
|
||||
}),
|
||||
]),
|
||||
h(currentForm.shapeshift ? '.activeForm' : '.inactiveForm.pointer', {
|
||||
onClick: () => props.dispatch(actions.shapeShiftSubview(props.provider.type)),
|
||||
}, 'Shapeshift'),
|
||||
|
||||
],
|
||||
key: 'coinbase',
|
||||
},
|
||||
{
|
||||
content: [
|
||||
'Shapeshift',
|
||||
h('a', {
|
||||
href: 'https://github.com/MetaMask/faq/blob/master/COINBASE.md',
|
||||
onClick: (event) => this.navigateTo('https://info.shapeshift.io/about'),
|
||||
}, [
|
||||
h('i.fa.fa-question-circle', {
|
||||
style: {
|
||||
position: 'relative',
|
||||
right: '28px',
|
||||
margin: '0px 5px',
|
||||
},
|
||||
}),
|
||||
]),
|
||||
]),
|
||||
],
|
||||
key: 'shapeshift',
|
||||
},
|
||||
],
|
||||
defaultTab: 'coinbase',
|
||||
tabSelected: (key) => {
|
||||
switch (key) {
|
||||
case 'coinbase':
|
||||
props.dispatch(actions.coinBaseSubview())
|
||||
break
|
||||
case 'shapeshift':
|
||||
props.dispatch(actions.shapeShiftSubview(props.provider.type))
|
||||
break
|
||||
}
|
||||
},
|
||||
}),
|
||||
|
||||
this.formVersionSubview(),
|
||||
])
|
||||
)
|
||||
|
35
ui/app/components/tab-bar.js
Normal file
35
ui/app/components/tab-bar.js
Normal file
@ -0,0 +1,35 @@
|
||||
const Component = require('react').Component
|
||||
const h = require('react-hyperscript')
|
||||
const inherits = require('util').inherits
|
||||
|
||||
module.exports = TabBar
|
||||
|
||||
inherits(TabBar, Component)
|
||||
function TabBar () {
|
||||
Component.call(this)
|
||||
}
|
||||
|
||||
TabBar.prototype.render = function () {
|
||||
const props = this.props
|
||||
const state = this.state || {}
|
||||
const { tabs = [], defaultTab, tabSelected } = props
|
||||
const { subview = defaultTab } = state
|
||||
|
||||
return (
|
||||
h('.flex-row.space-around.text-transform-uppercase', {
|
||||
style: {
|
||||
background: '#EBEBEB',
|
||||
color: '#AEAEAE',
|
||||
paddingTop: '4px',
|
||||
},
|
||||
}, tabs.map((tab) => {
|
||||
const { key, content } = tab
|
||||
return h(subview === key ? '.activeForm' : '.inactiveForm.pointer', {
|
||||
onClick: () => {
|
||||
this.setState({ subview: key })
|
||||
tabSelected(key)
|
||||
},
|
||||
}, content)
|
||||
}))
|
||||
)
|
||||
}
|
@ -23,6 +23,14 @@
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.space-between {
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.space-around {
|
||||
justify-content: space-around;
|
||||
}
|
||||
|
||||
.flex-column-bottom {
|
||||
display: flex;
|
||||
flex-direction: column-reverse;
|
||||
|
@ -110,7 +110,7 @@ InfoScreen.prototype.render = function () {
|
||||
onClick (event) { this.navigateTo(event.target.href) },
|
||||
}, [
|
||||
h('img.icon-size', {
|
||||
src: manifest.icons[128],
|
||||
src: manifest.icons['128'],
|
||||
style: {
|
||||
filter: 'grayscale(100%)', /* IE6-9 */
|
||||
WebkitFilter: 'grayscale(100%)', /* Microsoft Edge and Firefox 35+ */
|
||||
|
@ -99,6 +99,14 @@ function reduceApp (state, action) {
|
||||
transForward: action.value,
|
||||
})
|
||||
|
||||
case actions.SHOW_IMPORT_PAGE:
|
||||
return extend(appState, {
|
||||
currentView: {
|
||||
name: 'import-menu',
|
||||
},
|
||||
transForward: true,
|
||||
})
|
||||
|
||||
case actions.SHOW_INFO_PAGE:
|
||||
return extend(appState, {
|
||||
currentView: {
|
||||
@ -128,6 +136,15 @@ function reduceApp (state, action) {
|
||||
isLoading: false,
|
||||
})
|
||||
|
||||
case actions.NEW_ACCOUNT_SCREEN:
|
||||
return extend(appState, {
|
||||
currentView: {
|
||||
name: 'new-account',
|
||||
context: appState.currentView.context,
|
||||
},
|
||||
transForward: true,
|
||||
})
|
||||
|
||||
case actions.SHOW_SEND_PAGE:
|
||||
return extend(appState, {
|
||||
currentView: {
|
||||
|
@ -26,7 +26,7 @@ UnlockScreen.prototype.render = function () {
|
||||
const state = this.props
|
||||
const warning = state.warning
|
||||
return (
|
||||
h('.flex-column.hey-im-here', [
|
||||
h('.flex-column', [
|
||||
h('.unlock-screen.flex-column.flex-center.flex-grow', [
|
||||
|
||||
h(Mascot, {
|
||||
|
@ -10,6 +10,7 @@ var cssFiles = {
|
||||
'index.css': fs.readFileSync(path.join(__dirname, '/app/css/index.css'), 'utf8'),
|
||||
'transitions.css': fs.readFileSync(path.join(__dirname, '/app/css/transitions.css'), 'utf8'),
|
||||
'react-tooltip-component.css': fs.readFileSync(path.join(__dirname, '..', 'node_modules', 'react-tooltip-component', 'dist', 'react-tooltip-component.css'), 'utf8'),
|
||||
'react-css': fs.readFileSync(path.join(__dirname, '..', 'node_modules', 'react-select', 'dist', 'react-select.css'), 'utf8'),
|
||||
}
|
||||
|
||||
function bundleCss () {
|
||||
|
Loading…
Reference in New Issue
Block a user