Update trezor-connect.js to v4 (#856)

* Update trezor connect.

* Re-ignore trezor connect, fix typings.
This commit is contained in:
William O'Beirne 2018-01-18 00:16:47 -05:00 committed by Daniel Ternyak
parent 9c9d6c2f61
commit 1713e3fa29
3 changed files with 923 additions and 968 deletions

View File

@ -1,5 +1,5 @@
import DPATHS from 'config/dpaths';
import { TrezorWallet } from 'libs/wallet';
import { TrezorWallet, TREZOR_MINIMUM_FIRMWARE } from 'libs/wallet';
import React, { Component } from 'react';
import translate, { translateRaw } from 'translations';
import TrezorConnect from 'vendor/trezor-connect';
@ -97,7 +97,7 @@ export class TrezorDecrypt extends Component<Props, State> {
error: null
});
TrezorConnect.getXPubKey(
(TrezorConnect as any).getXPubKey(
dPath,
res => {
if (res.success) {
@ -114,7 +114,7 @@ export class TrezorDecrypt extends Component<Props, State> {
});
}
},
'1.5.2'
TREZOR_MINIMUM_FIRMWARE
);
};

View File

@ -10,6 +10,8 @@ import mapValues from 'lodash/mapValues';
import { IFullWallet } from '../IWallet';
import { translateRaw } from 'translations';
export const TREZOR_MINIMUM_FIRMWARE = '1.5.2';
export class TrezorWallet extends DeterministicWallet implements IFullWallet {
public signRawTransaction(tx: EthTx): Promise<Buffer> {
return new Promise((resolve, reject) => {
@ -17,7 +19,7 @@ export class TrezorWallet extends DeterministicWallet implements IFullWallet {
// stripHexPrefixAndLower identical to ethFuncs.getNakedAddress
const cleanedTx = mapValues(mapValues(strTx, stripHexPrefixAndLower), padLeftEven);
TrezorConnect.ethereumSignTx(
(TrezorConnect as any).ethereumSignTx(
// Args
this.getPath(),
cleanedTx.nonce,
@ -51,7 +53,6 @@ export class TrezorWallet extends DeterministicWallet implements IFullWallet {
public signMessage = () => Promise.reject(new Error('Signing via Trezor not yet supported.'));
// trezor-connect.js doesn't provide the promise return type
public displayAddress = (dPath?: string, index?: number): Promise<any> => {
if (!dPath) {
dPath = this.dPath;
@ -59,7 +60,20 @@ export class TrezorWallet extends DeterministicWallet implements IFullWallet {
if (!index) {
index = this.index;
}
return TrezorConnect.ethereumGetAddress(dPath + '/' + index);
return new Promise((resolve, reject) => {
(TrezorConnect as any).ethereumGetAddress(
dPath + '/' + index,
res => {
if (res.error) {
reject(res.error);
} else {
resolve(res);
}
},
TREZOR_MINIMUM_FIRMWARE
);
});
};
public getWalletType(): string {

View File

@ -1,12 +1,12 @@
/* prettier-ignore */
/* eslint-ignore */
/* prettier-ignore */
/**
* (C) 2017 SatoshiLabs
*
* GPLv3
*/
var VERSION = 3;
var VERSION = 4;
if (!Array.isArray) {
Array.isArray = function(arg) {
@ -24,7 +24,8 @@ function _fwStrFix(obj, fw) {
return obj;
}
('use strict');
'use strict';
var chrome = window.chrome;
var IS_CHROME_APP = chrome && chrome.app && chrome.app.window;
@ -37,44 +38,32 @@ var ERR_CHROME_NOT_CONNECTED = 'Internal Chrome popup is not responding.';
var DISABLE_LOGIN_BUTTONS = window.TREZOR_DISABLE_LOGIN_BUTTONS || false;
var CHROME_URL = window.TREZOR_CHROME_URL || './chrome/wrapper.html';
var POPUP_URL =
window.TREZOR_POPUP_URL || 'https://connect.trezor.io/' + VERSION + '/popup/popup.html';
var POPUP_PATH = window.TREZOR_POPUP_PATH || 'https://connect.trezor.io/' + VERSION;
var POPUP_ORIGIN = window.TREZOR_POPUP_ORIGIN || 'https://connect.trezor.io';
var INSIGHT_URLS = window.TREZOR_INSIGHT_URLS || [
'https://btc-bitcore1.trezor.io/api/',
'https://btc-bitcore3.trezor.io/api/'
];
var POPUP_PATH = window.TREZOR_POPUP_PATH || POPUP_ORIGIN + '/' + VERSION;
if (window.location.hostname === 'localhost' && !window.TREZOR_POPUP_ORIGIN) {
// development settings
//POPUP_ORIGIN = window.location.origin;
//POPUP_PATH = POPUP_ORIGIN;
}
var POPUP_URL = window.TREZOR_POPUP_URL || POPUP_PATH + '/popup/popup.html';
var POPUP_INIT_TIMEOUT = 15000;
/**
* Public API.
*/
function TrezorConnect() {
class TrezorConnect {
constructor() {
this.manager = new PopupManager();
this.LOGIN_CSS = '<style>@import url("@connect_path@/login_buttons.css")</style>';
this.LOGIN_ONCLICK =
'TrezorConnect.requestLogin(' +
"'@hosticon@','@challenge_hidden@','@challenge_visual@','@callback@'" +
')';
this.LOGIN_HTML =
'<div id="trezorconnect-wrapper">' +
' <a id="trezorconnect-button" onclick="' +
this.LOGIN_ONCLICK +
'">' +
' <span id="trezorconnect-icon"></span>' +
' <span id="trezorconnect-text">@text@</span>' +
' </a>' +
' <span id="trezorconnect-info">' +
' <a id="trezorconnect-infolink" href="https://www.buytrezor.com/"' +
' target="_blank">What is TREZOR?</a>' +
' </span>' +
'</div>';
}
var manager = new PopupManager();
/**
* Popup errors.
*/
this.ERR_TIMED_OUT = ERR_TIMED_OUT;
this.ERR_WINDOW_CLOSED = ERR_WINDOW_CLOSED;
this.ERR_WINDOW_BLOCKED = ERR_WINDOW_BLOCKED;
this.ERR_ALREADY_WAITING = ERR_ALREADY_WAITING;
this.ERR_CHROME_NOT_CONNECTED = ERR_CHROME_NOT_CONNECTED;
/**
* Open the popup for further communication. All API functions open the
@ -82,7 +71,7 @@ class TrezorConnect {
* asynchronously, use `open` first to avoid popup blockers.
* @param {function(?Error)} callback
*/
open(callback) {
this.open = function (callback) {
var onchannel = function (result) {
if (result instanceof Error) {
callback(result);
@ -90,41 +79,65 @@ class TrezorConnect {
callback();
}
};
this.manager.waitForChannel(onchannel);
}
manager.waitForChannel(onchannel);
};
/**
* Close the opened popup, if any.
*/
close() {
this.manager.close();
}
this.close = function () { manager.close(); };
/**
* Enable or disable closing the opened popup after a successful call.
* @param {boolean} value
*/
closeAfterSuccess(value) {
this.manager.closeAfterSuccess = value;
}
this.closeAfterSuccess = function (value) { manager.closeAfterSuccess = value; };
/**
* Enable or disable closing the opened popup after a failed call.
* @param {boolean} value
*/
closeAfterFailure(value) {
this.manager.closeAfterFailure = value;
}
this.closeAfterFailure = function (value) { manager.closeAfterFailure = value; };
/**
* Set bitcore server
* @param {string|Array<string>} value
*/
setBitcoreURLS(value) {
this.setBitcoreURLS = function(value) {
if (typeof value === 'string') {
this.manager.bitcoreURLS = [value];
manager.bitcoreURLS = [ value ];
}else if (value instanceof Array) {
this.manager.bitcoreURLS = value;
manager.bitcoreURLS = value;
}
}
/**
* Set currency. Human readable coin name
* @param {string|Array<string>} value
*/
this.setCurrency = function(value) {
if (typeof value === 'string') {
manager.currency = value;
}
}
/**
* Set currency units (mBTC, BTC)
* @param {string|Array<string>} value
*/
this.setCurrencyUnits = function(value) {
if (typeof value === 'string') {
manager.currencyUnits = value;
}
}
/**
* Set coin info json url
* @param {string|Array<string>} value
*/
this.setCoinInfoURL = function(value) {
if (typeof value === 'string') {
manager.coinInfoURL = value;
}
}
@ -132,24 +145,27 @@ class TrezorConnect {
* Set max. limit for account discovery
* @param {number} value
*/
setAccountDiscoveryLimit(value) {
if (!isNaN(value)) this.manager.accountDiscoveryLimit = value;
this.setAccountDiscoveryLimit = function(value) {
if(!isNaN(value))
manager.accountDiscoveryLimit = value;
}
/**
* Set max. gap for account discovery
* @param {number} value
*/
setAccountDiscoveryGapLength(value) {
if (!isNaN(value)) this.manager.accountDiscoveryGapLength = value;
this.setAccountDiscoveryGapLength = function(value) {
if(!isNaN(value))
manager.accountDiscoveryGapLength = value;
}
/**
* Set discovery BIP44 coin type
* @param {number} value
*/
setAccountDiscoveryBip44CoinType(value) {
if (!isNaN(value)) this.manager.accountDiscoveryBip44CoinType = value;
this.setAccountDiscoveryBip44CoinType = function(value) {
if(!isNaN(value))
manager.accountDiscoveryBip44CoinType = value;
}
/**
@ -172,87 +188,56 @@ class TrezorConnect {
* @param {function(XPubKeyResult)} callback
* @param {?(string|array<number>)} requiredFirmware
*/
getXPubKey(path, callback, requiredFirmware) {
this.getXPubKey = function (path, callback, requiredFirmware) {
if (typeof path === 'string') {
path = parseHDPath(path);
}
this.manager.sendWithChannel(
_fwStrFix(
{
manager.sendWithChannel(_fwStrFix({
type: 'xpubkey',
path: path
},
requiredFirmware
),
callback
);
}
}, requiredFirmware), callback);
};
getFreshAddress(callback, requiredFirmware) {
this.getFreshAddress = function (callback, requiredFirmware) {
var wrapperCallback = function (result) {
if (result.success) {
callback({success: true, address: result.freshAddress});
} else {
callback(result);
}
};
this.manager.sendWithChannel(
_fwStrFix(
{
type: 'accountinfo'
},
requiredFirmware
),
wrapperCallback
);
}
getAccountInfo(input, callback, requiredFirmware) {
manager.sendWithChannel(_fwStrFix({
type: 'accountinfo'
}, requiredFirmware), wrapperCallback);
}
this.getAccountInfo = function (input, callback, requiredFirmware) {
try {
var description = parseAccountInfoInput(input);
this.manager.sendWithChannel(
_fwStrFix(
{
manager.sendWithChannel(_fwStrFix({
type: 'accountinfo',
description: description
},
requiredFirmware
),
callback
);
description: input
}, requiredFirmware), callback);
} catch(e) {
callback({success: false, error: e});
}
}
getAllAccountsInfo(callback, requiredFirmware) {
this.getAllAccountsInfo = function(callback, requiredFirmware){
try {
this.manager.sendWithChannel(
_fwStrFix(
{
manager.sendWithChannel(_fwStrFix({
type: 'allaccountsinfo',
description: 'all'
},
requiredFirmware
),
callback
);
}, requiredFirmware), callback);
} catch(e) {
callback({success: false, error: e});
}
}
getBalance(callback, requiredFirmware) {
this.manager.sendWithChannel(
_fwStrFix(
{
this.getBalance = function (callback, requiredFirmware) {
manager.sendWithChannel(_fwStrFix({
type: 'accountinfo'
},
requiredFirmware
),
callback
);
}, requiredFirmware), callback)
}
/**
@ -274,28 +259,22 @@ class TrezorConnect {
*
* @see https://github.com/trezor/trezor-common/blob/master/protob/types.proto
*/
signTx(inputs, outputs, callback, requiredFirmware, coin) {
this.manager.sendWithChannel(
_fwStrFix(
{
this.signTx = function (inputs, outputs, callback, requiredFirmware, coin) {
manager.sendWithChannel(_fwStrFix({
type: 'signtx',
inputs: inputs,
outputs: outputs,
coin: coin
},
requiredFirmware
),
callback
);
}
}, requiredFirmware), callback);
};
// new implementation with ethereum at beginnig
ethereumSignTx() {
this.ethereumSignTx = function() {
this.signEthereumTx.apply(this, arguments);
}
// old fallback
signEthereumTx(
this.signEthereumTx = function (
address_n,
nonce,
gas_price,
@ -313,9 +292,7 @@ class TrezorConnect {
if (typeof address_n === 'string') {
address_n = parseHDPath(address_n);
}
this.manager.sendWithChannel(
_fwStrFix(
{
manager.sendWithChannel(_fwStrFix({
type: 'signethtx',
address_n: address_n,
nonce: nonce,
@ -324,13 +301,9 @@ class TrezorConnect {
to: to,
value: value,
data: data,
chain_id: chain_id
},
requiredFirmware
),
callback
);
}
chain_id: chain_id,
}, requiredFirmware), callback);
};
/**
* @typedef TxRecipient
@ -348,18 +321,12 @@ class TrezorConnect {
* @param {function(SignTxResult)} callback
* @param {?(string|array<number>)} requiredFirmware
*/
composeAndSignTx(recipients, callback, requiredFirmware) {
this.manager.sendWithChannel(
_fwStrFix(
{
this.composeAndSignTx = function (recipients, callback, requiredFirmware) {
manager.sendWithChannel(_fwStrFix({
type: 'composetx',
recipients: recipients
},
requiredFirmware
),
callback
);
}
}, requiredFirmware), callback);
};
/**
* @typedef RequestLoginResult
@ -380,7 +347,13 @@ class TrezorConnect {
*
* @see https://github.com/trezor/trezor-common/blob/master/protob/messages.proto
*/
requestLogin(hosticon, challenge_hidden, challenge_visual, callback, requiredFirmware) {
this.requestLogin = function (
hosticon,
challenge_hidden,
challenge_visual,
callback,
requiredFirmware
) {
if (typeof callback === 'string') {
// special case for a login through <trezor:login> button.
// `callback` is name of global var
@ -389,19 +362,13 @@ class TrezorConnect {
if (!callback) {
throw new TypeError('TrezorConnect: login callback not found');
}
this.manager.sendWithChannel(
_fwStrFix(
{
manager.sendWithChannel(_fwStrFix({
type: 'login',
icon: hosticon,
challenge_hidden: challenge_hidden,
challenge_visual: challenge_visual
},
requiredFirmware
),
callback
);
}
}, requiredFirmware), callback);
};
/**
* @typedef SignMessageResult
@ -421,7 +388,13 @@ class TrezorConnect {
* @param {?(string|array<number>)} requiredFirmware
*
*/
signMessage(path, message, callback, opt_coin, requiredFirmware) {
this.signMessage = function (
path,
message,
callback,
opt_coin,
requiredFirmware
) {
if (typeof path === 'string') {
path = parseHDPath(path);
}
@ -431,19 +404,13 @@ class TrezorConnect {
if (!callback) {
throw new TypeError('TrezorConnect: callback not found');
}
this.manager.sendWithChannel(
_fwStrFix(
{
manager.sendWithChannel(_fwStrFix({
type: 'signmsg',
path: path,
message: message,
coin: { coin_name: opt_coin }
},
requiredFirmware
),
callback
);
}
coin: opt_coin,
}, requiredFirmware), callback);
};
/**
* Sign an Ethereum message
@ -454,25 +421,24 @@ class TrezorConnect {
* @param {?(string|array<number>)} requiredFirmware
*
*/
ethereumSignMessage(path, message, callback, requiredFirmware) {
this.ethereumSignMessage = function (
path,
message,
callback,
requiredFirmware
) {
if (typeof path === 'string') {
path = parseHDPath(path);
}
if (!callback) {
throw new TypeError('TrezorConnect: callback not found');
}
this.manager.sendWithChannel(
_fwStrFix(
{
manager.sendWithChannel(_fwStrFix({
type: 'signethmsg',
path: path,
message: message
},
requiredFirmware
),
callback
);
}
message: message,
}, requiredFirmware), callback);
};
/**
* Verify message
@ -485,27 +451,28 @@ class TrezorConnect {
* @param {?(string|array<number>)} requiredFirmware
*
*/
verifyMessage(address, signature, message, callback, opt_coin, requiredFirmware) {
this.verifyMessage = function (
address,
signature,
message,
callback,
opt_coin,
requiredFirmware
) {
if (!opt_coin) {
opt_coin = 'Bitcoin';
}
if (!callback) {
throw new TypeError('TrezorConnect: callback not found');
}
this.manager.sendWithChannel(
_fwStrFix(
{
manager.sendWithChannel(_fwStrFix({
type: 'verifymsg',
address: address,
signature: signature,
message: message,
coin: { coin_name: opt_coin }
},
requiredFirmware
),
callback
);
}
coin: {coin_name: opt_coin},
}, requiredFirmware), callback);
};
/**
* Verify ethereum message
@ -517,23 +484,23 @@ class TrezorConnect {
* @param {?(string|array<number>)} requiredFirmware
*
*/
ethereumVerifyMessage(address, signature, message, callback, requiredFirmware) {
this.ethereumVerifyMessage = function (
address,
signature,
message,
callback,
requiredFirmware
) {
if (!callback) {
throw new TypeError('TrezorConnect: callback not found');
}
this.manager.sendWithChannel(
_fwStrFix(
{
manager.sendWithChannel(_fwStrFix({
type: 'verifyethmsg',
address: address,
signature: signature,
message: message
},
requiredFirmware
),
callback
);
}
message: message,
}, requiredFirmware), callback);
};
/**
* Symmetric key-value encryption
@ -548,7 +515,7 @@ class TrezorConnect {
* @param {?(string|array<number>)} requiredFirmware
*
*/
cipherKeyValue(
this.cipherKeyValue = function (
path,
key,
value,
@ -564,7 +531,7 @@ class TrezorConnect {
if (typeof value !== 'string') {
throw new TypeError('TrezorConnect: Value must be a string');
}
if (!/^[0-9A-Fa-f]*$/.test(value)) {
if (!(/^[0-9A-Fa-f]*$/.test(value))) {
throw new TypeError('TrezorConnect: Value must be hexadecimal');
}
if (value.length % 32 !== 0) {
@ -574,9 +541,7 @@ class TrezorConnect {
if (!callback) {
throw new TypeError('TrezorConnect: callback not found');
}
this.manager.sendWithChannel(
_fwStrFix(
{
manager.sendWithChannel(_fwStrFix({
type: 'cipherkeyvalue',
path: path,
key: key,
@ -584,50 +549,62 @@ class TrezorConnect {
encrypt: !!encrypt,
ask_on_encrypt: !!ask_on_encrypt,
ask_on_decrypt: !!ask_on_decrypt
},
}, requiredFirmware), callback);
};
this.nemGetAddress = function (
address_n,
network,
callback,
requiredFirmware
),
callback
);
) {
if (requiredFirmware == null) {
requiredFirmware = '1.6.0'; // first firmware that supports NEM
}
if (typeof address_n === 'string') {
address_n = parseHDPath(address_n);
}
manager.sendWithChannel(_fwStrFix({
type: 'nemGetAddress',
address_n: address_n,
network: network,
}, requiredFirmware), callback);
}
pushTransaction(rawTx, callback) {
if (!/^[0-9A-Fa-f]*$/.test(rawTx)) {
this.nemSignTx = function (
address_n,
transaction,
callback,
requiredFirmware
) {
if (requiredFirmware == null) {
requiredFirmware = '1.6.0'; // first firmware that supports NEM
}
if (typeof address_n === 'string') {
address_n = parseHDPath(address_n);
}
manager.sendWithChannel(_fwStrFix({
type: 'nemSignTx',
address_n: address_n,
transaction: transaction
}, requiredFirmware), callback);
}
this.pushTransaction = function (
rawTx,
callback
) {
if (!(/^[0-9A-Fa-f]*$/.test(rawTx))) {
throw new TypeError('TrezorConnect: Transaction must be hexadecimal');
}
if (!callback) {
throw new TypeError('TrezorConnect: callback not found');
}
var tryUrl = function(i) {
var insight_url = INSIGHT_URLS[i];
var xhr = new XMLHttpRequest();
var method = 'POST';
var url = insight_url + '/tx/send';
var data = {
rawtx: rawTx
};
xhr.open(method, url, true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.onreadystatechange = function() {
if (xhr.readyState === XMLHttpRequest.DONE) {
if (xhr.status === 200) {
var txid = JSON.parse(xhr.responseText).txid;
callback({ success: true, txid: txid });
} else {
if (i === INSIGHT_URLS.length - 1) {
callback({ error: new Error(xhr.responseText) });
} else {
tryUrl(i + 1);
}
}
}
};
xhr.send(JSON.stringify(data));
};
tryUrl(0);
manager.sendWithChannel({
type: 'pushtx',
rawTx: rawTx,
}, callback);
}
/**
@ -639,63 +616,65 @@ class TrezorConnect {
* @param {?(string|array<number>)} requiredFirmware
*
*/
getAddress(address, coin, segwit, callback, requiredFirmware) {
this.getAddress = function (address, coin, segwit, callback, requiredFirmware) {
if (typeof address === 'string') {
address = parseHDPath(address);
}
this.manager.sendWithChannel(
_fwStrFix(
{
manager.sendWithChannel(_fwStrFix({
type: 'getaddress',
address_n: address,
coin: coin,
segwit: segwit
},
requiredFirmware
),
callback
);
}, requiredFirmware), callback);
}
/**
* Display ethereum address on device
*
* @param {string|array} address
* @param {string|array<number>} requiredFirmware
* @param {function()} callback
* @param {array} address
* @param {?(string|array<number>)} requiredFirmware
*
*/
ethereumGetAddress(address, requiredFirmware = undefined) {
this.ethereumGetAddress = function (address, callback, requiredFirmware) {
if (typeof address === 'string') {
address = parseHDPath(address);
}
return new Promise((resolve, reject) => {
this.manager.sendWithChannel(
_fwStrFix(
{
manager.sendWithChannel(_fwStrFix({
type: 'ethgetaddress',
address_n: address
},
requiredFirmware
),
response => {
if (response.error) {
reject(response.error.message);
} else {
resolve(response);
}
}
);
});
address_n: address,
}, requiredFirmware), callback);
}
var LOGIN_CSS =
'<style>@import url("@connect_path@/login_buttons.css")</style>';
var LOGIN_ONCLICK =
'TrezorConnect.requestLogin('
+ "'@hosticon@','@challenge_hidden@','@challenge_visual@','@callback@'"
+ ')';
var LOGIN_HTML =
'<div id="trezorconnect-wrapper">'
+ ' <a id="trezorconnect-button" onclick="' + LOGIN_ONCLICK + '">'
+ ' <span id="trezorconnect-icon"></span>'
+ ' <span id="trezorconnect-text">@text@</span>'
+ ' </a>'
+ ' <span id="trezorconnect-info">'
+ ' <a id="trezorconnect-infolink" href="https://www.buytrezor.com/"'
+ ' target="_blank">What is TREZOR?</a>'
+ ' </span>'
+ '</div>';
/**
* Find <trezor:login> elements and replace them with login buttons.
* It's not required to use these special elements, feel free to call
* `TrezorConnect.requestLogin` directly.
*/
renderLoginButtons() {
this.renderLoginButtons = function () {
var elements = document.getElementsByTagName('trezor:login');
for (var i = 0; i < elements.length; i++) {
@ -709,7 +688,8 @@ class TrezorConnect {
// it's not valid to put markup into attributes, so let users
// supply a raw text and make TREZOR bold
text = text.replace('TREZOR', '<strong>TREZOR</strong>');
e.outerHTML = (this.LOGIN_CSS + this.LOGIN_HTML)
e.outerHTML =
(LOGIN_CSS + LOGIN_HTML)
.replace('@text@', text)
.replace('@callback@', callback)
.replace('@hosticon@', hosticon)
@ -717,7 +697,7 @@ class TrezorConnect {
.replace('@challenge_visual@', challenge_visual)
.replace('@connect_path@', POPUP_PATH);
}
}
};
}
/*
@ -728,9 +708,7 @@ function parseHDPath(string) {
return string
.toLowerCase()
.split('/')
.filter(function(p) {
return p !== 'm';
})
.filter(function (p) { return p !== 'm'; })
.map(function (p) {
var hardened = false;
if (p[p.length - 1] === "'") {
@ -741,51 +719,13 @@ function parseHDPath(string) {
throw new Error('Not a valid path.');
}
var n = parseInt(p);
if (hardened) {
// hardened index
if (hardened) { // hardened index
n = (n | 0x80000000) >>> 0;
}
return n;
});
}
function getIdFromPath(path) {
if (path.length !== 3) {
throw new Error();
}
if (path[0] >>> 0 !== (44 | HD_HARDENED) >>> 0) {
throw new Error();
}
if (path[1] >>> 0 !== (0 | HD_HARDENED) >>> 0) {
throw new Error();
}
return (path[2] & ~HD_HARDENED) >>> 0;
}
// parses first argument from getAccountInfo
function parseAccountInfoInput(input) {
if (input == null) {
return null;
}
if (typeof input === 'string') {
if (input.substr(0, 4) === 'xpub') {
return input;
}
if (isNaN(input)) {
var parsedPath = parseHDPath(input);
return getIdFromPath(parsedPath);
} else {
return parseInt(input);
}
} else if (Array.isArray(input)) {
return getIdFromPath(input);
} else if (typeof input === 'number') {
return input;
}
throw new Error('Unknown input format.');
}
/*
* Popup management
*/
@ -870,14 +810,10 @@ function Popup(url, origin, name, width, height) {
var left = (screen.width - width) / 2;
var top = (screen.height - height) / 2;
var opts =
'width=' +
width +
',height=' +
height +
',left=' +
left +
',top=' +
top +
'width=' + width +
',height=' + height +
',left=' + left +
',top=' + top +
',menubar=no' +
',toolbar=no' +
',location=no' +
@ -903,6 +839,7 @@ function Popup(url, origin, name, width, height) {
}
function Channel(popup, waiting) {
var respond = function (data) {
if (waiting) {
var w = waiting;
@ -912,7 +849,10 @@ function Channel(popup, waiting) {
};
var receive = function (event) {
if (event.source === popup.window && event.origin === popup.origin) {
var org1 = event.origin.match(/^.+\:\/\/[^\/]+/)[0];
var org2 = popup.origin.match(/^.+\:\/\/[^\/]+/)[0];
//if (event.source === popup.window && event.origin === popup.origin) {
if (event.source === popup.window && org1 === org2) {
respond(event.data);
}
};
@ -936,6 +876,7 @@ function Channel(popup, waiting) {
}
function ConnectedChannel(p) {
var ready = function () {
clearTimeout(this.timeout);
this.popup.onclose = null;