UNPKG

@c4tplatform/caminojs

Version:
722 lines 129 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.UTXOSet = exports.AssetAmountDestination = exports.UTXO = void 0; /** * @packageDocumentation * @module API-AVM-UTXOs */ const buffer_1 = require("buffer/"); const bintools_1 = __importDefault(require("../../utils/bintools")); const bn_js_1 = __importDefault(require("bn.js")); const outputs_1 = require("./outputs"); const constants_1 = require("./constants"); const tx_1 = require("./tx"); const inputs_1 = require("./inputs"); const ops_1 = require("./ops"); const helperfunctions_1 = require("../../utils/helperfunctions"); const initialstates_1 = require("./initialstates"); const utxos_1 = require("../../common/utxos"); const createassettx_1 = require("./createassettx"); const operationtx_1 = require("./operationtx"); const basetx_1 = require("./basetx"); const exporttx_1 = require("./exporttx"); const importtx_1 = require("./importtx"); const constants_2 = require("../../utils/constants"); const assetamount_1 = require("../../common/assetamount"); 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 UTXO. */ class UTXO extends utxos_1.StandardUTXO { constructor() { super(...arguments); this._typeName = "UTXO"; this._typeID = undefined; } //serialize is inherited deserialize(fields, encoding = "hex") { super.deserialize(fields, encoding); this.output = (0, outputs_1.SelectOutputClass)(fields["output"]["_typeID"]); this.output.deserialize(fields["output"], encoding); } fromBuffer(bytes, offset = 0) { this.codecID = bintools.copyFrom(bytes, offset, offset + 2); offset += 2; this.txid = bintools.copyFrom(bytes, offset, offset + 32); offset += 32; this.outputidx = bintools.copyFrom(bytes, offset, offset + 4); offset += 4; this.assetID = bintools.copyFrom(bytes, offset, offset + 32); offset += 32; const outputid = bintools .copyFrom(bytes, offset, offset + 4) .readUInt32BE(0); offset += 4; this.output = (0, outputs_1.SelectOutputClass)(outputid); return this.output.fromBuffer(bytes, offset); } /** * Takes a base-58 string containing a [[UTXO]], parses it, populates the class, and returns the length of the StandardUTXO in bytes. * * @param serialized A base-58 string containing a raw [[UTXO]] * * @returns The length of the raw [[UTXO]] * * @remarks * unlike most fromStrings, it expects the string to be serialized in cb58 format */ fromString(serialized) { /* istanbul ignore next */ return this.fromBuffer(bintools.cb58Decode(serialized)); } /** * Returns a base-58 representation of the [[UTXO]]. * * @remarks * unlike most toStrings, this returns in cb58 serialization format */ toString() { /* istanbul ignore next */ return bintools.cb58Encode(this.toBuffer()); } clone() { const utxo = new UTXO(); utxo.fromBuffer(this.toBuffer()); return utxo; } create(codecID = constants_1.AVMConstants.LATESTCODEC, txid = undefined, outputidx = undefined, assetID = undefined, output = undefined) { return new UTXO(codecID, txid, outputidx, assetID, output); } } exports.UTXO = UTXO; class AssetAmountDestination extends assetamount_1.StandardAssetAmountDestination { } exports.AssetAmountDestination = AssetAmountDestination; /** * Class representing a set of [[UTXO]]s. */ class UTXOSet extends utxos_1.StandardUTXOSet { constructor() { super(...arguments); this._typeName = "UTXOSet"; this._typeID = undefined; this.getMinimumSpendable = (aad, asOf = (0, helperfunctions_1.UnixNow)(), locktime = new bn_js_1.default(0), threshold = 1) => { const utxoArray = this.getAllUTXOs(); const outids = {}; for (let i = 0; i < utxoArray.length && !aad.canComplete(); i++) { const u = utxoArray[`${i}`]; const assetKey = u.getAssetID().toString("hex"); const fromAddresses = aad.getSenders(); if (u.getOutput() instanceof outputs_1.AmountOutput && aad.assetExists(assetKey) && u.getOutput().meetsThreshold(fromAddresses, asOf)) { const am = aad.getAssetAmount(assetKey); if (!am.isFinished()) { const uout = u.getOutput(); outids[`${assetKey}`] = uout.getOutputID(); const amount = uout.getAmount(); am.spendAmount(amount); const txid = u.getTxID(); const outputidx = u.getOutputIdx(); const input = new inputs_1.SECPTransferInput(amount); const xferin = new inputs_1.TransferableInput(txid, outputidx, u.getAssetID(), input); const spenders = uout.getSpenders(fromAddresses, asOf); for (let j = 0; j < spenders.length; j++) { const idx = uout.getAddressIdx(spenders[`${j}`]); if (idx === -1) { /* istanbul ignore next */ throw new errors_1.AddressError("Error - UTXOSet.getMinimumSpendable: no such " + `address in output: ${spenders[`${j}`]}`); } xferin.getInput().addSignatureIdx(idx, spenders[`${j}`]); } aad.addInput(xferin); } else if (aad.assetExists(assetKey) && !(u.getOutput() instanceof outputs_1.AmountOutput)) { /** * Leaving the below lines, not simply for posterity, but for clarification. * AssetIDs may have mixed OutputTypes. * Some of those OutputTypes may implement AmountOutput. * Others may not. * Simply continue in this condition. */ /*return new Error('Error - UTXOSet.getMinimumSpendable: outputID does not ' + `implement AmountOutput: ${u.getOutput().getOutputID}`)*/ continue; } } } if (!aad.canComplete()) { return new errors_1.InsufficientFundsError("Error - UTXOSet.getMinimumSpendable: insufficient " + "funds to create the transaction"); } const amounts = aad.getAmounts(); const zero = new bn_js_1.default(0); for (let i = 0; i < amounts.length; i++) { const assetKey = amounts[`${i}`].getAssetIDString(); const amount = amounts[`${i}`].getAmount(); if (amount.gt(zero)) { const spendout = (0, outputs_1.SelectOutputClass)(outids[`${assetKey}`], amount, aad.getDestinations(), locktime, threshold); const xferout = new outputs_1.TransferableOutput(amounts[`${i}`].getAssetID(), spendout); aad.addOutput(xferout); } const change = amounts[`${i}`].getChange(); if (change.gt(zero)) { const changeout = (0, outputs_1.SelectOutputClass)(outids[`${assetKey}`], change, aad.getChangeAddresses()); const chgxferout = new outputs_1.TransferableOutput(amounts[`${i}`].getAssetID(), changeout); aad.addChange(chgxferout); } } return undefined; }; /** * Creates an [[UnsignedTx]] wrapping a [[BaseTx]]. For more granular control, you may create your own * [[UnsignedTx]] wrapping a [[BaseTx]] manually (with their corresponding [[TransferableInput]]s and [[TransferableOutput]]s). * * @param networkID The number representing NetworkID of the node * @param blockchainID The {@link https://github.com/feross/buffer|Buffer} representing the BlockchainID for the transaction * @param amount The amount of the asset to be spent in its smallest denomination, represented as {@link https://github.com/indutny/bn.js/|BN}. * @param assetID {@link https://github.com/feross/buffer|Buffer} of the asset ID for the UTXO * @param toAddresses The addresses to send the funds * @param fromAddresses The addresses being used to send the funds from the UTXOs {@link https://github.com/feross/buffer|Buffer} * @param changeAddresses Optional. The addresses that can spend the change remaining from the spent UTXOs. Default: toAddresses * @param fee Optional. The amount of fees to burn in its smallest denomination, represented as {@link https://github.com/indutny/bn.js/|BN} * @param feeAssetID Optional. The assetID of the fees being burned. Default: assetID * @param memo Optional. Contains arbitrary data, up to 256 bytes * @param asOf Optional. The timestamp to verify the transaction against as a {@link https://github.com/indutny/bn.js/|BN} * @param locktime Optional. The locktime field created in the resulting outputs * @param toThreshold Optional. The number of signatures required to spend the funds in the resultant UTXO * @param changethreshold Optional. The number of signatures required to spend the funds in the resultant change UTXO * * @returns An unsigned transaction created from the passed in parameters. * */ this.buildBaseTx = (networkID, blockchainID, amount, assetID, toAddresses, fromAddresses, changeAddresses = undefined, fee = undefined, feeAssetID = undefined, memo = undefined, asOf = (0, helperfunctions_1.UnixNow)(), locktime = new bn_js_1.default(0), toThreshold = 1, changeThreshold = 1) => { if (toThreshold > toAddresses.length) { /* istanbul ignore next */ throw new errors_1.ThresholdError("Error - UTXOSet.buildBaseTx: threshold is greater than number of addresses"); } if (typeof changeAddresses === "undefined") { changeAddresses = toAddresses; } if (typeof feeAssetID === "undefined") { feeAssetID = assetID; } const zero = new bn_js_1.default(0); if (amount.eq(zero)) { return undefined; } const aad = new AssetAmountDestination(toAddresses, toThreshold, fromAddresses, changeAddresses, changeThreshold); if (assetID.toString("hex") === feeAssetID.toString("hex")) { aad.addAssetAmount(assetID, amount, fee); } else { aad.addAssetAmount(assetID, amount, zero); if (this._feeCheck(fee, feeAssetID)) { aad.addAssetAmount(feeAssetID, zero, fee); } } let ins = []; let outs = []; const success = this.getMinimumSpendable(aad, asOf, locktime); if (typeof success === "undefined") { ins = aad.getInputs(); outs = aad.getAllOutputs(); } else { throw success; } const baseTx = new basetx_1.BaseTx(networkID, blockchainID, outs, ins, memo); return new tx_1.UnsignedTx(baseTx); }; /** * Creates an unsigned Create Asset transaction. For more granular control, you may create your own * [[CreateAssetTX]] manually (with their corresponding [[TransferableInput]]s, [[TransferableOutput]]s). * * @param networkID The number representing NetworkID of the node * @param blockchainID The {@link https://github.com/feross/buffer|Buffer} representing the BlockchainID for the transaction * @param fromAddresses The addresses being used to send the funds from the UTXOs {@link https://github.com/feross/buffer|Buffer} * @param changeAddresses Optional. The addresses that can spend the change remaining from the spent UTXOs * @param initialState The [[InitialStates]] that represent the intial state of a created asset * @param name String for the descriptive name of the asset * @param symbol String for the ticker symbol of the asset * @param denomination Optional number for the denomination which is 10^D. D must be >= 0 and <= 32. Ex: $1 AVAX = 10^9 $nAVAX * @param mintOutputs Optional. Array of [[SECPMintOutput]]s to be included in the transaction. These outputs can be spent to mint more tokens. * @param fee Optional. The amount of fees to burn in its smallest denomination, represented as {@link https://github.com/indutny/bn.js/|BN} * @param feeAssetID Optional. The assetID of the fees being burned. * @param memo Optional contains arbitrary bytes, up to 256 bytes * @param asOf Optional. The timestamp to verify the transaction against as a {@link https://github.com/indutny/bn.js/|BN} * @param changethreshold Optional. The number of signatures required to spend the funds in the resultant change UTXO * * @returns An unsigned transaction created from the passed in parameters. * */ this.buildCreateAssetTx = (networkID, blockchainID, fromAddresses, changeAddresses, initialState, name, symbol, denomination, mintOutputs = undefined, fee = undefined, feeAssetID = undefined, memo = undefined, asOf = (0, helperfunctions_1.UnixNow)(), changeThreshold = 1) => { const zero = new bn_js_1.default(0); let ins = []; let outs = []; if (this._feeCheck(fee, feeAssetID)) { const aad = new AssetAmountDestination([], 0, fromAddresses, changeAddresses, changeThreshold); aad.addAssetAmount(feeAssetID, zero, fee); const success = this.getMinimumSpendable(aad, asOf); if (typeof success === "undefined") { ins = aad.getInputs(); outs = aad.getAllOutputs(); } else { throw success; } } if (typeof mintOutputs !== "undefined") { for (let i = 0; i < mintOutputs.length; i++) { if (mintOutputs[`${i}`] instanceof outputs_1.SECPMintOutput) { initialState.addOutput(mintOutputs[`${i}`]); } else { throw new errors_1.SECPMintOutputError("Error - UTXOSet.buildCreateAssetTx: A submitted mintOutput was not of type SECPMintOutput"); } } } let CAtx = new createassettx_1.CreateAssetTx(networkID, blockchainID, outs, ins, memo, name, symbol, denomination, initialState); return new tx_1.UnsignedTx(CAtx); }; /** * Creates an unsigned Secp mint transaction. For more granular control, you may create your own * [[OperationTx]] manually (with their corresponding [[TransferableInput]]s, [[TransferableOutput]]s, and [[TransferOperation]]s). * * @param networkID The number representing NetworkID of the node * @param blockchainID The {@link https://github.com/feross/buffer|Buffer} representing the BlockchainID for the transaction * @param mintOwner A [[SECPMintOutput]] which specifies the new set of minters * @param transferOwner A [[SECPTransferOutput]] which specifies where the minted tokens will go * @param fromAddresses The addresses being used to send the funds from the UTXOs {@link https://github.com/feross/buffer|Buffer} * @param changeAddresses The addresses that can spend the change remaining from the spent UTXOs * @param mintUTXOID The UTXOID for the [[SCPMintOutput]] being spent to produce more tokens * @param fee Optional. The amount of fees to burn in its smallest denomination, represented as {@link https://github.com/indutny/bn.js/|BN} * @param feeAssetID Optional. The assetID of the fees being burned. * @param memo Optional contains arbitrary bytes, up to 256 bytes * @param asOf Optional. The timestamp to verify the transaction against as a {@link https://github.com/indutny/bn.js/|BN} * @param changethreshold Optional. The number of signatures required to spend the funds in the resultant change UTXO * * @returns An unsigned transaction created from the passed in parameters. */ this.buildSECPMintTx = (networkID, blockchainID, mintOwner, transferOwner, fromAddresses, changeAddresses, mintUTXOID, fee = undefined, feeAssetID = undefined, memo = undefined, asOf = (0, helperfunctions_1.UnixNow)(), changeThreshold = 1) => { const zero = new bn_js_1.default(0); let ins = []; let outs = []; if (this._feeCheck(fee, feeAssetID)) { const aad = new AssetAmountDestination([], 0, fromAddresses, changeAddresses, changeThreshold); aad.addAssetAmount(feeAssetID, zero, fee); const success = this.getMinimumSpendable(aad, asOf); if (typeof success === "undefined") { ins = aad.getInputs(); outs = aad.getAllOutputs(); } else { throw success; } } let ops = []; let mintOp = new ops_1.SECPMintOperation(mintOwner, transferOwner); let utxo = this.getUTXO(mintUTXOID); if (typeof utxo === "undefined") { throw new errors_1.UTXOError("Error - UTXOSet.buildSECPMintTx: UTXOID not found"); } if (utxo.getOutput().getOutputID() !== constants_1.AVMConstants.SECPMINTOUTPUTID) { throw new errors_1.SECPMintOutputError("Error - UTXOSet.buildSECPMintTx: UTXO is not a SECPMINTOUTPUTID"); } let out = utxo.getOutput(); let spenders = out.getSpenders(fromAddresses, asOf); for (let j = 0; j < spenders.length; j++) { let idx = out.getAddressIdx(spenders[`${j}`]); if (idx == -1) { /* istanbul ignore next */ throw new Error("Error - UTXOSet.buildSECPMintTx: no such address in output"); } mintOp.addSignatureIdx(idx, spenders[`${j}`]); } let transferableOperation = new ops_1.TransferableOperation(utxo.getAssetID(), [`${mintUTXOID}`], mintOp); ops.push(transferableOperation); let operationTx = new operationtx_1.OperationTx(networkID, blockchainID, outs, ins, memo, ops); return new tx_1.UnsignedTx(operationTx); }; /** * Creates an unsigned Create Asset transaction. For more granular control, you may create your own * [[CreateAssetTX]] manually (with their corresponding [[TransferableInput]]s, [[TransferableOutput]]s). * * @param networkID The number representing NetworkID of the node * @param blockchainID The {@link https://github.com/feross/buffer|Buffer} representing the BlockchainID for the transaction * @param fromAddresses The addresses being used to send the funds from the UTXOs {@link https://github.com/feross/buffer|Buffer} * @param changeAddresses Optional. The addresses that can spend the change remaining from the spent UTXOs. * @param minterSets The minters and thresholds required to mint this nft asset * @param name String for the descriptive name of the nft asset * @param symbol String for the ticker symbol of the nft asset * @param fee Optional. The amount of fees to burn in its smallest denomination, represented as {@link https://github.com/indutny/bn.js/|BN} * @param feeAssetID Optional. The assetID of the fees being burned. * @param memo Optional contains arbitrary bytes, up to 256 bytes * @param asOf Optional. The timestamp to verify the transaction against as a {@link https://github.com/indutny/bn.js/|BN} * @param locktime Optional. The locktime field created in the resulting mint output * @param changethreshold Optional. The number of signatures required to spend the funds in the resultant change UTXO * * @returns An unsigned transaction created from the passed in parameters. * */ this.buildCreateNFTAssetTx = (networkID, blockchainID, fromAddresses, changeAddresses, minterSets, name, symbol, fee = undefined, feeAssetID = undefined, memo = undefined, asOf = (0, helperfunctions_1.UnixNow)(), locktime = undefined, changeThreshold = 1) => { const zero = new bn_js_1.default(0); let ins = []; let outs = []; if (this._feeCheck(fee, feeAssetID)) { const aad = new AssetAmountDestination([], 0, fromAddresses, changeAddresses, changeThreshold); aad.addAssetAmount(feeAssetID, zero, fee); const success = this.getMinimumSpendable(aad, asOf); if (typeof success === "undefined") { ins = aad.getInputs(); outs = aad.getAllOutputs(); } else { throw success; } } let initialState = new initialstates_1.InitialStates(); for (let i = 0; i < minterSets.length; i++) { let nftMintOutput = new outputs_1.NFTMintOutput(i, minterSets[`${i}`].getMinters(), locktime, minterSets[`${i}`].getThreshold()); initialState.addOutput(nftMintOutput, constants_1.AVMConstants.NFTFXID); } let denomination = 0; // NFTs are non-fungible let CAtx = new createassettx_1.CreateAssetTx(networkID, blockchainID, outs, ins, memo, name, symbol, denomination, initialState); return new tx_1.UnsignedTx(CAtx); }; /** * Creates an unsigned NFT mint transaction. For more granular control, you may create your own * [[OperationTx]] manually (with their corresponding [[TransferableInput]]s, [[TransferableOutput]]s, and [[TransferOperation]]s). * * @param networkID The number representing NetworkID of the node * @param blockchainID The {@link https://github.com/feross/buffer|Buffer} representing the BlockchainID for the transaction * @param owners An array of [[OutputOwners]] who will be given the NFTs. * @param fromAddresses The addresses being used to send the funds from the UTXOs * @param changeAddresses Optional. The addresses that can spend the change remaining from the spent UTXOs. * @param utxoids An array of strings for the NFTs being transferred * @param groupID Optional. The group this NFT is issued to. * @param payload Optional. Data for NFT Payload. * @param fee Optional. The amount of fees to burn in its smallest denomination, represented as {@link https://github.com/indutny/bn.js/|BN} * @param feeAssetID Optional. The assetID of the fees being burned. * @param memo Optional contains arbitrary bytes, up to 256 bytes * @param asOf Optional. The timestamp to verify the transaction against as a {@link https://github.com/indutny/bn.js/|BN} * @param changethreshold Optional. The number of signatures required to spend the funds in the resultant change UTXO * * @returns An unsigned transaction created from the passed in parameters. * */ this.buildCreateNFTMintTx = (networkID, blockchainID, owners, fromAddresses, changeAddresses, utxoids, groupID = 0, payload = undefined, fee = undefined, feeAssetID = undefined, memo = undefined, asOf = (0, helperfunctions_1.UnixNow)(), changeThreshold = 1) => { const zero = new bn_js_1.default(0); let ins = []; let outs = []; if (this._feeCheck(fee, feeAssetID)) { const aad = new AssetAmountDestination([], 0, fromAddresses, changeAddresses, changeThreshold); aad.addAssetAmount(feeAssetID, zero, fee); const success = this.getMinimumSpendable(aad, asOf); if (typeof success === "undefined") { ins = aad.getInputs(); outs = aad.getAllOutputs(); } else { throw success; } } let ops = []; let nftMintOperation = new ops_1.NFTMintOperation(groupID, payload, owners); for (let i = 0; i < utxoids.length; i++) { let utxo = this.getUTXO(utxoids[`${i}`]); let out = utxo.getOutput(); let spenders = out.getSpenders(fromAddresses, asOf); for (let j = 0; j < spenders.length; j++) { let idx; idx = out.getAddressIdx(spenders[`${j}`]); if (idx == -1) { /* istanbul ignore next */ throw new errors_1.AddressError("Error - UTXOSet.buildCreateNFTMintTx: no such address in output"); } nftMintOperation.addSignatureIdx(idx, spenders[`${j}`]); } let transferableOperation = new ops_1.TransferableOperation(utxo.getAssetID(), utxoids, nftMintOperation); ops.push(transferableOperation); } let operationTx = new operationtx_1.OperationTx(networkID, blockchainID, outs, ins, memo, ops); return new tx_1.UnsignedTx(operationTx); }; /** * Creates an unsigned NFT transfer transaction. For more granular control, you may create your own * [[OperationTx]] manually (with their corresponding [[TransferableInput]]s, [[TransferableOutput]]s, and [[TransferOperation]]s). * * @param networkID The number representing NetworkID of the node * @param blockchainID The {@link https://github.com/feross/buffer|Buffer} representing the BlockchainID for the transaction * @param toAddresses An array of {@link https://github.com/feross/buffer|Buffer}s which indicate who recieves the NFT * @param fromAddresses An array for {@link https://github.com/feross/buffer|Buffer} who owns the NFT * @param changeAddresses Optional. The addresses that can spend the change remaining from the spent UTXOs. * @param utxoids An array of strings for the NFTs being transferred * @param fee Optional. The amount of fees to burn in its smallest denomination, represented as {@link https://github.com/indutny/bn.js/|BN} * @param feeAssetID Optional. The assetID of the fees being burned. * @param memo Optional contains arbitrary bytes, up to 256 bytes * @param asOf Optional. The timestamp to verify the transaction against as a {@link https://github.com/indutny/bn.js/|BN} * @param locktime Optional. The locktime field created in the resulting outputs * @param toThreshold Optional. The number of signatures required to spend the funds in the resultant UTXO * @param changethreshold Optional. The number of signatures required to spend the funds in the resultant change UTXO * * @returns An unsigned transaction created from the passed in parameters. * */ this.buildNFTTransferTx = (networkID, blockchainID, toAddresses, fromAddresses, changeAddresses, utxoids, fee = undefined, feeAssetID = undefined, memo = undefined, asOf = (0, helperfunctions_1.UnixNow)(), locktime = new bn_js_1.default(0), toThreshold = 1, changeThreshold = 1) => { const zero = new bn_js_1.default(0); let ins = []; let outs = []; if (this._feeCheck(fee, feeAssetID)) { const aad = new AssetAmountDestination([], 0, fromAddresses, changeAddresses, changeThreshold); aad.addAssetAmount(feeAssetID, zero, fee); const success = this.getMinimumSpendable(aad, asOf); if (typeof success === "undefined") { ins = aad.getInputs(); outs = aad.getAllOutputs(); } else { throw success; } } const ops = []; for (let i = 0; i < utxoids.length; i++) { const utxo = this.getUTXO(utxoids[`${i}`]); const out = utxo.getOutput(); const spenders = out.getSpenders(fromAddresses, asOf); const outbound = new outputs_1.NFTTransferOutput(out.getGroupID(), out.getPayload(), toAddresses, locktime, toThreshold); const op = new ops_1.NFTTransferOperation(outbound); for (let j = 0; j < spenders.length; j++) { const idx = out.getAddressIdx(spenders[`${j}`]); if (idx === -1) { /* istanbul ignore next */ throw new errors_1.AddressError("Error - UTXOSet.buildNFTTransferTx: " + `no such address in output: ${spenders[`${j}`]}`); } op.addSignatureIdx(idx, spenders[`${j}`]); } const xferop = new ops_1.TransferableOperation(utxo.getAssetID(), [utxoids[`${i}`]], op); ops.push(xferop); } const OpTx = new operationtx_1.OperationTx(networkID, blockchainID, outs, ins, memo, ops); return new tx_1.UnsignedTx(OpTx); }; /** * Creates an unsigned ImportTx transaction. * * @param networkID The number representing NetworkID of the node * @param blockchainID The {@link https://github.com/feross/buffer|Buffer} representing the BlockchainID for the transaction * @param toAddresses The addresses to send the funds * @param fromAddresses The addresses being used to send the funds from the UTXOs {@link https://github.com/feross/buffer|Buffer} * @param changeAddresses Optional. The addresses that can spend the change remaining from the spent UTXOs. * @param importIns An array of [[TransferableInput]]s being imported * @param sourceChain A {@link https://github.com/feross/buffer|Buffer} for the chainid where the imports are coming from. * @param fee Optional. The amount of fees to burn in its smallest denomination, represented as {@link https://github.com/indutny/bn.js/|BN}. Fee will come from the inputs first, if they can. * @param feeAssetID Optional. The assetID of the fees being burned. * @param memo Optional contains arbitrary bytes, up to 256 bytes * @param asOf Optional. The timestamp to verify the transaction against as a {@link https://github.com/indutny/bn.js/|BN} * @param locktime Optional. The locktime field created in the resulting outputs * @param toThreshold Optional. The number of signatures required to spend the funds in the resultant UTXO * @param changethreshold Optional. The number of signatures required to spend the funds in the resultant change UTXO * * @returns An unsigned transaction created from the passed in parameters. * */ this.buildImportTx = (networkID, blockchainID, toAddresses, fromAddresses, changeAddresses, atomics, sourceChain = undefined, fee = undefined, feeAssetID = undefined, memo = undefined, asOf = (0, helperfunctions_1.UnixNow)(), locktime = new bn_js_1.default(0), toThreshold = 1, changeThreshold = 1) => { const zero = new bn_js_1.default(0); let ins = []; let outs = []; if (typeof fee === "undefined") { fee = zero.clone(); } const importIns = []; let feepaid = new bn_js_1.default(0); let feeAssetStr = feeAssetID.toString("hex"); for (let i = 0; i < atomics.length; i++) { const utxo = atomics[`${i}`]; const assetID = utxo.getAssetID(); const output = utxo.getOutput(); let amt = output.getAmount().clone(); let infeeamount = amt.clone(); let assetStr = assetID.toString("hex"); if (typeof feeAssetID !== "undefined" && fee.gt(zero) && feepaid.lt(fee) && assetStr === feeAssetStr) { feepaid = feepaid.add(infeeamount); if (feepaid.gt(fee)) { infeeamount = feepaid.sub(fee); feepaid = fee.clone(); } else { infeeamount = zero.clone(); } } const txid = utxo.getTxID(); const outputidx = utxo.getOutputIdx(); const input = new inputs_1.SECPTransferInput(amt); const xferin = new inputs_1.TransferableInput(txid, outputidx, assetID, input); const from = output.getAddresses(); const spenders = output.getSpenders(from, asOf); for (let j = 0; j < spenders.length; j++) { const idx = output.getAddressIdx(spenders[`${j}`]); if (idx === -1) { /* istanbul ignore next */ throw new errors_1.AddressError("Error - UTXOSet.buildImportTx: no such " + `address in output: ${spenders[`${j}`]}`); } xferin.getInput().addSignatureIdx(idx, spenders[`${j}`]); } importIns.push(xferin); //add extra outputs for each amount (calculated from the imported inputs), minus fees if (infeeamount.gt(zero)) { const spendout = (0, outputs_1.SelectOutputClass)(output.getOutputID(), infeeamount, toAddresses, locktime, toThreshold); const xferout = new outputs_1.TransferableOutput(assetID, spendout); outs.push(xferout); } } // get remaining fees from the provided addresses let feeRemaining = fee.sub(feepaid); if (feeRemaining.gt(zero) && this._feeCheck(feeRemaining, feeAssetID)) { const aad = new AssetAmountDestination(toAddresses, toThreshold, fromAddresses, changeAddresses, changeThreshold); aad.addAssetAmount(feeAssetID, zero, feeRemaining); const success = this.getMinimumSpendable(aad, asOf, locktime); if (typeof success === "undefined") { ins = aad.getInputs(); outs = aad.getAllOutputs(); } else { throw success; } } const importTx = new importtx_1.ImportTx(networkID, blockchainID, outs, ins, memo, sourceChain, importIns); return new tx_1.UnsignedTx(importTx); }; /** * Creates an unsigned ExportTx transaction. * * @param networkID The number representing NetworkID of the node * @param blockchainID The {@link https://github.com/feross/buffer|Buffer} representing the BlockchainID for the transaction * @param amount The amount being exported as a {@link https://github.com/indutny/bn.js/|BN} * @param avaxAssetID {@link https://github.com/feross/buffer|Buffer} of the asset ID for AVAX * @param toAddresses An array of addresses as {@link https://github.com/feross/buffer|Buffer} who recieves the AVAX * @param fromAddresses An array of addresses as {@link https://github.com/feross/buffer|Buffer} who owns the AVAX * @param changeAddresses Optional. The addresses that can spend the change remaining from the spent UTXOs. * @param fee Optional. The amount of fees to burn in its smallest denomination, represented as {@link https://github.com/indutny/bn.js/|BN} * @param destinationChain Optional. A {@link https://github.com/feross/buffer|Buffer} for the chainid where to send the asset. * @param feeAssetID Optional. The assetID of the fees being burned. * @param memo Optional contains arbitrary bytes, up to 256 bytes * @param asOf Optional. The timestamp to verify the transaction against as a {@link https://github.com/indutny/bn.js/|BN} * @param locktime Optional. The locktime field created in the resulting outputs * @param toThreshold Optional. The number of signatures required to spend the funds in the resultant UTXO * @param changethreshold Optional. The number of signatures required to spend the funds in the resultant change UTXO * * @returns An unsigned transaction created from the passed in parameters. * */ this.buildExportTx = (networkID, blockchainID, amount, assetID, toAddresses, fromAddresses, changeAddresses = undefined, destinationChain = undefined, fee = undefined, feeAssetID = undefined, memo = undefined, asOf = (0, helperfunctions_1.UnixNow)(), locktime = new bn_js_1.default(0), toThreshold = 1, changeThreshold = 1) => { let ins = []; let outs = []; let exportouts = []; if (typeof changeAddresses === "undefined") { changeAddresses = toAddresses; } const zero = new bn_js_1.default(0); if (amount.eq(zero)) { return undefined; } if (typeof feeAssetID === "undefined") { feeAssetID = assetID; } if (typeof destinationChain === "undefined") { destinationChain = bintools.cb58Decode(constants_2.DefaultPlatformChainID); } const aad = new AssetAmountDestination(toAddresses, toThreshold, fromAddresses, changeAddresses, changeThreshold); if (assetID.toString("hex") === feeAssetID.toString("hex")) { aad.addAssetAmount(assetID, amount, fee); } else { aad.addAssetAmount(assetID, amount, zero); if (this._feeCheck(fee, feeAssetID)) { aad.addAssetAmount(feeAssetID, zero, fee); } } const success = this.getMinimumSpendable(aad, asOf, locktime); if (typeof success === "undefined") { ins = aad.getInputs(); outs = aad.getChangeOutputs(); exportouts = aad.getOutputs(); } else { throw success; } const exportTx = new exporttx_1.ExportTx(networkID, blockchainID, outs, ins, memo, destinationChain, exportouts); return new tx_1.UnsignedTx(exportTx); }; } //serialize is inherited deserialize(fields, encoding = "hex") { super.deserialize(fields, encoding); let utxos = {}; for (let utxoid in fields["utxos"]) { let utxoidCleaned = serialization.decoder(utxoid, encoding, "base58", "base58"); utxos[`${utxoidCleaned}`] = new UTXO(); utxos[`${utxoidCleaned}`].deserialize(fields["utxos"][`${utxoid}`], encoding); } let addressUTXOs = {}; for (let address in fields["addressUTXOs"]) { let addressCleaned = serialization.decoder(address, encoding, "cb58", "hex"); let utxobalance = {}; for (let utxoid in fields["addressUTXOs"][`${address}`]) { let utxoidCleaned = serialization.decoder(utxoid, encoding, "base58", "base58"); utxobalance[`${utxoidCleaned}`] = serialization.decoder(fields["addressUTXOs"][`${address}`][`${utxoid}`], encoding, "decimalString", "BN"); } addressUTXOs[`${addressCleaned}`] = utxobalance; } this.utxos = utxos; this.addressUTXOs = addressUTXOs; } parseUTXO(utxo) { const utxovar = new UTXO(); // force a copy if (typeof utxo === "string") { utxovar.fromBuffer(bintools.cb58Decode(utxo)); } else if (utxo instanceof UTXO) { utxovar.fromBuffer(utxo.toBuffer()); // forces a copy } else { /* istanbul ignore next */ throw new errors_1.UTXOError("Error - UTXO.parseUTXO: utxo parameter is not a UTXO or string"); } return utxovar; } create() { return new UTXOSet(); } clone() { const newset = this.create(); const allUTXOs = this.getAllUTXOs(); newset.addArray(allUTXOs); return newset; } _feeCheck(fee, feeAssetID) { return (typeof fee !== "undefined" && typeof feeAssetID !== "undefined" && fee.gt(new bn_js_1.default(0)) && feeAssetID instanceof buffer_1.Buffer); } } exports.UTXOSet = UTXOSet; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXR4b3MuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvYXBpcy9hdm0vdXR4b3MudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUE7OztHQUdHO0FBQ0gsb0NBQWdDO0FBQ2hDLG9FQUEyQztBQUMzQyxrREFBc0I7QUFDdEIsdUNBUWtCO0FBQ2xCLDJDQUEwQztBQUMxQyw2QkFBaUM7QUFDakMscUNBQStEO0FBQy9ELCtCQUtjO0FBRWQsaUVBQXFEO0FBQ3JELG1EQUErQztBQUUvQyw4Q0FBa0U7QUFDbEUsbURBQStDO0FBQy9DLCtDQUEyQztBQUMzQyxxQ0FBaUM7QUFDakMseUNBQXFDO0FBQ3JDLHlDQUFxQztBQUNyQyxxREFBOEQ7QUFDOUQsMERBR2lDO0FBQ2pDLDZEQUE2RTtBQUM3RSwrQ0FNMkI7QUFFM0I7O0dBRUc7QUFDSCxNQUFNLFFBQVEsR0FBYSxrQkFBUSxDQUFDLFdBQVcsRUFBRSxDQUFBO0FBQ2pELE1BQU0sYUFBYSxHQUFrQiw2QkFBYSxDQUFDLFdBQVcsRUFBRSxDQUFBO0FBRWhFOztHQUVHO0FBQ0gsTUFBYSxJQUFLLFNBQVEsb0JBQVk7SUFBdEM7O1FBQ1ksY0FBUyxHQUFHLE1BQU0sQ0FBQTtRQUNsQixZQUFPLEdBQUcsU0FBUyxDQUFBO0lBb0UvQixDQUFDO0lBbEVDLHdCQUF3QjtJQUV4QixXQUFXLENBQUMsTUFBYyxFQUFFLFdBQStCLEtBQUs7UUFDOUQsS0FBSyxDQUFDLFdBQVcsQ0FBQyxNQUFNLEVBQUUsUUFBUSxDQUFDLENBQUE7UUFDbkMsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFBLDJCQUFpQixFQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFBO1FBQzVELElBQUksQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsRUFBRSxRQUFRLENBQUMsQ0FBQTtJQUNyRCxDQUFDO0lBRUQsVUFBVSxDQUFDLEtBQWEsRUFBRSxTQUFpQixDQUFDO1FBQzFDLElBQUksQ0FBQyxPQUFPLEdBQUcsUUFBUSxDQUFDLFFBQVEsQ0FBQyxLQUFLLEVBQUUsTUFBTSxFQUFFLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQTtRQUMzRCxNQUFNLElBQUksQ0FBQyxDQUFBO1FBQ1gsSUFBSSxDQUFDLElBQUksR0FBRyxRQUFRLENBQUMsUUFBUSxDQUFDLEtBQUssRUFBRSxNQUFNLEVBQUUsTUFBTSxHQUFHLEVBQUUsQ0FBQyxDQUFBO1FBQ3pELE1BQU0sSUFBSSxFQUFFLENBQUE7UUFDWixJQUFJLENBQUMsU0FBUyxHQUFHLFFBQVEsQ0FBQyxRQUFRLENBQUMsS0FBSyxFQUFFLE1BQU0sRUFBRSxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUE7UUFDN0QsTUFBTSxJQUFJLENBQUMsQ0FBQTtRQUNYLElBQUksQ0FBQyxPQUFPLEdBQUcsUUFBUSxDQUFDLFFBQVEsQ0FBQyxLQUFLLEVBQUUsTUFBTSxFQUFFLE1BQU0sR0FBRyxFQUFFLENBQUMsQ0FBQTtRQUM1RCxNQUFNLElBQUksRUFBRSxDQUFBO1FBQ1osTUFBTSxRQUFRLEdBQVcsUUFBUTthQUM5QixRQUFRLENBQUMsS0FBSyxFQUFFLE1BQU0sRUFBRSxNQUFNLEdBQUcsQ0FBQyxDQUFDO2FBQ25DLFlBQVksQ0FBQyxDQUFDLENBQUMsQ0FBQTtRQUNsQixNQUFNLElBQUksQ0FBQyxDQUFBO1FBQ1gsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFBLDJCQUFpQixFQUFDLFFBQVEsQ0FBQyxDQUFBO1FBQ3pDLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsS0FBSyxFQUFFLE1BQU0sQ0FBQyxDQUFBO0lBQzlDLENBQUM7SUFFRDs7Ozs7Ozs7O09BU0c7SUFDSCxVQUFVLENBQUMsVUFBa0I7UUFDM0IsMEJBQTBCO1FBQzFCLE9BQU8sSUFBSSxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsVUFBVSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUE7SUFDekQsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsUUFBUTtRQUNOLDBCQUEwQjtRQUMxQixPQUFPLFFBQVEsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUE7SUFDN0MsQ0FBQztJQUVELEtBQUs7UUFDSCxNQUFNLElBQUksR0FBUyxJQUFJLElBQUksRUFBRSxDQUFBO1FBQzdCLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUE7UUFDaEMsT0FBTyxJQUFZLENBQUE7SUFDckIsQ0FBQztJQUVELE1BQU0sQ0FDSixVQUFrQix3QkFBWSxDQUFDLFdBQVcsRUFDMUMsT0FBZSxTQUFTLEVBQ3hCLFlBQTZCLFNBQVMsRUFDdEMsVUFBa0IsU0FBUyxFQUMzQixTQUFpQixTQUFTO1FBRTFCLE9BQU8sSUFBSSxJQUFJLENBQUMsT0FBTyxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFFLE1BQU0sQ0FBUyxDQUFBO0lBQ3BFLENBQUM7Q0FDRjtBQXRFRCxvQkFzRUM7QUFFRCxNQUFhLHNCQUF1QixTQUFRLDRDQUczQztDQUFHO0FBSEosd0RBR0k7QUFFSjs7R0FFRztBQUNILE1BQWEsT0FBUSxTQUFRLHVCQUFxQjtJQUFsRDs7UUFDWSxjQUFTLEdBQUcsU0FBUyxDQUFBO1FBQ3JCLFlBQU8sR0FBRyxTQUFTLENBQUE7UUFxRjdCLHdCQUFtQixHQUFHLENBQ3BCLEdBQTJCLEVBQzNCLE9BQVcsSUFBQSx5QkFBTyxHQUFFLEVBQ3BCLFdBQWUsSUFBSSxlQUFFLENBQUMsQ0FBQyxDQUFDLEVBQ3hCLFlBQW9CLENBQUMsRUFDZCxFQUFFO1lBQ1QsTUFBTSxTQUFTLEdBQVcsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFBO1lBQzVDLE1BQU0sTUFBTSxHQUFXLEVBQUUsQ0FBQTtZQUN6QixLQUFLLElBQUksQ0FBQyxHQUFXLENBQUMsRUFBRSxDQUFDLEdBQUcsU0FBUyxDQUFDLE1BQU0sSUFBSSxDQUFDLEdBQUcsQ0FBQyxXQUFXLEVBQUUsRUFBRSxDQUFDLEVBQUUsRUFBRTtnQkFDdkUsTUFBTSxDQUFDLEdBQVMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQTtnQkFDakMsTUFBTSxRQUFRLEdBQVcsQ0FBQyxDQUFDLFVBQVUsRUFBRSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQTtnQkFDdkQsTUFBTSxhQUFhLEdBQWEsR0FBRyxDQUFDLFVBQVUsRUFBRSxDQUFBO2dCQUNoRCxJQUNFLENBQUMsQ0FBQyxTQUFTLEVBQUUsWUFBWSxzQkFBWTtvQkFDckMsR0FBRyxDQUFDLFdBQVcsQ0FBQyxRQUFRLENBQUM7b0JBQ3pCLENBQUMsQ0FBQyxTQUFTLEVBQUUsQ0FBQyxjQUFjLENBQUMsYUFBYSxFQUFFLElBQUksQ0FBQyxFQUNqRDtvQkFDQSxNQUFNLEVBQUUsR0FBZ0IsR0FBRyxDQUFDLGNBQWMsQ0FBQyxRQUFRLENBQUMsQ0FBQTtvQkFDcEQsSUFBSSxDQUFDLEVBQUUsQ0FBQyxVQUFVLEVBQUUsRUFBRTt3QkFDcEIsTUFBTSxJQUFJLEdBQWlCLENBQUMsQ0FBQyxTQUFTLEVBQWtCLENBQUE7d0JBQ3hELE1BQU0sQ0FBQyxHQUFHLFFBQVEsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFBO3dCQUMxQyxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUE7d0JBQy9CLEVBQUUsQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLENBQUE7d0JBQ3RCLE1BQU0sSUFBSSxHQUFXLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQTt3QkFDaEMsTUFBTSxTQUFTLEdBQVcsQ0FBQyxDQUFDLFlBQVksRUFBRSxDQUFBO3dCQUMxQyxNQUFNLEtBQUssR0FBc0IsSUFBSSwwQkFBaUIsQ0FBQyxNQUFNLENBQUMsQ0FBQTt3QkFDOUQsTUFBTSxNQUFNLEdBQXNCLElBQUksMEJBQWlCLENBQ3JELElBQUksRUFDSixTQUFTLEVBQ1QsQ0FBQyxDQUFDLFVBQVUsRUFBRSxFQUNkLEtBQUssQ0FDTixDQUFBO3dCQUNELE1BQU0sUUFBUSxHQUFhLElBQUksQ0FBQyxXQUFXLENBQUMsYUFBYSxFQUFFLElBQUksQ0FBQyxDQUFBO3dCQUNoRSxLQUFLLElBQUksQ0FBQyxHQUFXLENBQUMsRUFBRSxDQUFDLEdBQUcsUUFBUSxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRTs0QkFDaEQsTUFBTSxHQUFHLEdBQVcsSUFBSSxDQUFDLGFBQWEsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUE7NEJBQ3hELElBQUksR0FBRyxLQUFLLENBQUMsQ0FBQyxFQUFFO2dDQUNkLDBCQUEwQjtnQ0FDMUIsTUFBTSxJQUFJLHFCQUFZLENBQ3BCLCtDQUErQztvQ0FDN0Msc0JBQXNCLFFBQVEsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FDM0MsQ0FBQTs2QkFDRjs0QkFDRCxNQUFNLENBQUMsUUFBUSxFQUFFLENBQUMsZUFBZSxDQUFDLEdBQUcsRUFBRSxRQUFRLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUE7eUJBQ3pEO3dCQUNELEdBQUcsQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUE7cUJBQ3JCO3lCQUFNLElBQ0wsR0FBRyxDQUFDLFdBQVcsQ0FBQyxRQUFRLENBQUM7d0JBQ3pCLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUyxFQUFFLFlBQVksc0JBQVksQ0FBQyxFQUN4Qzt3QkFDQTs7Ozs7OzJCQU1HO3dCQUNIO3FGQUM2RDt3QkFDN0QsU0FBUTtxQkFDVDtpQkFDRjthQUNGO1lBQ0QsSUFBSSxDQUFDLEdBQUcsQ0FBQyxXQUFXLEVBQUUsRUFBRTtnQkFDdEIsT0FBTyxJQUFJLCtCQUFzQixDQUMvQixvREFBb0Q7b0JBQ2xELGlDQUFpQyxDQUNwQyxDQUFBO2FBQ0Y7WUFDRCxNQUFNLE9BQU8sR0FBa0IsR0FBRyxDQUFDLFVBQVUsRUFBRSxDQUFBO1lBQy9DLE1BQU0sSUFBSSxHQUFPLElBQUksZUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFBO1lBQzFCLEtBQUssSUFBSSxDQUFDLEdBQVcsQ0FBQyxFQUFFLENBQUMsR0FBRyxPQUFPLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFO2dCQUMvQyxNQUFNLFFBQVEsR0FBVyxPQUFPLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLGdCQUFnQixFQUFFLENBQUE7Z0JBQzNELE1BQU0sTUFBTSxHQUFPLE9BQU8sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUMsU0FBUyxFQUFFLENBQUE7Z0JBQzlDLElBQUksTUFBTSxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsRUFBRTtvQkFDbkIsTUFBTSxRQUFRLEdBQWlCLElBQUEsMkJBQWlCLEVBQzlDLE1BQU0sQ0FBQyxHQUFHLFFBQVEsRUFBRSxDQUFDLEVBQ3JCLE1BQU0sRUFDTixHQUFHLENBQUMsZUFBZSxFQUFFLEVBQ3JCLFFBQVEsRUFDUixTQUFTLENBQ00sQ0FBQTtvQkFDakIsTUFBTSxPQUFPLEdBQXVCLElBQUksNEJBQWtCLENBQ3hELE9BQU8sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUMsVUFBVSxFQUFFLEVBQzVCLFFBQVEsQ0FDVCxDQUFBO29CQUNELEdBQUcsQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLENBQUE7aUJBQ3ZCO2dCQUNELE1BQU0sTUFBTSxHQUFPLE9BQU8sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUMsU0FBUyxFQUFFLENBQUE7Z0JBQzlDLElBQUksTUFBTSxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsRUFBRTtvQkFDbkIsTUFBTSxTQUFTLEdBQWlCLElBQUEsMkJBQWlCLEVBQy9DLE1BQU0sQ0FBQyxHQUFHLFFBQVEsRUFBRSxDQUFDLEVBQ3JCLE1BQU0sRUFDTixHQUFHLENBQUMsa0JBQWtCLEVBQUUsQ0FDVCxDQUFBO29CQUNqQixNQUFNLFVBQVUsR0FBdUIsSUFBSSw0QkFBa0IsQ0FDM0QsT0FBTyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxVQUFVLEVBQUUsRUFDNUIsU0FBUyxDQUNWLENBQUE7b0JBQ0QsR0FBRyxDQUFDLFNBQVMsQ0FBQyxVQUFVLENBQUMsQ0FBQTtpQkFDMUI7YUFDRjtZQUNELE9BQU8sU0FBUyxDQUFBO1FBQ2xCLENBQUMsQ0FBQTtRQUVEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7V0FxQkc7UUFDSCxnQkFBVyxHQUFHLENBQ1osU0FBaUIsRUFDakIsWUFBb0IsRUFDcEIsTUFBVSxFQUNWLE9BQWUsRUFDZixXQUFxQixFQUNyQixhQUF1QixFQUN2QixrQkFBNEIsU0FBUyxFQUNyQyxNQUFVLFNBQVMsRUFDbkIsYUFBcUIsU0FBUyxFQUM5QixPQUFlLFNBQVMsRUFDeEIsT0FBVyxJQUFBLHlCQUFPLEdBQUUsRUFDcEIsV0FBZSxJQUFJLGVBQUUsQ0FBQyxDQUFDLENBQUMsRUFDeEIsY0FBc0IsQ0FBQyxFQUN2QixrQkFBMEIsQ0FBQyxFQUNmLEVBQUU7WUFDZCxJQUFJLFdBQVcsR0FBRyxXQUFXLENBQUMsTUFBTSxFQUFFO2dCQUNwQywwQkFBMEI7Z0JBQzFCLE1BQU0sSUFBSSx1QkFBYyxDQUN0Qiw0RUFBNEUsQ0FDN0UsQ0FBQTthQUNGO1lBRUQsSU