diff --git a/src/js/backend/BlockchainLink.js b/src/js/backend/BlockchainLink.js index c14be6321..ffcb07afb 100644 --- a/src/js/backend/BlockchainLink.js +++ b/src/js/backend/BlockchainLink.js @@ -9,10 +9,7 @@ import type { GetAccountInfo, BlockchainBlock, BlockchainSubscribeAccount, - BlockchainTransactions, BlockchainFiatRates, - BlockchainTimestampedFiatRates, - BlockchainAccountBalanceHistory, BlockchainGetAccountBalanceHistory, } from '../types'; @@ -108,32 +105,32 @@ export default class Blockchain { } } - async loadTransaction(id: string): Promise { + async loadTransaction(id: string) { const transaction = await this.link.getTransaction(id); return BitcoinJsTransaction.fromHex(transaction.tx.hex, this.coinInfo.network); } - async getTransactions(txs: string[]): Promise { + async getTransactions(txs: string[]) { return Promise.all( txs.map(id => this.link.getTransaction(id)) ); } - async getReferencedTransactions(txs: string[]): Promise { + async getReferencedTransactions(txs: string[]) { return Promise.all( txs.map(id => this.loadTransaction(id)) ); } - async getCurrentFiatRates(params: { currencies?: ?string[] }): Promise { + async getCurrentFiatRates(params: { currencies?: ?string[] }) { return this.link.getCurrentFiatRates(params); } - async getFiatRatesForTimestamps(params: { timestamps?: ?number[] }): Promise { + async getFiatRatesForTimestamps(params: { timestamps?: ?number[] }) { return this.link.getFiatRatesForTimestamps(params); } - async getAccountBalanceHistory(params: $Shape): Promise { + async getAccountBalanceHistory(params: $Shape) { return this.link.getAccountBalanceHistory(params); } @@ -170,7 +167,7 @@ export default class Blockchain { return this.link.estimateFee(request); } - async subscribe(accounts: BlockchainSubscribeAccount[]): Promise<{ subscribed: boolean }> { + async subscribe(accounts: BlockchainSubscribeAccount[]) { // set block listener if it wasn't set before if (this.link.listenerCount('block') === 0) { this.link.on('block', (block: BlockchainBlock) => { @@ -199,7 +196,7 @@ export default class Blockchain { }); } - async subscribeFiatRates(currency?: string): Promise<{ subscribed: boolean }> { + async subscribeFiatRates(currency?: string) { // set block listener if it wasn't set before if (this.link.listenerCount('fiatRates') === 0) { this.link.on('fiatRates', (res: { @@ -217,7 +214,7 @@ export default class Blockchain { }); } - async unsubscribe(accounts?: BlockchainSubscribeAccount[]): Promise { + async unsubscribe(accounts?: BlockchainSubscribeAccount[]) { if (!accounts) { this.link.removeAllListeners('block'); this.link.removeAllListeners('fiatRates'); @@ -232,12 +229,12 @@ export default class Blockchain { return this.link.unsubscribe({ type: 'accounts', accounts }); } - async unsubscribeFiatRates(): Promise { + async unsubscribeFiatRates() { this.link.removeAllListeners('fiatRates'); return this.link.unsubscribe({ type: 'fiatRates' }); } - async pushTransaction(tx: string): Promise { + async pushTransaction(tx: string) { return await this.link.pushTransaction(tx); } @@ -249,16 +246,17 @@ export default class Blockchain { } const instances: Blockchain[] = []; +const customBackends: { [coin: string]: CoinInfo } = {}; -const remove = (backend: Blockchain): void => { - const index: number = instances.indexOf(backend); +export const remove = (backend: Blockchain) => { + const index = instances.indexOf(backend); if (index >= 0) { instances.splice(index, 1); } }; -export const find = (name: string): ?Blockchain => { - for (let i: number = 0; i < instances.length; i++) { +export const find = (name: string) => { + for (let i = 0; i < instances.length; i++) { if (instances[i].coinInfo.name === name) { return instances[i]; } @@ -266,11 +264,20 @@ export const find = (name: string): ?Blockchain => { return null; }; -export const initBlockchain = async (coinInfo: $ElementType, postMessage: $ElementType) => { - let backend: ?Blockchain = find(coinInfo.name); +export const setCustomBackend = (coinInfo: CoinInfo, blockchainLink: $ElementType) => { + if (!blockchainLink) { + delete customBackends[coinInfo.shortcut]; + } else { + customBackends[coinInfo.shortcut] = coinInfo; + customBackends[coinInfo.shortcut].blockchainLink = blockchainLink; + } +}; + +export const initBlockchain = async (coinInfo: CoinInfo, postMessage: $ElementType) => { + let backend = find(coinInfo.name); if (!backend) { backend = new Blockchain({ - coinInfo, + coinInfo: customBackends[coinInfo.shortcut] || coinInfo, postMessage, }); try { diff --git a/src/js/core/methods/blockchain/BlockchainDisconnect.js b/src/js/core/methods/blockchain/BlockchainDisconnect.js index 877b60fa3..289996d84 100644 --- a/src/js/core/methods/blockchain/BlockchainDisconnect.js +++ b/src/js/core/methods/blockchain/BlockchainDisconnect.js @@ -29,11 +29,7 @@ export default class BlockchainDisconnect extends AbstractMethod { { name: 'coin', type: 'string', obligatory: true }, ]); - let coinInfo: ?CoinInfo = getCoinInfo(payload.coin); - if (!coinInfo) { - coinInfo = getCoinInfo(payload.coin); - } - + const coinInfo = getCoinInfo(payload.coin); if (!coinInfo) { throw NO_COIN_INFO; } @@ -46,14 +42,11 @@ export default class BlockchainDisconnect extends AbstractMethod { }; } - async run(): Promise<{ disconnected: true }> { + async run() { const backend = await findBlockchainBackend(this.params.coinInfo.name); if (backend) { backend.disconnect(); } - - return { - disconnected: true, - }; + return { disconnected: true }; } } diff --git a/src/js/core/methods/blockchain/BlockchainEstimateFee.js b/src/js/core/methods/blockchain/BlockchainEstimateFee.js index 63109d01f..d9037fc46 100644 --- a/src/js/core/methods/blockchain/BlockchainEstimateFee.js +++ b/src/js/core/methods/blockchain/BlockchainEstimateFee.js @@ -54,7 +54,7 @@ export default class BlockchainEstimateFee extends AbstractMethod { ]); } } - const coinInfo: ?CoinInfo = getCoinInfo(payload.coin); + const coinInfo = getCoinInfo(payload.coin); if (!coinInfo) { throw NO_COIN_INFO; diff --git a/src/js/core/methods/blockchain/BlockchainGetAccountBalanceHistory.js b/src/js/core/methods/blockchain/BlockchainGetAccountBalanceHistory.js index 737a119cd..a1125e99b 100644 --- a/src/js/core/methods/blockchain/BlockchainGetAccountBalanceHistory.js +++ b/src/js/core/methods/blockchain/BlockchainGetAccountBalanceHistory.js @@ -37,7 +37,7 @@ export default class BlockchainGetAccountBalanceHistory extends AbstractMethod { { name: 'groupBy', type: 'number', obligatory: false }, ]); - const coinInfo: ?CoinInfo = getCoinInfo(payload.coin); + const coinInfo = getCoinInfo(payload.coin); if (!coinInfo) { throw NO_COIN_INFO; } diff --git a/src/js/core/methods/blockchain/BlockchainGetCurrentFiatRates.js b/src/js/core/methods/blockchain/BlockchainGetCurrentFiatRates.js index 89630169d..95536e99e 100644 --- a/src/js/core/methods/blockchain/BlockchainGetCurrentFiatRates.js +++ b/src/js/core/methods/blockchain/BlockchainGetCurrentFiatRates.js @@ -29,7 +29,7 @@ export default class BlockchainGetCurrentFiatRates extends AbstractMethod { { name: 'coin', type: 'string', obligatory: true }, ]); - const coinInfo: ?CoinInfo = getCoinInfo(payload.coin); + const coinInfo = getCoinInfo(payload.coin); if (!coinInfo) { throw NO_COIN_INFO; } diff --git a/src/js/core/methods/blockchain/BlockchainGetFiatRatesForTimestamps.js b/src/js/core/methods/blockchain/BlockchainGetFiatRatesForTimestamps.js index 97f129aec..3dc19a25b 100644 --- a/src/js/core/methods/blockchain/BlockchainGetFiatRatesForTimestamps.js +++ b/src/js/core/methods/blockchain/BlockchainGetFiatRatesForTimestamps.js @@ -29,7 +29,7 @@ export default class BlockchainGetFiatRatesForTimestamps extends AbstractMethod { name: 'coin', type: 'string', obligatory: true }, ]); - const coinInfo: ?CoinInfo = getCoinInfo(payload.coin); + const coinInfo = getCoinInfo(payload.coin); if (!coinInfo) { throw NO_COIN_INFO; } diff --git a/src/js/core/methods/blockchain/BlockchainGetTransactions.js b/src/js/core/methods/blockchain/BlockchainGetTransactions.js index 7abc2f682..93e940f98 100644 --- a/src/js/core/methods/blockchain/BlockchainGetTransactions.js +++ b/src/js/core/methods/blockchain/BlockchainGetTransactions.js @@ -29,7 +29,7 @@ export default class BlockchainGetTransactions extends AbstractMethod { { name: 'coin', type: 'string', obligatory: true }, ]); - const coinInfo: ?CoinInfo = getCoinInfo(payload.coin); + const coinInfo = getCoinInfo(payload.coin); if (!coinInfo) { throw NO_COIN_INFO; } diff --git a/src/js/core/methods/blockchain/BlockchainSetCustomBackend.js b/src/js/core/methods/blockchain/BlockchainSetCustomBackend.js new file mode 100644 index 000000000..7bedaf463 --- /dev/null +++ b/src/js/core/methods/blockchain/BlockchainSetCustomBackend.js @@ -0,0 +1,56 @@ +/* @flow */ + +import AbstractMethod from '../AbstractMethod'; +import { validateParams } from '../helpers/paramsValidator'; +import { NO_COIN_INFO } from '../../../constants/errors'; + +import { find as findBackend, remove as removeBackend, setCustomBackend, initBlockchain } from '../../../backend/BlockchainLink'; +import { getCoinInfo } from '../../../data/CoinInfo'; +import type { CoreMessage, CoinInfo } from '../../../types'; + +type Params = { + coinInfo: CoinInfo; +} + +export default class BlockchainSetCustomBackend extends AbstractMethod { + params: Params; + + constructor(message: CoreMessage) { + super(message); + this.requiredPermissions = []; + this.info = ''; + this.useDevice = false; + this.useUi = false; + + const { payload } = message; + + // validate incoming parameters + validateParams(payload, [ + { name: 'coin', type: 'string', obligatory: true }, + { name: 'blockchainLink', type: 'object' }, + ]); + + const coinInfo = getCoinInfo(payload.coin); + if (!coinInfo) { + throw NO_COIN_INFO; + } + + setCustomBackend(coinInfo, payload.blockchainLink); + + this.params = { + coinInfo, + }; + } + + async run() { + const current = await findBackend(this.params.coinInfo.name); + if (current) { + await current.disconnect(); + removeBackend(current); + + await initBlockchain(this.params.coinInfo, this.postMessage); + } + + return true; + } +} diff --git a/src/js/core/methods/blockchain/BlockchainSubscribe.js b/src/js/core/methods/blockchain/BlockchainSubscribe.js index f97531c57..da4eb9a8a 100644 --- a/src/js/core/methods/blockchain/BlockchainSubscribe.js +++ b/src/js/core/methods/blockchain/BlockchainSubscribe.js @@ -35,7 +35,7 @@ export default class BlockchainSubscribe extends AbstractMethod { ]); }); - const coinInfo: ?CoinInfo = getCoinInfo(payload.coin); + const coinInfo = getCoinInfo(payload.coin); if (!coinInfo) { throw NO_COIN_INFO; } @@ -49,7 +49,7 @@ export default class BlockchainSubscribe extends AbstractMethod { }; } - async run(): Promise<{ subscribed: boolean }> { + async run() { const backend = await initBlockchain(this.params.coinInfo, this.postMessage); return backend.subscribe(this.params.accounts); } diff --git a/src/js/core/methods/blockchain/BlockchainSubscribeFiatRates.js b/src/js/core/methods/blockchain/BlockchainSubscribeFiatRates.js index 6e9a734b7..2ea04f1d9 100644 --- a/src/js/core/methods/blockchain/BlockchainSubscribeFiatRates.js +++ b/src/js/core/methods/blockchain/BlockchainSubscribeFiatRates.js @@ -29,7 +29,7 @@ export default class BlockchainSubscribeFiatRates extends AbstractMethod { { name: 'coin', type: 'string', obligatory: true }, ]); - const coinInfo: ?CoinInfo = getCoinInfo(payload.coin); + const coinInfo = getCoinInfo(payload.coin); if (!coinInfo) { throw NO_COIN_INFO; } @@ -43,7 +43,7 @@ export default class BlockchainSubscribeFiatRates extends AbstractMethod { }; } - async run(): Promise<{ subscribed: boolean }> { + async run() { const backend = await initBlockchain(this.params.coinInfo, this.postMessage); return backend.subscribeFiatRates(this.params.currency); } diff --git a/src/js/core/methods/blockchain/BlockchainUnsubscribe.js b/src/js/core/methods/blockchain/BlockchainUnsubscribe.js index 7c2918eb4..b0bc691f0 100644 --- a/src/js/core/methods/blockchain/BlockchainUnsubscribe.js +++ b/src/js/core/methods/blockchain/BlockchainUnsubscribe.js @@ -37,7 +37,7 @@ export default class BlockchainUnsubscribe extends AbstractMethod { }); } - const coinInfo: ?CoinInfo = getCoinInfo(payload.coin); + const coinInfo = getCoinInfo(payload.coin); if (!coinInfo) { throw NO_COIN_INFO; } @@ -51,7 +51,7 @@ export default class BlockchainUnsubscribe extends AbstractMethod { }; } - async run(): Promise { + async run() { const backend = await initBlockchain(this.params.coinInfo, this.postMessage); return backend.unsubscribe(this.params.accounts); } diff --git a/src/js/core/methods/blockchain/BlockchainUnsubscribeFiatRates.js b/src/js/core/methods/blockchain/BlockchainUnsubscribeFiatRates.js index 75264c4b6..2b33d6e97 100644 --- a/src/js/core/methods/blockchain/BlockchainUnsubscribeFiatRates.js +++ b/src/js/core/methods/blockchain/BlockchainUnsubscribeFiatRates.js @@ -27,7 +27,7 @@ export default class BlockchainUnsubscribeFiatRates extends AbstractMethod { { name: 'coin', type: 'string', obligatory: true }, ]); - const coinInfo: ?CoinInfo = getCoinInfo(payload.coin); + const coinInfo = getCoinInfo(payload.coin); if (!coinInfo) { throw NO_COIN_INFO; } @@ -40,7 +40,7 @@ export default class BlockchainUnsubscribeFiatRates extends AbstractMethod { }; } - async run(): Promise { + async run() { const backend = await initBlockchain(this.params.coinInfo, this.postMessage); return backend.unsubscribeFiatRates(); } diff --git a/src/js/core/methods/index.js b/src/js/core/methods/index.js index 4111493ad..4d1b29dd3 100644 --- a/src/js/core/methods/index.js +++ b/src/js/core/methods/index.js @@ -6,14 +6,15 @@ import AbstractMethod from './AbstractMethod'; import BlockchainDisconnect from './blockchain/BlockchainDisconnect'; import BlockchainEstimateFee from './blockchain/BlockchainEstimateFee'; -import BlockchainGetTransactions from './blockchain/BlockchainGetTransactions'; +import BlockchainGetAccountBalanceHistory from './blockchain/BlockchainGetAccountBalanceHistory'; import BlockchainGetCurrentFiatRates from './blockchain/BlockchainGetCurrentFiatRates'; import BlockchainGetFiatRatesForTimestamps from './blockchain/BlockchainGetFiatRatesForTimestamps'; -import BlockchainGetAccountBalanceHistory from './blockchain/BlockchainGetAccountBalanceHistory'; -import BlockchainSubscribeFiatRates from './blockchain/BlockchainSubscribeFiatRates'; -import BlockchainUnsubscribeFiatRates from './blockchain/BlockchainUnsubscribeFiatRates'; +import BlockchainGetTransactions from './blockchain/BlockchainGetTransactions'; +import BlockchainSetCustomBackend from './blockchain/BlockchainSetCustomBackend'; import BlockchainSubscribe from './blockchain/BlockchainSubscribe'; +import BlockchainSubscribeFiatRates from './blockchain/BlockchainSubscribeFiatRates'; import BlockchainUnsubscribe from './blockchain/BlockchainUnsubscribe'; +import BlockchainUnsubscribeFiatRates from './blockchain/BlockchainUnsubscribeFiatRates'; import CardanoGetAddress from './CardanoGetAddress'; import CardanoGetPublicKey from './CardanoGetPublicKey'; import CardanoSignTransaction from './CardanoSignTransaction'; @@ -74,6 +75,7 @@ const classes: { [k: string]: any } = { 'blockchainGetCurrentFiatRates': BlockchainGetCurrentFiatRates, 'blockchainGetFiatRatesForTimestamps': BlockchainGetFiatRatesForTimestamps, 'blockchainGetTransactions': BlockchainGetTransactions, + 'blockchainSetCustomBackend': BlockchainSetCustomBackend, 'blockchainSubscribe': BlockchainSubscribe, 'blockchainSubscribeFiatRates': BlockchainSubscribeFiatRates, 'blockchainUnsubscribe': BlockchainUnsubscribe, diff --git a/src/js/data/CoinInfo.js b/src/js/data/CoinInfo.js index 24810777b..cb8734d5f 100644 --- a/src/js/data/CoinInfo.js +++ b/src/js/data/CoinInfo.js @@ -165,7 +165,7 @@ const parseBitcoinNetworksJson = (json: JSON) => { const isBitcoin = shortcut === 'BTC' || shortcut === 'TEST'; const hasTimestamp = shortcut === 'CPC' || shortcut === 'PPC' || shortcut === 'tPPC'; - const network: $ElementType = { + const network = { messagePrefix: coin.signed_message_header, bech32: coin.bech32_prefix, bip32: { diff --git a/src/js/index.js b/src/js/index.js index 8b5db64e8..839825c4a 100644 --- a/src/js/index.js +++ b/src/js/index.js @@ -57,6 +57,10 @@ const TrezorConnect: API = { return call({ method: 'blockchainGetTransactions', ...params }); }, + blockchainSetCustomBackend: params => { + return call({ method: 'blockchainSetCustomBackend', ...params }); + }, + blockchainSubscribe: params => { return call({ method: 'blockchainSubscribe', ...params }); }, diff --git a/src/js/types/__tests__/blockchain.js b/src/js/types/__tests__/blockchain.js index b87a66f12..747581942 100644 --- a/src/js/types/__tests__/blockchain.js +++ b/src/js/types/__tests__/blockchain.js @@ -102,4 +102,17 @@ export const others = async () => { }); TrezorConnect.blockchainDisconnect({ coin: 'btc' }); + + TrezorConnect.blockchainSetCustomBackend({ + coin: 'btc', + blockchainLink: undefined, + }); + + TrezorConnect.blockchainSetCustomBackend({ + coin: 'btc', + blockchainLink: { + type: 'blockbook', + url: ['https://btc1.trezor.io/'], + }, + }); }; diff --git a/src/js/types/api.js b/src/js/types/api.js index 132eb1a99..f43822b82 100644 --- a/src/js/types/api.js +++ b/src/js/types/api.js @@ -94,6 +94,7 @@ export type API = { blockchainGetCurrentFiatRates: Method; blockchainGetFiatRatesForTimestamps: Method; blockchainGetTransactions: Method; + blockchainSetCustomBackend: Method; blockchainSubscribe: Method; blockchainSubscribeFiatRates: Method; blockchainUnsubscribe: Method; diff --git a/src/js/types/backend/blockchain.js b/src/js/types/backend/blockchain.js index 3c4716be8..e99eb3dc6 100644 --- a/src/js/types/backend/blockchain.js +++ b/src/js/types/backend/blockchain.js @@ -144,6 +144,11 @@ export type BlockchainEstimatedFee = { levels: FeeLevel[]; } +export type BlockchainSetCustomBackend = { + coin: string; + blockchainLink: $PropertyType; +} + export type BlockchainEvent = | { type: typeof BLOCKCHAIN.CONNECT; diff --git a/src/js/types/networks/coinInfo.js b/src/js/types/networks/coinInfo.js index 3304dab78..9900cd6e8 100644 --- a/src/js/types/networks/coinInfo.js +++ b/src/js/types/networks/coinInfo.js @@ -1,131 +1,77 @@ /* @flow */ +import type { Network } from '@trezor/utxo-lib'; type CoinSupport = { connect: boolean; - // electrum not used, trezor1: string; trezor2: string; - // webwallet not used -}; - -// copy-paste from 'bitcoinjs-lib-zcash' module -type Network = { - messagePrefix: string; - bech32: ?string; - bip32: { - public: number; - private: number; - }; - pubKeyHash: number; - scriptHash: number; - wif: number; - dustThreshold: number; - coin: string; }; type BlockchainLink = { type: string; - url: Array; + url: string[]; }; -type DefaultFees = {[level: 'High' | 'Normal' | 'Economy' | 'Low']: number}; +type BitcoinDefaultFees = {[level: 'High' | 'Normal' | 'Economy' | 'Low']: number}; -export type BitcoinNetworkInfo = { - type: 'bitcoin'; - // address_type: in Network - // address_type_p2sh: in Network - // bech32_prefix: in Network - // consensus_branch_id in Network - // bip115: not used - // bitcore: not used - // blockbook: not used - blockchainLink: ?BlockchainLink; - blocktime: number; - cashAddrPrefix: ?string; - label: string; // this is human readable format, could be different from "name" - name: string; // this is Trezor readable format +type Common = { + label: string; // Human readable format, label != name + name: string; // Trezor readable format shortcut: string; - // cooldown not used + slip44: number; + support: CoinSupport; + decimals: number; + blockchainLink?: BlockchainLink; + blocktime: number; + minFee: number; + maxFee: number; +}; + +export type BitcoinNetworkInfo = Common & { + type: 'bitcoin'; + cashAddrPrefix?: string; curveName: string; - // decred not used - defaultFees: DefaultFees; dustLimit: number; forceBip143: boolean; - forkid: ?number; - // github: not used + forkid?: number; hashGenesisBlock: string; - // key not used - // maintainer: not used maxAddressLength: number; maxFeeSatoshiKb: number; minAddressLength: number; minFeeSatoshiKb: number; - // name: same as coin_label + defaultFees: BitcoinDefaultFees; segwit: boolean; - // signed_message_header: in Network - slip44: number; - support: CoinSupport; - // uri_prefix not used - // version_group_id: not used - // website: not used - // xprv_magic: in Network + xPubMagic: number; - xPubMagicSegwitNative: ?number; - xPubMagicSegwit: ?number; + xPubMagicSegwitNative?: number; + xPubMagicSegwit?: number; // custom network: Network; isBitcoin: boolean; hasTimestamp: boolean; - minFee: number; - maxFee: number; // used in backend blocks?: number; - decimals: number; }; -export type EthereumNetworkInfo = { +export type EthereumNetworkInfo = Common & { type: 'ethereum'; - blockchainLink: ?BlockchainLink; - blocktime: number; chain: string; chainId: number; - // key not used + rskip60: boolean; defaultFees: { label: 'high' | 'normal' | 'low'; feePerUnit: string; feeLimit: string; }[]; - minFee: number; - maxFee: number; - label: string; // compatibility - name: string; - shortcut: string; - rskip60: boolean; - slip44: number; - support: CoinSupport; - // url not used - network: typeof undefined; // compatibility - decimals: number; + network: typeof undefined; }; -export type MiscNetworkInfo = { +export type MiscNetworkInfo = Common & { type: 'misc' | 'nem'; - blockchainLink: ?BlockchainLink; - blocktime: number; curve: string; - // key not used - defaultFees: DefaultFees; - minFee: number; - maxFee: number; - // links not used - label: string; // compatibility - name: string; - shortcut: string; - slip44: number; - support: CoinSupport; - network: typeof undefined; // compatibility - decimals: number; + defaultFees: BitcoinDefaultFees; + network: typeof undefined; }; export type CoinInfo = BitcoinNetworkInfo | EthereumNetworkInfo | MiscNetworkInfo; diff --git a/src/ts/types/__tests__/blockchain.ts b/src/ts/types/__tests__/blockchain.ts index 31216391f..de08d693a 100644 --- a/src/ts/types/__tests__/blockchain.ts +++ b/src/ts/types/__tests__/blockchain.ts @@ -101,4 +101,17 @@ export const others = async () => { }); TrezorConnect.blockchainDisconnect({ coin: 'btc' }); + + TrezorConnect.blockchainSetCustomBackend({ + coin: 'btc', + blockchainLink: undefined, + }); + + TrezorConnect.blockchainSetCustomBackend({ + coin: 'btc', + blockchainLink: { + type: 'blockbook', + url: ['https://btc1.trezor.io/'], + }, + }); }; diff --git a/src/ts/types/api.d.ts b/src/ts/types/api.d.ts index c30b9b304..da5314245 100644 --- a/src/ts/types/api.d.ts +++ b/src/ts/types/api.d.ts @@ -85,6 +85,9 @@ export namespace TrezorConnect { function blockchainGetTransactions( params: P.CommonParams & Blockchain.BlockchainGetTransactions, ): P.Response; + function blockchainSetCustomBackend( + params: P.CommonParams & Blockchain.BlockchainSetCustomBackend, + ): P.Response; function blockchainSubscribe( params: P.CommonParams & Blockchain.BlockchainSubscribe, ): P.Response; diff --git a/src/ts/types/backend/blockchain.d.ts b/src/ts/types/backend/blockchain.d.ts index 98bac6998..d797ae70f 100644 --- a/src/ts/types/backend/blockchain.d.ts +++ b/src/ts/types/backend/blockchain.d.ts @@ -146,6 +146,11 @@ export interface BlockchainAccountBalanceHistory { fiatRate: number; } +export interface BlockchainSetCustomBackend { + coin: string; + blockchainLink: CoinInfo['blockchainLink']; +} + export type BlockchainEvent = | { type: typeof BLOCKCHAIN.CONNECT; diff --git a/src/ts/types/networks/coinInfo.d.ts b/src/ts/types/networks/coinInfo.d.ts index c6e4cffb8..d99b22821 100644 --- a/src/ts/types/networks/coinInfo.d.ts +++ b/src/ts/types/networks/coinInfo.d.ts @@ -1,9 +1,7 @@ export interface CoinSupport { connect: boolean; - // electrum not used, trezor1: string; trezor2: string; - // webwallet not used } // copy-paste from 'bitcoinjs-lib-zcash' module @@ -29,45 +27,34 @@ export interface BlockchainLink { export type BitcoinDefaultFeesKeys = 'High' | 'Normal' | 'Economy' | 'Low'; export type BitcoinDefaultFees = { [key in BitcoinDefaultFeesKeys]: number }; -export interface BitcoinNetworkInfo { - type: 'bitcoin'; - // address_type: in Network - // address_type_p2sh: in Network - // bech32_prefix: in Network - // consensus_branch_id in Network - // bip115: not used - // bitcore: not used - // blockbook: not used +type Common = { + label: string; // Human readable format, label != name + name: string; // Trezor readable format + shortcut: string; + slip44: number; + support: CoinSupport; + decimals: number; blockchainLink?: BlockchainLink; blocktime: number; + minFee: number; + maxFee: number; +}; + +export interface BitcoinNetworkInfo extends Common { + type: 'bitcoin'; cashAddrPrefix?: string; - label: string; // this is human readable format, could be different from "name" - name: string; // this is Trezor readable format - shortcut: string; - // cooldown not used curveName: string; - // decred not used - defaultFees: BitcoinDefaultFees; dustLimit: number; forceBip143: boolean; forkid?: number; - // github: not used hashGenesisBlock: string; - // key not used - // maintainer: not used maxAddressLength: number; maxFeeSatoshiKb: number; minAddressLength: number; minFeeSatoshiKb: number; - // name: same as coin_label + defaultFees: BitcoinDefaultFees; segwit: boolean; - // signed_message_header: in Network - slip44: number; - support: CoinSupport; - // uri_prefix not used - // version_group_id: not used - // website: not used - // xprv_magic: in Network + xPubMagic: number; xPubMagicSegwitNative?: number; xPubMagicSegwit?: number; @@ -76,55 +63,28 @@ export interface BitcoinNetworkInfo { network: Network; isBitcoin: boolean; hasTimestamp: boolean; - minFee: number; - maxFee: number; // used in backend blocks?: number; - decimals: number; } -export interface EthereumNetworkInfo { +export interface EthereumNetworkInfo extends Common { type: 'ethereum'; - blockchainLink?: BlockchainLink; - blocktime: number; chain: string; chainId: number; - // key not used + rskip60: boolean; defaultFees: Array<{ label: 'high' | 'normal' | 'low'; feePerUnit: string; feeLimit: string; }>; - minFee: number; - maxFee: number; - label: string; // compatibility - name: string; - shortcut: string; - rskip60: boolean; - slip44: number; - support: CoinSupport; - // url not used - network: typeof undefined; // compatibility - decimals: number; + network: typeof undefined; } -export interface MiscNetworkInfo { +export interface MiscNetworkInfo extends Common { type: 'misc' | 'nem'; - blockchainLink?: BlockchainLink; - blocktime: number; curve: string; - // key not used defaultFees: BitcoinDefaultFees; - minFee: number; - maxFee: number; - // links not used - label: string; // compatibility - name: string; - shortcut: string; - slip44: number; - support: CoinSupport; network: typeof undefined; // compatibility - decimals: number; } export type CoinInfo = BitcoinNetworkInfo | EthereumNetworkInfo | MiscNetworkInfo;