UNPKG

bitfact

Version:

A Javascript library to fingerprint (prove) your data, text, & files on the Ethereum blockchain.

177 lines (151 loc) 5.12 kB
const Web3 = require("web3"); const Tx = require("ethereumjs-tx"); const sha256 = require("js-sha256"); const sha256f = require("sha256-file"); const config = require("./config"); class BitFact { constructor(setup) { /* setup example { "provider": "https://eth-ropsten.alchemyapi.io/v2/01GesjZxWhg-KMfDuLH_-aUOmV-bRBaf", "privateKey": "67ccc16df9e7581ec11e7483c7eba5f2ae937b7ab37db413bad46470165629cf", "options": { "chain": "ropsten" } } */ this.privateKey = setup.privateKey; this.options = setup.options ? setup.options : config.DEFAULT_OPTIONS; // ie: { chain: "ropsten" } this.web3 = new Web3(setup.provider); } async stampText(text, memo) { // Exposed method: // BitFact's a piece of text. const hash = sha256(text); const fact = this.buildFact("text", hash, memo); const stamp = await this.stamp(fact); // stamp to chain return this.formReply(fact, stamp); } async stampFile(filePath, memo) { // Exposed method: // BitFact's a file (path). const hash = sha256f(filePath); const fact = this.buildFact("file", hash, memo); const stamp = await this.stamp(fact); // stamp to chain. return this.formReply(fact, stamp); } async verifyText(text, txid) { // Exposed method: // Checks the bitfact at txid, for matching text. const receipt = await this.getByTx(txid); return Boolean(receipt.hash === sha256(text)); } async verifyFile(filePath, txid) { // Exposed method: // Checks the bitfact at txid, for matching text. const receipt = await this.getByTx(txid); return Boolean(receipt.hash === sha256f(filePath)); } // -------------------------- async getByTx(hash) { // Gets a bitfact by hash. const txObj = await this.web3.eth.getTransaction(hash); const { input } = txObj; // input contains hex version of bitfact. const factString = this.web3.utils.hexToUtf8(input); return this.formReply(factString, txObj); } formReply(factString, tx) { // returns a nicely formatted response for lib user. const fact = this.parseFact(factString); // txid might be either "transactionhash" or simply "hash" const txid = tx.transactionHash ? tx.transactionHash : tx.hash; return { txid, hash: fact.hash, meta: { info: this.options, fact, tx, }, }; } async stamp(fact) { // fact: BitFact({"algo":"sha256","hash":"b94e2efcde9","type":"text","memo":"mymemo"}) let tx = await this.buildTx(fact); tx = await this.signTx(tx); tx = await this.broadcastTx(tx); return tx; } // -------------------------- async buildTx(bitFactData) { return { nonce: this.web3.utils.toHex(await this.getTransactionCount()), to: config.BITFACT_ADDR, value: this.web3.utils.toHex(this.web3.utils.toWei("0", "ether")), gasLimit: this.web3.utils.toHex(40000), gasPrice: this.web3.utils.toHex( this.web3.utils.toWei(await this.getGasPrice(), "wei") ), data: this.web3.utils.toHex(bitFactData), }; } async signTx(txObj) { // Signs a TX object. const tx = new Tx.Transaction(txObj, this.options); let pkb = this.getKeyBuffer(); tx.sign(pkb); return tx.serialize(); } async broadcastTx(serializedTx) { serializedTx = "0x" + serializedTx.toString("hex"); const receipt = await this.web3.eth.sendSignedTransaction(serializedTx); return receipt; } // -------------------------- getKeyBuffer() { let pk = this.privateKey; if (this.web3.utils.isHexStrict(this.privateKey)) { // leading hex provided. remove 0x. pk = pk.substring(2); } return Buffer.from(pk, "hex"); } async createKeypair() { // returns a random new keypair. return await this.web3.eth.accounts.create(this.web3.utils.randomHex(32)); } async getPublicKey() { return await this.web3.eth.accounts.privateKeyToAccount( this.privateKey.toString() ).address; } async getGasPrice() { // returns as wei. return await this.web3.eth.getGasPrice(); } async getTransactionCount() { // returns the number of TX's from this account. let pubKey = await this.getPublicKey(); const txCount = await this.web3.eth.getTransactionCount(pubKey); return txCount; } // -------------------------- parseFact(fact) { // BitFact(algo:sha256|hash:dabfac484|type:file|memo:testing..) // this method turns a "bitfact string" into an object. // algo:sha256|hash:dabfac484|type:file|memo:testing.." const factString = fact.substring(8, fact.length - 1); // {algo: "sha256", hash: "b94e2efcde9", type: "text", memo: "mymemo"} return JSON.parse(factString); } buildFact(type, hash, memo) { // this method turns "object data" into a "bitfact string". const input = { algo: "sha256", hash, type, memo, }; // BitFact({"algo":"sha256","hash":"b94e2efcde9","type":"text","memo":"mymemo"}) return "BitFact(" + JSON.stringify(input) + ")"; } } module.exports = BitFact;