From c9f83fe8bc60a87876242a2dfb5350fceafffca1 Mon Sep 17 00:00:00 2001 From: bitpshr Date: Wed, 18 Apr 2018 17:02:08 -0400 Subject: [PATCH 1/5] Add JSDoc to various background scripts --- app/scripts/config.js | 39 ++++++++- app/scripts/contentscript.js | 42 ++++++++++ app/scripts/edge-encryptor.js | 142 +++++++++++++++++++------------- app/scripts/first-time-state.js | 16 +++- app/scripts/inpage.js | 11 +-- app/scripts/popup-core.js | 25 +++++- 6 files changed, 205 insertions(+), 70 deletions(-) diff --git a/app/scripts/config.js b/app/scripts/config.js index a8470ed82..634d7a013 100644 --- a/app/scripts/config.js +++ b/app/scripts/config.js @@ -15,7 +15,41 @@ const BETA_UI_NETWORK_TYPE = 'networkBeta' global.METAMASK_DEBUG = process.env.METAMASK_DEBUG -module.exports = { +/** + * @typedef {Object} UrlConfig + * @property {string} localhost URL of local RPC provider + * @property {string} mainnet URL of mainnet RPC provider + * @property {string} ropsten URL of Ropsten testnet RPC provider + * @property {string} kovan URL of Kovan testnet RPC provider + * @property {string} rinkeby URL of Rinkeby testnet RPC provider + */ + +/** + * @typedef {Object} NameConfig + * @property {string} 3 URL of local RPC provider + * @property {string} 4 URL of mainnet RPC provider + * @property {string} 42 URL of Ropsten testnet RPC provider + */ + +/** + * @typedef {Object} EnumConfig + * @property {string} DEFAULT_RPC Default network provider URL + * @property {string} OLD_UI_NETWORK_TYPE + * @property {string} BETA_UI_NETWORK_TYPE + */ + +/** + * @typedef {Object} Config + * @property {UrlConfig} network Network configuration parameters + * @property {UrlConfig} networkBeta Beta UI network configuration parameters + * @property {NameConfig} networkNames Network name configuration parameters + * @property {EnumConfig} enums Application-wide string constants + */ + +/** + * @type {Config} Application configuration object + **/ +const config = { network: { localhost: LOCALHOST_RPC_URL, mainnet: MAINET_RPC_URL, @@ -23,7 +57,6 @@ module.exports = { kovan: KOVAN_RPC_URL, rinkeby: RINKEBY_RPC_URL, }, - // Used for beta UI networkBeta: { localhost: LOCALHOST_RPC_URL, mainnet: MAINET_RPC_URL_BETA, @@ -42,3 +75,5 @@ module.exports = { BETA_UI_NETWORK_TYPE, }, } + +module.exports = config \ No newline at end of file diff --git a/app/scripts/contentscript.js b/app/scripts/contentscript.js index fe1766273..728aab8cb 100644 --- a/app/scripts/contentscript.js +++ b/app/scripts/contentscript.js @@ -23,6 +23,9 @@ if (shouldInjectWeb3()) { setupStreams() } +/** + * Creates a script tag that injects inpage.js + */ function setupInjection () { try { // inject in-page script @@ -37,6 +40,10 @@ function setupInjection () { } } +/** + * Sets up two-way communication streams between the + * browser extension and local per-page browser context + */ function setupStreams () { // setup communication to page and plugin const pageStream = new LocalMessageDuplexStream({ @@ -89,17 +96,34 @@ function setupStreams () { mux.ignoreStream('publicConfig') } + +/** + * Error handler for page to plugin stream disconnections + * + * @param {string} remoteLabel Remote stream name + * @param {Error} err Stream connection error + */ function logStreamDisconnectWarning (remoteLabel, err) { let warningMsg = `MetamaskContentscript - lost connection to ${remoteLabel}` if (err) warningMsg += '\n' + err.stack console.warn(warningMsg) } +/** + * Determines if Web3 should be injected + * + * @returns {boolean} True of Web3 should be injected + */ function shouldInjectWeb3 () { return doctypeCheck() && suffixCheck() && documentElementCheck() && !blacklistedDomainCheck() } +/** + * Checks the doctype of the current document if it exists + * + * @returns {boolean} True if the doctype is html or if none exists + */ function doctypeCheck () { const doctype = window.document.doctype if (doctype) { @@ -109,6 +133,11 @@ function doctypeCheck () { } } +/** + * Checks the current document extension + * + * @returns {boolean} True if the current extension is not prohibited + */ function suffixCheck () { var prohibitedTypes = ['xml', 'pdf'] var currentUrl = window.location.href @@ -122,6 +151,11 @@ function suffixCheck () { return true } +/** + * Checks the documentElement of the current document + * + * @returns {boolean} True if the documentElement is an html node or if none exists + */ function documentElementCheck () { var documentElement = document.documentElement.nodeName if (documentElement) { @@ -130,6 +164,11 @@ function documentElementCheck () { return true } +/** + * Checks if the current domain is blacklisted + * + * @returns {boolean} True if the current domain is blacklisted + */ function blacklistedDomainCheck () { var blacklistedDomains = [ 'uscourts.gov', @@ -148,6 +187,9 @@ function blacklistedDomainCheck () { return false } +/** + * Redirects the current page to a phishing information page + */ function redirectToPhishingWarning () { console.log('MetaMask - redirecting to phishing warning') window.location.href = 'https://metamask.io/phishing.html' diff --git a/app/scripts/edge-encryptor.js b/app/scripts/edge-encryptor.js index 24c0c93a8..5f6699746 100644 --- a/app/scripts/edge-encryptor.js +++ b/app/scripts/edge-encryptor.js @@ -1,69 +1,97 @@ const asmcrypto = require('asmcrypto.js') const Unibabel = require('browserify-unibabel') +/** + * A Microsoft Edge-specific encryption class that exposes + * the interface expected by eth-keykeyring-controller + */ class EdgeEncryptor { + /** + * Encrypts an arbitrary JavaScript object to cypher text + * + * @param {string} password Password used to unlock a cryptographic key + * @param {Object} dataObject Data to encrypt + * @returns {Object} Object containing cypher text, generation vectors, and salt + */ + encrypt (password, dataObject) { + var salt = this._generateSalt() + return this._keyFromPassword(password, salt) + .then(function (key) { + var data = JSON.stringify(dataObject) + var dataBuffer = Unibabel.utf8ToBuffer(data) + var vector = global.crypto.getRandomValues(new Uint8Array(16)) + var resultbuffer = asmcrypto.AES_GCM.encrypt(dataBuffer, key, vector) - encrypt (password, dataObject) { + var buffer = new Uint8Array(resultbuffer) + var vectorStr = Unibabel.bufferToBase64(vector) + var vaultStr = Unibabel.bufferToBase64(buffer) + return JSON.stringify({ + data: vaultStr, + iv: vectorStr, + salt: salt, + }) + }) + } - var salt = this._generateSalt() - return this._keyFromPassword(password, salt) - .then(function (key) { + /** + * Decrypts an arbitrary JavaScript object from cypher text + * + * @param {string} password Password used to unlock a cryptographic key + * @param {string} text Cypher text of an encrypted JavaScript object + * @returns {Promise} Promise resolving to copy of decrypted JavaScript object + */ + decrypt (password, text) { + const payload = JSON.parse(text) + const salt = payload.salt + return this._keyFromPassword(password, salt) + .then(function (key) { + const encryptedData = Unibabel.base64ToBuffer(payload.data) + const vector = Unibabel.base64ToBuffer(payload.iv) + return new Promise((resolve, reject) => { + var result + try { + result = asmcrypto.AES_GCM.decrypt(encryptedData, key, vector) + } catch (err) { + return reject(new Error('Incorrect password')) + } + const decryptedData = new Uint8Array(result) + const decryptedStr = Unibabel.bufferToUtf8(decryptedData) + const decryptedObj = JSON.parse(decryptedStr) + resolve(decryptedObj) + }) + }) + } - var data = JSON.stringify(dataObject) - var dataBuffer = Unibabel.utf8ToBuffer(data) - var vector = global.crypto.getRandomValues(new Uint8Array(16)) - var resultbuffer = asmcrypto.AES_GCM.encrypt(dataBuffer, key, vector) + /** + * Retrieves a cryptographic key using a password + * + * @private + * @param {string} password Password used to unlock a cryptographic key + * @param {string} salt Random base-64 data + * @returns {Promise} Promise resolving to a derived key + */ + _keyFromPassword (password, salt) { - var buffer = new Uint8Array(resultbuffer) - var vectorStr = Unibabel.bufferToBase64(vector) - var vaultStr = Unibabel.bufferToBase64(buffer) - return JSON.stringify({ - data: vaultStr, - iv: vectorStr, - salt: salt, - }) - }) - } + var passBuffer = Unibabel.utf8ToBuffer(password) + var saltBuffer = Unibabel.base64ToBuffer(salt) + return new Promise((resolve) => { + var key = asmcrypto.PBKDF2_HMAC_SHA256.bytes(passBuffer, saltBuffer, 10000) + resolve(key) + }) + } - decrypt (password, text) { - - const payload = JSON.parse(text) - const salt = payload.salt - return this._keyFromPassword(password, salt) - .then(function (key) { - const encryptedData = Unibabel.base64ToBuffer(payload.data) - const vector = Unibabel.base64ToBuffer(payload.iv) - return new Promise((resolve, reject) => { - var result - try { - result = asmcrypto.AES_GCM.decrypt(encryptedData, key, vector) - } catch (err) { - return reject(new Error('Incorrect password')) - } - const decryptedData = new Uint8Array(result) - const decryptedStr = Unibabel.bufferToUtf8(decryptedData) - const decryptedObj = JSON.parse(decryptedStr) - resolve(decryptedObj) - }) - }) - } - - _keyFromPassword (password, salt) { - - var passBuffer = Unibabel.utf8ToBuffer(password) - var saltBuffer = Unibabel.base64ToBuffer(salt) - return new Promise((resolve) => { - var key = asmcrypto.PBKDF2_HMAC_SHA256.bytes(passBuffer, saltBuffer, 10000) - resolve(key) - }) - } - - _generateSalt (byteCount = 32) { - var view = new Uint8Array(byteCount) - global.crypto.getRandomValues(view) - var b64encoded = btoa(String.fromCharCode.apply(null, view)) - return b64encoded - } + /** + * Generates random base-64 encoded data + * + * @private + * @returns {string} Randomized base-64 encoded data + */ + _generateSalt (byteCount = 32) { + var view = new Uint8Array(byteCount) + global.crypto.getRandomValues(view) + var b64encoded = btoa(String.fromCharCode.apply(null, view)) + return b64encoded + } } module.exports = EdgeEncryptor diff --git a/app/scripts/first-time-state.js b/app/scripts/first-time-state.js index 3063df627..0c8f35303 100644 --- a/app/scripts/first-time-state.js +++ b/app/scripts/first-time-state.js @@ -2,10 +2,16 @@ const env = process.env.METAMASK_ENV const METAMASK_DEBUG = process.env.METAMASK_DEBUG -// -// The default state of MetaMask -// -module.exports = { +/** + * @typedef {Object} FirstTimeState + * @property {Object} config Initial configuration parameters + * @property {Object} NetworkController Network controller state + */ + +/** + * @type {FirstTimeState} The default state of MetaMask + */ +const initialState = { config: {}, NetworkController: { provider: { @@ -13,3 +19,5 @@ module.exports = { }, }, } + +module.exports = initialState diff --git a/app/scripts/inpage.js b/app/scripts/inpage.js index 92c732813..798af78bf 100644 --- a/app/scripts/inpage.js +++ b/app/scripts/inpage.js @@ -42,20 +42,18 @@ log.debug('MetaMask - injected web3') setupDappAutoReload(web3, inpageProvider.publicConfigStore) // set web3 defaultAccount - inpageProvider.publicConfigStore.subscribe(function (state) { web3.eth.defaultAccount = state.selectedAddress }) -// -// util -// - // need to make sure we aren't affected by overlapping namespaces // and that we dont affect the app with our namespace // mostly a fix for web3's BigNumber if AMD's "define" is defined... var __define +/** + * Caches reference to global define object and deletes it + */ function cleanContextForImports () { __define = global.define try { @@ -65,6 +63,9 @@ function cleanContextForImports () { } } +/** + * Restores global define object from cached reference + */ function restoreContextAfterImports () { try { global.define = __define diff --git a/app/scripts/popup-core.js b/app/scripts/popup-core.js index 2e4334bb1..5a5fa95f9 100644 --- a/app/scripts/popup-core.js +++ b/app/scripts/popup-core.js @@ -7,10 +7,14 @@ const launchMetamaskUi = require('../../ui') const StreamProvider = require('web3-stream-provider') const setupMultiplex = require('./lib/stream-utils.js').setupMultiplex - module.exports = initializePopup - +/** + * Asynchronously initializes the MetaMask popup UI + * + * @param {{ container: Element, connectionStream: any }} config Popup configuration object + * @param {Function} cb Called when initialization is comlete + */ function initializePopup ({ container, connectionStream }, cb) { // setup app async.waterfall([ @@ -19,6 +23,12 @@ function initializePopup ({ container, connectionStream }, cb) { ], cb) } +/** + * Establishes streamed connections to background scripts and a Web3 provider + * + * @param {any} connectionStream PortStream instance establishing a background connection + * @param {Function} cb Called when controller connection is established + */ function connectToAccountManager (connectionStream, cb) { // setup communication with background // setup multiplexing @@ -28,6 +38,11 @@ function connectToAccountManager (connectionStream, cb) { setupWeb3Connection(mx.createStream('provider')) } +/** + * Establishes a streamed connection to a Web3 provider + * + * @param {any} connectionStream PortStream instance establishing a background connection + */ function setupWeb3Connection (connectionStream) { var providerStream = new StreamProvider() providerStream.pipe(connectionStream).pipe(providerStream) @@ -38,6 +53,12 @@ function setupWeb3Connection (connectionStream) { global.eth = new Eth(providerStream) } +/** + * Establishes a streamed connection to the background account manager + * + * @param {any} connectionStream PortStream instance establishing a background connection + * @param {Function} cb Called when the remote account manager connection is established + */ function setupControllerConnection (connectionStream, cb) { // this is a really sneaky way of adding EventEmitter api // to a bi-directional dnode instance From 6dbdc87713a652dec4c90fa792dda08d613d4198 Mon Sep 17 00:00:00 2001 From: bitpshr Date: Wed, 18 Apr 2018 17:24:36 -0400 Subject: [PATCH 2/5] Add generated docs --- app/scripts/config.js | 4 +- app/scripts/controllers/token-rates.js | 6 +- app/scripts/first-time-state.js | 2 +- docs/jsdocs/ComposableObservableStore.html | 541 ++++ docs/jsdocs/EdgeEncryptor.html | 545 ++++ docs/jsdocs/TokenRatesController.html | 682 +++++ docs/jsdocs/config.js.html | 148 + docs/jsdocs/contentscript.js.html | 265 ++ docs/jsdocs/controllers_token-rates.js.html | 146 + docs/jsdocs/edge-encryptor.js.html | 166 ++ docs/jsdocs/first-time-state.js.html | 92 + docs/jsdocs/global.html | 2547 ++++++++++++++++- docs/jsdocs/index.html | 104 +- docs/jsdocs/inpage.js.html | 144 + .../lib_ComposableObservableStore.js.html | 118 + docs/jsdocs/metamask-controller.js.html | 142 +- .../jsdocs/module.exports_module.exports.html | 6 +- docs/jsdocs/popup-core.js.html | 146 + 18 files changed, 5531 insertions(+), 273 deletions(-) create mode 100644 docs/jsdocs/ComposableObservableStore.html create mode 100644 docs/jsdocs/EdgeEncryptor.html create mode 100644 docs/jsdocs/TokenRatesController.html create mode 100644 docs/jsdocs/config.js.html create mode 100644 docs/jsdocs/contentscript.js.html create mode 100644 docs/jsdocs/controllers_token-rates.js.html create mode 100644 docs/jsdocs/edge-encryptor.js.html create mode 100644 docs/jsdocs/first-time-state.js.html create mode 100644 docs/jsdocs/inpage.js.html create mode 100644 docs/jsdocs/lib_ComposableObservableStore.js.html create mode 100644 docs/jsdocs/popup-core.js.html diff --git a/app/scripts/config.js b/app/scripts/config.js index 634d7a013..21905d5b4 100644 --- a/app/scripts/config.js +++ b/app/scripts/config.js @@ -47,7 +47,7 @@ global.METAMASK_DEBUG = process.env.METAMASK_DEBUG */ /** - * @type {Config} Application configuration object + * @type {Config} **/ const config = { network: { @@ -76,4 +76,4 @@ const config = { }, } -module.exports = config \ No newline at end of file +module.exports = config diff --git a/app/scripts/controllers/token-rates.js b/app/scripts/controllers/token-rates.js index 22e3e8154..28409ea10 100644 --- a/app/scripts/controllers/token-rates.js +++ b/app/scripts/controllers/token-rates.js @@ -46,7 +46,7 @@ class TokenRatesController { } /** - * @type {Number} - Interval used to poll for exchange rates + * @type {Number} */ set interval (interval) { this._handle && clearInterval(this._handle) @@ -55,7 +55,7 @@ class TokenRatesController { } /** - * @type {Object} - Preferences controller instance + * @type {Object} */ set preferences (preferences) { this._preferences && this._preferences.unsubscribe() @@ -66,7 +66,7 @@ class TokenRatesController { } /** - * @type {Array} - Array of token objects with contract addresses + * @type {Array} */ set tokens (tokens) { this._tokens = tokens diff --git a/app/scripts/first-time-state.js b/app/scripts/first-time-state.js index 0c8f35303..144534f43 100644 --- a/app/scripts/first-time-state.js +++ b/app/scripts/first-time-state.js @@ -9,7 +9,7 @@ const METAMASK_DEBUG = process.env.METAMASK_DEBUG */ /** - * @type {FirstTimeState} The default state of MetaMask + * @type {FirstTimeState} */ const initialState = { config: {}, diff --git a/docs/jsdocs/ComposableObservableStore.html b/docs/jsdocs/ComposableObservableStore.html new file mode 100644 index 000000000..fa0807608 --- /dev/null +++ b/docs/jsdocs/ComposableObservableStore.html @@ -0,0 +1,541 @@ + + + + + + + ComposableObservableStore - Documentation + + + + + + + + + + + + + + + + + + + + + +
+ +

ComposableObservableStore

+ + + + + + + +
+ +
+ +

+ ComposableObservableStore +

+ +

An ObservableStore that can composes a flat +structure of child stores based on configuration

+ + +
+ +
+
+ + + + +

Constructor

+ + +

new ComposableObservableStore(initStateopt, configopt)

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+

Create a new store

+
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
initState + + +Object + + + + + + <optional>
+ + + + + +

The initial store state

config + + +Object + + + + + + <optional>
+ + + + + +

Map of internal state keys to child stores

+ + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + +

Methods

+ + + + + + +

getFlatState() → {Object}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+

Merges all child store state into a single object rather than +returning an object keyed by child store class name

+
+ + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • Object containing merged child store state
  • +
+
+ + + +
+
+ Type +
+
+ +Object + + +
+
+ + + + + + + + + +

updateStructure(configopt)

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+

Composes a new internal store subscription structure

+
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
config + + +Object + + + + + + <optional>
+ + + + + +

Map of internal state keys to child stores

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ +
+ +
+ Documentation generated by JSDoc 3.5.5 on Wed Apr 18 2018 17:21:38 GMT-0400 (EDT) using the radgrad jsdoc theme. Derived from docdash. +
+ + + + + + \ No newline at end of file diff --git a/docs/jsdocs/EdgeEncryptor.html b/docs/jsdocs/EdgeEncryptor.html new file mode 100644 index 000000000..538b14291 --- /dev/null +++ b/docs/jsdocs/EdgeEncryptor.html @@ -0,0 +1,545 @@ + + + + + + + EdgeEncryptor - Documentation + + + + + + + + + + + + + + + + + + + + + +
+ +

EdgeEncryptor

+ + + + + + + +
+ +
+ +

+ EdgeEncryptor +

+ +

A Microsoft Edge-specific encryption class that exposes +the interface expected by eth-keykeyring-controller

+ + +
+ +
+
+ + + + +

Constructor

+ + +

new EdgeEncryptor()

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + +

Methods

+ + + + + + +

decrypt(password, text) → {Promise.<Object>}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+

Decrypts an arbitrary JavaScript object from cypher text

+
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
password + + +string + + + +

Password used to unlock a cryptographic key

text + + +string + + + +

Cypher text of an encrypted JavaScript object

+ + + + + + + + + + + + + + +
Returns:
+ + +
+

Promise resolving to copy of decrypted JavaScript object

+
+ + + +
+
+ Type +
+
+ +Promise.<Object> + + +
+
+ + + + + + + + + +

encrypt(password, dataObject) → {Object}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+

Encrypts an arbitrary JavaScript object to cypher text

+
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
password + + +string + + + +

Password used to unlock a cryptographic key

dataObject + + +Object + + + +

Data to encrypt

+ + + + + + + + + + + + + + +
Returns:
+ + +
+

Object containing cypher text, generation vectors, and salt

+
+ + + +
+
+ Type +
+
+ +Object + + +
+
+ + + + + + + + + + +
+ +
+ + + + +
+ +
+ +
+ Documentation generated by JSDoc 3.5.5 on Wed Apr 18 2018 17:21:38 GMT-0400 (EDT) using the radgrad jsdoc theme. Derived from docdash. +
+ + + + + + \ No newline at end of file diff --git a/docs/jsdocs/TokenRatesController.html b/docs/jsdocs/TokenRatesController.html new file mode 100644 index 000000000..60994b685 --- /dev/null +++ b/docs/jsdocs/TokenRatesController.html @@ -0,0 +1,682 @@ + + + + + + + TokenRatesController - Documentation + + + + + + + + + + + + + + + + + + + + + +
+ +

TokenRatesController

+ + + + + + + +
+ +
+ +

+ TokenRatesController +

+ +

A controller that polls for token exchange +rates based on a user's current token list

+ + +
+ +
+
+ + + + +

Constructor

+ + +

new TokenRatesController(configopt)

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+

Creates a TokenRatesController

+
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
config + + +Object + + + + + + <optional>
+ + + + + +

Options to configure controller

+ + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + +

Members

+ + + +

interval :Number

+ + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
Type:
+
    +
  • + +Number + + +
  • +
+ + + + + + + + +

preferences :Object

+ + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
Type:
+
    +
  • + +Object + + +
  • +
+ + + + + + + + +

tokens :Array

+ + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
Type:
+
    +
  • + +Array + + +
  • +
+ + + + + + + + + + +

Methods

+ + + + + + +

(async) fetchExchangeRate(address)

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+

Fetches a token exchange rate by address

+
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
address + + +String + + + +

Token contract address

+ + + + + + + + + + + + + + + + + + + + + +

(async) updateExchangeRates()

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+

Updates exchange rates for all tokens

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ +
+ +
+ Documentation generated by JSDoc 3.5.5 on Wed Apr 18 2018 17:21:38 GMT-0400 (EDT) using the radgrad jsdoc theme. Derived from docdash. +
+ + + + + + \ No newline at end of file diff --git a/docs/jsdocs/config.js.html b/docs/jsdocs/config.js.html new file mode 100644 index 000000000..425b517d1 --- /dev/null +++ b/docs/jsdocs/config.js.html @@ -0,0 +1,148 @@ + + + + + + + config.js - Documentation + + + + + + + + + + + + + + + + + + + + + +
+ +

config.js

+ + + + + + + +
+
+
const MAINET_RPC_URL = 'https://mainnet.infura.io/metamask'
+const ROPSTEN_RPC_URL = 'https://ropsten.infura.io/metamask'
+const KOVAN_RPC_URL = 'https://kovan.infura.io/metamask'
+const RINKEBY_RPC_URL = 'https://rinkeby.infura.io/metamask'
+const LOCALHOST_RPC_URL = 'http://localhost:8545'
+
+const MAINET_RPC_URL_BETA = 'https://mainnet.infura.io/metamask2'
+const ROPSTEN_RPC_URL_BETA = 'https://ropsten.infura.io/metamask2'
+const KOVAN_RPC_URL_BETA = 'https://kovan.infura.io/metamask2'
+const RINKEBY_RPC_URL_BETA = 'https://rinkeby.infura.io/metamask2'
+
+const DEFAULT_RPC = 'rinkeby'
+const OLD_UI_NETWORK_TYPE = 'network'
+const BETA_UI_NETWORK_TYPE = 'networkBeta'
+
+global.METAMASK_DEBUG = process.env.METAMASK_DEBUG
+
+/**
+ * @typedef {Object} UrlConfig
+ * @property {string} localhost URL of local RPC provider
+ * @property {string} mainnet URL of mainnet RPC provider
+ * @property {string} ropsten URL of Ropsten testnet RPC provider
+ * @property {string} kovan URL of Kovan testnet RPC provider
+ * @property {string} rinkeby URL of Rinkeby testnet RPC provider
+ */
+
+/**
+ * @typedef {Object} NameConfig
+ * @property {string} 3 URL of local RPC provider
+ * @property {string} 4 URL of mainnet RPC provider
+ * @property {string} 42 URL of Ropsten testnet RPC provider
+ */
+
+/**
+ * @typedef {Object} EnumConfig
+ * @property {string} DEFAULT_RPC Default network provider URL
+ * @property {string} OLD_UI_NETWORK_TYPE
+ * @property {string} BETA_UI_NETWORK_TYPE
+ */
+
+/**
+ * @typedef {Object} Config
+ * @property {UrlConfig} network Network configuration parameters
+ * @property {UrlConfig} networkBeta Beta UI network configuration parameters
+ * @property {NameConfig} networkNames Network name configuration parameters
+ * @property {EnumConfig} enums Application-wide string constants
+ */
+
+/**
+ * @type {Config}
+ **/
+const config = {
+  network: {
+    localhost: LOCALHOST_RPC_URL,
+    mainnet: MAINET_RPC_URL,
+    ropsten: ROPSTEN_RPC_URL,
+    kovan: KOVAN_RPC_URL,
+    rinkeby: RINKEBY_RPC_URL,
+  },
+  networkBeta: {
+    localhost: LOCALHOST_RPC_URL,
+    mainnet: MAINET_RPC_URL_BETA,
+    ropsten: ROPSTEN_RPC_URL_BETA,
+    kovan: KOVAN_RPC_URL_BETA,
+    rinkeby: RINKEBY_RPC_URL_BETA,
+  },
+  networkNames: {
+    3: 'Ropsten',
+    4: 'Rinkeby',
+    42: 'Kovan',
+  },
+  enums: {
+    DEFAULT_RPC,
+    OLD_UI_NETWORK_TYPE,
+    BETA_UI_NETWORK_TYPE,
+  },
+}
+
+module.exports = config
+
+
+
+ + + + +
+ +
+ +
+ Documentation generated by JSDoc 3.5.5 on Wed Apr 18 2018 17:21:38 GMT-0400 (EDT) using the radgrad jsdoc theme. Derived from docdash. +
+ + + + + + diff --git a/docs/jsdocs/contentscript.js.html b/docs/jsdocs/contentscript.js.html new file mode 100644 index 000000000..0a798e81c --- /dev/null +++ b/docs/jsdocs/contentscript.js.html @@ -0,0 +1,265 @@ + + + + + + + contentscript.js - Documentation + + + + + + + + + + + + + + + + + + + + + +
+ +

contentscript.js

+ + + + + + + +
+
+
const fs = require('fs')
+const path = require('path')
+const pump = require('pump')
+const LocalMessageDuplexStream = require('post-message-stream')
+const PongStream = require('ping-pong-stream/pong')
+const ObjectMultiplex = require('obj-multiplex')
+const extension = require('extensionizer')
+const PortStream = require('./lib/port-stream.js')
+
+const inpageContent = fs.readFileSync(path.join(__dirname, '..', '..', 'dist', 'chrome', 'inpage.js')).toString()
+const inpageSuffix = '//# sourceURL=' + extension.extension.getURL('inpage.js') + '\n'
+const inpageBundle = inpageContent + inpageSuffix
+
+// Eventually this streaming injection could be replaced with:
+// https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Language_Bindings/Components.utils.exportFunction
+//
+// But for now that is only Firefox
+// If we create a FireFox-only code path using that API,
+// MetaMask will be much faster loading and performant on Firefox.
+
+if (shouldInjectWeb3()) {
+  setupInjection()
+  setupStreams()
+}
+
+/**
+ * Creates a script tag that injects inpage.js
+ */
+function setupInjection () {
+  try {
+    // inject in-page script
+    var scriptTag = document.createElement('script')
+    scriptTag.textContent = inpageBundle
+    scriptTag.onload = function () { this.parentNode.removeChild(this) }
+    var container = document.head || document.documentElement
+    // append as first child
+    container.insertBefore(scriptTag, container.children[0])
+  } catch (e) {
+    console.error('Metamask injection failed.', e)
+  }
+}
+
+/**
+ * Sets up two-way communication streams between the
+ * browser extension and local per-page browser context
+ */
+function setupStreams () {
+  // setup communication to page and plugin
+  const pageStream = new LocalMessageDuplexStream({
+    name: 'contentscript',
+    target: 'inpage',
+  })
+  const pluginPort = extension.runtime.connect({ name: 'contentscript' })
+  const pluginStream = new PortStream(pluginPort)
+
+  // forward communication plugin->inpage
+  pump(
+    pageStream,
+    pluginStream,
+    pageStream,
+    (err) => logStreamDisconnectWarning('MetaMask Contentscript Forwarding', err)
+  )
+
+  // setup local multistream channels
+  const mux = new ObjectMultiplex()
+  mux.setMaxListeners(25)
+
+  pump(
+    mux,
+    pageStream,
+    mux,
+    (err) => logStreamDisconnectWarning('MetaMask Inpage', err)
+  )
+  pump(
+    mux,
+    pluginStream,
+    mux,
+    (err) => logStreamDisconnectWarning('MetaMask Background', err)
+  )
+
+  // connect ping stream
+  const pongStream = new PongStream({ objectMode: true })
+  pump(
+    mux,
+    pongStream,
+    mux,
+    (err) => logStreamDisconnectWarning('MetaMask PingPongStream', err)
+  )
+
+  // connect phishing warning stream
+  const phishingStream = mux.createStream('phishing')
+  phishingStream.once('data', redirectToPhishingWarning)
+
+  // ignore unused channels (handled by background, inpage)
+  mux.ignoreStream('provider')
+  mux.ignoreStream('publicConfig')
+}
+
+
+/**
+ * Error handler for page to plugin stream disconnections
+ *
+ * @param {string} remoteLabel Remote stream name
+ * @param {Error} err Stream connection error
+ */
+function logStreamDisconnectWarning (remoteLabel, err) {
+  let warningMsg = `MetamaskContentscript - lost connection to ${remoteLabel}`
+  if (err) warningMsg += '\n' + err.stack
+  console.warn(warningMsg)
+}
+
+/**
+ * Determines if Web3 should be injected
+ *
+ * @returns {boolean} True of Web3 should be injected
+ */
+function shouldInjectWeb3 () {
+  return doctypeCheck() && suffixCheck()
+    && documentElementCheck() && !blacklistedDomainCheck()
+}
+
+/**
+ * Checks the doctype of the current document if it exists
+ *
+ * @returns {boolean} True if the doctype is html or if none exists
+ */
+function doctypeCheck () {
+  const doctype = window.document.doctype
+  if (doctype) {
+    return doctype.name === 'html'
+  } else {
+    return true
+  }
+}
+
+/**
+ * Checks the current document extension
+ *
+ * @returns {boolean} True if the current extension is not prohibited
+ */
+function suffixCheck () {
+  var prohibitedTypes = ['xml', 'pdf']
+  var currentUrl = window.location.href
+  var currentRegex
+  for (let i = 0; i < prohibitedTypes.length; i++) {
+    currentRegex = new RegExp(`\\.${prohibitedTypes[i]}$`)
+    if (currentRegex.test(currentUrl)) {
+      return false
+    }
+  }
+  return true
+}
+
+/**
+ * Checks the documentElement of the current document
+ *
+ * @returns {boolean} True if the documentElement is an html node or if none exists
+ */
+function documentElementCheck () {
+  var documentElement = document.documentElement.nodeName
+  if (documentElement) {
+    return documentElement.toLowerCase() === 'html'
+  }
+  return true
+}
+
+/**
+ * Checks if the current domain is blacklisted
+ * 
+ * @returns {boolean} True if the current domain is blacklisted
+ */
+function blacklistedDomainCheck () {
+  var blacklistedDomains = [
+    'uscourts.gov',
+    'dropbox.com',
+    'webbyawards.com',
+  ]
+  var currentUrl = window.location.href
+  var currentRegex
+  for (let i = 0; i < blacklistedDomains.length; i++) {
+    const blacklistedDomain = blacklistedDomains[i].replace('.', '\\.')
+    currentRegex = new RegExp(`(?:https?:\\/\\/)(?:(?!${blacklistedDomain}).)*$`)
+    if (!currentRegex.test(currentUrl)) {
+      return true
+    }
+  }
+  return false
+}
+
+/**
+ * Redirects the current page to a phishing information page
+ */
+function redirectToPhishingWarning () {
+  console.log('MetaMask - redirecting to phishing warning')
+  window.location.href = 'https://metamask.io/phishing.html'
+}
+
+
+
+ + + + +
+ +
+ +
+ Documentation generated by JSDoc 3.5.5 on Wed Apr 18 2018 17:21:38 GMT-0400 (EDT) using the radgrad jsdoc theme. Derived from docdash. +
+ + + + + + diff --git a/docs/jsdocs/controllers_token-rates.js.html b/docs/jsdocs/controllers_token-rates.js.html new file mode 100644 index 000000000..12c6d70fc --- /dev/null +++ b/docs/jsdocs/controllers_token-rates.js.html @@ -0,0 +1,146 @@ + + + + + + + controllers/token-rates.js - Documentation + + + + + + + + + + + + + + + + + + + + + +
+ +

controllers/token-rates.js

+ + + + + + + +
+
+
const ObservableStore = require('obs-store')
+
+// By default, poll every 3 minutes
+const DEFAULT_INTERVAL = 180 * 1000
+
+/**
+ * A controller that polls for token exchange
+ * rates based on a user's current token list
+ */
+class TokenRatesController {
+  /**
+   * Creates a TokenRatesController
+   *
+   * @param {Object} [config] - Options to configure controller
+   */
+  constructor ({ interval = DEFAULT_INTERVAL, preferences } = {}) {
+    this.store = new ObservableStore()
+    this.preferences = preferences
+    this.interval = interval
+  }
+
+  /**
+   * Updates exchange rates for all tokens
+   */
+  async updateExchangeRates () {
+    if (!this.isActive) { return }
+    const contractExchangeRates = {}
+    for (const i in this._tokens) {
+      const address = this._tokens[i].address
+      contractExchangeRates[address] = await this.fetchExchangeRate(address)
+    }
+    this.store.putState({ contractExchangeRates })
+  }
+
+  /**
+   * Fetches a token exchange rate by address
+   *
+   * @param {String} address - Token contract address
+   */
+  async fetchExchangeRate (address) {
+    try {
+      const response = await fetch(`https://exchanges.balanc3.net/prices?from=${address}&to=ETH&autoConversion=false&summaryOnly=true`)
+      const json = await response.json()
+      return json && json.length ? json[0].averagePrice : 0
+    } catch (error) { }
+  }
+
+  /**
+   * @type {Number}
+   */
+  set interval (interval) {
+    this._handle && clearInterval(this._handle)
+    if (!interval) { return }
+    this._handle = setInterval(() => { this.updateExchangeRates() }, interval)
+  }
+
+  /**
+   * @type {Object}
+   */
+  set preferences (preferences) {
+    this._preferences && this._preferences.unsubscribe()
+    if (!preferences) { return }
+    this._preferences = preferences
+    this.tokens = preferences.getState().tokens
+    preferences.subscribe(({ tokens = [] }) => { this.tokens = tokens })
+  }
+
+  /**
+   * @type {Array}
+   */
+  set tokens (tokens) {
+    this._tokens = tokens
+    this.updateExchangeRates()
+  }
+}
+
+module.exports = TokenRatesController
+
+
+
+ + + + +
+ +
+ +
+ Documentation generated by JSDoc 3.5.5 on Wed Apr 18 2018 17:21:38 GMT-0400 (EDT) using the radgrad jsdoc theme. Derived from docdash. +
+ + + + + + diff --git a/docs/jsdocs/edge-encryptor.js.html b/docs/jsdocs/edge-encryptor.js.html new file mode 100644 index 000000000..e85f444b4 --- /dev/null +++ b/docs/jsdocs/edge-encryptor.js.html @@ -0,0 +1,166 @@ + + + + + + + edge-encryptor.js - Documentation + + + + + + + + + + + + + + + + + + + + + +
+ +

edge-encryptor.js

+ + + + + + + +
+
+
const asmcrypto = require('asmcrypto.js')
+const Unibabel = require('browserify-unibabel')
+
+/**
+ * A Microsoft Edge-specific encryption class that exposes
+ * the interface expected by eth-keykeyring-controller
+ */
+class EdgeEncryptor {
+  /**
+   * Encrypts an arbitrary JavaScript object to cypher text
+   *
+   * @param {string} password Password used to unlock a cryptographic key
+   * @param {Object} dataObject Data to encrypt
+   * @returns {Object} Object containing cypher text, generation vectors, and salt
+   */
+  encrypt (password, dataObject) {
+      var salt = this._generateSalt()
+      return this._keyFromPassword(password, salt)
+          .then(function (key) {
+              var data = JSON.stringify(dataObject)
+              var dataBuffer = Unibabel.utf8ToBuffer(data)
+              var vector = global.crypto.getRandomValues(new Uint8Array(16))
+              var resultbuffer = asmcrypto.AES_GCM.encrypt(dataBuffer, key, vector)
+
+              var buffer = new Uint8Array(resultbuffer)
+              var vectorStr = Unibabel.bufferToBase64(vector)
+              var vaultStr = Unibabel.bufferToBase64(buffer)
+              return JSON.stringify({
+                  data: vaultStr,
+                  iv: vectorStr,
+                  salt: salt,
+              })
+          })
+  }
+
+  /**
+   * Decrypts an arbitrary JavaScript object from cypher text
+   *
+   * @param {string} password Password used to unlock a cryptographic key
+   * @param {string} text Cypher text of an encrypted JavaScript object
+   * @returns {Promise<Object>} Promise resolving to copy of decrypted JavaScript object
+   */
+  decrypt (password, text) {
+      const payload = JSON.parse(text)
+      const salt = payload.salt
+      return this._keyFromPassword(password, salt)
+          .then(function (key) {
+              const encryptedData = Unibabel.base64ToBuffer(payload.data)
+              const vector = Unibabel.base64ToBuffer(payload.iv)
+              return new Promise((resolve, reject) => {
+                  var result
+                  try {
+                      result = asmcrypto.AES_GCM.decrypt(encryptedData, key, vector)
+                  } catch (err) {
+                      return reject(new Error('Incorrect password'))
+                  }
+                  const decryptedData = new Uint8Array(result)
+                  const decryptedStr = Unibabel.bufferToUtf8(decryptedData)
+                  const decryptedObj = JSON.parse(decryptedStr)
+                  resolve(decryptedObj)
+              })
+          })
+  }
+
+  /**
+   * Retrieves a cryptographic key using a password
+   *
+   * @private
+   * @param {string} password Password used to unlock a cryptographic key
+   * @param {string} salt Random base-64 data
+   * @returns {Promise<Object>} Promise resolving to a derived key
+   */
+  _keyFromPassword (password, salt) {
+
+      var passBuffer = Unibabel.utf8ToBuffer(password)
+      var saltBuffer = Unibabel.base64ToBuffer(salt)
+      return new Promise((resolve) => {
+          var key = asmcrypto.PBKDF2_HMAC_SHA256.bytes(passBuffer, saltBuffer, 10000)
+          resolve(key)
+      })
+  }
+
+  /**
+   * Generates random base-64 encoded data
+   *
+   * @private
+   * @returns {string} Randomized base-64 encoded data
+   */
+  _generateSalt (byteCount = 32) {
+      var view = new Uint8Array(byteCount)
+      global.crypto.getRandomValues(view)
+      var b64encoded = btoa(String.fromCharCode.apply(null, view))
+      return b64encoded
+  }
+}
+
+module.exports = EdgeEncryptor
+
+
+
+ + + + +
+ +
+ +
+ Documentation generated by JSDoc 3.5.5 on Wed Apr 18 2018 17:21:38 GMT-0400 (EDT) using the radgrad jsdoc theme. Derived from docdash. +
+ + + + + + diff --git a/docs/jsdocs/first-time-state.js.html b/docs/jsdocs/first-time-state.js.html new file mode 100644 index 000000000..431846e45 --- /dev/null +++ b/docs/jsdocs/first-time-state.js.html @@ -0,0 +1,92 @@ + + + + + + + first-time-state.js - Documentation + + + + + + + + + + + + + + + + + + + + + +
+ +

first-time-state.js

+ + + + + + + +
+
+
// test and development environment variables
+const env = process.env.METAMASK_ENV
+const METAMASK_DEBUG = process.env.METAMASK_DEBUG
+
+/**
+ * @typedef {Object} FirstTimeState
+ * @property {Object} config Initial configuration parameters
+ * @property {Object} NetworkController Network controller state
+ */
+
+/**
+ * @type {FirstTimeState}
+ */
+const initialState = {
+  config: {},
+  NetworkController: {
+    provider: {
+      type: (METAMASK_DEBUG || env === 'test') ? 'rinkeby' : 'mainnet',
+    },
+  },
+}
+
+module.exports = initialState
+
+
+
+ + + + +
+ +
+ +
+ Documentation generated by JSDoc 3.5.5 on Wed Apr 18 2018 17:21:38 GMT-0400 (EDT) using the radgrad jsdoc theme. Derived from docdash. +
+ + + + + + diff --git a/docs/jsdocs/global.html b/docs/jsdocs/global.html index c06006e58..499111982 100644 --- a/docs/jsdocs/global.html +++ b/docs/jsdocs/global.html @@ -32,7 +32,7 @@
@@ -116,15 +116,11 @@ - - - - -

Type Definitions

+

Members

- -

MetaMaskOptions

+ +

(constant) config :Config

@@ -135,7 +131,1865 @@
Source:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Type:
+ + + + + + + + + +

(constant) initialState :FirstTimeState

+ + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
Type:
+ + + + + + + + + + + +

Methods

+ + + + + + +

blacklistedDomainCheck() → {boolean}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+

Checks if the current domain is blacklisted

+
+ + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+

True if the current domain is blacklisted

+
+ + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + +

cleanContextForImports()

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+

Caches reference to global define object and deletes it

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

connectToAccountManager(connectionStream, cb)

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+

Establishes streamed connections to background scripts and a Web3 provider

+
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
connectionStream + + +any + + + +

PortStream instance establishing a background connection

cb + + +function + + + +

Called when controller connection is established

+ + + + + + + + + + + + + + + + + + + + + +

doctypeCheck() → {boolean}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+

Checks the doctype of the current document if it exists

+
+ + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+

True if the doctype is html or if none exists

+
+ + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + +

documentElementCheck() → {boolean}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+

Checks the documentElement of the current document

+
+ + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+

True if the documentElement is an html node or if none exists

+
+ + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + +

initializePopup(config, cb)

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+

Asynchronously initializes the MetaMask popup UI

+
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
config + + +Object + + + +

Popup configuration object

cb + + +function + + + +

Called when initialization is comlete

+ + + + + + + + + + + + + + + + + + + + + +

logStreamDisconnectWarning(remoteLabel, err)

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+

Error handler for page to plugin stream disconnections

+
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
remoteLabel + + +string + + + +

Remote stream name

err + + +Error + + + +

Stream connection error

+ + + + + + + + + + + + + + + + + + + + + +

redirectToPhishingWarning()

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+

Redirects the current page to a phishing information page

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

restoreContextAfterImports()

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+

Restores global define object from cached reference

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

setupControllerConnection(connectionStream, cb)

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+

Establishes a streamed connection to the background account manager

+
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
connectionStream + + +any + + + +

PortStream instance establishing a background connection

cb + + +function + + + +

Called when the remote account manager connection is established

+ + + + + + + + + + + + + + + + + + + + + +

setupInjection()

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+

Creates a script tag that injects inpage.js

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

setupStreams()

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+

Sets up two-way communication streams between the +browser extension and local per-page browser context

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

setupWeb3Connection(connectionStream)

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+

Establishes a streamed connection to a Web3 provider

+
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
connectionStream + + +any + + + +

PortStream instance establishing a background connection

+ + + + + + + + + + + + + + + + + + + + + +

shouldInjectWeb3() → {boolean}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+

Determines if Web3 should be injected

+
+ + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+

True of Web3 should be injected

+
+ + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + +

suffixCheck() → {boolean}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+

Checks the current document extension

+
+ + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+

True if the current extension is not prohibited

+
+ + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + +

Type Definitions

+ + + +

Config

+ + + + + +
+ + +
Source:
+
@@ -198,13 +2052,13 @@ - platform + network -Platform +UrlConfig @@ -214,7 +2068,76 @@ -

An object including platform-specific functions.

+

Network configuration parameters

+ + + + + + + networkBeta + + + + + +UrlConfig + + + + + + + + + +

Beta UI network configuration parameters

+ + + + + + + networkNames + + + + + +NameConfig + + + + + + + + + +

Network name configuration parameters

+ + + + + + + enums + + + + + +EnumConfig + + + + + + + + + +

Application-wide string constants

@@ -232,7 +2155,7 @@
  • -object +Object
  • @@ -245,7 +2168,7 @@ -

    Platform

    +

    EnumConfig

    @@ -256,7 +2179,7 @@
    Source:
    @@ -319,13 +2242,13 @@ - reload + DEFAULT_RPC -function +string @@ -335,20 +2258,20 @@ -

    A function to reload the application.

    +

    Default network provider URL

    - openWindow + OLD_UI_NETWORK_TYPE -function +string @@ -358,20 +2281,20 @@ -

    Opens a URL in the web browser.

    + - getVersion + BETA_UI_NETWORK_TYPE -function +string @@ -381,53 +2304,7 @@ -

    Gets the current version of MetaMask.

    - - - - - - - openExtensionInBrowser - - - - - -function - - - - - - - - - -

    Opens the MetaMask UI in a full window.

    - - - - - - - getPlatformInfo - - - - - -function - - - - - - - - - -

    Callback function that returns info about the current platform.

    + @@ -439,9 +2316,149 @@ -
    -

    An object that provides a variety of platform-specific functions.

    -
    + + +
    Type:
    +
      +
    • + +Object + + +
    • +
    + + + + + + + + +

    FirstTimeState

    + + + + + +
    + + +
    Source:
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + +
    Properties:
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NameTypeDescription
    config + + +Object + + + +

    Initial configuration parameters

    NetworkController + + +Object + + + +

    Network controller state

    + + + + + @@ -449,7 +2466,387 @@
    • -object +Object + + +
    • +
    + + + + + + + + +

    NameConfig

    + + + + + +
    + + +
    Source:
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + +
    Properties:
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NameTypeDescription
    3 + + +string + + + +

    URL of local RPC provider

    4 + + +string + + + +

    URL of mainnet RPC provider

    42 + + +string + + + +

    URL of Ropsten testnet RPC provider

    + + + + + + + + +
    Type:
    +
      +
    • + +Object + + +
    • +
    + + + + + + + + +

    UrlConfig

    + + + + + +
    + + +
    Source:
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + +
    Properties:
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NameTypeDescription
    localhost + + +string + + + +

    URL of local RPC provider

    mainnet + + +string + + + +

    URL of mainnet RPC provider

    ropsten + + +string + + + +

    URL of Ropsten testnet RPC provider

    kovan + + +string + + + +

    URL of Kovan testnet RPC provider

    rinkeby + + +string + + + +

    URL of Rinkeby testnet RPC provider

    + + + + + + + + +
    Type:
    +
      +
    • + +Object
    • @@ -476,7 +2873,7 @@
      - Documentation generated by JSDoc 3.5.5 on Thu Apr 12 2018 14:37:39 GMT-0700 (PDT) using the radgrad jsdoc theme. Derived from docdash. + Documentation generated by JSDoc 3.5.5 on Wed Apr 18 2018 17:21:38 GMT-0400 (EDT) using the radgrad jsdoc theme. Derived from docdash.
      diff --git a/docs/jsdocs/index.html b/docs/jsdocs/index.html index 7ac43e45d..0d5b08d90 100644 --- a/docs/jsdocs/index.html +++ b/docs/jsdocs/index.html @@ -32,7 +32,7 @@
      @@ -56,106 +56,6 @@ - - - - - - - -
      - -
      - -

      - controllers/transactions.js -

      - - -
      - -
      -
      - - - -
      - - -
      Source:
      -
      - - - - - - - - - - - - - - - - - - - - - - - - - - -
      License:
      -
      • MIT
      - - - - - - - - - -
      - - - - - -

      The transaction controller. Receives incoming transactions, and emits events for various states of their processing.

      - - - - -
      - - - - - - - - - - - - - - - - - - -
      - -
      @@ -265,7 +165,7 @@
      - Documentation generated by JSDoc 3.5.5 on Thu Apr 12 2018 14:37:39 GMT-0700 (PDT) using the radgrad jsdoc theme. Derived from docdash. + Documentation generated by JSDoc 3.5.5 on Wed Apr 18 2018 17:21:38 GMT-0400 (EDT) using the radgrad jsdoc theme. Derived from docdash.
      diff --git a/docs/jsdocs/inpage.js.html b/docs/jsdocs/inpage.js.html new file mode 100644 index 000000000..acfd6223c --- /dev/null +++ b/docs/jsdocs/inpage.js.html @@ -0,0 +1,144 @@ + + + + + + + inpage.js - Documentation + + + + + + + + + + + + + + + + + + + + + +
      + +

      inpage.js

      + + + + + + + +
      +
      +
      /*global Web3*/
      +cleanContextForImports()
      +require('web3/dist/web3.min.js')
      +const log = require('loglevel')
      +const LocalMessageDuplexStream = require('post-message-stream')
      +const setupDappAutoReload = require('./lib/auto-reload.js')
      +const MetamaskInpageProvider = require('./lib/inpage-provider.js')
      +restoreContextAfterImports()
      +
      +log.setDefaultLevel(process.env.METAMASK_DEBUG ? 'debug' : 'warn')
      +
      +//
      +// setup plugin communication
      +//
      +
      +// setup background connection
      +var metamaskStream = new LocalMessageDuplexStream({
      +  name: 'inpage',
      +  target: 'contentscript',
      +})
      +
      +// compose the inpage provider
      +var inpageProvider = new MetamaskInpageProvider(metamaskStream)
      +
      +//
      +// setup web3
      +//
      +
      +if (typeof window.web3 !== 'undefined') {
      +  throw new Error(`MetaMask detected another web3.
      +     MetaMask will not work reliably with another web3 extension.
      +     This usually happens if you have two MetaMasks installed,
      +     or MetaMask and another web3 extension. Please remove one
      +     and try again.`)
      +}
      +var web3 = new Web3(inpageProvider)
      +web3.setProvider = function () {
      +  log.debug('MetaMask - overrode web3.setProvider')
      +}
      +log.debug('MetaMask - injected web3')
      +// export global web3, with usage-detection
      +setupDappAutoReload(web3, inpageProvider.publicConfigStore)
      +
      +// set web3 defaultAccount
      +inpageProvider.publicConfigStore.subscribe(function (state) {
      +  web3.eth.defaultAccount = state.selectedAddress
      +})
      +
      +// need to make sure we aren't affected by overlapping namespaces
      +// and that we dont affect the app with our namespace
      +// mostly a fix for web3's BigNumber if AMD's "define" is defined...
      +var __define
      +
      +/**
      + * Caches reference to global define object and deletes it
      + */
      +function cleanContextForImports () {
      +  __define = global.define
      +  try {
      +    global.define = undefined
      +  } catch (_) {
      +    console.warn('MetaMask - global.define could not be deleted.')
      +  }
      +}
      +
      +/**
      + * Restores global define object from cached reference
      + */
      +function restoreContextAfterImports () {
      +  try {
      +    global.define = __define
      +  } catch (_) {
      +    console.warn('MetaMask - global.define could not be overwritten.')
      +  }
      +}
      +
      +
      +
      + + + + +
      + +
      + +
      + Documentation generated by JSDoc 3.5.5 on Wed Apr 18 2018 17:21:38 GMT-0400 (EDT) using the radgrad jsdoc theme. Derived from docdash. +
      + + + + + + diff --git a/docs/jsdocs/lib_ComposableObservableStore.js.html b/docs/jsdocs/lib_ComposableObservableStore.js.html new file mode 100644 index 000000000..dc39a9f55 --- /dev/null +++ b/docs/jsdocs/lib_ComposableObservableStore.js.html @@ -0,0 +1,118 @@ + + + + + + + lib/ComposableObservableStore.js - Documentation + + + + + + + + + + + + + + + + + + + + + +
      + +

      lib/ComposableObservableStore.js

      + + + + + + + +
      +
      +
      const ObservableStore = require('obs-store')
      +
      +/**
      + * An ObservableStore that can composes a flat
      + * structure of child stores based on configuration
      + */
      +class ComposableObservableStore extends ObservableStore {
      +  /**
      +   * Create a new store
      +   *
      +   * @param {Object} [initState] - The initial store state
      +   * @param {Object} [config] - Map of internal state keys to child stores
      +   */
      +  constructor (initState, config) {
      +    super(initState)
      +    this.updateStructure(config)
      +  }
      +
      +  /**
      +   * Composes a new internal store subscription structure
      +   *
      +   * @param {Object} [config] - Map of internal state keys to child stores
      +   */
      +  updateStructure (config) {
      +    this.config = config
      +    this.removeAllListeners()
      +    for (const key in config) {
      +      config[key].subscribe((state) => {
      +        this.updateState({ [key]: state })
      +      })
      +    }
      +  }
      +
      +  /**
      +   * Merges all child store state into a single object rather than
      +   * returning an object keyed by child store class name
      +   *
      +   * @returns {Object} - Object containing merged child store state
      +   */
      +  getFlatState () {
      +    let flatState = {}
      +    for (const key in this.config) {
      +      flatState = { ...flatState, ...this.config[key].getState() }
      +    }
      +    return flatState
      +  }
      +}
      +
      +module.exports = ComposableObservableStore
      +
      +
      +
      + + + + +
      + +
      + +
      + Documentation generated by JSDoc 3.5.5 on Wed Apr 18 2018 17:21:38 GMT-0400 (EDT) using the radgrad jsdoc theme. Derived from docdash. +
      + + + + + + diff --git a/docs/jsdocs/metamask-controller.js.html b/docs/jsdocs/metamask-controller.js.html index 2162138d1..5f8748577 100644 --- a/docs/jsdocs/metamask-controller.js.html +++ b/docs/jsdocs/metamask-controller.js.html @@ -32,7 +32,7 @@
      @@ -54,10 +54,10 @@ */ const EventEmitter = require('events') -const extend = require('xtend') const pump = require('pump') const Dnode = require('dnode') const ObservableStore = require('obs-store') +const ComposableObservableStore = require('./lib/ComposableObservableStore') const asStream = require('obs-store/lib/asStream') const AccountTracker = require('./lib/account-tracker') const RpcEngine = require('json-rpc-engine') @@ -83,6 +83,7 @@ const PersonalMessageManager = require('./lib/personal-message-manager') const TypedMessageManager = require('./lib/typed-message-manager') const TransactionController = require('./controllers/transactions') const BalancesController = require('./controllers/computed-balances') +const TokenRatesController = require('./controllers/token-rates') const ConfigManager = require('./lib/config-manager') const nodeify = require('./lib/nodeify') const accountImporter = require('./account-import-strategies') @@ -93,11 +94,7 @@ const BN = require('ethereumjs-util').BN const GWEI_BN = new BN('1000000000') const percentile = require('percentile') const seedPhraseVerifier = require('./lib/seed-phrase-verifier') - -/** - * @typedef {object} MetaMaskOptions - * @property {Platform} platform - An object including platform-specific functions. - */ +const log = require('loglevel') module.exports = class MetamaskController extends EventEmitter { @@ -108,7 +105,6 @@ module.exports = class MetamaskController extends EventEmitter { constructor (opts) { super() - // Avoids warnings when we use lots of emitters. this.defaultMaxListeners = 20 this.sendUpdate = debounce(this.privateSendUpdate.bind(this), 200) @@ -120,7 +116,7 @@ module.exports = class MetamaskController extends EventEmitter { this.platform = opts.platform // observable state store - this.store = new ObservableStore(initState) + this.store = new ComposableObservableStore(initState) // lock to ensure only one vault created at once this.createVaultMutex = new Mutex() @@ -159,6 +155,11 @@ module.exports = class MetamaskController extends EventEmitter { this.provider = this.initializeProvider() this.blockTracker = this.provider._blockTracker + // token exchange rate tracker + this.tokenRatesController = new TokenRatesController({ + preferences: this.preferencesController.store, + }) + this.recentBlocksController = new RecentBlocksController({ blockTracker: this.blockTracker, provider: this.provider, @@ -239,53 +240,37 @@ module.exports = class MetamaskController extends EventEmitter { this.typedMessageManager = new TypedMessageManager() this.publicConfigStore = this.initPublicConfigStore() - // manual disk state subscriptions - this.txController.store.subscribe((state) => { - this.store.updateState({ TransactionController: state }) - }) - this.keyringController.store.subscribe((state) => { - this.store.updateState({ KeyringController: state }) - }) - this.preferencesController.store.subscribe((state) => { - this.store.updateState({ PreferencesController: state }) - }) - this.addressBookController.store.subscribe((state) => { - this.store.updateState({ AddressBookController: state }) - }) - this.currencyController.store.subscribe((state) => { - this.store.updateState({ CurrencyController: state }) - }) - this.noticeController.store.subscribe((state) => { - this.store.updateState({ NoticeController: state }) - }) - this.shapeshiftController.store.subscribe((state) => { - this.store.updateState({ ShapeShiftController: state }) - }) - this.networkController.store.subscribe((state) => { - this.store.updateState({ NetworkController: state }) + this.store.updateStructure({ + TransactionController: this.txController.store, + KeyringController: this.keyringController.store, + PreferencesController: this.preferencesController.store, + AddressBookController: this.addressBookController.store, + CurrencyController: this.currencyController.store, + NoticeController: this.noticeController.store, + ShapeShiftController: this.shapeshiftController.store, + NetworkController: this.networkController.store, + InfuraController: this.infuraController.store, }) - this.infuraController.store.subscribe((state) => { - this.store.updateState({ InfuraController: state }) + this.memStore = new ComposableObservableStore(null, { + NetworkController: this.networkController.store, + AccountTracker: this.accountTracker.store, + TxController: this.txController.memStore, + BalancesController: this.balancesController.store, + TokenRatesController: this.tokenRatesController.store, + MessageManager: this.messageManager.memStore, + PersonalMessageManager: this.personalMessageManager.memStore, + TypesMessageManager: this.typedMessageManager.memStore, + KeyringController: this.keyringController.memStore, + PreferencesController: this.preferencesController.store, + RecentBlocksController: this.recentBlocksController.store, + AddressBookController: this.addressBookController.store, + CurrencyController: this.currencyController.store, + NoticeController: this.noticeController.memStore, + ShapeshiftController: this.shapeshiftController.store, + InfuraController: this.infuraController.store, }) - - // manual mem state subscriptions - const sendUpdate = this.sendUpdate.bind(this) - this.networkController.store.subscribe(sendUpdate) - this.accountTracker.store.subscribe(sendUpdate) - this.txController.memStore.subscribe(sendUpdate) - this.balancesController.store.subscribe(sendUpdate) - this.messageManager.memStore.subscribe(sendUpdate) - this.personalMessageManager.memStore.subscribe(sendUpdate) - this.typedMessageManager.memStore.subscribe(sendUpdate) - this.keyringController.memStore.subscribe(sendUpdate) - this.preferencesController.store.subscribe(sendUpdate) - this.recentBlocksController.store.subscribe(sendUpdate) - this.addressBookController.store.subscribe(sendUpdate) - this.currencyController.store.subscribe(sendUpdate) - this.noticeController.memStore.subscribe(sendUpdate) - this.shapeshiftController.store.subscribe(sendUpdate) - this.infuraController.store.subscribe(sendUpdate) + this.memStore.subscribe(this.sendUpdate.bind(this)) } /** @@ -334,6 +319,7 @@ module.exports = class MetamaskController extends EventEmitter { // memStore -> transform -> publicConfigStore this.on('update', (memState) => { + this.isClientOpenAndUnlocked = memState.isUnlocked && this._isClientOpen const publicState = selectPublicState(memState) publicConfigStore.putState(publicState) }) @@ -363,33 +349,16 @@ module.exports = class MetamaskController extends EventEmitter { const vault = this.keyringController.store.getState().vault const isInitialized = (!!wallet || !!vault) - return extend( - { - isInitialized, - }, - this.networkController.store.getState(), - this.accountTracker.store.getState(), - this.txController.memStore.getState(), - this.messageManager.memStore.getState(), - this.personalMessageManager.memStore.getState(), - this.typedMessageManager.memStore.getState(), - this.keyringController.memStore.getState(), - this.balancesController.store.getState(), - this.preferencesController.store.getState(), - this.addressBookController.store.getState(), - this.currencyController.store.getState(), - this.noticeController.memStore.getState(), - this.infuraController.store.getState(), - this.recentBlocksController.store.getState(), - // config manager - this.configManager.getConfig(), - this.shapeshiftController.store.getState(), - { + return { + ...{ isInitialized }, + ...this.memStore.getFlatState(), + ...this.configManager.getConfig(), + ...{ lostAccounts: this.configManager.getLostAccounts(), seedWords: this.configManager.getSeedWords(), forgottenPassword: this.configManager.getPasswordForgotten(), - } - ) + }, + } } /** @@ -1103,15 +1072,6 @@ module.exports = class MetamaskController extends EventEmitter { } } - /** - * Records the MetaMask version and time of first installation, - * mutating the initState param. - * - * @private - * - * @param {object} initState The initial state passed to the controller, - * which may be new. - */ recordFirstTimeInfo (initState) { if (!('firstTimeInfo' in initState)) { initState.firstTimeInfo = { @@ -1121,6 +1081,14 @@ module.exports = class MetamaskController extends EventEmitter { } } + set isClientOpen (open) { + this._isClientOpen = open + this.isClientOpenAndUnlocked = this.getState().isUnlocked && open + } + + set isClientOpenAndUnlocked (active) { + this.tokenRatesController.isActive = active + } } @@ -1134,7 +1102,7 @@ module.exports = class MetamaskController extends EventEmitter {
      - Documentation generated by JSDoc 3.5.5 on Thu Apr 12 2018 14:37:39 GMT-0700 (PDT) using the radgrad jsdoc theme. Derived from docdash. + Documentation generated by JSDoc 3.5.5 on Wed Apr 18 2018 17:21:38 GMT-0400 (EDT) using the radgrad jsdoc theme. Derived from docdash.
      diff --git a/docs/jsdocs/module.exports_module.exports.html b/docs/jsdocs/module.exports_module.exports.html index 5558cea07..f5c96b6eb 100644 --- a/docs/jsdocs/module.exports_module.exports.html +++ b/docs/jsdocs/module.exports_module.exports.html @@ -32,7 +32,7 @@
      @@ -75,7 +75,7 @@
      Source:
      @@ -219,7 +219,7 @@
      - Documentation generated by JSDoc 3.5.5 on Thu Apr 12 2018 14:37:39 GMT-0700 (PDT) using the radgrad jsdoc theme. Derived from docdash. + Documentation generated by JSDoc 3.5.5 on Wed Apr 18 2018 17:21:38 GMT-0400 (EDT) using the radgrad jsdoc theme. Derived from docdash.
      diff --git a/docs/jsdocs/popup-core.js.html b/docs/jsdocs/popup-core.js.html new file mode 100644 index 000000000..919637cfe --- /dev/null +++ b/docs/jsdocs/popup-core.js.html @@ -0,0 +1,146 @@ + + + + + + + popup-core.js - Documentation + + + + + + + + + + + + + + + + + + + + + +
      + +

      popup-core.js

      + + + + + + + +
      +
      +
      const EventEmitter = require('events').EventEmitter
      +const async = require('async')
      +const Dnode = require('dnode')
      +const Eth = require('ethjs')
      +const EthQuery = require('eth-query')
      +const launchMetamaskUi = require('../../ui')
      +const StreamProvider = require('web3-stream-provider')
      +const setupMultiplex = require('./lib/stream-utils.js').setupMultiplex
      +
      +module.exports = initializePopup
      +
      +/**
      + * Asynchronously initializes the MetaMask popup UI
      + *
      + * @param {{ container: Element, connectionStream: any }} config Popup configuration object 
      + * @param {Function} cb Called when initialization is comlete
      + */
      +function initializePopup ({ container, connectionStream }, cb) {
      +  // setup app
      +  async.waterfall([
      +    (cb) => connectToAccountManager(connectionStream, cb),
      +    (accountManager, cb) => launchMetamaskUi({ container, accountManager }, cb),
      +  ], cb)
      +}
      +
      +/**
      + * Establishes streamed connections to background scripts and a Web3 provider
      + *
      + * @param {any} connectionStream PortStream instance establishing a background connection
      + * @param {Function} cb Called when controller connection is established
      + */
      +function connectToAccountManager (connectionStream, cb) {
      +  // setup communication with background
      +  // setup multiplexing
      +  var mx = setupMultiplex(connectionStream)
      +  // connect features
      +  setupControllerConnection(mx.createStream('controller'), cb)
      +  setupWeb3Connection(mx.createStream('provider'))
      +}
      +
      +/**
      + * Establishes a streamed connection to a Web3 provider
      + *
      + * @param {any} connectionStream PortStream instance establishing a background connection
      + */
      +function setupWeb3Connection (connectionStream) {
      +  var providerStream = new StreamProvider()
      +  providerStream.pipe(connectionStream).pipe(providerStream)
      +  connectionStream.on('error', console.error.bind(console))
      +  providerStream.on('error', console.error.bind(console))
      +  global.ethereumProvider = providerStream
      +  global.ethQuery = new EthQuery(providerStream)
      +  global.eth = new Eth(providerStream)
      +}
      +
      +/**
      + * Establishes a streamed connection to the background account manager
      + *
      + * @param {any} connectionStream PortStream instance establishing a background connection
      + * @param {Function} cb Called when the remote account manager connection is established
      + */
      +function setupControllerConnection (connectionStream, cb) {
      +  // this is a really sneaky way of adding EventEmitter api
      +  // to a bi-directional dnode instance
      +  var eventEmitter = new EventEmitter()
      +  var accountManagerDnode = Dnode({
      +    sendUpdate: function (state) {
      +      eventEmitter.emit('update', state)
      +    },
      +  })
      +  connectionStream.pipe(accountManagerDnode).pipe(connectionStream)
      +  accountManagerDnode.once('remote', function (accountManager) {
      +    // setup push events
      +    accountManager.on = eventEmitter.on.bind(eventEmitter)
      +    cb(null, accountManager)
      +  })
      +}
      +
      +
      +
      + + + + +
      + +
      + +
      + Documentation generated by JSDoc 3.5.5 on Wed Apr 18 2018 17:21:38 GMT-0400 (EDT) using the radgrad jsdoc theme. Derived from docdash. +
      + + + + + + From 1ef6528921263fb9dbae35476a1d9827e1d87508 Mon Sep 17 00:00:00 2001 From: bitpshr Date: Wed, 18 Apr 2018 21:30:13 -0400 Subject: [PATCH 3/5] Add JSDoc to various background scripts --- .gitignore | 1 + app/scripts/edge-encryptor.js | 12 +- app/scripts/inpage.js | 4 +- app/scripts/popup-core.js | 8 +- docs/jsdocs/ComposableObservableStore.html | 541 ---- docs/jsdocs/EdgeEncryptor.html | 545 ---- docs/jsdocs/TokenRatesController.html | 682 ---- docs/jsdocs/config.js.html | 148 - docs/jsdocs/contentscript.js.html | 265 -- docs/jsdocs/controllers_token-rates.js.html | 146 - docs/jsdocs/controllers_transactions.js.html | 471 --- docs/jsdocs/edge-encryptor.js.html | 166 - docs/jsdocs/first-time-state.js.html | 92 - docs/jsdocs/global.html | 2883 ----------------- docs/jsdocs/index.html | 175 - docs/jsdocs/inpage.js.html | 144 - .../lib_ComposableObservableStore.js.html | 118 - docs/jsdocs/metamask-controller.js.html | 1112 ------- .../jsdocs/module.exports_module.exports.html | 229 -- docs/jsdocs/platforms_extension.js.html | 117 - docs/jsdocs/popup-core.js.html | 146 - docs/jsdocs/scripts/linenumber.js | 25 - .../scripts/prettify/Apache-License-2.0.txt | 202 -- docs/jsdocs/scripts/prettify/lang-css.js | 2 - docs/jsdocs/scripts/prettify/prettify.js | 28 - docs/jsdocs/scripts/semantic.min.js | 19 - docs/jsdocs/styles/jsdoc.css | 626 ---- docs/jsdocs/styles/override.css | 3 - docs/jsdocs/styles/prettify.css | 79 - docs/jsdocs/styles/semantic.min.css | 364 --- 30 files changed, 14 insertions(+), 9339 deletions(-) delete mode 100644 docs/jsdocs/ComposableObservableStore.html delete mode 100644 docs/jsdocs/EdgeEncryptor.html delete mode 100644 docs/jsdocs/TokenRatesController.html delete mode 100644 docs/jsdocs/config.js.html delete mode 100644 docs/jsdocs/contentscript.js.html delete mode 100644 docs/jsdocs/controllers_token-rates.js.html delete mode 100644 docs/jsdocs/controllers_transactions.js.html delete mode 100644 docs/jsdocs/edge-encryptor.js.html delete mode 100644 docs/jsdocs/first-time-state.js.html delete mode 100644 docs/jsdocs/global.html delete mode 100644 docs/jsdocs/index.html delete mode 100644 docs/jsdocs/inpage.js.html delete mode 100644 docs/jsdocs/lib_ComposableObservableStore.js.html delete mode 100644 docs/jsdocs/metamask-controller.js.html delete mode 100644 docs/jsdocs/module.exports_module.exports.html delete mode 100644 docs/jsdocs/platforms_extension.js.html delete mode 100644 docs/jsdocs/popup-core.js.html delete mode 100644 docs/jsdocs/scripts/linenumber.js delete mode 100644 docs/jsdocs/scripts/prettify/Apache-License-2.0.txt delete mode 100644 docs/jsdocs/scripts/prettify/lang-css.js delete mode 100644 docs/jsdocs/scripts/prettify/prettify.js delete mode 100644 docs/jsdocs/scripts/semantic.min.js delete mode 100644 docs/jsdocs/styles/jsdoc.css delete mode 100644 docs/jsdocs/styles/override.css delete mode 100644 docs/jsdocs/styles/prettify.css delete mode 100644 docs/jsdocs/styles/semantic.min.css diff --git a/.gitignore b/.gitignore index dee5ec220..0e91a7d04 100644 --- a/.gitignore +++ b/.gitignore @@ -20,6 +20,7 @@ dist builds/ disc/ builds.zip +docs/jsdocs development/bundle.js development/states.js diff --git a/app/scripts/edge-encryptor.js b/app/scripts/edge-encryptor.js index 5f6699746..d2e985790 100644 --- a/app/scripts/edge-encryptor.js +++ b/app/scripts/edge-encryptor.js @@ -7,11 +7,11 @@ const Unibabel = require('browserify-unibabel') */ class EdgeEncryptor { /** - * Encrypts an arbitrary JavaScript object to cypher text + * Encrypts an arbitrary JavaScript object to ciphertext * - * @param {string} password Password used to unlock a cryptographic key + * @param {string} password Used to generate a key to encrypt the data * @param {Object} dataObject Data to encrypt - * @returns {Object} Object containing cypher text, generation vectors, and salt + * @returns {Promise} Promise resolving to an object with ciphertext */ encrypt (password, dataObject) { var salt = this._generateSalt() @@ -34,10 +34,10 @@ class EdgeEncryptor { } /** - * Decrypts an arbitrary JavaScript object from cypher text + * Decrypts an arbitrary JavaScript object from ciphertext * - * @param {string} password Password used to unlock a cryptographic key - * @param {string} text Cypher text of an encrypted JavaScript object + * @param {string} password Used to generate a key to decrypt the data + * @param {string} text Ciphertext of an encrypted JavaScript object * @returns {Promise} Promise resolving to copy of decrypted JavaScript object */ decrypt (password, text) { diff --git a/app/scripts/inpage.js b/app/scripts/inpage.js index 798af78bf..6d16eebd4 100644 --- a/app/scripts/inpage.js +++ b/app/scripts/inpage.js @@ -52,7 +52,9 @@ inpageProvider.publicConfigStore.subscribe(function (state) { var __define /** - * Caches reference to global define object and deletes it + * Caches reference to global define object and deletes it to + * avoid conflicts with other global define objects, such as + * AMD's define function */ function cleanContextForImports () { __define = global.define diff --git a/app/scripts/popup-core.js b/app/scripts/popup-core.js index 5a5fa95f9..69fbcf49c 100644 --- a/app/scripts/popup-core.js +++ b/app/scripts/popup-core.js @@ -12,7 +12,7 @@ module.exports = initializePopup /** * Asynchronously initializes the MetaMask popup UI * - * @param {{ container: Element, connectionStream: any }} config Popup configuration object + * @param {{ container: Element, connectionStream: * }} config Popup configuration object * @param {Function} cb Called when initialization is comlete */ function initializePopup ({ container, connectionStream }, cb) { @@ -26,7 +26,7 @@ function initializePopup ({ container, connectionStream }, cb) { /** * Establishes streamed connections to background scripts and a Web3 provider * - * @param {any} connectionStream PortStream instance establishing a background connection + * @param {*} connectionStream PortStream instance establishing a background connection * @param {Function} cb Called when controller connection is established */ function connectToAccountManager (connectionStream, cb) { @@ -41,7 +41,7 @@ function connectToAccountManager (connectionStream, cb) { /** * Establishes a streamed connection to a Web3 provider * - * @param {any} connectionStream PortStream instance establishing a background connection + * @param {*} connectionStream PortStream instance establishing a background connection */ function setupWeb3Connection (connectionStream) { var providerStream = new StreamProvider() @@ -56,7 +56,7 @@ function setupWeb3Connection (connectionStream) { /** * Establishes a streamed connection to the background account manager * - * @param {any} connectionStream PortStream instance establishing a background connection + * @param {*} connectionStream PortStream instance establishing a background connection * @param {Function} cb Called when the remote account manager connection is established */ function setupControllerConnection (connectionStream, cb) { diff --git a/docs/jsdocs/ComposableObservableStore.html b/docs/jsdocs/ComposableObservableStore.html deleted file mode 100644 index fa0807608..000000000 --- a/docs/jsdocs/ComposableObservableStore.html +++ /dev/null @@ -1,541 +0,0 @@ - - - - - - - ComposableObservableStore - Documentation - - - - - - - - - - - - - - - - - - - - - -
      - -

      ComposableObservableStore

      - - - - - - - -
      - -
      - -

      - ComposableObservableStore -

      - -

      An ObservableStore that can composes a flat -structure of child stores based on configuration

      - - -
      - -
      -
      - - - - -

      Constructor

      - - -

      new ComposableObservableStore(initStateopt, configopt)

      - - - - - - -
      - - -
      Source:
      -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      - - - - - -
      -

      Create a new store

      -
      - - - - - - - - - - - -
      Parameters:
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      NameTypeAttributesDescription
      initState - - -Object - - - - - - <optional>
      - - - - - -

      The initial store state

      config - - -Object - - - - - - <optional>
      - - - - - -

      Map of internal state keys to child stores

      - - - - - - - - - - - - - - - - - -
      - - - - - - - - - - - - - - -

      Methods

      - - - - - - -

      getFlatState() → {Object}

      - - - - - - -
      - - -
      Source:
      -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      - - - - - -
      -

      Merges all child store state into a single object rather than -returning an object keyed by child store class name

      -
      - - - - - - - - - - - - - - - - - - - - - - - -
      Returns:
      - - -
      -
        -
      • Object containing merged child store state
      • -
      -
      - - - -
      -
      - Type -
      -
      - -Object - - -
      -
      - - - - - - - - - -

      updateStructure(configopt)

      - - - - - - -
      - - -
      Source:
      -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      - - - - - -
      -

      Composes a new internal store subscription structure

      -
      - - - - - - - - - - - -
      Parameters:
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      NameTypeAttributesDescription
      config - - -Object - - - - - - <optional>
      - - - - - -

      Map of internal state keys to child stores

      - - - - - - - - - - - - - - - - - - - - - - -
      - -
      - - - - -
      - -
      - -
      - Documentation generated by JSDoc 3.5.5 on Wed Apr 18 2018 17:21:38 GMT-0400 (EDT) using the radgrad jsdoc theme. Derived from docdash. -
      - - - - - - \ No newline at end of file diff --git a/docs/jsdocs/EdgeEncryptor.html b/docs/jsdocs/EdgeEncryptor.html deleted file mode 100644 index 538b14291..000000000 --- a/docs/jsdocs/EdgeEncryptor.html +++ /dev/null @@ -1,545 +0,0 @@ - - - - - - - EdgeEncryptor - Documentation - - - - - - - - - - - - - - - - - - - - - -
      - -

      EdgeEncryptor

      - - - - - - - -
      - -
      - -

      - EdgeEncryptor -

      - -

      A Microsoft Edge-specific encryption class that exposes -the interface expected by eth-keykeyring-controller

      - - -
      - -
      -
      - - - - -

      Constructor

      - - -

      new EdgeEncryptor()

      - - - - - - -
      - - -
      Source:
      -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      - - - - - - - - - - - - - - -

      Methods

      - - - - - - -

      decrypt(password, text) → {Promise.<Object>}

      - - - - - - -
      - - -
      Source:
      -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      - - - - - -
      -

      Decrypts an arbitrary JavaScript object from cypher text

      -
      - - - - - - - - - - - -
      Parameters:
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      NameTypeDescription
      password - - -string - - - -

      Password used to unlock a cryptographic key

      text - - -string - - - -

      Cypher text of an encrypted JavaScript object

      - - - - - - - - - - - - - - -
      Returns:
      - - -
      -

      Promise resolving to copy of decrypted JavaScript object

      -
      - - - -
      -
      - Type -
      -
      - -Promise.<Object> - - -
      -
      - - - - - - - - - -

      encrypt(password, dataObject) → {Object}

      - - - - - - -
      - - -
      Source:
      -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      - - - - - -
      -

      Encrypts an arbitrary JavaScript object to cypher text

      -
      - - - - - - - - - - - -
      Parameters:
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      NameTypeDescription
      password - - -string - - - -

      Password used to unlock a cryptographic key

      dataObject - - -Object - - - -

      Data to encrypt

      - - - - - - - - - - - - - - -
      Returns:
      - - -
      -

      Object containing cypher text, generation vectors, and salt

      -
      - - - -
      -
      - Type -
      -
      - -Object - - -
      -
      - - - - - - - - - - -
      - -
      - - - - -
      - -
      - -
      - Documentation generated by JSDoc 3.5.5 on Wed Apr 18 2018 17:21:38 GMT-0400 (EDT) using the radgrad jsdoc theme. Derived from docdash. -
      - - - - - - \ No newline at end of file diff --git a/docs/jsdocs/TokenRatesController.html b/docs/jsdocs/TokenRatesController.html deleted file mode 100644 index 60994b685..000000000 --- a/docs/jsdocs/TokenRatesController.html +++ /dev/null @@ -1,682 +0,0 @@ - - - - - - - TokenRatesController - Documentation - - - - - - - - - - - - - - - - - - - - - -
      - -

      TokenRatesController

      - - - - - - - -
      - -
      - -

      - TokenRatesController -

      - -

      A controller that polls for token exchange -rates based on a user's current token list

      - - -
      - -
      -
      - - - - -

      Constructor

      - - -

      new TokenRatesController(configopt)

      - - - - - - -
      - - -
      Source:
      -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      - - - - - -
      -

      Creates a TokenRatesController

      -
      - - - - - - - - - - - -
      Parameters:
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      NameTypeAttributesDescription
      config - - -Object - - - - - - <optional>
      - - - - - -

      Options to configure controller

      - - - - - - - - - - - - - - - - - -
      - - - - - - - - - - - - -

      Members

      - - - -

      interval :Number

      - - - - - -
      - - -
      Source:
      -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      - - - - - - - -
      Type:
      -
        -
      • - -Number - - -
      • -
      - - - - - - - - -

      preferences :Object

      - - - - - -
      - - -
      Source:
      -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      - - - - - - - -
      Type:
      -
        -
      • - -Object - - -
      • -
      - - - - - - - - -

      tokens :Array

      - - - - - -
      - - -
      Source:
      -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      - - - - - - - -
      Type:
      -
        -
      • - -Array - - -
      • -
      - - - - - - - - - - -

      Methods

      - - - - - - -

      (async) fetchExchangeRate(address)

      - - - - - - -
      - - -
      Source:
      -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      - - - - - -
      -

      Fetches a token exchange rate by address

      -
      - - - - - - - - - - - -
      Parameters:
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      NameTypeDescription
      address - - -String - - - -

      Token contract address

      - - - - - - - - - - - - - - - - - - - - - -

      (async) updateExchangeRates()

      - - - - - - -
      - - -
      Source:
      -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      - - - - - -
      -

      Updates exchange rates for all tokens

      -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      - -
      - - - - -
      - -
      - -
      - Documentation generated by JSDoc 3.5.5 on Wed Apr 18 2018 17:21:38 GMT-0400 (EDT) using the radgrad jsdoc theme. Derived from docdash. -
      - - - - - - \ No newline at end of file diff --git a/docs/jsdocs/config.js.html b/docs/jsdocs/config.js.html deleted file mode 100644 index 425b517d1..000000000 --- a/docs/jsdocs/config.js.html +++ /dev/null @@ -1,148 +0,0 @@ - - - - - - - config.js - Documentation - - - - - - - - - - - - - - - - - - - - - -
      - -

      config.js

      - - - - - - - -
      -
      -
      const MAINET_RPC_URL = 'https://mainnet.infura.io/metamask'
      -const ROPSTEN_RPC_URL = 'https://ropsten.infura.io/metamask'
      -const KOVAN_RPC_URL = 'https://kovan.infura.io/metamask'
      -const RINKEBY_RPC_URL = 'https://rinkeby.infura.io/metamask'
      -const LOCALHOST_RPC_URL = 'http://localhost:8545'
      -
      -const MAINET_RPC_URL_BETA = 'https://mainnet.infura.io/metamask2'
      -const ROPSTEN_RPC_URL_BETA = 'https://ropsten.infura.io/metamask2'
      -const KOVAN_RPC_URL_BETA = 'https://kovan.infura.io/metamask2'
      -const RINKEBY_RPC_URL_BETA = 'https://rinkeby.infura.io/metamask2'
      -
      -const DEFAULT_RPC = 'rinkeby'
      -const OLD_UI_NETWORK_TYPE = 'network'
      -const BETA_UI_NETWORK_TYPE = 'networkBeta'
      -
      -global.METAMASK_DEBUG = process.env.METAMASK_DEBUG
      -
      -/**
      - * @typedef {Object} UrlConfig
      - * @property {string} localhost URL of local RPC provider
      - * @property {string} mainnet URL of mainnet RPC provider
      - * @property {string} ropsten URL of Ropsten testnet RPC provider
      - * @property {string} kovan URL of Kovan testnet RPC provider
      - * @property {string} rinkeby URL of Rinkeby testnet RPC provider
      - */
      -
      -/**
      - * @typedef {Object} NameConfig
      - * @property {string} 3 URL of local RPC provider
      - * @property {string} 4 URL of mainnet RPC provider
      - * @property {string} 42 URL of Ropsten testnet RPC provider
      - */
      -
      -/**
      - * @typedef {Object} EnumConfig
      - * @property {string} DEFAULT_RPC Default network provider URL
      - * @property {string} OLD_UI_NETWORK_TYPE
      - * @property {string} BETA_UI_NETWORK_TYPE
      - */
      -
      -/**
      - * @typedef {Object} Config
      - * @property {UrlConfig} network Network configuration parameters
      - * @property {UrlConfig} networkBeta Beta UI network configuration parameters
      - * @property {NameConfig} networkNames Network name configuration parameters
      - * @property {EnumConfig} enums Application-wide string constants
      - */
      -
      -/**
      - * @type {Config}
      - **/
      -const config = {
      -  network: {
      -    localhost: LOCALHOST_RPC_URL,
      -    mainnet: MAINET_RPC_URL,
      -    ropsten: ROPSTEN_RPC_URL,
      -    kovan: KOVAN_RPC_URL,
      -    rinkeby: RINKEBY_RPC_URL,
      -  },
      -  networkBeta: {
      -    localhost: LOCALHOST_RPC_URL,
      -    mainnet: MAINET_RPC_URL_BETA,
      -    ropsten: ROPSTEN_RPC_URL_BETA,
      -    kovan: KOVAN_RPC_URL_BETA,
      -    rinkeby: RINKEBY_RPC_URL_BETA,
      -  },
      -  networkNames: {
      -    3: 'Ropsten',
      -    4: 'Rinkeby',
      -    42: 'Kovan',
      -  },
      -  enums: {
      -    DEFAULT_RPC,
      -    OLD_UI_NETWORK_TYPE,
      -    BETA_UI_NETWORK_TYPE,
      -  },
      -}
      -
      -module.exports = config
      -
      -
      -
      - - - - -
      - -
      - -
      - Documentation generated by JSDoc 3.5.5 on Wed Apr 18 2018 17:21:38 GMT-0400 (EDT) using the radgrad jsdoc theme. Derived from docdash. -
      - - - - - - diff --git a/docs/jsdocs/contentscript.js.html b/docs/jsdocs/contentscript.js.html deleted file mode 100644 index 0a798e81c..000000000 --- a/docs/jsdocs/contentscript.js.html +++ /dev/null @@ -1,265 +0,0 @@ - - - - - - - contentscript.js - Documentation - - - - - - - - - - - - - - - - - - - - - -
      - -

      contentscript.js

      - - - - - - - -
      -
      -
      const fs = require('fs')
      -const path = require('path')
      -const pump = require('pump')
      -const LocalMessageDuplexStream = require('post-message-stream')
      -const PongStream = require('ping-pong-stream/pong')
      -const ObjectMultiplex = require('obj-multiplex')
      -const extension = require('extensionizer')
      -const PortStream = require('./lib/port-stream.js')
      -
      -const inpageContent = fs.readFileSync(path.join(__dirname, '..', '..', 'dist', 'chrome', 'inpage.js')).toString()
      -const inpageSuffix = '//# sourceURL=' + extension.extension.getURL('inpage.js') + '\n'
      -const inpageBundle = inpageContent + inpageSuffix
      -
      -// Eventually this streaming injection could be replaced with:
      -// https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Language_Bindings/Components.utils.exportFunction
      -//
      -// But for now that is only Firefox
      -// If we create a FireFox-only code path using that API,
      -// MetaMask will be much faster loading and performant on Firefox.
      -
      -if (shouldInjectWeb3()) {
      -  setupInjection()
      -  setupStreams()
      -}
      -
      -/**
      - * Creates a script tag that injects inpage.js
      - */
      -function setupInjection () {
      -  try {
      -    // inject in-page script
      -    var scriptTag = document.createElement('script')
      -    scriptTag.textContent = inpageBundle
      -    scriptTag.onload = function () { this.parentNode.removeChild(this) }
      -    var container = document.head || document.documentElement
      -    // append as first child
      -    container.insertBefore(scriptTag, container.children[0])
      -  } catch (e) {
      -    console.error('Metamask injection failed.', e)
      -  }
      -}
      -
      -/**
      - * Sets up two-way communication streams between the
      - * browser extension and local per-page browser context
      - */
      -function setupStreams () {
      -  // setup communication to page and plugin
      -  const pageStream = new LocalMessageDuplexStream({
      -    name: 'contentscript',
      -    target: 'inpage',
      -  })
      -  const pluginPort = extension.runtime.connect({ name: 'contentscript' })
      -  const pluginStream = new PortStream(pluginPort)
      -
      -  // forward communication plugin->inpage
      -  pump(
      -    pageStream,
      -    pluginStream,
      -    pageStream,
      -    (err) => logStreamDisconnectWarning('MetaMask Contentscript Forwarding', err)
      -  )
      -
      -  // setup local multistream channels
      -  const mux = new ObjectMultiplex()
      -  mux.setMaxListeners(25)
      -
      -  pump(
      -    mux,
      -    pageStream,
      -    mux,
      -    (err) => logStreamDisconnectWarning('MetaMask Inpage', err)
      -  )
      -  pump(
      -    mux,
      -    pluginStream,
      -    mux,
      -    (err) => logStreamDisconnectWarning('MetaMask Background', err)
      -  )
      -
      -  // connect ping stream
      -  const pongStream = new PongStream({ objectMode: true })
      -  pump(
      -    mux,
      -    pongStream,
      -    mux,
      -    (err) => logStreamDisconnectWarning('MetaMask PingPongStream', err)
      -  )
      -
      -  // connect phishing warning stream
      -  const phishingStream = mux.createStream('phishing')
      -  phishingStream.once('data', redirectToPhishingWarning)
      -
      -  // ignore unused channels (handled by background, inpage)
      -  mux.ignoreStream('provider')
      -  mux.ignoreStream('publicConfig')
      -}
      -
      -
      -/**
      - * Error handler for page to plugin stream disconnections
      - *
      - * @param {string} remoteLabel Remote stream name
      - * @param {Error} err Stream connection error
      - */
      -function logStreamDisconnectWarning (remoteLabel, err) {
      -  let warningMsg = `MetamaskContentscript - lost connection to ${remoteLabel}`
      -  if (err) warningMsg += '\n' + err.stack
      -  console.warn(warningMsg)
      -}
      -
      -/**
      - * Determines if Web3 should be injected
      - *
      - * @returns {boolean} True of Web3 should be injected
      - */
      -function shouldInjectWeb3 () {
      -  return doctypeCheck() && suffixCheck()
      -    && documentElementCheck() && !blacklistedDomainCheck()
      -}
      -
      -/**
      - * Checks the doctype of the current document if it exists
      - *
      - * @returns {boolean} True if the doctype is html or if none exists
      - */
      -function doctypeCheck () {
      -  const doctype = window.document.doctype
      -  if (doctype) {
      -    return doctype.name === 'html'
      -  } else {
      -    return true
      -  }
      -}
      -
      -/**
      - * Checks the current document extension
      - *
      - * @returns {boolean} True if the current extension is not prohibited
      - */
      -function suffixCheck () {
      -  var prohibitedTypes = ['xml', 'pdf']
      -  var currentUrl = window.location.href
      -  var currentRegex
      -  for (let i = 0; i < prohibitedTypes.length; i++) {
      -    currentRegex = new RegExp(`\\.${prohibitedTypes[i]}$`)
      -    if (currentRegex.test(currentUrl)) {
      -      return false
      -    }
      -  }
      -  return true
      -}
      -
      -/**
      - * Checks the documentElement of the current document
      - *
      - * @returns {boolean} True if the documentElement is an html node or if none exists
      - */
      -function documentElementCheck () {
      -  var documentElement = document.documentElement.nodeName
      -  if (documentElement) {
      -    return documentElement.toLowerCase() === 'html'
      -  }
      -  return true
      -}
      -
      -/**
      - * Checks if the current domain is blacklisted
      - * 
      - * @returns {boolean} True if the current domain is blacklisted
      - */
      -function blacklistedDomainCheck () {
      -  var blacklistedDomains = [
      -    'uscourts.gov',
      -    'dropbox.com',
      -    'webbyawards.com',
      -  ]
      -  var currentUrl = window.location.href
      -  var currentRegex
      -  for (let i = 0; i < blacklistedDomains.length; i++) {
      -    const blacklistedDomain = blacklistedDomains[i].replace('.', '\\.')
      -    currentRegex = new RegExp(`(?:https?:\\/\\/)(?:(?!${blacklistedDomain}).)*$`)
      -    if (!currentRegex.test(currentUrl)) {
      -      return true
      -    }
      -  }
      -  return false
      -}
      -
      -/**
      - * Redirects the current page to a phishing information page
      - */
      -function redirectToPhishingWarning () {
      -  console.log('MetaMask - redirecting to phishing warning')
      -  window.location.href = 'https://metamask.io/phishing.html'
      -}
      -
      -
      -
      - - - - -
      - -
      - -
      - Documentation generated by JSDoc 3.5.5 on Wed Apr 18 2018 17:21:38 GMT-0400 (EDT) using the radgrad jsdoc theme. Derived from docdash. -
      - - - - - - diff --git a/docs/jsdocs/controllers_token-rates.js.html b/docs/jsdocs/controllers_token-rates.js.html deleted file mode 100644 index 12c6d70fc..000000000 --- a/docs/jsdocs/controllers_token-rates.js.html +++ /dev/null @@ -1,146 +0,0 @@ - - - - - - - controllers/token-rates.js - Documentation - - - - - - - - - - - - - - - - - - - - - -
      - -

      controllers/token-rates.js

      - - - - - - - -
      -
      -
      const ObservableStore = require('obs-store')
      -
      -// By default, poll every 3 minutes
      -const DEFAULT_INTERVAL = 180 * 1000
      -
      -/**
      - * A controller that polls for token exchange
      - * rates based on a user's current token list
      - */
      -class TokenRatesController {
      -  /**
      -   * Creates a TokenRatesController
      -   *
      -   * @param {Object} [config] - Options to configure controller
      -   */
      -  constructor ({ interval = DEFAULT_INTERVAL, preferences } = {}) {
      -    this.store = new ObservableStore()
      -    this.preferences = preferences
      -    this.interval = interval
      -  }
      -
      -  /**
      -   * Updates exchange rates for all tokens
      -   */
      -  async updateExchangeRates () {
      -    if (!this.isActive) { return }
      -    const contractExchangeRates = {}
      -    for (const i in this._tokens) {
      -      const address = this._tokens[i].address
      -      contractExchangeRates[address] = await this.fetchExchangeRate(address)
      -    }
      -    this.store.putState({ contractExchangeRates })
      -  }
      -
      -  /**
      -   * Fetches a token exchange rate by address
      -   *
      -   * @param {String} address - Token contract address
      -   */
      -  async fetchExchangeRate (address) {
      -    try {
      -      const response = await fetch(`https://exchanges.balanc3.net/prices?from=${address}&to=ETH&autoConversion=false&summaryOnly=true`)
      -      const json = await response.json()
      -      return json && json.length ? json[0].averagePrice : 0
      -    } catch (error) { }
      -  }
      -
      -  /**
      -   * @type {Number}
      -   */
      -  set interval (interval) {
      -    this._handle && clearInterval(this._handle)
      -    if (!interval) { return }
      -    this._handle = setInterval(() => { this.updateExchangeRates() }, interval)
      -  }
      -
      -  /**
      -   * @type {Object}
      -   */
      -  set preferences (preferences) {
      -    this._preferences && this._preferences.unsubscribe()
      -    if (!preferences) { return }
      -    this._preferences = preferences
      -    this.tokens = preferences.getState().tokens
      -    preferences.subscribe(({ tokens = [] }) => { this.tokens = tokens })
      -  }
      -
      -  /**
      -   * @type {Array}
      -   */
      -  set tokens (tokens) {
      -    this._tokens = tokens
      -    this.updateExchangeRates()
      -  }
      -}
      -
      -module.exports = TokenRatesController
      -
      -
      -
      - - - - -
      - -
      - -
      - Documentation generated by JSDoc 3.5.5 on Wed Apr 18 2018 17:21:38 GMT-0400 (EDT) using the radgrad jsdoc theme. Derived from docdash. -
      - - - - - - diff --git a/docs/jsdocs/controllers_transactions.js.html b/docs/jsdocs/controllers_transactions.js.html deleted file mode 100644 index f86d3aa48..000000000 --- a/docs/jsdocs/controllers_transactions.js.html +++ /dev/null @@ -1,471 +0,0 @@ - - - - - - - controllers/transactions.js - Documentation - - - - - - - - - - - - - - - - - - - - - -
      - -

      controllers/transactions.js

      - - - - - - - -
      -
      -
      const EventEmitter = require('events')
      -const ObservableStore = require('obs-store')
      -const ethUtil = require('ethereumjs-util')
      -/**
      - * @file      The transaction controller. Receives incoming transactions, and emits events for various states of their processing.
      - * @copyright Copyright (c) 2018 MetaMask
      - * @license   MIT
      - */
      -
      -
      -const Transaction = require('ethereumjs-tx')
      -const EthQuery = require('ethjs-query')
      -const TransactionStateManager = require('../lib/tx-state-manager')
      -const TxGasUtil = require('../lib/tx-gas-utils')
      -const PendingTransactionTracker = require('../lib/pending-tx-tracker')
      -const NonceTracker = require('../lib/nonce-tracker')
      -
      -/*
      -  Transaction Controller is an aggregate of sub-controllers and trackers
      -  composing them in a way to be exposed to the metamask controller
      -    - txStateManager
      -      responsible for the state of a transaction and
      -      storing the transaction
      -    - pendingTxTracker
      -      watching blocks for transactions to be include
      -      and emitting confirmed events
      -    - txGasUtil
      -      gas calculations and safety buffering
      -    - nonceTracker
      -      calculating nonces
      -*/
      -
      -module.exports = class TransactionController extends EventEmitter {
      -  constructor (opts) {
      -    super()
      -    this.networkStore = opts.networkStore || new ObservableStore({})
      -    this.preferencesStore = opts.preferencesStore || new ObservableStore({})
      -    this.provider = opts.provider
      -    this.blockTracker = opts.blockTracker
      -    this.signEthTx = opts.signTransaction
      -    this.getGasPrice = opts.getGasPrice
      -
      -    this.memStore = new ObservableStore({})
      -    this.query = new EthQuery(this.provider)
      -    this.txGasUtil = new TxGasUtil(this.provider)
      -
      -    this.txStateManager = new TransactionStateManager({
      -      initState: opts.initState,
      -      txHistoryLimit: opts.txHistoryLimit,
      -      getNetwork: this.getNetwork.bind(this),
      -    })
      -
      -    this.txStateManager.getFilteredTxList({
      -      status: 'unapproved',
      -      loadingDefaults: true,
      -    }).forEach((tx) => {
      -      this.addTxDefaults(tx)
      -      .then((txMeta) => {
      -        txMeta.loadingDefaults = false
      -        this.txStateManager.updateTx(txMeta, 'transactions: gas estimation for tx on boot')
      -      }).catch((error) => {
      -        this.txStateManager.setTxStatusFailed(tx.id, error)
      -      })
      -    })
      -
      -    this.txStateManager.getFilteredTxList({
      -      status: 'approved',
      -    }).forEach((txMeta) => {
      -      const txSignError = new Error('Transaction found as "approved" during boot - possibly stuck during signing')
      -      this.txStateManager.setTxStatusFailed(txMeta.id, txSignError)
      -    })
      -
      -
      -    this.store = this.txStateManager.store
      -    this.txStateManager.on('tx:status-update', this.emit.bind(this, 'tx:status-update'))
      -    this.nonceTracker = new NonceTracker({
      -      provider: this.provider,
      -      getPendingTransactions: this.txStateManager.getPendingTransactions.bind(this.txStateManager),
      -      getConfirmedTransactions: (address) => {
      -        return this.txStateManager.getFilteredTxList({
      -          from: address,
      -          status: 'confirmed',
      -          err: undefined,
      -        })
      -      },
      -    })
      -
      -    this.pendingTxTracker = new PendingTransactionTracker({
      -      provider: this.provider,
      -      nonceTracker: this.nonceTracker,
      -      publishTransaction: (rawTx) => this.query.sendRawTransaction(rawTx),
      -      getPendingTransactions: this.txStateManager.getPendingTransactions.bind(this.txStateManager),
      -      getCompletedTransactions: this.txStateManager.getConfirmedTransactions.bind(this.txStateManager),
      -    })
      -
      -    this.txStateManager.store.subscribe(() => this.emit('update:badge'))
      -
      -    this.pendingTxTracker.on('tx:warning', (txMeta) => {
      -      this.txStateManager.updateTx(txMeta, 'transactions/pending-tx-tracker#event: tx:warning')
      -    })
      -    this.pendingTxTracker.on('tx:confirmed', (txId) => this._markNonceDuplicatesDropped(txId))
      -    this.pendingTxTracker.on('tx:failed', this.txStateManager.setTxStatusFailed.bind(this.txStateManager))
      -    this.pendingTxTracker.on('tx:block-update', (txMeta, latestBlockNumber) => {
      -      if (!txMeta.firstRetryBlockNumber) {
      -        txMeta.firstRetryBlockNumber = latestBlockNumber
      -        this.txStateManager.updateTx(txMeta, 'transactions/pending-tx-tracker#event: tx:block-update')
      -      }
      -    })
      -    this.pendingTxTracker.on('tx:retry', (txMeta) => {
      -      if (!('retryCount' in txMeta)) txMeta.retryCount = 0
      -      txMeta.retryCount++
      -      this.txStateManager.updateTx(txMeta, 'transactions/pending-tx-tracker#event: tx:retry')
      -    })
      -
      -    this.blockTracker.on('block', this.pendingTxTracker.checkForTxInBlock.bind(this.pendingTxTracker))
      -    // this is a little messy but until ethstore has been either
      -    // removed or redone this is to guard against the race condition
      -    this.blockTracker.on('latest', this.pendingTxTracker.resubmitPendingTxs.bind(this.pendingTxTracker))
      -    this.blockTracker.on('sync', this.pendingTxTracker.queryPendingTxs.bind(this.pendingTxTracker))
      -    // memstore is computed from a few different stores
      -    this._updateMemstore()
      -    this.txStateManager.store.subscribe(() => this._updateMemstore())
      -    this.networkStore.subscribe(() => this._updateMemstore())
      -    this.preferencesStore.subscribe(() => this._updateMemstore())
      -  }
      -
      -  getState () {
      -    return this.memStore.getState()
      -  }
      -
      -  getNetwork () {
      -    return this.networkStore.getState()
      -  }
      -
      -  getSelectedAddress () {
      -    return this.preferencesStore.getState().selectedAddress
      -  }
      -
      -  getUnapprovedTxCount () {
      -    return Object.keys(this.txStateManager.getUnapprovedTxList()).length
      -  }
      -
      -  getPendingTxCount (account) {
      -    return this.txStateManager.getPendingTransactions(account).length
      -  }
      -
      -  getFilteredTxList (opts) {
      -    return this.txStateManager.getFilteredTxList(opts)
      -  }
      -
      -  getChainId () {
      -    const networkState = this.networkStore.getState()
      -    const getChainId = parseInt(networkState)
      -    if (Number.isNaN(getChainId)) {
      -      return 0
      -    } else {
      -      return getChainId
      -    }
      -  }
      -
      -  wipeTransactions (address) {
      -    this.txStateManager.wipeTransactions(address)
      -  }
      -
      -  // Adds a tx to the txlist
      -  addTx (txMeta) {
      -    this.txStateManager.addTx(txMeta)
      -    this.emit(`${txMeta.id}:unapproved`, txMeta)
      -  }
      -
      -  async newUnapprovedTransaction (txParams, opts = {}) {
      -    log.debug(`MetaMaskController newUnapprovedTransaction ${JSON.stringify(txParams)}`)
      -    const initialTxMeta = await this.addUnapprovedTransaction(txParams)
      -    initialTxMeta.origin = opts.origin
      -    this.txStateManager.updateTx(initialTxMeta, '#newUnapprovedTransaction - adding the origin')
      -    // listen for tx completion (success, fail)
      -    return new Promise((resolve, reject) => {
      -      this.txStateManager.once(`${initialTxMeta.id}:finished`, (finishedTxMeta) => {
      -        switch (finishedTxMeta.status) {
      -          case 'submitted':
      -            return resolve(finishedTxMeta.hash)
      -          case 'rejected':
      -            return reject(new Error('MetaMask Tx Signature: User denied transaction signature.'))
      -          case 'failed':
      -            return reject(new Error(finishedTxMeta.err.message))
      -          default:
      -            return reject(new Error(`MetaMask Tx Signature: Unknown problem: ${JSON.stringify(finishedTxMeta.txParams)}`))
      -        }
      -      })
      -    })
      -  }
      -
      -  async addUnapprovedTransaction (txParams) {
      -    // validate
      -    const normalizedTxParams = this._normalizeTxParams(txParams)
      -    this._validateTxParams(normalizedTxParams)
      -    // construct txMeta
      -    let txMeta = this.txStateManager.generateTxMeta({ txParams: normalizedTxParams })
      -    this.addTx(txMeta)
      -    this.emit('newUnapprovedTx', txMeta)
      -    // add default tx params
      -    try {
      -      txMeta = await this.addTxDefaults(txMeta)
      -    } catch (error) {
      -      console.log(error)
      -      this.txStateManager.setTxStatusFailed(txMeta.id, error)
      -      throw error
      -    }
      -    txMeta.loadingDefaults = false
      -    // save txMeta
      -    this.txStateManager.updateTx(txMeta)
      -
      -    return txMeta
      -  }
      -
      -  async addTxDefaults (txMeta) {
      -    const txParams = txMeta.txParams
      -    // ensure value
      -    txMeta.gasPriceSpecified = Boolean(txParams.gasPrice)
      -    let gasPrice = txParams.gasPrice
      -    if (!gasPrice) {
      -      gasPrice = this.getGasPrice ? this.getGasPrice() : await this.query.gasPrice()
      -    }
      -    txParams.gasPrice = ethUtil.addHexPrefix(gasPrice.toString(16))
      -    txParams.value = txParams.value || '0x0'
      -    // set gasLimit
      -    return await this.txGasUtil.analyzeGasUsage(txMeta)
      -  }
      -
      -  async retryTransaction (originalTxId) {
      -    const originalTxMeta = this.txStateManager.getTx(originalTxId)
      -    const lastGasPrice = originalTxMeta.txParams.gasPrice
      -    const txMeta = this.txStateManager.generateTxMeta({
      -      txParams: originalTxMeta.txParams,
      -      lastGasPrice,
      -      loadingDefaults: false,
      -    })
      -    this.addTx(txMeta)
      -    this.emit('newUnapprovedTx', txMeta)
      -    return txMeta
      -  }
      -
      -  async updateTransaction (txMeta) {
      -    this.txStateManager.updateTx(txMeta, 'confTx: user updated transaction')
      -  }
      -
      -  async updateAndApproveTransaction (txMeta) {
      -    this.txStateManager.updateTx(txMeta, 'confTx: user approved transaction')
      -    await this.approveTransaction(txMeta.id)
      -  }
      -
      -  async approveTransaction (txId) {
      -    let nonceLock
      -    try {
      -      // approve
      -      this.txStateManager.setTxStatusApproved(txId)
      -      // get next nonce
      -      const txMeta = this.txStateManager.getTx(txId)
      -      const fromAddress = txMeta.txParams.from
      -      // wait for a nonce
      -      nonceLock = await this.nonceTracker.getNonceLock(fromAddress)
      -      // add nonce to txParams
      -      // if txMeta has lastGasPrice then it is a retry at same nonce with higher
      -      // gas price transaction and their for the nonce should not be calculated
      -      const nonce = txMeta.lastGasPrice ? txMeta.txParams.nonce : nonceLock.nextNonce
      -      txMeta.txParams.nonce = ethUtil.addHexPrefix(nonce.toString(16))
      -      // add nonce debugging information to txMeta
      -      txMeta.nonceDetails = nonceLock.nonceDetails
      -      this.txStateManager.updateTx(txMeta, 'transactions#approveTransaction')
      -      // sign transaction
      -      const rawTx = await this.signTransaction(txId)
      -      await this.publishTransaction(txId, rawTx)
      -      // must set transaction to submitted/failed before releasing lock
      -      nonceLock.releaseLock()
      -    } catch (err) {
      -      this.txStateManager.setTxStatusFailed(txId, err)
      -      // must set transaction to submitted/failed before releasing lock
      -      if (nonceLock) nonceLock.releaseLock()
      -      // continue with error chain
      -      throw err
      -    }
      -  }
      -
      -  async signTransaction (txId) {
      -    const txMeta = this.txStateManager.getTx(txId)
      -    // add network/chain id
      -    const chainId = this.getChainId()
      -    const txParams = Object.assign({}, txMeta.txParams, { chainId })
      -    // sign tx
      -    const fromAddress = txParams.from
      -    const ethTx = new Transaction(txParams)
      -    await this.signEthTx(ethTx, fromAddress)
      -    // set state to signed
      -    this.txStateManager.setTxStatusSigned(txMeta.id)
      -    const rawTx = ethUtil.bufferToHex(ethTx.serialize())
      -    return rawTx
      -  }
      -
      -  async publishTransaction (txId, rawTx) {
      -    const txMeta = this.txStateManager.getTx(txId)
      -    txMeta.rawTx = rawTx
      -    this.txStateManager.updateTx(txMeta, 'transactions#publishTransaction')
      -    const txHash = await this.query.sendRawTransaction(rawTx)
      -    this.setTxHash(txId, txHash)
      -    this.txStateManager.setTxStatusSubmitted(txId)
      -  }
      -
      -  async cancelTransaction (txId) {
      -    this.txStateManager.setTxStatusRejected(txId)
      -  }
      -
      -  // receives a txHash records the tx as signed
      -  setTxHash (txId, txHash) {
      -    // Add the tx hash to the persisted meta-tx object
      -    const txMeta = this.txStateManager.getTx(txId)
      -    txMeta.hash = txHash
      -    this.txStateManager.updateTx(txMeta, 'transactions#setTxHash')
      -  }
      -
      -//
      -//           PRIVATE METHODS
      -//
      -
      -  _normalizeTxParams (txParams) {
      -    // functions that handle normalizing of that key in txParams
      -    const whiteList = {
      -      from: from => ethUtil.addHexPrefix(from).toLowerCase(),
      -      to: to => ethUtil.addHexPrefix(txParams.to).toLowerCase(),
      -      nonce: nonce => ethUtil.addHexPrefix(nonce),
      -      value: value => ethUtil.addHexPrefix(value),
      -      data: data => ethUtil.addHexPrefix(data),
      -      gas: gas => ethUtil.addHexPrefix(gas),
      -      gasPrice: gasPrice => ethUtil.addHexPrefix(gasPrice),
      -    }
      -
      -    // apply only keys in the whiteList
      -    const normalizedTxParams = {}
      -    Object.keys(whiteList).forEach((key) => {
      -      if (txParams[key]) normalizedTxParams[key] = whiteList[key](txParams[key])
      -    })
      -
      -    return normalizedTxParams
      -  }
      -
      -  _validateTxParams (txParams) {
      -    this._validateFrom(txParams)
      -    this._validateRecipient(txParams)
      -    if ('value' in txParams) {
      -      const value = txParams.value.toString()
      -      if (value.includes('-')) {
      -        throw new Error(`Invalid transaction value of ${txParams.value} not a positive number.`)
      -      }
      -
      -      if (value.includes('.')) {
      -        throw new Error(`Invalid transaction value of ${txParams.value} number must be in wei`)
      -      }
      -    }
      -  }
      -
      -  _validateFrom (txParams) {
      -    if ( !(typeof txParams.from === 'string') ) throw new Error(`Invalid from address ${txParams.from} not a string`)
      -    if (!ethUtil.isValidAddress(txParams.from)) throw new Error('Invalid from address')
      -  }
      -
      -  _validateRecipient (txParams) {
      -    if (txParams.to === '0x' || txParams.to === null ) {
      -      if (txParams.data) {
      -        delete txParams.to
      -      } else {
      -        throw new Error('Invalid recipient address')
      -      }
      -    } else if ( txParams.to !== undefined && !ethUtil.isValidAddress(txParams.to) ) {
      -      throw new Error('Invalid recipient address')
      -    }
      -    return txParams
      -  }
      -
      -  _markNonceDuplicatesDropped (txId) {
      -    this.txStateManager.setTxStatusConfirmed(txId)
      -    // get the confirmed transactions nonce and from address
      -    const txMeta = this.txStateManager.getTx(txId)
      -    const { nonce, from } = txMeta.txParams
      -    const sameNonceTxs = this.txStateManager.getFilteredTxList({nonce, from})
      -    if (!sameNonceTxs.length) return
      -    // mark all same nonce transactions as dropped and give i a replacedBy hash
      -    sameNonceTxs.forEach((otherTxMeta) => {
      -      if (otherTxMeta.id === txId) return
      -      otherTxMeta.replacedBy = txMeta.hash
      -      this.txStateManager.updateTx(txMeta, 'transactions/pending-tx-tracker#event: tx:confirmed reference to confirmed txHash with same nonce')
      -      this.txStateManager.setTxStatusDropped(otherTxMeta.id)
      -    })
      -  }
      -
      -  _updateMemstore () {
      -    const unapprovedTxs = this.txStateManager.getUnapprovedTxList()
      -    const selectedAddressTxList = this.txStateManager.getFilteredTxList({
      -      from: this.getSelectedAddress(),
      -      metamaskNetworkId: this.getNetwork(),
      -    })
      -    this.memStore.updateState({ unapprovedTxs, selectedAddressTxList })
      -  }
      -}
      -
      -
      -
      - - - - -
      - -
      - -
      - Documentation generated by JSDoc 3.5.5 on Thu Apr 12 2018 14:37:39 GMT-0700 (PDT) using the radgrad jsdoc theme. Derived from docdash. -
      - - - - - - diff --git a/docs/jsdocs/edge-encryptor.js.html b/docs/jsdocs/edge-encryptor.js.html deleted file mode 100644 index e85f444b4..000000000 --- a/docs/jsdocs/edge-encryptor.js.html +++ /dev/null @@ -1,166 +0,0 @@ - - - - - - - edge-encryptor.js - Documentation - - - - - - - - - - - - - - - - - - - - - -
      - -

      edge-encryptor.js

      - - - - - - - -
      -
      -
      const asmcrypto = require('asmcrypto.js')
      -const Unibabel = require('browserify-unibabel')
      -
      -/**
      - * A Microsoft Edge-specific encryption class that exposes
      - * the interface expected by eth-keykeyring-controller
      - */
      -class EdgeEncryptor {
      -  /**
      -   * Encrypts an arbitrary JavaScript object to cypher text
      -   *
      -   * @param {string} password Password used to unlock a cryptographic key
      -   * @param {Object} dataObject Data to encrypt
      -   * @returns {Object} Object containing cypher text, generation vectors, and salt
      -   */
      -  encrypt (password, dataObject) {
      -      var salt = this._generateSalt()
      -      return this._keyFromPassword(password, salt)
      -          .then(function (key) {
      -              var data = JSON.stringify(dataObject)
      -              var dataBuffer = Unibabel.utf8ToBuffer(data)
      -              var vector = global.crypto.getRandomValues(new Uint8Array(16))
      -              var resultbuffer = asmcrypto.AES_GCM.encrypt(dataBuffer, key, vector)
      -
      -              var buffer = new Uint8Array(resultbuffer)
      -              var vectorStr = Unibabel.bufferToBase64(vector)
      -              var vaultStr = Unibabel.bufferToBase64(buffer)
      -              return JSON.stringify({
      -                  data: vaultStr,
      -                  iv: vectorStr,
      -                  salt: salt,
      -              })
      -          })
      -  }
      -
      -  /**
      -   * Decrypts an arbitrary JavaScript object from cypher text
      -   *
      -   * @param {string} password Password used to unlock a cryptographic key
      -   * @param {string} text Cypher text of an encrypted JavaScript object
      -   * @returns {Promise<Object>} Promise resolving to copy of decrypted JavaScript object
      -   */
      -  decrypt (password, text) {
      -      const payload = JSON.parse(text)
      -      const salt = payload.salt
      -      return this._keyFromPassword(password, salt)
      -          .then(function (key) {
      -              const encryptedData = Unibabel.base64ToBuffer(payload.data)
      -              const vector = Unibabel.base64ToBuffer(payload.iv)
      -              return new Promise((resolve, reject) => {
      -                  var result
      -                  try {
      -                      result = asmcrypto.AES_GCM.decrypt(encryptedData, key, vector)
      -                  } catch (err) {
      -                      return reject(new Error('Incorrect password'))
      -                  }
      -                  const decryptedData = new Uint8Array(result)
      -                  const decryptedStr = Unibabel.bufferToUtf8(decryptedData)
      -                  const decryptedObj = JSON.parse(decryptedStr)
      -                  resolve(decryptedObj)
      -              })
      -          })
      -  }
      -
      -  /**
      -   * Retrieves a cryptographic key using a password
      -   *
      -   * @private
      -   * @param {string} password Password used to unlock a cryptographic key
      -   * @param {string} salt Random base-64 data
      -   * @returns {Promise<Object>} Promise resolving to a derived key
      -   */
      -  _keyFromPassword (password, salt) {
      -
      -      var passBuffer = Unibabel.utf8ToBuffer(password)
      -      var saltBuffer = Unibabel.base64ToBuffer(salt)
      -      return new Promise((resolve) => {
      -          var key = asmcrypto.PBKDF2_HMAC_SHA256.bytes(passBuffer, saltBuffer, 10000)
      -          resolve(key)
      -      })
      -  }
      -
      -  /**
      -   * Generates random base-64 encoded data
      -   *
      -   * @private
      -   * @returns {string} Randomized base-64 encoded data
      -   */
      -  _generateSalt (byteCount = 32) {
      -      var view = new Uint8Array(byteCount)
      -      global.crypto.getRandomValues(view)
      -      var b64encoded = btoa(String.fromCharCode.apply(null, view))
      -      return b64encoded
      -  }
      -}
      -
      -module.exports = EdgeEncryptor
      -
      -
      -
      - - - - -
      - -
      - -
      - Documentation generated by JSDoc 3.5.5 on Wed Apr 18 2018 17:21:38 GMT-0400 (EDT) using the radgrad jsdoc theme. Derived from docdash. -
      - - - - - - diff --git a/docs/jsdocs/first-time-state.js.html b/docs/jsdocs/first-time-state.js.html deleted file mode 100644 index 431846e45..000000000 --- a/docs/jsdocs/first-time-state.js.html +++ /dev/null @@ -1,92 +0,0 @@ - - - - - - - first-time-state.js - Documentation - - - - - - - - - - - - - - - - - - - - - -
      - -

      first-time-state.js

      - - - - - - - -
      -
      -
      // test and development environment variables
      -const env = process.env.METAMASK_ENV
      -const METAMASK_DEBUG = process.env.METAMASK_DEBUG
      -
      -/**
      - * @typedef {Object} FirstTimeState
      - * @property {Object} config Initial configuration parameters
      - * @property {Object} NetworkController Network controller state
      - */
      -
      -/**
      - * @type {FirstTimeState}
      - */
      -const initialState = {
      -  config: {},
      -  NetworkController: {
      -    provider: {
      -      type: (METAMASK_DEBUG || env === 'test') ? 'rinkeby' : 'mainnet',
      -    },
      -  },
      -}
      -
      -module.exports = initialState
      -
      -
      -
      - - - - -
      - -
      - -
      - Documentation generated by JSDoc 3.5.5 on Wed Apr 18 2018 17:21:38 GMT-0400 (EDT) using the radgrad jsdoc theme. Derived from docdash. -
      - - - - - - diff --git a/docs/jsdocs/global.html b/docs/jsdocs/global.html deleted file mode 100644 index 499111982..000000000 --- a/docs/jsdocs/global.html +++ /dev/null @@ -1,2883 +0,0 @@ - - - - - - - Global - Documentation - - - - - - - - - - - - - - - - - - - - - -
      - -

      Global

      - - - - - - - -
      - -
      - -

      - -

      - - -
      - -
      -
      - - - -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      - - - - - - - - -
      - - - - - - - - - - - - -

      Members

      - - - -

      (constant) config :Config

      - - - - - -
      - - -
      Source:
      -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      - - - - - - - -
      Type:
      - - - - - - - - - -

      (constant) initialState :FirstTimeState

      - - - - - -
      - - -
      Source:
      -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      - - - - - - - -
      Type:
      - - - - - - - - - - - -

      Methods

      - - - - - - -

      blacklistedDomainCheck() → {boolean}

      - - - - - - -
      - - -
      Source:
      -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      - - - - - -
      -

      Checks if the current domain is blacklisted

      -
      - - - - - - - - - - - - - - - - - - - - - - - -
      Returns:
      - - -
      -

      True if the current domain is blacklisted

      -
      - - - -
      -
      - Type -
      -
      - -boolean - - -
      -
      - - - - - - - - - -

      cleanContextForImports()

      - - - - - - -
      - - -
      Source:
      -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      - - - - - -
      -

      Caches reference to global define object and deletes it

      -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

      connectToAccountManager(connectionStream, cb)

      - - - - - - -
      - - -
      Source:
      -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      - - - - - -
      -

      Establishes streamed connections to background scripts and a Web3 provider

      -
      - - - - - - - - - - - -
      Parameters:
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      NameTypeDescription
      connectionStream - - -any - - - -

      PortStream instance establishing a background connection

      cb - - -function - - - -

      Called when controller connection is established

      - - - - - - - - - - - - - - - - - - - - - -

      doctypeCheck() → {boolean}

      - - - - - - -
      - - -
      Source:
      -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      - - - - - -
      -

      Checks the doctype of the current document if it exists

      -
      - - - - - - - - - - - - - - - - - - - - - - - -
      Returns:
      - - -
      -

      True if the doctype is html or if none exists

      -
      - - - -
      -
      - Type -
      -
      - -boolean - - -
      -
      - - - - - - - - - -

      documentElementCheck() → {boolean}

      - - - - - - -
      - - -
      Source:
      -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      - - - - - -
      -

      Checks the documentElement of the current document

      -
      - - - - - - - - - - - - - - - - - - - - - - - -
      Returns:
      - - -
      -

      True if the documentElement is an html node or if none exists

      -
      - - - -
      -
      - Type -
      -
      - -boolean - - -
      -
      - - - - - - - - - -

      initializePopup(config, cb)

      - - - - - - -
      - - -
      Source:
      -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      - - - - - -
      -

      Asynchronously initializes the MetaMask popup UI

      -
      - - - - - - - - - - - -
      Parameters:
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      NameTypeDescription
      config - - -Object - - - -

      Popup configuration object

      cb - - -function - - - -

      Called when initialization is comlete

      - - - - - - - - - - - - - - - - - - - - - -

      logStreamDisconnectWarning(remoteLabel, err)

      - - - - - - -
      - - -
      Source:
      -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      - - - - - -
      -

      Error handler for page to plugin stream disconnections

      -
      - - - - - - - - - - - -
      Parameters:
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      NameTypeDescription
      remoteLabel - - -string - - - -

      Remote stream name

      err - - -Error - - - -

      Stream connection error

      - - - - - - - - - - - - - - - - - - - - - -

      redirectToPhishingWarning()

      - - - - - - -
      - - -
      Source:
      -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      - - - - - -
      -

      Redirects the current page to a phishing information page

      -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

      restoreContextAfterImports()

      - - - - - - -
      - - -
      Source:
      -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      - - - - - -
      -

      Restores global define object from cached reference

      -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

      setupControllerConnection(connectionStream, cb)

      - - - - - - -
      - - -
      Source:
      -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      - - - - - -
      -

      Establishes a streamed connection to the background account manager

      -
      - - - - - - - - - - - -
      Parameters:
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      NameTypeDescription
      connectionStream - - -any - - - -

      PortStream instance establishing a background connection

      cb - - -function - - - -

      Called when the remote account manager connection is established

      - - - - - - - - - - - - - - - - - - - - - -

      setupInjection()

      - - - - - - -
      - - -
      Source:
      -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      - - - - - -
      -

      Creates a script tag that injects inpage.js

      -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

      setupStreams()

      - - - - - - -
      - - -
      Source:
      -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      - - - - - -
      -

      Sets up two-way communication streams between the -browser extension and local per-page browser context

      -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

      setupWeb3Connection(connectionStream)

      - - - - - - -
      - - -
      Source:
      -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      - - - - - -
      -

      Establishes a streamed connection to a Web3 provider

      -
      - - - - - - - - - - - -
      Parameters:
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      NameTypeDescription
      connectionStream - - -any - - - -

      PortStream instance establishing a background connection

      - - - - - - - - - - - - - - - - - - - - - -

      shouldInjectWeb3() → {boolean}

      - - - - - - -
      - - -
      Source:
      -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      - - - - - -
      -

      Determines if Web3 should be injected

      -
      - - - - - - - - - - - - - - - - - - - - - - - -
      Returns:
      - - -
      -

      True of Web3 should be injected

      -
      - - - -
      -
      - Type -
      -
      - -boolean - - -
      -
      - - - - - - - - - -

      suffixCheck() → {boolean}

      - - - - - - -
      - - -
      Source:
      -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      - - - - - -
      -

      Checks the current document extension

      -
      - - - - - - - - - - - - - - - - - - - - - - - -
      Returns:
      - - -
      -

      True if the current extension is not prohibited

      -
      - - - -
      -
      - Type -
      -
      - -boolean - - -
      -
      - - - - - - - - -

      Type Definitions

      - - - -

      Config

      - - - - - -
      - - -
      Source:
      -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      - - - -
      Properties:
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      NameTypeDescription
      network - - -UrlConfig - - - -

      Network configuration parameters

      networkBeta - - -UrlConfig - - - -

      Beta UI network configuration parameters

      networkNames - - -NameConfig - - - -

      Network name configuration parameters

      enums - - -EnumConfig - - - -

      Application-wide string constants

      - - - - - - - - -
      Type:
      -
        -
      • - -Object - - -
      • -
      - - - - - - - - -

      EnumConfig

      - - - - - -
      - - -
      Source:
      -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      - - - -
      Properties:
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      NameTypeDescription
      DEFAULT_RPC - - -string - - - -

      Default network provider URL

      OLD_UI_NETWORK_TYPE - - -string - - - -
      BETA_UI_NETWORK_TYPE - - -string - - - -
      - - - - - - - - -
      Type:
      -
        -
      • - -Object - - -
      • -
      - - - - - - - - -

      FirstTimeState

      - - - - - -
      - - -
      Source:
      -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      - - - -
      Properties:
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      NameTypeDescription
      config - - -Object - - - -

      Initial configuration parameters

      NetworkController - - -Object - - - -

      Network controller state

      - - - - - - - - -
      Type:
      -
        -
      • - -Object - - -
      • -
      - - - - - - - - -

      NameConfig

      - - - - - -
      - - -
      Source:
      -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      - - - -
      Properties:
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      NameTypeDescription
      3 - - -string - - - -

      URL of local RPC provider

      4 - - -string - - - -

      URL of mainnet RPC provider

      42 - - -string - - - -

      URL of Ropsten testnet RPC provider

      - - - - - - - - -
      Type:
      -
        -
      • - -Object - - -
      • -
      - - - - - - - - -

      UrlConfig

      - - - - - -
      - - -
      Source:
      -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      - - - -
      Properties:
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      NameTypeDescription
      localhost - - -string - - - -

      URL of local RPC provider

      mainnet - - -string - - - -

      URL of mainnet RPC provider

      ropsten - - -string - - - -

      URL of Ropsten testnet RPC provider

      kovan - - -string - - - -

      URL of Kovan testnet RPC provider

      rinkeby - - -string - - - -

      URL of Rinkeby testnet RPC provider

      - - - - - - - - -
      Type:
      -
        -
      • - -Object - - -
      • -
      - - - - - - - - - - -
      - -
      - - - - -
      - -
      - -
      - Documentation generated by JSDoc 3.5.5 on Wed Apr 18 2018 17:21:38 GMT-0400 (EDT) using the radgrad jsdoc theme. Derived from docdash. -
      - - - - - - \ No newline at end of file diff --git a/docs/jsdocs/index.html b/docs/jsdocs/index.html deleted file mode 100644 index 0d5b08d90..000000000 --- a/docs/jsdocs/index.html +++ /dev/null @@ -1,175 +0,0 @@ - - - - - - - Home - Documentation - - - - - - - - - - - - - - - - - - - - - -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      - -
      - -

      - metamask-controller.js -

      - - -
      - -
      -
      - - - -
      - - -
      Source:
      -
      - - - - - - - - - - - - - - - - - - - - - - - - - - -
      License:
      -
      • MIT
      - - - - - - - - - -
      - - - - - -

      The central metamask controller. Aggregates other controllers and exports an api.

      - - - - -
      - - - - - - - - - - - - - - - - - - -
      - -
      - - - - -
      - -
      - -
      - Documentation generated by JSDoc 3.5.5 on Wed Apr 18 2018 17:21:38 GMT-0400 (EDT) using the radgrad jsdoc theme. Derived from docdash. -
      - - - - - - \ No newline at end of file diff --git a/docs/jsdocs/inpage.js.html b/docs/jsdocs/inpage.js.html deleted file mode 100644 index acfd6223c..000000000 --- a/docs/jsdocs/inpage.js.html +++ /dev/null @@ -1,144 +0,0 @@ - - - - - - - inpage.js - Documentation - - - - - - - - - - - - - - - - - - - - - -
      - -

      inpage.js

      - - - - - - - -
      -
      -
      /*global Web3*/
      -cleanContextForImports()
      -require('web3/dist/web3.min.js')
      -const log = require('loglevel')
      -const LocalMessageDuplexStream = require('post-message-stream')
      -const setupDappAutoReload = require('./lib/auto-reload.js')
      -const MetamaskInpageProvider = require('./lib/inpage-provider.js')
      -restoreContextAfterImports()
      -
      -log.setDefaultLevel(process.env.METAMASK_DEBUG ? 'debug' : 'warn')
      -
      -//
      -// setup plugin communication
      -//
      -
      -// setup background connection
      -var metamaskStream = new LocalMessageDuplexStream({
      -  name: 'inpage',
      -  target: 'contentscript',
      -})
      -
      -// compose the inpage provider
      -var inpageProvider = new MetamaskInpageProvider(metamaskStream)
      -
      -//
      -// setup web3
      -//
      -
      -if (typeof window.web3 !== 'undefined') {
      -  throw new Error(`MetaMask detected another web3.
      -     MetaMask will not work reliably with another web3 extension.
      -     This usually happens if you have two MetaMasks installed,
      -     or MetaMask and another web3 extension. Please remove one
      -     and try again.`)
      -}
      -var web3 = new Web3(inpageProvider)
      -web3.setProvider = function () {
      -  log.debug('MetaMask - overrode web3.setProvider')
      -}
      -log.debug('MetaMask - injected web3')
      -// export global web3, with usage-detection
      -setupDappAutoReload(web3, inpageProvider.publicConfigStore)
      -
      -// set web3 defaultAccount
      -inpageProvider.publicConfigStore.subscribe(function (state) {
      -  web3.eth.defaultAccount = state.selectedAddress
      -})
      -
      -// need to make sure we aren't affected by overlapping namespaces
      -// and that we dont affect the app with our namespace
      -// mostly a fix for web3's BigNumber if AMD's "define" is defined...
      -var __define
      -
      -/**
      - * Caches reference to global define object and deletes it
      - */
      -function cleanContextForImports () {
      -  __define = global.define
      -  try {
      -    global.define = undefined
      -  } catch (_) {
      -    console.warn('MetaMask - global.define could not be deleted.')
      -  }
      -}
      -
      -/**
      - * Restores global define object from cached reference
      - */
      -function restoreContextAfterImports () {
      -  try {
      -    global.define = __define
      -  } catch (_) {
      -    console.warn('MetaMask - global.define could not be overwritten.')
      -  }
      -}
      -
      -
      -
      - - - - -
      - -
      - -
      - Documentation generated by JSDoc 3.5.5 on Wed Apr 18 2018 17:21:38 GMT-0400 (EDT) using the radgrad jsdoc theme. Derived from docdash. -
      - - - - - - diff --git a/docs/jsdocs/lib_ComposableObservableStore.js.html b/docs/jsdocs/lib_ComposableObservableStore.js.html deleted file mode 100644 index dc39a9f55..000000000 --- a/docs/jsdocs/lib_ComposableObservableStore.js.html +++ /dev/null @@ -1,118 +0,0 @@ - - - - - - - lib/ComposableObservableStore.js - Documentation - - - - - - - - - - - - - - - - - - - - - -
      - -

      lib/ComposableObservableStore.js

      - - - - - - - -
      -
      -
      const ObservableStore = require('obs-store')
      -
      -/**
      - * An ObservableStore that can composes a flat
      - * structure of child stores based on configuration
      - */
      -class ComposableObservableStore extends ObservableStore {
      -  /**
      -   * Create a new store
      -   *
      -   * @param {Object} [initState] - The initial store state
      -   * @param {Object} [config] - Map of internal state keys to child stores
      -   */
      -  constructor (initState, config) {
      -    super(initState)
      -    this.updateStructure(config)
      -  }
      -
      -  /**
      -   * Composes a new internal store subscription structure
      -   *
      -   * @param {Object} [config] - Map of internal state keys to child stores
      -   */
      -  updateStructure (config) {
      -    this.config = config
      -    this.removeAllListeners()
      -    for (const key in config) {
      -      config[key].subscribe((state) => {
      -        this.updateState({ [key]: state })
      -      })
      -    }
      -  }
      -
      -  /**
      -   * Merges all child store state into a single object rather than
      -   * returning an object keyed by child store class name
      -   *
      -   * @returns {Object} - Object containing merged child store state
      -   */
      -  getFlatState () {
      -    let flatState = {}
      -    for (const key in this.config) {
      -      flatState = { ...flatState, ...this.config[key].getState() }
      -    }
      -    return flatState
      -  }
      -}
      -
      -module.exports = ComposableObservableStore
      -
      -
      -
      - - - - -
      - -
      - -
      - Documentation generated by JSDoc 3.5.5 on Wed Apr 18 2018 17:21:38 GMT-0400 (EDT) using the radgrad jsdoc theme. Derived from docdash. -
      - - - - - - diff --git a/docs/jsdocs/metamask-controller.js.html b/docs/jsdocs/metamask-controller.js.html deleted file mode 100644 index 5f8748577..000000000 --- a/docs/jsdocs/metamask-controller.js.html +++ /dev/null @@ -1,1112 +0,0 @@ - - - - - - - metamask-controller.js - Documentation - - - - - - - - - - - - - - - - - - - - - -
      - -

      metamask-controller.js

      - - - - - - - -
      -
      -
      /**
      - * @file      The central metamask controller. Aggregates other controllers and exports an api.
      - * @copyright Copyright (c) 2018 MetaMask
      - * @license   MIT
      - */
      -
      -const EventEmitter = require('events')
      -const pump = require('pump')
      -const Dnode = require('dnode')
      -const ObservableStore = require('obs-store')
      -const ComposableObservableStore = require('./lib/ComposableObservableStore')
      -const asStream = require('obs-store/lib/asStream')
      -const AccountTracker = require('./lib/account-tracker')
      -const RpcEngine = require('json-rpc-engine')
      -const debounce = require('debounce')
      -const createEngineStream = require('json-rpc-middleware-stream/engineStream')
      -const createFilterMiddleware = require('eth-json-rpc-filters')
      -const createOriginMiddleware = require('./lib/createOriginMiddleware')
      -const createLoggerMiddleware = require('./lib/createLoggerMiddleware')
      -const createProviderMiddleware = require('./lib/createProviderMiddleware')
      -const setupMultiplex = require('./lib/stream-utils.js').setupMultiplex
      -const KeyringController = require('eth-keyring-controller')
      -const NetworkController = require('./controllers/network')
      -const PreferencesController = require('./controllers/preferences')
      -const CurrencyController = require('./controllers/currency')
      -const NoticeController = require('./notice-controller')
      -const ShapeShiftController = require('./controllers/shapeshift')
      -const AddressBookController = require('./controllers/address-book')
      -const InfuraController = require('./controllers/infura')
      -const BlacklistController = require('./controllers/blacklist')
      -const RecentBlocksController = require('./controllers/recent-blocks')
      -const MessageManager = require('./lib/message-manager')
      -const PersonalMessageManager = require('./lib/personal-message-manager')
      -const TypedMessageManager = require('./lib/typed-message-manager')
      -const TransactionController = require('./controllers/transactions')
      -const BalancesController = require('./controllers/computed-balances')
      -const TokenRatesController = require('./controllers/token-rates')
      -const ConfigManager = require('./lib/config-manager')
      -const nodeify = require('./lib/nodeify')
      -const accountImporter = require('./account-import-strategies')
      -const getBuyEthUrl = require('./lib/buy-eth-url')
      -const Mutex = require('await-semaphore').Mutex
      -const version = require('../manifest.json').version
      -const BN = require('ethereumjs-util').BN
      -const GWEI_BN = new BN('1000000000')
      -const percentile = require('percentile')
      -const seedPhraseVerifier = require('./lib/seed-phrase-verifier')
      -const log = require('loglevel')
      -
      -module.exports = class MetamaskController extends EventEmitter {
      -
      -  /**
      -   * @constructor
      -   * @param {Object} opts
      -   */
      -   constructor (opts) {
      -    super()
      -
      -    this.defaultMaxListeners = 20
      -
      -    this.sendUpdate = debounce(this.privateSendUpdate.bind(this), 200)
      -    this.opts = opts
      -    const initState = opts.initState || {}
      -    this.recordFirstTimeInfo(initState)
      -
      -    // platform-specific api
      -    this.platform = opts.platform
      -
      -    // observable state store
      -    this.store = new ComposableObservableStore(initState)
      -
      -    // lock to ensure only one vault created at once
      -    this.createVaultMutex = new Mutex()
      -
      -    // network store
      -    this.networkController = new NetworkController(initState.NetworkController)
      -
      -    // config manager
      -    this.configManager = new ConfigManager({
      -      store: this.store,
      -    })
      -
      -    // preferences controller
      -    this.preferencesController = new PreferencesController({
      -      initState: initState.PreferencesController,
      -      initLangCode: opts.initLangCode,
      -    })
      -
      -    // currency controller
      -    this.currencyController = new CurrencyController({
      -      initState: initState.CurrencyController,
      -    })
      -    this.currencyController.updateConversionRate()
      -    this.currencyController.scheduleConversionInterval()
      -
      -    // infura controller
      -    this.infuraController = new InfuraController({
      -      initState: initState.InfuraController,
      -    })
      -    this.infuraController.scheduleInfuraNetworkCheck()
      -
      -    this.blacklistController = new BlacklistController()
      -    this.blacklistController.scheduleUpdates()
      -
      -    // rpc provider
      -    this.provider = this.initializeProvider()
      -    this.blockTracker = this.provider._blockTracker
      -
      -    // token exchange rate tracker
      -    this.tokenRatesController = new TokenRatesController({
      -      preferences: this.preferencesController.store,
      -    })
      -
      -    this.recentBlocksController = new RecentBlocksController({
      -      blockTracker: this.blockTracker,
      -      provider: this.provider,
      -    })
      -
      -    // account tracker watches balances, nonces, and any code at their address.
      -    this.accountTracker = new AccountTracker({
      -      provider: this.provider,
      -      blockTracker: this.blockTracker,
      -    })
      -
      -    // key mgmt
      -    this.keyringController = new KeyringController({
      -      initState: initState.KeyringController,
      -      getNetwork: this.networkController.getNetworkState.bind(this.networkController),
      -      encryptor: opts.encryptor || undefined,
      -    })
      -
      -    // If only one account exists, make sure it is selected.
      -    this.keyringController.memStore.subscribe((state) => {
      -      const addresses = state.keyrings.reduce((res, keyring) => {
      -        return res.concat(keyring.accounts)
      -      }, [])
      -      if (addresses.length === 1) {
      -        const address = addresses[0]
      -        this.preferencesController.setSelectedAddress(address)
      -      }
      -      this.accountTracker.syncWithAddresses(addresses)
      -    })
      -
      -    // address book controller
      -    this.addressBookController = new AddressBookController({
      -      initState: initState.AddressBookController,
      -    }, this.keyringController)
      -
      -    // tx mgmt
      -    this.txController = new TransactionController({
      -      initState: initState.TransactionController || initState.TransactionManager,
      -      networkStore: this.networkController.networkStore,
      -      preferencesStore: this.preferencesController.store,
      -      txHistoryLimit: 40,
      -      getNetwork: this.networkController.getNetworkState.bind(this),
      -      signTransaction: this.keyringController.signTransaction.bind(this.keyringController),
      -      provider: this.provider,
      -      blockTracker: this.blockTracker,
      -      getGasPrice: this.getGasPrice.bind(this),
      -    })
      -    this.txController.on('newUnapprovedTx', opts.showUnapprovedTx.bind(opts))
      -
      -    // computed balances (accounting for pending transactions)
      -    this.balancesController = new BalancesController({
      -      accountTracker: this.accountTracker,
      -      txController: this.txController,
      -      blockTracker: this.blockTracker,
      -    })
      -    this.networkController.on('networkDidChange', () => {
      -      this.balancesController.updateAllBalances()
      -    })
      -    this.balancesController.updateAllBalances()
      -
      -    // notices
      -    this.noticeController = new NoticeController({
      -      initState: initState.NoticeController,
      -      version,
      -      firstVersion: initState.firstTimeInfo.version,
      -    })
      -    this.noticeController.updateNoticesList()
      -    // to be uncommented when retrieving notices from a remote server.
      -    // this.noticeController.startPolling()
      -
      -    this.shapeshiftController = new ShapeShiftController({
      -      initState: initState.ShapeShiftController,
      -    })
      -
      -    this.networkController.lookupNetwork()
      -    this.messageManager = new MessageManager()
      -    this.personalMessageManager = new PersonalMessageManager()
      -    this.typedMessageManager = new TypedMessageManager()
      -    this.publicConfigStore = this.initPublicConfigStore()
      -
      -    this.store.updateStructure({
      -      TransactionController: this.txController.store,
      -      KeyringController: this.keyringController.store,
      -      PreferencesController: this.preferencesController.store,
      -      AddressBookController: this.addressBookController.store,
      -      CurrencyController: this.currencyController.store,
      -      NoticeController: this.noticeController.store,
      -      ShapeShiftController: this.shapeshiftController.store,
      -      NetworkController: this.networkController.store,
      -      InfuraController: this.infuraController.store,
      -    })
      -
      -    this.memStore = new ComposableObservableStore(null, {
      -      NetworkController: this.networkController.store,
      -      AccountTracker: this.accountTracker.store,
      -      TxController: this.txController.memStore,
      -      BalancesController: this.balancesController.store,
      -      TokenRatesController: this.tokenRatesController.store,
      -      MessageManager: this.messageManager.memStore,
      -      PersonalMessageManager: this.personalMessageManager.memStore,
      -      TypesMessageManager: this.typedMessageManager.memStore,
      -      KeyringController: this.keyringController.memStore,
      -      PreferencesController: this.preferencesController.store,
      -      RecentBlocksController: this.recentBlocksController.store,
      -      AddressBookController: this.addressBookController.store,
      -      CurrencyController: this.currencyController.store,
      -      NoticeController: this.noticeController.memStore,
      -      ShapeshiftController: this.shapeshiftController.store,
      -      InfuraController: this.infuraController.store,
      -    })
      -    this.memStore.subscribe(this.sendUpdate.bind(this))
      -  }
      -
      -  /**
      -   * Constructor helper: initialize a provider.
      -   */
      -  initializeProvider () {
      -    const providerOpts = {
      -      static: {
      -        eth_syncing: false,
      -        web3_clientVersion: `MetaMask/v${version}`,
      -        eth_sendTransaction: (payload, next, end) => {
      -          const origin = payload.origin
      -          const txParams = payload.params[0]
      -          nodeify(this.txController.newUnapprovedTransaction, this.txController)(txParams, { origin }, end)
      -        },
      -      },
      -      // account mgmt
      -      getAccounts: (cb) => {
      -        const isUnlocked = this.keyringController.memStore.getState().isUnlocked
      -        const result = []
      -        const selectedAddress = this.preferencesController.getSelectedAddress()
      -
      -        // only show address if account is unlocked
      -        if (isUnlocked && selectedAddress) {
      -          result.push(selectedAddress)
      -        }
      -        cb(null, result)
      -      },
      -      // tx signing
      -      // old style msg signing
      -      processMessage: this.newUnsignedMessage.bind(this),
      -      // personal_sign msg signing
      -      processPersonalMessage: this.newUnsignedPersonalMessage.bind(this),
      -      processTypedMessage: this.newUnsignedTypedMessage.bind(this),
      -    }
      -    const providerProxy = this.networkController.initializeProvider(providerOpts)
      -    return providerProxy
      -  }
      -
      -  /**
      -   * Constructor helper: initialize a public config store.
      -   */
      -  initPublicConfigStore () {
      -    // get init state
      -    const publicConfigStore = new ObservableStore()
      -
      -    // memStore -> transform -> publicConfigStore
      -    this.on('update', (memState) => {
      -      this.isClientOpenAndUnlocked = memState.isUnlocked && this._isClientOpen
      -      const publicState = selectPublicState(memState)
      -      publicConfigStore.putState(publicState)
      -    })
      -
      -    function selectPublicState (memState) {
      -      const result = {
      -        selectedAddress: memState.isUnlocked ? memState.selectedAddress : undefined,
      -        networkVersion: memState.network,
      -      }
      -      return result
      -    }
      -
      -    return publicConfigStore
      -  }
      -
      -//=============================================================================
      -// EXPOSED TO THE UI SUBSYSTEM
      -//=============================================================================
      -
      -  /**
      -   * The metamask-state of the various controllers, made available to the UI
      -   *
      -   * @returns {Object} status
      -   */
      -  getState () {
      -    const wallet = this.configManager.getWallet()
      -    const vault = this.keyringController.store.getState().vault
      -    const isInitialized = (!!wallet || !!vault)
      -
      -    return {
      -      ...{ isInitialized },
      -      ...this.memStore.getFlatState(),
      -      ...this.configManager.getConfig(),
      -      ...{
      -        lostAccounts: this.configManager.getLostAccounts(),
      -        seedWords: this.configManager.getSeedWords(),
      -        forgottenPassword: this.configManager.getPasswordForgotten(),
      -      },
      -    }
      -  }
      -
      -  /**
      -   * Returns an api-object which is consumed by the UI
      -   *
      -   * @returns {Object}
      -   */
      -  getApi () {
      -    const keyringController = this.keyringController
      -    const preferencesController = this.preferencesController
      -    const txController = this.txController
      -    const noticeController = this.noticeController
      -    const addressBookController = this.addressBookController
      -    const networkController = this.networkController
      -
      -    return {
      -      // etc
      -      getState: (cb) => cb(null, this.getState()),
      -      setCurrentCurrency: this.setCurrentCurrency.bind(this),
      -      setUseBlockie: this.setUseBlockie.bind(this),
      -      setCurrentLocale: this.setCurrentLocale.bind(this),
      -      markAccountsFound: this.markAccountsFound.bind(this),
      -      markPasswordForgotten: this.markPasswordForgotten.bind(this),
      -      unMarkPasswordForgotten: this.unMarkPasswordForgotten.bind(this),
      -
      -      // coinbase
      -      buyEth: this.buyEth.bind(this),
      -      // shapeshift
      -      createShapeShiftTx: this.createShapeShiftTx.bind(this),
      -
      -      // primary HD keyring management
      -      addNewAccount: nodeify(this.addNewAccount, this),
      -      placeSeedWords: this.placeSeedWords.bind(this),
      -      verifySeedPhrase: nodeify(this.verifySeedPhrase, this),
      -      clearSeedWordCache: this.clearSeedWordCache.bind(this),
      -      resetAccount: nodeify(this.resetAccount, this),
      -      importAccountWithStrategy: this.importAccountWithStrategy.bind(this),
      -
      -      // vault management
      -      submitPassword: nodeify(keyringController.submitPassword, keyringController),
      -
      -      // network management
      -      setNetworkEndpoints: nodeify(networkController.setNetworkEndpoints, networkController),
      -      setProviderType: nodeify(networkController.setProviderType, networkController),
      -      setCustomRpc: nodeify(this.setCustomRpc, this),
      -
      -      // PreferencesController
      -      setSelectedAddress: nodeify(preferencesController.setSelectedAddress, preferencesController),
      -      addToken: nodeify(preferencesController.addToken, preferencesController),
      -      removeToken: nodeify(preferencesController.removeToken, preferencesController),
      -      setCurrentAccountTab: nodeify(preferencesController.setCurrentAccountTab, preferencesController),
      -      setFeatureFlag: nodeify(preferencesController.setFeatureFlag, preferencesController),
      -
      -      // AddressController
      -      setAddressBook: nodeify(addressBookController.setAddressBook, addressBookController),
      -
      -      // KeyringController
      -      setLocked: nodeify(keyringController.setLocked, keyringController),
      -      createNewVaultAndKeychain: nodeify(this.createNewVaultAndKeychain, this),
      -      createNewVaultAndRestore: nodeify(this.createNewVaultAndRestore, this),
      -      addNewKeyring: nodeify(keyringController.addNewKeyring, keyringController),
      -      saveAccountLabel: nodeify(keyringController.saveAccountLabel, keyringController),
      -      exportAccount: nodeify(keyringController.exportAccount, keyringController),
      -
      -      // txController
      -      cancelTransaction: nodeify(txController.cancelTransaction, txController),
      -      updateTransaction: nodeify(txController.updateTransaction, txController),
      -      updateAndApproveTransaction: nodeify(txController.updateAndApproveTransaction, txController),
      -      retryTransaction: nodeify(this.retryTransaction, this),
      -
      -      // messageManager
      -      signMessage: nodeify(this.signMessage, this),
      -      cancelMessage: this.cancelMessage.bind(this),
      -
      -      // personalMessageManager
      -      signPersonalMessage: nodeify(this.signPersonalMessage, this),
      -      cancelPersonalMessage: this.cancelPersonalMessage.bind(this),
      -
      -      // personalMessageManager
      -      signTypedMessage: nodeify(this.signTypedMessage, this),
      -      cancelTypedMessage: this.cancelTypedMessage.bind(this),
      -
      -      // notices
      -      checkNotices: noticeController.updateNoticesList.bind(noticeController),
      -      markNoticeRead: noticeController.markNoticeRead.bind(noticeController),
      -    }
      -  }
      -
      -
      -
      -//=============================================================================
      -// VAULT / KEYRING RELATED METHODS
      -//=============================================================================
      -
      -  /**
      -   * Creates a new Vault(?) and create a new keychain(?)
      -   *
      -   * A vault is ...
      -   *
      -   * A keychain is ...
      -   *
      -   *
      -   * @param  {} password
      -   *
      -   * @returns {} vault
      -   */
      -  async createNewVaultAndKeychain (password) {
      -    const release = await this.createVaultMutex.acquire()
      -    let vault
      -
      -    try {
      -      const accounts = await this.keyringController.getAccounts()
      -
      -      if (accounts.length > 0) {
      -        vault = await this.keyringController.fullUpdate()
      -
      -      } else {
      -        vault = await this.keyringController.createNewVaultAndKeychain(password)
      -        this.selectFirstIdentity(vault)
      -      }
      -      release()
      -    } catch (err) {
      -      release()
      -      throw err
      -    }
      -
      -    return vault
      -  }
      -
      -  /**
      -   * Create a new Vault and restore an existent keychain
      -   * @param  {} password
      -   * @param  {} seed
      -   */
      -  async createNewVaultAndRestore (password, seed) {
      -    const release = await this.createVaultMutex.acquire()
      -    try {
      -      const vault = await this.keyringController.createNewVaultAndRestore(password, seed)
      -      this.selectFirstIdentity(vault)
      -      release()
      -      return vault
      -    } catch (err) {
      -      release()
      -      throw err
      -    }
      -  }
      -
      -  /**
      -   * Retrieves the first Identiy from the passed Vault and selects the related address
      -   *
      -   * An Identity is ...
      -   *
      -   * @param  {} vault
      -   */
      -  selectFirstIdentity (vault) {
      -    const { identities } = vault
      -    const address = Object.keys(identities)[0]
      -    this.preferencesController.setSelectedAddress(address)
      -  }
      -
      -  // ?
      -  // Opinionated Keyring Management
      -  //
      -
      -  /**
      -   * Adds a new account to ...
      -   *
      -   * @returns {} keyState
      -   */
      -  async addNewAccount () {
      -    const primaryKeyring = this.keyringController.getKeyringsByType('HD Key Tree')[0]
      -    if (!primaryKeyring) {
      -      throw new Error('MetamaskController - No HD Key Tree found')
      -    }
      -    const keyringController = this.keyringController
      -    const oldAccounts = await keyringController.getAccounts()
      -    const keyState = await keyringController.addNewAccount(primaryKeyring)
      -    const newAccounts = await keyringController.getAccounts()
      -
      -    await this.verifySeedPhrase()
      -
      -    newAccounts.forEach((address) => {
      -      if (!oldAccounts.includes(address)) {
      -        this.preferencesController.setSelectedAddress(address)
      -      }
      -    })
      -
      -    return keyState
      -  }
      -
      -  /**
      -   * Adds the current vault's seed words to the UI's state tree.
      -   *
      -   * Used when creating a first vault, to allow confirmation.
      -   * Also used when revealing the seed words in the confirmation view.
      -   */
      -  placeSeedWords (cb) {
      -
      -    this.verifySeedPhrase()
      -      .then((seedWords) => {
      -        this.configManager.setSeedWords(seedWords)
      -        return cb(null, seedWords)
      -      })
      -      .catch((err) => {
      -        return cb(err)
      -      })
      -  }
      -
      -  /**
      -   * Verifies the validity of the current vault's seed phrase.
      -   *
      -   * Validity: seed phrase restores the accounts belonging to the current vault.
      -   *
      -   * Called when the first account is created and on unlocking the vault.
      -   */
      -  async verifySeedPhrase () {
      -
      -    const primaryKeyring = this.keyringController.getKeyringsByType('HD Key Tree')[0]
      -    if (!primaryKeyring) {
      -      throw new Error('MetamaskController - No HD Key Tree found')
      -    }
      -
      -    const serialized = await primaryKeyring.serialize()
      -    const seedWords = serialized.mnemonic
      -
      -    const accounts = await primaryKeyring.getAccounts()
      -    if (accounts.length < 1) {
      -      throw new Error('MetamaskController - No accounts found')
      -    }
      -
      -    try {
      -      await seedPhraseVerifier.verifyAccounts(accounts, seedWords)
      -      return seedWords
      -    } catch (err) {
      -      log.error(err.message)
      -      throw err
      -    }
      -  }
      -
      -  /**
      -   * Remove the primary account seed phrase from the UI's state tree.
      -   *
      -   * The seed phrase remains available in the background process.
      -   *
      -   */
      -  clearSeedWordCache (cb) {
      -    this.configManager.setSeedWords(null)
      -    cb(null, this.preferencesController.getSelectedAddress())
      -  }
      -
      -  /**
      -   * ?
      -   */
      -  async resetAccount (cb) {
      -    const selectedAddress = this.preferencesController.getSelectedAddress()
      -    this.txController.wipeTransactions(selectedAddress)
      -
      -    const networkController = this.networkController
      -    const oldType = networkController.getProviderConfig().type
      -    await networkController.setProviderType(oldType, true)
      -
      -    return selectedAddress
      -  }
      -
      -  /**
      -   * Imports an account ... ?
      -   *
      -   * @param  {} strategy
      -   * @param  {} args
      -   * @param  {} cb
      -   */
      -  importAccountWithStrategy (strategy, args, cb) {
      -    accountImporter.importAccount(strategy, args)
      -    .then((privateKey) => {
      -      return this.keyringController.addNewKeyring('Simple Key Pair', [ privateKey ])
      -    })
      -    .then(keyring => keyring.getAccounts())
      -    .then((accounts) => this.preferencesController.setSelectedAddress(accounts[0]))
      -    .then(() => { cb(null, this.keyringController.fullUpdate()) })
      -    .catch((reason) => { cb(reason) })
      -  }
      -
      -  // ---------------------------------------------------------------------------
      -  // Identity Management (sign)
      -
      -  /**
      -   * @param  {} msgParams
      -   * @param  {} cb
      -   */
      -  signMessage (msgParams, cb) {
      -    log.info('MetaMaskController - signMessage')
      -    const msgId = msgParams.metamaskId
      -
      -    // sets the status op the message to 'approved'
      -    // and removes the metamaskId for signing
      -    return this.messageManager.approveMessage(msgParams)
      -    .then((cleanMsgParams) => {
      -      // signs the message
      -      return this.keyringController.signMessage(cleanMsgParams)
      -    })
      -    .then((rawSig) => {
      -      // tells the listener that the message has been signed
      -      // and can be returned to the dapp
      -      this.messageManager.setMsgStatusSigned(msgId, rawSig)
      -      return this.getState()
      -    })
      -  }
      -
      -  // Prefixed Style Message Signing Methods:
      -
      -  /**
      -   *
      -   * @param  {} msgParams
      -   * @param  {} cb
      -   */
      -  approvePersonalMessage (msgParams, cb) {
      -    const msgId = this.personalMessageManager.addUnapprovedMessage(msgParams)
      -    this.sendUpdate()
      -    this.opts.showUnconfirmedMessage()
      -    this.personalMessageManager.once(`${msgId}:finished`, (data) => {
      -      switch (data.status) {
      -        case 'signed':
      -          return cb(null, data.rawSig)
      -        case 'rejected':
      -          return cb(new Error('MetaMask Message Signature: User denied transaction signature.'))
      -        default:
      -          return cb(new Error(`MetaMask Message Signature: Unknown problem: ${JSON.stringify(msgParams)}`))
      -      }
      -    })
      -  }
      -
      -  /**
      -   * @param  {} msgParams
      -   */
      -  signPersonalMessage (msgParams) {
      -    log.info('MetaMaskController - signPersonalMessage')
      -    const msgId = msgParams.metamaskId
      -    // sets the status op the message to 'approved'
      -    // and removes the metamaskId for signing
      -    return this.personalMessageManager.approveMessage(msgParams)
      -    .then((cleanMsgParams) => {
      -      // signs the message
      -      return this.keyringController.signPersonalMessage(cleanMsgParams)
      -    })
      -    .then((rawSig) => {
      -      // tells the listener that the message has been signed
      -      // and can be returned to the dapp
      -      this.personalMessageManager.setMsgStatusSigned(msgId, rawSig)
      -      return this.getState()
      -    })
      -  }
      -
      -  /**
      -   * @param  {} msgParams
      -   */
      -  signTypedMessage (msgParams) {
      -    log.info('MetaMaskController - signTypedMessage')
      -    const msgId = msgParams.metamaskId
      -    // sets the status op the message to 'approved'
      -    // and removes the metamaskId for signing
      -    return this.typedMessageManager.approveMessage(msgParams)
      -      .then((cleanMsgParams) => {
      -        // signs the message
      -        return this.keyringController.signTypedMessage(cleanMsgParams)
      -      })
      -      .then((rawSig) => {
      -        // tells the listener that the message has been signed
      -        // and can be returned to the dapp
      -        this.typedMessageManager.setMsgStatusSigned(msgId, rawSig)
      -        return this.getState()
      -      })
      -  }
      -
      -  // ---------------------------------------------------------------------------
      -  // Account Restauration
      -
      -  /**
      -   * ?
      -   *
      -   * @param  {} migratorOutput
      -   */
      -  restoreOldVaultAccounts (migratorOutput) {
      -    const { serialized } = migratorOutput
      -    return this.keyringController.restoreKeyring(serialized)
      -    .then(() => migratorOutput)
      -  }
      -
      -  /**
      -   * ?
      -   *
      -   * @param  {} migratorOutput
      -   */
      -  restoreOldLostAccounts (migratorOutput) {
      -    const { lostAccounts } = migratorOutput
      -    if (lostAccounts) {
      -      this.configManager.setLostAccounts(lostAccounts.map(acct => acct.address))
      -      return this.importLostAccounts(migratorOutput)
      -    }
      -    return Promise.resolve(migratorOutput)
      -  }
      -
      -  /**
      -   * Import (lost) Accounts
      -   *
      -   * @param  {Object} {lostAccounts} @Array accounts <{ address, privateKey }>
      -   *
      -   * Uses the array's private keys to create a new Simple Key Pair keychain
      -   * and add it to the keyring controller.
      -   */
      -  importLostAccounts ({ lostAccounts }) {
      -    const privKeys = lostAccounts.map(acct => acct.privateKey)
      -    return this.keyringController.restoreKeyring({
      -      type: 'Simple Key Pair',
      -      data: privKeys,
      -    })
      -  }
      -
      -//=============================================================================
      -// END (VAULT / KEYRING RELATED METHODS)
      -//=============================================================================
      -
      -//
      -
      -//=============================================================================
      -// MESSAGES
      -//=============================================================================
      -
      -  async retryTransaction (txId, cb) {
      -    await this.txController.retryTransaction(txId)
      -    const state = await this.getState()
      -    return state
      -  }
      -
      -
      -  newUnsignedMessage (msgParams, cb) {
      -    const msgId = this.messageManager.addUnapprovedMessage(msgParams)
      -    this.sendUpdate()
      -    this.opts.showUnconfirmedMessage()
      -    this.messageManager.once(`${msgId}:finished`, (data) => {
      -      switch (data.status) {
      -        case 'signed':
      -          return cb(null, data.rawSig)
      -        case 'rejected':
      -          return cb(new Error('MetaMask Message Signature: User denied message signature.'))
      -        default:
      -          return cb(new Error(`MetaMask Message Signature: Unknown problem: ${JSON.stringify(msgParams)}`))
      -      }
      -    })
      -  }
      -
      -  newUnsignedPersonalMessage (msgParams, cb) {
      -    if (!msgParams.from) {
      -      return cb(new Error('MetaMask Message Signature: from field is required.'))
      -    }
      -
      -    const msgId = this.personalMessageManager.addUnapprovedMessage(msgParams)
      -    this.sendUpdate()
      -    this.opts.showUnconfirmedMessage()
      -    this.personalMessageManager.once(`${msgId}:finished`, (data) => {
      -      switch (data.status) {
      -        case 'signed':
      -          return cb(null, data.rawSig)
      -        case 'rejected':
      -          return cb(new Error('MetaMask Message Signature: User denied message signature.'))
      -        default:
      -          return cb(new Error(`MetaMask Message Signature: Unknown problem: ${JSON.stringify(msgParams)}`))
      -      }
      -    })
      -  }
      -
      -  newUnsignedTypedMessage (msgParams, cb) {
      -    let msgId
      -    try {
      -      msgId = this.typedMessageManager.addUnapprovedMessage(msgParams)
      -      this.sendUpdate()
      -      this.opts.showUnconfirmedMessage()
      -    } catch (e) {
      -      return cb(e)
      -    }
      -
      -    this.typedMessageManager.once(`${msgId}:finished`, (data) => {
      -      switch (data.status) {
      -        case 'signed':
      -          return cb(null, data.rawSig)
      -        case 'rejected':
      -          return cb(new Error('MetaMask Message Signature: User denied message signature.'))
      -        default:
      -          return cb(new Error(`MetaMask Message Signature: Unknown problem: ${JSON.stringify(msgParams)}`))
      -      }
      -    })
      -  }
      -
      -  cancelMessage (msgId, cb) {
      -    const messageManager = this.messageManager
      -    messageManager.rejectMsg(msgId)
      -    if (cb && typeof cb === 'function') {
      -      cb(null, this.getState())
      -    }
      -  }
      -
      -  cancelPersonalMessage (msgId, cb) {
      -    const messageManager = this.personalMessageManager
      -    messageManager.rejectMsg(msgId)
      -    if (cb && typeof cb === 'function') {
      -      cb(null, this.getState())
      -    }
      -  }
      -
      -  cancelTypedMessage (msgId, cb) {
      -    const messageManager = this.typedMessageManager
      -    messageManager.rejectMsg(msgId)
      -    if (cb && typeof cb === 'function') {
      -      cb(null, this.getState())
      -    }
      -  }
      -
      -  markAccountsFound (cb) {
      -    this.configManager.setLostAccounts([])
      -    this.sendUpdate()
      -    cb(null, this.getState())
      -  }
      -
      -  markPasswordForgotten(cb) {
      -    this.configManager.setPasswordForgotten(true)
      -    this.sendUpdate()
      -    cb()
      -  }
      -
      -  unMarkPasswordForgotten(cb) {
      -    this.configManager.setPasswordForgotten(false)
      -    this.sendUpdate()
      -    cb()
      -  }
      -
      -//=============================================================================
      -// SETUP
      -//=============================================================================
      -
      -  setupUntrustedCommunication (connectionStream, originDomain) {
      -    // Check if new connection is blacklisted
      -    if (this.blacklistController.checkForPhishing(originDomain)) {
      -      log.debug('MetaMask - sending phishing warning for', originDomain)
      -      this.sendPhishingWarning(connectionStream, originDomain)
      -      return
      -    }
      -
      -    // setup multiplexing
      -    const mux = setupMultiplex(connectionStream)
      -    // connect features
      -    this.setupProviderConnection(mux.createStream('provider'), originDomain)
      -    this.setupPublicConfig(mux.createStream('publicConfig'))
      -  }
      -
      -  setupTrustedCommunication (connectionStream, originDomain) {
      -    // setup multiplexing
      -    const mux = setupMultiplex(connectionStream)
      -    // connect features
      -    this.setupControllerConnection(mux.createStream('controller'))
      -    this.setupProviderConnection(mux.createStream('provider'), originDomain)
      -  }
      -
      -  sendPhishingWarning (connectionStream, hostname) {
      -    const mux = setupMultiplex(connectionStream)
      -    const phishingStream = mux.createStream('phishing')
      -    phishingStream.write({ hostname })
      -  }
      -
      -  setupControllerConnection (outStream) {
      -    const api = this.getApi()
      -    const dnode = Dnode(api)
      -    pump(
      -      outStream,
      -      dnode,
      -      outStream,
      -      (err) => {
      -        if (err) log.error(err)
      -      }
      -    )
      -    dnode.on('remote', (remote) => {
      -      // push updates to popup
      -      const sendUpdate = remote.sendUpdate.bind(remote)
      -      this.on('update', sendUpdate)
      -    })
      -  }
      -
      -  setupProviderConnection (outStream, origin) {
      -    // setup json rpc engine stack
      -    const engine = new RpcEngine()
      -
      -    // create filter polyfill middleware
      -    const filterMiddleware = createFilterMiddleware({
      -      provider: this.provider,
      -      blockTracker: this.provider._blockTracker,
      -    })
      -
      -    engine.push(createOriginMiddleware({ origin }))
      -    engine.push(createLoggerMiddleware({ origin }))
      -    engine.push(filterMiddleware)
      -    engine.push(createProviderMiddleware({ provider: this.provider }))
      -
      -    // setup connection
      -    const providerStream = createEngineStream({ engine })
      -    pump(
      -      outStream,
      -      providerStream,
      -      outStream,
      -      (err) => {
      -        // cleanup filter polyfill middleware
      -        filterMiddleware.destroy()
      -        if (err) log.error(err)
      -      }
      -    )
      -  }
      -
      -  setupPublicConfig (outStream) {
      -    pump(
      -      asStream(this.publicConfigStore),
      -      outStream,
      -      (err) => {
      -        if (err) log.error(err)
      -      }
      -    )
      -  }
      -
      -  privateSendUpdate () {
      -    this.emit('update', this.getState())
      -  }
      -
      -  getGasPrice () {
      -    const { recentBlocksController } = this
      -    const { recentBlocks } = recentBlocksController.store.getState()
      -
      -    // Return 1 gwei if no blocks have been observed:
      -    if (recentBlocks.length === 0) {
      -      return '0x' + GWEI_BN.toString(16)
      -    }
      -
      -    const lowestPrices = recentBlocks.map((block) => {
      -      if (!block.gasPrices || block.gasPrices.length < 1) {
      -        return GWEI_BN
      -      }
      -      return block.gasPrices
      -      .map(hexPrefix => hexPrefix.substr(2))
      -      .map(hex => new BN(hex, 16))
      -      .sort((a, b) => {
      -        return a.gt(b) ? 1 : -1
      -      })[0]
      -    })
      -    .map(number => number.div(GWEI_BN).toNumber())
      -
      -    const percentileNum = percentile(50, lowestPrices)
      -    const percentileNumBn = new BN(percentileNum)
      -    return '0x' + percentileNumBn.mul(GWEI_BN).toString(16)
      -  }
      -
      -//=============================================================================
      -// CONFIG
      -//=============================================================================
      -
      -  // Log blocks
      -
      -  setCurrentCurrency (currencyCode, cb) {
      -    try {
      -      this.currencyController.setCurrentCurrency(currencyCode)
      -      this.currencyController.updateConversionRate()
      -      const data = {
      -        conversionRate: this.currencyController.getConversionRate(),
      -        currentCurrency: this.currencyController.getCurrentCurrency(),
      -        conversionDate: this.currencyController.getConversionDate(),
      -      }
      -      cb(null, data)
      -    } catch (err) {
      -      cb(err)
      -    }
      -  }
      -
      -  buyEth (address, amount) {
      -    if (!amount) amount = '5'
      -    const network = this.networkController.getNetworkState()
      -    const url = getBuyEthUrl({ network, address, amount })
      -    if (url) this.platform.openWindow({ url })
      -  }
      -
      -  createShapeShiftTx (depositAddress, depositType) {
      -    this.shapeshiftController.createShapeShiftTx(depositAddress, depositType)
      -  }
      -
      -  // network
      -
      -  async setCustomRpc (rpcTarget, rpcList) {
      -    this.networkController.setRpcTarget(rpcTarget)
      -    await this.preferencesController.updateFrequentRpcList(rpcTarget)
      -    return rpcTarget
      -  }
      -
      -  setUseBlockie (val, cb) {
      -    try {
      -      this.preferencesController.setUseBlockie(val)
      -      cb(null)
      -    } catch (err) {
      -      cb(err)
      -    }
      -  }
      -
      -  setCurrentLocale (key, cb) {
      -    try {
      -      this.preferencesController.setCurrentLocale(key)
      -      cb(null)
      -    } catch (err) {
      -      cb(err)
      -    }
      -  }
      -
      -  recordFirstTimeInfo (initState) {
      -    if (!('firstTimeInfo' in initState)) {
      -      initState.firstTimeInfo = {
      -        version,
      -        date: Date.now(),
      -      }
      -    }
      -  }
      -
      -  set isClientOpen (open) {
      -    this._isClientOpen = open
      -    this.isClientOpenAndUnlocked = this.getState().isUnlocked && open
      -  }
      -
      -  set isClientOpenAndUnlocked (active) {
      -    this.tokenRatesController.isActive = active
      -  }
      -}
      -
      -
      -
      - - - - -
      - -
      - -
      - Documentation generated by JSDoc 3.5.5 on Wed Apr 18 2018 17:21:38 GMT-0400 (EDT) using the radgrad jsdoc theme. Derived from docdash. -
      - - - - - - diff --git a/docs/jsdocs/module.exports_module.exports.html b/docs/jsdocs/module.exports_module.exports.html deleted file mode 100644 index f5c96b6eb..000000000 --- a/docs/jsdocs/module.exports_module.exports.html +++ /dev/null @@ -1,229 +0,0 @@ - - - - - - - exports - Documentation - - - - - - - - - - - - - - - - - - - - - -
      - -

      exports

      - - - - - - - -
      - -
      - -

      - exports -

      - - -
      - -
      -
      - - - - - -

      new exports(opts)

      - - - - - - -
      - - -
      Source:
      -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      - - - - - - - - - - - - - - - -
      Parameters:
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      NameTypeDescription
      opts - - -Object - - - -
      - - - - - - - - - - - - - - - - - -
      - - - - - - - - - - - - - - - - - - -
      - -
      - - - - -
      - -
      - -
      - Documentation generated by JSDoc 3.5.5 on Wed Apr 18 2018 17:21:38 GMT-0400 (EDT) using the radgrad jsdoc theme. Derived from docdash. -
      - - - - - - \ No newline at end of file diff --git a/docs/jsdocs/platforms_extension.js.html b/docs/jsdocs/platforms_extension.js.html deleted file mode 100644 index c75f6c108..000000000 --- a/docs/jsdocs/platforms_extension.js.html +++ /dev/null @@ -1,117 +0,0 @@ - - - - - - - platforms/extension.js - Documentation - - - - - - - - - - - - - - - - - - - - - -
      - -

      platforms/extension.js

      - - - - - - - -
      -
      -
      const extension = require('extensionizer')
      -
      -/**
      - * An object that provides a variety of platform-specific functions.
      - *
      - * @typedef {object} Platform
      - *
      - * @property {Function} reload - A function to reload the application.
      - * @property {Function} openWindow - Opens a URL in the web browser.
      - * @property {Function} getVersion - Gets the current version of MetaMask.
      - * @property {Function} openExtensionInBrowser - Opens the MetaMask UI in a full window.
      - * @property {Function} getPlatformInfo - Callback function that returns info about the current platform.
      - */
      -
      -class ExtensionPlatform {
      -
      -  //
      -  // Public
      -  //
      -  reload () {
      -    extension.runtime.reload()
      -  }
      -
      -  openWindow ({ url }) {
      -    extension.tabs.create({ url })
      -  }
      -
      -  getVersion () {
      -    return extension.runtime.getManifest().version
      -  }
      -
      -  openExtensionInBrowser () {
      -    const extensionURL = extension.runtime.getURL('home.html')
      -    this.openWindow({ url: extensionURL })
      -  }
      -
      -  getPlatformInfo (cb) {
      -    try {
      -      extension.runtime.getPlatformInfo((platform) => {
      -        cb(null, platform)
      -      })
      -    } catch (e) {
      -      cb(e)
      -    }
      -  }
      -}
      -
      -module.exports = ExtensionPlatform
      -
      -
      -
      - - - - -
      - -
      - -
      - Documentation generated by JSDoc 3.5.5 on Thu Apr 12 2018 14:37:39 GMT-0700 (PDT) using the radgrad jsdoc theme. Derived from docdash. -
      - - - - - - diff --git a/docs/jsdocs/popup-core.js.html b/docs/jsdocs/popup-core.js.html deleted file mode 100644 index 919637cfe..000000000 --- a/docs/jsdocs/popup-core.js.html +++ /dev/null @@ -1,146 +0,0 @@ - - - - - - - popup-core.js - Documentation - - - - - - - - - - - - - - - - - - - - - -
      - -

      popup-core.js

      - - - - - - - -
      -
      -
      const EventEmitter = require('events').EventEmitter
      -const async = require('async')
      -const Dnode = require('dnode')
      -const Eth = require('ethjs')
      -const EthQuery = require('eth-query')
      -const launchMetamaskUi = require('../../ui')
      -const StreamProvider = require('web3-stream-provider')
      -const setupMultiplex = require('./lib/stream-utils.js').setupMultiplex
      -
      -module.exports = initializePopup
      -
      -/**
      - * Asynchronously initializes the MetaMask popup UI
      - *
      - * @param {{ container: Element, connectionStream: any }} config Popup configuration object 
      - * @param {Function} cb Called when initialization is comlete
      - */
      -function initializePopup ({ container, connectionStream }, cb) {
      -  // setup app
      -  async.waterfall([
      -    (cb) => connectToAccountManager(connectionStream, cb),
      -    (accountManager, cb) => launchMetamaskUi({ container, accountManager }, cb),
      -  ], cb)
      -}
      -
      -/**
      - * Establishes streamed connections to background scripts and a Web3 provider
      - *
      - * @param {any} connectionStream PortStream instance establishing a background connection
      - * @param {Function} cb Called when controller connection is established
      - */
      -function connectToAccountManager (connectionStream, cb) {
      -  // setup communication with background
      -  // setup multiplexing
      -  var mx = setupMultiplex(connectionStream)
      -  // connect features
      -  setupControllerConnection(mx.createStream('controller'), cb)
      -  setupWeb3Connection(mx.createStream('provider'))
      -}
      -
      -/**
      - * Establishes a streamed connection to a Web3 provider
      - *
      - * @param {any} connectionStream PortStream instance establishing a background connection
      - */
      -function setupWeb3Connection (connectionStream) {
      -  var providerStream = new StreamProvider()
      -  providerStream.pipe(connectionStream).pipe(providerStream)
      -  connectionStream.on('error', console.error.bind(console))
      -  providerStream.on('error', console.error.bind(console))
      -  global.ethereumProvider = providerStream
      -  global.ethQuery = new EthQuery(providerStream)
      -  global.eth = new Eth(providerStream)
      -}
      -
      -/**
      - * Establishes a streamed connection to the background account manager
      - *
      - * @param {any} connectionStream PortStream instance establishing a background connection
      - * @param {Function} cb Called when the remote account manager connection is established
      - */
      -function setupControllerConnection (connectionStream, cb) {
      -  // this is a really sneaky way of adding EventEmitter api
      -  // to a bi-directional dnode instance
      -  var eventEmitter = new EventEmitter()
      -  var accountManagerDnode = Dnode({
      -    sendUpdate: function (state) {
      -      eventEmitter.emit('update', state)
      -    },
      -  })
      -  connectionStream.pipe(accountManagerDnode).pipe(connectionStream)
      -  accountManagerDnode.once('remote', function (accountManager) {
      -    // setup push events
      -    accountManager.on = eventEmitter.on.bind(eventEmitter)
      -    cb(null, accountManager)
      -  })
      -}
      -
      -
      -
      - - - - -
      - -
      - -
      - Documentation generated by JSDoc 3.5.5 on Wed Apr 18 2018 17:21:38 GMT-0400 (EDT) using the radgrad jsdoc theme. Derived from docdash. -
      - - - - - - diff --git a/docs/jsdocs/scripts/linenumber.js b/docs/jsdocs/scripts/linenumber.js deleted file mode 100644 index 9cb891484..000000000 --- a/docs/jsdocs/scripts/linenumber.js +++ /dev/null @@ -1,25 +0,0 @@ -/*global document */ -(function() { - var source = document.getElementsByClassName('prettyprint source linenums'); - var i = 0; - var lineNumber = 0; - var lineId; - var lines; - var totalLines; - var anchorHash; - - if (source && source[0]) { - anchorHash = document.location.hash.substring(1); - lines = source[0].getElementsByTagName('li'); - totalLines = lines.length; - - for (; i < totalLines; i++) { - lineNumber++; - lineId = 'line' + lineNumber; - lines[i].id = lineId; - if (lineId === anchorHash) { - lines[i].className += ' selected'; - } - } - } -})(); diff --git a/docs/jsdocs/scripts/prettify/Apache-License-2.0.txt b/docs/jsdocs/scripts/prettify/Apache-License-2.0.txt deleted file mode 100644 index 75b52484e..000000000 --- a/docs/jsdocs/scripts/prettify/Apache-License-2.0.txt +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/docs/jsdocs/scripts/prettify/lang-css.js b/docs/jsdocs/scripts/prettify/lang-css.js deleted file mode 100644 index bb6dbea43..000000000 --- a/docs/jsdocs/scripts/prettify/lang-css.js +++ /dev/null @@ -1,2 +0,0 @@ -PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\f\r ]+/,null," \t\r\n "]],[["str",/^"(?:[^\n\f\r"\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*"/,null],["str",/^'(?:[^\n\f\r'\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*'/,null],["lang-css-str",/^url\(([^"')]*)\)/i],["kwd",/^(?:url|rgb|!important|@import|@page|@media|@charset|inherit)(?=[^\w-]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*)\s*:/i],["com",/^\/\*[^*]*\*+(?:[^*/][^*]*\*+)*\//],["com", -/^(?:<\!--|--\>)/],["lit",/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],["lit",/^#[\da-f]{3,6}/i],["pln",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i],["pun",/^[^\s\w"']+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[["kwd",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[["str",/^[^"')]+/]]),["css-str"]); diff --git a/docs/jsdocs/scripts/prettify/prettify.js b/docs/jsdocs/scripts/prettify/prettify.js deleted file mode 100644 index ec2a488bd..000000000 --- a/docs/jsdocs/scripts/prettify/prettify.js +++ /dev/null @@ -1,28 +0,0 @@ -var q=null;window.PR_SHOULD_USE_CONTINUATION=!0; -(function(){function L(a){function m(a){var f=a.charCodeAt(0);if(f!==92)return f;var b=a.charAt(1);return(f=r[b])?f:"0"<=b&&b<="7"?parseInt(a.substring(1),8):b==="u"||b==="x"?parseInt(a.substring(2),16):a.charCodeAt(1)}function e(a){if(a<32)return(a<16?"\\x0":"\\x")+a.toString(16);a=String.fromCharCode(a);if(a==="\\"||a==="-"||a==="["||a==="]")a="\\"+a;return a}function h(a){for(var f=a.substring(1,a.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\s]|[^\\]/g),a= -[],b=[],o=f[0]==="^",c=o?1:0,i=f.length;c122||(d<65||j>90||b.push([Math.max(65,j)|32,Math.min(d,90)|32]),d<97||j>122||b.push([Math.max(97,j)&-33,Math.min(d,122)&-33]))}}b.sort(function(a,f){return a[0]-f[0]||f[1]-a[1]});f=[];j=[NaN,NaN];for(c=0;ci[0]&&(i[1]+1>i[0]&&b.push("-"),b.push(e(i[1])));b.push("]");return b.join("")}function y(a){for(var f=a.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),b=f.length,d=[],c=0,i=0;c=2&&a==="["?f[c]=h(j):a!=="\\"&&(f[c]=j.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return f.join("")}for(var t=0,s=!1,l=!1,p=0,d=a.length;p=5&&"lang-"===b.substring(0,5))&&!(o&&typeof o[1]==="string"))c=!1,b="src";c||(r[f]=b)}i=d;d+=f.length;if(c){c=o[1];var j=f.indexOf(c),k=j+c.length;o[2]&&(k=f.length-o[2].length,j=k-c.length);b=b.substring(5);B(l+i,f.substring(0,j),e,p);B(l+i+j,c,C(b,c),p);B(l+i+k,f.substring(k),e,p)}else p.push(l+i,b)}a.e=p}var h={},y;(function(){for(var e=a.concat(m), -l=[],p={},d=0,g=e.length;d=0;)h[n.charAt(k)]=r;r=r[1];n=""+r;p.hasOwnProperty(n)||(l.push(r),p[n]=q)}l.push(/[\S\s]/);y=L(l)})();var t=m.length;return e}function u(a){var m=[],e=[];a.tripleQuotedStrings?m.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,q,"'\""]):a.multiLineStrings?m.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/, -q,"'\"`"]):m.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,q,"\"'"]);a.verbatimStrings&&e.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,q]);var h=a.hashComments;h&&(a.cStyleComments?(h>1?m.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,"#"]):m.push(["com",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\n\r]*)/,q,"#"]),e.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,q])):m.push(["com",/^#[^\n\r]*/, -q,"#"]));a.cStyleComments&&(e.push(["com",/^\/\/[^\n\r]*/,q]),e.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,q]));a.regexLiterals&&e.push(["lang-regex",/^(?:^^\.?|[!+-]|!=|!==|#|%|%=|&|&&|&&=|&=|\(|\*|\*=|\+=|,|-=|->|\/|\/=|:|::|;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|[?@[^]|\^=|\^\^|\^\^=|{|\||\|=|\|\||\|\|=|~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\s*(\/(?=[^*/])(?:[^/[\\]|\\[\S\s]|\[(?:[^\\\]]|\\[\S\s])*(?:]|$))+\/)/]);(h=a.types)&&e.push(["typ",h]);a=(""+a.keywords).replace(/^ | $/g, -"");a.length&&e.push(["kwd",RegExp("^(?:"+a.replace(/[\s,]+/g,"|")+")\\b"),q]);m.push(["pln",/^\s+/,q," \r\n\t\xa0"]);e.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/,q],["pun",/^.[^\s\w"-$'./@\\`]*/,q]);return x(m,e)}function D(a,m){function e(a){switch(a.nodeType){case 1:if(k.test(a.className))break;if("BR"===a.nodeName)h(a), -a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)e(a);break;case 3:case 4:if(p){var b=a.nodeValue,d=b.match(t);if(d){var c=b.substring(0,d.index);a.nodeValue=c;(b=b.substring(d.index+d[0].length))&&a.parentNode.insertBefore(s.createTextNode(b),a.nextSibling);h(a);c||a.parentNode.removeChild(a)}}}}function h(a){function b(a,d){var e=d?a.cloneNode(!1):a,f=a.parentNode;if(f){var f=b(f,1),g=a.nextSibling;f.appendChild(e);for(var h=g;h;h=g)g=h.nextSibling,f.appendChild(h)}return e} -for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),e;(e=a.parentNode)&&e.nodeType===1;)a=e;d.push(a)}var k=/(?:^|\s)nocode(?:\s|$)/,t=/\r\n?|\n/,s=a.ownerDocument,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=s.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);for(l=s.createElement("LI");a.firstChild;)l.appendChild(a.firstChild);for(var d=[l],g=0;g=0;){var h=m[e];A.hasOwnProperty(h)?window.console&&console.warn("cannot override language handler %s",h):A[h]=a}}function C(a,m){if(!a||!A.hasOwnProperty(a))a=/^\s*=o&&(h+=2);e>=c&&(a+=2)}}catch(w){"console"in window&&console.log(w&&w.stack?w.stack:w)}}var v=["break,continue,do,else,for,if,return,while"],w=[[v,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"], -"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],F=[w,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],G=[w,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"], -H=[G,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"],w=[w,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],I=[v,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"], -J=[v,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],v=[v,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],K=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/,N=/\S/,O=u({keywords:[F,H,w,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END"+ -I,J,v],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),A={};k(O,["default-code"]);k(x([],[["pln",/^[^]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",/^]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]), -["default-markup","htm","html","mxml","xhtml","xml","xsl"]);k(x([["pln",/^\s+/,q," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,q,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/],["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css", -/^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);k(x([],[["atv",/^[\S\s]+/]]),["uq.val"]);k(u({keywords:F,hashComments:!0,cStyleComments:!0,types:K}),["c","cc","cpp","cxx","cyc","m"]);k(u({keywords:"null,true,false"}),["json"]);k(u({keywords:H,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:K}),["cs"]);k(u({keywords:G,cStyleComments:!0}),["java"]);k(u({keywords:v,hashComments:!0,multiLineStrings:!0}),["bsh","csh","sh"]);k(u({keywords:I,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}), -["cv","py"]);k(u({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["perl","pl","pm"]);k(u({keywords:J,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb"]);k(u({keywords:w,cStyleComments:!0,regexLiterals:!0}),["js"]);k(u({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes", -hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);k(x([],[["str",/^[\S\s]+/]]),["regex"]);window.prettyPrintOne=function(a,m,e){var h=document.createElement("PRE");h.innerHTML=a;e&&D(h,e);E({g:m,i:e,h:h});return h.innerHTML};window.prettyPrint=function(a){function m(){for(var e=window.PR_SHOULD_USE_CONTINUATION?l.now()+250:Infinity;p=0){var k=k.match(g),f,b;if(b= -!k){b=n;for(var o=void 0,c=b.firstChild;c;c=c.nextSibling)var i=c.nodeType,o=i===1?o?b:c:i===3?N.test(c.nodeValue)?b:o:o;b=(f=o===b?void 0:o)&&"CODE"===f.tagName}b&&(k=f.className.match(g));k&&(k=k[1]);b=!1;for(o=n.parentNode;o;o=o.parentNode)if((o.tagName==="pre"||o.tagName==="code"||o.tagName==="xmp")&&o.className&&o.className.indexOf("prettyprint")>=0){b=!0;break}b||((b=(b=n.className.match(/\blinenums\b(?::(\d+))?/))?b[1]&&b[1].length?+b[1]:!0:!1)&&D(n,b),d={g:k,h:n,i:b},E(d))}}p0&&(o.verbose("Modifying existing settings",s),s[r]("setting",t,n))))})},settings:function(t,n,i){n="string"==typeof n?[n]:n||d.modules,i=void 0===i||i,e.each(n,function(n,a){var r;o.moduleExists(a)&&(o.verbose("Changing default setting",t,a),e.extend(!0,e.fn[a].settings,t),i&&f&&(r=e(":data(module-"+f+")"),r.length>0&&(o.verbose("Modifying existing settings",r),r[a]("setting",t))))})}},enable:{console:function(){o.console(!0)},debug:function(e,t){e=e||d.modules,o.debug("Enabling debug for modules",e),o.change.setting("debug",!0,e,t)},verbose:function(e,t){e=e||d.modules,o.debug("Enabling verbose debug for modules",e),o.change.setting("verbose",!0,e,t)}},disable:{console:function(){o.console(!1)},debug:function(e,t){e=e||d.modules,o.debug("Disabling debug for modules",e),o.change.setting("debug",!1,e,t)},verbose:function(e,t){e=e||d.modules,o.debug("Disabling verbose debug for modules",e),o.change.setting("verbose",!1,e,t)}},console:function(e){if(e){if(void 0===b.cache.console)return void o.error(m.console);o.debug("Restoring console function"),t.console=b.cache.console}else o.debug("Disabling console function"),b.cache.console=t.console,t.console={clear:function(){},error:function(){},group:function(){},groupCollapsed:function(){},groupEnd:function(){},info:function(){},log:function(){},markTimeline:function(){},warn:function(){}}},destroy:function(){o.verbose("Destroying previous site for",p),p.removeData(g)},cache:{},setting:function(t,n){if(e.isPlainObject(t))e.extend(!0,d,t);else{if(void 0===n)return d[t];d[t]=n}},internal:function(t,n){if(e.isPlainObject(t))e.extend(!0,o,t);else{if(void 0===n)return o[t];o[t]=n}},debug:function(){d.debug&&(d.performance?o.performance.log(arguments):(o.debug=Function.prototype.bind.call(console.info,console,d.name+":"),o.debug.apply(console,arguments)))},verbose:function(){d.verbose&&d.debug&&(d.performance?o.performance.log(arguments):(o.verbose=Function.prototype.bind.call(console.info,console,d.name+":"),o.verbose.apply(console,arguments)))},error:function(){o.error=Function.prototype.bind.call(console.error,console,d.name+":"),o.error.apply(console,arguments)},performance:{log:function(e){var t,n,i;d.performance&&(t=(new Date).getTime(),i=r||t,n=t-i,r=t,s.push({Element:h,Name:e[0],Arguments:[].slice.call(e,1)||"","Execution Time":n})),clearTimeout(o.performance.timer),o.performance.timer=setTimeout(o.performance.display,500)},display:function(){var t=d.name+":",n=0;r=!1,clearTimeout(o.performance.timer),e.each(s,function(e,t){n+=t["Execution Time"]}),t+=" "+n+"ms",(void 0!==console.group||void 0!==console.table)&&s.length>0&&(console.groupCollapsed(t),console.table?console.table(s):e.each(s,function(e,t){console.log(t.Name+": "+t["Execution Time"]+"ms")}),console.groupEnd()),s=[]}},invoke:function(t,n,i){var r,s,l,c=b;return n=n||u,i=h||i,"string"==typeof t&&void 0!==c&&(t=t.split(/[\. ]/),r=t.length-1,e.each(t,function(n,i){var a=n!=r?i+t[n+1].charAt(0).toUpperCase()+t[n+1].slice(1):t;if(e.isPlainObject(c[a])&&n!=r)c=c[a];else{if(void 0!==c[a])return s=c[a],!1;if(!e.isPlainObject(c[i])||n==r)return void 0!==c[i]?(s=c[i],!1):(o.error(m.method,t),!1);c=c[i]}})),e.isFunction(s)?l=s.apply(i,n):void 0!==s&&(l=s),e.isArray(a)?a.push(l):void 0!==a?a=[a,l]:void 0!==l&&(a=l),s}},c?(void 0===b&&o.initialize(),o.invoke(l)):(void 0!==b&&o.destroy(),o.initialize()),void 0!==a?a:this},e.site.settings={name:"Site",namespace:"site",error:{console:"Console cannot be restored, most likely it was overwritten outside of module",method:"The method you called is not defined."},debug:!1,verbose:!1,performance:!0,modules:["accordion","api","checkbox","dimmer","dropdown","embed","form","modal","nag","popup","rating","shape","sidebar","state","sticky","tab","transition","visit","visibility"],siteNamespace:"site",namespaceStub:{cache:{},config:{},sections:{},section:{},utilities:{}}},e.extend(e.expr[":"],{data:e.expr.createPseudo?e.expr.createPseudo(function(t){return function(n){return!!e.data(n,t)}}):function(t,n,i){return!!e.data(t,i[3])}})}(jQuery,window,document),function(e,t,n,i){"use strict";t=void 0!==t&&t.Math==Math?t:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")(),e.fn.form=function(t){var i,o=e(this),a=o.selector||"",r=(new Date).getTime(),s=[],l=arguments[0],c=arguments[1],u="string"==typeof l,d=[].slice.call(arguments,1);return o.each(function(){var f,m,g,v,p,h,b,y,x,C,w,k,S,T,A,R,P,E,F,O=e(this),D=this,q=[],j=!1;F={initialize:function(){F.get.settings(),u?(void 0===E&&F.instantiate(),F.invoke(l)):(void 0!==E&&E.invoke("destroy"),F.verbose("Initializing form validation",O,y),F.bindEvents(),F.set.defaults(),F.instantiate())},instantiate:function(){F.verbose("Storing instance of module",F),E=F,O.data(R,F)},destroy:function(){F.verbose("Destroying previous module",E),F.removeEvents(),O.removeData(R)},refresh:function(){F.verbose("Refreshing selector cache"),f=O.find(w.field),m=O.find(w.group),g=O.find(w.message),v=O.find(w.prompt),p=O.find(w.submit),h=O.find(w.clear),b=O.find(w.reset)},submit:function(){F.verbose("Submitting form",O),O.submit()},attachEvents:function(t,n){n=n||"submit",e(t).on("click"+P,function(e){F[n](),e.preventDefault()})},bindEvents:function(){F.verbose("Attaching form events"),O.on("submit"+P,F.validate.form).on("blur"+P,w.field,F.event.field.blur).on("click"+P,w.submit,F.submit).on("click"+P,w.reset,F.reset).on("click"+P,w.clear,F.clear),y.keyboardShortcuts&&O.on("keydown"+P,w.field,F.event.field.keydown),f.each(function(){var t=e(this),n=t.prop("type"),i=F.get.changeEvent(n,t);e(this).on(i+P,F.event.field.change)})},clear:function(){f.each(function(){var t=e(this),n=t.parent(),i=t.closest(m),o=i.find(w.prompt),a=t.data(C.defaultValue)||"",r=n.is(w.uiCheckbox),s=n.is(w.uiDropdown);i.hasClass(k.error)&&(F.verbose("Resetting error on field",i),i.removeClass(k.error),o.remove()),s?(F.verbose("Resetting dropdown value",n,a),n.dropdown("clear")):r?t.prop("checked",!1):(F.verbose("Resetting field value",t,a),t.val(""))})},reset:function(){f.each(function(){var t=e(this),n=t.parent(),i=t.closest(m),o=i.find(w.prompt),a=t.data(C.defaultValue),r=n.is(w.uiCheckbox),s=n.is(w.uiDropdown),l=i.hasClass(k.error);void 0!==a&&(l&&(F.verbose("Resetting error on field",i),i.removeClass(k.error),o.remove()),s?(F.verbose("Resetting dropdown value",n,a),n.dropdown("restore defaults")):r?(F.verbose("Resetting checkbox value",n,a),t.prop("checked",a)):(F.verbose("Resetting field value",t,a),t.val(a)))})},determine:{isValid:function(){var t=!0;return e.each(x,function(e,n){F.validate.field(n,e,!0)||(t=!1)}),t}},is:{bracketedRule:function(e){return e.type&&e.type.match(y.regExp.bracket)},shorthandFields:function(e){var t=Object.keys(e),n=e[t[0]];return F.is.shorthandRules(n)},shorthandRules:function(t){return"string"==typeof t||e.isArray(t)},empty:function(e){return!e||0===e.length||(e.is('input[type="checkbox"]')?!e.is(":checked"):F.is.blank(e))},blank:function(t){return""===e.trim(t.val())},valid:function(t){var n=!0;return t?(F.verbose("Checking if field is valid",t),F.validate.field(x[t],t,!1)):(F.verbose("Checking if form is valid"),e.each(x,function(e,t){F.is.valid(e)||(n=!1)}),n)}},removeEvents:function(){O.off(P),f.off(P),p.off(P),f.off(P)},event:{field:{keydown:function(t){var n=e(this),i=t.which,o=n.is(w.input),a=n.is(w.checkbox),r=n.closest(w.uiDropdown).length>0,s={enter:13,escape:27};i==s.escape&&(F.verbose("Escape key pressed blurring field"),n.blur()),t.ctrlKey||i!=s.enter||!o||r||a||(j||(n.one("keyup"+P,F.event.field.keyup),F.submit(),F.debug("Enter pressed on input submitting form")),j=!0)},keyup:function(){j=!1},blur:function(t){var n=e(this),i=n.closest(m),o=F.get.validation(n);i.hasClass(k.error)?(F.debug("Revalidating field",n,o),o&&F.validate.field(o)):"blur"!=y.on&&"change"!=y.on||o&&F.validate.field(o)},change:function(t){var n=e(this),i=n.closest(m),o=F.get.validation(n);o&&("change"==y.on||i.hasClass(k.error)&&y.revalidate)&&(clearTimeout(F.timer),F.timer=setTimeout(function(){F.debug("Revalidating field",n,F.get.validation(n)),F.validate.field(o)},y.delay))}}},get:{ancillaryValue:function(e){return!(!e.type||!e.value&&!F.is.bracketedRule(e))&&(void 0!==e.value?e.value:e.type.match(y.regExp.bracket)[1]+"")},ruleName:function(e){return F.is.bracketedRule(e)?e.type.replace(e.type.match(y.regExp.bracket)[0],""):e.type},changeEvent:function(e,t){return"checkbox"==e||"radio"==e||"hidden"==e||t.is("select")?"change":F.get.inputEvent()},inputEvent:function(){return void 0!==n.createElement("input").oninput?"input":void 0!==n.createElement("input").onpropertychange?"propertychange":"keyup"},fieldsFromShorthand:function(t){var n={};return e.each(t,function(t,i){"string"==typeof i&&(i=[i]),n[t]={rules:[]},e.each(i,function(e,i){n[t].rules.push({type:i})})}),n},prompt:function(e,t){var n,i,o,a=F.get.ruleName(e),r=F.get.ancillaryValue(e),s=e.prompt||y.prompt[a]||y.text.unspecifiedRule,l=-1!==s.search("{value}"),c=-1!==s.search("{name}");return(c||l)&&(i=F.get.field(t.identifier)),l&&(s=s.replace("{value}",i.val())),c&&(n=i.closest(w.group).find("label").eq(0),o=1==n.length?n.text():i.prop("placeholder")||y.text.unspecifiedField,s=s.replace("{name}",o)),s=s.replace("{identifier}",t.identifier),s=s.replace("{ruleValue}",r),e.prompt||F.verbose("Using default validation prompt for type",s,a),s},settings:function(){if(e.isPlainObject(t)){var n=Object.keys(t),i=n.length>0&&(void 0!==t[n[0]].identifier&&void 0!==t[n[0]].rules);i?(y=e.extend(!0,{},e.fn.form.settings,c),x=e.extend({},e.fn.form.settings.defaults,t),F.error(y.error.oldSyntax,D),F.verbose("Extending settings from legacy parameters",x,y)):(t.fields&&F.is.shorthandFields(t.fields)&&(t.fields=F.get.fieldsFromShorthand(t.fields)),y=e.extend(!0,{},e.fn.form.settings,t),x=e.extend({},e.fn.form.settings.defaults,y.fields),F.verbose("Extending settings",x,y))}else y=e.fn.form.settings,x=e.fn.form.settings.defaults,F.verbose("Using default form validation",x,y);A=y.namespace,C=y.metadata,w=y.selector,k=y.className,S=y.regExp,T=y.error,R="module-"+A,P="."+A,E=O.data(R),F.refresh()},field:function(t){return F.verbose("Finding field with identifier",t),t=F.escape.string(t),f.filter("#"+t).length>0?f.filter("#"+t):f.filter('[name="'+t+'"]').length>0?f.filter('[name="'+t+'"]'):f.filter('[name="'+t+'[]"]').length>0?f.filter('[name="'+t+'[]"]'):f.filter("[data-"+C.validate+'="'+t+'"]').length>0?f.filter("[data-"+C.validate+'="'+t+'"]'):e("")},fields:function(t){var n=e();return e.each(t,function(e,t){n=n.add(F.get.field(t))}),n},validation:function(t){var n,i;return!!x&&(e.each(x,function(e,o){i=o.identifier||e,F.get.field(i)[0]==t[0]&&(o.identifier=i,n=o)}),n||!1)},value:function(e){var t,n=[];return n.push(e),t=F.get.values.call(D,n),t[e]},values:function(t){var n=e.isArray(t)?F.get.fields(t):f,i={};return n.each(function(t,n){var o=e(n),a=(o.prop("type"),o.prop("name")),r=o.val(),s=o.is(w.checkbox),l=o.is(w.radio),c=-1!==a.indexOf("[]"),u=!!s&&o.is(":checked");a&&(c?(a=a.replace("[]",""),i[a]||(i[a]=[]),s?u?i[a].push(r||!0):i[a].push(!1):i[a].push(r)):l?void 0===i[a]&&(i[a]=!!u):i[a]=s?!!u&&(r||!0):r)}),i}},has:{field:function(e){return F.verbose("Checking for existence of a field with identifier",e),e=F.escape.string(e),"string"!=typeof e&&F.error(T.identifier,e),f.filter("#"+e).length>0||(f.filter('[name="'+e+'"]').length>0||f.filter("[data-"+C.validate+'="'+e+'"]').length>0)}},escape:{string:function(e){return e=String(e),e.replace(S.escape,"\\$&")}},add:{rule:function(e,t){F.add.field(e,t)},field:function(t,n){var i={};F.is.shorthandRules(n)?(n=e.isArray(n)?n:[n],i[t]={rules:[]},e.each(n,function(e,n){i[t].rules.push({type:n})})):i[t]=n,x=e.extend({},x,i),F.debug("Adding rules",i,x)},fields:function(t){var n;n=t&&F.is.shorthandFields(t)?F.get.fieldsFromShorthand(t):t,x=e.extend({},x,n)},prompt:function(t,n){var i=F.get.field(t),o=i.closest(m),a=o.children(w.prompt),r=0!==a.length;n="string"==typeof n?[n]:n,F.verbose("Adding field error state",t),o.addClass(k.error),y.inline&&(r||(a=y.templates.prompt(n),a.appendTo(o)),a.html(n[0]),r?F.verbose("Inline errors are disabled, no inline error added",t):y.transition&&void 0!==e.fn.transition&&O.transition("is supported")?(F.verbose("Displaying error with css transition",y.transition),a.transition(y.transition+" in",y.duration)):(F.verbose("Displaying error with fallback javascript animation"),a.fadeIn(y.duration)))},errors:function(e){F.debug("Adding form error messages",e),F.set.error(),g.html(y.templates.error(e))}},remove:{rule:function(t,n){var i=e.isArray(n)?n:[n];if(void 0==n)return F.debug("Removed all rules"),void(x[t].rules=[]);void 0!=x[t]&&e.isArray(x[t].rules)&&e.each(x[t].rules,function(e,n){-1!==i.indexOf(n.type)&&(F.debug("Removed rule",n.type),x[t].rules.splice(e,1))})},field:function(t){var n=e.isArray(t)?t:[t];e.each(n,function(e,t){F.remove.rule(t)})},rules:function(t,n){e.isArray(t)?e.each(fields,function(e,t){F.remove.rule(t,n)}):F.remove.rule(t,n)},fields:function(e){F.remove.field(e)},prompt:function(t){var n=F.get.field(t),i=n.closest(m),o=i.children(w.prompt);i.removeClass(k.error),y.inline&&o.is(":visible")&&(F.verbose("Removing prompt for field",t),y.transition&&void 0!==e.fn.transition&&O.transition("is supported")?o.transition(y.transition+" out",y.duration,function(){o.remove()}):o.fadeOut(y.duration,function(){o.remove()}))}},set:{success:function(){O.removeClass(k.error).addClass(k.success)},defaults:function(){f.each(function(){var t=e(this),n=t.filter(w.checkbox).length>0,i=n?t.is(":checked"):t.val();t.data(C.defaultValue,i)})},error:function(){O.removeClass(k.success).addClass(k.error)},value:function(e,t){var n={};return n[e]=t,F.set.values.call(D,n)},values:function(t){e.isEmptyObject(t)||e.each(t,function(t,n){var i,o=F.get.field(t),a=o.parent(),r=e.isArray(n),s=a.is(w.uiCheckbox),l=a.is(w.uiDropdown),c=o.is(w.radio)&&s,u=o.length>0;u&&(r&&s?(F.verbose("Selecting multiple",n,o),a.checkbox("uncheck"),e.each(n,function(e,t){i=o.filter('[value="'+t+'"]'),a=i.parent(),i.length>0&&a.checkbox("check")})):c?(F.verbose("Selecting radio value",n,o),o.filter('[value="'+n+'"]').parent(w.uiCheckbox).checkbox("check")):s?(F.verbose("Setting checkbox value",n,a),!0===n?a.checkbox("check"):a.checkbox("uncheck")):l?(F.verbose("Setting dropdown value",n,a),a.dropdown("set selected",n)):(F.verbose("Setting field value",n,o),o.val(n)))})}},validate:{form:function(e,t){var n=F.get.values();if(j)return!1;if(q=[],F.determine.isValid()){if(F.debug("Form has no validation errors, submitting"),F.set.success(),!0!==t)return y.onSuccess.call(D,e,n)}else if(F.debug("Form has errors"),F.set.error(),y.inline||F.add.errors(q),void 0!==O.data("moduleApi")&&e.stopImmediatePropagation(),!0!==t)return y.onFailure.call(D,q,n)},field:function(t,n,i){i=void 0===i||i,"string"==typeof t&&(F.verbose("Validating field",t),n=t,t=x[t]);var o=t.identifier||n,a=F.get.field(o),r=!!t.depends&&F.get.field(t.depends),s=!0,l=[];return t.identifier||(F.debug("Using field name as identifier",o),t.identifier=o),a.prop("disabled")?(F.debug("Field is disabled. Skipping",o),s=!0):t.optional&&F.is.blank(a)?(F.debug("Field is optional and blank. Skipping",o),s=!0):t.depends&&F.is.empty(r)?(F.debug("Field depends on another value that is not present or empty. Skipping",r),s=!0):void 0!==t.rules&&e.each(t.rules,function(e,n){F.has.field(o)&&!F.validate.rule(t,n)&&(F.debug("Field is invalid",o,n.type),l.push(F.get.prompt(n,t)),s=!1)}),s?(i&&(F.remove.prompt(o,l),y.onValid.call(a)),!0):(i&&(q=q.concat(l),F.add.prompt(o,l),y.onInvalid.call(a,l)),!1)},rule:function(t,n){var i=F.get.field(t.identifier),o=(n.type,i.val()),a=F.get.ancillaryValue(n),r=F.get.ruleName(n),s=y.rules[r];return e.isFunction(s)?(o=void 0===o||""===o||null===o?"":e.trim(o+""),s.call(i,o,a)):void F.error(T.noRule,r)}},setting:function(t,n){if(e.isPlainObject(t))e.extend(!0,y,t);else{if(void 0===n)return y[t];y[t]=n}},internal:function(t,n){if(e.isPlainObject(t))e.extend(!0,F,t);else{if(void 0===n)return F[t];F[t]=n}},debug:function(){!y.silent&&y.debug&&(y.performance?F.performance.log(arguments):(F.debug=Function.prototype.bind.call(console.info,console,y.name+":"),F.debug.apply(console,arguments)))},verbose:function(){!y.silent&&y.verbose&&y.debug&&(y.performance?F.performance.log(arguments):(F.verbose=Function.prototype.bind.call(console.info,console,y.name+":"),F.verbose.apply(console,arguments)))},error:function(){y.silent||(F.error=Function.prototype.bind.call(console.error,console,y.name+":"),F.error.apply(console,arguments))},performance:{log:function(e){var t,n,i;y.performance&&(t=(new Date).getTime(),i=r||t,n=t-i,r=t,s.push({Name:e[0],Arguments:[].slice.call(e,1)||"",Element:D,"Execution Time":n})),clearTimeout(F.performance.timer),F.performance.timer=setTimeout(F.performance.display,500)},display:function(){var t=y.name+":",n=0;r=!1,clearTimeout(F.performance.timer),e.each(s,function(e,t){n+=t["Execution Time"]}),t+=" "+n+"ms",a&&(t+=" '"+a+"'"),o.length>1&&(t+=" ("+o.length+")"),(void 0!==console.group||void 0!==console.table)&&s.length>0&&(console.groupCollapsed(t),console.table?console.table(s):e.each(s,function(e,t){console.log(t.Name+": "+t["Execution Time"]+"ms")}),console.groupEnd()),s=[]}},invoke:function(t,n,o){var a,r,s,l=E;return n=n||d,o=D||o,"string"==typeof t&&void 0!==l&&(t=t.split(/[\. ]/),a=t.length-1,e.each(t,function(n,i){var o=n!=a?i+t[n+1].charAt(0).toUpperCase()+t[n+1].slice(1):t;if(e.isPlainObject(l[o])&&n!=a)l=l[o];else{if(void 0!==l[o])return r=l[o],!1;if(!e.isPlainObject(l[i])||n==a)return void 0!==l[i]&&(r=l[i],!1);l=l[i]}})),e.isFunction(r)?s=r.apply(o,n):void 0!==r&&(s=r),e.isArray(i)?i.push(s):void 0!==i?i=[i,s]:void 0!==s&&(i=s),r}},F.initialize()}),void 0!==i?i:this},e.fn.form.settings={name:"Form",namespace:"form",debug:!1,verbose:!1,performance:!0,fields:!1,keyboardShortcuts:!0,on:"submit",inline:!1,delay:200,revalidate:!0,transition:"scale",duration:200,onValid:function(){},onInvalid:function(){},onSuccess:function(){return!0},onFailure:function(){return!1},metadata:{defaultValue:"default",validate:"validate"},regExp:{htmlID:/^[a-zA-Z][\w:.-]*$/g,bracket:/\[(.*)\]/i,decimal:/^\d+\.?\d*$/,email:/^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i,escape:/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,flags:/^\/(.*)\/(.*)?/,integer:/^\-?\d+$/,number:/^\-?\d*(\.\d+)?$/,url:/(https?:\/\/(?:www\.|(?!www))[^\s\.]+\.[^\s]{2,}|www\.[^\s]+\.[^\s]{2,})/i},text:{unspecifiedRule:"Please enter a valid value",unspecifiedField:"This field"},prompt:{empty:"{name} must have a value",checked:"{name} must be checked",email:"{name} must be a valid e-mail",url:"{name} must be a valid url",regExp:"{name} is not formatted correctly",integer:"{name} must be an integer",decimal:"{name} must be a decimal number",number:"{name} must be set to a number",is:'{name} must be "{ruleValue}"',isExactly:'{name} must be exactly "{ruleValue}"',not:'{name} cannot be set to "{ruleValue}"',notExactly:'{name} cannot be set to exactly "{ruleValue}"',contain:'{name} cannot contain "{ruleValue}"',containExactly:'{name} cannot contain exactly "{ruleValue}"',doesntContain:'{name} must contain "{ruleValue}"',doesntContainExactly:'{name} must contain exactly "{ruleValue}"',minLength:"{name} must be at least {ruleValue} characters",length:"{name} must be at least {ruleValue} characters",exactLength:"{name} must be exactly {ruleValue} characters",maxLength:"{name} cannot be longer than {ruleValue} characters",match:"{name} must match {ruleValue} field",different:"{name} must have a different value than {ruleValue} field",creditCard:"{name} must be a valid credit card number",minCount:"{name} must have at least {ruleValue} choices",exactCount:"{name} must have exactly {ruleValue} choices",maxCount:"{name} must have {ruleValue} or less choices"},selector:{checkbox:'input[type="checkbox"], input[type="radio"]',clear:".clear",field:"input, textarea, select",group:".field",input:"input",message:".error.message",prompt:".prompt.label",radio:'input[type="radio"]',reset:'.reset:not([type="reset"])',submit:'.submit:not([type="submit"])',uiCheckbox:".ui.checkbox",uiDropdown:".ui.dropdown"},className:{error:"error",label:"ui prompt label",pressed:"down",success:"success"},error:{identifier:"You must specify a string identifier for each field",method:"The method you called is not defined.",noRule:"There is no rule matching the one you specified",oldSyntax:"Starting in 2.0 forms now only take a single settings object. Validation settings converted to new syntax automatically."},templates:{error:function(t){var n='
        ';return e.each(t,function(e,t){n+="
      • "+t+"
      • "}),n+="
      ",e(n)},prompt:function(t){return e("
      ").addClass("ui basic red pointing prompt label").html(t[0])}},rules:{empty:function(t){return!(void 0===t||""===t||e.isArray(t)&&0===t.length)},checked:function(){return e(this).filter(":checked").length>0},email:function(t){return e.fn.form.settings.regExp.email.test(t)},url:function(t){return e.fn.form.settings.regExp.url.test(t)},regExp:function(t,n){if(n instanceof RegExp)return t.match(n);var i,o=n.match(e.fn.form.settings.regExp.flags);return o&&(n=o.length>=2?o[1]:n,i=o.length>=3?o[2]:""),t.match(new RegExp(n,i))},integer:function(t,n){var i,o,a,r=e.fn.form.settings.regExp.integer;return n&&-1===["",".."].indexOf(n)&&(-1==n.indexOf("..")?r.test(n)&&(i=o=n-0):(a=n.split("..",2),r.test(a[0])&&(i=a[0]-0),r.test(a[1])&&(o=a[1]-0))),r.test(t)&&(void 0===i||t>=i)&&(void 0===o||t<=o)},decimal:function(t){return e.fn.form.settings.regExp.decimal.test(t)},number:function(t){return e.fn.form.settings.regExp.number.test(t)},is:function(e,t){return t="string"==typeof t?t.toLowerCase():t,(e="string"==typeof e?e.toLowerCase():e)==t},isExactly:function(e,t){return e==t},not:function(e,t){return e="string"==typeof e?e.toLowerCase():e,t="string"==typeof t?t.toLowerCase():t,e!=t},notExactly:function(e,t){return e!=t},contains:function(t,n){return n=n.replace(e.fn.form.settings.regExp.escape,"\\$&"),-1!==t.search(new RegExp(n,"i"))},containsExactly:function(t,n){return n=n.replace(e.fn.form.settings.regExp.escape,"\\$&"),-1!==t.search(new RegExp(n))},doesntContain:function(t,n){return n=n.replace(e.fn.form.settings.regExp.escape,"\\$&"),-1===t.search(new RegExp(n,"i"))},doesntContainExactly:function(t,n){return n=n.replace(e.fn.form.settings.regExp.escape,"\\$&"),-1===t.search(new RegExp(n))},minLength:function(e,t){return void 0!==e&&e.length>=t},length:function(e,t){return void 0!==e&&e.length>=t},exactLength:function(e,t){return void 0!==e&&e.length==t},maxLength:function(e,t){return void 0!==e&&e.length<=t},match:function(t,n){var i;e(this);return e('[data-validate="'+n+'"]').length>0?i=e('[data-validate="'+n+'"]').val():e("#"+n).length>0?i=e("#"+n).val():e('[name="'+n+'"]').length>0?i=e('[name="'+n+'"]').val():e('[name="'+n+'[]"]').length>0&&(i=e('[name="'+n+'[]"]')),void 0!==i&&t.toString()==i.toString()},different:function(t,n){var i;e(this);return e('[data-validate="'+n+'"]').length>0?i=e('[data-validate="'+n+'"]').val():e("#"+n).length>0?i=e("#"+n).val():e('[name="'+n+'"]').length>0?i=e('[name="'+n+'"]').val():e('[name="'+n+'[]"]').length>0&&(i=e('[name="'+n+'[]"]')),void 0!==i&&t.toString()!==i.toString()},creditCard:function(t,n){var i,o,a={visa:{pattern:/^4/,length:[16]},amex:{pattern:/^3[47]/,length:[15]},mastercard:{pattern:/^5[1-5]/,length:[16]},discover:{pattern:/^(6011|622(12[6-9]|1[3-9][0-9]|[2-8][0-9]{2}|9[0-1][0-9]|92[0-5]|64[4-9])|65)/,length:[16]},unionPay:{pattern:/^(62|88)/,length:[16,17,18,19]},jcb:{pattern:/^35(2[89]|[3-8][0-9])/,length:[16]},maestro:{pattern:/^(5018|5020|5038|6304|6759|676[1-3])/,length:[12,13,14,15,16,17,18,19]},dinersClub:{pattern:/^(30[0-5]|^36)/,length:[14]},laser:{pattern:/^(6304|670[69]|6771)/,length:[16,17,18,19]},visaElectron:{pattern:/^(4026|417500|4508|4844|491(3|7))/,length:[16]}},r={},s=!1,l="string"==typeof n&&n.split(",");if("string"==typeof t&&0!==t.length){if(t=t.replace(/[\-]/g,""),l&&(e.each(l,function(n,i){(o=a[i])&&(r={length:-1!==e.inArray(t.length,o.length),pattern:-1!==t.search(o.pattern)},r.length&&r.pattern&&(s=!0))}),!s))return!1;if(i={number:-1!==e.inArray(t.length,a.unionPay.length),pattern:-1!==t.search(a.unionPay.pattern)},i.number&&i.pattern)return!0;for(var c=t.length,u=0,d=[[0,1,2,3,4,5,6,7,8,9],[0,2,4,6,8,1,3,5,7,9]],f=0;c--;)f+=d[u][parseInt(t.charAt(c),10)],u^=1;return f%10==0&&f>0}},minCount:function(e,t){return 0==t||(1==t?""!==e:e.split(",").length>=t)},exactCount:function(e,t){return 0==t?""===e:1==t?""!==e&&-1===e.search(","):e.split(",").length==t},maxCount:function(e,t){return 0!=t&&(1==t?-1===e.search(","):e.split(",").length<=t)}}}}(jQuery,window,document),function(e,t,n,i){"use strict";t=void 0!==t&&t.Math==Math?t:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")(),e.fn.accordion=function(n){var i,o=e(this),a=(new Date).getTime(),r=[],s=arguments[0],l="string"==typeof s,c=[].slice.call(arguments,1);t.requestAnimationFrame||t.mozRequestAnimationFrame||t.webkitRequestAnimationFrame||t.msRequestAnimationFrame;return o.each(function(){var u,d,f=e.isPlainObject(n)?e.extend(!0,{},e.fn.accordion.settings,n):e.extend({},e.fn.accordion.settings),m=f.className,g=f.namespace,v=f.selector,p=f.error,h="."+g,b="module-"+g,y=o.selector||"",x=e(this),C=x.find(v.title),w=x.find(v.content),k=this,S=x.data(b);d={initialize:function(){d.debug("Initializing",x),d.bind.events(),f.observeChanges&&d.observeChanges(),d.instantiate()},instantiate:function(){S=d,x.data(b,d)},destroy:function(){d.debug("Destroying previous instance",x),x.off(h).removeData(b)},refresh:function(){C=x.find(v.title),w=x.find(v.content)},observeChanges:function(){"MutationObserver"in t&&(u=new MutationObserver(function(e){d.debug("DOM tree modified, updating selector cache"),d.refresh()}),u.observe(k,{childList:!0,subtree:!0}),d.debug("Setting up mutation observer",u))},bind:{events:function(){d.debug("Binding delegated events"),x.on(f.on+h,v.trigger,d.event.click)}},event:{click:function(){d.toggle.call(this)}},toggle:function(t){var n=void 0!==t?"number"==typeof t?C.eq(t):e(t).closest(v.title):e(this).closest(v.title),i=n.next(w),o=i.hasClass(m.animating),a=i.hasClass(m.active),r=a&&!o,s=!a&&o;d.debug("Toggling visibility of content",n),r||s?f.collapsible?d.close.call(n):d.debug("Cannot close accordion content collapsing is disabled"):d.open.call(n)},open:function(t){var n=void 0!==t?"number"==typeof t?C.eq(t):e(t).closest(v.title):e(this).closest(v.title),i=n.next(w),o=i.hasClass(m.animating);if(i.hasClass(m.active)||o)return void d.debug("Accordion already open, skipping",i);d.debug("Opening accordion content",n),f.onOpening.call(i),f.exclusive&&d.closeOthers.call(n),n.addClass(m.active),i.stop(!0,!0).addClass(m.animating),f.animateChildren&&(void 0!==e.fn.transition&&x.transition("is supported")?i.children().transition({animation:"fade in",queue:!1,useFailSafe:!0,debug:f.debug,verbose:f.verbose,duration:f.duration}):i.children().stop(!0,!0).animate({opacity:1},f.duration,d.resetOpacity)),i.slideDown(f.duration,f.easing,function(){i.removeClass(m.animating).addClass(m.active),d.reset.display.call(this),f.onOpen.call(this),f.onChange.call(this)})},close:function(t){var n=void 0!==t?"number"==typeof t?C.eq(t):e(t).closest(v.title):e(this).closest(v.title),i=n.next(w),o=i.hasClass(m.animating),a=i.hasClass(m.active),r=!a&&o,s=a&&o;!a&&!r||s||(d.debug("Closing accordion content",i),f.onClosing.call(i),n.removeClass(m.active),i.stop(!0,!0).addClass(m.animating),f.animateChildren&&(void 0!==e.fn.transition&&x.transition("is supported")?i.children().transition({animation:"fade out",queue:!1,useFailSafe:!0,debug:f.debug,verbose:f.verbose,duration:f.duration}):i.children().stop(!0,!0).animate({opacity:0},f.duration,d.resetOpacity)),i.slideUp(f.duration,f.easing,function(){i.removeClass(m.animating).removeClass(m.active),d.reset.display.call(this),f.onClose.call(this),f.onChange.call(this)}))},closeOthers:function(t){var n,i,o,a=void 0!==t?C.eq(t):e(this).closest(v.title),r=a.parents(v.content).prev(v.title),s=a.closest(v.accordion),l=v.title+"."+m.active+":visible",c=v.content+"."+m.active+":visible";f.closeNested?(n=s.find(l).not(r),o=n.next(w)):(n=s.find(l).not(r),i=s.find(c).find(l).not(r),n=n.not(i),o=n.next(w)),n.length>0&&(d.debug("Exclusive enabled, closing other content",n),n.removeClass(m.active),o.removeClass(m.animating).stop(!0,!0),f.animateChildren&&(void 0!==e.fn.transition&&x.transition("is supported")?o.children().transition({animation:"fade out",useFailSafe:!0,debug:f.debug,verbose:f.verbose,duration:f.duration}):o.children().stop(!0,!0).animate({opacity:0},f.duration,d.resetOpacity)),o.slideUp(f.duration,f.easing,function(){e(this).removeClass(m.active),d.reset.display.call(this)}))},reset:{display:function(){d.verbose("Removing inline display from element",this),e(this).css("display",""),""===e(this).attr("style")&&e(this).attr("style","").removeAttr("style")},opacity:function(){d.verbose("Removing inline opacity from element",this),e(this).css("opacity",""),""===e(this).attr("style")&&e(this).attr("style","").removeAttr("style")}},setting:function(t,n){if(d.debug("Changing setting",t,n),e.isPlainObject(t))e.extend(!0,f,t);else{if(void 0===n)return f[t];e.isPlainObject(f[t])?e.extend(!0,f[t],n):f[t]=n}},internal:function(t,n){if(d.debug("Changing internal",t,n),void 0===n)return d[t];e.isPlainObject(t)?e.extend(!0,d,t):d[t]=n},debug:function(){!f.silent&&f.debug&&(f.performance?d.performance.log(arguments):(d.debug=Function.prototype.bind.call(console.info,console,f.name+":"),d.debug.apply(console,arguments)))},verbose:function(){ -!f.silent&&f.verbose&&f.debug&&(f.performance?d.performance.log(arguments):(d.verbose=Function.prototype.bind.call(console.info,console,f.name+":"),d.verbose.apply(console,arguments)))},error:function(){f.silent||(d.error=Function.prototype.bind.call(console.error,console,f.name+":"),d.error.apply(console,arguments))},performance:{log:function(e){var t,n,i;f.performance&&(t=(new Date).getTime(),i=a||t,n=t-i,a=t,r.push({Name:e[0],Arguments:[].slice.call(e,1)||"",Element:k,"Execution Time":n})),clearTimeout(d.performance.timer),d.performance.timer=setTimeout(d.performance.display,500)},display:function(){var t=f.name+":",n=0;a=!1,clearTimeout(d.performance.timer),e.each(r,function(e,t){n+=t["Execution Time"]}),t+=" "+n+"ms",y&&(t+=" '"+y+"'"),(void 0!==console.group||void 0!==console.table)&&r.length>0&&(console.groupCollapsed(t),console.table?console.table(r):e.each(r,function(e,t){console.log(t.Name+": "+t["Execution Time"]+"ms")}),console.groupEnd()),r=[]}},invoke:function(t,n,o){var a,r,s,l=S;return n=n||c,o=k||o,"string"==typeof t&&void 0!==l&&(t=t.split(/[\. ]/),a=t.length-1,e.each(t,function(n,i){var o=n!=a?i+t[n+1].charAt(0).toUpperCase()+t[n+1].slice(1):t;if(e.isPlainObject(l[o])&&n!=a)l=l[o];else{if(void 0!==l[o])return r=l[o],!1;if(!e.isPlainObject(l[i])||n==a)return void 0!==l[i]?(r=l[i],!1):(d.error(p.method,t),!1);l=l[i]}})),e.isFunction(r)?s=r.apply(o,n):void 0!==r&&(s=r),e.isArray(i)?i.push(s):void 0!==i?i=[i,s]:void 0!==s&&(i=s),r}},l?(void 0===S&&d.initialize(),d.invoke(s)):(void 0!==S&&S.invoke("destroy"),d.initialize())}),void 0!==i?i:this},e.fn.accordion.settings={name:"Accordion",namespace:"accordion",silent:!1,debug:!1,verbose:!1,performance:!0,on:"click",observeChanges:!0,exclusive:!0,collapsible:!0,closeNested:!1,animateChildren:!0,duration:350,easing:"easeOutQuad",onOpening:function(){},onOpen:function(){},onClosing:function(){},onClose:function(){},onChange:function(){},error:{method:"The method you called is not defined"},className:{active:"active",animating:"animating"},selector:{accordion:".accordion",title:".title",trigger:".title",content:".content"}},e.extend(e.easing,{easeOutQuad:function(e,t,n,i,o){return-i*(t/=o)*(t-2)+n}})}(jQuery,window,document),function(e,t,n,i){"use strict";t=void 0!==t&&t.Math==Math?t:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")(),e.fn.checkbox=function(i){var o,a=e(this),r=a.selector||"",s=(new Date).getTime(),l=[],c=arguments[0],u="string"==typeof c,d=[].slice.call(arguments,1);return a.each(function(){var a,f,m=e.extend(!0,{},e.fn.checkbox.settings,i),g=m.className,v=m.namespace,p=m.selector,h=m.error,b="."+v,y="module-"+v,x=e(this),C=e(this).children(p.label),w=e(this).children(p.input),k=w[0],S=!1,T=!1,A=x.data(y),R=this;f={initialize:function(){f.verbose("Initializing checkbox",m),f.create.label(),f.bind.events(),f.set.tabbable(),f.hide.input(),f.observeChanges(),f.instantiate(),f.setup()},instantiate:function(){f.verbose("Storing instance of module",f),A=f,x.data(y,f)},destroy:function(){f.verbose("Destroying module"),f.unbind.events(),f.show.input(),x.removeData(y)},fix:{reference:function(){x.is(p.input)&&(f.debug("Behavior called on adjusting invoked element"),x=x.closest(p.checkbox),f.refresh())}},setup:function(){f.set.initialLoad(),f.is.indeterminate()?(f.debug("Initial value is indeterminate"),f.indeterminate()):f.is.checked()?(f.debug("Initial value is checked"),f.check()):(f.debug("Initial value is unchecked"),f.uncheck()),f.remove.initialLoad()},refresh:function(){C=x.children(p.label),w=x.children(p.input),k=w[0]},hide:{input:function(){f.verbose("Modifying z-index to be unselectable"),w.addClass(g.hidden)}},show:{input:function(){f.verbose("Modifying z-index to be selectable"),w.removeClass(g.hidden)}},observeChanges:function(){"MutationObserver"in t&&(a=new MutationObserver(function(e){f.debug("DOM tree modified, updating selector cache"),f.refresh()}),a.observe(R,{childList:!0,subtree:!0}),f.debug("Setting up mutation observer",a))},attachEvents:function(t,n){var i=e(t);n=e.isFunction(f[n])?f[n]:f.toggle,i.length>0?(f.debug("Attaching checkbox events to element",t,n),i.on("click"+b,n)):f.error(h.notFound)},event:{click:function(t){var n=e(t.target);return n.is(p.input)?void f.verbose("Using default check action on initialized checkbox"):n.is(p.link)?void f.debug("Clicking link inside checkbox, skipping toggle"):(f.toggle(),w.focus(),void t.preventDefault())},keydown:function(e){var t=e.which,n={enter:13,space:32,escape:27};t==n.escape?(f.verbose("Escape key pressed blurring field"),w.blur(),T=!0):e.ctrlKey||t!=n.space&&t!=n.enter?T=!1:(f.verbose("Enter/space key pressed, toggling checkbox"),f.toggle(),T=!0)},keyup:function(e){T&&e.preventDefault()}},check:function(){f.should.allowCheck()&&(f.debug("Checking checkbox",w),f.set.checked(),f.should.ignoreCallbacks()||(m.onChecked.call(k),m.onChange.call(k)))},uncheck:function(){f.should.allowUncheck()&&(f.debug("Unchecking checkbox"),f.set.unchecked(),f.should.ignoreCallbacks()||(m.onUnchecked.call(k),m.onChange.call(k)))},indeterminate:function(){if(f.should.allowIndeterminate())return void f.debug("Checkbox is already indeterminate");f.debug("Making checkbox indeterminate"),f.set.indeterminate(),f.should.ignoreCallbacks()||(m.onIndeterminate.call(k),m.onChange.call(k))},determinate:function(){if(f.should.allowDeterminate())return void f.debug("Checkbox is already determinate");f.debug("Making checkbox determinate"),f.set.determinate(),f.should.ignoreCallbacks()||(m.onDeterminate.call(k),m.onChange.call(k))},enable:function(){if(f.is.enabled())return void f.debug("Checkbox is already enabled");f.debug("Enabling checkbox"),f.set.enabled(),m.onEnable.call(k),m.onEnabled.call(k)},disable:function(){if(f.is.disabled())return void f.debug("Checkbox is already disabled");f.debug("Disabling checkbox"),f.set.disabled(),m.onDisable.call(k),m.onDisabled.call(k)},get:{radios:function(){var t=f.get.name();return e('input[name="'+t+'"]').closest(p.checkbox)},otherRadios:function(){return f.get.radios().not(x)},name:function(){return w.attr("name")}},is:{initialLoad:function(){return S},radio:function(){return w.hasClass(g.radio)||"radio"==w.attr("type")},indeterminate:function(){return void 0!==w.prop("indeterminate")&&w.prop("indeterminate")},checked:function(){return void 0!==w.prop("checked")&&w.prop("checked")},disabled:function(){return void 0!==w.prop("disabled")&&w.prop("disabled")},enabled:function(){return!f.is.disabled()},determinate:function(){return!f.is.indeterminate()},unchecked:function(){return!f.is.checked()}},should:{allowCheck:function(){return f.is.determinate()&&f.is.checked()&&!f.should.forceCallbacks()?(f.debug("Should not allow check, checkbox is already checked"),!1):!1!==m.beforeChecked.apply(k)||(f.debug("Should not allow check, beforeChecked cancelled"),!1)},allowUncheck:function(){return f.is.determinate()&&f.is.unchecked()&&!f.should.forceCallbacks()?(f.debug("Should not allow uncheck, checkbox is already unchecked"),!1):!1!==m.beforeUnchecked.apply(k)||(f.debug("Should not allow uncheck, beforeUnchecked cancelled"),!1)},allowIndeterminate:function(){return f.is.indeterminate()&&!f.should.forceCallbacks()?(f.debug("Should not allow indeterminate, checkbox is already indeterminate"),!1):!1!==m.beforeIndeterminate.apply(k)||(f.debug("Should not allow indeterminate, beforeIndeterminate cancelled"),!1)},allowDeterminate:function(){return f.is.determinate()&&!f.should.forceCallbacks()?(f.debug("Should not allow determinate, checkbox is already determinate"),!1):!1!==m.beforeDeterminate.apply(k)||(f.debug("Should not allow determinate, beforeDeterminate cancelled"),!1)},forceCallbacks:function(){return f.is.initialLoad()&&m.fireOnInit},ignoreCallbacks:function(){return S&&!m.fireOnInit}},can:{change:function(){return!(x.hasClass(g.disabled)||x.hasClass(g.readOnly)||w.prop("disabled")||w.prop("readonly"))},uncheck:function(){return"boolean"==typeof m.uncheckable?m.uncheckable:!f.is.radio()}},set:{initialLoad:function(){S=!0},checked:function(){if(f.verbose("Setting class to checked"),x.removeClass(g.indeterminate).addClass(g.checked),f.is.radio()&&f.uncheckOthers(),!f.is.indeterminate()&&f.is.checked())return void f.debug("Input is already checked, skipping input property change");f.verbose("Setting state to checked",k),w.prop("indeterminate",!1).prop("checked",!0),f.trigger.change()},unchecked:function(){if(f.verbose("Removing checked class"),x.removeClass(g.indeterminate).removeClass(g.checked),!f.is.indeterminate()&&f.is.unchecked())return void f.debug("Input is already unchecked");f.debug("Setting state to unchecked"),w.prop("indeterminate",!1).prop("checked",!1),f.trigger.change()},indeterminate:function(){if(f.verbose("Setting class to indeterminate"),x.addClass(g.indeterminate),f.is.indeterminate())return void f.debug("Input is already indeterminate, skipping input property change");f.debug("Setting state to indeterminate"),w.prop("indeterminate",!0),f.trigger.change()},determinate:function(){if(f.verbose("Removing indeterminate class"),x.removeClass(g.indeterminate),f.is.determinate())return void f.debug("Input is already determinate, skipping input property change");f.debug("Setting state to determinate"),w.prop("indeterminate",!1)},disabled:function(){if(f.verbose("Setting class to disabled"),x.addClass(g.disabled),f.is.disabled())return void f.debug("Input is already disabled, skipping input property change");f.debug("Setting state to disabled"),w.prop("disabled","disabled"),f.trigger.change()},enabled:function(){if(f.verbose("Removing disabled class"),x.removeClass(g.disabled),f.is.enabled())return void f.debug("Input is already enabled, skipping input property change");f.debug("Setting state to enabled"),w.prop("disabled",!1),f.trigger.change()},tabbable:function(){f.verbose("Adding tabindex to checkbox"),void 0===w.attr("tabindex")&&w.attr("tabindex",0)}},remove:{initialLoad:function(){S=!1}},trigger:{change:function(){var e=n.createEvent("HTMLEvents"),t=w[0];t&&(f.verbose("Triggering native change event"),e.initEvent("change",!0,!1),t.dispatchEvent(e))}},create:{label:function(){w.prevAll(p.label).length>0?(w.prev(p.label).detach().insertAfter(w),f.debug("Moving existing label",C)):f.has.label()||(C=e("