/* * This file is part of the Flowee project * Copyright (C) 2019-2020 Tom Zander * Copyright (C) 2020 James Zuccon * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ const Message = require('./message'); /** * Blockchain information service. * @param {Flowee} instance Instance of Flowee */ class BlockchainService { constructor(network) { this.network = network; } /** * Get Blockchain Information * @example * let blockChainInfo = await flowee.getBlockChainInfo(); */ async getBlockChainInfo() { let reply = await this.network.sendMessage(new Message(1, 0)); return { difficulty: reply[64], medianTime: reply[65], chainWork: reply["66str"], chain: reply[67], blocks: reply[68], headers: reply[69], bestBlockHash: reply[70], bestBlockId: reply["70str"], }; } /** * Get the best block hash available * @returns The an object with the block hash as string and buffer. * @example * let bestBlockHash = await flowee.getBestBlockHash(); */ async getBestBlockHash() { let reply = await this.network.sendMessage(new Message(1, 2)); return { blockId: reply["1str"], blockHash: reply[1], } } /** * Get Block height * @returns {number} The block height * @example * let blockCount = await flowee.getBlockCount(); */ async getBlockCount() { let reply = await this.network.sendMessage(new Message(1, 10)); return reply.body[7]; // Block Height (is equal to count since genesis is height=0) } /** * Get Block * @param param (Number or Hash) The block height * @returns {number} Object containing details about block * @example * let blockHeader = await flowee.getBlock(500000); */ async getBlock(param) { let message = new Message(1, 4); message.body[44] = true; // Include_OffsetInBlock message.body[45] = false; // Include_FullTxData if (typeof param === 'number') { message.body[7] = param; } else if (param * 1 == parseInt(param)) { // is really a number message.body[7] = parseInt(param); } else if (typeof param === 'string') { message.body[5] = Buffer.from(param, 'hex').reverse(); if (message.body[5].length != 32) throw "Invalid argument, not blockId"; } else if (typeof param == 'undefined') { throw "Missing argument"; } else { message.body[5] = param; } let reply = await this.network.sendMessage(message); let answer = { blockId: reply["5str"], blockHash: reply[5], blockHeight: reply[7], transactions: [] } let tx = null; for (let prop of reply.body) { if (prop.key == 0) { if (tx != null) answer.transactions.push(tx); tx = null; } else if (prop.key == 8) { tx = {}; tx.offset = prop.value; } } return answer; } async getRawTransaction(blockHeight, offsetInBlock) { if (blockHeight * 1 == parseInt(blockHeight)) { // is really a number blockHeight = blockHeight * 1; } if (typeof blockHeight === 'string') { // assume this is a txid var search = await this.network.search({ jobs: [{ value: blockHeight, type: this.network.Job.FetchTx, txFilter: [ this.network.IncludeFullTxData ] }]}); return search.transactions[0].fullTxData; } if (typeof blockHeight === 'number' && typeof offsetInBlock === 'number') { let message = new Message(1, 12); message.body[7] = blockHeight; message.body[8] = offsetInBlock; message.body[45] = true; // Include_FullTxData let reply = await this.network.sendMessage(message); return reply["1"]; } else throw "Missing arguments"; } async getBlockHeader(blockHeight) { if (blockHeight * 1 == parseInt(blockHeight)) { // is really a number blockHeight = blockHeight * 1; } let message = new Message(1, 8); if (typeof blockHeight === 'number') { message.body[7] = blockHeight; } else if (typeof blockHeight === 'string') { message.body[5] = Buffer.from(param, 'hex').reverse(); if (message.body[5].length != 32) throw "Invalid argument, not blockId"; } else throw "Missing arguments"; let reply = await this.network.sendMessage(message); return { blockId: reply["5str"], blockHash: reply[5], confirmations: reply[72], blockHeight: reply[7], version: reply[62], merkleRoot: reply[73], merkleRootHex: reply["73str"], time: reply[63], medianTime: reply[65], nonce: reply[74], bits: reply[75], difficulty: reply[64], prevBlockHash: reply["76str"], nextBlockHash: reply["77str"] }; } } module.exports = BlockchainService;