UNPKG

eulith-web3js-core

Version:

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

187 lines 22.5 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.FlashLiquidity = void 0; const web3_1 = __importDefault(require("web3")); const Eulith = __importStar(require("../src/index")); // # this is based on the uniswap fee standard, which the server adheres to for other protocols // # 500 is 5 bips = 0.05% const INT_FEE_TO_FLOAT_DIVISOR = 1000000; /** * This maps to the python API FlashRequest */ class PayDefinition { } /** * typedef Eulith.FlashLiquidity * * Create a loan or swap for the extent of a transacation. * * What is a flash (loan/swap)? * * Put simply, a flash loan/swap gives you access to liquidity at the START of a transaction * provided you pay it back at the end. Otherwise, the whole transaction reverts. * * Eulith supports flash loans & swaps from Aave and Uniswap. The fee for the loan depends on the provider: * o Uniswap: 0.05%, 0.3% or 1% (depending on which fee the specific pool is using) * o Aave: 0.09% * * It acts as a nested transaction. * * Example Usage: * ~~~ * // in the context of an AtomicTx - which must be commited * const flashPay: Eulith.FlashLiquidity = await Eulith.FlashLiquidity.start({ * parentTx: atomicTx, * paymentDef: { * take: takeTokenContract, * pay: payTokenContract, * takeAmount: takeAmount, * payTransferFrom: acct.address, * recipient: acct.address * } * }); * console.log( * `The price was ${flashPay.price}, and the fee was: ${flashPay.feePct}% - aka ${flashPay.feeAmt * .map((a) => a.asDisplayString) * .join(",")}` * ); * await flashPay.commit(); * ~~~ */ class FlashLiquidity extends Eulith.AtomicTx.NestedTransaction { constructor({ parentTx }) { super({ parentTx }); } /** * returns fee (float) as percent; * The fee is applied to all tokens converted. * See feeAmt for the actual fees. */ get feePct() { return this.feePct_; } /** * Returns the fee for this transaction as a list of token values (since the fee may comprise multiple values for multiple tokens) */ get feeAmt() { return this.feeAmt_; } /** */ get price() { return this.price_; } /** * Start the argument 'loan' flashloan, nested inside the argument 'parentTx' transaction */ static start({ parentTx, loan, paymentDef }) { return __awaiter(this, void 0, void 0, function* () { if (loan) { const flashLoan = new FlashLiquidity({ parentTx }); const res = yield flashLoan.provider.request(loan.generateLoanRequest()); flashLoan.feePct_ = web3_1.default.utils.toNumber(res) / INT_FEE_TO_FLOAT_DIVISOR; flashLoan.feeAmt_ = loan.tokenValues.map((a) => a.cloneWithNewValue(a.asFloat * 100 * flashLoan.feePct_)); return flashLoan; } else if (paymentDef) { const flashPay = new FlashLiquidity({ parentTx }); if (paymentDef.take.options.address == paymentDef.pay.options.address) { // Because of how NestedTransaction works CURRENTLY, doesn't matter WHICH one we return, // so leverage Eulith.FlashLoan code, and just ignore its result, and return this subatomictx. // Will need to refactor if/when we correct design of NestedTransaction to truely be integrated with // AtomicTx and generalize atomictx mechanism. const flashLoan = yield Eulith.FlashLiquidity.start({ parentTx: parentTx, loan: new Eulith.Uniswap.LoanRequest({ borrowTokenA: paymentDef.take, borrowAmountA: paymentDef.takeAmount, borrowTokenB: null, borrowAmountB: null, payTransferFrom: paymentDef.payTransferFrom, recipient: paymentDef.recipient }) }); flashPay.feePct_ = flashLoan.feePct; flashPay.feeAmt_ = flashLoan.feeAmt; flashPay.price_ = 1.0; // If it's a loan, price is 1. There is no exchange } else { const quote = yield Eulith.Uniswap.getBestPriceQuote({ swapQuoteRequest: { sellToken: paymentDef.pay, buyToken: paymentDef.take, amount: paymentDef.takeAmount, trueForAmountIn: false }, recipient: paymentDef.recipient, fillOrKill: true, payTransferFrom: paymentDef.payTransferFrom, provider: flashPay.provider }); const swapAtomicTx = yield Eulith.Uniswap.startSwap({ request: quote.swapRequest, parentTx }); // @todo CLEANUP KLUGE (as part of cleaning up subtx objects). // Uniswap.startSwap creates a subAtomicTx (NestedTransaction), but that doesn't matter - drop it on the floor and return // this as the NestedTransaction (since its a subclass). // Still gets one call to subatomictx.commit() // // NOTE BOTH FlashLiquidity and the result of Unitswap.startSwap() are atomicTx objects. the 'data' // for each is essentially just a provider with teh right URL (atomictx) flag. And they share the same // implmentation (no overrides). // So this is a CHEAT. // // The LOGICALLY CORRECT thing todo here would be to return an atomicTx (or more precisely flashLiquidity subcalss of atomic tx) // that DELEGATED to the above swapAtomicTx. But thats alot of typing for now change to what goes over the wire. // --LGP 2023-04-05 flashPay.feePct_ = quote.feePct; flashPay.feeAmt_ = [quote.feeAmt]; flashPay.price_ = quote.price; } return flashPay; } }); } } exports.FlashLiquidity = FlashLiquidity; /** * This maps to the python API FlashRequest */ FlashLiquidity.PayDefinition = PayDefinition; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmxhc2gtbGlxdWlkaXR5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2ZsYXNoLWxpcXVpZGl0eS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLGdEQUF3QjtBQUd4QixxREFBdUM7QUFFdkMsK0ZBQStGO0FBQy9GLDBCQUEwQjtBQUMxQixNQUFNLHdCQUF3QixHQUFHLE9BQU8sQ0FBQztBQVF6Qzs7R0FFRztBQUNILE1BQU0sYUFBYTtDQU1sQjtBQUVEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FvQ0c7QUFDSCxNQUFhLGNBQWUsU0FBUSxNQUFNLENBQUMsUUFBUSxDQUFDLGlCQUFpQjtJQU1qRSxZQUFvQixFQUFFLFFBQVEsRUFBNkM7UUFDdkUsS0FBSyxDQUFDLEVBQUUsUUFBUSxFQUFFLENBQUMsQ0FBQztJQUN4QixDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILElBQVcsTUFBTTtRQUNiLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQztJQUN4QixDQUFDO0lBRUQ7O09BRUc7SUFDSCxJQUFXLE1BQU07UUFDYixPQUFPLElBQUksQ0FBQyxPQUFPLENBQUM7SUFDeEIsQ0FBQztJQUVEO09BQ0c7SUFDSCxJQUFXLEtBQUs7UUFDWixPQUFPLElBQUksQ0FBQyxNQUFNLENBQUM7SUFDdkIsQ0FBQztJQUVEOztPQUVHO0lBQ0ksTUFBTSxDQUFPLEtBQUssQ0FBQyxFQUN0QixRQUFRLEVBQ1IsSUFBSSxFQUNKLFVBQVUsRUFLYjs7WUFDRyxJQUFJLElBQUksRUFBRTtnQkFDTixNQUFNLFNBQVMsR0FBRyxJQUFJLGNBQWMsQ0FBQyxFQUFFLFFBQVEsRUFBRSxDQUFDLENBQUM7Z0JBQ25ELE1BQU0sR0FBRyxHQUFHLE1BQU0sU0FBUyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLG1CQUFtQixFQUFFLENBQUMsQ0FBQztnQkFDekUsU0FBUyxDQUFDLE9BQU8sR0FBSSxjQUFJLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQVksR0FBRyx3QkFBd0IsQ0FBQztnQkFDcEYsU0FBUyxDQUFDLE9BQU8sR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLGlCQUFpQixDQUFDLENBQUMsQ0FBQyxPQUFPLEdBQUcsR0FBRyxHQUFHLFNBQVMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO2dCQUMxRyxPQUFPLFNBQVMsQ0FBQzthQUNwQjtpQkFBTSxJQUFJLFVBQVUsRUFBRTtnQkFDbkIsTUFBTSxRQUFRLEdBQUcsSUFBSSxjQUFjLENBQUMsRUFBRSxRQUFRLEVBQUUsQ0FBQyxDQUFDO2dCQUVsRCxJQUFJLFVBQVUsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sSUFBSSxVQUFVLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxPQUFPLEVBQUU7b0JBQ25FLHdGQUF3RjtvQkFDeEYsOEZBQThGO29CQUM5RixvR0FBb0c7b0JBQ3BHLDhDQUE4QztvQkFDOUMsTUFBTSxTQUFTLEdBQTBCLE1BQU0sTUFBTSxDQUFDLGNBQWMsQ0FBQyxLQUFLLENBQUM7d0JBQ3ZFLFFBQVEsRUFBRSxRQUFRO3dCQUNsQixJQUFJLEVBQUUsSUFBSSxNQUFNLENBQUMsT0FBTyxDQUFDLFdBQVcsQ0FBQzs0QkFDakMsWUFBWSxFQUFFLFVBQVUsQ0FBQyxJQUFJOzRCQUM3QixhQUFhLEVBQUUsVUFBVSxDQUFDLFVBQVU7NEJBQ3BDLFlBQVksRUFBRSxJQUFJOzRCQUNsQixhQUFhLEVBQUUsSUFBSTs0QkFDbkIsZUFBZSxFQUFFLFVBQVUsQ0FBQyxlQUFlOzRCQUMzQyxTQUFTLEVBQUUsVUFBVSxDQUFDLFNBQVM7eUJBQ2xDLENBQUM7cUJBQ0wsQ0FBQyxDQUFDO29CQUNILFFBQVEsQ0FBQyxPQUFPLEdBQUcsU0FBUyxDQUFDLE1BQU0sQ0FBQztvQkFDcEMsUUFBUSxDQUFDLE9BQU8sR0FBRyxTQUFTLENBQUMsTUFBTSxDQUFDO29CQUNwQyxRQUFRLENBQUMsTUFBTSxHQUFHLEdBQUcsQ0FBQyxDQUFDLG1EQUFtRDtpQkFDN0U7cUJBQU07b0JBQ0gsTUFBTSxLQUFLLEdBQUcsTUFBTSxNQUFNLENBQUMsT0FBTyxDQUFDLGlCQUFpQixDQUFDO3dCQUNqRCxnQkFBZ0IsRUFBRTs0QkFDZCxTQUFTLEVBQUUsVUFBVSxDQUFDLEdBQUc7NEJBQ3pCLFFBQVEsRUFBRSxVQUFVLENBQUMsSUFBSTs0QkFDekIsTUFBTSxFQUFFLFVBQVUsQ0FBQyxVQUFVOzRCQUM3QixlQUFlLEVBQUUsS0FBSzt5QkFDekI7d0JBQ0QsU0FBUyxFQUFFLFVBQVUsQ0FBQyxTQUFTO3dCQUMvQixVQUFVLEVBQUUsSUFBSTt3QkFDaEIsZUFBZSxFQUFFLFVBQVUsQ0FBQyxlQUFlO3dCQUMzQyxRQUFRLEVBQUUsUUFBUSxDQUFDLFFBQVE7cUJBQzlCLENBQUMsQ0FBQztvQkFDSCxNQUFNLFlBQVksR0FBc0MsTUFBTSxNQUFNLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQzt3QkFDbkYsT0FBTyxFQUFFLEtBQUssQ0FBQyxXQUFXO3dCQUMxQixRQUFRO3FCQUNYLENBQUMsQ0FBQztvQkFDSCw4REFBOEQ7b0JBQzlELHlIQUF5SDtvQkFDekgsd0RBQXdEO29CQUN4RCw4Q0FBOEM7b0JBQzlDLEVBQUU7b0JBQ0YsbUdBQW1HO29CQUNuRyxzR0FBc0c7b0JBQ3RHLGdDQUFnQztvQkFDaEMsc0JBQXNCO29CQUN0QixFQUFFO29CQUNGLGdJQUFnSTtvQkFDaEksZ0hBQWdIO29CQUNoSCx3QkFBd0I7b0JBQ3hCLFFBQVEsQ0FBQyxPQUFPLEdBQUcsS0FBSyxDQUFDLE1BQU0sQ0FBQztvQkFDaEMsUUFBUSxDQUFDLE9BQU8sR0FBRyxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQztvQkFDbEMsUUFBUSxDQUFDLE1BQU0sR0FBRyxLQUFLLENBQUMsS0FBSyxDQUFDO2lCQUNqQztnQkFDRCxPQUFPLFFBQVEsQ0FBQzthQUNuQjtRQUNMLENBQUM7S0FBQTs7QUE1R0wsd0NBaUhDO0FBaEhHOztHQUVHO0FBQ1csNEJBQWEsR0FBRyxhQUFhLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgV2ViMyBmcm9tIFwid2ViM1wiO1xuaW1wb3J0IHsgUmVxdWVzdEFyZ3VtZW50cyB9IGZyb20gXCJ3ZWIzLWNvcmVcIjtcblxuaW1wb3J0ICogYXMgRXVsaXRoIGZyb20gXCIuLi9zcmMvaW5kZXhcIjtcblxuLy8gIyB0aGlzIGlzIGJhc2VkIG9uIHRoZSB1bmlzd2FwIGZlZSBzdGFuZGFyZCwgd2hpY2ggdGhlIHNlcnZlciBhZGhlcmVzIHRvIGZvciBvdGhlciBwcm90b2NvbHNcbi8vICMgNTAwIGlzIDUgYmlwcyA9IDAuMDUlXG5jb25zdCBJTlRfRkVFX1RPX0ZMT0FUX0RJVklTT1IgPSAxMDAwMDAwO1xuXG4vLyBAdG9kbyBjbGVhbnVwIGJ1dCBhdCBsZWFzdCBhbGwgbm93IHByaXZhdGVcbmludGVyZmFjZSBJRmxhc2hMb2FuYWJsZVgge1xuICAgIGdlbmVyYXRlTG9hblJlcXVlc3QoKTogUmVxdWVzdEFyZ3VtZW50cztcbiAgICBnZXQgdG9rZW5WYWx1ZXMoKTogRXVsaXRoLlRva2Vucy5WYWx1ZS5JVG9rZW5WYWx1ZVtdO1xufVxuXG4vKipcbiAqICBUaGlzIG1hcHMgdG8gdGhlIHB5dGhvbiBBUEkgRmxhc2hSZXF1ZXN0XG4gKi9cbmNsYXNzIFBheURlZmluaXRpb24ge1xuICAgIHRha2U6IEV1bGl0aC5Db250cmFjdHMuRVJDMjBUb2tlbkNvbnRyYWN0O1xuICAgIHBheTogRXVsaXRoLkNvbnRyYWN0cy5FUkMyMFRva2VuQ29udHJhY3Q7XG4gICAgdGFrZUFtb3VudDogbnVtYmVyO1xuICAgIHJlY2lwaWVudD86IHN0cmluZztcbiAgICBwYXlUcmFuc2ZlckZyb20/OiBzdHJpbmc7XG59XG5cbi8qKlxuICogdHlwZWRlZiBFdWxpdGguRmxhc2hMaXF1aWRpdHlcbiAqXG4gKiAgQ3JlYXRlIGEgbG9hbiBvciBzd2FwIGZvciB0aGUgZXh0ZW50IG9mIGEgdHJhbnNhY2F0aW9uLlxuICpcbiAqIFdoYXQgaXMgYSBmbGFzaCAobG9hbi9zd2FwKT9cbiAqXG4gKiAgICAgIFB1dCBzaW1wbHksIGEgZmxhc2ggbG9hbi9zd2FwIGdpdmVzIHlvdSBhY2Nlc3MgdG8gbGlxdWlkaXR5IGF0IHRoZSBTVEFSVCBvZiBhIHRyYW5zYWN0aW9uXG4gKiAgICAgIHByb3ZpZGVkIHlvdSBwYXkgaXQgYmFjayBhdCB0aGUgZW5kLiBPdGhlcndpc2UsIHRoZSB3aG9sZSB0cmFuc2FjdGlvbiByZXZlcnRzLlxuICpcbiAqICAgICAgRXVsaXRoIHN1cHBvcnRzIGZsYXNoIGxvYW5zICYgc3dhcHMgZnJvbSBBYXZlIGFuZCBVbmlzd2FwLiBUaGUgZmVlIGZvciB0aGUgbG9hbiBkZXBlbmRzIG9uIHRoZSBwcm92aWRlcjpcbiAqICAgICAgICAgIG8gICBVbmlzd2FwOiAwLjA1JSwgMC4zJSBvciAxJSAoZGVwZW5kaW5nIG9uIHdoaWNoIGZlZSB0aGUgc3BlY2lmaWMgcG9vbCBpcyB1c2luZylcbiAqICAgICAgICAgIG8gICBBYXZlOiAwLjA5JVxuICpcbiAqICBJdCBhY3RzIGFzIGEgbmVzdGVkIHRyYW5zYWN0aW9uLlxuICpcbiAqICBFeGFtcGxlIFVzYWdlOlxuICogICAgICB+fn5cbiAqICAgICAgICAgIC8vIGluIHRoZSBjb250ZXh0IG9mIGFuIEF0b21pY1R4IC0gd2hpY2ggbXVzdCBiZSBjb21taXRlZFxuICogICAgICAgICAgY29uc3QgZmxhc2hQYXk6IEV1bGl0aC5GbGFzaExpcXVpZGl0eSA9IGF3YWl0IEV1bGl0aC5GbGFzaExpcXVpZGl0eS5zdGFydCh7XG4gKiAgICAgICAgICAgICAgcGFyZW50VHg6IGF0b21pY1R4LFxuICogICAgICAgICAgICAgIHBheW1lbnREZWY6IHtcbiAqICAgICAgICAgICAgICAgICAgdGFrZTogdGFrZVRva2VuQ29udHJhY3QsXG4gKiAgICAgICAgICAgICAgICAgIHBheTogcGF5VG9rZW5Db250cmFjdCxcbiAqICAgICAgICAgICAgICAgICAgdGFrZUFtb3VudDogdGFrZUFtb3VudCxcbiAqICAgICAgICAgICAgICAgICAgcGF5VHJhbnNmZXJGcm9tOiBhY2N0LmFkZHJlc3MsXG4gKiAgICAgICAgICAgICAgICAgIHJlY2lwaWVudDogYWNjdC5hZGRyZXNzXG4gKiAgICAgICAgICAgICAgfVxuICogICAgICAgICAgfSk7XG4gKiAgICAgICAgICBjb25zb2xlLmxvZyhcbiAqICAgICAgICAgICAgICBgVGhlIHByaWNlIHdhcyAke2ZsYXNoUGF5LnByaWNlfSwgYW5kIHRoZSBmZWUgd2FzOiAke2ZsYXNoUGF5LmZlZVBjdH0lIC0gYWthICR7Zmxhc2hQYXkuZmVlQW10XG4gKiAgICAgICAgICAgICAgICAgIC5tYXAoKGEpID0+IGEuYXNEaXNwbGF5U3RyaW5nKVxuICogICAgICAgICAgICAgICAgICAuam9pbihcIixcIil9YFxuICogICAgICAgICAgKTtcbiAqICAgICAgICAgIGF3YWl0IGZsYXNoUGF5LmNvbW1pdCgpO1xuICogICAgICB+fn5cbiAqL1xuZXhwb3J0IGNsYXNzIEZsYXNoTGlxdWlkaXR5IGV4dGVuZHMgRXVsaXRoLkF0b21pY1R4Lk5lc3RlZFRyYW5zYWN0aW9uIHtcbiAgICAvKipcbiAgICAgKiAgVGhpcyBtYXBzIHRvIHRoZSBweXRob24gQVBJIEZsYXNoUmVxdWVzdFxuICAgICAqL1xuICAgIHB1YmxpYyBzdGF0aWMgUGF5RGVmaW5pdGlvbiA9IFBheURlZmluaXRpb247XG5cbiAgICBwcml2YXRlIGNvbnN0cnVjdG9yKHsgcGFyZW50VHggfTogeyBwYXJlbnRUeDogRXVsaXRoLkF0b21pY1R4LlRyYW5zYWN0aW9uIH0pIHtcbiAgICAgICAgc3VwZXIoeyBwYXJlbnRUeCB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiAgcmV0dXJucyBmZWUgKGZsb2F0KSBhcyBwZXJjZW50O1xuICAgICAqICBUaGUgZmVlIGlzIGFwcGxpZWQgdG8gYWxsIHRva2VucyBjb252ZXJ0ZWQuXG4gICAgICogIFNlZSBmZWVBbXQgZm9yIHRoZSBhY3R1YWwgZmVlcy5cbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0IGZlZVBjdCgpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gdGhpcy5mZWVQY3RfO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqICBSZXR1cm5zIHRoZSBmZWUgZm9yIHRoaXMgdHJhbnNhY3Rpb24gYXMgYSBsaXN0IG9mIHRva2VuIHZhbHVlcyAoc2luY2UgdGhlIGZlZSBtYXkgY29tcHJpc2UgbXVsdGlwbGUgdmFsdWVzIGZvciBtdWx0aXBsZSB0b2tlbnMpXG4gICAgICovXG4gICAgcHVibGljIGdldCBmZWVBbXQoKTogRXVsaXRoLlRva2Vucy5WYWx1ZS5JVG9rZW5WYWx1ZVtdIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZmVlQW10XztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0IHByaWNlKCk6IG51bWJlciB7XG4gICAgICAgIHJldHVybiB0aGlzLnByaWNlXztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTdGFydCB0aGUgYXJndW1lbnQgJ2xvYW4nIGZsYXNobG9hbiwgbmVzdGVkIGluc2lkZSB0aGUgYXJndW1lbnQgJ3BhcmVudFR4JyB0cmFuc2FjdGlvblxuICAgICAqL1xuICAgIHB1YmxpYyBzdGF0aWMgYXN5bmMgc3RhcnQoe1xuICAgICAgICBwYXJlbnRUeCxcbiAgICAgICAgbG9hbixcbiAgICAgICAgcGF5bWVudERlZlxuICAgIH06IHtcbiAgICAgICAgcGFyZW50VHg6IEV1bGl0aC5BdG9taWNUeC5UcmFuc2FjdGlvbjtcbiAgICAgICAgbG9hbj86IEV1bGl0aC5GbGFzaExpcXVpZGl0eS5JRmxhc2hMb2FuYWJsZTtcbiAgICAgICAgcGF5bWVudERlZj86IFBheURlZmluaXRpb247XG4gICAgfSk6IFByb21pc2U8Rmxhc2hMaXF1aWRpdHk+IHtcbiAgICAgICAgaWYgKGxvYW4pIHtcbiAgICAgICAgICAgIGNvbnN0IGZsYXNoTG9hbiA9IG5ldyBGbGFzaExpcXVpZGl0eSh7IHBhcmVudFR4IH0pO1xuICAgICAgICAgICAgY29uc3QgcmVzID0gYXdhaXQgZmxhc2hMb2FuLnByb3ZpZGVyLnJlcXVlc3QobG9hbi5nZW5lcmF0ZUxvYW5SZXF1ZXN0KCkpO1xuICAgICAgICAgICAgZmxhc2hMb2FuLmZlZVBjdF8gPSAoV2ViMy51dGlscy50b051bWJlcihyZXMpIGFzIG51bWJlcikgLyBJTlRfRkVFX1RPX0ZMT0FUX0RJVklTT1I7XG4gICAgICAgICAgICBmbGFzaExvYW4uZmVlQW10XyA9IGxvYW4udG9rZW5WYWx1ZXMubWFwKChhKSA9PiBhLmNsb25lV2l0aE5ld1ZhbHVlKGEuYXNGbG9hdCAqIDEwMCAqIGZsYXNoTG9hbi5mZWVQY3RfKSk7XG4gICAgICAgICAgICByZXR1cm4gZmxhc2hMb2FuO1xuICAgICAgICB9IGVsc2UgaWYgKHBheW1lbnREZWYpIHtcbiAgICAgICAgICAgIGNvbnN0IGZsYXNoUGF5ID0gbmV3IEZsYXNoTGlxdWlkaXR5KHsgcGFyZW50VHggfSk7XG5cbiAgICAgICAgICAgIGlmIChwYXltZW50RGVmLnRha2Uub3B0aW9ucy5hZGRyZXNzID09IHBheW1lbnREZWYucGF5Lm9wdGlvbnMuYWRkcmVzcykge1xuICAgICAgICAgICAgICAgIC8vIEJlY2F1c2Ugb2YgaG93IE5lc3RlZFRyYW5zYWN0aW9uIHdvcmtzIENVUlJFTlRMWSwgZG9lc24ndCBtYXR0ZXIgV0hJQ0ggb25lIHdlIHJldHVybixcbiAgICAgICAgICAgICAgICAvLyBzbyBsZXZlcmFnZSBFdWxpdGguRmxhc2hMb2FuIGNvZGUsIGFuZCBqdXN0IGlnbm9yZSBpdHMgcmVzdWx0LCBhbmQgcmV0dXJuIHRoaXMgc3ViYXRvbWljdHguXG4gICAgICAgICAgICAgICAgLy8gV2lsbCBuZWVkIHRvIHJlZmFjdG9yIGlmL3doZW4gd2UgY29ycmVjdCBkZXNpZ24gb2YgTmVzdGVkVHJhbnNhY3Rpb24gdG8gdHJ1ZWx5IGJlIGludGVncmF0ZWQgd2l0aFxuICAgICAgICAgICAgICAgIC8vIEF0b21pY1R4IGFuZCBnZW5lcmFsaXplIGF0b21pY3R4IG1lY2hhbmlzbS5cbiAgICAgICAgICAgICAgICBjb25zdCBmbGFzaExvYW46IEV1bGl0aC5GbGFzaExpcXVpZGl0eSA9IGF3YWl0IEV1bGl0aC5GbGFzaExpcXVpZGl0eS5zdGFydCh7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudFR4OiBwYXJlbnRUeCxcbiAgICAgICAgICAgICAgICAgICAgbG9hbjogbmV3IEV1bGl0aC5Vbmlzd2FwLkxvYW5SZXF1ZXN0KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJvcnJvd1Rva2VuQTogcGF5bWVudERlZi50YWtlLFxuICAgICAgICAgICAgICAgICAgICAgICAgYm9ycm93QW1vdW50QTogcGF5bWVudERlZi50YWtlQW1vdW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgYm9ycm93VG9rZW5COiBudWxsLFxuICAgICAgICAgICAgICAgICAgICAgICAgYm9ycm93QW1vdW50QjogbnVsbCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHBheVRyYW5zZmVyRnJvbTogcGF5bWVudERlZi5wYXlUcmFuc2ZlckZyb20sXG4gICAgICAgICAgICAgICAgICAgICAgICByZWNpcGllbnQ6IHBheW1lbnREZWYucmVjaXBpZW50XG4gICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgZmxhc2hQYXkuZmVlUGN0XyA9IGZsYXNoTG9hbi5mZWVQY3Q7XG4gICAgICAgICAgICAgICAgZmxhc2hQYXkuZmVlQW10XyA9IGZsYXNoTG9hbi5mZWVBbXQ7XG4gICAgICAgICAgICAgICAgZmxhc2hQYXkucHJpY2VfID0gMS4wOyAvLyBJZiBpdCdzIGEgbG9hbiwgcHJpY2UgaXMgMS4gVGhlcmUgaXMgbm8gZXhjaGFuZ2VcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc3QgcXVvdGUgPSBhd2FpdCBFdWxpdGguVW5pc3dhcC5nZXRCZXN0UHJpY2VRdW90ZSh7XG4gICAgICAgICAgICAgICAgICAgIHN3YXBRdW90ZVJlcXVlc3Q6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGxUb2tlbjogcGF5bWVudERlZi5wYXksXG4gICAgICAgICAgICAgICAgICAgICAgICBidXlUb2tlbjogcGF5bWVudERlZi50YWtlLFxuICAgICAgICAgICAgICAgICAgICAgICAgYW1vdW50OiBwYXltZW50RGVmLnRha2VBbW91bnQsXG4gICAgICAgICAgICAgICAgICAgICAgICB0cnVlRm9yQW1vdW50SW46IGZhbHNlXG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIHJlY2lwaWVudDogcGF5bWVudERlZi5yZWNpcGllbnQsXG4gICAgICAgICAgICAgICAgICAgIGZpbGxPcktpbGw6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgIHBheVRyYW5zZmVyRnJvbTogcGF5bWVudERlZi5wYXlUcmFuc2ZlckZyb20sXG4gICAgICAgICAgICAgICAgICAgIHByb3ZpZGVyOiBmbGFzaFBheS5wcm92aWRlclxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGNvbnN0IHN3YXBBdG9taWNUeDogRXVsaXRoLkF0b21pY1R4Lk5lc3RlZFRyYW5zYWN0aW9uID0gYXdhaXQgRXVsaXRoLlVuaXN3YXAuc3RhcnRTd2FwKHtcbiAgICAgICAgICAgICAgICAgICAgcmVxdWVzdDogcXVvdGUuc3dhcFJlcXVlc3QsXG4gICAgICAgICAgICAgICAgICAgIHBhcmVudFR4XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgLy8gQHRvZG8gQ0xFQU5VUCBLTFVHRSAoYXMgcGFydCBvZiBjbGVhbmluZyB1cCBzdWJ0eCBvYmplY3RzKS5cbiAgICAgICAgICAgICAgICAvLyBVbmlzd2FwLnN0YXJ0U3dhcCBjcmVhdGVzIGEgc3ViQXRvbWljVHggKE5lc3RlZFRyYW5zYWN0aW9uKSwgYnV0IHRoYXQgZG9lc24ndCBtYXR0ZXIgLSBkcm9wIGl0IG9uIHRoZSBmbG9vciBhbmQgcmV0dXJuXG4gICAgICAgICAgICAgICAgLy8gdGhpcyBhcyB0aGUgTmVzdGVkVHJhbnNhY3Rpb24gKHNpbmNlIGl0cyBhIHN1YmNsYXNzKS5cbiAgICAgICAgICAgICAgICAvLyBTdGlsbCBnZXRzIG9uZSBjYWxsIHRvIHN1YmF0b21pY3R4LmNvbW1pdCgpXG4gICAgICAgICAgICAgICAgLy9cbiAgICAgICAgICAgICAgICAvLyBOT1RFIEJPVEggRmxhc2hMaXF1aWRpdHkgYW5kIHRoZSByZXN1bHQgb2YgVW5pdHN3YXAuc3RhcnRTd2FwKCkgYXJlIGF0b21pY1R4IG9iamVjdHMuIHRoZSAnZGF0YSdcbiAgICAgICAgICAgICAgICAvLyBmb3IgZWFjaCBpcyBlc3NlbnRpYWxseSBqdXN0IGEgcHJvdmlkZXIgd2l0aCB0ZWggcmlnaHQgVVJMIChhdG9taWN0eCkgZmxhZy4gQW5kIHRoZXkgc2hhcmUgdGhlIHNhbWVcbiAgICAgICAgICAgICAgICAvLyBpbXBsbWVudGF0aW9uIChubyBvdmVycmlkZXMpLlxuICAgICAgICAgICAgICAgIC8vIFNvIHRoaXMgaXMgYSBDSEVBVC5cbiAgICAgICAgICAgICAgICAvL1xuICAgICAgICAgICAgICAgIC8vIFRoZSBMT0dJQ0FMTFkgQ09SUkVDVCB0aGluZyB0b2RvIGhlcmUgd291bGQgYmUgdG8gcmV0dXJuIGFuIGF0b21pY1R4IChvciBtb3JlIHByZWNpc2VseSBmbGFzaExpcXVpZGl0eSBzdWJjYWxzcyBvZiBhdG9taWMgdHgpXG4gICAgICAgICAgICAgICAgLy8gdGhhdCBERUxFR0FURUQgdG8gdGhlIGFib3ZlIHN3YXBBdG9taWNUeC4gQnV0IHRoYXRzIGFsb3Qgb2YgdHlwaW5nIGZvciBub3cgY2hhbmdlIHRvIHdoYXQgZ29lcyBvdmVyIHRoZSB3aXJlLlxuICAgICAgICAgICAgICAgIC8vICAgICAgLS1MR1AgMjAyMy0wNC0wNVxuICAgICAgICAgICAgICAgIGZsYXNoUGF5LmZlZVBjdF8gPSBxdW90ZS5mZWVQY3Q7XG4gICAgICAgICAgICAgICAgZmxhc2hQYXkuZmVlQW10XyA9IFtxdW90ZS5mZWVBbXRdO1xuICAgICAgICAgICAgICAgIGZsYXNoUGF5LnByaWNlXyA9IHF1b3RlLnByaWNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGZsYXNoUGF5O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBwcmljZV86IG51bWJlcjtcbiAgICBwcml2YXRlIGZlZVBjdF86IG51bWJlcjtcbiAgICBwcml2YXRlIGZlZUFtdF86IEV1bGl0aC5Ub2tlbnMuVmFsdWUuSVRva2VuVmFsdWVbXTtcbn1cblxuZXhwb3J0IGRlY2xhcmUgbW9kdWxlIEZsYXNoTGlxdWlkaXR5IHtcbiAgICBleHBvcnQgdHlwZSBJRmxhc2hMb2FuYWJsZSA9IElGbGFzaExvYW5hYmxlWDtcbn1cbiJdfQ==