UNPKG

@bloom-trade/finance-connector

Version:

Is a package entended to be used with multiple web3 and web2 providers to interact with blockchains.

285 lines (282 loc) 7.98 kB
/* eslint-disable @typescript-eslint/no-var-requires */ import { ProviderCredentials, Providers, Client, Balance, Contracts, PoloniexPrice, } from '../@types/index'; import Web3 from 'web3'; import { cryptocurrencies } from '../data/cryptocurrencies'; import { contracts } from '../data/contracts'; import { Transaction, Chain, Asset, Provider, STABLECOINS, StableCoin, } from '@bloom-trade/types'; import axios from 'axios'; import moment from 'moment'; const sum = (a: any, b: any, positions: number) => { const factor = Math.pow(10, positions); return ( (a.toFixed(positions) * factor + b.toFixed(positions) * factor) / factor ); }; const setClient = (providerConnection: ProviderCredentials[]): Client => { const providers = providerConnection; return { providers, getProvider(id) { //staff this function to return the provider object }, async getBalance() { const balance: Balance = []; for (const connection of providerConnection) { const { ProviderConnectorImpl, } = require(`../impl/${connection.provider.id}/index`); const service = new ProviderConnectorImpl(connection); const res = (await service.getBalance()) as Balance; res.forEach((e) => { const foundElement = balance.find( (element) => element.asset === e.asset ); if (!foundElement) { balance.push(e); } else { if ( foundElement.asset === 'ETH' || foundElement.asset === 'MATIC' || foundElement.asset === 'AVAX' ) { const index = balance.indexOf(foundElement); balance[index].balance = sumEthsBalances( foundElement.balance, e.balance ); balance[index].detail.push(...e.detail); } else { const index = balance.indexOf(foundElement); balance[index].balance = sum( parseFloat(e.balance), parseFloat(balance[index].balance), 3 ).toString(); balance[index].detail.push(...e.detail); } } }); } return balance; }, async getTransactionHistory(params: { from: | 'beginning' | { selfCustodialProviders?: { chain: Chain; block: number; }[]; custodialProviders?: { id: Provider; block?: number; date: number; //NOT IN UNIX TIMESTAMP }[]; }; order?: 'asc' | 'desc'; filters?: { onlyStables?: boolean; }; }) { let transactions: Transaction[] = []; const StableAssets: STABLECOINS = ['usdt', 'usdc', 'dai']; for (const connection of providerConnection) { const { ProviderConnectorImpl, } = require(`../impl/${connection.provider.id}/index`); const service = new ProviderConnectorImpl(connection); const res = (await service.getTransactionHistory( params )) as Transaction[]; res.forEach((e) => { transactions.push(e); }); } switch (params.order) { case 'asc': transactions.sort((a, b) => a.timestamp - b.timestamp); break; case 'desc': transactions.sort((a, b) => b.timestamp - a.timestamp); default: break; } if (params.filters && params.filters.onlyStables) { transactions = transactions.filter((tx) => { if (StableAssets.includes(tx.asset as StableCoin)) { return tx; } }); } return transactions; }, }; }; const getDescription = (asset: string) => { const myKeys = Object.keys(cryptocurrencies); const foundKey = myKeys.find((e) => e === asset); if (!foundKey) return ''; return cryptocurrencies[foundKey]; }; const getSupportedContracts = () => { return contracts.tokens as Contracts; }; const manageBaseUrl = (connection: ProviderCredentials): string => { let url = ''; if (!connection.provider.useTestnet) { url = setProdUrl(connection.provider.id); } else { url = setTestUrl(connection.provider.id); } return url; //staff this function to return the base url }; const setProdUrl = (provider: Providers) => { switch (provider) { case 'binance': return 'https://api.binance.com'; case 'etherscan': return 'https://api.etherscan.io/api'; case 'polygonscan': return 'https://api.polygonscan.com/api'; case 'snowtrace': return 'https://snowtrace.io/api'; case 'circle': return 'https://api.circle.com/v1'; default: return 'https://api.etherscan.io/api'; } }; const setTestUrl = (provider: Providers) => { switch (provider) { case 'binance': return 'https://testnet.binance.vision'; case 'etherscan': return 'https://api-goerli.etherscan.io/api'; case 'polygonscan': return 'https://api-testnet.polygonscan.com/api'; case 'snowtrace': return 'https://api-testnet.snowtrace.io/api'; case 'circle': return 'https://api-sandbox.circle.com/v1'; default: return 'https://api-goerli.etherscan.io/api'; } }; const getTestnetByMainnet = (chain: Chain) => { switch (chain) { case 'eth': return 'goerli'; case 'avax': return 'fuji'; case 'polygon': return 'mumbai'; default: return 'goerli'; } }; const sumEthsBalances = (referenceBalance: string, balanceToAdd: string) => { const web3 = new Web3(Web3.givenProvider || 'ws://localhost:8545'); const totalBalanceInWei = web3.utils.toWei(referenceBalance, 'ether'); const foundElementInWei = web3.utils.toWei(balanceToAdd, 'ether'); const newBalance = web3.utils .toBN(totalBalanceInWei) .add(web3.utils.toBN(foundElementInWei)) .toString(); const formattedBalance = web3.utils.fromWei(newBalance, 'ether'); return formattedBalance; }; const weiToEth = (value: string) => { const web3 = new Web3(Web3.givenProvider || 'ws://localhost:8545'); return web3.utils.fromWei(value, 'ether'); }; const convertToken = (value: string, decimals: number) => { const web3 = new Web3(Web3.givenProvider || 'ws://localhost:8545'); return web3.utils .toBN(value) .div(web3.utils.toBN(10 ** decimals)) .toString(); }; const getAssetPriceInUSDC = async ( asset: Asset, startDate: number, endDate: number ) => { //staff this function to return the price of the asset in USDC try { const { data } = await axios.get( `https://poloniex.com/public?command=returnChartData&currencyPair=USDC_${asset.toUpperCase()}&start=${startDate}&end=${endDate}&period=14400` ); return data[0] as PoloniexPrice; } catch (error) { throw new Error(); } }; const getAssetDataByChain = ( contract: { token: Asset; networks: { chain: Chain; address: string; decimalPosition: number; }[]; }, chain: Chain, provider: { id: Providers; useTestnet: boolean; auth: { apiKey?: string; apiSecret?: string; }; } ) => { const filteredContract = contract.networks.find( (e) => e.chain === (provider.useTestnet ? getTestnetByMainnet(chain as Chain) : chain === 'eth' ? 'erc20' : chain) ); return filteredContract as { chain: Chain; address: string; decimalPosition: number; }; }; const stringToMilisecondsDate = (string: string) => { const date = new Date(string); return date.getTime(); }; const fDate = (date: number) => { return moment(date).format(); }; export { setClient, getDescription, manageBaseUrl, getSupportedContracts, weiToEth, convertToken, getAssetPriceInUSDC, getTestnetByMainnet, getAssetDataByChain, fDate, stringToMilisecondsDate, };