import { PinoLogger } from 'nestjs-pino' ; import axios from 'axios' ; import { QtumError } from './QtumError' ; import { QtumIUTXO , QtumIGetInfo , QtumISendRawTxResult , QtumIRawTransactionInfo , QtumIRawTransactions } from '@tatumio/tatum' ; import { QtumBlock } from '@tatumio/tatum/dist/src/model/response/qtum/QtumBlock' ; export abstract class QtumService { protected constructor ( protected readonly logger ) { } public abstract isTestnet ( ) ; protected abstract getNodesUrl ( testnet ) ; protected abstract storeKMSTransaction ( txData , currency , signatureId , index ? ) ; protected abstract completeKMSTransaction ( txId , signatureId ) ; private async getFirstNodeUrl ( ) { const nodes = await this . getNodesUrl ( await this . isTestnet ( ) ) ; if ( nodes . length === 0 ) { new QtumError ( 'Nodes url array must have at least one element.' , 'qtum.nodes.url' ) ; } return nodes [ 0 ] ; } public async getQtumUTXOs ( address ) { try { const baseURL = await this . getFirstNodeUrl ( ) ; const res = await axios . get ( baseURL + `/addr/${ address }/utxo` ) ; return res . data ; } catch ( e ) { this . logger . error ( e ) ; throw new QtumError ( `Error occurred. ${ e }` , 'qtum.error' ) ; } } public async getInfo ( address ) { try { const baseURL = await this . getFirstNodeUrl ( ) ; const res = await axios . get ( baseURL + `/addr/${ address }` ) ; return res . data ; } catch ( e ) { this . logger . error ( e ) ; throw new QtumError ( `Error occurred. ${ e }` , 'qtum.error' ) ; } } public async getCurrentBlock ( ) { try { const baseURL = await this . getFirstNodeUrl ( ) ; const res = await axios . get ( baseURL + `/status?q=getLastBlockHash` ) ; return res . data [ 'lastblockhash' ] ; } catch ( e ) { this . logger . error ( e ) ; throw new QtumError ( `Error occurred. ${ e }` , 'qtum.error' ) ; } } public async getBlock ( hash ) { try { const baseURL = await this . getFirstNodeUrl ( ) ; if ( ! isNaN ( + hash ) ) { let newHash = await axios . get ( baseURL + `/block-index/${ hash }` ) ; hash = newHash . data . blockHash ; } const res = await axios . get ( baseURL + `/block/${ hash }` ) ; return res . data ; } catch ( e ) { this . logger . error ( e ) ; throw new QtumError ( `Error occurred. ${ e }` , 'qtum.error' ) ; } } public async broadcast ( rawtx ) { try { const baseURL = await this . getFirstNodeUrl ( ) ; const res = await axios . post ( baseURL + "/tx/send" , { rawtx , } ) ; return res . data ; } catch ( e ) { this . logger . error ( e ) ; throw new QtumError ( `Error occurred. ${ e }` , 'qtum.error' ) ; } } public async estimateFee ( nblocks = 6 ) { try { const baseURL = await this . getFirstNodeUrl ( ) ; const res = await axios . get ( baseURL + `/utils/estimatefee?nbBlocks=${ nblocks }` ) ; const feeRate = res . data ; if ( typeof feeRate !== "number" || feeRate < 0 ) { return - 1 ; } return Math . ceil ( feeRate * 1e8 ) ; } catch ( e ) { this . logger . error ( e ) ; throw new QtumError ( `Error occurred. ${ e }` , 'qtum.error' ) ; } } public async estimateFeePerByte ( nblocks = 6 ) { try { const feeRate = await this . estimateFee ( nblocks ) ; if ( feeRate < 0 ) { return feeRate ; } return Math . ceil ( feeRate / 1024 ) ; } catch ( e ) { this . logger . error ( e ) ; throw new QtumError ( `Error occurred. ${ e }` , 'qtum.error' ) ; } } public async getQtumTransaction ( id ) { try { const baseURL = await this . getFirstNodeUrl ( ) ; const res = await axios . get ( baseURL + `/tx/${ id }` ) ; return res . data as QtumIRawTransactionInfo ; } catch ( e ) { this . logger . error ( e ) ; throw new QtumError ( `Error occurred. ${ e }` , 'qtum.error' ) ; } } public async getQtumTransactions ( address , pageSize = 50 , offset = 0 ) { try { const baseURL = await this . getFirstNodeUrl ( ) ; const to = pageSize + offset ; const result = await axios . get ( baseURL + `/addrs/${ address }/txs?from=${ offset }&to=${ to }` ) ; return result . data as QtumIRawTransactions ; } catch ( e ) { this . logger . error ( e ) ; throw new QtumError ( `Error occurred. ${ e }` , 'qtum.error' ) ; } } }