@c4tplatform/caminojs
Version:
Camino Platform JS Library
628 lines • 87.3 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 {
/**
* @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;
}
/**
* 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(buffer_1.Buffer.from(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, fee = new bn_js_1.default(0)) => __awaiter(this, void 0, void 0, function* () {
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.");
}
var atomicUTXOs = utxoset;
if (!utxoset) {
const utxoResponse = yield this.getUTXOs(ownerAddresses, srcChain, 0, undefined);
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 = atomicUTXOs.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 fromAddressesHex The addresses to send the funds (hex)
* @param fromAddressesBech The addresses being used to send the funds from the UTXOs provided
* @param toAddresses An array of addresses as {@link https://github.com/feross/buffer|Buffer} who recieves the AVAX
* @param nonce Optional. The nonce to be used
* @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 fee Optional. The the fee for this transaction
*
* @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), toThreshold = 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, toThreshold);
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);
}
}
}
exports.EVMAPI = EVMAPI;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBpLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2FwaXMvZXZtL2FwaS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7OztHQUdHOzs7Ozs7Ozs7Ozs7Ozs7QUFFSCxvQ0FBZ0M7QUFDaEMsa0RBQXNCO0FBRXRCLGtEQUE4QztBQUU5QyxvRUFBMkM7QUFDM0MsbUNBQXVDO0FBQ3ZDLHlDQUFxQztBQUNyQyw2QkFBcUM7QUFDckMsMkNBQTBDO0FBTzFDLHFDQUFtQztBQUNuQyx1Q0FBa0U7QUFDbEUseUNBQXFDO0FBQ3JDLCtDQUsyQjtBQUMzQix1Q0FBMkQ7QUFjM0Q7O0dBRUc7QUFDSCxNQUFNLFFBQVEsR0FBYSxrQkFBUSxDQUFDLFdBQVcsRUFBRSxDQUFBO0FBQ2pELE1BQU0sYUFBYSxHQUFrQixxQkFBYSxDQUFDLFdBQVcsRUFBRSxDQUFBO0FBRWhFOzs7Ozs7R0FNRztBQUNILE1BQWEsTUFBTyxTQUFRLGlCQUFPO0lBbXRCakM7O09BRUc7SUFDTyxrQkFBa0IsQ0FDMUIsU0FBOEIsRUFDOUIsTUFBYztRQUVkLE1BQU0sS0FBSyxHQUFhLEVBQUUsQ0FBQTtRQUMxQixNQUFNLE9BQU8sR0FBVyxJQUFJLENBQUMsa0JBQWtCLEVBQUU7WUFDL0MsQ0FBQyxDQUFDLElBQUksQ0FBQyxrQkFBa0IsRUFBRTtZQUMzQixDQUFDLENBQUMsSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFBO1FBQzFCLElBQUksU0FBUyxJQUFJLFNBQVMsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFO1lBQ3JDLFNBQVMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxPQUF3QixFQUFFLEVBQUU7Z0JBQzdDLElBQUksT0FBTyxPQUFPLEtBQUssUUFBUSxFQUFFO29CQUMvQixJQUFJLE9BQU8sSUFBSSxDQUFDLFlBQVksQ0FBQyxPQUFpQixDQUFDLEtBQUssV0FBVyxFQUFFO3dCQUMvRCwwQkFBMEI7d0JBQzFCLE1BQU0sSUFBSSxxQkFBWSxDQUFDLGdDQUFn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LENBQUE7U0FDRjtJQUNILENBQUM7Q0FrQ0Y7QUFqekJELHdCQWl6QkMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBwYWNrYWdlRG9jdW1lbnRhdGlvblxuICogQG1vZHVsZSBBUEktRVZNXG4gKi9cblxuaW1wb3J0IHsgQnVmZmVyIH0gZnJvbSBcImJ1ZmZlci9cIlxuaW1wb3J0IEJOIGZyb20gXCJibi5qc1wiXG5pbXBvcnQgQXZhbGFuY2hlQ29yZSBmcm9tIFwiLi4vLi4vY2FtaW5vXCJcbmltcG9ydCB7IEpSUENBUEkgfSBmcm9tIFwiLi4vLi4vY29tbW9uL2pycGNhcGlcIlxuaW1wb3J0IHsgUmVxdWVzdFJlc3BvbnNlRGF0YSB9IGZyb20gXCIuLi8uLi9jb21tb24vYXBpYmFzZVwiXG5pbXBvcnQgQmluVG9vbHMgZnJvbSBcIi4uLy4uL3V0aWxzL2JpbnRvb2xzXCJcbmltcG9ydCB7IFVUWE9TZXQsIFVUWE8gfSBmcm9tIFwiLi91dHhvc1wiXG5pbXBvcnQgeyBLZXlDaGFpbiB9IGZyb20gXCIuL2tleWNoYWluXCJcbmltcG9