@kubectl/caminojs
Version:
Camino Platform JS Library
625 lines • 87.6 kB
JavaScript
"use strict";
/**
* @packageDocumentation
* @module API-EVM
*/
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.EVMAPI = void 0;
const buffer_1 = require("buffer/");
const bn_js_1 = __importDefault(require("bn.js"));
const jrpcapi_1 = require("../../common/jrpcapi");
const bintools_1 = __importDefault(require("../../utils/bintools"));
const utxos_1 = require("./utxos");
const keychain_1 = require("./keychain");
const tx_1 = require("./tx");
const constants_1 = require("./constants");
const inputs_1 = require("./inputs");
const outputs_1 = require("./outputs");
const exporttx_1 = require("./exporttx");
const errors_1 = require("../../utils/errors");
const utils_1 = require("../../utils");
/**
* @ignore
*/
const bintools = bintools_1.default.getInstance();
const serialization = utils_1.Serialization.getInstance();
/**
* Class for interacting with a node's EVMAPI
*
* @category RPCAPIs
*
* @remarks This extends the [[JRPCAPI]] class. This class should not be directly called. Instead, use the [[Avalanche.addAPI]] function to register this interface with Avalanche.
*/
class EVMAPI extends jrpcapi_1.JRPCAPI {
/**
* This class should not be instantiated directly.
* Instead use the [[Avalanche.addAPI]] method.
*
* @param core A reference to the Avalanche class
* @param baseURL Defaults to the string "/ext/bc/C/avax" as the path to blockchain's baseURL
* @param blockchainID The Blockchain's ID. Defaults to an empty string: ""
*/
constructor(core, baseURL = "/ext/bc/C/avax", blockchainID = "") {
super(core, baseURL);
/**
* @ignore
*/
this.keychain = new keychain_1.KeyChain("", "");
this.blockchainID = "";
this.blockchainAlias = undefined;
this.AVAXAssetID = undefined;
this.txFee = undefined;
/**
* Gets the alias for the blockchainID if it exists, otherwise returns `undefined`.
*
* @returns The alias for the blockchainID
*/
this.getBlockchainAlias = () => {
if (typeof this.blockchainAlias === "undefined") {
this.blockchainAlias = this.core.getNetwork().C.alias;
}
return this.blockchainAlias;
};
/**
* Gets the blockchainID and returns it.
*
* @returns The blockchainID
*/
this.getBlockchainID = () => this.blockchainID;
/**
* Takes an address string and returns its {@link https://github.com/feross/buffer|Buffer} representation if valid.
*
* @returns A {@link https://github.com/feross/buffer|Buffer} for the address if valid, undefined if not valid.
*/
this.parseAddress = (addr) => {
const alias = this.getBlockchainAlias();
const blockchainID = this.getBlockchainID();
return bintools.parseAddress(addr, blockchainID, alias, constants_1.EVMConstants.ADDRESSLENGTH);
};
this.addressFromBuffer = (address) => {
const chainID = this.getBlockchainAlias()
? this.getBlockchainAlias()
: this.getBlockchainID();
const type = "bech32";
return serialization.bufferToType(address, type, this.core.getHRP(), chainID);
};
/**
* Retrieves an assets name and symbol.
*
* @param assetID Either a {@link https://github.com/feross/buffer|Buffer} or an b58 serialized string for the AssetID or its alias.
*
* @returns Returns a Promise Asset with keys "name", "symbol", "assetID" and "denomination".
*/
this.getAssetDescription = (assetID) => __awaiter(this, void 0, void 0, function* () {
let asset;
if (typeof assetID !== "string") {
asset = bintools.cb58Encode(assetID);
}
else {
asset = assetID;
}
const params = {
assetID: asset
};
const tmpBaseURL = this.getBaseURL();
// set base url to get asset description
this.setBaseURL("/ext/bc/X");
const response = yield this.callMethod("avm.getAssetDescription", params);
// set base url back what it originally was
this.setBaseURL(tmpBaseURL);
return {
name: response.data.result.name,
symbol: response.data.result.symbol,
assetID: bintools.cb58Decode(response.data.result.assetID),
denomination: parseInt(response.data.result.denomination, 10)
};
});
/**
* Fetches the AVAX AssetID and returns it in a Promise.
*
* @param refresh This function caches the response. Refresh = true will bust the cache.
*
* @returns The the provided string representing the AVAX AssetID
*/
this.getAVAXAssetID = (refresh = false) => __awaiter(this, void 0, void 0, function* () {
if (typeof this.AVAXAssetID === "undefined" || refresh) {
const asset = yield this.getAssetDescription(this.core.getPrimaryAssetAlias());
this.AVAXAssetID = asset.assetID;
}
return this.AVAXAssetID;
});
/**
* Overrides the defaults and sets the cache to a specific AVAX AssetID
*
* @param avaxAssetID A cb58 string or Buffer representing the AVAX AssetID
*
* @returns The the provided string representing the AVAX AssetID
*/
this.setAVAXAssetID = (avaxAssetID) => {
if (typeof avaxAssetID === "string") {
avaxAssetID = bintools.cb58Decode(avaxAssetID);
}
this.AVAXAssetID = avaxAssetID;
};
/**
* Gets the default tx fee for this chain.
*
* @returns The default tx fee as a {@link https://github.com/indutny/bn.js/|BN}
*/
this.getDefaultTxFee = () => {
return new bn_js_1.default(this.core.getNetwork().C.txFee);
};
/**
* returns the amount of [assetID] for the given address in the state of the given block number.
* "latest", "pending", and "accepted" meta block numbers are also allowed.
*
* @param hexAddress The hex representation of the address
* @param blockHeight The block height
* @param assetID The asset ID
*
* @returns Returns a Promise object containing the balance
*/
this.getAssetBalance = (hexAddress, blockHeight, assetID) => __awaiter(this, void 0, void 0, function* () {
const params = [hexAddress, blockHeight, assetID];
const method = "eth_getAssetBalance";
const path = "ext/bc/C/rpc";
const response = yield this.callMethod(method, params, path);
return response.data;
});
/**
* Returns the status of a provided atomic transaction ID by calling the node's `getAtomicTxStatus` method.
*
* @param txID The string representation of the transaction ID
*
* @returns Returns a Promise string containing the status retrieved from the node
*/
this.getAtomicTxStatus = (txID) => __awaiter(this, void 0, void 0, function* () {
const params = {
txID
};
const response = yield this.callMethod("avax.getAtomicTxStatus", params);
return response.data.result.status
? response.data.result.status
: response.data.result;
});
/**
* Returns the transaction data of a provided transaction ID by calling the node's `getAtomicTx` method.
*
* @param txID The string representation of the transaction ID
*
* @returns Returns a Promise string containing the bytes retrieved from the node
*/
this.getAtomicTx = (txID) => __awaiter(this, void 0, void 0, function* () {
const params = {
txID
};
const response = yield this.callMethod("avax.getAtomicTx", params);
return response.data.result.tx;
});
/**
* Gets the tx fee for this chain.
*
* @returns The tx fee as a {@link https://github.com/indutny/bn.js/|BN}
*/
this.getTxFee = () => {
if (typeof this.txFee === "undefined") {
this.txFee = this.getDefaultTxFee();
}
return this.txFee;
};
/**
* Send ANT (Avalanche Native Token) assets including AVAX from the C-Chain to an account on the X-Chain.
*
* After calling this method, you must call the X-Chain’s import method to complete the transfer.
*
* @param username The Keystore user that controls the X-Chain account specified in `to`
* @param password The password of the Keystore user
* @param to The account on the X-Chain to send the AVAX to.
* @param amount Amount of asset to export as a {@link https://github.com/indutny/bn.js/|BN}
* @param assetID The asset id which is being sent
*
* @returns String representing the transaction id
*/
this.export = (username, password, to, amount, assetID) => __awaiter(this, void 0, void 0, function* () {
const params = {
to,
amount: amount.toString(10),
username,
password,
assetID
};
const response = yield this.callMethod("avax.export", params);
return response.data.result.txID
? response.data.result.txID
: response.data.result;
});
/**
* Send AVAX from the C-Chain to an account on the X-Chain.
*
* After calling this method, you must call the X-Chain’s importAVAX method to complete the transfer.
*
* @param username The Keystore user that controls the X-Chain account specified in `to`
* @param password The password of the Keystore user
* @param to The account on the X-Chain to send the AVAX to.
* @param amount Amount of AVAX to export as a {@link https://github.com/indutny/bn.js/|BN}
*
* @returns String representing the transaction id
*/
this.exportAVAX = (username, password, to, amount) => __awaiter(this, void 0, void 0, function* () {
const params = {
to,
amount: amount.toString(10),
username,
password
};
const response = yield this.callMethod("avax.exportAVAX", params);
return response.data.result.txID
? response.data.result.txID
: response.data.result;
});
/**
* Retrieves the UTXOs related to the addresses provided from the node's `getUTXOs` method.
*
* @param addresses An array of addresses as cb58 strings or addresses as {@link https://github.com/feross/buffer|Buffer}s
* @param sourceChain A string for the chain to look for the UTXO's. Default is to use this chain, but if exported UTXOs exist
* from other chains, this can used to pull them instead.
* @param limit Optional. Returns at most [limit] addresses. If [limit] == 0 or > [maxUTXOsToFetch], fetches up to [maxUTXOsToFetch].
* @param startIndex Optional. [StartIndex] defines where to start fetching UTXOs (for pagination.)
* UTXOs fetched are from addresses equal to or greater than [StartIndex.Address]
* For address [StartIndex.Address], only UTXOs with IDs greater than [StartIndex.Utxo] will be returned.
*/
this.getUTXOs = (addresses, sourceChain = undefined, limit = 0, startIndex = undefined, encoding = "hex") => __awaiter(this, void 0, void 0, function* () {
if (typeof addresses === "string") {
addresses = [addresses];
}
const params = {
addresses: addresses,
limit,
encoding
};
if (typeof startIndex !== "undefined" && startIndex) {
params.startIndex = startIndex;
}
if (typeof sourceChain !== "undefined") {
params.sourceChain = sourceChain;
}
const response = yield this.callMethod("avax.getUTXOs", params);
const utxos = new utxos_1.UTXOSet();
const data = response.data.result.utxos;
if (data.length > 0 && data[0].substring(0, 2) === "0x") {
const cb58Strs = [];
data.forEach((str) => {
cb58Strs.push(bintools.cb58Encode(new buffer_1.Buffer(str.slice(2), "hex")));
});
utxos.addArray(cb58Strs, false);
}
else {
utxos.addArray(data, false);
}
response.data.result.utxos = utxos;
return response.data.result;
});
/**
* Send ANT (Avalanche Native Token) assets including AVAX from an account on the X-Chain to an address on the C-Chain. This transaction
* must be signed with the key of the account that the asset is sent from and which pays
* the transaction fee.
*
* @param username The Keystore user that controls the account specified in `to`
* @param password The password of the Keystore user
* @param to The address of the account the asset is sent to.
* @param sourceChain The chainID where the funds are coming from. Ex: "X"
*
* @returns Promise for a string for the transaction, which should be sent to the network
* by calling issueTx.
*/
this.import = (username, password, to, sourceChain) => __awaiter(this, void 0, void 0, function* () {
const params = {
to,
sourceChain,
username,
password
};
const response = yield this.callMethod("avax.import", params);
return response.data.result.txID
? response.data.result.txID
: response.data.result;
});
/**
* Send AVAX from an account on the X-Chain to an address on the C-Chain. This transaction
* must be signed with the key of the account that the AVAX is sent from and which pays
* the transaction fee.
*
* @param username The Keystore user that controls the account specified in `to`
* @param password The password of the Keystore user
* @param to The address of the account the AVAX is sent to. This must be the same as the to
* argument in the corresponding call to the X-Chain’s exportAVAX
* @param sourceChain The chainID where the funds are coming from.
*
* @returns Promise for a string for the transaction, which should be sent to the network
* by calling issueTx.
*/
this.importAVAX = (username, password, to, sourceChain) => __awaiter(this, void 0, void 0, function* () {
const params = {
to,
sourceChain,
username,
password
};
const response = yield this.callMethod("avax.importAVAX", params);
return response.data.result.txID
? response.data.result.txID
: response.data.result;
});
/**
* Give a user control over an address by providing the private key that controls the address.
*
* @param username The name of the user to store the private key
* @param password The password that unlocks the user
* @param privateKey A string representing the private key in the vm"s format
*
* @returns The address for the imported private key.
*/
this.importKey = (username, password, privateKey) => __awaiter(this, void 0, void 0, function* () {
const params = {
username,
password,
privateKey
};
const response = yield this.callMethod("avax.importKey", params);
return response.data.result.address
? response.data.result.address
: response.data.result;
});
/**
* Calls the node's issueTx method from the API and returns the resulting transaction ID as a string.
*
* @param tx A string, {@link https://github.com/feross/buffer|Buffer}, or [[Tx]] representing a transaction
*
* @returns A Promise string representing the transaction ID of the posted transaction.
*/
this.issueTx = (tx) => __awaiter(this, void 0, void 0, function* () {
let Transaction = "";
if (typeof tx === "string") {
Transaction = tx;
}
else if (tx instanceof buffer_1.Buffer) {
const txobj = new tx_1.Tx();
txobj.fromBuffer(tx);
Transaction = txobj.toStringHex();
}
else if (tx instanceof tx_1.Tx) {
Transaction = tx.toStringHex();
}
else {
/* istanbul ignore next */
throw new errors_1.TransactionError("Error - avax.issueTx: provided tx is not expected type of string, Buffer, or Tx");
}
const params = {
tx: Transaction.toString(),
encoding: "hex"
};
const response = yield this.callMethod("avax.issueTx", params);
return response.data.result.txID
? response.data.result.txID
: response.data.result;
});
/**
* Exports the private key for an address.
*
* @param username The name of the user with the private key
* @param password The password used to decrypt the private key
* @param address The address whose private key should be exported
*
* @returns Promise with the decrypted private key and private key hex as store in the database
*/
this.exportKey = (username, password, address) => __awaiter(this, void 0, void 0, function* () {
const params = {
username,
password,
address
};
const response = yield this.callMethod("avax.exportKey", params);
return response.data.result;
});
/**
* Helper function which creates an unsigned Import Tx. For more granular control, you may create your own
* [[UnsignedTx]] manually (with their corresponding [[TransferableInput]]s, [[TransferableOutput]]s).
*
* @param utxoset A set of UTXOs that the transaction is built on
* @param toAddress The address to send the funds
* @param ownerAddresses The addresses being used to import
* @param sourceChain The chainid for where the import is coming from
* @param fromAddresses The addresses being used to send the funds from the UTXOs provided
*
* @returns An unsigned transaction ([[UnsignedTx]]) which contains a [[ImportTx]].
*
* @remarks
* This helper exists because the endpoint API should be the primary point of entry for most functionality.
*/
this.buildImportTx = (utxoset, toAddress, ownerAddresses, sourceChain, fromAddresses, fee = new bn_js_1.default(0)) => __awaiter(this, void 0, void 0, function* () {
const from = this._cleanAddressArray(fromAddresses, "buildImportTx").map((a) => bintools.stringToAddress(a));
let srcChain = undefined;
if (typeof sourceChain === "string") {
// if there is a sourceChain passed in and it's a string then save the string value and cast the original
// variable from a string to a Buffer
srcChain = sourceChain;
sourceChain = bintools.cb58Decode(sourceChain);
}
else if (typeof sourceChain === "undefined" ||
!(sourceChain instanceof buffer_1.Buffer)) {
// if there is no sourceChain passed in or the sourceChain is any data type other than a Buffer then throw an error
throw new errors_1.ChainIdError("Error - EVMAPI.buildImportTx: sourceChain is undefined or invalid sourceChain type.");
}
const utxoResponse = yield this.getUTXOs(ownerAddresses, srcChain, 0, undefined);
const atomicUTXOs = utxoResponse.utxos;
const networkID = this.core.getNetworkID();
const avaxAssetID = this.core.getNetwork().X.avaxAssetID;
const avaxAssetIDBuf = bintools.cb58Decode(avaxAssetID);
const atomics = atomicUTXOs.getAllUTXOs();
if (atomics.length === 0) {
throw new errors_1.NoAtomicUTXOsError("Error - EVMAPI.buildImportTx: no atomic utxos to import");
}
const builtUnsignedTx = utxoset.buildImportTx(networkID, bintools.cb58Decode(this.blockchainID), toAddress, atomics, sourceChain, fee, avaxAssetIDBuf);
return builtUnsignedTx;
});
/**
* Helper function which creates an unsigned Export Tx. For more granular control, you may create your own
* [[UnsignedTx]] manually (with their corresponding [[TransferableInput]]s, [[TransferableOutput]]s).
*
* @param amount The amount being exported as a {@link https://github.com/indutny/bn.js/|BN}
* @param assetID The asset id which is being sent
* @param destinationChain The chainid for where the assets will be sent.
* @param toAddresses The addresses to send the funds
* @param fromAddresses The addresses being used to send the funds from the UTXOs provided
* @param changeAddresses The addresses that can spend the change remaining from the spent UTXOs
* @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 threshold Optional. The number of signatures required to spend the funds in the resultant UTXO
*
* @returns An unsigned transaction ([[UnsignedTx]]) which contains an [[ExportTx]].
*/
this.buildExportTx = (amount, assetID, destinationChain, fromAddressHex, fromAddressBech, toAddresses, nonce = 0, locktime = new bn_js_1.default(0), threshold = 1, fee = new bn_js_1.default(0)) => __awaiter(this, void 0, void 0, function* () {
const prefixes = {};
toAddresses.map((address) => {
prefixes[address.split("-")[0]] = true;
});
if (Object.keys(prefixes).length !== 1) {
throw new errors_1.AddressError("Error - EVMAPI.buildExportTx: To addresses must have the same chainID prefix.");
}
if (typeof destinationChain === "undefined") {
throw new errors_1.ChainIdError("Error - EVMAPI.buildExportTx: Destination ChainID is undefined.");
}
else if (typeof destinationChain === "string") {
destinationChain = bintools.cb58Decode(destinationChain);
}
else if (!(destinationChain instanceof buffer_1.Buffer)) {
throw new errors_1.ChainIdError("Error - EVMAPI.buildExportTx: Invalid destinationChain type");
}
if (destinationChain.length !== 32) {
throw new errors_1.ChainIdError("Error - EVMAPI.buildExportTx: Destination ChainID must be 32 bytes in length.");
}
const assetDescription = yield this.getAssetDescription(this.core.getPrimaryAssetAlias());
let evmInputs = [];
if (bintools.cb58Encode(assetDescription.assetID) === assetID) {
const evmInput = new inputs_1.EVMInput(fromAddressHex, amount.add(fee), assetID, nonce);
evmInput.addSignatureIdx(0, bintools.stringToAddress(fromAddressBech));
evmInputs.push(evmInput);
}
else {
// if asset id isn't AVAX asset id then create 2 inputs
// first input will be AVAX and will be for the amount of the fee
// second input will be the ANT
const evmAVAXInput = new inputs_1.EVMInput(fromAddressHex, fee, assetDescription.assetID, nonce);
evmAVAXInput.addSignatureIdx(0, bintools.stringToAddress(fromAddressBech));
evmInputs.push(evmAVAXInput);
const evmANTInput = new inputs_1.EVMInput(fromAddressHex, amount, assetID, nonce);
evmANTInput.addSignatureIdx(0, bintools.stringToAddress(fromAddressBech));
evmInputs.push(evmANTInput);
}
const to = [];
toAddresses.map((address) => {
to.push(bintools.stringToAddress(address));
});
let exportedOuts = [];
const secpTransferOutput = new outputs_1.SECPTransferOutput(amount, to, locktime, threshold);
const transferableOutput = new outputs_1.TransferableOutput(bintools.cb58Decode(assetID), secpTransferOutput);
exportedOuts.push(transferableOutput);
// lexicographically sort ins and outs
evmInputs = evmInputs.sort(inputs_1.EVMInput.comparator());
exportedOuts = exportedOuts.sort(outputs_1.TransferableOutput.comparator());
const exportTx = new exporttx_1.ExportTx(this.core.getNetworkID(), bintools.cb58Decode(this.blockchainID), destinationChain, evmInputs, exportedOuts);
const unsignedTx = new tx_1.UnsignedTx(exportTx);
return unsignedTx;
});
/**
* Gets a reference to the keychain for this class.
*
* @returns The instance of [[KeyChain]] for this class
*/
this.keyChain = () => this.keychain;
/**
*
* @returns new instance of [[KeyChain]]
*/
this.newKeyChain = () => {
// warning, overwrites the old keychain
const alias = this.getBlockchainAlias();
if (alias) {
this.keychain = new keychain_1.KeyChain(this.core.getHRP(), alias);
}
else {
this.keychain = new keychain_1.KeyChain(this.core.getHRP(), this.blockchainID);
}
return this.keychain;
};
/**
* @returns a Promise string containing the base fee for the next block.
*/
this.getBaseFee = () => __awaiter(this, void 0, void 0, function* () {
const params = [];
const method = "eth_baseFee";
const path = "ext/bc/C/rpc";
const response = yield this.callMethod(method, params, path);
return response.data.result;
});
/**
* returns the priority fee needed to be included in a block.
*
* @returns Returns a Promise string containing the priority fee needed to be included in a block.
*/
this.getMaxPriorityFeePerGas = () => __awaiter(this, void 0, void 0, function* () {
const params = [];
const method = "eth_maxPriorityFeePerGas";
const path = "ext/bc/C/rpc";
const response = yield this.callMethod(method, params, path);
return response.data.result;
});
this.blockchainID = core.getNetwork().C.blockchainID;
if (blockchainID !== "" && blockchainID !== this.blockchainID) {
this.keychain = new keychain_1.KeyChain(this.core.getHRP(), blockchainID);
this.blockchainID = blockchainID;
}
else {
this.keychain = new keychain_1.KeyChain(this.core.getHRP(), core.getNetwork().C.alias);
}
}
/**
* @ignore
*/
_cleanAddressArray(addresses, caller) {
const addrs = [];
const chainid = this.getBlockchainAlias()
? this.getBlockchainAlias()
: this.getBlockchainID();
if (addresses && addresses.length > 0) {
addresses.forEach((address) => {
if (typeof address === "string") {
if (typeof this.parseAddress(address) === "undefined") {
/* istanbul ignore next */
throw new errors_1.AddressError("Error - Invalid address format");
}
addrs.push(address);
}
else {
const type = "bech32";
addrs.push(serialization.bufferToType(address, type, this.core.getHRP(), chainid));
}
});
}
return addrs;
}
}
exports.EVMAPI = EVMAPI;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBpLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2FwaXMvZXZtL2FwaS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7OztHQUdHOzs7Ozs7Ozs7Ozs7Ozs7QUFFSCxvQ0FBZ0M7QUFDaEMsa0RBQXNCO0FBRXRCLGtEQUE4QztBQUU5QyxvRUFBMkM7QUFDM0MsbUNBQXVDO0FBQ3ZDLHlDQUFxQztBQUNyQyw2QkFBcUM7QUFDckMsMkNBQTBDO0FBTzFDLHFDQUFtQztBQUNuQyx1Q0FBa0U7QUFDbEUseUNBQXFDO0FBQ3JDLCtDQUsyQjtBQUMzQix1Q0FBMkQ7QUFjM0Q7O0dBRUc7QUFDSCxNQUFNLFFBQVEsR0FBYSxrQkFBUSxDQUFDLFdBQVcsRUFBRSxDQUFBO0FBQ2pELE1BQU0sYUFBYSxHQUFrQixxQkFBYSxDQUFDLFdBQVcsRUFBRSxDQUFBO0FBRWhFOzs7Ozs7R0FNRztBQUNILE1BQWEsTUFBTyxTQUFRLGlCQUFPO0lBcXZCakM7Ozs7Ozs7T0FPRztJQUNILFlBQ0UsSUFBbUIsRUFDbkIsVUFBa0IsZ0JBQWdCLEVBQ2xDLGVBQXVCLEVBQUU7UUFFekIsS0FBSyxDQUFDLElBQUksRUFBRSxPQUFPLENBQUMsQ0FBQTtRQWp3QnRCOztXQUVHO1FBQ08sYUFBUSxHQUFhLElBQUksbUJBQVEsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUE7UUFDekMsaUJBQVksR0FBVyxFQUFFLENBQUE7UUFDekIsb0JBQWUsR0FBVyxTQUFTLENBQUE7UUFDbkMsZ0JBQVcsR0FBVyxTQUFTLENBQUE7UUFDL0IsVUFBSyxHQUFPLFNBQVMsQ0FBQTtRQUUvQjs7OztXQUlHO1FBQ0gsdUJBQWtCLEdBQUcsR0FBVyxFQUFFO1lBQ2hDLElBQUksT0FBTyxJQUFJLENBQUMsZUFBZSxLQUFLLFdBQVcsRUFBRTtnQkFDL0MsSUFBSSxDQUFDLGVBQWUsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDLENBQUMs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SUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsRUFDbEIsT0FBTyxDQUNSLENBQ0YsQ0FBQTtpQkFDRjtZQUNILENBQUMsQ0FBQyxDQUFBO1NBQ0g7UUFDRCxPQUFPLEtBQUssQ0FBQTtJQUNkLENBQUM7Q0E2REY7QUFoekJELHdCQWd6QkMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBwYWNrYWdlRG9jdW1lbnRhdGlvblxuICogQG1vZHVsZSBBUEktRVZNXG4gKi9cblxuaW1wb3J0IHsgQnVmZmVyIH0gZnJvbSBcImJ1ZmZlci9cIlxuaW1wb3J0IEJOIGZyb20gXCJibi5qc1wiXG5pbXBvcnQgQXZhbGFuY2hlQ29yZSBmcm9tIFwiLi4vLi4vY2FtaW5vXCJcbmltcG9ydCB7IEpSUENBUEkgfSBmcm9tIFwiLi4vLi4vY29tbW9uL2pycGNhcGlcIlxuaW1wb3J0IHsgUmVxdWVzdFJlc3BvbnNlRGF0YSB9IGZyb20gXCIuLi8uLi9jb21tb24vYXBpYmFzZVwiXG5pbXBvcnQgQmluVG9vbHMgZnJvbSBcIi4u