mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-23 18:41:38 +01:00
8819475a2e
Implement generation of markdown for notice files. Create npm command. Enhance notice generation. Add test files to test multiple notices. Add basic markdown support to notices. Interval checks for updates. Add extensionizer and linker Add terms and conditions state file Add link support to disclaimer. Changelog addition.
467 lines
12 KiB
JavaScript
467 lines
12 KiB
JavaScript
const Migrator = require('pojo-migrator')
|
|
const MetamaskConfig = require('../config.js')
|
|
const migrations = require('./migrations')
|
|
const rp = require('request-promise')
|
|
const notices = require('../../../development/notices.json')
|
|
|
|
const TESTNET_RPC = MetamaskConfig.network.testnet
|
|
const MAINNET_RPC = MetamaskConfig.network.mainnet
|
|
const MORDEN_RPC = MetamaskConfig.network.morden
|
|
const txLimit = 40
|
|
|
|
/* The config-manager is a convenience object
|
|
* wrapping a pojo-migrator.
|
|
*
|
|
* It exists mostly to allow the creation of
|
|
* convenience methods to access and persist
|
|
* particular portions of the state.
|
|
*/
|
|
module.exports = ConfigManager
|
|
function ConfigManager (opts) {
|
|
this.txLimit = txLimit
|
|
|
|
// ConfigManager is observable and will emit updates
|
|
this._subs = []
|
|
|
|
/* The migrator exported on the config-manager
|
|
* has two methods the user should be concerned with:
|
|
*
|
|
* getData(), which returns the app-consumable data object
|
|
* saveData(), which persists the app-consumable data object.
|
|
*/
|
|
this.migrator = new Migrator({
|
|
|
|
// Migrations must start at version 1 or later.
|
|
// They are objects with a `version` number
|
|
// and a `migrate` function.
|
|
//
|
|
// The `migrate` function receives the previous
|
|
// config data format, and returns the new one.
|
|
migrations: migrations,
|
|
|
|
// How to load initial config.
|
|
// Includes step on migrating pre-pojo-migrator data.
|
|
loadData: opts.loadData,
|
|
|
|
// How to persist migrated config.
|
|
setData: opts.setData,
|
|
})
|
|
}
|
|
|
|
ConfigManager.prototype.setConfig = function (config) {
|
|
var data = this.migrator.getData()
|
|
data.config = config
|
|
this.setData(data)
|
|
this._emitUpdates(config)
|
|
}
|
|
|
|
ConfigManager.prototype.getConfig = function () {
|
|
var data = this.migrator.getData()
|
|
if ('config' in data) {
|
|
return data.config
|
|
} else {
|
|
return {
|
|
provider: {
|
|
type: 'testnet',
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
ConfigManager.prototype.setRpcTarget = function (rpcUrl) {
|
|
var config = this.getConfig()
|
|
config.provider = {
|
|
type: 'rpc',
|
|
rpcTarget: rpcUrl,
|
|
}
|
|
this.setConfig(config)
|
|
}
|
|
|
|
ConfigManager.prototype.setProviderType = function (type) {
|
|
var config = this.getConfig()
|
|
config.provider = {
|
|
type: type,
|
|
}
|
|
this.setConfig(config)
|
|
}
|
|
|
|
ConfigManager.prototype.useEtherscanProvider = function () {
|
|
var config = this.getConfig()
|
|
config.provider = {
|
|
type: 'etherscan',
|
|
}
|
|
this.setConfig(config)
|
|
}
|
|
|
|
ConfigManager.prototype.getProvider = function () {
|
|
var config = this.getConfig()
|
|
return config.provider
|
|
}
|
|
|
|
ConfigManager.prototype.setData = function (data) {
|
|
this.migrator.saveData(data)
|
|
}
|
|
|
|
ConfigManager.prototype.getData = function () {
|
|
return this.migrator.getData()
|
|
}
|
|
|
|
ConfigManager.prototype.setWallet = function (wallet) {
|
|
var data = this.migrator.getData()
|
|
data.wallet = wallet
|
|
this.setData(data)
|
|
}
|
|
|
|
ConfigManager.prototype.getSelectedAccount = function () {
|
|
var config = this.getConfig()
|
|
return config.selectedAccount
|
|
}
|
|
|
|
ConfigManager.prototype.setSelectedAccount = function (address) {
|
|
var config = this.getConfig()
|
|
config.selectedAccount = address
|
|
this.setConfig(config)
|
|
}
|
|
|
|
ConfigManager.prototype.getWallet = function () {
|
|
return this.migrator.getData().wallet
|
|
}
|
|
|
|
// Takes a boolean
|
|
ConfigManager.prototype.setShowSeedWords = function (should) {
|
|
var data = this.migrator.getData()
|
|
data.showSeedWords = should
|
|
this.setData(data)
|
|
}
|
|
|
|
ConfigManager.prototype.getShouldShowSeedWords = function () {
|
|
var data = this.migrator.getData()
|
|
return data.showSeedWords
|
|
}
|
|
|
|
ConfigManager.prototype.getCurrentRpcAddress = function () {
|
|
var provider = this.getProvider()
|
|
if (!provider) return null
|
|
switch (provider.type) {
|
|
|
|
case 'mainnet':
|
|
return MAINNET_RPC
|
|
|
|
case 'testnet':
|
|
return TESTNET_RPC
|
|
|
|
case 'morden':
|
|
return MORDEN_RPC
|
|
|
|
default:
|
|
return provider && provider.rpcTarget ? provider.rpcTarget : TESTNET_RPC
|
|
}
|
|
}
|
|
|
|
ConfigManager.prototype.setData = function (data) {
|
|
this.migrator.saveData(data)
|
|
}
|
|
|
|
//
|
|
// Notices
|
|
//
|
|
|
|
ConfigManager.prototype.getNoticesList = function () {
|
|
var data = this.getData()
|
|
if ('noticesList' in data) {
|
|
return data.noticesList
|
|
} else {
|
|
return []
|
|
}
|
|
}
|
|
|
|
ConfigManager.prototype.setNoticesList = function (list) {
|
|
var data = this.getData()
|
|
data.noticesList = list
|
|
this.setData(data)
|
|
return Promise.resolve(true)
|
|
}
|
|
|
|
ConfigManager.prototype.markNoticeRead = function (notice) {
|
|
var notices = this.getNoticesList()
|
|
var id = notice.id
|
|
notices[id].read = true
|
|
this.setNoticesList(notices)
|
|
}
|
|
|
|
ConfigManager.prototype.updateNoticesList = function () {
|
|
return this._retrieveNoticeData().then((newNotices) => {
|
|
var oldNotices = this.getNoticesList()
|
|
var combinedNotices = this._mergeNotices(oldNotices, newNotices)
|
|
return Promise.resolve(this.setNoticesList(combinedNotices))
|
|
})
|
|
}
|
|
|
|
ConfigManager.prototype.getLatestUnreadNotice = function () {
|
|
var notices = this.getNoticesList()
|
|
var filteredNotices = notices.filter((notice) => {
|
|
return notice.read === false
|
|
})
|
|
return filteredNotices[filteredNotices.length - 1]
|
|
}
|
|
|
|
ConfigManager.prototype._mergeNotices = function (oldNotices, newNotices) {
|
|
var noticeMap = this._mapNoticeIds(oldNotices)
|
|
newNotices.forEach((notice) => {
|
|
if (noticeMap.indexOf(notice.id) === -1) {
|
|
oldNotices.push(notice)
|
|
}
|
|
})
|
|
return oldNotices
|
|
}
|
|
|
|
ConfigManager.prototype._mapNoticeIds = function (notices) {
|
|
return notices.map((notice) => notice.id)
|
|
}
|
|
|
|
ConfigManager.prototype._retrieveNoticeData = function () {
|
|
// Placeholder for the API.
|
|
return Promise.resolve(notices)
|
|
}
|
|
|
|
|
|
//
|
|
// Tx
|
|
//
|
|
|
|
ConfigManager.prototype.getTxList = function () {
|
|
var data = this.migrator.getData()
|
|
if (data.transactions !== undefined) {
|
|
return data.transactions
|
|
} else {
|
|
return []
|
|
}
|
|
}
|
|
|
|
ConfigManager.prototype.unconfirmedTxs = function () {
|
|
var transactions = this.getTxList()
|
|
return transactions.filter(tx => tx.status === 'unconfirmed')
|
|
.reduce((result, tx) => { result[tx.id] = tx; return result }, {})
|
|
}
|
|
|
|
ConfigManager.prototype._saveTxList = function (txList) {
|
|
var data = this.migrator.getData()
|
|
data.transactions = txList
|
|
this.setData(data)
|
|
}
|
|
|
|
ConfigManager.prototype.addTx = function (tx) {
|
|
var transactions = this.getTxList()
|
|
while (transactions.length > this.txLimit - 1) {
|
|
transactions.shift()
|
|
}
|
|
transactions.push(tx)
|
|
this._saveTxList(transactions)
|
|
}
|
|
|
|
ConfigManager.prototype.getTx = function (txId) {
|
|
var transactions = this.getTxList()
|
|
var matching = transactions.filter(tx => tx.id === txId)
|
|
return matching.length > 0 ? matching[0] : null
|
|
}
|
|
|
|
ConfigManager.prototype.confirmTx = function (txId) {
|
|
this._setTxStatus(txId, 'confirmed')
|
|
}
|
|
|
|
ConfigManager.prototype.rejectTx = function (txId) {
|
|
this._setTxStatus(txId, 'rejected')
|
|
}
|
|
|
|
ConfigManager.prototype._setTxStatus = function (txId, status) {
|
|
var tx = this.getTx(txId)
|
|
tx.status = status
|
|
this.updateTx(tx)
|
|
}
|
|
|
|
ConfigManager.prototype.updateTx = function (tx) {
|
|
var transactions = this.getTxList()
|
|
var found, index
|
|
transactions.forEach((otherTx, i) => {
|
|
if (otherTx.id === tx.id) {
|
|
found = true
|
|
index = i
|
|
}
|
|
})
|
|
if (found) {
|
|
transactions[index] = tx
|
|
}
|
|
this._saveTxList(transactions)
|
|
}
|
|
|
|
// wallet nickname methods
|
|
|
|
ConfigManager.prototype.getWalletNicknames = function () {
|
|
var data = this.getData()
|
|
const nicknames = ('walletNicknames' in data) ? data.walletNicknames : {}
|
|
return nicknames
|
|
}
|
|
|
|
ConfigManager.prototype.nicknameForWallet = function (account) {
|
|
const nicknames = this.getWalletNicknames()
|
|
return nicknames[account]
|
|
}
|
|
|
|
ConfigManager.prototype.setNicknameForWallet = function (account, nickname) {
|
|
const nicknames = this.getWalletNicknames()
|
|
nicknames[account] = nickname
|
|
var data = this.getData()
|
|
data.walletNicknames = nicknames
|
|
this.setData(data)
|
|
}
|
|
|
|
// observable
|
|
|
|
ConfigManager.prototype.subscribe = function (fn) {
|
|
this._subs.push(fn)
|
|
var unsubscribe = this.unsubscribe.bind(this, fn)
|
|
return unsubscribe
|
|
}
|
|
|
|
ConfigManager.prototype.unsubscribe = function (fn) {
|
|
var index = this._subs.indexOf(fn)
|
|
if (index !== -1) this._subs.splice(index, 1)
|
|
}
|
|
|
|
ConfigManager.prototype._emitUpdates = function (state) {
|
|
this._subs.forEach(function (handler) {
|
|
handler(state)
|
|
})
|
|
}
|
|
|
|
ConfigManager.prototype.setConfirmed = function (confirmed) {
|
|
var data = this.getData()
|
|
data.isConfirmed = confirmed
|
|
this.setData(data)
|
|
}
|
|
|
|
ConfigManager.prototype.getConfirmed = function () {
|
|
var data = this.getData()
|
|
return ('isConfirmed' in data) && data.isConfirmed
|
|
}
|
|
|
|
ConfigManager.prototype.setTOSHash = function (hash) {
|
|
var data = this.getData()
|
|
data.TOSHash = hash
|
|
this.setData(data)
|
|
}
|
|
|
|
ConfigManager.prototype.getTOSHash = function () {
|
|
var data = this.getData()
|
|
return ('TOSHash' in data) && data.TOSHash
|
|
}
|
|
|
|
ConfigManager.prototype.setCurrentFiat = function (currency) {
|
|
var data = this.getData()
|
|
data.fiatCurrency = currency
|
|
this.setData(data)
|
|
}
|
|
|
|
ConfigManager.prototype.getCurrentFiat = function () {
|
|
var data = this.getData()
|
|
return ('fiatCurrency' in data) && data.fiatCurrency
|
|
}
|
|
|
|
ConfigManager.prototype.updateConversionRate = function () {
|
|
var data = this.getData()
|
|
return rp(`https://www.cryptonator.com/api/ticker/eth-${data.fiatCurrency}`)
|
|
.then((response) => {
|
|
const parsedResponse = JSON.parse(response)
|
|
this.setConversionPrice(parsedResponse.ticker.price)
|
|
this.setConversionDate(parsedResponse.timestamp)
|
|
}).catch((err) => {
|
|
console.error('Error in conversion.', err)
|
|
this.setConversionPrice(0)
|
|
this.setConversionDate('N/A')
|
|
})
|
|
|
|
}
|
|
|
|
ConfigManager.prototype.setConversionPrice = function (price) {
|
|
var data = this.getData()
|
|
data.conversionRate = Number(price)
|
|
this.setData(data)
|
|
}
|
|
|
|
ConfigManager.prototype.setConversionDate = function (datestring) {
|
|
var data = this.getData()
|
|
data.conversionDate = datestring
|
|
this.setData(data)
|
|
}
|
|
|
|
ConfigManager.prototype.getConversionRate = function () {
|
|
var data = this.getData()
|
|
return (('conversionRate' in data) && data.conversionRate) || 0
|
|
}
|
|
|
|
ConfigManager.prototype.getConversionDate = function () {
|
|
var data = this.getData()
|
|
return (('conversionDate' in data) && data.conversionDate) || 'N/A'
|
|
}
|
|
|
|
ConfigManager.prototype.setShouldntShowWarning = function () {
|
|
var data = this.getData()
|
|
if (data.isEthConfirmed) {
|
|
data.isEthConfirmed = !data.isEthConfirmed
|
|
} else {
|
|
data.isEthConfirmed = true
|
|
}
|
|
this.setData(data)
|
|
}
|
|
|
|
ConfigManager.prototype.getShouldntShowWarning = function () {
|
|
var data = this.getData()
|
|
return ('isEthConfirmed' in data) && data.isEthConfirmed
|
|
}
|
|
|
|
ConfigManager.prototype.getShapeShiftTxList = function () {
|
|
var data = this.getData()
|
|
var shapeShiftTxList = data.shapeShiftTxList ? data.shapeShiftTxList : []
|
|
shapeShiftTxList.forEach((tx) => {
|
|
if (tx.response.status !== 'complete') {
|
|
var requestListner = function (request) {
|
|
tx.response = JSON.parse(this.responseText)
|
|
if (tx.response.status === 'complete') {
|
|
tx.time = new Date().getTime()
|
|
}
|
|
}
|
|
|
|
var shapShiftReq = new XMLHttpRequest()
|
|
shapShiftReq.addEventListener('load', requestListner)
|
|
shapShiftReq.open('GET', `https://shapeshift.io/txStat/${tx.depositAddress}`, true)
|
|
shapShiftReq.send()
|
|
}
|
|
})
|
|
this.setData(data)
|
|
return shapeShiftTxList
|
|
}
|
|
|
|
ConfigManager.prototype.createShapeShiftTx = function (depositAddress, depositType) {
|
|
var data = this.getData()
|
|
|
|
var shapeShiftTx = {depositAddress, depositType, key: 'shapeshift', time: new Date().getTime(), response: {}}
|
|
if (!data.shapeShiftTxList) {
|
|
data.shapeShiftTxList = [shapeShiftTx]
|
|
} else {
|
|
data.shapeShiftTxList.push(shapeShiftTx)
|
|
}
|
|
this.setData(data)
|
|
}
|
|
|
|
ConfigManager.prototype.getGasMultiplier = function () {
|
|
var data = this.getData()
|
|
return ('gasMultiplier' in data) && data.gasMultiplier
|
|
}
|
|
|
|
ConfigManager.prototype.setGasMultiplier = function (gasMultiplier) {
|
|
var data = this.getData()
|
|
|
|
data.gasMultiplier = gasMultiplier
|
|
this.setData(data)
|
|
}
|