aboutsummaryrefslogtreecommitdiffstats
path: root/app/scripts/lib
diff options
context:
space:
mode:
Diffstat (limited to 'app/scripts/lib')
-rw-r--r--app/scripts/lib/buy-eth-url.js11
-rw-r--r--app/scripts/lib/config-manager.js22
-rw-r--r--app/scripts/lib/createLoggerMiddleware.js14
-rw-r--r--app/scripts/lib/createOriginMiddleware.js12
-rw-r--r--app/scripts/lib/events-proxy.js25
-rw-r--r--app/scripts/lib/get-first-preferred-lang-code.js7
-rw-r--r--app/scripts/lib/hex-to-bn.js7
-rw-r--r--app/scripts/lib/local-store.js37
-rw-r--r--app/scripts/lib/migrator/index.js35
-rw-r--r--app/scripts/lib/nodeify.js8
-rw-r--r--app/scripts/lib/stream-utils.js18
-rw-r--r--app/scripts/lib/util.js49
12 files changed, 216 insertions, 29 deletions
diff --git a/app/scripts/lib/buy-eth-url.js b/app/scripts/lib/buy-eth-url.js
index b9dde3c28..4e2d0bc79 100644
--- a/app/scripts/lib/buy-eth-url.js
+++ b/app/scripts/lib/buy-eth-url.js
@@ -1,5 +1,16 @@
module.exports = getBuyEthUrl
+/**
+ * Gives the caller a url at which the user can acquire eth, depending on the network they are in
+ *
+ * @param {object} opts Options required to determine the correct url
+ * @param {string} opts.network The network for which to return a url
+ * @param {string} opts.amount The amount of ETH to buy on coinbase. Only relevant if network === '1'.
+ * @param {string} opts.address The address the bought ETH should be sent to. Only relevant if network === '1'.
+ * @returns {string|undefined} The url at which the user can access ETH, while in the given network. If the passed
+ * network does not match any of the specified cases, or if no network is given, returns undefined.
+ *
+ */
function getBuyEthUrl ({ network, amount, address }) {
let url
switch (network) {
diff --git a/app/scripts/lib/config-manager.js b/app/scripts/lib/config-manager.js
index 34b603b96..63d27c40e 100644
--- a/app/scripts/lib/config-manager.js
+++ b/app/scripts/lib/config-manager.js
@@ -102,7 +102,6 @@ ConfigManager.prototype.setShowSeedWords = function (should) {
this.setData(data)
}
-
ConfigManager.prototype.getShouldShowSeedWords = function () {
var data = this.getData()
return data.showSeedWords
@@ -118,6 +117,27 @@ ConfigManager.prototype.getSeedWords = function () {
var data = this.getData()
return data.seedWords
}
+
+/**
+ * Called to set the isRevealingSeedWords flag. This happens only when the user chooses to reveal
+ * the seed words and not during the first time flow.
+ * @param {boolean} reveal - Value to set the isRevealingSeedWords flag.
+ */
+ConfigManager.prototype.setIsRevealingSeedWords = function (reveal = false) {
+ const data = this.getData()
+ data.isRevealingSeedWords = reveal
+ this.setData(data)
+}
+
+/**
+ * Returns the isRevealingSeedWords flag.
+ * @returns {boolean|undefined}
+ */
+ConfigManager.prototype.getIsRevealingSeedWords = function () {
+ const data = this.getData()
+ return data.isRevealingSeedWords
+}
+
ConfigManager.prototype.setRpcTarget = function (rpcUrl) {
var config = this.getConfig()
config.provider = {
diff --git a/app/scripts/lib/createLoggerMiddleware.js b/app/scripts/lib/createLoggerMiddleware.js
index fc6abf828..996c3477c 100644
--- a/app/scripts/lib/createLoggerMiddleware.js
+++ b/app/scripts/lib/createLoggerMiddleware.js
@@ -1,16 +1,20 @@
const log = require('loglevel')
-// log rpc activity
module.exports = createLoggerMiddleware
-function createLoggerMiddleware ({ origin }) {
- return function loggerMiddleware (req, res, next, end) {
- next((cb) => {
+/**
+ * Returns a middleware that logs RPC activity
+ * @param {{ origin: string }} opts - The middleware options
+ * @returns {Function}
+ */
+function createLoggerMiddleware (opts) {
+ return function loggerMiddleware (/** @type {any} */ req, /** @type {any} */ res, /** @type {Function} */ next) {
+ next((/** @type {Function} */ cb) => {
if (res.error) {
log.error('Error in RPC response:\n', res)
}
if (req.isMetamaskInternal) return
- log.info(`RPC (${origin}):`, req, '->', res)
+ log.info(`RPC (${opts.origin}):`, req, '->', res)
cb()
})
}
diff --git a/app/scripts/lib/createOriginMiddleware.js b/app/scripts/lib/createOriginMiddleware.js
index f8bdb2dc2..98bb0e3b3 100644
--- a/app/scripts/lib/createOriginMiddleware.js
+++ b/app/scripts/lib/createOriginMiddleware.js
@@ -1,9 +1,13 @@
-// append dapp origin domain to request
module.exports = createOriginMiddleware
-function createOriginMiddleware ({ origin }) {
- return function originMiddleware (req, res, next, end) {
- req.origin = origin
+/**
+ * Returns a middleware that appends the DApp origin to request
+ * @param {{ origin: string }} opts - The middleware options
+ * @returns {Function}
+ */
+function createOriginMiddleware (opts) {
+ return function originMiddleware (/** @type {any} */ req, /** @type {any} */ _, /** @type {Function} */ next) {
+ req.origin = opts.origin
next()
}
}
diff --git a/app/scripts/lib/events-proxy.js b/app/scripts/lib/events-proxy.js
index c0a490b05..f83773ccc 100644
--- a/app/scripts/lib/events-proxy.js
+++ b/app/scripts/lib/events-proxy.js
@@ -1,26 +1,37 @@
+/**
+ * Returns an EventEmitter that proxies events from the given event emitter
+ * @param {any} eventEmitter
+ * @param {object} listeners - The listeners to proxy to
+ * @returns {any}
+ */
module.exports = function createEventEmitterProxy (eventEmitter, listeners) {
let target = eventEmitter
const eventHandlers = listeners || {}
- const proxy = new Proxy({}, {
- get: (obj, name) => {
+ const proxy = /** @type {any} */ (new Proxy({}, {
+ get: (_, name) => {
// intercept listeners
if (name === 'on') return addListener
if (name === 'setTarget') return setTarget
if (name === 'proxyEventHandlers') return eventHandlers
- return target[name]
+ return (/** @type {any} */ (target))[name]
},
- set: (obj, name, value) => {
+ set: (_, name, value) => {
target[name] = value
return true
},
- })
- function setTarget (eventEmitter) {
+ }))
+ function setTarget (/** @type {EventEmitter} */ eventEmitter) {
target = eventEmitter
// migrate listeners
Object.keys(eventHandlers).forEach((name) => {
- eventHandlers[name].forEach((handler) => target.on(name, handler))
+ /** @type {Array<Function>} */ (eventHandlers[name]).forEach((handler) => target.on(name, handler))
})
}
+ /**
+ * Attaches a function to be called whenever the specified event is emitted
+ * @param {string} name
+ * @param {Function} handler
+ */
function addListener (name, handler) {
if (!eventHandlers[name]) eventHandlers[name] = []
eventHandlers[name].push(handler)
diff --git a/app/scripts/lib/get-first-preferred-lang-code.js b/app/scripts/lib/get-first-preferred-lang-code.js
index e3635434e..5473fccf0 100644
--- a/app/scripts/lib/get-first-preferred-lang-code.js
+++ b/app/scripts/lib/get-first-preferred-lang-code.js
@@ -4,6 +4,13 @@ const allLocales = require('../../_locales/index.json')
const existingLocaleCodes = allLocales.map(locale => locale.code.toLowerCase().replace('_', '-'))
+/**
+ * Returns a preferred language code, based on settings within the user's browser. If we have no translations for the
+ * users preferred locales, 'en' is returned.
+ *
+ * @returns {Promise<string>} Promises a locale code, either one from the user's preferred list that we have a translation for, or 'en'
+ *
+ */
async function getFirstPreferredLangCode () {
const userPreferredLocaleCodes = await promisify(
extension.i18n.getAcceptLanguages,
diff --git a/app/scripts/lib/hex-to-bn.js b/app/scripts/lib/hex-to-bn.js
index 184217279..b28746920 100644
--- a/app/scripts/lib/hex-to-bn.js
+++ b/app/scripts/lib/hex-to-bn.js
@@ -1,6 +1,11 @@
-const ethUtil = require('ethereumjs-util')
+const ethUtil = (/** @type {object} */ (require('ethereumjs-util')))
const BN = ethUtil.BN
+/**
+ * Returns a [BinaryNumber]{@link BN} representation of the given hex value
+ * @param {string} hex
+ * @return {any}
+ */
module.exports = function hexToBn (hex) {
return new BN(ethUtil.stripHexPrefix(hex), 16)
}
diff --git a/app/scripts/lib/local-store.js b/app/scripts/lib/local-store.js
index 2dda0ba1f..139ff86bd 100644
--- a/app/scripts/lib/local-store.js
+++ b/app/scripts/lib/local-store.js
@@ -1,11 +1,13 @@
-// We should not rely on local storage in an extension!
-// We should use this instead!
-// https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/storage/local
-
const extension = require('extensionizer')
const log = require('loglevel')
+/**
+ * A wrapper around the extension's storage local API
+ */
module.exports = class ExtensionStore {
+ /**
+ * @constructor
+ */
constructor() {
this.isSupported = !!(extension.storage.local)
if (!this.isSupported) {
@@ -13,6 +15,10 @@ module.exports = class ExtensionStore {
}
}
+ /**
+ * Returns all of the keys currently saved
+ * @return {Promise<*>}
+ */
async get() {
if (!this.isSupported) return undefined
const result = await this._get()
@@ -25,14 +31,24 @@ module.exports = class ExtensionStore {
}
}
+ /**
+ * Sets the key in local state
+ * @param {object} state - The state to set
+ * @return {Promise<void>}
+ */
async set(state) {
return this._set(state)
}
+ /**
+ * Returns all of the keys currently saved
+ * @private
+ * @return {object} the key-value map from local storage
+ */
_get() {
const local = extension.storage.local
return new Promise((resolve, reject) => {
- local.get(null, (result) => {
+ local.get(null, (/** @type {any} */ result) => {
const err = extension.runtime.lastError
if (err) {
reject(err)
@@ -43,6 +59,12 @@ module.exports = class ExtensionStore {
})
}
+ /**
+ * Sets the key in local state
+ * @param {object} obj - The key to set
+ * @return {Promise<void>}
+ * @private
+ */
_set(obj) {
const local = extension.storage.local
return new Promise((resolve, reject) => {
@@ -58,6 +80,11 @@ module.exports = class ExtensionStore {
}
}
+/**
+ * Returns whether or not the given object contains no keys
+ * @param {object} obj - The object to check
+ * @returns {boolean}
+ */
function isEmpty(obj) {
return Object.keys(obj).length === 0
}
diff --git a/app/scripts/lib/migrator/index.js b/app/scripts/lib/migrator/index.js
index 85c2717ea..345ca8001 100644
--- a/app/scripts/lib/migrator/index.js
+++ b/app/scripts/lib/migrator/index.js
@@ -1,7 +1,23 @@
const EventEmitter = require('events')
+/**
+ * @typedef {object} Migration
+ * @property {number} version - The migration version
+ * @property {Function} migrate - Returns a promise of the migrated data
+ */
+
+/**
+ * @typedef {object} MigratorOptions
+ * @property {Array<Migration>} [migrations] - The list of migrations to apply
+ * @property {number} [defaultVersion] - The version to use in the initial state
+ */
+
class Migrator extends EventEmitter {
+ /**
+ * @constructor
+ * @param {MigratorOptions} opts
+ */
constructor (opts = {}) {
super()
const migrations = opts.migrations || []
@@ -42,19 +58,30 @@ class Migrator extends EventEmitter {
return versionedData
- // migration is "pending" if it has a higher
- // version number than currentVersion
+ /**
+ * Returns whether or not the migration is pending
+ *
+ * A migration is considered "pending" if it has a higher
+ * version number than the current version.
+ * @param {Migration} migration
+ * @returns {boolean}
+ */
function migrationIsPending (migration) {
return migration.version > versionedData.meta.version
}
}
- generateInitialState (initState) {
+ /**
+ * Returns the initial state for the migrator
+ * @param {object} [data] - The data for the initial state
+ * @returns {{meta: {version: number}, data: any}}
+ */
+ generateInitialState (data) {
return {
meta: {
version: this.defaultVersion,
},
- data: initState,
+ data,
}
}
diff --git a/app/scripts/lib/nodeify.js b/app/scripts/lib/nodeify.js
index 9b595d93c..25be6537b 100644
--- a/app/scripts/lib/nodeify.js
+++ b/app/scripts/lib/nodeify.js
@@ -1,6 +1,14 @@
const promiseToCallback = require('promise-to-callback')
const noop = function () {}
+/**
+ * A generator that returns a function which, when passed a promise, can treat that promise as a node style callback.
+ * The prime advantage being that callbacks are better for error handling.
+ *
+ * @param {Function} fn The function to handle as a callback
+ * @param {Object} context The context in which the fn is to be called, most often a this reference
+ *
+ */
module.exports = function nodeify (fn, context) {
return function () {
const args = [].slice.call(arguments)
diff --git a/app/scripts/lib/stream-utils.js b/app/scripts/lib/stream-utils.js
index 8bb0b4f3c..3dbc064b5 100644
--- a/app/scripts/lib/stream-utils.js
+++ b/app/scripts/lib/stream-utils.js
@@ -8,20 +8,34 @@ module.exports = {
setupMultiplex: setupMultiplex,
}
+/**
+ * Returns a stream transform that parses JSON strings passing through
+ * @return {stream.Transform}
+ */
function jsonParseStream () {
- return Through.obj(function (serialized, encoding, cb) {
+ return Through.obj(function (serialized, _, cb) {
this.push(JSON.parse(serialized))
cb()
})
}
+/**
+ * Returns a stream transform that calls {@code JSON.stringify}
+ * on objects passing through
+ * @return {stream.Transform} the stream transform
+ */
function jsonStringifyStream () {
- return Through.obj(function (obj, encoding, cb) {
+ return Through.obj(function (obj, _, cb) {
this.push(JSON.stringify(obj))
cb()
})
}
+/**
+ * Sets up stream multiplexing for the given stream
+ * @param {any} connectionStream - the stream to mux
+ * @return {stream.Stream} the multiplexed stream
+ */
function setupMultiplex (connectionStream) {
const mux = new ObjectMultiplex()
pump(
diff --git a/app/scripts/lib/util.js b/app/scripts/lib/util.js
index df815906f..431d1e59c 100644
--- a/app/scripts/lib/util.js
+++ b/app/scripts/lib/util.js
@@ -7,11 +7,26 @@ const {
ENVIRONMENT_TYPE_FULLSCREEN,
} = require('./enums')
+/**
+ * Generates an example stack trace
+ *
+ * @returns {string} A stack trace
+ *
+ */
function getStack () {
const stack = new Error('Stack trace generator - not an error').stack
return stack
}
+/**
+ * Used to determine the window type through which the app is being viewed.
+ * - 'popup' refers to the extension opened through the browser app icon (in top right corner in chrome and firefox)
+ * - 'responsive' refers to the main browser window
+ * - 'notification' refers to the popup that appears in its own window when taking action outside of metamask
+ *
+ * @returns {string} A single word label that represents the type of window through which the app is being viewed
+ *
+ */
const getEnvironmentType = (url = window.location.href) => {
if (url.match(/popup.html(?:\?.+)*$/)) {
return ENVIRONMENT_TYPE_POPUP
@@ -22,6 +37,17 @@ const getEnvironmentType = (url = window.location.href) => {
}
}
+/**
+ * Checks whether a given balance of ETH, represented as a hex string, is sufficient to pay a value plus a gas fee
+ *
+ * @param {object} txParams Contains data about a transaction
+ * @param {string} txParams.gas The gas for a transaction
+ * @param {string} txParams.gasPrice The price per gas for the transaction
+ * @param {string} txParams.value The value of ETH to send
+ * @param {string} hexBalance A balance of ETH represented as a hex string
+ * @returns {boolean} Whether the balance is greater than or equal to the value plus the value of gas times gasPrice
+ *
+ */
function sufficientBalance (txParams, hexBalance) {
// validate hexBalance is a hex string
assert.equal(typeof hexBalance, 'string', 'sufficientBalance - hexBalance is not a hex string')
@@ -36,14 +62,37 @@ function sufficientBalance (txParams, hexBalance) {
return balance.gte(maxCost)
}
+/**
+ * Converts a BN object to a hex string with a '0x' prefix
+ *
+ * @param {BN} inputBn The BN to convert to a hex string
+ * @returns {string} A '0x' prefixed hex string
+ *
+ */
function bnToHex (inputBn) {
return ethUtil.addHexPrefix(inputBn.toString(16))
}
+/**
+ * Converts a hex string to a BN object
+ *
+ * @param {string} inputHex A number represented as a hex string
+ * @returns {Object} A BN object
+ *
+ */
function hexToBn (inputHex) {
return new BN(ethUtil.stripHexPrefix(inputHex), 16)
}
+/**
+ * Used to multiply a BN by a fraction
+ *
+ * @param {BN} targetBN The number to multiply by a fraction
+ * @param {number|string} numerator The numerator of the fraction multiplier
+ * @param {number|string} denominator The denominator of the fraction multiplier
+ * @returns {BN} The product of the multiplication
+ *
+ */
function BnMultiplyByFraction (targetBN, numerator, denominator) {
const numBN = new BN(numerator)
const denomBN = new BN(denominator)