@c4tplatform/caminojs
Version:
Camino Platform JS Library
546 lines • 72.2 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.StandardUTXOSet = exports.StandardUTXO = void 0;
/**
* @packageDocumentation
* @module Common-UTXOs
*/
const buffer_1 = require("buffer/");
const bintools_1 = __importDefault(require("../utils/bintools"));
const bn_js_1 = __importDefault(require("bn.js"));
const output_1 = require("./output");
const helperfunctions_1 = require("../utils/helperfunctions");
const serialization_1 = require("../utils/serialization");
const errors_1 = require("../utils/errors");
/**
* @ignore
*/
const bintools = bintools_1.default.getInstance();
const serialization = serialization_1.Serialization.getInstance();
/**
* Class for representing a single StandardUTXO.
*/
class StandardUTXO extends serialization_1.Serializable {
serialize(encoding = "hex") {
let fields = super.serialize(encoding);
return Object.assign(Object.assign({}, fields), { codecID: serialization.encoder(this.codecID, encoding, "Buffer", "decimalString"), txid: serialization.encoder(this.txid, encoding, "Buffer", "cb58"), outputidx: serialization.encoder(this.outputidx, encoding, "Buffer", "decimalString"), assetID: serialization.encoder(this.assetID, encoding, "Buffer", "cb58"), output: this.output.serialize(encoding) });
}
deserialize(fields, encoding = "hex") {
super.deserialize(fields, encoding);
this.codecID = serialization.decoder(fields["codecID"], encoding, "decimalString", "Buffer", 2);
this.txid = serialization.decoder(fields["txid"], encoding, "cb58", "Buffer", 32);
this.outputidx = serialization.decoder(fields["outputidx"], encoding, "decimalString", "Buffer", 4);
this.assetID = serialization.decoder(fields["assetID"], encoding, "cb58", "Buffer", 32);
}
/**
* Returns a {@link https://github.com/feross/buffer|Buffer} representation of the [[StandardUTXO]].
*/
toBuffer() {
const outbuff = this.output.toBuffer();
const outputidbuffer = buffer_1.Buffer.alloc(4);
outputidbuffer.writeUInt32BE(this.output.getOutputID(), 0);
const barr = [
this.codecID,
this.txid,
this.outputidx,
this.assetID,
outputidbuffer,
outbuff
];
return buffer_1.Buffer.concat(barr, this.codecID.length +
this.txid.length +
this.outputidx.length +
this.assetID.length +
outputidbuffer.length +
outbuff.length);
}
/**
* Class for representing a single StandardUTXO.
*
* @param codecID Optional number which specifies the codeID of the UTXO. Default 0
* @param txID Optional {@link https://github.com/feross/buffer|Buffer} of transaction ID for the StandardUTXO
* @param txidx Optional {@link https://github.com/feross/buffer|Buffer} or number for the index of the transaction's [[Output]]
* @param assetID Optional {@link https://github.com/feross/buffer|Buffer} of the asset ID for the StandardUTXO
* @param outputid Optional {@link https://github.com/feross/buffer|Buffer} or number of the output ID for the StandardUTXO
*/
constructor(codecID = 0, txID = undefined, outputidx = undefined, assetID = undefined, output = undefined) {
super();
this._typeName = "StandardUTXO";
this._typeID = undefined;
this.codecID = buffer_1.Buffer.alloc(2);
this.txid = buffer_1.Buffer.alloc(32);
this.outputidx = buffer_1.Buffer.alloc(4);
this.assetID = buffer_1.Buffer.alloc(32);
this.output = undefined;
/**
* Returns the numeric representation of the CodecID.
*/
this.getCodecID = () => this.codecID.readUInt8(0);
/**
* Returns the {@link https://github.com/feross/buffer|Buffer} representation of the CodecID
*/
this.getCodecIDBuffer = () => this.codecID;
/**
* Returns a {@link https://github.com/feross/buffer|Buffer} of the TxID.
*/
this.getTxID = () => this.txid;
/**
* Returns a {@link https://github.com/feross/buffer|Buffer} of the OutputIdx.
*/
this.getOutputIdx = () => this.outputidx;
/**
* Returns the assetID as a {@link https://github.com/feross/buffer|Buffer}.
*/
this.getAssetID = () => this.assetID;
/**
* Returns the UTXOID as a base-58 string (UTXOID is a string )
*/
this.getUTXOID = () => bintools.bufferToB58(buffer_1.Buffer.concat([this.getTxID(), this.getOutputIdx()]));
/**
* Returns a reference to the output
*/
this.getOutput = () => this.output;
if (typeof codecID !== "undefined") {
this.codecID.writeUInt8(codecID, 0);
}
if (typeof txID !== "undefined") {
this.txid = txID;
}
if (typeof outputidx === "number") {
this.outputidx.writeUInt32BE(outputidx, 0);
}
else if (outputidx instanceof buffer_1.Buffer) {
this.outputidx = outputidx;
}
if (typeof assetID !== "undefined") {
this.assetID = assetID;
}
if (typeof output !== "undefined") {
this.output = output;
}
}
}
exports.StandardUTXO = StandardUTXO;
/**
* Class representing a set of [[StandardUTXO]]s.
*/
class StandardUTXOSet extends serialization_1.Serializable {
constructor() {
super(...arguments);
this._typeName = "StandardUTXOSet";
this._typeID = undefined;
this.utxos = {};
this.addressUTXOs = {}; // maps address to utxoids:locktime
/**
* Returns true if the [[StandardUTXO]] is in the StandardUTXOSet.
*
* @param utxo Either a [[StandardUTXO]] a cb58 serialized string representing a StandardUTXO
*/
this.includes = (utxo) => {
let utxoX = undefined;
let utxoid = undefined;
try {
utxoX = this.parseUTXO(utxo);
utxoid = utxoX.getUTXOID();
}
catch (e) {
if (e instanceof Error) {
console.log(e.message);
}
else {
console.log(e);
}
return false;
}
return utxoid in this.utxos;
};
/**
* Removes a [[StandardUTXO]] from the [[StandardUTXOSet]] if it exists.
*
* @param utxo Either a [[StandardUTXO]] an cb58 serialized string representing a StandardUTXO
*
* @returns A [[StandardUTXO]] if it was removed and undefined if nothing was removed.
*/
this.remove = (utxo) => {
let utxovar = undefined;
try {
utxovar = this.parseUTXO(utxo);
}
catch (e) {
if (e instanceof Error) {
console.log(e.message);
}
else {
console.log(e);
}
return undefined;
}
const utxoid = utxovar.getUTXOID();
if (!(utxoid in this.utxos)) {
return undefined;
}
delete this.utxos[`${utxoid}`];
const addresses = Object.keys(this.addressUTXOs);
for (let i = 0; i < addresses.length; i++) {
if (utxoid in this.addressUTXOs[addresses[`${i}`]]) {
delete this.addressUTXOs[addresses[`${i}`]][`${utxoid}`];
}
}
return utxovar;
};
/**
* Removes an array of [[StandardUTXO]]s to the [[StandardUTXOSet]].
*
* @param utxo Either a [[StandardUTXO]] an cb58 serialized string representing a StandardUTXO
* @param overwrite If true, if the UTXOID already exists, overwrite it... default false
*
* @returns An array of UTXOs which were removed.
*/
this.removeArray = (utxos) => {
const removed = [];
for (let i = 0; i < utxos.length; i++) {
const result = this.remove(utxos[`${i}`]);
if (typeof result !== "undefined") {
removed.push(result);
}
}
return removed;
};
/**
* Gets a [[StandardUTXO]] from the [[StandardUTXOSet]] by its UTXOID.
*
* @param utxoid String representing the UTXOID
*
* @returns A [[StandardUTXO]] if it exists in the set.
*/
this.getUTXO = (utxoid) => this.utxos[`${utxoid}`];
/**
* Gets all the [[StandardUTXO]]s, optionally that match with UTXOIDs in an array
*
* @param utxoids An optional array of UTXOIDs, returns all [[StandardUTXO]]s if not provided
*
* @returns An array of [[StandardUTXO]]s.
*/
this.getAllUTXOs = (utxoids = undefined) => {
let results = [];
if (typeof utxoids !== "undefined" && Array.isArray(utxoids)) {
results = utxoids
.filter((utxoid) => this.utxos[`${utxoid}`])
.map((utxoid) => this.utxos[`${utxoid}`]);
}
else {
results = Object.values(this.utxos);
}
return results;
};
/**
* Gets all the [[StandardUTXO]]s as strings, optionally that match with UTXOIDs in an array.
*
* @param utxoids An optional array of UTXOIDs, returns all [[StandardUTXO]]s if not provided
*
* @returns An array of [[StandardUTXO]]s as cb58 serialized strings.
*/
this.getAllUTXOStrings = (utxoids = undefined) => {
const results = [];
const utxos = Object.keys(this.utxos);
if (typeof utxoids !== "undefined" && Array.isArray(utxoids)) {
for (let i = 0; i < utxoids.length; i++) {
if (utxoids[`${i}`] in this.utxos) {
results.push(this.utxos[utxoids[`${i}`]].toString());
}
}
}
else {
for (const u of utxos) {
results.push(this.utxos[`${u}`].toString());
}
}
return results;
};
/**
* Given an address or array of addresses, returns all the UTXOIDs for those addresses
*
* @param address An array of address {@link https://github.com/feross/buffer|Buffer}s
* @param spendable If true, only retrieves UTXOIDs whose locktime has passed
*
* @returns An array of addresses.
*/
this.getUTXOIDs = (addresses = undefined, spendable = true) => {
if (typeof addresses !== "undefined") {
const results = [];
const now = (0, helperfunctions_1.UnixNow)();
for (let i = 0; i < addresses.length; i++) {
if (addresses[`${i}`].toString("hex") in this.addressUTXOs) {
const entries = Object.entries(this.addressUTXOs[addresses[`${i}`].toString("hex")]);
for (const [utxoid, locktime] of entries) {
if ((results.indexOf(utxoid) === -1 &&
spendable &&
locktime.lte(now)) ||
!spendable) {
results.push(utxoid);
}
}
}
}
return results;
}
return Object.keys(this.utxos);
};
/**
* Gets the addresses in the [[StandardUTXOSet]] and returns an array of {@link https://github.com/feross/buffer|Buffer}.
*/
this.getAddresses = () => Object.keys(this.addressUTXOs).map((k) => buffer_1.Buffer.from(k, "hex"));
/**
* Returns the balance of a set of addresses in the StandardUTXOSet.
*
* @param addresses An array of addresses
* @param assetID Either a {@link https://github.com/feross/buffer|Buffer} or an cb58 serialized representation of an AssetID
* @param asOf The timestamp to verify the transaction against as a {@link https://github.com/indutny/bn.js/|BN}
*
* @returns Returns the total balance as a {@link https://github.com/indutny/bn.js/|BN}.
*/
this.getBalance = (addresses, assetID, asOf = undefined) => {
const utxoids = this.getUTXOIDs(addresses);
const utxos = this.getAllUTXOs(utxoids);
let spend = new bn_js_1.default(0);
let asset;
if (typeof assetID === "string") {
asset = bintools.cb58Decode(assetID);
}
else {
asset = assetID;
}
for (let i = 0; i < utxos.length; i++) {
if (utxos[`${i}`].getOutput() instanceof output_1.StandardAmountOutput &&
utxos[`${i}`].getAssetID().toString("hex") === asset.toString("hex") &&
utxos[`${i}`].getOutput().meetsThreshold(addresses, asOf)) {
spend = spend.add(utxos[`${i}`].getOutput().getAmount());
}
}
return spend;
};
/**
* Gets all the Asset IDs, optionally that match with Asset IDs in an array
*
* @param utxoids An optional array of Addresses as string or Buffer, returns all Asset IDs if not provided
*
* @returns An array of {@link https://github.com/feross/buffer|Buffer} representing the Asset IDs.
*/
this.getAssetIDs = (addresses = undefined) => {
const results = new Set();
let utxoids = [];
if (typeof addresses !== "undefined") {
utxoids = this.getUTXOIDs(addresses);
}
else {
utxoids = this.getUTXOIDs();
}
for (let i = 0; i < utxoids.length; i++) {
if (utxoids[`${i}`] in this.utxos && !(utxoids[`${i}`] in results)) {
results.add(this.utxos[utxoids[`${i}`]].getAssetID());
}
}
return [...results];
};
/**
* Returns a new set with copy of UTXOs in this and set parameter.
*
* @param utxoset The [[StandardUTXOSet]] to merge with this one
* @param hasUTXOIDs Will subselect a set of [[StandardUTXO]]s which have the UTXOIDs provided in this array, defults to all UTXOs
*
* @returns A new StandardUTXOSet that contains all the filtered elements.
*/
this.merge = (utxoset, hasUTXOIDs = undefined) => {
const results = this.create();
const utxos1 = this.getAllUTXOs(hasUTXOIDs);
const utxos2 = utxoset.getAllUTXOs(hasUTXOIDs);
const process = (utxo) => {
results.add(utxo);
};
utxos1.forEach(process);
utxos2.forEach(process);
return results;
};
/**
* Set intersetion between this set and a parameter.
*
* @param utxoset The set to intersect
*
* @returns A new StandardUTXOSet containing the intersection
*/
this.intersection = (utxoset) => {
const us1 = this.getUTXOIDs();
const us2 = utxoset.getUTXOIDs();
const results = us1.filter((utxoid) => us2.includes(utxoid));
return this.merge(utxoset, results);
};
/**
* Set difference between this set and a parameter.
*
* @param utxoset The set to difference
*
* @returns A new StandardUTXOSet containing the difference
*/
this.difference = (utxoset) => {
const us1 = this.getUTXOIDs();
const us2 = utxoset.getUTXOIDs();
const results = us1.filter((utxoid) => !us2.includes(utxoid));
return this.merge(utxoset, results);
};
/**
* Set symmetrical difference between this set and a parameter.
*
* @param utxoset The set to symmetrical difference
*
* @returns A new StandardUTXOSet containing the symmetrical difference
*/
this.symDifference = (utxoset) => {
const us1 = this.getUTXOIDs();
const us2 = utxoset.getUTXOIDs();
const results = us1
.filter((utxoid) => !us2.includes(utxoid))
.concat(us2.filter((utxoid) => !us1.includes(utxoid)));
return this.merge(utxoset, results);
};
/**
* Set union between this set and a parameter.
*
* @param utxoset The set to union
*
* @returns A new StandardUTXOSet containing the union
*/
this.union = (utxoset) => this.merge(utxoset);
/**
* Merges a set by the rule provided.
*
* @param utxoset The set to merge by the MergeRule
* @param mergeRule The [[MergeRule]] to apply
*
* @returns A new StandardUTXOSet containing the merged data
*
* @remarks
* The merge rules are as follows:
* * "intersection" - the intersection of the set
* * "differenceSelf" - the difference between the existing data and new set
* * "differenceNew" - the difference between the new data and the existing set
* * "symDifference" - the union of the differences between both sets of data
* * "union" - the unique set of all elements contained in both sets
* * "unionMinusNew" - the unique set of all elements contained in both sets, excluding values only found in the new set
* * "unionMinusSelf" - the unique set of all elements contained in both sets, excluding values only found in the existing set
*/
this.mergeByRule = (utxoset, mergeRule) => {
let uSet;
switch (mergeRule) {
case "intersection":
return this.intersection(utxoset);
case "differenceSelf":
return this.difference(utxoset);
case "differenceNew":
return utxoset.difference(this);
case "symDifference":
return this.symDifference(utxoset);
case "union":
return this.union(utxoset);
case "unionMinusNew":
uSet = this.union(utxoset);
return uSet.difference(utxoset);
case "unionMinusSelf":
uSet = this.union(utxoset);
return uSet.difference(this);
default:
throw new errors_1.MergeRuleError("Error - StandardUTXOSet.mergeByRule: bad MergeRule");
}
};
}
serialize(encoding = "hex") {
let fields = super.serialize(encoding);
let utxos = {};
for (let utxoid in this.utxos) {
let utxoidCleaned = serialization.encoder(utxoid, encoding, "base58", "base58");
utxos[`${utxoidCleaned}`] = this.utxos[`${utxoid}`].serialize(encoding);
}
let addressUTXOs = {};
for (let address in this.addressUTXOs) {
let addressCleaned = serialization.encoder(address, encoding, "hex", "cb58");
let utxobalance = {};
for (let utxoid in this.addressUTXOs[`${address}`]) {
let utxoidCleaned = serialization.encoder(utxoid, encoding, "base58", "base58");
utxobalance[`${utxoidCleaned}`] = serialization.encoder(this.addressUTXOs[`${address}`][`${utxoid}`], encoding, "BN", "decimalString");
}
addressUTXOs[`${addressCleaned}`] = utxobalance;
}
return Object.assign(Object.assign({}, fields), { utxos,
addressUTXOs });
}
/**
* Adds a [[StandardUTXO]] to the StandardUTXOSet.
*
* @param utxo Either a [[StandardUTXO]] an cb58 serialized string representing a StandardUTXO
* @param overwrite If true, if the UTXOID already exists, overwrite it... default false
*
* @returns A [[StandardUTXO]] if one was added and undefined if nothing was added.
*/
add(utxo, overwrite = false) {
let utxovar = undefined;
try {
utxovar = this.parseUTXO(utxo);
}
catch (e) {
if (e instanceof Error) {
console.log(e.message);
}
else {
console.log(e);
}
return undefined;
}
const utxoid = utxovar.getUTXOID();
if (!(utxoid in this.utxos) || overwrite === true) {
this.utxos[`${utxoid}`] = utxovar;
const addresses = utxovar.getOutput().getAddresses();
const locktime = utxovar.getOutput().getLocktime();
for (let i = 0; i < addresses.length; i++) {
const address = addresses[`${i}`].toString("hex");
if (!(address in this.addressUTXOs)) {
this.addressUTXOs[`${address}`] = {};
}
this.addressUTXOs[`${address}`][`${utxoid}`] = locktime;
}
return utxovar;
}
return undefined;
}
/**
* Adds an array of [[StandardUTXO]]s to the [[StandardUTXOSet]].
*
* @param utxo Either a [[StandardUTXO]] an cb58 serialized string representing a StandardUTXO
* @param overwrite If true, if the UTXOID already exists, overwrite it... default false
*
* @returns An array of StandardUTXOs which were added.
*/
addArray(utxos, overwrite = false) {
const added = [];
for (let i = 0; i < utxos.length; i++) {
let result = this.add(utxos[`${i}`], overwrite);
if (typeof result !== "undefined") {
added.push(result);
}
}
return added;
}
filter(args, lambda) {
let newset = this.clone();
let utxos = this.getAllUTXOs();
for (let i = 0; i < utxos.length; i++) {
if (lambda(utxos[`${i}`], ...args) === false) {
newset.remove(utxos[`${i}`]);
}
}
return newset;
}
}
exports.StandardUTXOSet = StandardUTXOSet;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXR4b3MuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY29tbW9uL3V0eG9zLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBOzs7R0FHRztBQUNILG9DQUFnQztBQUNoQyxpRUFBd0M7QUFDeEMsa0RBQXNCO0FBQ3RCLHFDQUEyRDtBQUMzRCw4REFBa0Q7QUFFbEQsMERBSStCO0FBQy9CLDRDQUFnRDtBQUVoRDs7R0FFRztBQUNILE1BQU0sUUFBUSxHQUFhLGtCQUFRLENBQUMsV0FBVyxFQUFFLENBQUE7QUFDakQsTUFBTSxhQUFhLEdBQWtCLDZCQUFhLENBQUMsV0FBVyxFQUFFLENBQUE7QUFFaEU7O0dBRUc7QUFDSCxNQUFzQixZQUFhLFNBQVEsNEJBQVk7SUFJckQsU0FBUyxDQUFDLFdBQStCLEtBQUs7UUFDNUMsSUFBSSxNQUFNLEdBQVcsS0FBSyxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsQ0FBQTtRQUM5Qyx1Q0FDSyxNQUFNLEtBQ1QsT0FBTyxFQUFFLGFBQWEsQ0FBQyxPQUFPLENBQzVCLElBQUksQ0FBQyxPQUFPLEVBQ1osUUFBUSxFQUNSLFFBQVEsRUFDUixlQUFlLENBQ2hCLEVBQ0QsSUFBSSxFQUFFLGFBQWEsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxRQUFRLEVBQUUsUUFBUSxFQUFFLE1BQU0sQ0FBQyxFQUNsRSxTQUFTLEVBQUUsYUFBYSxDQUFDLE9BQU8sQ0FDOUIsSUFBSSxDQUFDLFNBQVMsRUFDZCxRQUFRLEVBQ1IsUUFBUSxFQUNSLGVBQWUsQ0FDaEIsRUFDRCxPQUFPLEVBQUUsYUFBYSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLFFBQVEsRUFBRSxRQUFRLEVBQUUsTUFBTSxDQUFDLEVBQ3hFLE1BQU0sRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsSUFDeEM7SUFDSCxDQUFDO0lBQ0QsV0FBVyxDQUFDLE1BQWMs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LEtBQUssQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQTthQUM3QjtTQUNGO1FBQ0QsT0FBTyxNQUFNLENBQUE7SUFDZixDQUFDO0NBc0hGO0FBamVELDBDQWllQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQHBhY2thZ2VEb2N1bWVudGF0aW9uXG4gKiBAbW9kdWxlIENvbW1vbi1VVFhPc1xuICovXG5pbXBvcnQgeyBCdWZmZXIgfSBmcm9tIFwiYnVmZmVyL1wiXG5pbXBvcnQgQmluVG9vbHMgZnJvbSBcIi4uL3V0aWxzL2JpbnRvb2xzXCJcbmltcG9ydCBCTiBmcm9tIFwiYm4uanNcIlxuaW1wb3J0IHsgQmFzZU91dHB1dCwgU3RhbmRhcmRBbW91bnRPdXRwdXQgfSBmcm9tIFwiLi9vdXRwdXRcIlxuaW1wb3J0IHsgVW5peE5vdyB9IGZyb20gXCIuLi91dGlscy9oZWxwZXJmdW5jdGlvbnNcIlxuaW1wb3J0IHsgTWVyZ2VSdWxlIH0gZnJvbSBcIi4uL3V0aWxzL2NvbnN0YW50c1wiXG5pbXBvcnQge1xuICBTZXJpYWxpemFibGUsXG4gIFNlcmlhbGl6YXRpb24sXG4gIFNlcmlhbGl6ZWRFbmNvZGluZ1xufSBmcm9tIFwiLi4vdXRpbHMvc2VyaWFsaXphdGlvblwiXG5pbXBvcnQgeyBNZXJnZVJ1bGVFcnJvciB9IGZyb20gXCIuLi91dGlscy9lcnJvcnNcIlxuXG4vKipcbiAqIEBpZ25vcmVcbiAqL1xuY29uc3QgYmludG9vbHM6IEJpblRvb2xzID0gQmluVG9vbHMuZ2V0SW5zdGFuY2UoKVxuY29uc3Qgc2VyaWFsaXphdGlvbjogU2VyaWFsaXphdGlvbiA9IFNlcmlhbGl6YXRpb24uZ2V0SW5zdGFuY2UoKVxuXG4vKipcbiAqIENsYXNzIGZvciByZXByZXNlbnRpbmcgYSBzaW5nbGUgU3RhbmRhcmRVVFhPLlxuICovXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgU3RhbmRhcmRVVFhPIGV4dGVuZHMgU2VyaWFsaXphYmxlIHtcbiAgcHJvdGVjdGVkIF90eXBlTmFtZSA9IFwiU3RhbmRhcmRVVFhPXCJcbiAgcHJvdGVjdGVkIF90eXBlSUQgPSB1bmRlZmluZWRcblxuICBzZXJpYWxpemUoZW5jb2Rpbmc6IFNlcmlhbGl6ZWRFbmNvZGluZyA9IFwiaGV4XCIpOiBvYmplY3Qge1xuICAgIGxldCBmaWVsZHM6IG9iamVjdCA9IHN1cGVyLnNlcmlhbGl6ZShlbmNvZGluZylcbiAgICByZXR1cm4ge1xuICAgICAgLi4uZmllbGRzLFxuICAgICAgY29kZWNJRDogc2VyaWFsaXphdGlvbi5lbmNvZGVyKFxuICAgICAgICB0aGlzLmNvZGVjSUQsXG4gICAgICAgIGVuY29kaW5nLFxuICAgICAgICBcIkJ1ZmZlclwiLFxuICAgICAgICBcImRlY2ltYWxTdHJpbmdcIlxuICAgICAgKSxcbiAgICAgIHR4aWQ6IHNlcmlhbGl6YXRpb24uZW5jb2Rlcih0aGlzLnR4aWQsIGVuY29kaW5nLCBcIkJ1ZmZlclwiLCBcImNiNThcIiksXG4gICAgICBvdXRwdXRpZHg6IHNlcmlhbGl6YXRpb24uZW5jb2RlcihcbiAgICAgICAgdGhpcy5vdXRwdXRpZHgsXG4gICAgICAgIGVuY29kaW5nLFxuICAgICAgICBcIkJ1ZmZlclwiLFxuICAgICAgICBcImRlY2ltYWxTdHJpbmdcIlxuICAgICAgKSxcbiAgICAgIGFzc2V0SUQ6IHNlcmlhbGl6YXRpb24uZW5jb2Rlcih0aGlzLmFzc2V0SUQsIGVuY29kaW5nLCBcIkJ1ZmZlclwiLCBcImNiNThcIiksXG4gICAgICBvdXRwdXQ6IHRoaXMub3V0cHV0LnNlcmlhbGl6ZShlbmNvZGluZylcbiAgICB9XG4gIH1cbiAgZGVzZXJpYWxpemUoZmllbGRzOiBvYmplY3QsIGVuY29kaW5nOiBTZXJpYWxpemVkRW5jb2RpbmcgPSBcImhleFwiKSB7XG4gICAgc3VwZXIuZGVzZXJpYWxpemUoZmllbGRzLCBlbmNvZGluZylcbiAgICB0aGlzLmNvZGVjSUQgPSBzZXJpYWxpemF0aW9uLmRlY29kZXIoXG4gICAgICBmaWVsZHNbXCJjb2RlY0lEXCJdLFxuICAgICAgZW5jb2RpbmcsXG4gICAgICBcImRlY2ltYWxTdHJpbmdcIixcbiAgICAgIFwiQnVmZmVyXCIsXG4gICAgICAyXG4gICAgKVxuICAgIHRoaXMudHhpZCA9IHNlcmlhbGl6YXRpb24uZGVjb2RlcihcbiAgICAgIGZpZWxkc1tcInR4aWRcIl0sXG4gICAgICBlbmNvZGluZyxcbiAgICAgIFwiY2I1OFwiLFxuICAgICAgXCJCdWZmZXJcIixcbiAgICAgIDMyXG4gICAgKVxuICAgIHRoaXMub3V0cHV0aWR4ID0gc2VyaWFsaXphdGlvbi5kZWNvZGVyKFxuICAgICAgZmllbGRzW1wib3V0cHV0aWR4XCJdLFxuICAgICAgZW5jb2RpbmcsXG4gICAgICBcImRlY2ltYWxTdHJpbmdcIixcbiAgICAgIFwiQnVmZmVyXCIsXG4gICAgICA0XG4gICAgKVxuICAgIHRoaXMuYXNzZXRJRCA9IHNlcmlhbGl6YXRpb24uZGVjb2RlcihcbiAgICAgIGZpZWxkc1tcImFzc2V0SURcIl0sXG4gICAgICBlbmNvZGluZyxcbiAgICAgIFwiY2I1OFwiLFxuICAgICAgXCJCdWZmZXJcIixcbiAgICAgIDMyXG4gICAgKVxuICB9XG5cbiAgcHJvdGVjdGVkIGNvZGVjSUQ6IEJ1ZmZlciA9IEJ1ZmZlci5hbGxvYygyKVxuICBwcm90ZWN0ZWQgdHhpZDogQnVmZmVyID0gQnVmZmVyLmFsbG9jKDMyKVxuICBwcm90ZWN0ZWQgb3V0cHV0aWR4OiBCdWZmZXIgPSBCdWZmZXIuYWxsb2MoNClcbiAgcHJvdGVjdGVkIGFzc2V0SUQ6IEJ1ZmZlciA9IEJ1ZmZlci5hbGxvYygzMilcbiAgcHJvdGVjdGVkIG91dHB1dDogQmFzZU91dHB1dCA9IHVuZGVmaW5lZFxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBudW1lcmljIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBDb2RlY0lELlxuICAgKi9cbiAgZ2V0Q29kZWNJRCA9ICgpOiAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqLyBudW1iZXIgPT5cbiAgICB0aGlzLmNvZGVjSUQucmVhZFVJbnQ4KDApXG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIHtAbGluayBodHRwczovL2dpdGh1Yi5jb20vZmVyb3NzL2J1ZmZlcnxCdWZmZXJ9IHJlcHJlc2VudGF0aW9uIG9mIHRoZSBDb2RlY0lEXG4gICAqL1xuICBnZXRDb2RlY0lEQnVmZmVyID0gKCk6IEJ1ZmZlciA9PiB0aGlzLmNvZGVjSURcblxuICAvKipcbiAgICogUmV0dXJucyBhIHtAbGluayBodHRwczovL2dpdGh1Yi5jb20vZmVyb3NzL2J1ZmZlcnxCdWZmZXJ9IG9mIHRoZSBUeElELlxuICAgKi9cbiAgZ2V0VHhJRCA9ICgpOiAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqLyBCdWZmZXIgPT4gdGhpcy50eGlkXG5cbiAgLyoqXG4gICAqIFJldHVybnMgYSB7QGxpbmsgaHR0cHM6Ly9naXRodWIuY29tL2Zlcm9zcy9idWZmZXJ8QnVmZmVyfSAgb2YgdGhlIE91dHB1dElkeC5cbiAgICovXG4gIGdldE91dHB1dElkeCA9ICgpOiAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqLyBCdWZmZXIgPT4gdGhpcy5vdXRwdXRpZHhcblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgYXNzZXRJRCBhcyBhIHtAbGluayBodHRwczovL2dpdGh1Yi5jb20vZmVyb3NzL2J1ZmZlcnxCdWZmZXJ9LlxuICAgKi9cbiAgZ2V0QXNzZXRJRCA9ICgpOiBCdWZmZXIgPT4gdGhpcy5hc3NldElEXG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIFVUWE9JRCBhcyBhIGJhc2UtNTggc3RyaW5nIChVVFhPSUQgaXMgYSBzdHJpbmcgKVxuICAgKi9cbiAgZ2V0VVRYT0lEID0gKCk6IC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovIHN0cmluZyA9PlxuICAgIGJpbnRvb2xzLmJ1ZmZlclRvQjU4KEJ1ZmZlci5jb25jYXQoW3RoaXMuZ2V0VHhJRCgpLCB0aGlzLmdldE91dHB1dElkeCgpXSkpXG5cbiAgLyoqXG4gICAqIFJldHVybnMgYSByZWZlcmVuY2UgdG8gdGhlIG91dHB1dFxuICAgKi9cbiAgZ2V0T3V0cHV0ID0gKCk6IEJhc2VPdXRwdXQgPT4gdGhpcy5vdXRwdXRcblxuICAvKipcbiAgICogVGFrZXMgYSB7QGxpbmsgaHR0cHM6Ly9naXRodWIuY29tL2Zlcm9zcy9idWZmZXJ8QnVmZmVyfSBjb250YWluaW5nIGFuIFtbU3RhbmRhcmRVVFhPXV0sIHBhcnNlcyBpdCwgcG9wdWxhdGVzIHRoZSBjbGFzcywgYW5kIHJldHVybnMgdGhlIGxlbmd0aCBvZiB0aGUgU3RhbmRhcmRVVFhPIGluIGJ5dGVzLlxuICAgKlxuICAgKiBAcGFyYW0gYnl0ZXMgQSB7QGxpbmsgaHR0cHM6Ly9naXRodWIuY29tL2Zlcm9zcy9idWZmZXJ8QnVmZmVyfSBjb250YWluaW5nIGEgcmF3IFtbU3RhbmRhcmRVVFhPXV1cbiAgICovXG4gIGFic3RyYWN0IGZyb21CdWZmZXIoYnl0ZXM6IEJ1ZmZlciwgb2Zmc2V0PzogbnVtYmVyKTogbnVtYmVyXG5cbiAgLyoqXG4gICAqIFJldHVybnMgYSB7QGxpbmsgaHR0cHM6Ly9naXRodWIuY29tL2Zlcm9zcy9idWZmZXJ8QnVmZmVyfSByZXByZXNlbnRhdGlvbiBvZiB0aGUgW1tTdGFuZGFyZFVUWE9dXS5cbiAgICovXG4gIHRvQnVmZmVyKCk6IEJ1ZmZlciB7XG4gICAgY29uc3Qgb3V0YnVmZjogQnVmZmVyID0gdGhpcy5vdXRwdXQudG9CdWZmZXIoKVxuICAgIGNvbnN0IG91dHB1dGlkYnVmZmVyOiBCdWZmZXIgPSBCdWZmZXIuYWxsb2MoNClcbiAgICBvdXRwdXRpZGJ1ZmZlci53cml0ZVVJbnQzMkJFKHRoaXMub3V0cHV0LmdldE91dHB1dElEKCksIDApXG4gICAgY29uc3QgYmFycjogQnVmZmVyW10gPSBbXG4gICAgICB0aGlzLmNvZGVjSUQsXG4gICAgICB0aGlzLnR4aWQsXG4gICAgICB0aGlzLm91dHB1dGlkeCxcbiAgICAgIHRoaXMuYXNzZXRJRCxcbiAgICAgIG91dHB1dGlkYnVmZmVyLFxuICAgICAgb3V0YnVmZlxuICAgIF1cbiAgICByZXR1cm4gQnVmZmVyLmNvbmNhdChcbiAgICAgIGJhcnIsXG4gICAgICB0aGlzLmNvZGVjSUQubGVuZ3RoICtcbiAgICAgICAgdGhpcy50eGlkLmxlbmd0aCArXG4gICAgICAgIHRoaXMub3V0cHV0aWR4Lmxlbmd0aCArXG4gICAgICAgIHRoaXMuYXNzZXRJRC5sZW5ndGggK1xuICAgICAgICBvdXRwdXRpZGJ1ZmZlci5sZW5ndGggK1xuICAgICAgICBvdXRidWZmLmxlbmd0aFxuICAgIClcbiAgfVxuXG4gIGFic3RyYWN0IGZyb21TdHJpbmcoc2VyaWFsaXplZDogc3RyaW5nKTogbnVtYmVyXG5cbiAgYWJzdHJhY3QgdG9TdHJpbmcoKTogc3RyaW5nXG5cbiAgYWJzdHJhY3QgY2xvbmUoKTogdGhpc1xuXG4gIGFic3RyYWN0IGNyZWF0ZShcbiAgICBjb2RlY0lEPzogbnVtYmVyLFxuICAgIHR4aWQ/OiBCdWZmZXIsXG4gICAgb3V0cHV0aWR4PzogQnVmZmVyIHwgbnVtYmVyLFxuICAgIGFzc2V0SUQ/OiBCdWZmZXIsXG4gICAgb3V0cHV0PzogQmFzZU91dHB1dFxuICApOiB0aGlzXG5cbiAgLyoqXG4gICAqIENsYXNzIGZvciByZXByZXNlbnRpbmcgYSBzaW5nbGUgU3RhbmRhcmRVVFhPLlxuICAgKlxuICAgKiBAcGFyYW0gY29kZWNJRCBPcHRpb25hbCBudW1iZXIgd2hpY2ggc3BlY2lmaWVzIHRoZSBjb2RlSUQgb2YgdGhlIFVUWE8uIERlZmF1bHQgMFxuICAgKiBAcGFyYW0gdHhJRCBPcHRpb25hbCB7QGxpbmsgaHR0cHM6Ly9naXRodWIuY29tL2Zlcm9zcy9idWZmZXJ8QnVmZmVyfSBvZiB0cmFuc2FjdGlvbiBJRCBmb3IgdGhlIFN0YW5kYXJkVVRYT1xuICAgKiBAcGFyYW0gdHhpZHggT3B0aW9uYWwge0BsaW5rIGh0dHBzOi8vZ2l0aHViLmNvbS9mZXJvc3MvYnVmZmVyfEJ1ZmZlcn0gb3IgbnVtYmVyIGZvciB0aGUgaW5kZXggb2YgdGhlIHRyYW5zYWN0aW9uJ3MgW1tPdXRwdXRdXVxuICAgKiBAcGFyYW0gYXNzZXRJRCBPcHRpb25hbCB7QGxpbmsgaHR0cHM6Ly9naXRodWIuY29tL2Zlcm9zcy9idWZmZXJ8QnVmZmVyfSBvZiB0aGUgYXNzZXQgSUQgZm9yIHRoZSBTdGFuZGFyZFVUWE9cbiAgICogQHBhcmFtIG91dHB1dGlkIE9wdGlvbmFsIHtAbGluayBodHRwczovL2dpdGh1Yi5jb20vZmVyb3NzL2J1ZmZlcnxCdWZmZXJ9IG9yIG51bWJlciBvZiB0aGUgb3V0cHV0IElEIGZvciB0aGUgU3RhbmRhcmRVVFhPXG4gICAqL1xuICBjb25zdHJ1Y3RvcihcbiAgICBjb2RlY0lEOiBudW1iZXIgPSAwLFxuICAgIHR4SUQ6IEJ1ZmZlciA9IHVuZGVmaW5lZCxcbiAgICBvdXRwdXRpZHg6IEJ1ZmZlciB8IG51bWJlciA9IHVuZGVmaW5lZCxcbiAgICBhc3NldElEOiBCdWZmZXIgPSB1bmRlZmluZWQsXG4gICAgb3V0cHV0OiBCYXNlT3V0cHV0ID0gdW5kZWZpbmVkXG4gICkge1xuICAgIHN1cGVyKClcbiAgICBpZiAodHlwZW9mIGNvZGVjSUQgIT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICAgIHRoaXMuY29kZWNJRC53cml0ZVVJbnQ4KGNvZGVjSUQsIDApXG4gICAgfVxuICAgIGlmICh0eXBlb2