187 lines
5.4 KiB
JavaScript
187 lines
5.4 KiB
JavaScript
/*
|
|
* This file is part of the Flowee project
|
|
* Copyright (C) 2019-2020 Tom Zander <tomz@freedommail.ch>
|
|
* Copyright (C) 2020 James Zuccon <zuccon@gmail.com>
|
|
*
|
|
* 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 <http://www.gnu.org/licenses/>.
|
|
*/
|
|
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;
|