Merge pull request #427 from poanetwork/vb-eip712
Fix support of eth_signTypedData_v4 (eip-712)
This commit is contained in:
commit
141e153321
|
@ -2,6 +2,7 @@
|
|||
|
||||
## Current Master
|
||||
|
||||
- [#427](https://github.com/poanetwork/nifty-wallet/pull/427) - Fix support of eth_signTypedData_v4 (eip-712)
|
||||
- [#426](https://github.com/poanetwork/nifty-wallet/pull/426) - Update inpage provider: add ethereum.request method support
|
||||
|
||||
## 5.1.6 Tue Oct 27 2020
|
||||
|
|
|
@ -40,6 +40,33 @@ const CLASSIC_CODE = 61
|
|||
const RSK_CODE = 30
|
||||
const RSK_TESTNET_CODE = 31
|
||||
|
||||
|
||||
const MAINNET_NETWORK_ID = '1'
|
||||
const ROPSTEN_NETWORK_ID = '3'
|
||||
const RINKEBY_NETWORK_ID = '4'
|
||||
const GOERLI_NETWORK_ID = '5'
|
||||
const KOVAN_NETWORK_ID = '42'
|
||||
const POA_NETWORK_ID = '99'
|
||||
const DAI_NETWORK_ID = '100'
|
||||
const POA_SOKOL_NETWORK_ID = '77'
|
||||
const CLASSIC_NETWORK_ID = '61'
|
||||
const RSK_NETWORK_ID = '30'
|
||||
const RSK_TESTNET_NETWORK_ID = '31'
|
||||
|
||||
const NETWORK_TYPE_TO_ID_MAP = {
|
||||
[ROPSTEN]: { networkId: ROPSTEN_NETWORK_ID, chainId: ROPSTEN_CHAINID },
|
||||
[RINKEBY]: { networkId: RINKEBY_NETWORK_ID, chainId: RINKEBY_CHAINID },
|
||||
[KOVAN]: { networkId: KOVAN_NETWORK_ID, chainId: KOVAN_CHAINID },
|
||||
[GOERLI_TESTNET]: { networkId: GOERLI_NETWORK_ID, chainId: GOERLI_TESTNET_CHAINID },
|
||||
[MAINNET]: { networkId: MAINNET_NETWORK_ID, chainId: MAINNET_CHAINID },
|
||||
[POA]: { networkId: POA_NETWORK_ID, chainId: POA_CHAINID },
|
||||
[DAI]: { networkId: DAI_NETWORK_ID, chainId: DAI_CHAINID },
|
||||
[POA_SOKOL]: { networkId: POA_SOKOL_NETWORK_ID, chainId: POA_SOKOL_CHAINID },
|
||||
[CLASSIC]: { networkId: CLASSIC_NETWORK_ID, chainId: CLASSIC_CHAINID },
|
||||
[RSK]: { networkId: RSK_NETWORK_ID, chainId: RSK_CHAINID },
|
||||
[RSK_TESTNET]: { networkId: RSK_TESTNET_NETWORK_ID, chainId: RSK_TESTNET_CHAINID },
|
||||
}
|
||||
|
||||
const POA_DISPLAY_NAME = 'POA'
|
||||
const DAI_DISPLAY_NAME = 'xDai'
|
||||
const POA_SOKOL_DISPLAY_NAME = 'Sokol Testnet'
|
||||
|
@ -141,4 +168,5 @@ module.exports = {
|
|||
DROPDOWN_RSK_TESTNET_DISPLAY_NAME,
|
||||
chainTypes,
|
||||
customDPaths,
|
||||
NETWORK_TYPE_TO_ID_MAP,
|
||||
}
|
||||
|
|
|
@ -16,6 +16,9 @@ import ethNetProps from 'eth-net-props'
|
|||
import parse from 'url-parse'
|
||||
const networks = { networkList: {} }
|
||||
const { isKnownProvider } = require('../../../../old-ui/app/util')
|
||||
import {
|
||||
NETWORK_TYPE_TO_ID_MAP,
|
||||
} from './enums'
|
||||
|
||||
const {
|
||||
ROPSTEN,
|
||||
|
@ -155,6 +158,11 @@ module.exports = class NetworkController extends EventEmitter {
|
|||
})
|
||||
}
|
||||
|
||||
getCurrentChainId () {
|
||||
const { type, chainId: configChainId } = this.getProviderConfig()
|
||||
return NETWORK_TYPE_TO_ID_MAP[type] ? NETWORK_TYPE_TO_ID_MAP[type].chainId : configChainId
|
||||
}
|
||||
|
||||
setRpcTarget (rpcTarget, chainId, ticker = 'ETH', nickname = '', rpcPrefs) {
|
||||
const providerConfig = {
|
||||
type: 'rpc',
|
||||
|
|
|
@ -67,6 +67,7 @@ export const SAFE_METHODS = [
|
|||
'eth_sendTransaction',
|
||||
'eth_sign',
|
||||
'personal_sign',
|
||||
'personal_ecRecover',
|
||||
'eth_signTypedData',
|
||||
'eth_signTypedData_v1',
|
||||
'eth_signTypedData_v3',
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
module.exports = createProviderMiddleware
|
||||
|
||||
/**
|
||||
* Forwards an HTTP request to the current Web3 provider
|
||||
*
|
||||
* @param {{ provider: Object }} config Configuration containing current Web3 provider
|
||||
*/
|
||||
function createProviderMiddleware ({ provider }) {
|
||||
return (req, res, next, end) => {
|
||||
provider.sendAsync(req, (err, _res) => {
|
||||
if (err) return end(err)
|
||||
res.result = _res.result
|
||||
end()
|
||||
})
|
||||
}
|
||||
}
|
|
@ -2,10 +2,12 @@ import EventEmitter from 'events'
|
|||
import ObservableStore from 'obs-store'
|
||||
import ethUtil from 'ethereumjs-util'
|
||||
import { ethErrors } from 'eth-json-rpc-errors'
|
||||
import createId from './random-id'
|
||||
|
||||
const hexRe = /^[0-9A-Fa-f]+$/g
|
||||
import log from 'loglevel'
|
||||
import { addHexPrefix } from './util'
|
||||
import createId from './random-id'
|
||||
import { MESSAGE_TYPE } from './enums'
|
||||
|
||||
const hexRe = /^[0-9A-Fa-f]+$/gu
|
||||
|
||||
/**
|
||||
* Represents, and contains data about, an 'eth_decrypt' type decryption request. These are created when a
|
||||
|
@ -29,10 +31,10 @@ export default class DecryptMessageManager extends EventEmitter {
|
|||
* Controller in charge of managing - storing, adding, removing, updating - DecryptMessage.
|
||||
*
|
||||
* @typedef {Object} DecryptMessageManager
|
||||
* @property {Object} memStore The observable store where DecryptMessage are saved with persistance.
|
||||
* @property {Object} memStore The observable store where DecryptMessage are saved.
|
||||
* @property {Object} memStore.unapprovedDecryptMsgs A collection of all DecryptMessages in the 'unapproved' state
|
||||
* @property {number} memStore.unapprovedDecryptMsgCount The count of all DecryptMessages in this.memStore.unapprobedMsgs
|
||||
* @property {array} messages Holds all messages that have been created by this DecryptMessageManager
|
||||
* @property {number} memStore.unapprovedDecryptMsgCount The count of all DecryptMessages in this.memStore.unapprovedDecryptMsgs
|
||||
* @property {Array} messages Holds all messages that have been created by this DecryptMessageManager
|
||||
*
|
||||
*/
|
||||
constructor () {
|
||||
|
@ -62,9 +64,11 @@ export default class DecryptMessageManager extends EventEmitter {
|
|||
*
|
||||
*/
|
||||
getUnapprovedMsgs () {
|
||||
return this.messages.filter((msg) => msg.status === 'unapproved')
|
||||
return this.messages
|
||||
.filter((msg) => msg.status === 'unapproved')
|
||||
.reduce((result, msg) => {
|
||||
result[msg.id] = msg; return result
|
||||
result[msg.id] = msg
|
||||
return result
|
||||
}, {})
|
||||
}
|
||||
|
||||
|
@ -73,27 +77,41 @@ export default class DecryptMessageManager extends EventEmitter {
|
|||
* the new DecryptMessage to this.messages, and to save the unapproved DecryptMessages from that list to
|
||||
* this.memStore.
|
||||
*
|
||||
* @param {Object} msgParams The params for the eth_decrypt call to be made after the message is approved.
|
||||
* @param {Object} req (optional) The original request object possibly containing the origin
|
||||
* @param {Object} msgParams - The params for the eth_decrypt call to be made after the message is approved.
|
||||
* @param {Object} [req] - The original request object possibly containing the origin
|
||||
* @returns {Promise<Buffer>} The raw decrypted message contents
|
||||
*
|
||||
*/
|
||||
addUnapprovedMessageAsync (msgParams, req) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!msgParams.from) {
|
||||
reject(new Error('MetaMask Message for Decryption: from field is required.'))
|
||||
reject(new Error('MetaMask Decryption: from field is required.'))
|
||||
return
|
||||
}
|
||||
const msgId = this.addUnapprovedMessage(msgParams, req)
|
||||
this.once(`${msgId}:finished`, (data) => {
|
||||
switch (data.status) {
|
||||
case 'decrypted':
|
||||
return resolve(data.rawData)
|
||||
resolve(data.rawData)
|
||||
return
|
||||
case 'rejected':
|
||||
return reject(ethErrors.provider.userRejectedRequest('MetaMask Message for Decryption: User denied message decryption.'))
|
||||
reject(
|
||||
ethErrors.provider.userRejectedRequest(
|
||||
'MetaMask Decryption: User denied message decryption.',
|
||||
),
|
||||
)
|
||||
return
|
||||
case 'errored':
|
||||
return reject(new Error('This message cannot be decrypted'))
|
||||
reject(new Error('This message cannot be decrypted'))
|
||||
return
|
||||
default:
|
||||
return reject(new Error(`MetaMask Message for Decryption: Unknown problem: ${JSON.stringify(msgParams)}`))
|
||||
reject(
|
||||
new Error(
|
||||
`MetaMask Decryption: Unknown problem: ${JSON.stringify(
|
||||
msgParams,
|
||||
)}`,
|
||||
),
|
||||
)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
@ -104,27 +122,31 @@ export default class DecryptMessageManager extends EventEmitter {
|
|||
* the new DecryptMessage to this.messages, and to save the unapproved DecryptMessages from that list to
|
||||
* this.memStore.
|
||||
*
|
||||
* @param {Object} msgParams The params for the eth_decryptMsg call to be made after the message is approved.
|
||||
* @param {Object} req (optional) The original request object possibly containing the origin
|
||||
* @param {Object} msgParams - The params for the eth_decryptMsg call to be made after the message is approved.
|
||||
* @param {Object} [req] - The original request object possibly containing the origin
|
||||
* @returns {number} The id of the newly created DecryptMessage.
|
||||
*
|
||||
*/
|
||||
addUnapprovedMessage (msgParams, req) {
|
||||
log.debug(`DecryptMessageManager addUnapprovedMessage: ${JSON.stringify(msgParams)}`)
|
||||
log.debug(
|
||||
`DecryptMessageManager addUnapprovedMessage: ${JSON.stringify(
|
||||
msgParams,
|
||||
)}`,
|
||||
)
|
||||
// add origin from request
|
||||
if (req) {
|
||||
msgParams.origin = req.origin
|
||||
}
|
||||
msgParams.data = this.normalizeMsgData(msgParams.data)
|
||||
// create txData obj with parameters and meta data
|
||||
const time = (new Date()).getTime()
|
||||
const time = new Date().getTime()
|
||||
const msgId = createId()
|
||||
const msgData = {
|
||||
id: msgId,
|
||||
msgParams: msgParams,
|
||||
time: time,
|
||||
msgParams,
|
||||
time,
|
||||
status: 'unapproved',
|
||||
type: 'eth_decrypt',
|
||||
type: MESSAGE_TYPE.ETH_DECRYPT,
|
||||
}
|
||||
this.addMsg(msgData)
|
||||
|
||||
|
@ -247,12 +269,18 @@ export default class DecryptMessageManager extends EventEmitter {
|
|||
_setMsgStatus (msgId, status) {
|
||||
const msg = this.getMsg(msgId)
|
||||
if (!msg) {
|
||||
throw new Error('DecryptMessageManager - Message not found for id: "${msgId}".')
|
||||
throw new Error(
|
||||
`DecryptMessageManager - Message not found for id: "${msgId}".`,
|
||||
)
|
||||
}
|
||||
msg.status = status
|
||||
this._updateMsg(msg)
|
||||
this.emit(`${msgId}:${status}`, msg)
|
||||
if (status === 'rejected' || status === 'decrypted' || status === 'errored') {
|
||||
if (
|
||||
status === 'rejected' ||
|
||||
status === 'decrypted' ||
|
||||
status === 'errored'
|
||||
) {
|
||||
this.emit(`${msgId}:finished`, msg)
|
||||
}
|
||||
}
|
||||
|
@ -262,7 +290,7 @@ export default class DecryptMessageManager extends EventEmitter {
|
|||
* unapprovedDecryptMsgs index to storage via this._saveMsgList
|
||||
*
|
||||
* @private
|
||||
* @param {msg} DecryptMessage A DecryptMessage that will replace an existing DecryptMessage (with the same
|
||||
* @param {DecryptMessage} msg - A DecryptMessage that will replace an existing DecryptMessage (with the same
|
||||
* id) in this.messages
|
||||
*
|
||||
*/
|
||||
|
@ -284,7 +312,10 @@ export default class DecryptMessageManager extends EventEmitter {
|
|||
_saveMsgList () {
|
||||
const unapprovedDecryptMsgs = this.getUnapprovedMsgs()
|
||||
const unapprovedDecryptMsgCount = Object.keys(unapprovedDecryptMsgs).length
|
||||
this.memStore.updateState({ unapprovedDecryptMsgs, unapprovedDecryptMsgCount })
|
||||
this.memStore.updateState({
|
||||
unapprovedDecryptMsgs,
|
||||
unapprovedDecryptMsgCount,
|
||||
})
|
||||
this.emit('updateBadge')
|
||||
}
|
||||
|
||||
|
@ -299,7 +330,7 @@ export default class DecryptMessageManager extends EventEmitter {
|
|||
try {
|
||||
const stripped = ethUtil.stripHexPrefix(data)
|
||||
if (stripped.match(hexRe)) {
|
||||
return ethUtil.addHexPrefix(stripped)
|
||||
return addHexPrefix(stripped)
|
||||
}
|
||||
} catch (e) {
|
||||
log.debug(`Message was not hex encoded, interpreting as utf8.`)
|
||||
|
@ -307,5 +338,4 @@ export default class DecryptMessageManager extends EventEmitter {
|
|||
|
||||
return ethUtil.bufferToHex(Buffer.from(data, 'utf8'))
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import EventEmitter from 'events'
|
||||
import ObservableStore from 'obs-store'
|
||||
import { ethErrors } from 'eth-json-rpc-errors'
|
||||
import createId from './random-id'
|
||||
import log from 'loglevel'
|
||||
import createId from './random-id'
|
||||
import { MESSAGE_TYPE } from './enums'
|
||||
|
||||
/**
|
||||
* Represents, and contains data about, an 'eth_getEncryptionPublicKey' type request. These are created when
|
||||
|
@ -29,7 +30,7 @@ export default class EncryptionPublicKeyManager extends EventEmitter {
|
|||
* @property {Object} memStore The observable store where EncryptionPublicKey are saved with persistance.
|
||||
* @property {Object} memStore.unapprovedEncryptionPublicKeyMsgs A collection of all EncryptionPublicKeys in the 'unapproved' state
|
||||
* @property {number} memStore.unapprovedEncryptionPublicKeyMsgCount The count of all EncryptionPublicKeys in this.memStore.unapprobedMsgs
|
||||
* @property {array} messages Holds all messages that have been created by this EncryptionPublicKeyManager
|
||||
* @property {Array} messages Holds all messages that have been created by this EncryptionPublicKeyManager
|
||||
*
|
||||
*/
|
||||
constructor () {
|
||||
|
@ -59,9 +60,11 @@ export default class EncryptionPublicKeyManager extends EventEmitter {
|
|||
*
|
||||
*/
|
||||
getUnapprovedMsgs () {
|
||||
return this.messages.filter((msg) => msg.status === 'unapproved')
|
||||
return this.messages
|
||||
.filter((msg) => msg.status === 'unapproved')
|
||||
.reduce((result, msg) => {
|
||||
result[msg.id] = msg; return result
|
||||
result[msg.id] = msg
|
||||
return result
|
||||
}, {})
|
||||
}
|
||||
|
||||
|
@ -70,25 +73,38 @@ export default class EncryptionPublicKeyManager extends EventEmitter {
|
|||
* the new EncryptionPublicKey to this.messages, and to save the unapproved EncryptionPublicKeys from that list to
|
||||
* this.memStore.
|
||||
*
|
||||
* @param {Object} address The param for the eth_getEncryptionPublicKey call to be made after the message is approved.
|
||||
* @param {Object} req (optional) The original request object possibly containing the origin
|
||||
* @param {Object} address - The param for the eth_getEncryptionPublicKey call to be made after the message is approved.
|
||||
* @param {Object} [req] - The original request object possibly containing the origin
|
||||
* @returns {Promise<Buffer>} The raw public key contents
|
||||
*
|
||||
*/
|
||||
addUnapprovedMessageAsync (address, req) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!address) {
|
||||
reject(new Error('MetaMask Message for EncryptionPublicKey: address field is required.'))
|
||||
reject(new Error('MetaMask Message: address field is required.'))
|
||||
return
|
||||
}
|
||||
const msgId = this.addUnapprovedMessage(address, req)
|
||||
this.once(`${msgId}:finished`, (data) => {
|
||||
switch (data.status) {
|
||||
case 'received':
|
||||
return resolve(data.rawData)
|
||||
resolve(data.rawData)
|
||||
return
|
||||
case 'rejected':
|
||||
return reject(ethErrors.provider.userRejectedRequest('MetaMask Message for EncryptionPublicKey: User denied message EncryptionPublicKey.'))
|
||||
reject(
|
||||
ethErrors.provider.userRejectedRequest(
|
||||
'MetaMask EncryptionPublicKey: User denied message EncryptionPublicKey.',
|
||||
),
|
||||
)
|
||||
return
|
||||
default:
|
||||
return reject(new Error(`MetaMask Message for EncryptionPublicKey: Unknown problem: ${JSON.stringify(address)}`))
|
||||
reject(
|
||||
new Error(
|
||||
`MetaMask EncryptionPublicKey: Unknown problem: ${JSON.stringify(
|
||||
address,
|
||||
)}`,
|
||||
),
|
||||
)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
@ -99,22 +115,22 @@ export default class EncryptionPublicKeyManager extends EventEmitter {
|
|||
* the new EncryptionPublicKey to this.messages, and to save the unapproved EncryptionPublicKeys from that list to
|
||||
* this.memStore.
|
||||
*
|
||||
* @param {Object} address The param for the eth_getEncryptionPublicKey call to be made after the message is approved.
|
||||
* @param {Object} _req (optional) The original request object possibly containing the origin
|
||||
* @param {Object} address - The param for the eth_getEncryptionPublicKey call to be made after the message is approved.
|
||||
* @param {Object} [req] - The original request object possibly containing the origin
|
||||
* @returns {number} The id of the newly created EncryptionPublicKey.
|
||||
*
|
||||
*/
|
||||
addUnapprovedMessage (address, req) {
|
||||
log.debug(`EncryptionPublicKeyManager addUnapprovedMessage: address`)
|
||||
// create txData obj with parameters and meta data
|
||||
const time = (new Date()).getTime()
|
||||
const time = new Date().getTime()
|
||||
const msgId = createId()
|
||||
const msgData = {
|
||||
id: msgId,
|
||||
msgParams: address,
|
||||
time: time,
|
||||
time,
|
||||
status: 'unapproved',
|
||||
type: 'eth_getEncryptionPublicKey',
|
||||
type: MESSAGE_TYPE.ETH_GET_ENCRYPTION_PUBLIC_KEY,
|
||||
}
|
||||
|
||||
if (req) {
|
||||
|
@ -242,7 +258,9 @@ export default class EncryptionPublicKeyManager extends EventEmitter {
|
|||
_setMsgStatus (msgId, status) {
|
||||
const msg = this.getMsg(msgId)
|
||||
if (!msg) {
|
||||
throw new Error('EncryptionPublicKeyManager - Message not found for id: "${msgId}".')
|
||||
throw new Error(
|
||||
`EncryptionPublicKeyManager - Message not found for id: "${msgId}".`,
|
||||
)
|
||||
}
|
||||
msg.status = status
|
||||
this._updateMsg(msg)
|
||||
|
@ -257,7 +275,7 @@ export default class EncryptionPublicKeyManager extends EventEmitter {
|
|||
* unapprovedEncryptionPublicKeyMsgs index to storage via this._saveMsgList
|
||||
*
|
||||
* @private
|
||||
* @param {msg} EncryptionPublicKey A EncryptionPublicKey that will replace an existing EncryptionPublicKey (with the same
|
||||
* @param {EncryptionPublicKey} msg - A EncryptionPublicKey that will replace an existing EncryptionPublicKey (with the same
|
||||
* id) in this.messages
|
||||
*
|
||||
*/
|
||||
|
@ -278,9 +296,13 @@ export default class EncryptionPublicKeyManager extends EventEmitter {
|
|||
*/
|
||||
_saveMsgList () {
|
||||
const unapprovedEncryptionPublicKeyMsgs = this.getUnapprovedMsgs()
|
||||
const unapprovedEncryptionPublicKeyMsgCount = Object.keys(unapprovedEncryptionPublicKeyMsgs).length
|
||||
this.memStore.updateState({ unapprovedEncryptionPublicKeyMsgs, unapprovedEncryptionPublicKeyMsgCount })
|
||||
const unapprovedEncryptionPublicKeyMsgCount = Object.keys(
|
||||
unapprovedEncryptionPublicKeyMsgs,
|
||||
).length
|
||||
this.memStore.updateState({
|
||||
unapprovedEncryptionPublicKeyMsgs,
|
||||
unapprovedEncryptionPublicKeyMsgCount,
|
||||
})
|
||||
this.emit('updateBadge')
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -9,11 +9,21 @@ const PLATFORM_EDGE = 'Edge'
|
|||
const PLATFORM_FIREFOX = 'Firefox'
|
||||
const PLATFORM_OPERA = 'Opera'
|
||||
|
||||
const MESSAGE_TYPE = {
|
||||
ETH_DECRYPT: 'eth_decrypt',
|
||||
ETH_GET_ENCRYPTION_PUBLIC_KEY: 'eth_getEncryptionPublicKey',
|
||||
ETH_SIGN: 'eth_sign',
|
||||
ETH_SIGN_TYPED_DATA: 'eth_signTypedData',
|
||||
LOG_WEB3_USAGE: 'metamask_logInjectedWeb3Usage',
|
||||
PERSONAL_SIGN: 'personal_sign',
|
||||
}
|
||||
|
||||
export {
|
||||
ENVIRONMENT_TYPE_POPUP,
|
||||
ENVIRONMENT_TYPE_NOTIFICATION,
|
||||
ENVIRONMENT_TYPE_FULLSCREEN,
|
||||
ENVIRONMENT_TYPE_BACKGROUND,
|
||||
MESSAGE_TYPE,
|
||||
PLATFORM_BRAVE,
|
||||
PLATFORM_CHROME,
|
||||
PLATFORM_EDGE,
|
||||
|
|
|
@ -3,6 +3,7 @@ import ObservableStore from 'obs-store'
|
|||
import ethUtil from 'ethereumjs-util'
|
||||
import { ethErrors } from 'eth-json-rpc-errors'
|
||||
import createId from './random-id'
|
||||
import { MESSAGE_TYPE } from './enums'
|
||||
|
||||
/**
|
||||
* Represents, and contains data about, an 'eth_sign' type signature request. These are created when a signature for
|
||||
|
@ -23,16 +24,14 @@ import createId from './random-id'
|
|||
*/
|
||||
|
||||
export default class MessageManager extends EventEmitter {
|
||||
|
||||
/**
|
||||
* Controller in charge of managing - storing, adding, removing, updating - Messages.
|
||||
*
|
||||
* @typedef {Object} MessageManager
|
||||
* @param {Object} opts @deprecated
|
||||
* @property {Object} memStore The observable store where Messages are saved.
|
||||
* @property {Object} memStore.unapprovedMsgs A collection of all Messages in the 'unapproved' state
|
||||
* @property {number} memStore.unapprovedMsgCount The count of all Messages in this.memStore.unapprobedMsgs
|
||||
* @property {array} messages Holds all messages that have been created by this MessageManager
|
||||
* @property {number} memStore.unapprovedMsgCount The count of all Messages in this.memStore.unapprovedMsgs
|
||||
* @property {Array} messages Holds all messages that have been created by this MessageManager
|
||||
*
|
||||
*/
|
||||
constructor () {
|
||||
|
@ -47,7 +46,7 @@ export default class MessageManager extends EventEmitter {
|
|||
/**
|
||||
* A getter for the number of 'unapproved' Messages in this.messages
|
||||
*
|
||||
* @returns {number} - The number of 'unapproved' Messages in this.messages
|
||||
* @returns {number} The number of 'unapproved' Messages in this.messages
|
||||
*
|
||||
*/
|
||||
get unapprovedMsgCount () {
|
||||
|
@ -57,13 +56,15 @@ export default class MessageManager extends EventEmitter {
|
|||
/**
|
||||
* A getter for the 'unapproved' Messages in this.messages
|
||||
*
|
||||
* @returns {Object} - An index of Message ids to Messages, for all 'unapproved' Messages in this.messages
|
||||
* @returns {Object} An index of Message ids to Messages, for all 'unapproved' Messages in this.messages
|
||||
*
|
||||
*/
|
||||
getUnapprovedMsgs () {
|
||||
return this.messages.filter((msg) => msg.status === 'unapproved')
|
||||
return this.messages
|
||||
.filter((msg) => msg.status === 'unapproved')
|
||||
.reduce((result, msg) => {
|
||||
result[msg.id] = msg; return result
|
||||
result[msg.id] = msg
|
||||
return result
|
||||
}, {})
|
||||
}
|
||||
|
||||
|
@ -72,8 +73,8 @@ export default class MessageManager extends EventEmitter {
|
|||
* new Message to this.messages, and to save the unapproved Messages from that list to this.memStore.
|
||||
*
|
||||
* @param {Object} msgParams - The params for the eth_sign call to be made after the message is approved.
|
||||
* @param {Object} req (optional) The original request object possibly containing the origin
|
||||
* @returns {promise} - after signature has been
|
||||
* @param {Object} [req] - The original request object possibly containing the origin
|
||||
* @returns {promise} after signature has been
|
||||
*
|
||||
*/
|
||||
addUnapprovedMessageAsync (msgParams, req) {
|
||||
|
@ -85,9 +86,19 @@ export default class MessageManager extends EventEmitter {
|
|||
case 'signed':
|
||||
return resolve(data.rawSig)
|
||||
case 'rejected':
|
||||
return reject(ethErrors.provider.userRejectedRequest('Nifty Wallet Message Signature: User denied message signature.'))
|
||||
return reject(
|
||||
ethErrors.provider.userRejectedRequest(
|
||||
'Nifty Wallet Message Signature: User denied message signature.',
|
||||
),
|
||||
)
|
||||
default:
|
||||
return reject(new Error(`Nifty Wallet Message Signature: Unknown problem: ${JSON.stringify(msgParams)}`))
|
||||
return reject(
|
||||
new Error(
|
||||
`Nifty Wallet Message Signature: Unknown problem: ${JSON.stringify(
|
||||
msgParams,
|
||||
)}`,
|
||||
),
|
||||
)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
@ -98,8 +109,8 @@ export default class MessageManager extends EventEmitter {
|
|||
* new Message to this.messages, and to save the unapproved Messages from that list to this.memStore.
|
||||
*
|
||||
* @param {Object} msgParams - The params for the eth_sign call to be made after the message is approved.
|
||||
* @param {Object} req (optional) The original request object where the origin may be specificied
|
||||
* @returns {number} - The id of the newly created message.
|
||||
* @param {Object} [req] - The original request object where the origin may be specified
|
||||
* @returns {number} The id of the newly created message.
|
||||
*
|
||||
*/
|
||||
addUnapprovedMessage (msgParams, req) {
|
||||
|
@ -109,14 +120,14 @@ export default class MessageManager extends EventEmitter {
|
|||
}
|
||||
msgParams.data = normalizeMsgData(msgParams.data)
|
||||
// create txData obj with parameters and meta data
|
||||
const time = (new Date()).getTime()
|
||||
const time = new Date().getTime()
|
||||
const msgId = createId()
|
||||
const msgData = {
|
||||
id: msgId,
|
||||
msgParams: msgParams,
|
||||
time: time,
|
||||
msgParams,
|
||||
time,
|
||||
status: 'unapproved',
|
||||
type: 'eth_sign',
|
||||
type: MESSAGE_TYPE.ETH_SIGN,
|
||||
}
|
||||
this.addMsg(msgData)
|
||||
|
||||
|
@ -141,7 +152,7 @@ export default class MessageManager extends EventEmitter {
|
|||
* Returns a specified Message.
|
||||
*
|
||||
* @param {number} msgId - The id of the Message to get
|
||||
* @returns {Message|undefined} - The Message with the id that matches the passed msgId, or undefined if no Message has that id.
|
||||
* @returns {Message|undefined} The Message with the id that matches the passed msgId, or undefined if no Message has that id.
|
||||
*
|
||||
*/
|
||||
getMsg (msgId) {
|
||||
|
@ -154,7 +165,7 @@ export default class MessageManager extends EventEmitter {
|
|||
*
|
||||
* @param {Object} msgParams - The msgParams to be used when eth_sign is called, plus data added by MetaMask.
|
||||
* @param {Object} msgParams.metamaskId Added to msgParams for tracking and identification within MetaMask.
|
||||
* @returns {Promise<object>} - Promises the msgParams object with metamaskId removed.
|
||||
* @returns {Promise<object>} Promises the msgParams object with metamaskId removed.
|
||||
*
|
||||
*/
|
||||
approveMessage (msgParams) {
|
||||
|
@ -191,7 +202,7 @@ export default class MessageManager extends EventEmitter {
|
|||
* Removes the metamaskId property from passed msgParams and returns a promise which resolves the updated msgParams
|
||||
*
|
||||
* @param {Object} msgParams - The msgParams to modify
|
||||
* @returns {Promise<object>} - Promises the msgParams with the metamaskId property removed
|
||||
* @returns {Promise<object>} Promises the msgParams with the metamaskId property removed
|
||||
*
|
||||
*/
|
||||
prepMsgForSigning (msgParams) {
|
||||
|
@ -224,7 +235,7 @@ export default class MessageManager extends EventEmitter {
|
|||
_setMsgStatus (msgId, status) {
|
||||
const msg = this.getMsg(msgId)
|
||||
if (!msg) {
|
||||
throw new Error('MessageManager - Message not found for id: "${msgId}".')
|
||||
throw new Error(`MessageManager - Message not found for id: "${msgId}".`)
|
||||
}
|
||||
msg.status = status
|
||||
this._updateMsg(msg)
|
||||
|
@ -263,22 +274,20 @@ export default class MessageManager extends EventEmitter {
|
|||
this.memStore.updateState({ unapprovedMsgs, unapprovedMsgCount })
|
||||
this.emit('updateBadge')
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* A helper function that converts raw buffer data to a hex, or just returns the data if it is already formatted as a hex.
|
||||
*
|
||||
* @param {any} data - The buffer data to convert to a hex
|
||||
* @returns {string} - A hex string conversion of the buffer data
|
||||
* @returns {string} A hex string conversion of the buffer data
|
||||
*
|
||||
*/
|
||||
function normalizeMsgData (data) {
|
||||
if (data.slice(0, 2) === '0x') {
|
||||
// data is already hex
|
||||
return data
|
||||
} else {
|
||||
// data is unicode, convert to hex
|
||||
return ethUtil.bufferToHex(Buffer.from(data, 'utf8'))
|
||||
}
|
||||
// data is unicode, convert to hex
|
||||
return ethUtil.bufferToHex(Buffer.from(data, 'utf8'))
|
||||
}
|
||||
|
|
|
@ -2,10 +2,12 @@ import EventEmitter from 'events'
|
|||
import ObservableStore from 'obs-store'
|
||||
import ethUtil from 'ethereumjs-util'
|
||||
import { ethErrors } from 'eth-json-rpc-errors'
|
||||
import createId from './random-id'
|
||||
|
||||
const hexRe = /^[0-9A-Fa-f]+$/g
|
||||
import log from 'loglevel'
|
||||
import { addHexPrefix } from './util'
|
||||
import createId from './random-id'
|
||||
import { MESSAGE_TYPE } from './enums'
|
||||
|
||||
const hexRe = /^[0-9A-Fa-f]+$/gu
|
||||
|
||||
/**
|
||||
* Represents, and contains data about, an 'personal_sign' type signature request. These are created when a
|
||||
|
@ -31,11 +33,10 @@ export default class PersonalMessageManager extends EventEmitter {
|
|||
* Controller in charge of managing - storing, adding, removing, updating - PersonalMessage.
|
||||
*
|
||||
* @typedef {Object} PersonalMessageManager
|
||||
* @param {Object} opts @deprecated
|
||||
* @property {Object} memStore The observable store where PersonalMessage are saved with persistance.
|
||||
* @property {Object} memStore The observable store where PersonalMessage are saved.
|
||||
* @property {Object} memStore.unapprovedPersonalMsgs A collection of all PersonalMessages in the 'unapproved' state
|
||||
* @property {number} memStore.unapprovedPersonalMsgCount The count of all PersonalMessages in this.memStore.unapprobedMsgs
|
||||
* @property {array} messages Holds all messages that have been created by this PersonalMessageManager
|
||||
* @property {Array} messages Holds all messages that have been created by this PersonalMessageManager
|
||||
*
|
||||
*/
|
||||
constructor () {
|
||||
|
@ -50,7 +51,7 @@ export default class PersonalMessageManager extends EventEmitter {
|
|||
/**
|
||||
* A getter for the number of 'unapproved' PersonalMessages in this.messages
|
||||
*
|
||||
* @returns {number} - The number of 'unapproved' PersonalMessages in this.messages
|
||||
* @returns {number} The number of 'unapproved' PersonalMessages in this.messages
|
||||
*
|
||||
*/
|
||||
get unapprovedPersonalMsgCount () {
|
||||
|
@ -60,14 +61,16 @@ export default class PersonalMessageManager extends EventEmitter {
|
|||
/**
|
||||
* A getter for the 'unapproved' PersonalMessages in this.messages
|
||||
*
|
||||
* @returns {Object} - An index of PersonalMessage ids to PersonalMessages, for all 'unapproved' PersonalMessages in
|
||||
* @returns {Object} An index of PersonalMessage ids to PersonalMessages, for all 'unapproved' PersonalMessages in
|
||||
* this.messages
|
||||
*
|
||||
*/
|
||||
getUnapprovedMsgs () {
|
||||
return this.messages.filter((msg) => msg.status === 'unapproved')
|
||||
return this.messages
|
||||
.filter((msg) => msg.status === 'unapproved')
|
||||
.reduce((result, msg) => {
|
||||
result[msg.id] = msg; return result
|
||||
result[msg.id] = msg
|
||||
return result
|
||||
}, {})
|
||||
}
|
||||
|
||||
|
@ -77,24 +80,37 @@ export default class PersonalMessageManager extends EventEmitter {
|
|||
* this.memStore.
|
||||
*
|
||||
* @param {Object} msgParams - The params for the eth_sign call to be made after the message is approved.
|
||||
* @param {Object} req (optional) The original request object possibly containing the origin
|
||||
* @returns {promise} - When the message has been signed or rejected
|
||||
* @param {Object} [req] - The original request object possibly containing the origin
|
||||
* @returns {promise} When the message has been signed or rejected
|
||||
*
|
||||
*/
|
||||
addUnapprovedMessageAsync (msgParams, req) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!msgParams.from) {
|
||||
reject(new Error('Nifty Wallet Message Signature: from field is required.'))
|
||||
return
|
||||
}
|
||||
const msgId = this.addUnapprovedMessage(msgParams, req)
|
||||
this.once(`${msgId}:finished`, (data) => {
|
||||
switch (data.status) {
|
||||
case 'signed':
|
||||
return resolve(data.rawSig)
|
||||
resolve(data.rawSig)
|
||||
return
|
||||
case 'rejected':
|
||||
return reject(ethErrors.provider.userRejectedRequest('Nifty Wallet Message Signature: User denied message signature.'))
|
||||
reject(
|
||||
ethErrors.provider.userRejectedRequest(
|
||||
'Nifty Wallet Message Signature: User denied message signature.',
|
||||
),
|
||||
)
|
||||
return
|
||||
default:
|
||||
return reject(new Error(`Nifty Wallet Message Signature: Unknown problem: ${JSON.stringify(msgParams)}`))
|
||||
reject(
|
||||
new Error(
|
||||
`Nifty Wallet Message Signature: Unknown problem: ${JSON.stringify(
|
||||
msgParams,
|
||||
)}`,
|
||||
),
|
||||
)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
@ -106,26 +122,30 @@ export default class PersonalMessageManager extends EventEmitter {
|
|||
* this.memStore.
|
||||
*
|
||||
* @param {Object} msgParams - The params for the eth_sign call to be made after the message is approved.
|
||||
* @param {Object} req (optional) The original request object possibly containing the origin
|
||||
* @returns {number} - The id of the newly created PersonalMessage.
|
||||
* @param {Object} [req] - The original request object possibly containing the origin
|
||||
* @returns {number} The id of the newly created PersonalMessage.
|
||||
*
|
||||
*/
|
||||
addUnapprovedMessage (msgParams, req) {
|
||||
log.debug(`PersonalMessageManager addUnapprovedMessage: ${JSON.stringify(msgParams)}`)
|
||||
log.debug(
|
||||
`PersonalMessageManager addUnapprovedMessage: ${JSON.stringify(
|
||||
msgParams,
|
||||
)}`,
|
||||
)
|
||||
// add origin from request
|
||||
if (req) {
|
||||
msgParams.origin = req.origin
|
||||
}
|
||||
msgParams.data = this.normalizeMsgData(msgParams.data)
|
||||
// create txData obj with parameters and meta data
|
||||
const time = (new Date()).getTime()
|
||||
const time = new Date().getTime()
|
||||
const msgId = createId()
|
||||
const msgData = {
|
||||
id: msgId,
|
||||
msgParams: msgParams,
|
||||
time: time,
|
||||
msgParams,
|
||||
time,
|
||||
status: 'unapproved',
|
||||
type: 'personal_sign',
|
||||
type: MESSAGE_TYPE.PERSONAL_SIGN,
|
||||
}
|
||||
this.addMsg(msgData)
|
||||
|
||||
|
@ -150,7 +170,7 @@ export default class PersonalMessageManager extends EventEmitter {
|
|||
* Returns a specified PersonalMessage.
|
||||
*
|
||||
* @param {number} msgId - The id of the PersonalMessage to get
|
||||
* @returns {PersonalMessage|undefined} - The PersonalMessage with the id that matches the passed msgId, or undefined
|
||||
* @returns {PersonalMessage|undefined} The PersonalMessage with the id that matches the passed msgId, or undefined
|
||||
* if no PersonalMessage has that id.
|
||||
*
|
||||
*/
|
||||
|
@ -164,7 +184,7 @@ export default class PersonalMessageManager extends EventEmitter {
|
|||
*
|
||||
* @param {Object} msgParams - The msgParams to be used when eth_sign is called, plus data added by MetaMask.
|
||||
* @param {Object} msgParams.metamaskId Added to msgParams for tracking and identification within MetaMask.
|
||||
* @returns {Promise<object>} - Promises the msgParams object with metamaskId removed.
|
||||
* @returns {Promise<object>} Promises the msgParams object with metamaskId removed.
|
||||
*
|
||||
*/
|
||||
approveMessage (msgParams) {
|
||||
|
@ -201,7 +221,7 @@ export default class PersonalMessageManager extends EventEmitter {
|
|||
* Removes the metamaskId property from passed msgParams and returns a promise which resolves the updated msgParams
|
||||
*
|
||||
* @param {Object} msgParams - The msgParams to modify
|
||||
* @returns {Promise<object>} - Promises the msgParams with the metamaskId property removed
|
||||
* @returns {Promise<object>} Promises the msgParams with the metamaskId property removed
|
||||
*
|
||||
*/
|
||||
prepMsgForSigning (msgParams) {
|
||||
|
@ -235,7 +255,9 @@ export default class PersonalMessageManager extends EventEmitter {
|
|||
_setMsgStatus (msgId, status) {
|
||||
const msg = this.getMsg(msgId)
|
||||
if (!msg) {
|
||||
throw new Error(`PersonalMessageManager - Message not found for id: "${msgId}".`)
|
||||
throw new Error(
|
||||
`PersonalMessageManager - Message not found for id: "${msgId}".`,
|
||||
)
|
||||
}
|
||||
msg.status = status
|
||||
this._updateMsg(msg)
|
||||
|
@ -271,8 +293,12 @@ export default class PersonalMessageManager extends EventEmitter {
|
|||
*/
|
||||
_saveMsgList () {
|
||||
const unapprovedPersonalMsgs = this.getUnapprovedMsgs()
|
||||
const unapprovedPersonalMsgCount = Object.keys(unapprovedPersonalMsgs).length
|
||||
this.memStore.updateState({ unapprovedPersonalMsgs, unapprovedPersonalMsgCount })
|
||||
const unapprovedPersonalMsgCount = Object.keys(unapprovedPersonalMsgs)
|
||||
.length
|
||||
this.memStore.updateState({
|
||||
unapprovedPersonalMsgs,
|
||||
unapprovedPersonalMsgCount,
|
||||
})
|
||||
this.emit('updateBadge')
|
||||
}
|
||||
|
||||
|
@ -280,14 +306,14 @@ export default class PersonalMessageManager extends EventEmitter {
|
|||
* A helper function that converts raw buffer data to a hex, or just returns the data if it is already formatted as a hex.
|
||||
*
|
||||
* @param {any} data - The buffer data to convert to a hex
|
||||
* @returns {string} - A hex string conversion of the buffer data
|
||||
* @returns {string} A hex string conversion of the buffer data
|
||||
*
|
||||
*/
|
||||
normalizeMsgData (data) {
|
||||
try {
|
||||
const stripped = ethUtil.stripHexPrefix(data)
|
||||
if (stripped.match(hexRe)) {
|
||||
return ethUtil.addHexPrefix(stripped)
|
||||
return addHexPrefix(stripped)
|
||||
}
|
||||
} catch (e) {
|
||||
log.debug(`Message was not hex encoded, interpreting as utf8.`)
|
||||
|
@ -295,5 +321,4 @@ export default class PersonalMessageManager extends EventEmitter {
|
|||
|
||||
return ethUtil.bufferToHex(Buffer.from(data, 'utf8'))
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
import EventEmitter from 'events'
|
||||
import ObservableStore from 'obs-store'
|
||||
import createId from './random-id'
|
||||
import assert from 'assert'
|
||||
import ObservableStore from 'obs-store'
|
||||
import { ethErrors } from 'eth-json-rpc-errors'
|
||||
import sigUtil from 'eth-sig-util'
|
||||
import { typedSignatureHash, TYPED_MESSAGE_SCHEMA } from 'eth-sig-util'
|
||||
import { isValidAddress } from 'ethereumjs-util'
|
||||
import log from 'loglevel'
|
||||
import jsonschema from 'jsonschema'
|
||||
import createId from './random-id'
|
||||
import { MESSAGE_TYPE } from './enums'
|
||||
|
||||
/**
|
||||
* Represents, and contains data about, an 'eth_signTypedData' type signature request. These are created when a
|
||||
|
@ -29,9 +31,9 @@ export default class TypedMessageManager extends EventEmitter {
|
|||
/**
|
||||
* Controller in charge of managing - storing, adding, removing, updating - TypedMessage.
|
||||
*/
|
||||
constructor ({ networkController }) {
|
||||
constructor ({ getCurrentChainId }) {
|
||||
super()
|
||||
this.networkController = networkController
|
||||
this._getCurrentChainId = getCurrentChainId
|
||||
this.memStore = new ObservableStore({
|
||||
unapprovedTypedMessages: {},
|
||||
unapprovedTypedMessagesCount: 0,
|
||||
|
@ -42,7 +44,7 @@ export default class TypedMessageManager extends EventEmitter {
|
|||
/**
|
||||
* A getter for the number of 'unapproved' TypedMessages in this.messages
|
||||
*
|
||||
* @returns {number} - The number of 'unapproved' TypedMessages in this.messages
|
||||
* @returns {number} The number of 'unapproved' TypedMessages in this.messages
|
||||
*
|
||||
*/
|
||||
get unapprovedTypedMessagesCount () {
|
||||
|
@ -52,14 +54,16 @@ export default class TypedMessageManager extends EventEmitter {
|
|||
/**
|
||||
* A getter for the 'unapproved' TypedMessages in this.messages
|
||||
*
|
||||
* @returns {Object} - An index of TypedMessage ids to TypedMessages, for all 'unapproved' TypedMessages in
|
||||
* @returns {Object} An index of TypedMessage ids to TypedMessages, for all 'unapproved' TypedMessages in
|
||||
* this.messages
|
||||
*
|
||||
*/
|
||||
getUnapprovedMsgs () {
|
||||
return this.messages.filter((msg) => msg.status === 'unapproved')
|
||||
return this.messages
|
||||
.filter((msg) => msg.status === 'unapproved')
|
||||
.reduce((result, msg) => {
|
||||
result[msg.id] = msg; return result
|
||||
result[msg.id] = msg
|
||||
return result
|
||||
}, {})
|
||||
}
|
||||
|
||||
|
@ -69,8 +73,8 @@ export default class TypedMessageManager extends EventEmitter {
|
|||
* this.memStore. Before any of this is done, msgParams are validated
|
||||
*
|
||||
* @param {Object} msgParams - The params for the eth_sign call to be made after the message is approved.
|
||||
* @param {Object} req (optional) The original request object possibly containing the origin
|
||||
* @returns {promise} - When the message has been signed or rejected
|
||||
* @param {Object} [req] - The original request object possibly containing the origin
|
||||
* @returns {promise} When the message has been signed or rejected
|
||||
*
|
||||
*/
|
||||
addUnapprovedMessageAsync (msgParams, req, version) {
|
||||
|
@ -81,11 +85,23 @@ export default class TypedMessageManager extends EventEmitter {
|
|||
case 'signed':
|
||||
return resolve(data.rawSig)
|
||||
case 'rejected':
|
||||
return reject(ethErrors.provider.userRejectedRequest('Nifty Wallet Message Signature: User denied message signature.'))
|
||||
return reject(
|
||||
ethErrors.provider.userRejectedRequest(
|
||||
'Nifty Wallet Message Signature: User denied message signature.',
|
||||
),
|
||||
)
|
||||
case 'errored':
|
||||
return reject(new Error(`Nifty Wallet Message Signature: ${data.error}`))
|
||||
return reject(
|
||||
new Error(`Nifty Wallet Message Signature: ${data.error}`),
|
||||
)
|
||||
default:
|
||||
return reject(new Error(`Nifty Wallet Message Signature: Unknown problem: ${JSON.stringify(msgParams)}`))
|
||||
return reject(
|
||||
new Error(
|
||||
`Nifty Wallet Message Signature: Unknown problem: ${JSON.stringify(
|
||||
msgParams,
|
||||
)}`,
|
||||
),
|
||||
)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
@ -97,28 +113,30 @@ export default class TypedMessageManager extends EventEmitter {
|
|||
* this.memStore. Before any of this is done, msgParams are validated
|
||||
*
|
||||
* @param {Object} msgParams - The params for the eth_sign call to be made after the message is approved.
|
||||
* @param {Object} req (optional) The original request object possibly containing the origin
|
||||
* @returns {number} - The id of the newly created TypedMessage.
|
||||
* @param {Object} [req] - The original request object possibly containing the origin
|
||||
* @returns {number} The id of the newly created TypedMessage.
|
||||
*
|
||||
*/
|
||||
addUnapprovedMessage (msgParams, req, version) {
|
||||
msgParams.version = version
|
||||
this.validateParams(msgParams)
|
||||
// add origin from request
|
||||
if (req) {
|
||||
msgParams.origin = req.origin
|
||||
}
|
||||
this.validateParams(msgParams)
|
||||
|
||||
log.debug(
|
||||
`TypedMessageManager addUnapprovedMessage: ${JSON.stringify(msgParams)}`,
|
||||
)
|
||||
|
||||
log.debug(`TypedMessageManager addUnapprovedMessage: ${JSON.stringify(msgParams)}`)
|
||||
// create txData obj with parameters and meta data
|
||||
const time = (new Date()).getTime()
|
||||
const time = new Date().getTime()
|
||||
const msgId = createId()
|
||||
const msgData = {
|
||||
id: msgId,
|
||||
msgParams: msgParams,
|
||||
time: time,
|
||||
msgParams,
|
||||
time,
|
||||
status: 'unapproved',
|
||||
type: 'eth_signTypedData',
|
||||
type: MESSAGE_TYPE.ETH_SIGN_TYPED_DATA,
|
||||
}
|
||||
this.addMsg(msgData)
|
||||
|
||||
|
@ -134,37 +152,59 @@ export default class TypedMessageManager extends EventEmitter {
|
|||
*
|
||||
*/
|
||||
validateParams (params) {
|
||||
assert.ok(params && typeof params === 'object', 'Params must be an object.')
|
||||
assert.ok('data' in params, 'Params must include a "data" field.')
|
||||
assert.ok('from' in params, 'Params must include a "from" field.')
|
||||
assert.ok(
|
||||
typeof params.from === 'string' && isValidAddress(params.from),
|
||||
'"from" field must be a valid, lowercase, hexadecimal Ethereum address string.',
|
||||
)
|
||||
|
||||
switch (params.version) {
|
||||
case 'V1':
|
||||
assert.equal(typeof params, 'object', 'Params should ben an object.')
|
||||
assert.ok('data' in params, 'Params must include a data field.')
|
||||
assert.ok('from' in params, 'Params must include a from field.')
|
||||
assert.ok(Array.isArray(params.data), 'Data should be an array.')
|
||||
assert.equal(typeof params.from, 'string', 'From field must be a string.')
|
||||
assert.ok(Array.isArray(params.data), '"params.data" must be an array.')
|
||||
assert.doesNotThrow(() => {
|
||||
sigUtil.typedSignatureHash(params.data)
|
||||
}, 'Expected EIP712 typed data')
|
||||
typedSignatureHash(params.data)
|
||||
}, 'Signing data must be valid EIP-712 typed data.')
|
||||
break
|
||||
case 'V3':
|
||||
case 'V4':
|
||||
case 'V4': {
|
||||
assert.equal(
|
||||
typeof params.data,
|
||||
'string',
|
||||
'"params.data" must be a string.',
|
||||
)
|
||||
let data
|
||||
assert.equal(typeof params, 'object', 'Params should be an object.')
|
||||
assert.ok('data' in params, 'Params must include a data field.')
|
||||
assert.ok('from' in params, 'Params must include a from field.')
|
||||
assert.equal(typeof params.from, 'string', 'From field must be a string.')
|
||||
assert.equal(typeof params.data, 'string', 'Data must be passed as a valid JSON string.')
|
||||
assert.doesNotThrow(() => {
|
||||
data = JSON.parse(params.data)
|
||||
}, 'Data must be passed as a valid JSON string.')
|
||||
const validation = jsonschema.validate(data, sigUtil.TYPED_MESSAGE_SCHEMA)
|
||||
assert.ok(data.primaryType in data.types, `Primary type of "${data.primaryType}" has no type definition.`)
|
||||
assert.equal(validation.errors.length, 0, 'Data must conform to EIP-712 schema. See https://git.io/fNtcx.')
|
||||
const chainId = data.domain.chainId
|
||||
const activeChainId = parseInt(this.networkController.getNetworkState())
|
||||
chainId && assert.equal(chainId, activeChainId, `Provided chainId (${chainId}) must match the active chainId (${activeChainId})`)
|
||||
}, '"data" must be a valid JSON string.')
|
||||
const validation = jsonschema.validate(data, TYPED_MESSAGE_SCHEMA)
|
||||
assert.ok(
|
||||
data.primaryType in data.types,
|
||||
`Primary type of "${data.primaryType}" has no type definition.`,
|
||||
)
|
||||
assert.equal(
|
||||
validation.errors.length,
|
||||
0,
|
||||
'Signing data must conform to EIP-712 schema. See https://git.io/fNtcx.',
|
||||
)
|
||||
const { chainId } = data.domain
|
||||
if (chainId) {
|
||||
const activeChainId = parseInt(this._getCurrentChainId(), 16)
|
||||
assert.ok(
|
||||
!Number.isNaN(activeChainId),
|
||||
`Cannot sign messages for chainId "${chainId}", because MetaMask is switching networks.`,
|
||||
)
|
||||
assert.equal(
|
||||
chainId,
|
||||
activeChainId,
|
||||
`Provided chainId "${chainId}" must match the active chainId "${activeChainId}"`,
|
||||
)
|
||||
}
|
||||
break
|
||||
}
|
||||
default:
|
||||
assert.fail(`Unknown params.version ${params.version}`)
|
||||
assert.fail(`Unknown typed data version "${params.version}"`)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -184,7 +224,7 @@ export default class TypedMessageManager extends EventEmitter {
|
|||
* Returns a specified TypedMessage.
|
||||
*
|
||||
* @param {number} msgId - The id of the TypedMessage to get
|
||||
* @returns {TypedMessage|undefined} - The TypedMessage with the id that matches the passed msgId, or undefined
|
||||
* @returns {TypedMessage|undefined} The TypedMessage with the id that matches the passed msgId, or undefined
|
||||
* if no TypedMessage has that id.
|
||||
*
|
||||
*/
|
||||
|
@ -198,7 +238,7 @@ export default class TypedMessageManager extends EventEmitter {
|
|||
*
|
||||
* @param {Object} msgParams - The msgParams to be used when eth_sign is called, plus data added by MetaMask.
|
||||
* @param {Object} msgParams.metamaskId Added to msgParams for tracking and identification within MetaMask.
|
||||
* @returns {Promise<object>} - Promises the msgParams object with metamaskId removed.
|
||||
* @returns {Promise<object>} Promises the msgParams object with metamaskId removed.
|
||||
*
|
||||
*/
|
||||
approveMessage (msgParams) {
|
||||
|
@ -235,7 +275,7 @@ export default class TypedMessageManager extends EventEmitter {
|
|||
* Removes the metamaskId property from passed msgParams and returns a promise which resolves the updated msgParams
|
||||
*
|
||||
* @param {Object} msgParams - The msgParams to modify
|
||||
* @returns {Promise<object>} - Promises the msgParams with the metamaskId property removed
|
||||
* @returns {Promise<object>} Promises the msgParams with the metamaskId property removed
|
||||
*
|
||||
*/
|
||||
prepMsgForSigning (msgParams) {
|
||||
|
@ -287,7 +327,9 @@ export default class TypedMessageManager extends EventEmitter {
|
|||
_setMsgStatus (msgId, status) {
|
||||
const msg = this.getMsg(msgId)
|
||||
if (!msg) {
|
||||
throw new Error('TypedMessageManager - Message not found for id: "${msgId}".')
|
||||
throw new Error(
|
||||
`TypedMessageManager - Message not found for id: "${msgId}".`,
|
||||
)
|
||||
}
|
||||
msg.status = status
|
||||
this._updateMsg(msg)
|
||||
|
@ -323,9 +365,12 @@ export default class TypedMessageManager extends EventEmitter {
|
|||
*/
|
||||
_saveMsgList () {
|
||||
const unapprovedTypedMessages = this.getUnapprovedMsgs()
|
||||
const unapprovedTypedMessagesCount = Object.keys(unapprovedTypedMessages).length
|
||||
this.memStore.updateState({ unapprovedTypedMessages, unapprovedTypedMessagesCount })
|
||||
const unapprovedTypedMessagesCount = Object.keys(unapprovedTypedMessages)
|
||||
.length
|
||||
this.memStore.updateState({
|
||||
unapprovedTypedMessages,
|
||||
unapprovedTypedMessagesCount,
|
||||
})
|
||||
this.emit('updateBadge')
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -84,6 +84,28 @@ function sufficientBalance (txParams, hexBalance) {
|
|||
return balance.gte(maxCost)
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefixes a hex string with '0x' or '-0x' and returns it. Idempotent.
|
||||
*
|
||||
* @param {string} str - The string to prefix.
|
||||
* @returns {string} The prefixed string.
|
||||
*/
|
||||
const addHexPrefix = (str) => {
|
||||
if (typeof str !== 'string' || str.match(/^-?0x/u)) {
|
||||
return str
|
||||
}
|
||||
|
||||
if (str.match(/^-?0X/u)) {
|
||||
return str.replace('0X', '0x')
|
||||
}
|
||||
|
||||
if (str.startsWith('-')) {
|
||||
return str.replace('-', '-0x')
|
||||
}
|
||||
|
||||
return `0x${str}`
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a BN object to a hex string with a '0x' prefix
|
||||
*
|
||||
|
@ -171,6 +193,7 @@ module.exports = {
|
|||
getEnvironmentType,
|
||||
sufficientBalance,
|
||||
hexToBn,
|
||||
addHexPrefix,
|
||||
bnToHex,
|
||||
BnMultiplyByFraction,
|
||||
capitalizeFirstLetter,
|
||||
|
|
|
@ -284,7 +284,11 @@ module.exports = class MetamaskController extends EventEmitter {
|
|||
this.personalMessageManager = new PersonalMessageManager()
|
||||
this.decryptMessageManager = new DecryptMessageManager()
|
||||
this.encryptionPublicKeyManager = new EncryptionPublicKeyManager()
|
||||
this.typedMessageManager = new TypedMessageManager({ networkController: this.networkController })
|
||||
this.typedMessageManager = new TypedMessageManager({
|
||||
getCurrentChainId: this.networkController.getCurrentChainId.bind(
|
||||
this.networkController,
|
||||
),
|
||||
})
|
||||
|
||||
// ensure isClientOpenAndUnlocked is updated when memState updates
|
||||
this.on('update', (memState) => {
|
||||
|
@ -1694,10 +1698,6 @@ module.exports = class MetamaskController extends EventEmitter {
|
|||
// engine.push(this.permissionsController.createMiddleware({ origin, extensionId }))
|
||||
// watch asset
|
||||
engine.push(this.preferencesController.requestWatchAsset.bind(this.preferencesController))
|
||||
// sign typed data middleware
|
||||
engine.push(this.createTypedDataMiddleware('eth_signTypedData', 'V1').bind(this))
|
||||
engine.push(this.createTypedDataMiddleware('eth_signTypedData_v1', 'V1').bind(this))
|
||||
engine.push(this.createTypedDataMiddleware('eth_signTypedData_v3', 'V3', true).bind(this))
|
||||
// forward to metamask primary provider
|
||||
engine.push(providerAsMiddleware(provider))
|
||||
return engine
|
||||
|
@ -2189,35 +2189,35 @@ module.exports = class MetamaskController extends EventEmitter {
|
|||
this.tokenRatesController.isActive = active
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates RPC engine middleware for processing eth_signTypedData requests
|
||||
*
|
||||
* @param {Object} req - request object
|
||||
* @param {Object} res - response object
|
||||
* @param {Function} - next
|
||||
* @param {Function} - end
|
||||
*/
|
||||
createTypedDataMiddleware (methodName, version, reverse) {
|
||||
return async (req, res, next, end) => {
|
||||
const { method, params } = req
|
||||
if (method === methodName) {
|
||||
const promise = this.typedMessageManager.addUnapprovedMessageAsync({
|
||||
data: reverse ? params[1] : params[0],
|
||||
from: reverse ? params[0] : params[1],
|
||||
}, req, version)
|
||||
this.sendUpdate()
|
||||
this.opts.showUnconfirmedMessage()
|
||||
try {
|
||||
res.result = await promise
|
||||
end()
|
||||
} catch (error) {
|
||||
end(error)
|
||||
}
|
||||
} else {
|
||||
next()
|
||||
}
|
||||
}
|
||||
}
|
||||
// /**
|
||||
// * Creates RPC engine middleware for processing eth_signTypedData requests
|
||||
// *
|
||||
// * @param {Object} req - request object
|
||||
// * @param {Object} res - response object
|
||||
// * @param {Function} - next
|
||||
// * @param {Function} - end
|
||||
// */
|
||||
// createTypedDataMiddleware (methodName, version, reverse) {
|
||||
// return async (req, res, next, end) => {
|
||||
// const { method, params } = req
|
||||
// if (method === methodName) {
|
||||
// const promise = this.typedMessageManager.addUnapprovedMessageAsync({
|
||||
// data: reverse ? params[1] : params[0],
|
||||
// from: reverse ? params[0] : params[1],
|
||||
// }, req, version)
|
||||
// this.sendUpdate()
|
||||
// this.opts.showUnconfirmedMessage()
|
||||
// try {
|
||||
// res.result = await promise
|
||||
// end()
|
||||
// } catch (error) {
|
||||
// end(error)
|
||||
// }
|
||||
// } else {
|
||||
// next()
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
/**
|
||||
* Adds a domain to the PhishingController whitelist
|
||||
|
|
|
@ -1,70 +1,98 @@
|
|||
const Component = require('react').Component
|
||||
const h = require('react-hyperscript')
|
||||
const inherits = require('util').inherits
|
||||
import React, { Component } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
const extend = require('xtend')
|
||||
const { ObjectInspector } = require('react-inspector')
|
||||
import classnames from 'classnames'
|
||||
|
||||
module.exports = TypedMessageRenderer
|
||||
|
||||
inherits(TypedMessageRenderer, Component)
|
||||
function TypedMessageRenderer () {
|
||||
Component.call(this)
|
||||
}
|
||||
|
||||
TypedMessageRenderer.prototype.render = function () {
|
||||
const props = this.props
|
||||
const { value, version, style } = props
|
||||
let text
|
||||
switch (version) {
|
||||
case 'V1':
|
||||
text = renderTypedData(value)
|
||||
break
|
||||
case 'V3':
|
||||
text = renderTypedDataV3(value)
|
||||
break
|
||||
class TypedMessageRenderer extends Component {
|
||||
static propTypes = {
|
||||
value: PropTypes.object,
|
||||
version: PropTypes.string,
|
||||
style: PropTypes.object,
|
||||
}
|
||||
|
||||
const defaultStyle = extend({
|
||||
width: '100%',
|
||||
maxHeight: '210px',
|
||||
resize: 'none',
|
||||
border: 'none',
|
||||
background: '#542289',
|
||||
color: 'white',
|
||||
padding: '20px',
|
||||
overflow: 'scroll',
|
||||
}, style)
|
||||
renderTypedData (values) {
|
||||
return values.map(function (value, ind) {
|
||||
let v = value.value
|
||||
if (typeof v === 'boolean') {
|
||||
v = v.toString()
|
||||
}
|
||||
return (
|
||||
<div key={ind}>
|
||||
<strong style={{display: 'block', fontWeight: 'bold'}}>{String(value.name) + ':'}</strong>
|
||||
<div>{v}</div>
|
||||
</div
|
||||
>)
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
h('div.font-small', {
|
||||
style: defaultStyle,
|
||||
}, text)
|
||||
)
|
||||
}
|
||||
renderTypedDataV3V4 (values) {
|
||||
const { message } = JSON.parse(values)
|
||||
return [
|
||||
message ? <div>
|
||||
<h1>Message</h1>
|
||||
{this.renderNode(message)}
|
||||
</div> : '',
|
||||
]
|
||||
}
|
||||
|
||||
function renderTypedData (values) {
|
||||
return values.map(function (value) {
|
||||
let v = value.value
|
||||
if (typeof v === 'boolean') {
|
||||
v = v.toString()
|
||||
renderNode (data) {
|
||||
return (
|
||||
<div className="signature-request-message--node">
|
||||
{Object.entries(data).map(([label, value], i) => (
|
||||
<div
|
||||
className={classnames('signature-request-message--node', {
|
||||
'signature-request-message--node-leaf':
|
||||
typeof value !== 'object' || value === null,
|
||||
})}
|
||||
key={i}
|
||||
>
|
||||
<span className="signature-request-message--node-label">
|
||||
{label}:{' '}
|
||||
</span>
|
||||
{typeof value === 'object' && value !== null ? (
|
||||
this.renderNode(value)
|
||||
) : (
|
||||
<span className="signature-request-message--node-value">
|
||||
{value}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
render () {
|
||||
const props = this.props
|
||||
const { value, version, style } = props
|
||||
let text
|
||||
switch (version) {
|
||||
case 'V1':
|
||||
text = this.renderTypedData(value)
|
||||
break
|
||||
case 'V3':
|
||||
case 'V4':
|
||||
text = this.renderTypedDataV3V4(value)
|
||||
break
|
||||
}
|
||||
return h('div', {}, [
|
||||
h('strong', {style: {display: 'block', fontWeight: 'bold'}}, String(value.name) + ':'),
|
||||
h('div', {}, v),
|
||||
])
|
||||
})
|
||||
|
||||
const defaultStyle = extend({
|
||||
width: '100%',
|
||||
maxHeight: '210px',
|
||||
resize: 'none',
|
||||
border: 'none',
|
||||
background: '#542289',
|
||||
color: 'white',
|
||||
padding: '20px',
|
||||
overflow: 'auto',
|
||||
}, style)
|
||||
|
||||
return (
|
||||
<div className="font-small" style={defaultStyle}>
|
||||
{text}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
function renderTypedDataV3 (values) {
|
||||
const { domain, message } = JSON.parse(values)
|
||||
return [
|
||||
domain ? h('div', [
|
||||
h('h1', 'Domain'),
|
||||
h(ObjectInspector, { data: domain, expandLevel: 1, name: 'domain' }),
|
||||
]) : '',
|
||||
message ? h('div', [
|
||||
h('h1', 'Message'),
|
||||
h(ObjectInspector, { data: message, expandLevel: 1, name: 'message' }),
|
||||
]) : '',
|
||||
]
|
||||
}
|
||||
module.exports = TypedMessageRenderer
|
||||
|
|
|
@ -3381,6 +3381,14 @@
|
|||
"integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/pbkdf2": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/pbkdf2/-/pbkdf2-3.1.0.tgz",
|
||||
"integrity": "sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ==",
|
||||
"requires": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/prop-types": {
|
||||
"version": "15.7.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.3.tgz",
|
||||
|
@ -3446,6 +3454,14 @@
|
|||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"@types/secp256k1": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.1.tgz",
|
||||
"integrity": "sha512-+ZjSA8ELlOp8SlKi0YLB2tz9d5iPNEmOBd+8Rz21wTMdaXQIa9b6TEnD6l5qKOCypE7FSyPyck12qZJxSDNoog==",
|
||||
"requires": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/stack-utils": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-1.0.1.tgz",
|
||||
|
@ -6573,6 +6589,11 @@
|
|||
"safe-buffer": "^5.1.1"
|
||||
}
|
||||
},
|
||||
"blakejs": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.1.0.tgz",
|
||||
"integrity": "sha1-ad+S75U6qIylGjLfarHFShVfx6U="
|
||||
},
|
||||
"blob": {
|
||||
"version": "0.0.5",
|
||||
"resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz",
|
||||
|
@ -7085,22 +7106,6 @@
|
|||
"randombytes": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"browserify-sha3": {
|
||||
"version": "0.0.4",
|
||||
"resolved": "https://registry.npmjs.org/browserify-sha3/-/browserify-sha3-0.0.4.tgz",
|
||||
"integrity": "sha1-CGxHuMgjFsnUcCLCYYWVRXbdjiY=",
|
||||
"requires": {
|
||||
"js-sha3": "^0.6.1",
|
||||
"safe-buffer": "^5.1.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"js-sha3": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.6.1.tgz",
|
||||
"integrity": "sha1-W4n3enR3Z5h39YxKB1JAk0sflcA="
|
||||
}
|
||||
}
|
||||
},
|
||||
"browserify-sign": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz",
|
||||
|
@ -11383,6 +11388,44 @@
|
|||
"xtend": "^4.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"eth-sig-util": {
|
||||
"version": "2.5.2",
|
||||
"resolved": "https://registry.npmjs.org/eth-sig-util/-/eth-sig-util-2.5.2.tgz",
|
||||
"integrity": "sha512-xvDojS/4reXsw8Pz/+p/qcM5rVB61FOdPbEtMZ8FQ0YHnPEzPy5F8zAAaZ+zj5ud0SwRLWPfor2Cacjm7EzMIw==",
|
||||
"requires": {
|
||||
"buffer": "^5.2.1",
|
||||
"elliptic": "^6.4.0",
|
||||
"ethereumjs-abi": "0.6.5",
|
||||
"ethereumjs-util": "^5.1.1",
|
||||
"tweetnacl": "^1.0.0",
|
||||
"tweetnacl-util": "^0.15.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ethereumjs-abi": {
|
||||
"version": "0.6.5",
|
||||
"resolved": "https://registry.npmjs.org/ethereumjs-abi/-/ethereumjs-abi-0.6.5.tgz",
|
||||
"integrity": "sha1-WmN+8Wq0NHP6cqKa2QhxQFs/UkE=",
|
||||
"requires": {
|
||||
"bn.js": "^4.10.0",
|
||||
"ethereumjs-util": "^4.3.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ethereumjs-util": {
|
||||
"version": "4.5.1",
|
||||
"resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-4.5.1.tgz",
|
||||
"integrity": "sha512-WrckOZ7uBnei4+AKimpuF1B3Fv25OmoRgmYCpGsP7u8PFxXAmAgiJSYT2kRWnt6fVIlKaQlZvuwXp7PIrmn3/w==",
|
||||
"requires": {
|
||||
"bn.js": "^4.8.0",
|
||||
"create-hash": "^1.1.2",
|
||||
"elliptic": "^6.5.2",
|
||||
"ethereum-cryptography": "^0.1.3",
|
||||
"rlp": "^2.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"events": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz",
|
||||
|
@ -11866,9 +11909,9 @@
|
|||
}
|
||||
},
|
||||
"eth-sig-util": {
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://registry.npmjs.org/eth-sig-util/-/eth-sig-util-2.5.1.tgz",
|
||||
"integrity": "sha512-F5k+6gdSphUtHwCsj0QD59gwxxXoG+ZiFODgTiGS7xc53tPcjBSdBRuhcXdLwXGiytsjk+77oYQRRYeAKXIjBQ==",
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/eth-sig-util/-/eth-sig-util-3.0.0.tgz",
|
||||
"integrity": "sha512-4eFkMOhpGbTxBQ3AMzVf0haUX2uTur7DpWiHzWyTURa28BVJJtOkcb9Ok5TV0YvEPG61DODPW7ZUATbJTslioQ==",
|
||||
"requires": {
|
||||
"buffer": "^5.2.1",
|
||||
"elliptic": "^6.4.0",
|
||||
|
@ -11888,15 +11931,15 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"ethereumjs-util": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-4.5.0.tgz",
|
||||
"integrity": "sha1-PpQosxfuvaPXJg2FT93alUsfG8Y=",
|
||||
"version": "4.5.1",
|
||||
"resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-4.5.1.tgz",
|
||||
"integrity": "sha512-WrckOZ7uBnei4+AKimpuF1B3Fv25OmoRgmYCpGsP7u8PFxXAmAgiJSYT2kRWnt6fVIlKaQlZvuwXp7PIrmn3/w==",
|
||||
"requires": {
|
||||
"bn.js": "^4.8.0",
|
||||
"create-hash": "^1.1.2",
|
||||
"keccakjs": "^0.2.0",
|
||||
"rlp": "^2.0.0",
|
||||
"secp256k1": "^3.0.1"
|
||||
"elliptic": "^6.5.2",
|
||||
"ethereum-cryptography": "^0.1.3",
|
||||
"rlp": "^2.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11916,6 +11959,44 @@
|
|||
"xtend": "^4.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"eth-sig-util": {
|
||||
"version": "2.5.2",
|
||||
"resolved": "https://registry.npmjs.org/eth-sig-util/-/eth-sig-util-2.5.2.tgz",
|
||||
"integrity": "sha512-xvDojS/4reXsw8Pz/+p/qcM5rVB61FOdPbEtMZ8FQ0YHnPEzPy5F8zAAaZ+zj5ud0SwRLWPfor2Cacjm7EzMIw==",
|
||||
"requires": {
|
||||
"buffer": "^5.2.1",
|
||||
"elliptic": "^6.4.0",
|
||||
"ethereumjs-abi": "0.6.5",
|
||||
"ethereumjs-util": "^5.1.1",
|
||||
"tweetnacl": "^1.0.0",
|
||||
"tweetnacl-util": "^0.15.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ethereumjs-abi": {
|
||||
"version": "0.6.5",
|
||||
"resolved": "https://registry.npmjs.org/ethereumjs-abi/-/ethereumjs-abi-0.6.5.tgz",
|
||||
"integrity": "sha1-WmN+8Wq0NHP6cqKa2QhxQFs/UkE=",
|
||||
"requires": {
|
||||
"bn.js": "^4.10.0",
|
||||
"ethereumjs-util": "^4.3.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ethereumjs-util": {
|
||||
"version": "4.5.1",
|
||||
"resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-4.5.1.tgz",
|
||||
"integrity": "sha512-WrckOZ7uBnei4+AKimpuF1B3Fv25OmoRgmYCpGsP7u8PFxXAmAgiJSYT2kRWnt6fVIlKaQlZvuwXp7PIrmn3/w==",
|
||||
"requires": {
|
||||
"bn.js": "^4.8.0",
|
||||
"create-hash": "^1.1.2",
|
||||
"elliptic": "^6.5.2",
|
||||
"ethereum-cryptography": "^0.1.3",
|
||||
"rlp": "^2.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"events": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz",
|
||||
|
@ -12114,6 +12195,49 @@
|
|||
"resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.2.0.tgz",
|
||||
"integrity": "sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA=="
|
||||
},
|
||||
"ethereum-cryptography": {
|
||||
"version": "0.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz",
|
||||
"integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==",
|
||||
"requires": {
|
||||
"@types/pbkdf2": "^3.0.0",
|
||||
"@types/secp256k1": "^4.0.1",
|
||||
"blakejs": "^1.1.0",
|
||||
"browserify-aes": "^1.2.0",
|
||||
"bs58check": "^2.1.2",
|
||||
"create-hash": "^1.2.0",
|
||||
"create-hmac": "^1.1.7",
|
||||
"hash.js": "^1.1.7",
|
||||
"keccak": "^3.0.0",
|
||||
"pbkdf2": "^3.0.17",
|
||||
"randombytes": "^2.1.0",
|
||||
"safe-buffer": "^5.1.2",
|
||||
"scrypt-js": "^3.0.0",
|
||||
"secp256k1": "^4.0.1",
|
||||
"setimmediate": "^1.0.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"keccak": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.1.tgz",
|
||||
"integrity": "sha512-epq90L9jlFWCW7+pQa6JOnKn2Xgl2mtI664seYR6MHskvI9agt7AnDqmAlp9TqU4/caMYbA08Hi5DMZAl5zdkA==",
|
||||
"requires": {
|
||||
"node-addon-api": "^2.0.0",
|
||||
"node-gyp-build": "^4.2.0"
|
||||
}
|
||||
},
|
||||
"secp256k1": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.2.tgz",
|
||||
"integrity": "sha512-UDar4sKvWAksIlfX3xIaQReADn+WFnHvbVujpcbr+9Sf/69odMwy2MUsz5CKLQgX9nsIyrjuxL2imVyoNHa3fg==",
|
||||
"requires": {
|
||||
"elliptic": "^6.5.2",
|
||||
"node-addon-api": "^2.0.0",
|
||||
"node-gyp-build": "^4.2.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"ethereum-ens-network-map": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/ethereum-ens-network-map/-/ethereum-ens-network-map-1.0.2.tgz",
|
||||
|
@ -36396,13 +36520,11 @@
|
|||
"dev": true
|
||||
},
|
||||
"json-rpc-engine": {
|
||||
"version": "5.1.8",
|
||||
"resolved": "https://registry.npmjs.org/json-rpc-engine/-/json-rpc-engine-5.1.8.tgz",
|
||||
"integrity": "sha512-vTBSDEPJV1fPAsbm2g5sEuPjsgLdiab2f1CTn2PyRr8nxggUpA996PDlNQDsM0gnrA99F8KIBLq2nIKrOFl1Mg==",
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/json-rpc-engine/-/json-rpc-engine-5.3.0.tgz",
|
||||
"integrity": "sha512-+diJ9s8rxB+fbJhT7ZEf8r8spaLRignLd8jTgQ/h5JSGppAHGtNMZtCoabipCaleR1B3GTGxbXBOqhaJSGmPGQ==",
|
||||
"requires": {
|
||||
"async": "^2.0.1",
|
||||
"eth-json-rpc-errors": "^2.0.1",
|
||||
"promise-to-callback": "^1.0.0",
|
||||
"eth-rpc-errors": "^3.0.0",
|
||||
"safe-event-emitter": "^1.0.1"
|
||||
}
|
||||
},
|
||||
|
@ -37205,15 +37327,6 @@
|
|||
"safe-buffer": "^5.2.0"
|
||||
}
|
||||
},
|
||||
"keccakjs": {
|
||||
"version": "0.2.3",
|
||||
"resolved": "https://registry.npmjs.org/keccakjs/-/keccakjs-0.2.3.tgz",
|
||||
"integrity": "sha512-BjLkNDcfaZ6l8HBG9tH0tpmDv3sS2mA7FNQxFHpCdzP3Gb2MVruXBSuoM66SnVxKJpAr5dKGdkHD+bDokt8fTg==",
|
||||
"requires": {
|
||||
"browserify-sha3": "^0.0.4",
|
||||
"sha3": "^1.2.2"
|
||||
}
|
||||
},
|
||||
"kind-of": {
|
||||
"version": "6.0.3",
|
||||
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
|
||||
|
@ -39784,6 +39897,11 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node-addon-api": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz",
|
||||
"integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA=="
|
||||
},
|
||||
"node-dir": {
|
||||
"version": "0.1.17",
|
||||
"resolved": "https://registry.npmjs.org/node-dir/-/node-dir-0.1.17.tgz",
|
||||
|
@ -39860,6 +39978,11 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node-gyp-build": {
|
||||
"version": "4.2.3",
|
||||
"resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.2.3.tgz",
|
||||
"integrity": "sha512-MN6ZpzmfNCRM+3t57PTJHgHyw/h4OWnZ6mR8P5j/uZtqQr46RRuDE/P+g3n0YR/AiYXeWixZZzaip77gdICfRg=="
|
||||
},
|
||||
"node-int64": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
|
||||
|
@ -44966,6 +45089,11 @@
|
|||
"nan": "^2.0.8"
|
||||
}
|
||||
},
|
||||
"scrypt-js": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz",
|
||||
"integrity": "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA=="
|
||||
},
|
||||
"scrypt.js": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/scrypt.js/-/scrypt.js-0.3.0.tgz",
|
||||
|
@ -45215,21 +45343,6 @@
|
|||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"sha3": {
|
||||
"version": "1.2.6",
|
||||
"resolved": "https://registry.npmjs.org/sha3/-/sha3-1.2.6.tgz",
|
||||
"integrity": "sha512-KgLGmJGrmNB4JWVsAV11Yk6KbvsAiygWJc7t5IebWva/0NukNrjJqhtKhzy3Eiv2AKuGvhZZt7dt1mDo7HkoiQ==",
|
||||
"requires": {
|
||||
"nan": "2.13.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"nan": {
|
||||
"version": "2.13.2",
|
||||
"resolved": "https://registry.npmjs.org/nan/-/nan-2.13.2.tgz",
|
||||
"integrity": "sha512-TghvYc72wlMGMVMluVo9WRJc0mB8KxxF/gZ4YYFy7V2ZQX9l7rgbPg7vjS9mt6U5HXODVFVI2bOduCzwOMv/lw=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"shallow-clone": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-0.1.2.tgz",
|
||||
|
|
|
@ -124,7 +124,7 @@
|
|||
"eth-net-props": "^1.0.36",
|
||||
"eth-phishing-detect": "^1.1.4",
|
||||
"eth-query": "^2.1.2",
|
||||
"eth-sig-util": "^2.5.1",
|
||||
"eth-sig-util": "^3.0.0",
|
||||
"eth-token-watcher": "^1.1.7",
|
||||
"eth-trezor-keyring": "github:vbaranov/eth-trezor-keyring#0.4.0",
|
||||
"ethereumjs-abi": "^0.6.7",
|
||||
|
@ -148,7 +148,7 @@
|
|||
"idb-global": "^2.1.0",
|
||||
"iframe-stream": "^3.0.0",
|
||||
"inject-css": "^0.1.1",
|
||||
"json-rpc-engine": "^5.1.8",
|
||||
"json-rpc-engine": "^5.3.0",
|
||||
"json-rpc-middleware-stream": "^2.1.1",
|
||||
"json-rpc-pocket": "0.0.1",
|
||||
"jsonschema": "^1.2.4",
|
||||
|
|
Loading…
Reference in New Issue