UNPKG

eulith-web3js-core

Version:

Eulith core web3js SDK (code to access Eulith services via web3js)

227 lines 27.7 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; 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.EulithWeb3 = void 0; const web3_1 = __importDefault(require("web3")); const crypto = require("crypto"); // import crypto doesn't work from (at least some) reactjs browser apps const Eulith = __importStar(require("../src/index")); function LogErr_(logger, w, e) { var _a; logger === null || logger === void 0 ? void 0 : logger.log(Eulith.Logging.LogLevel.ERROR, `Error while ${w}: ${e.message}; details: ${JSON.stringify((_a = e.response) === null || _a === void 0 ? void 0 : _a.data)}`); } /** * @typedef Eulith.Web3 * * This can be used to access Eulith-specific APIs, but often all that is needed * is Eulith.Provider, and that can be used directly with a web3 js object. * * @todo For now - extend Web3 the way the python code does. Perhaps do a class for just eulith-specific methods * or perhaps find a more object oriented path (like we did for AtomicTx) * * Also note - this API deviates from the web3js and etherjs patterns in one important respect: * their sendTransaction API returns a promise which resolves * <https://web3js.readthedocs.io/en/v1.2.11/web3-eth.html#sendtransaction> 'when the transaction receipt is available.' * (oversimplifying, PromiEvent) * * This causes a number of problems when using the Eulith atomic transactions, because we NEVER generate those transaction receipts. * and by default, web3js keeps a waiter around polling (at least on http and in some ways as bad with websocket/etc). It causes * false positive errors to be reported from various channels (e.g. automation tests). And wastes resources. * * So we follow the web3.py pattern, and return a Promise<HASH TAG> instead (eulith_send_and_sign_transaction). * * Then, the caller may poll wait with the that hash * await ew3.eth.getTransactionReceipt(txHash) * to get the receipt. * * Another 'deviation' to report/note, is that the python API has the (exposed in the API) concept of 'signing middleware'. * EVEN IF this makes sense in the python implementation (I doubt), I propose changing the public API instead to take a * 'signer' object. And have that 'signer' object ONLY be used in the context of a new proposed method - eulith_send_and_sign_transaction * - and have that do the signing, INSTEAD of the hooking of eth.send_transaction. * * The current behavior of the python code is quite idiosyncratic, and confusing, with respect to WHEN the send_transaction calls * are intercepted and signed (in context of an atomic transaction changes things, as does from/to address/presence of signature etc). * * Perhaps better to have an explicit method eulith_send_and_sign_transaction so you know you are signing (seems like the API flows * require the caller to know / understand this anyhow). * */ class EulithWeb3 extends web3_1.default { /** * @constructor * @param provider - this is a web3js provider, plus supports eulith apis * @param disable_transaction_polling defaults true * @param signer - modifies the behavior of a number of eulith apis (not web3.eth apis) - to include the signers address - but mostly for eulith_send_and_sign_transaction * * @todo discuss with Moh/Kristian if it might be cleaner to make ISigner a parameter to those APIs? So this subtlty is clear */ constructor({ provider, signer, disable_transaction_polling }) { super(); if (provider == null) { throw new Error("Cannot construct Eulith.Web3 without a Eulith.Provider"); } if (disable_transaction_polling == null) { disable_transaction_polling = true; } if (disable_transaction_polling == true) { this.eth.transactionPollingTimeout = 0; } this.logger_ = provider.logger; if (signer) { this.signer_ = Eulith.Signing.SigningService.assure(signer, provider); provider = provider.cloneWithSigner(this.signer_); } this.setProvider(provider); if (this.signer_ == null) { this.providerForAPIsRequiringAuthAddressField_ = provider; } else { this.providerForAPIsRequiringAuthAddressField_ = provider.cloneWithURLAdditions({ auth_address: this.signer_.address }); } } /** * The signer is an optional property of a web3 object, so this can return null */ get signer() { return this.signer_; } /** * Fetch the logger associate dwith this web3 object. */ get logger() { return this.logger_; } /** * @todo CONSIDER DEPRECATING * * delegate to this.eth.sendTransaction, but just return the transaction hash; * * to get the txReceipt, CALL * const txReceipt: TransactionReceipt = await ew3.eth.getTransactionReceipt(txHash); * @param transactionConfig * @returns * * This method is PERHAPS not useful, since there is probably no point in ever sending unsigned transactions * (besides our use in transactions, which could be done differently, and certainly doesnt require this to be public) */ eulith_send_unsigned_transaction(transactionConfig, extraURLQueryParams) { return __awaiter(this, void 0, void 0, function* () { let p = new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () { const txRes = this.eth .sendTransaction(transactionConfig) .once("transactionHash", (transactionHash) => { resolve(transactionHash); }) .once("error", (error) => { reject(error); }) .catch((reason) => reject(reason)); })); return p; }); } /* * @todo DOCUMENT * @todo consider migrating to Swaps module... */ // def eulith_swap_quote(self, params: Eulith.SwapRequest) -> (float, List[TxParams]): eulith_swap_quote(params) { var _a; return __awaiter(this, void 0, void 0, function* () { const wireFormatParams = { sell_token: params.sellToken.address, buy_token: params.buyToken.address, sell_amount: params.sellAmount }; if (params.recipient) { wireFormatParams["recipient"] = params.recipient; } if (params.routeThrough) { wireFormatParams["route_through"] = params.routeThrough; } if (params.liquiditySource) { wireFormatParams["liquidity_source"] = params.liquiditySource; } if (params.slippageTolerance) { wireFormatParams["slippage_tolerance"] = params.slippageTolerance; } const result = yield this.providerForAPIsRequiringAuthAddressField_.request({ method: "eulith_swap", params: [wireFormatParams] }); return [(_a = result.price) !== null && _a !== void 0 ? _a : 0.0, result.txs]; }); } /** * Send a series of transactions (eulith_send_and_sign_transaction), and wait for each to be confirmed, * returning the transaction receipts of each. * * At any point, one of them could fail, with some having gone on to completion. This process aborts at that time * and offers no clues about how many were processed (could include the completed ones in a special exception) * * @param txs * @returns */ eulith_send_multi_transaction(txs) { return __awaiter(this, void 0, void 0, function* () { let results = []; if (this.signer_ == null) { throw new Error("This API requires a valid signer provided to the EulithWeb3 object"); } // accumulate all the promises, and wait all at once let promises = []; for (const tx of txs) { const txHash = yield this.provider.signAndSendTransaction(tx, this.signer); const txReceipt = yield this.eth.getTransactionReceipt(txHash); results.push(txReceipt); } return results; }); } /** * Returns the provider object associated with this transaction. * * @todo NOTE due to quirks of how we implement signing, and cloning etc, this might not be the same * provider, but instead one derieved from - the original one provided in the constructor. */ get provider() { return this.providerForAPIsRequiringAuthAddressField_; } } exports.EulithWeb3 = EulithWeb3; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2ViMy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy93ZWIzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsZ0RBQXdCO0FBR3hCLE1BQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLHVFQUF1RTtBQUV6RyxxREFBdUM7QUFFdkMsU0FBUyxPQUFPLENBQUMsTUFBOEIsRUFBRSxDQUFTLEVBQUUsQ0FBYTs7SUFDckUsTUFBTSxhQUFOLE1BQU0sdUJBQU4sTUFBTSxDQUFFLEdBQUcsQ0FDUCxNQUFNLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxLQUFLLEVBQzdCLGVBQWUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxPQUFPLGNBQWMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFBLENBQUMsQ0FBQyxRQUFRLDBDQUFFLElBQUksQ0FBQyxFQUFFLENBQ2pGLENBQUM7QUFDTixDQUFDO0FBRUQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBbUNHO0FBQ0gsTUFBYSxVQUFXLFNBQVEsY0FBSTtJQUNoQzs7Ozs7OztPQU9HO0lBQ0gsWUFBbUIsRUFDZixRQUFRLEVBQ1IsTUFBTSxFQUNOLDJCQUEyQixFQUs5QjtRQUNHLEtBQUssRUFBRSxDQUFDO1FBRVIsSUFBSSxRQUFRLElBQUksSUFBSSxFQUFFO1lBQ2xCLE1BQU0sSUFBSSxLQUFLLENBQUMsd0RBQXdELENBQUMsQ0FBQztTQUM3RTtRQUVELElBQUksMkJBQTJCLElBQUksSUFBSSxFQUFFO1lBQ3JDLDJCQUEyQixHQUFHLElBQUksQ0FBQztTQUN0QztRQUNELElBQUksMkJBQTJCLElBQUksSUFBSSxFQUFFO1lBQ3JDLElBQUksQ0FBQyxHQUFHLENBQUMseUJBQXlCLEdBQUcsQ0FBQyxDQUFDO1NBQzFDO1FBRUQsSUFBSSxDQUFDLE9BQU8sR0FBRyxRQUFRLENBQUMsTUFB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LE1BQUEsTUFBTSxDQUFDLEtBQUssbUNBQUksR0FBRyxFQUFFLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQzs7S0FDNUM7SUFFRDs7Ozs7Ozs7O09BU0c7SUFDRyw2QkFBNkIsQ0FBQyxHQUF3Qjs7WUFDeEQsSUFBSSxPQUFPLEdBQUcsRUFBRSxDQUFDO1lBQ2pCLElBQUksSUFBSSxDQUFDLE9BQU8sSUFBSSxJQUFJLEVBQUU7Z0JBQ3RCLE1BQU0sSUFBSSxLQUFLLENBQUMsb0VBQW9FLENBQUMsQ0FBQzthQUN6RjtZQUNELG9EQUFvRDtZQUNwRCxJQUFJLFFBQVEsR0FBRyxFQUFFLENBQUM7WUFDbEIsS0FBSyxNQUFNLEVBQUUsSUFBSSxHQUFHLEVBQUU7Z0JBQ2xCLE1BQU0sTUFBTSxHQUFXLE1BQU0sSUFBSSxDQUFDLFFBQVEsQ0FBQyxzQkFBc0IsQ0FBQyxFQUFFLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO2dCQUNuRixNQUFNLFNBQVMsR0FBdUIsTUFBTSxJQUFJLENBQUMsR0FBRyxDQUFDLHFCQUFxQixDQUFDLE1BQU0sQ0FBQyxDQUFDO2dCQUNuRixPQUFPLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO2FBQzNCO1lBQ0QsT0FBTyxPQUFPLENBQUM7UUFDbkIsQ0FBQztLQUFBO0lBRUQ7Ozs7O09BS0c7SUFDSCxJQUFXLFFBQVE7UUFDZixPQUFPLElBQUksQ0FBQyx5Q0FBeUMsQ0FBQztJQUMxRCxDQUFDO0NBT0o7QUFuS0QsZ0NBbUtDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IFdlYjMgZnJvbSBcIndlYjNcIjtcbmltcG9ydCB7IFRyYW5zYWN0aW9uQ29uZmlnLCBUcmFuc2FjdGlvblJlY2VpcHQgfSBmcm9tIFwid2ViMy1ldGhcIjtcbmltcG9ydCB7IEF4aW9zRXJyb3IgfSBmcm9tIFwiYXhpb3NcIjtcbmNvbnN0IGNyeXB0byA9IHJlcXVpcmUoXCJjcnlwdG9cIik7IC8vIGltcG9ydCBjcnlwdG8gZG9lc24ndCB3b3JrIGZyb20gKGF0IGxlYXN0IHNvbWUpIHJlYWN0anMgYnJvd3NlciBhcHBzXG5cbmltcG9ydCAqIGFzIEV1bGl0aCBmcm9tIFwiLi4vc3JjL2luZGV4XCI7XG5cbmZ1bmN0aW9uIExvZ0Vycl8obG9nZ2VyOiBFdWxpdGguTG9nZ2luZy5JTG9nZ2VyLCB3OiBzdHJpbmcsIGU6IEF4aW9zRXJyb3IpOiB2b2lkIHtcbiAgICBsb2dnZXI/LmxvZyhcbiAgICAgICAgRXVsaXRoLkxvZ2dpbmcuTG9nTGV2ZWwuRVJST1IsXG4gICAgICAgIGBFcnJvciB3aGlsZSAke3d9OiAke2UubWVzc2FnZX07IGRldGFpbHM6ICR7SlNPTi5zdHJpbmdpZnkoZS5yZXNwb25zZT8uZGF0YSl9YFxuICAgICk7XG59XG5cbi8qKlxuICogIEB0eXBlZGVmIEV1bGl0aC5XZWIzXG4gKlxuICogIFRoaXMgY2FuIGJlIHVzZWQgdG8gYWNjZXNzIEV1bGl0aC1zcGVjaWZpYyBBUElzLCBidXQgb2Z0ZW4gYWxsIHRoYXQgaXMgbmVlZGVkXG4gKiAgaXMgRXVsaXRoLlByb3ZpZGVyLCBhbmQgdGhhdCBjYW4gYmUgdXNlZCBkaXJlY3RseSB3aXRoIGEgd2ViMyBqcyBvYmplY3QuXG4gKlxuICogIEB0b2RvIEZvciBub3cgLSBleHRlbmQgV2ViMyB0aGUgd2F5IHRoZSBweXRob24gY29kZSBkb2VzLiBQZXJoYXBzIGRvIGEgY2xhc3MgZm9yIGp1c3QgZXVsaXRoLXNwZWNpZmljIG1ldGhvZHNcbiAqICBvciBwZXJoYXBzIGZpbmQgYSBtb3JlIG9iamVjdCBvcmllbnRlZCBwYXRoIChsaWtlIHdlIGRpZCBmb3IgQXRvbWljVHgpXG4gKlxuICogIEFsc28gbm90ZSAtIHRoaXMgQVBJIGRldmlhdGVzIGZyb20gdGhlIHdlYjNqcyBhbmQgZXRoZXJqcyBwYXR0ZXJucyBpbiBvbmUgaW1wb3J0YW50IHJlc3BlY3Q6XG4gKiAgdGhlaXIgc2VuZFRyYW5zYWN0aW9uIEFQSSByZXR1cm5zIGEgcHJvbWlzZSB3aGljaCByZXNvbHZlc1xuICogICAgICA8aHR0cHM6Ly93ZWIzanMucmVhZHRoZWRvY3MuaW8vZW4vdjEuMi4xMS93ZWIzLWV0aC5odG1sI3NlbmR0cmFuc2FjdGlvbj4gJ3doZW4gdGhlIHRyYW5zYWN0aW9uIHJlY2VpcHQgaXMgYXZhaWxhYmxlLidcbiAqICAgICAgKG92ZXJzaW1wbGlmeWluZywgUHJvbWlFdmVudClcbiAqXG4gKiAgVGhpcyBjYXVzZXMgYSBudW1iZXIgb2YgcHJvYmxlbXMgd2hlbiB1c2luZyB0aGUgRXVsaXRoIGF0b21pYyB0cmFuc2FjdGlvbnMsIGJlY2F1c2Ugd2UgTkVWRVIgZ2VuZXJhdGUgdGhvc2UgdHJhbnNhY3Rpb24gcmVjZWlwdHMuXG4gKiAgYW5kIGJ5IGRlZmF1bHQsIHdlYjNqcyBrZWVwcyBhIHdhaXRlciBhcm91bmQgcG9sbGluZyAoYXQgbGVhc3Qgb24gaHR0cCBhbmQgaW4gc29tZSB3YXlzIGFzIGJhZCB3aXRoIHdlYnNvY2tldC9ldGMpLiBJdCBjYXVzZXNcbiAqICBmYWxzZSBwb3NpdGl2ZSBlcnJvcnMgdG8gYmUgcmVwb3J0ZWQgZnJvbSB2YXJpb3VzIGNoYW5uZWxzIChlLmcuIGF1dG9tYXRpb24gdGVzdHMpLiBBbmQgd2FzdGVzIHJlc291cmNlcy5cbiAqXG4gKiAgU28gd2UgZm9sbG93IHRoZSB3ZWIzLnB5IHBhdHRlcm4sIGFuZCByZXR1cm4gYSBQcm9taXNlPEhBU0ggVEFHPiBpbnN0ZWFkIChldWxpdGhfc2VuZF9hbmRfc2lnbl90cmFuc2FjdGlvbikuXG4gKlxuICogIFRoZW4sIHRoZSBjYWxsZXIgbWF5IHBvbGwgd2FpdCB3aXRoIHRoZSB0aGF0IGhhc2hcbiAqICAgICAgYXdhaXQgZXczLmV0aC5nZXRUcmFuc2FjdGlvblJlY2VpcHQodHhIYXNoKVxuICogIHRvIGdldCB0aGUgcmVjZWlwdC5cbiAqXG4gKiAgQW5vdGhlciAnZGV2aWF0aW9uJyB0byByZXBvcnQvbm90ZSwgaXMgdGhhdCB0aGUgcHl0aG9uIEFQSSBoYXMgdGhlIChleHBvc2VkIGluIHRoZSBBUEkpIGNvbmNlcHQgb2YgJ3NpZ25pbmcgbWlkZGxld2FyZScuXG4gKiAgRVZFTiBJRiB0aGlzIG1ha2VzIHNlbnNlIGluIHRoZSBweXRob24gaW1wbGVtZW50YXRpb24gKEkgZG91YnQpLCBJIHByb3Bvc2UgY2hhbmdpbmcgdGhlIHB1YmxpYyBBUEkgaW5zdGVhZCB0byB0YWtlIGFcbiAqICAnc2lnbmVyJyBvYmplY3QuIEFuZCBoYXZlIHRoYXQgJ3NpZ25lcicgb2JqZWN0IE9OTFkgYmUgdXNlZCBpbiB0aGUgY29udGV4dCBvZiBhIG5ldyBwcm9wb3NlZCBtZXRob2QgLSBldWxpdGhfc2VuZF9hbmRfc2lnbl90cmFuc2FjdGlvblxuICogIC0gYW5kIGhhdmUgdGhhdCBkbyB0aGUgc2lnbmluZywgSU5TVEVBRCBvZiB0aGUgaG9va2luZyBvZiBldGguc2VuZF90cmFuc2FjdGlvbi5cbiAqXG4gKiAgVGhlIGN1cnJlbnQgYmVoYXZpb3Igb2YgdGhlIHB5dGhvbiBjb2RlIGlzIHF1aXRlIGlkaW9zeW5jcmF0aWMsIGFuZCBjb25mdXNpbmcsIHdpdGggcmVzcGVjdCB0byBXSEVOIHRoZSBzZW5kX3RyYW5zYWN0aW9uIGNhbGxzXG4gKiAgYXJlIGludGVyY2VwdGVkIGFuZCBzaWduZWQgKGluIGNvbnRleHQgb2YgYW4gYXRvbWljIHRyYW5zYWN0aW9uIGNoYW5nZXMgdGhpbmdzLCBhcyBkb2VzIGZyb20vdG8gYWRkcmVzcy9wcmVzZW5jZSBvZiBzaWduYXR1cmUgZXRjKS5cbiAqXG4gKiAgUGVyaGFwcyBiZXR0ZXIgdG8gaGF2ZSBhbiBleHBsaWNpdCBtZXRob2QgZXVsaXRoX3NlbmRfYW5kX3NpZ25fdHJhbnNhY3Rpb24gc28geW91IGtub3cgeW91IGFyZSBzaWduaW5nIChzZWVtcyBsaWtlIHRoZSBBUEkgZmxvd3NcbiAqICByZXF1aXJlIHRoZSBjYWxsZXIgdG8ga25vdyAvIHVuZGVyc3RhbmQgdGhpcyBhbnlob3cpLlxuICpcbiAqL1xuZXhwb3J0IGNsYXNzIEV1bGl0aFdlYjMgZXh0ZW5kcyBXZWIzIHtcbiAgICAvKipcbiAgICAgKiBAY29uc3RydWN0b3JcbiAgICAgKiBAcGFyYW0gcHJvdmlkZXIgLSB0aGlzIGlzIGEgd2ViM2pzIHByb3ZpZGVyLCBwbHVzIHN1cHBvcnRzIGV1bGl0aCBhcGlzXG4gICAgICogQHBhcmFtIGRpc2FibGVfdHJhbnNhY3Rpb25fcG9sbGluZyBkZWZhdWx0cyB0cnVlXG4gICAgICogQHBhcmFtIHNpZ25lciAtIG1vZGlmaWVzIHRoZSBiZWhhdmlvciBvZiBhIG51bWJlciBvZiBldWxpdGggYXBpcyAobm90IHdlYjMuZXRoIGFwaXMpIC0gdG8gaW5jbHVkZSB0aGUgc2lnbmVycyBhZGRyZXNzIC0gYnV0IG1vc3RseSBmb3IgZXVsaXRoX3NlbmRfYW5kX3NpZ25fdHJhbnNhY3Rpb25cbiAgICAgKlxuICAgICAqIEB0b2RvIGRpc2N1c3Mgd2l0aCBNb2gvS3Jpc3RpYW4gaWYgaXQgbWlnaHQgYmUgY2xlYW5lciB0byBtYWtlIElTaWduZXIgYSBwYXJhbWV0ZXIgdG8gdGhvc2UgQVBJcz8gU28gdGhpcyBzdWJ0bHR5IGlzIGNsZWFyXG4gICAgICovXG4gICAgcHVibGljIGNvbnN0cnVjdG9yKHtcbiAgICAgICAgcHJvdmlkZXIsXG4gICAgICAgIHNpZ25lcixcbiAgICAgICAgZGlzYWJsZV90cmFuc2FjdGlvbl9wb2xsaW5nXG4gICAgfToge1xuICAgICAgICBwcm92aWRlcjogRXVsaXRoLlByb3ZpZGVyO1xuICAgICAgICBzaWduZXI/OiBFdWxpdGguU2lnbmluZy5JQ3J5cHRvZ3JhcGhpY1NpZ25lciB8IEV1bGl0aC5TaWduaW5nLlNpZ25pbmdTZXJ2aWNlO1xuICAgICAgICBkaXNhYmxlX3RyYW5zYWN0aW9uX3BvbGxpbmc/OiBib29sZWFuO1xuICAgIH0pIHtcbiAgICAgICAgc3VwZXIoKTtcblxuICAgICAgICBpZiAocHJvdmlkZXIgPT0gbnVsbCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ2Fubm90IGNvbnN0cnVjdCBFdWxpdGguV2ViMyB3aXRob3V0IGEgRXVsaXRoLlByb3ZpZGVyXCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGRpc2FibGVfdHJhbnNhY3Rpb25fcG9sbGluZyA9PSBudWxsKSB7XG4gICAgICAgICAgICBkaXNhYmxlX3RyYW5zYWN0aW9uX3BvbGxpbmcgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChkaXNhYmxlX3RyYW5zYWN0aW9uX3BvbGxpbmcgPT0gdHJ1ZSkge1xuICAgICAgICAgICAgdGhpcy5ldGgudHJhbnNhY3Rpb25Qb2xsaW5nVGltZW91dCA9IDA7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmxvZ2dlcl8gPSBwcm92aWRlci5sb2dnZXI7XG5cbiAgICAgICAgaWYgKHNpZ25lcikge1xuICAgICAgICAgICAgdGhpcy5zaWduZXJfID0gRXVsaXRoLlNpZ25pbmcuU2lnbmluZ1NlcnZpY2UuYXNzdXJlKHNpZ25lciwgcHJvdmlkZXIpO1xuICAgICAgICAgICAgcHJvdmlkZXIgPSBwcm92aWRlci5jbG9uZVdpdGhTaWduZXIodGhpcy5zaWduZXJfKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnNldFByb3ZpZGVyKHByb3ZpZGVyKTtcblxuICAgICAgICBpZiAodGhpcy5zaWduZXJfID09IG51bGwpIHtcbiAgICAgICAgICAgIHRoaXMucHJvdmlkZXJGb3JBUElzUmVxdWlyaW5nQXV0aEFkZHJlc3NGaWVsZF8gPSBwcm92aWRlcjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMucHJvdmlkZXJGb3JBUElzUmVxdWlyaW5nQXV0aEFkZHJlc3NGaWVsZF8gPSBwcm92aWRlci5jbG9uZVdpdGhVUkxBZGRpdGlvbnMoe1xuICAgICAgICAgICAgICAgIGF1dGhfYWRkcmVzczogdGhpcy5zaWduZXJfLmFkZHJlc3NcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogIFRoZSBzaWduZXIgaXMgYW4gb3B0aW9uYWwgcHJvcGVydHkgb2YgYSB3ZWIzIG9iamVjdCwgc28gdGhpcyBjYW4gcmV0dXJuIG51bGxcbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0IHNpZ25lcigpOiBFdWxpdGguU2lnbmluZy5TaWduaW5nU2VydmljZSB8IHVuZGVmaW5lZCB7XG4gICAgICAgIHJldHVybiB0aGlzLnNpZ25lcl87XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogIEZldGNoIHRoZSBsb2dnZXIgYXNzb2NpYXRlIGR3aXRoIHRoaXMgd2ViMyBvYmplY3QuXG4gICAgICovXG4gICAgcHVibGljIGdldCBsb2dnZXIoKTogRXVsaXRoLkxvZ2dpbmcuSUxvZ2dlciB7XG4gICAgICAgIHJldHVybiB0aGlzLmxvZ2dlcl87XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogIEB0b2RvIENPTlNJREVSIERFUFJFQ0FUSU5HXG4gICAgICpcbiAgICAgKiAgZGVsZWdhdGUgdG8gdGhpcy5ldGguc2VuZFRyYW5zYWN0aW9uLCBidXQganVzdCByZXR1cm4gdGhlIHRyYW5zYWN0aW9uIGhhc2g7XG4gICAgICpcbiAgICAgKiAgdG8gZ2V0IHRoZSB0eFJlY2VpcHQsIENBTExcbiAgICAgKiAgICAgIGNvbnN0IHR4UmVjZWlwdDogVHJhbnNhY3Rpb25SZWNlaXB0ID0gYXdhaXQgZXczLmV0aC5nZXRUcmFuc2FjdGlvblJlY2VpcHQodHhIYXNoKTtcbiAgICAgKiBAcGFyYW0gdHJhbnNhY3Rpb25Db25maWdcbiAgICAgKiBAcmV0dXJuc1xuICAgICAqXG4gICAgICogIFRoaXMgbWV0aG9kIGlzIFBFUkhBUFMgbm90IHVzZWZ1bCwgc2luY2UgdGhlcmUgaXMgcHJvYmFibHkgbm8gcG9pbnQgaW4gZXZlciBzZW5kaW5nIHVuc2lnbmVkIHRyYW5zYWN0aW9uc1xuICAgICAqICAoYmVzaWRlcyBvdXIgdXNlIGluIHRyYW5zYWN0aW9ucywgd2hpY2ggY291bGQgYmUgZG9uZSBkaWZmZXJlbnRseSwgYW5kIGNlcnRhaW5seSBkb2VzbnQgcmVxdWlyZSB0aGlzIHRvIGJlIHB1YmxpYylcbiAgICAgKi9cbiAgICBwdWJsaWMgYXN5bmMgZXVsaXRoX3NlbmRfdW5zaWduZWRfdHJhbnNhY3Rpb24oXG4gICAgICAgIHRyYW5zYWN0aW9uQ29uZmlnOiBUcmFuc2FjdGlvbkNvbmZpZyxcbiAgICAgICAgZXh0cmFVUkxRdWVyeVBhcmFtcz86IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH1cbiAgICApOiBQcm9taXNlPHN0cmluZz4ge1xuICAgICAgICBsZXQgcCA9IG5ldyBQcm9taXNlPHN0cmluZz4oYXN5bmMgKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgdHhSZXMgPSB0aGlzLmV0aFxuICAgICAgICAgICAgICAgIC5zZW5kVHJhbnNhY3Rpb24odHJhbnNhY3Rpb25Db25maWcpXG4gICAgICAgICAgICAgICAgLm9uY2UoXCJ0cmFuc2FjdGlvbkhhc2hcIiwgKHRyYW5zYWN0aW9uSGFzaDogc3RyaW5nKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUodHJhbnNhY3Rpb25IYXNoKTtcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5vbmNlKFwiZXJyb3JcIiwgKGVycm9yOiBFcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLmNhdGNoKChyZWFzb24pID0+IHJlamVjdChyZWFzb24pKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBwO1xuICAgIH1cblxuICAgIC8qXG4gICAgICogIEB0b2RvIERPQ1VNRU5UXG4gICAgICogIEB0b2RvIGNvbnNpZGVyIG1pZ3JhdGluZyB0byBTd2FwcyBtb2R1bGUuLi5cbiAgICAgKi9cbiAgICAvLyBkZWYgZXVsaXRoX3N3YXBfcXVvdGUoc2VsZiwgcGFyYW1zOiBFdWxpdGguU3dhcFJlcXVlc3QpIC0+IChmbG9hdCwgTGlzdFtUeFBhcmFtc10pOlxuICAgIHB1YmxpYyBhc3luYyBldWxpdGhfc3dhcF9xdW90ZShwYXJhbXM6IEV1bGl0aC5Td2Fwcy5SZXF1ZXN0KTogUHJvbWlzZTxbbnVtYmVyLCBUcmFuc2FjdGlvbkNvbmZpZ1tdXT4ge1xuICAgICAgICBjb25zdCB3aXJlRm9ybWF0UGFyYW1zID0ge1xuICAgICAgICAgICAgc2VsbF90b2tlbjogcGFyYW1zLnNlbGxUb2tlbi5hZGRyZXNzLFxuICAgICAgICAgICAgYnV5X3Rva2VuOiBwYXJhbXMuYnV5VG9rZW4uYWRkcmVzcyxcbiAgICAgICAgICAgIHNlbGxfYW1vdW50OiBwYXJhbXMuc2VsbEFtb3VudFxuICAgICAgICB9O1xuICAgICAgICBpZiAocGFyYW1zLnJlY2lwaWVudCkge1xuICAgICAgICAgICAgd2lyZUZvcm1hdFBhcmFtc1tcInJlY2lwaWVudFwiXSA9IHBhcmFtcy5yZWNpcGllbnQ7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHBhcmFtcy5yb3V0ZVRocm91Z2gpIHtcbiAgICAgICAgICAgIHdpcmVGb3JtYXRQYXJhbXNbXCJyb3V0ZV90aHJvdWdoXCJdID0gcGFyYW1zLnJvdXRlVGhyb3VnaDtcbiAgICAgICAgfVxuICAgICAgICBpZiAocGFyYW1zLmxpcXVpZGl0eVNvdXJjZSkge1xuICAgICAgICAgICAgd2lyZUZvcm1hdFBhcmFtc1tcImxpcXVpZGl0eV9zb3VyY2VcIl0gPSBwYXJhbXMubGlxdWlkaXR5U291cmNlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChwYXJhbXMuc2xpcHBhZ2VUb2xlcmFuY2UpIHtcbiAgICAgICAgICAgIHdpcmVGb3JtYXRQYXJhbXNbXCJzbGlwcGFnZV90b2xlcmFuY2VcIl0gPSBwYXJhbXMuc2xpcHBhZ2VUb2xlcmFuY2U7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdGhpcy5wcm92aWRlckZvckFQSXNSZXF1aXJpbmdBdXRoQWRkcmVzc0ZpZWxkXy5yZXF1ZXN0KHtcbiAgICAgICAgICAgIG1ldGhvZDogXCJldWxpdGhfc3dhcFwiLFxuICAgICAgICAgICAgcGFyYW1zOiBbd2lyZUZvcm1hdFBhcmFtc11cbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBbcmVzdWx0LnByaWNlID8/IDAuMCwgcmVzdWx0LnR4c107XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogIFNlbmQgYSBzZXJpZXMgb2YgdHJhbnNhY3Rpb25zIChldWxpdGhfc2VuZF9hbmRfc2lnbl90cmFuc2FjdGlvbiksIGFuZCB3YWl0IGZvciBlYWNoIHRvIGJlIGNvbmZpcm1lZCxcbiAgICAgKiAgcmV0dXJuaW5nIHRoZSB0cmFuc2FjdGlvbiByZWNlaXB0cyBvZiBlYWNoLlxuICAgICAqXG4gICAgICogIEF0IGFueSBwb2ludCwgb25lIG9mIHRoZW0gY291bGQgZmFpbCwgd2l0aCBzb21lIGhhdmluZyBnb25lIG9uIHRvIGNvbXBsZXRpb24uIFRoaXMgcHJvY2VzcyBhYm9ydHMgYXQgdGhhdCB0aW1lXG4gICAgICogIGFuZCBvZmZlcnMgbm8gY2x1ZXMgYWJvdXQgaG93IG1hbnkgd2VyZSBwcm9jZXNzZWQgKGNvdWxkIGluY2x1ZGUgdGhlIGNvbXBsZXRlZCBvbmVzIGluIGEgc3BlY2lhbCBleGNlcHRpb24pXG4gICAgICpcbiAgICAgKiBAcGFyYW0gdHhzXG4gICAgICogQHJldHVybnNcbiAgICAgKi9cbiAgICBhc3luYyBldWxpdGhfc2VuZF9tdWx0aV90cmFuc2FjdGlvbih0eHM6IFRyYW5zYWN0aW9uQ29uZmlnW10pOiBQcm9taXNlPFRyYW5zYWN0aW9uUmVjZWlwdFtdPiB7XG4gICAgICAgIGxldCByZXN1bHRzID0gW107XG4gICAgICAgIGlmICh0aGlzLnNpZ25lcl8gPT0gbnVsbCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiVGhpcyBBUEkgcmVxdWlyZXMgYSB2YWxpZCBzaWduZXIgcHJvdmlkZWQgdG8gdGhlIEV1bGl0aFdlYjMgb2JqZWN0XCIpO1xuICAgICAgICB9XG4gICAgICAgIC8vIGFjY3VtdWxhdGUgYWxsIHRoZSBwcm9taXNlcywgYW5kIHdhaXQgYWxsIGF0IG9uY2VcbiAgICAgICAgbGV0IHByb21pc2VzID0gW107XG4gICAgICAgIGZvciAoY29uc3QgdHggb2YgdHhzKSB7XG4gICAgICAgICAgICBjb25zdCB0eEhhc2g6IHN0cmluZyA9IGF3YWl0IHRoaXMucHJvdmlkZXIuc2lnbkFuZFNlbmRUcmFuc2FjdGlvbih0eCwgdGhpcy5zaWduZXIpO1xuICAgICAgICAgICAgY29uc3QgdHhSZWNlaXB0OiBUcmFuc2FjdGlvblJlY2VpcHQgPSBhd2FpdCB0aGlzLmV0aC5nZXRUcmFuc2FjdGlvblJlY2VpcHQodHhIYXNoKTtcbiAgICAgICAgICAgIHJlc3VsdHMucHVzaCh0eFJlY2VpcHQpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHRzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqICBSZXR1cm5zIHRoZSBwcm92aWRlciBvYmplY3QgYXNzb2NpYXRlZCB3aXRoIHRoaXMgdHJhbnNhY3Rpb24uXG4gICAgICpcbiAgICAgKiAgQHRvZG8gTk9URSBkdWUgdG8gcXVpcmtzIG9mIGhvdyB3ZSBpbXBsZW1lbnQgc2lnbmluZywgYW5kIGNsb25pbmcgZXRjLCB0aGlzIG1pZ2h0IG5vdCBiZSB0aGUgc2FtZVxuICAgICAqICAgICAgICBwcm92aWRlciwgYnV0IGluc3RlYWQgb25lIGRlcmlldmVkIGZyb20gLSB0aGUgb3JpZ2luYWwgb25lIHByb3ZpZGVkIGluIHRoZSBjb25zdHJ1Y3Rvci5cbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0IHByb3ZpZGVyKCk6IEV1bGl0aC5Qcm92aWRlciB7XG4gICAgICAgIHJldHVybiB0aGlzLnByb3ZpZGVyRm9yQVBJc1JlcXVpcmluZ0F1dGhBZGRyZXNzRmllbGRfO1xuICAgIH1cblxuICAgIHByaXZhdGUgc2lnbmVyXz86IEV1bGl0aC5TaWduaW5nLlNpZ25pbmdTZXJ2aWNlO1xuICAgIHByaXZhdGUgbG9nZ2VyXzogRXVsaXRoLkxvZ2dpbmcuSUxvZ2dlcjtcblxuICAgIC8vIFNvbWUgQVBJcyBuZWVkIGEgc3BlY2lhbCBVUkwgc2V0IChpbmNsdWRlIGF1dGhfYWRkcmVzcyksIHNvIHJlZGlyZWN0IHRob3NlIHRocm91Z2ggdGhpcyB3ZWIzanMgaW5zdGFuY2VcbiAgICBwcml2YXRlIHByb3ZpZGVyRm9yQVBJc1JlcXVpcmluZ0F1dGhBZGRyZXNzRmllbGRfOiBFdWxpdGguUHJvdmlkZXI7XG59XG4iXX0=