Update trezor-connect.js to v4 (#856)
* Update trezor connect. * Re-ignore trezor connect, fix typings.
This commit is contained in:
parent
9c9d6c2f61
commit
1713e3fa29
|
@ -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
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue