UNPKG

@kubectl/caminojs

Version:
625 lines 87.6 kB
"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