1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-11-27 12:56:01 +01:00
metamask-extension/app/scripts/lib/inpage-provider.js

139 lines
4.2 KiB
JavaScript
Raw Normal View History

2016-05-23 00:23:16 +02:00
const Streams = require('mississippi')
2016-05-23 03:02:27 +02:00
const StreamProvider = require('web3-stream-provider')
const ObjectMultiplex = require('./obj-multiplex')
2016-05-23 00:23:16 +02:00
const RemoteStore = require('./remote-store.js').RemoteStore
module.exports = MetamaskInpageProvider
2016-06-21 22:18:32 +02:00
function MetamaskInpageProvider (connectionStream) {
2016-05-23 00:23:16 +02:00
const self = this
2016-06-21 22:18:32 +02:00
// setup connectionStream multiplexing
2016-05-23 00:23:16 +02:00
var multiStream = ObjectMultiplex()
2016-06-21 22:18:32 +02:00
Streams.pipe(connectionStream, multiStream, connectionStream, function (err) {
let warningMsg = 'MetamaskInpageProvider - lost connection to MetaMask'
if (err) warningMsg += '\n' + err.stack
console.warn(warningMsg)
2016-05-23 00:23:16 +02:00
})
self.multiStream = multiStream
// subscribe to metamask public config
var publicConfigStore = remoteStoreWithLocalStorageCache('MetaMask-Config')
var storeStream = publicConfigStore.createStream()
2016-06-21 22:18:32 +02:00
Streams.pipe(storeStream, multiStream.createStream('publicConfig'), storeStream, function (err) {
let warningMsg = 'MetamaskInpageProvider - lost connection to MetaMask publicConfig'
if (err) warningMsg += '\n' + err.stack
console.warn(warningMsg)
2016-05-23 00:23:16 +02:00
})
self.publicConfigStore = publicConfigStore
// connect to async provider
var asyncProvider = new StreamProvider()
2016-06-21 22:18:32 +02:00
Streams.pipe(asyncProvider, multiStream.createStream('provider'), asyncProvider, function (err) {
let warningMsg = 'MetamaskInpageProvider - lost connection to MetaMask provider'
if (err) warningMsg += '\n' + err.stack
console.warn(warningMsg)
2016-05-23 00:23:16 +02:00
})
asyncProvider.on('error', console.error.bind(console))
self.asyncProvider = asyncProvider
2016-10-05 20:10:39 +02:00
2016-09-01 00:40:05 +02:00
self.idMap = {}
// handle sendAsync requests via asyncProvider
self.sendAsync = function(payload, cb){
// rewrite request ids
2016-09-01 00:40:05 +02:00
var request = eachJsonMessage(payload, (message) => {
var newId = createRandomId()
self.idMap[newId] = message.id
message.id = newId
return message
})
// forward to asyncProvider
2016-09-01 00:40:05 +02:00
asyncProvider.sendAsync(request, function(err, res){
if (err) return cb(err)
// transform messages to original ids
eachJsonMessage(res, (message) => {
var oldId = self.idMap[message.id]
delete self.idMap[message.id]
message.id = oldId
return message
})
cb(null, res)
})
}
2016-05-23 00:23:16 +02:00
}
2016-06-21 22:18:32 +02:00
MetamaskInpageProvider.prototype.send = function (payload) {
2016-05-23 00:23:16 +02:00
const self = this
2016-10-05 20:10:39 +02:00
2016-06-21 22:56:04 +02:00
let selectedAddress
2016-08-11 22:31:00 +02:00
let result = null
2016-05-23 00:23:16 +02:00
switch (payload.method) {
case 'eth_accounts':
// read from localStorage
2016-06-21 22:56:04 +02:00
selectedAddress = self.publicConfigStore.get('selectedAddress')
2016-05-23 00:23:16 +02:00
result = selectedAddress ? [selectedAddress] : []
break
case 'eth_coinbase':
// read from localStorage
2016-06-21 22:56:04 +02:00
selectedAddress = self.publicConfigStore.get('selectedAddress')
2016-05-23 00:23:16 +02:00
result = selectedAddress || '0x0000000000000000000000000000000000000000'
break
// throw not-supported Error
2016-05-23 00:23:16 +02:00
default:
2016-10-05 20:10:39 +02:00
var link = 'https://github.com/MetaMask/faq/blob/master/DEVELOPERS.md#dizzy-all-async---think-of-metamask-as-a-light-client'
var message = `The MetaMask Web3 object does not support synchronous methods like ${payload.method}. See ${link} for details.`
throw new Error(message)
2016-05-23 00:23:16 +02:00
}
// return the result
return {
id: payload.id,
jsonrpc: payload.jsonrpc,
result: result,
}
}
2016-06-21 22:18:32 +02:00
MetamaskInpageProvider.prototype.sendAsync = function () {
2016-05-23 00:23:16 +02:00
throw new Error('MetamaskInpageProvider - sendAsync not overwritten')
}
2016-06-21 22:18:32 +02:00
MetamaskInpageProvider.prototype.isConnected = function () {
2016-05-23 00:23:16 +02:00
return true
}
// util
2016-06-21 22:18:32 +02:00
function remoteStoreWithLocalStorageCache (storageKey) {
2016-05-23 00:23:16 +02:00
// read local cache
var initState = JSON.parse(localStorage[storageKey] || '{}')
var store = new RemoteStore(initState)
// cache the latest state locally
2016-06-21 22:18:32 +02:00
store.subscribe(function (state) {
2016-05-23 00:23:16 +02:00
localStorage[storageKey] = JSON.stringify(state)
})
return store
2016-06-21 22:18:32 +02:00
}
function createRandomId(){
const extraDigits = 3
// 13 time digits
const datePart = new Date().getTime() * Math.pow(10, extraDigits)
// 3 random digits
const extraPart = Math.floor(Math.random() * Math.pow(10, extraDigits))
// 16 digits
return datePart + extraPart
}
2016-09-01 00:40:05 +02:00
function eachJsonMessage(payload, transformFn){
if (Array.isArray(payload)) {
return payload.map(transformFn)
} else {
return transformFn(payload)
}
2016-09-06 05:20:22 +02:00
}