UNPKG

js-oip

Version:

A Javascript Library to fully interact with the Open Index Protocol

588 lines (485 loc) 11.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _bitcoinjsMessage = require("bitcoinjs-message"); /** * An ES6 Multipart Single Class * @class */ class MPSingle { /** * Construct a Multipart Single by passing in an object or a valid JSON string * ##### Examples * ```javascript * let myOIPObject = { * part: 0, * max: 1, * reference: `${firstTXIDRef}`, * address: `${p2pkh}`, * signature: `${signature}`, * data: `${data}` * } * let mps = new MPSingle(myOIPObject) * //or * mps = new MPSingle(JSON.stringify(myOIPObject)) * ``` * @param {String|Object} input - a multipart chunk * @return {MPSingle} */ constructor(input) { // this._source = input this.prefix = 'oip-mp'; this.part = undefined; this.max = undefined; this.address = undefined; this.reference = undefined; this.signature = undefined; this.data = undefined; this.meta = { complete: undefined, stale: undefined, time: undefined, txid: undefined, block: undefined, block_hash: undefined, // eslint-disable-line assembled: undefined, tx: undefined }; this.fromInput(input); } /** * Get Part Number * @return {number} */ getPart() { return parseInt(this.part); } /** * Set part number * @param {number} part */ setPart(part) { this.part = part; } /** * Get max number of parts * @return {number} */ getMax() { return parseInt(this.max); } /** * Set max number of parts * @param {number} max */ setMax(max) { this.max = max; } /** * Get publisher address * @return {string} */ getAddress() { return this.address; } /** * Set Publisher address * @param {string} address */ setAddress(address) { this.address = address; } /** * Get the reference to the first part's TXID * @return {string} */ getReference() { return this.reference; } /** * Set the reference to the first part's TXID * @param {string} reference */ setReference(reference) { this.reference = reference; } /** * Get signature * @return {string} */ getSignature() { return this.signature; } /** * Set signature * @param {string} signature */ setSignature(signature) { this.signature = signature; } /** * Get multipart data * @return {string} */ getData() { return this.data; } /** * Set multipart data * @param {string} data - floData */ setData(data) { this.data = data; } /** * Get the multipart meta data * @return {Object} */ getMeta() { return this.meta; } /** * Check if multipart is complete * @return {Boolean} */ isComplete() { return this.meta.complete; } /** * Set whether mulitpart is complete * @param {boolean} isComplete */ setIsComplete(isComplete) { this.meta.complete = isComplete; } /** * Check if multipart is stale * @return {Boolean} */ isStale() { return this.meta.stale; } /** * Set stale param * @param {Boolean} isStale */ setIsStale(isStale) { this.meta.stale = isStale; } getTime() { return this.meta.time; } setTime(time) { this.meta.time = time; } /** * Get TXID * @return {string} */ getTXID() { return this.meta.txid; } /** * Set TXID * @param {string} txid */ setTXID(txid) { this.meta.txid = txid; } /** * Get Block Height * @return {number} */ getBlock() { return parseInt(this.meta.block); } /** * Set Block Height * @param {number|string} block */ setBlock(block) { this.meta.block = block; } /** * Get block hash * @return {string} */ getBlockHash() { return this.meta.block_hash; // eslint-disable-line } /** * Set block hash * @param {string} blockHash */ setBlockHash(blockHash) { this.meta.block_hash = blockHash; // eslint-disable-line } /** * Get assembled multipart * @return {string} */ getAssembled() { return this.meta.assembled; } /** * Set assembled multipart * @param {string} assembled - assembled multipart */ setAssembled(assembled) { this.meta.assembled = assembled; } /** * Get Transaction * @return {Object} * @deprecated */ // getTX() { // return this.meta.tx // } /** * Set Transaction * @param {Object} tx * @deprecated */ // setTX(tx) { // this.meta.tx = tx // } /** * Get original source data * @private * @deprecated */ // _getSource() { // return this._source // } /** * Construct a MPSingle from a JSON string or Object * @param {string|object} input - see constructor example * @return {null} */ fromInput(input) { if (!input) { return new Error(`No input!`); } if (typeof input === 'string') { try { input = JSON.parse(input); } catch (err) { return new Error(`Input is invalid JSON: ${err}`); } } if (input.part !== undefined) { this.setPart(input.part); } if (input.max !== undefined) { this.setMax(input.max); } if (input.address) { this.setAddress(input.address); } if (input.reference) { this.setReference(input.reference); } if (input.signature) { this.setSignature(input.signature); } if (input.data) { this.setData(input.data); } if (!input.meta) return; if (input.meta.complete !== undefined) { this.setIsComplete(input.meta.complete); this.setAssembled(input.meta.assembled); } if (input.meta.stale !== undefined) { this.setIsStale(input.meta.stale); } if (input.meta.time) { this.setTime(input.meta.time); } if (input.meta.txid) { this.setTXID(input.meta.txid); } if (input.meta.block) { this.setBlock(input.meta.block); } if (input.meta.block_hash) { this.setBlockHash(input.meta.block_hash); } // if (input.meta.tx) { // this.setTX(input.meta.tx) // } } isValid() { if (this.getPart() < 0 || this.getPart() === undefined || this.getPart() === '') { return { success: false, error: "Part number can't be negative, null, or undefined" }; } if (this.getPart() > this.getMax()) { return { success: false, error: 'Part number too high for total parts!' }; } if (this.getMax() < 1) { return { success: false, error: 'Must have more than one part to be a MULTIPART message!' }; } if (!this.getAddress()) { return { success: false, error: 'Must have a Publisher Address!' }; } if (!this.getReference() && this.getPart() !== 0) { return { success: false, error: 'Only the first part in a multipart message can have a blank first part TXID!' }; } if (isNaN(this.getPart()) || isNaN(this.getPart())) { return { success: false, error: 'The part number and the total part number must be of NUMBER types' }; } if (!this.getSignature()) { return { success: false, error: 'Must have a Signature!' }; } if (!this.hasValidSignature()) { return { success: false, error: 'Invalid Signature' }; } this.is_valid = true; return { success: true }; } /** * Convert MPSingle to string * @return {string} * @example * ``` * oip-mp(4,6,FLZXRaHzVPxJJfaoM32CWT4GZHuj2rx63k,8c204c5f39,H9dqFw5Pd//qwHeEQA+ENifGvvs/0X1sLUXLQKj2L5qdI/BIJMBX2w3TKETHeNg3MMhA1i3PYVT2FnC8y/BxvUM=):":"Single Track","duration":268},{"fname":"miltjordan-vanishingbreed.jpg","fsize":40451,"type":"Image","subtype":"album-art"},{"fname":"miltjordan-angelsgettheblues.jpg","fsize":54648,"type":"Image","subtype":"cover"}],"location":"QmWmth4ES4ZH9Wgz6Z7S7dRFF8MzJVGgDhit5KzH5uCvZz"},"payment":{"fiat":"USD","scale":"1000:1","maxdisc":30,"promoter":15,"retailer":15,"sugTip" * ``` */ toString() { if (this.isValid().success) { let part = this.getPart(); let max = this.getMax(); let addr = this.getAddress(); // if part === 0, return empty string let ref = part ? this.getReference() : ''; let sig = this.getSignature(); let data = this.getData(); return `${this.prefix}(${part},${max},${addr},${ref},${sig}):${data}`; } else return new Error(`Invalid multipart: ${this.isValid().error}`); } /** * Get Signature Data (preimage: the message parameter for the signing function) * @return {string} signatureData */ getSignatureData() { let part = this.getPart(); let max = this.getMax(); let address = this.getAddress(); let reference = this.getPart() ? this.getReference() : ''; let data = this.getData(); return `${part}-${max}-${address}-${reference}-${data}`; } /** * Get the signature of a specific message that can be verified by others * @param {Object} ECPair - Elliptic Curve Key Pair (bitcoinjs-lib/ecpair) * @return {Object} success - Returns a success object * ```javascript * {success: true, signature: 'base64', error: undefined} * * //or something like * * {success: false, signature: undefined, error: "Missing address for signature} *``` * * ```javascript * //nice little trick * let {success, signature, error} = mp.signSelf(ECPair) * * if (success) { * mp.setSignature(signature) * } else { * handle(error) * } * ``` */ async signSelf(signMessage) { if (!signMessage) { return { success: false, error: 'No signMessage function available! Unable to sign message!' }; } if (this.getPart() === undefined) { return { success: false, error: 'Missing part number! Unable to sign message!' }; } if (this.getMax() === undefined) { return { success: false, error: 'Missing maximum part number! Unable to sign message!' }; } // if the first txid is not set on a part greater than 0, throw // part 0 multiparts should have an undefined ref if (this.getReference() === undefined && this.getPart() !== 0) { return { success: false, error: 'Missing first txid reference! Unable to sign message!' }; } if (this.getData() === undefined) { return { success: false, error: 'Missing data! Unable to sign message!' }; } let signature; try { signature = await signMessage(this.getSignatureData()); } catch (e) { return { success: false, error: e }; } this.setSignature(signature); return { success: true, signature }; } /** * Check to see if the signature is valid * @param {string} [message_prefix=\u001bFlorincoin Signed Message:] * @return {boolean} * @example * if (multipart.hasValidSignature()) { * launchSpaceship() * } */ hasValidSignature() { let message_prefix = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '\u001bFlorincoin Signed Message:\n'; return (0, _bitcoinjsMessage.verify)(this.getSignatureData(), this.getAddress(), this.getSignature(), message_prefix); } } var _default = MPSingle; exports.default = _default;