bivcore-insight
Version:
A blockchain explorer for Bitcore
156 lines (137 loc) • 4.58 kB
text/typescript
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { DefaultProvider } from '../../providers/default/default';
import * as _ from 'lodash';
export interface ChainNetwork {
chain: string;
network: string;
}
export interface NetworkSettings {
availableNetworks: ChainNetwork[];
selectedNetwork: ChainNetwork;
}
const CurrentEnv = process.env.ENV || 'dev';
const EnvApiHosts: { [env: string]: { [chain: string]: string } } = {
prod: {
default: 'https://api.bivcore.io/api',
ETH: 'https://api-eth.bivcore.io/api'
},
dev: { default: '/api' }
};
const CurrentApiHosts = EnvApiHosts[CurrentEnv];
export class ApiProvider {
public defaultNetwork = {
chain: this.defaults.getDefault('%CHAIN%'),
network: this.defaults.getDefault('%NETWORK%')
};
public networkSettings = {
availableNetworks: [this.defaultNetwork],
selectedNetwork: this.defaultNetwork,
chainNetworkLookup: {}
};
// TODO: check me
public ratesAPI = {
btc: 'https://bitpay.com/api/rates',
bch: 'https://bitpay.com/api/rates/bch',
eth: 'https://bitpay.com/api/rates/eth'
};
public bwsUrl = {
urlPrefix: 'https://bws.bitpay.com/bws/api/v1/fiatrates/'
};
constructor(
public httpClient: HttpClient,
private defaults: DefaultProvider
) {
this.getAvailableNetworks().subscribe(data => {
const newNetworks = data
.map(x => x.supported)
.reduce((agg, arr) => [...agg].concat(arr), []);
const chainNetworkLookup = {};
for (const hostConfig of data) {
for (const chainNetwork of hostConfig.supported) {
const key = `${chainNetwork.chain}:${chainNetwork.network}`;
chainNetworkLookup[key] = hostConfig.host;
}
}
for (const { chain, network } of newNetworks) {
const found = this.networkSettings.availableNetworks.find(
available =>
available.chain === chain && available.network === network
);
if (!found) {
this.networkSettings.availableNetworks.push({ chain, network });
}
}
this.networkSettings = {
availableNetworks: this.networkSettings.availableNetworks,
selectedNetwork: this.networkSettings.selectedNetwork,
chainNetworkLookup
};
});
}
public getAvailableNetworks(): Observable<
Array<{ host: string; supported: ChainNetwork[] }>
> {
const hosts = CurrentApiHosts;
return Observable.fromPromise(
Promise.all(
Object.keys(hosts).map(async chain => {
const host = hosts[chain];
const supported = await this.httpClient
.get<ChainNetwork[]>(host + '/status/enabled-chains')
.toPromise();
return {
host,
supported
};
})
)
);
}
getHostForChain(chain: string) {
return CurrentApiHosts[chain] || CurrentApiHosts.default;
}
public getUrlPrefix(chain, network): string {
const defaultChain = chain || this.defaultNetwork.chain;
const defaultNetwork = network || this.defaultNetwork.network;
const key = `${defaultChain}:${defaultNetwork}`;
const lookupHost = this.networkSettings.chainNetworkLookup[key];
const prefix = lookupHost || this.getHostForChain(chain);
return prefix;
}
public getUrl(params?: { chain?: string; network?: string }): string {
let { chain, network } = params;
chain = chain || this.networkSettings.selectedNetwork.chain;
network = network || this.networkSettings.selectedNetwork.network;
const prefix: string = this.getUrlPrefix(chain, network);
const apiPrefix = `${prefix}/${chain}/${network}`;
return apiPrefix;
}
public getConfig(): ChainNetwork {
const config = {
chain: this.networkSettings.selectedNetwork.chain,
network: this.networkSettings.selectedNetwork.network
};
return config;
}
public changeNetwork(network: ChainNetwork): void {
const availableNetworks = this.networkSettings.availableNetworks;
// Can't do the following because availableNetworks is loaded
/*
*const isValid = _.some(availableNetworks, network);
*if (!isValid) {
* this.logger.error(
* 'Invalid URL: missing or invalid COIN or NETWORK param'
* );
* return;
*}
*/
this.networkSettings = {
availableNetworks,
selectedNetwork: network,
chainNetworkLookup: this.networkSettings.chainNetworkLookup || {}
};
}
}