'use strict' import {QORT_DECIMALS, TX_TYPES} from '../constants.js' import nacl from '../deps/nacl-fast.js' import Base58 from '../deps/Base58.js' import utils from '../deps/utils.js' export default class TransactionBase { static get utils() { return utils } static get nacl() { return nacl } static get Base58() { return Base58 } constructor() { this.fee = 0 this.groupID = 0 this.timestamp = Date.now() this.tests = [ () => { if (!(this._type >= 1 && this._type in TX_TYPES)) { return 'Invalid type: ' + this.type } return true }, () => { if (this._fee < 0) { return 'Invalid fee: ' + this._fee / QORT_DECIMALS } return true }, () => { if (this._groupID < 0 || !Number.isInteger(this._groupID)) { return 'Invalid groupID: ' + this._groupID } return true }, () => { if (!(new Date(this._timestamp)).getTime() > 0) { return 'Invalid timestamp: ' + this._timestamp } return true }, () => { if (!(this._lastReference instanceof Uint8Array && this._lastReference.byteLength == 64)) { if (this._lastReference == 0) { return 'Invalid last reference. Please ensure that you have at least 0.001 QORT for the transaction fee.' } return 'Invalid last reference: ' + this._lastReference } return true }, () => { if (!(this._keyPair)) { return 'keyPair must be specified' } if (!(this._keyPair.publicKey instanceof Uint8Array && this._keyPair.publicKey.byteLength === 32)) { return 'Invalid publicKey' } if (!(this._keyPair.privateKey instanceof Uint8Array && this._keyPair.privateKey.byteLength === 64)) { return 'Invalid privateKey' } return true } ] } render(html) { return html`render method to display requested transaction info` } set keyPair(keyPair) { this._keyPair = keyPair } set type(type) { this.typeText = TX_TYPES[type] this._type = type this._typeBytes = this.constructor.utils.int32ToBytes(this._type) } set groupID(groupID) { this._groupID = groupID this._groupIDBytes = this.constructor.utils.int32ToBytes(this._groupID) } set timestamp(timestamp) { this._timestamp = timestamp this._timestampBytes = this.constructor.utils.int64ToBytes(this._timestamp) } set fee(fee) { this._fee = fee * QORT_DECIMALS this._feeBytes = this.constructor.utils.int64ToBytes(this._fee) } set lastReference(lastReference) { this._lastReference = lastReference instanceof Uint8Array ? lastReference : this.constructor.Base58.decode(lastReference) } get params() { return [ this._typeBytes, this._timestampBytes, this._groupIDBytes, this._lastReference, this._keyPair.publicKey ] } get signedBytes() { if (!this._signedBytes) { this.sign() } return this._signedBytes } validParams() { let finalResult = { valid: true } this.tests.some(test => { const result = test() if (result !== true) { finalResult = { valid: false, message: result } return true // exists the loop } }) return finalResult } generateBase() { const isValid = this.validParams() if (!isValid.valid) { throw new Error(isValid.message) } let result = new Uint8Array() this.params.forEach(item => { result = this.constructor.utils.appendBuffer(result, item) }) this._base = result return result } sign() { if (!this._keyPair) { throw new Error('keyPair not defined') } if (!this._base) { this.generateBase() } this._signature = this.constructor.nacl.sign.detached(this._base, this._keyPair.privateKey) this._signedBytes = this.constructor.utils.appendBuffer(this._base, this._signature) return this._signature } }