const assert = require("assert");
const BigInteger = require("../../common/biginteger").BigInteger;
const GenUtils = require("../../common/GenUtils");
const MoneroKeyImage = require("./MoneroKeyImage");
/**
* Models a Monero transaction output.
*
* @class
*/
class MoneroOutput {
/**
* Construct the model.
*
* @param {MoneroOutput|object} state is existing state to initialize from (optional)
*/
constructor(state) {
// initialize internal state
if (!state) state = {};
else if (state instanceof MoneroOutput) state = state.toJson();
else if (typeof state === "object") state = Object.assign({}, state);
else throw new MoneroError("state must be a MoneroOutput or JavaScript object");
this.state = state;
// deserialize fields if necessary
if (state.amount !== undefined && !(state.amount instanceof BigInteger)) state.amount = BigInteger.parse(state.amount);
if (state.keyImage && !(state.keyImage instanceof MoneroKeyImage)) state.keyImage = new MoneroKeyImage(state.keyImage);
}
getTx() {
return this.state.tx;
}
setTx(tx) {
this.state.tx = tx;
return this;
}
getKeyImage() {
return this.state.keyImage;
}
setKeyImage(keyImage) {
assert(keyImage === undefined || keyImage instanceof MoneroKeyImage);
this.state.keyImage = keyImage;
return this;
}
getAmount() {
return this.state.amount;
}
setAmount(amount) {
this.state.amount = amount;
return this;
}
getIndex() {
return this.state.index;
}
setIndex(index) {
this.state.index = index;
return this;
}
getRingOutputIndices() {
return this.state.ringOutputIndices;
}
setRingOutputIndices(ringOutputIndices) {
this.state.ringOutputIndices = ringOutputIndices;
return this;
}
getStealthPublicKey() {
return this.state.stealthPublicKey;
}
setStealthPublicKey(stealthPublicKey) {
this.state.stealthPublicKey = stealthPublicKey;
return this;
}
copy() {
return new MoneroOutput(this);
}
toJson() {
let json = Object.assign({}, this.state);
if (this.getAmount()) json.amount = this.getAmount() ? this.getAmount().toString() : undefined;
if (this.getKeyImage()) json.keyImage = this.getKeyImage() ? this.getKeyImage().toJson() : undefined;
delete json.tx;
return json;
}
merge(output) {
assert(output instanceof MoneroOutput);
if (this === output) return this;
// merge txs if they're different which comes back to merging outputs
if (this.getTx() !== output.getTx()) this.getTx().merge(output.getTx());
// otherwise merge output fields
else {
if (this.getKeyImage() === undefined) this.setKeyImage(output.getKeyImage());
else if (output.getKeyImage() !== undefined) this.getKeyImage().merge(output.getKeyImage());
this.setAmount(GenUtils.reconcile(this.getAmount(), output.getAmount()));
this.setIndex(GenUtils.reconcile(this.getIndex(), output.getIndex()));
}
return this;
}
toString(indent = 0) {
let str = "";
if (this.getKeyImage()) {
str += GenUtils.kvLine("Key image", "", indent);
str += this.getKeyImage().toString(indent + 1) + "\n";
}
str += GenUtils.kvLine("Amount", this.getAmount(), indent);
str += GenUtils.kvLine("Index", this.getIndex(), indent);
str += GenUtils.kvLine("Ring output indices", this.getRingOutputIndices(), indent);
str += GenUtils.kvLine("Stealth public key", this.getStealthPublicKey(), indent);
return str === "" ? str : str.slice(0, str.length - 1); // strip last newline
}
}
module.exports = MoneroOutput;