integrate metamask-ui with id mgmt

This commit is contained in:
kumavis 2016-01-15 02:03:42 -08:00
parent 3eaf027e30
commit 7347a66eb0
5 changed files with 199 additions and 28 deletions

View File

@ -1,33 +1,184 @@
const Dnode = require('dnode')
const KeyStore = require('eth-lightwallet').keystore
const PortStream = require('./lib/port-stream.js')
const MetaMaskProvider = require('./lib/metamask-provider')
// const PortStream = require('./lib/port-stream.js')
const identitiesUrl = 'https://alpha.metamask.io/identities/'
// var unsignedTxs = {}
console.log('ready to roll')
var zeroClient = MetaMaskProvider()
// setup provider
var zeroClient = MetaMaskProvider({
rpcUrl: 'https://testrpc.metamask.io/',
getAccounts: getAccounts,
sendTransaction: confirmTransaction,
})
// setup messaging
chrome.runtime.onConnect.addListener(connectRemote)
// chrome.runtime.onConnectExternal.addListener(connectRemote)
function connectRemote(remotePort){
var isMetaMaskInternalProcess = (remotePort.name === 'popup')
if (isMetaMaskInternalProcess) {
// communication with popup
handleInternalCommunication(remotePort)
} else {
// communication with page
handleExternalCommunication(remotePort)
}
}
function handleInternalCommunication(remotePort){
var duplex = new PortStream(remotePort)
var remote = Dnode({
getState: getState,
setLocked: setLocked,
submitPassword: submitPassword,
setSelectedAddress: setSelectedAddress,
signTransaction: signTransaction,
})
duplex.pipe(remote).pipe(duplex)
}
function handleExternalCommunication(remotePort){
remotePort.onMessage.addListener(onRpcRequest.bind(null, remotePort))
}
// handle rpc requests
function onRpcRequest(remotePort, payload){
// console.log('MetaMaskPlugin - incoming payload:', payload)
zeroClient.sendAsync(payload, function onPayloadHandled(err, response){
if (err) throw err
console.log('MetaMaskPlugin - RPC complete:', payload, '->', response)
// if (response.result === true) debugger
// if (typeof response !== 'object') {
// if (!response) {
// console.warn('-------------------------------')
// console.warn(payload, '->', response)
// console.warn('-------------------------------')
// }
remotePort.postMessage(response)
})
}
// id mgmt
var selectedAddress = null
function getState(cb){
var result = _getState()
cb(null, result)
}
function _getState(cb){
var unlocked = isUnlocked()
var result = {
isUnlocked: unlocked,
identities: unlocked ? getIdentities() : {},
selectedAddress: selectedAddress,
}
return result
}
function isUnlocked(){
var password = window.sessionStorage['password']
var result = Boolean(password)
return result
}
function setLocked(){
delete window.sessionStorage['password']
}
function setSelectedAddress(address, cb){
selectedAddress = address
cb(null, _getState())
}
function submitPassword(password, cb){
console.log('submitPassword:', password)
tryPassword(password, function(err){
if (err) console.log('bad password:', password, err)
if (err) return cb(err)
console.log('good password:', password)
window.sessionStorage['password'] = password
cb(null, _getState())
})
}
function getAccounts(cb){
var identities = getIdentities()
var result = selectedAddress ? [selectedAddress] : []
cb(null, result)
}
function getIdentities(cb){
var keyStore = getKeyStore()
var addresses = keyStore.getAddresses()
var accountStore = {}
addresses.map(function(address){
address = '0x'+address
accountStore[address] = {
name: 'Wally',
img: 'QmW6hcwYzXrNkuHrpvo58YeZvbZxUddv69ATSHY3BHpPdd',
address: address,
balance: 10.005,
txCount: 16,
}
})
return accountStore
}
function tryPassword(password, cb){
var keyStore = getKeyStore(password)
var address = keyStore.getAddresses()[0]
if (!address) return cb(new Error('KeyStore - No address to check.'))
var hdPathString = keyStore.defaultHdPathString
try {
var encKey = keyStore.generateEncKey(password)
var encPrivKey = keyStore.ksData[hdPathString].encPrivKeys[address]
var privKey = KeyStore._decryptKey(encPrivKey, encKey)
var addrFromPrivKey = KeyStore._computeAddressFromPrivKey(privKey)
} catch (err) {
return cb(err)
}
if (addrFromPrivKey !== address) return cb(new Error('KeyStore - Decrypting private key failed!'))
cb()
}
function confirmTransaction(txParams, cb){
console.log('confirmTransaction:', txParams)
}
function signTransaction(txParams, cb){
console.log('signTransaction:', txParams)
}
var keyStore = null
function getKeyStore(password){
if (keyStore) return keyStore
password = password || getPassword()
var serializedKeystore = window.localStorage['lightwallet']
// returning user
if (serializedKeystore) {
keyStore = KeyStore.deserialize(serializedKeystore)
// first time here
} else {
var defaultPassword = 'test'
console.log('creating new keystore with default password:', defaultPassword)
var secretSeed = KeyStore.generateRandomSeed()
keyStore = new KeyStore(secretSeed, defaultPassword)
keyStore.generateNewAddress(defaultPassword, 3)
saveKeystore()
}
keyStore.passwordProvider = unlockKeystore
return keyStore
}
function saveKeystore(){
window.localStorage['lightwallet'] = keyStore.serialize()
}
function getPassword(){
var password = window.sessionStorage['password']
if (!password) throw new Error('No password found...')
}
function unlockKeystore(cb){
var password = getPassword()
console.warn('unlocking keystore...')
cb(null, password)
}
// // load from storage
// chrome.storage.sync.get(function(data){
// for (var key in data) {

View File

@ -14,7 +14,7 @@ var pageStream = new LocalMessageDuplexStream({
name: 'contentscript',
target: 'inpage',
})
var pluginPort = chrome.runtime.connect({name: 'metamask'})
var pluginPort = chrome.runtime.connect({name: 'contentscript'})
var pluginStream = new PortStream(pluginPort)
// forward communication across

View File

@ -3,7 +3,7 @@ const CacheSubprovider = require('web3-provider-engine/subproviders/cache.js')
const StaticSubprovider = require('web3-provider-engine/subproviders/static.js')
const FilterSubprovider = require('web3-provider-engine/subproviders/filters.js')
const VmSubprovider = require('web3-provider-engine/subproviders/vm.js')
const LightWalletSubprovider = require('web3-provider-engine/subproviders/lightwallet.js')
const HookedWalletSubprovider = require('web3-provider-engine/subproviders/hooked-wallet.js')
const RpcSubprovider = require('web3-provider-engine/subproviders/rpc.js')
module.exports = metamaskProvider
@ -22,7 +22,7 @@ function metamaskProvider(opts){
eth_hashrate: '0x0',
eth_mining: false,
eth_syncing: true,
})
}))
// filters
engine.addProvider(new FilterSubprovider())
@ -31,21 +31,22 @@ function metamaskProvider(opts){
engine.addProvider(new VmSubprovider())
// id mgmt
engine.addProvider(new LightWalletSubprovider())
engine.addProvider(new HookedWalletSubprovider({
getAccounts: opts.getAccounts,
sendTransaction: opts.sendTransaction,
}))
// data source
engine.addProvider(new RpcSubprovider({
rpcUrl: 'https://testrpc.metamask.io/',
rpcUrl: opts.rpcUrl,
}))
// log new blocks
engine.on('block', function(block){
// lazy hack - move caching and current block to engine
engine.currentBlock = block
console.log('================================')
console.log('BLOCK CHANGED:', '#'+block.number.toString('hex'), '0x'+block.hash.toString('hex'))
console.log('================================')
})
// engine.on('block', function(block){
// console.log('================================')
// console.log('BLOCK CHANGED:', '#'+block.number.toString('hex'), '0x'+block.hash.toString('hex'))
// console.log('================================')
// })
// start polling for blocks
engine.start()

View File

@ -1,13 +1,30 @@
const Dnode = require('dnode')
const MetaMaskUi = require('metamask-ui')
const MetaMaskUiCss = require('metamask-ui/css')
const injectCss = require('inject-css')
const PortStream = require('./lib/port-stream.js')
var container = document.getElementById('app-content')
// setup communication with background
var pluginPort = chrome.runtime.connect({name: 'popup'})
var duplex = new PortStream(pluginPort)
var background = Dnode({
// setUnconfirmedTxs: setUnconfirmedTxs,
})
duplex.pipe(background).pipe(duplex)
background.once('remote', setupApp)
// setup app
var css = MetaMaskUiCss()
injectCss(css)
var app = MetaMaskUi({
container: container,
})
function setupApp(accountManager){
var container = document.getElementById('app-content')
var app = MetaMaskUi({
container: container,
accountManager: accountManager,
})
}

View File

@ -8,6 +8,8 @@
},
"dependencies": {
"async": "^1.4.0",
"dnode": "^1.2.2",
"eth-lightwallet": "^1.0.1",
"ethereumjs-tx": "^0.6.7",
"ethereumjs-util": "^1.3.5",
"inject-css": "^0.1.1",