UNPKG

bitbox-sdk

Version:
368 lines (324 loc) 10.6 kB
/* TODO - Add blockhash functionality back into getTxOutProof */ import axios, { AxiosRequestConfig, AxiosResponse } from "axios" import { BlockchainInfoResult, BlockDetailsResult, BlockHeaderResult, ChainTipResult, MempoolEntryResult, MempoolInfoResult, TxOutResult } from "bitcoin-com-rest" import { REST_URL } from "./BITBOX" export class Blockchain { public restURL: string constructor(restURL: string = REST_URL) { this.restURL = restURL } public async getBestBlockHash(): Promise<string> { try { const response: AxiosResponse = await axios.get( `${this.restURL}blockchain/getBestBlockHash` ) return response.data } catch (error) { if (error.response && error.response.data) throw error.response.data else throw error } } public async getBlock( blockhash: string, verbose: boolean = true ): Promise<BlockDetailsResult> { try { const response: AxiosResponse = await axios.get( `${this.restURL}blockchain/getBlock/${blockhash}?verbose=${verbose}` ) return response.data } catch (error) { if (error.response && error.response.data) throw error.response.data else throw error } } public async getBlockchainInfo(): Promise<BlockchainInfoResult> { try { const response: AxiosResponse = await axios.get( `${this.restURL}blockchain/getBlockchainInfo` ) return response.data } catch (error) { if (error.response && error.response.data) throw error.response.data else throw error } } public async getBlockCount(): Promise<number> { try { const response: AxiosResponse = await axios.get( `${this.restURL}blockchain/getBlockCount` ) return response.data } catch (error) { if (error.response && error.response.data) throw error.response.data else throw error } } public async getBlockHash(height: number = 1): Promise<string> { // if (typeof height !== "string") height = JSON.stringify(height) try { const response: AxiosResponse = await axios.get( `${this.restURL}blockchain/getBlockHash/${height}` ) return response.data } catch (error) { if (error.response && error.response.data) throw error.response.data else throw error } } public async getBlockHeader( hash: string | string[], verbose: boolean = true ): Promise<BlockHeaderResult | BlockHeaderResult[]> { try { // Handle single hash. if (typeof hash === "string") { const response: AxiosResponse = await axios.get( `${this.restURL}blockchain/getBlockHeader/${hash}?verbose=${verbose}` ) return response.data // Handle array of hashes. } else if (Array.isArray(hash)) { // Dev note: must use axios.post for unit test stubbing. const response: AxiosResponse = await axios.post( `${this.restURL}blockchain/getBlockHeader`, { hashes: hash, verbose: verbose } ) return response.data } throw new Error(`Input hash must be a string or array of strings.`) } catch (error) { if (error.response && error.response.data) throw error.response.data else throw error } } public async getChainTips(): Promise<ChainTipResult[]> { try { const response: AxiosResponse = await axios.get( `${this.restURL}blockchain/getChainTips` ) return response.data } catch (error) { if (error.response && error.response.data) throw error.response.data else throw error } } public async getDifficulty(): Promise<number> { try { const response: AxiosResponse = await axios.get( `${this.restURL}blockchain/getDifficulty` ) return response.data } catch (error) { if (error.response && error.response.data) throw error.response.data else throw error } } // TODO: add back to REST public async getMempoolAncestors( txid: string, verbose: boolean = false ): Promise<string[] | MempoolEntryResult[]> { if (typeof txid !== "string") txid = JSON.stringify(txid) try { const response: AxiosResponse = await axios.get( `${this.restURL}blockchain/getMempoolAncestors/${txid}?verbose=${verbose}` ) return response.data } catch (error) { if (error.response && error.response.data) throw error.response.data else throw error } } // TODO: add back to REST public async getMempoolDescendants( txid: string, verbose: boolean = false ): Promise<string[] | MempoolEntryResult[]> { if (typeof txid !== "string") txid = JSON.stringify(txid) try { const response: AxiosResponse = await axios.get( `${this.restURL}blockchain/getMempoolDescendants/${txid}?verbose=${verbose}` ) return response.data } catch (error) { if (error.response && error.response.data) throw error.response.data else throw error } } public async getMempoolEntry( txid: string | string[] ): Promise<MempoolEntryResult> { try { if (typeof txid === "string") { const response: AxiosResponse = await axios.get( `${this.restURL}blockchain/getMempoolEntry/${txid}` ) return response.data } else if (Array.isArray(txid)) { const options: AxiosRequestConfig = { method: "POST", url: `${this.restURL}blockchain/getMempoolEntry`, data: { txids: txid } } const response: AxiosResponse = await axios(options) return response.data } throw new Error(`Input must be a string or array of strings.`) } catch (error) { if (error.response && error.response.data) throw error.response.data else throw error } } public async getMempoolInfo(): Promise<MempoolInfoResult> { try { const response: AxiosResponse = await axios.get( `${this.restURL}blockchain/getMempoolInfo` ) return response.data } catch (error) { if (error.response && error.response.data) throw error.response.data else throw error } } public async getRawMempool(verbose: boolean = false): Promise<string[]> { // TODO fix verbose try { const response: AxiosResponse = await axios.get( `${this.restURL}blockchain/getRawMempool?vebose=${verbose}` ) return response.data } catch (error) { if (error.response && error.response.data) throw error.response.data else throw error } } // Returns details about an unspent transaction output. public async getTxOut( txid: string, n: any, include_mempool: boolean = true ): Promise<TxOutResult | null> { // Input validation if (typeof txid !== "string" || txid.length !== 64) throw new Error(`txid needs to be a proper transaction ID`) if (isNaN(n)) throw new Error(`n must be an integer`) if (typeof include_mempool !== "boolean") throw new Error(`include_mempool input must be of type boolean`) try { const path: string = `${this.restURL}blockchain/getTxOut/${txid}/${n}?include_mempool=${include_mempool}` // console.log(`path: ${path}`) const response: AxiosResponse = await axios.get(path) return response.data } catch (error) { if (error.response && error.response.data) throw error.response.data else throw error } } public async getTxOutProof( txids: string | string[] ): Promise<string | string[]> { try { // Single txid. if (typeof txids === "string") { const path = `${this.restURL}blockchain/getTxOutProof/${txids}` //if (blockhash) path = `${path}?blockhash=${blockhash}` const response: AxiosResponse = await axios.get(path) return response.data // Array of txids. } else if (Array.isArray(txids)) { // Dev note: must use axios.post for unit test stubbing. const response: AxiosResponse = await axios.post( `${this.restURL}blockchain/getTxOutProof`, { txids: txids } ) return response.data } throw new Error(`Input must be a string or array of strings.`) } catch (error) { if (error.response && error.response.data) throw error.response.data else throw error } } public async preciousBlock(blockhash: string): Promise<any> { // TODO bring this back to REST try { const response: AxiosResponse = await axios.get( `${this.restURL}blockchain/preciousBlock/${blockhash}` ) return response.data } catch (error) { if (error.response && error.response.data) throw error.response.data else throw error } } public async pruneBlockchain(height: number): Promise<number> { // TODO bring this back to REST try { const response: AxiosResponse = await axios.post( `${this.restURL}blockchain/pruneBlockchain/${height}` ) return response.data } catch (error) { if (error.response && error.response.data) throw error.response.data else throw error } } public async verifyChain( checklevel: number = 3, nblocks: number = 6 ): Promise<boolean> { try { const response: AxiosResponse = await axios.get( `${this.restURL}blockchain/verifyChain?checklevel=${checklevel}&nblocks=${nblocks}` ) return response.data } catch (error) { if (error.response && error.response.data) throw error.response.data else throw error } } public async verifyTxOutProof(proof: string | string[]): Promise<string[]> { try { // Single block if (typeof proof === "string") { const response: AxiosResponse = await axios.get( `${this.restURL}blockchain/verifyTxOutProof/${proof}` ) return response.data // Array of hashes. } else if (Array.isArray(proof)) { // Dev note: must use axios.post for unit test stubbing. const response: AxiosResponse = await axios.post( `${this.restURL}blockchain/verifyTxOutProof`, { proofs: proof } ) return response.data } throw new Error(`Input must be a string or array of strings.`) } catch (error) { if (error.response && error.response.data) throw error.response.data else throw error } } }