@trezor/connect
Version:
High-level javascript interface for Trezor hardware wallet.
220 lines • 7.71 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Blockchain = void 0;
const tslib_1 = require("tslib");
const blockchain_link_1 = tslib_1.__importDefault(require("@trezor/blockchain-link"));
const constants_1 = require("../constants");
const events_1 = require("../events");
const workers_1 = require("../workers/workers");
const getWorker = (type) => {
switch (type) {
case 'blockbook':
return workers_1.BlockbookWorker;
case 'ripple':
return workers_1.RippleWorker;
case 'blockfrost':
return workers_1.BlockfrostWorker;
case 'electrum':
return workers_1.ElectrumWorker;
case 'solana':
return workers_1.SolanaWorker;
case 'stellar':
return workers_1.StellarWorker;
default:
return null;
}
};
const getNormalizedTrezorShortcut = (shortcut) => {
if (shortcut === 'tXRP') {
return 'XRP';
}
return shortcut;
};
class Blockchain {
link;
serverInfo;
identity;
coinInfo;
postMessage;
onDisconnected;
initPromise;
constructor(options) {
this.identity = options.identity;
this.coinInfo = options.coinInfo;
this.postMessage = options.postMessage;
this.onDisconnected = options.onDisconnected;
const { blockchainLink } = options.coinInfo;
if (!blockchainLink) {
throw constants_1.ERRORS.TypedError('Backend_NotSupported');
}
const worker = getWorker(blockchainLink.type);
if (!worker) {
throw constants_1.ERRORS.TypedError('Backend_WorkerMissing', `BlockchainLink worker not found ${blockchainLink.type}`);
}
const server = blockchainLink.url;
this.link = new blockchain_link_1.default({
name: this.coinInfo.shortcut,
worker,
server,
debug: options.debug,
proxy: options.proxy,
...(this.coinInfo.type === 'ethereum' ? { throttleBlockEvent: 10 * 1000 } : {}),
...(['ripple', 'stellar'].includes(blockchainLink.type)
? { throttleBlockEvent: 60 * 1000 }
: {}),
});
}
onError(error) {
const pendingSubscriptions = this.link.listenerCount('block') ||
this.link.listenerCount('notification') ||
this.link.listenerCount('fiatRates');
this.link.dispose();
this.postMessage((0, events_1.createBlockchainMessage)(events_1.BLOCKCHAIN.ERROR, {
coin: this.coinInfo,
identity: this.identity,
error: error.message,
code: error.code,
}));
this.onDisconnected?.(!!pendingSubscriptions);
}
async initLink() {
let info;
try {
await this.link.connect();
info = await this.link.getInfo();
}
catch (error) {
throw constants_1.ERRORS.TypedError('Backend_Error', error.message);
}
this.serverInfo = info;
const trezorNetworkShortcut = getNormalizedTrezorShortcut(this.coinInfo.shortcut);
const backendNetworkShortcut = this.serverInfo.network;
if (backendNetworkShortcut.toLowerCase() !== trezorNetworkShortcut.toLowerCase()) {
throw constants_1.ERRORS.TypedError('Backend_Invalid');
}
this.link.on('disconnected', () => {
this.onError(constants_1.ERRORS.TypedError('Backend_Disconnected'));
});
return info;
}
init() {
if (!this.initPromise) {
this.initPromise = this.initLink()
.then(info => {
this.postMessage((0, events_1.createBlockchainMessage)(events_1.BLOCKCHAIN.CONNECT, {
coin: this.coinInfo,
identity: this.identity,
...info,
}));
this.initPromise = Promise.resolve(info);
return info;
})
.catch(error => {
this.postMessage((0, events_1.createBlockchainMessage)(events_1.BLOCKCHAIN.ERROR, {
coin: this.coinInfo,
identity: this.identity,
error: error.message,
code: error.code,
}));
this.initPromise = Promise.reject(error);
this.link.dispose();
return this.initPromise;
});
}
return this.initPromise;
}
getTransactions(txs) {
return Promise.all(txs.map(id => this.link.getTransaction(id)));
}
getTransactionHexes(txids) {
return Promise.all(txids.map(id => this.link.getTransactionHex(id)));
}
getCurrentFiatRates(params) {
return this.link.getCurrentFiatRates(params);
}
getFiatRatesForTimestamps(params) {
return this.link.getFiatRatesForTimestamps(params);
}
getAccountBalanceHistory(params) {
return this.link.getAccountBalanceHistory(params);
}
getNetworkInfo() {
return this.link.getInfo();
}
getAccountInfo(request) {
return this.link.getAccountInfo(request);
}
getAccountUtxo(descriptor) {
return this.link.getAccountUtxo(descriptor);
}
rpcCall(params) {
return this.link.rpcCall(params);
}
estimateFee(request) {
return this.link.estimateFee(request);
}
subscribeBlocks() {
if (this.link.listenerCount('block') === 0) {
this.link.on('block', block => {
this.postMessage((0, events_1.createBlockchainMessage)(events_1.BLOCKCHAIN.BLOCK, {
coin: this.coinInfo,
...block,
}));
});
}
return this.link.subscribe({ type: 'block' });
}
subscribeAccounts(accounts) {
if (this.link.listenerCount('notification') === 0) {
this.link.on('notification', notification => {
this.postMessage((0, events_1.createBlockchainMessage)(events_1.BLOCKCHAIN.NOTIFICATION, {
coin: this.coinInfo,
notification,
}));
});
}
return this.link.subscribe({
type: 'accounts',
accounts,
});
}
subscribeFiatRates(_currency) {
if (this.link.listenerCount('fiatRates') === 0) {
this.link.on('fiatRates', ({ rates }) => {
this.postMessage((0, events_1.createBlockchainMessage)(events_1.BLOCKCHAIN.FIAT_RATES_UPDATE, {
coin: this.coinInfo,
rates,
}));
});
}
return this.link.subscribe({
type: 'fiatRates',
});
}
unsubscribeBlocks() {
this.link.removeAllListeners('block');
return this.link.unsubscribe({ type: 'block' });
}
unsubscribeAccounts(accounts) {
return this.link.unsubscribe({ type: 'accounts', accounts });
}
unsubscribeFiatRates() {
this.link.removeAllListeners('fiatRates');
return this.link.unsubscribe({ type: 'fiatRates' });
}
async unsubscribeAll() {
this.link.removeAllListeners('notification');
await this.unsubscribeFiatRates();
return this.unsubscribeBlocks();
}
pushTransaction(tx) {
return this.link.pushTransaction(tx);
}
disconnect() {
this.link.removeAllListeners();
this.link.disconnect();
this.onError(constants_1.ERRORS.TypedError('Backend_Disconnected'));
}
}
exports.Blockchain = Blockchain;
//# sourceMappingURL=Blockchain.js.map