eulith-web3js-core
Version:
Eulith core web3js SDK (code to access Eulith services via web3js)
187 lines • 22.5 kB
JavaScript
;
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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmxhc2gtbGlxdWlkaXR5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2ZsYXNoLWxpcXVpZGl0eS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLGdEQUF3QjtBQUd4QixxREFBdUM7QUFFdkMsK0ZBQStGO0FBQy9GLDBCQUEwQjtBQUMxQixNQUFNLHdCQUF3QixHQUFHLE9BQU8sQ0FBQztBQVF6Qzs7R0FFRztBQUNILE1BQU0sYUFBYTtDQU1sQjtBQUVEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FvQ0c7QUFDSCxNQUFhLGNBQWUsU0FBUSxNQUFNLENBQUMsUUFBUSxDQUFDLGlCQUFpQjtJQU1qRSxZQUFvQixFQUFFLFFBQVEsRUFBNkM7UUFDdkUsS0FBSyxDQUFDLEVBQUUsUUFBUSxFQUFFLENBQUMsQ0FBQztJQUN4QixDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILElBQVcsTUFBTTtRQUNiLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQztJQUN4QixDQUFDO0lBRUQ7O09BRUc7SUFDSCxJQUFXLE1BQU07UUFDYixPQUFPLElBQUksQ0FBQyxPQUFPLENBQUM7SUFDeEIsQ0FBQztJQUVEO09BQ0c7SUFDSCxJQUFXLEtBQUs7UUFDWixPQUFPLElBQUksQ0FBQyxNQUFNLENBQUM7SUFDdkIsQ0FBQztJQUVEOztPQUVHO0lBQ0ksTUFBTSxDQUFPLEtBQUssQ0FBQyxFQUN0QixRQUFRLEVBQ1IsSUFBSSxFQUNKLFVBQVUsRUFLYjs7WUFDRyxJQUFJLElBQUksRUFBRTtnQkFDTixNQUFNLFNBQVMsR0FBRyxJQUFJLGNBQWMsQ0FBQyxFQUFFLFFBQVEsRUFBRSxDQUFDLENBQUM7Z0JBQ25ELE1BQU0sR0FBRyxHQUFHLE1BQU0sU0FBUyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLG1CQUFtQixFQUFFLENBQUMsQ0FBQztnQkFD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QjtRQUNMLENBQUM7S0FBQTs7QUE1R0wsd0NBaUhDO0FBaEhHOztHQUVHO0FBQ1csNEJBQWEsR0FBRyxhQUFhLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgV2ViMyBmcm9tIFwid2ViM1wiO1xuaW1wb3J0IHsgUmVxdWVzdEFyZ3VtZW50cyB9IGZyb20gXCJ3ZWIzLWNvcmVcIjtcblxuaW1wb3J0ICogYXMgRXVsaXRoIGZyb20gXCIuLi9zcmMvaW5kZXhcIjtcblxuLy8gIyB0aGlzIGlzIGJhc2VkIG9uIHRoZSB1bmlzd2FwIGZlZSBzdGFuZGFyZCwgd2hpY2ggdGhlIHNlcnZlciBhZGhlcmVzIHRvIGZvciBvdGhlciBwcm90b2NvbHNcbi8vICMgNTAwIGlzIDUgYmlwcyA9IDAuMDUlXG5jb25zdCBJTlRfRkVFX1RPX0ZMT0FUX0RJVklTT1IgPSAxMDAwMDAwO1xuXG4vLyBAdG9kbyBjbGVhbnVwIGJ1dCBhdCBsZWFzdCBhbGwgbm93IHByaXZhdGVcbmludGVyZmFjZSBJRmxhc2hMb2FuYWJsZVgge1xuICAgIGdlbmVyYXRlTG9hblJlcXVlc3QoKTogUmVxdWVzdEFyZ3VtZW50cztcbiAgICBnZXQgdG9rZW5WYWx1ZXMoKTogRXVsaXRoLlRva2Vucy5WYWx1ZS5JVG9rZW5WYWx1ZVtdO1xufVxuXG4vKipcbiAqICBUaGlzIG1hcHMgdG8gdGhlIHB5dGhvbiBBUEkgRmxhc2hSZXF1ZXN0XG4gKi9cbmNsYXNzIFBheURlZmluaXRpb24ge1xuICAgIHRha2U6IEV1bGl0aC5Db250cmFjdHMuRVJDMjBUb2tlbkNvbnRyYWN0O1xuICAgIHBheTogRXVsaXRoLkNvbnRyYWN0cy5FUkMyMFRva2VuQ29udHJhY3Q7XG4gICAgdGFrZUFtb3VudDogbnVtYmVyO1xuICAgIHJlY2lwaWVudD86IHN0cmluZztcbiAgICBwYXlUcmFuc2ZlckZyb20/OiBzdHJpbmc7XG59XG5cbi8qKlxuICogdHlwZWRlZiBFdWxpdGguRmxhc2hMaXF1aWRpdHlcbiAqXG4gKiAgQ3JlYXRlIGEgbG9hbiBvciBzd2FwIGZvciB0aGUgZXh0ZW50IG9mIGEgdHJhbnNhY2F0aW9uLlxuICpcbiAqIFdoYXQgaXMgYSBmbGFzaCAobG9hbi9zd2FwKT9cbiAqXG4gKiAgICAgIFB1dCBzaW1wbHksIGEgZmxhc2ggbG9hbi9zd2FwIGdpdmVzIHlvdSBhY2Nlc3MgdG8gbGlxdWlkaXR5IGF0IHRoZSBTVEFSVCBvZiBhIHRyYW5zYWN0aW9uXG4gKiAgICAgIHByb3ZpZGVkIHlvdSBwYXkgaXQgYmFjayBhdCB0aGUgZW5kLiBPdGhlcndpc2UsIHRoZSB3aG9sZSB0cmFuc2FjdGlvbiByZXZlcnRzLlxuICpcbiAqICAgICAgRXVsaXRoIHN1cHBvcnRzIGZsYXNoIGxvYW5zICYgc3dhcHMgZnJvbSBBYXZlIGFuZCBVbmlzd2FwLiBUaGUgZmVlIGZvciB0aGUgbG9hbiBkZXBlbmRzIG9uIHRoZSBwcm92aWRlcjpcbiAqICAgICAgICAgIG8gICBVbmlzd2FwOiAwLjA1JSwgMC4zJSBvciAxJSAoZGVwZW5kaW5nIG9uIHdoaWNoIGZlZSB0aGUgc3BlY2lmaWMgcG9vbCBpcyB1c2luZylcbiAqICAgICAgICAgIG8gICBBYXZlOiAwLjA5JVxuICpcbiAqICBJdCBhY3RzIGFzIGEgbmVzdGVkIHRyYW5zYWN0aW9uLlxuICpcbiAqICBFeGFtcGxlIFVzYWdlOlxuICogICAgICB+fn5cbiAqICAgICAgICAgIC8vIGluIHRoZSBjb250ZXh0IG9mIGFuIEF0b21pY1R4IC0gd2hpY2ggbXVzdCBiZSBjb21taXRlZFxuICogICAgICAgICAgY29uc3QgZmxhc2hQYXk6IEV1bGl0aC5GbGFzaExpcXVpZGl0eSA9IGF3YWl0IEV1bGl0aC5GbGFzaExpcXVpZGl0eS5zdGFydCh7XG4gKiAgICAgICAgICAgICAgcGFyZW50VHg6IGF0b21pY1R4LFxuICogICAgICAgICAgICAgIHBheW1lbnREZWY6IHtcbiAqICAgICAgICAgICAgICAgICAgdGFrZTogdGFrZVRva2VuQ29udHJhY3QsXG4gKiAgICAgICAgICAgICAgICAgIHBheTogcGF5VG9rZW5Db250cmFjdCxcbiAqICAgICAgICAgICAgICAgICAgdGFrZUFtb3VudDogdGFrZUFtb3VudCxcbiAqICAgICAgICAgICAgICAgICAgcGF5VHJhbnNmZXJGcm9tOiBhY2N0LmFkZHJlc3MsXG4gKiAgICAgICAgICAgICAgICAgIHJlY2lwaWVudDogYWNjdC5hZGRyZXNzXG4gKiAgICAgICAgICAgICAgfVxuICogICAgICAgICAgfSk7XG4gKiAgICAgICAgICBjb25zb2xlLmxvZyhcbiAqICAgICAgICAgICAgICBgVGhlIHByaWNlIHdhcyAke2ZsYXNoUGF5LnByaWNlfSwgYW5kIHRoZSBmZWUgd2FzOiAke2ZsYXNoUGF5LmZlZVBjdH0lIC0gYWthICR7Zmxhc2hQYXkuZmVlQW10XG4gKiAgICAgICAgICAgICAgICAgIC5tYXAoKGEpID0+IGEuYXNEaXNwbGF5U3RyaW5nKVxuICogICAgICAgICAgICAgICAgICAuam9pbihcIixcIil9YFxuICogICAgICAgICAgKTtcbiAqICAgICAgICAgIGF3YWl0IGZsYXNoUGF5LmNvbW1pdCgpO1xuICogICAgICB+fn5cbiAqL1xuZXhwb3J0IGNsYXNzIEZsYXNoTGlxdWlkaXR5IGV4dGVuZHMgRXVsaXRoLkF0b21pY1R4Lk5lc3RlZFRyYW5zYWN0aW9uIHtcbiAgICAvKipcbiAgICAgKiAgVGhpcyBtYXBzIHRvIHRoZSBweXRob24gQVBJIEZsYXNoUmVxdWVzdFxuICAgICAqL1xuICAgIHB1YmxpYyBzdGF0aWMgUGF5RGVmaW5pdGlvbiA9IFBheURlZmluaXRpb247XG5cbiAgICBwcml2YXRlIGNvbnN0cnVjdG9yKHsgcGFyZW50VHggfTogeyBwYXJlbnRUeDogRXVsaXRoLkF0b21pY1R4LlRyYW5zYWN0aW9uIH0pIHtcbiAgICAgICAgc3VwZXIoeyBwYXJlbnRUeCB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiAgcmV0dXJucyBmZWUgKGZsb2F0KSBhcyBwZXJjZW50O1xuICAgICAqICBUaGUgZmVlIGlzIGFwcGxpZWQgdG8gYWxsIHRva2VucyBjb252ZXJ0ZWQuXG4gICAgICogIFNlZSBmZWVBbXQgZm9yIHRoZSBhY3R1YWwgZmVlcy5cbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0IGZlZVBjdCgpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gdGhpcy5mZWVQY3RfO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqICBSZXR1cm5zIHRoZSBmZWUgZm9yIHRoaXMgdHJhbnNhY3Rpb24gYXMgYSBsaXN0IG9mIHRva2VuIHZhbHVlcyAoc2luY2UgdGhlIGZlZSBtYXkgY29tcHJpc2UgbXVsdGlwbGUgdmFsdWVzIGZvciBtdWx0aXBsZSB0b2tlbnMpXG4gICAgICovXG4gICAgcHVibGljIGdldCBmZWVBbXQoKTogRXVsaXRoLlRva2Vucy5WYWx1ZS5JVG9rZW5WYWx1ZVtdIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZmVlQW10XztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0IHByaWNlKCk6IG51bWJlciB7XG4gICAgICAgIHJldHVybiB0aGlzLnByaWNlXztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTdGFydCB0aGUgYXJndW1lbnQgJ2xvYW4nIGZsYXNobG9hbiwgbmVzdGVkIGluc2lkZSB0aGUgYXJndW1lbnQgJ3BhcmVudFR4JyB0cmFuc2FjdGlvblxuICAgICAqL1xuICAgIHB1YmxpYyBzdGF0aWMgYXN5bmMgc3RhcnQoe1xuICAgICAgICBwYXJlbnRUeCxcbiAgICAgICAgbG9hbixcbiAgICAgICAgcGF5bWVudERlZlxuICAgIH06IHtcbiAgICAgICAgcGFyZW50VHg6IEV1bGl0aC5BdG9taWNUeC5UcmFuc2FjdGlvbjtcbiAgICAgICAgbG9hbj86IEV1bGl0aC5GbGFzaExpcXVpZGl0eS5JRmxhc2hMb2FuYWJsZTtcbiAgICAgICAgcGF5bWVudERlZj86IFBheURlZmluaXRpb247XG4gICAgfSk6IFByb21pc2U8Rmxhc2hMaXF1aWRpdHk+IHtcbiAgICAgICAgaWYgKGxvYW4pIHtcbiAgICAgICAgICAgIGNvbnN0IGZsYXNoTG9hbiA9IG5ldyBGbGFzaExpcXVpZGl0eSh7IHBhcmVudFR4IH0pO1xuICAgICAgICAgICAgY29uc3QgcmVzID0gYXdhaXQgZmxhc2hMb2FuLnByb3ZpZGVyLnJlcXVlc3QobG9hbi5nZW5lcmF0ZUxvYW5SZXF1ZXN0KCkpO1xuICAgICAgICAgICAgZmxhc2hMb2FuLmZlZVBjdF8gPSAoV2ViMy51dGlscy50b051bWJlcihyZXMpIGFzIG51bWJlcikgLyBJTlRfRkVFX1RPX0ZMT0FUX0RJVklTT1I7XG4gICAgICAgICAgICBmbGFzaExvYW4uZmVlQW10XyA9IGxvYW4udG9rZW5WYWx1ZXMubWFwKChhKSA9PiBhLmNsb25lV2l0aE5ld1ZhbHVlKGEuYXNGbG9hdCAqIDEwMCAqIGZsYXNoTG9hbi5mZWVQY3RfKSk7XG4gICAgICAgICAgICByZXR1cm4gZmxhc2hMb2FuO1xuICAgICAgICB9IGVsc2UgaWYgKHBheW1lbnREZWYpIHtcbiAgICAgICAgICAgIGNvbnN0IGZsYXNoUGF5ID0gbmV3IEZsYXNoTGlxdWlkaXR5KHsgcGFyZW50VHggfSk7XG5cbiAgICAgICAgICAgIGlmIChwYXltZW50RGVmLnRha2Uub3B0aW9ucy5hZGRyZXNzID09IHBheW1lbnREZWYucGF5Lm9wdGlvbnMuYWRkcmVzcykge1xuICAgICAgICAgICAgICAgIC8vIEJlY2F1c2Ugb2YgaG93IE5lc3RlZFRyYW5zYWN0aW9uIHdvcmtzIENVUlJFTlRMWSwgZG9lc24ndCBtYXR0ZXIgV0hJQ0ggb25lIHdlIHJldHVybixcbiAgICAgICAgICAgICAgICAvLyBzbyBsZXZlcmFnZSBFdWxpdGguRmxhc2hMb2FuIGNvZGUsIGFuZCBqdXN0IGlnbm9yZSBpdHMgcmVzdWx0LCBhbmQgcmV0dXJuIHRoaXMgc3ViYXRvbWljdHguXG4gICAgICAgICAgICAgICAgLy8gV2lsbCBuZWVkIHRvIHJlZmFjdG9yIGlmL3doZW4gd2UgY29ycmVjdCBkZXNpZ24gb2YgTmVzdGVkVHJhbnNhY3Rpb24gdG8gdHJ1ZWx5IGJlIGludGVncmF0ZWQgd2l0aFxuICAgICAgICAgICAgICAgIC8vIEF0b21pY1R4IGFuZCBnZW5lcmFsaXplIGF0b21pY3R4IG1lY2hhbmlzbS5cbiAgICAgICAgICAgICAgICBjb25zdCBmbGFzaExvYW46IEV1bGl0aC5GbGFzaExpcXVpZGl0eSA9IGF3YWl0IEV1bGl0aC5GbGFzaExpcXVpZGl0eS5zdGFydCh7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudFR4OiBwYXJlbnRUeCxcbiAgICAgICAgICAgICAgICAgICAgbG9hbjogbmV3IEV1bGl0aC5Vbmlzd2FwLkxvYW5SZXF1ZXN0KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJvcnJvd1Rva2VuQTogcGF5bWVudERlZi50YWtlLFxuICAgICAgICAgICAgICAgICAgICAgICAgYm9ycm93QW1vdW50QTogcGF5bWVudERlZi50YWtlQW1vdW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgYm9ycm93VG9rZW5COiBudWxsLFxuICAgICAgICAgICAgICAgICAgICAgICAgYm9ycm93QW1vdW50QjogbnVsbCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHBheVRyYW5zZmVyRnJvbTogcGF5bWVudERlZi5wYXlUcmFuc2ZlckZyb20sXG4gICAgICAgICAgICAgICAgICAgICAgICByZWNpcGllbnQ6IHBheW1lbnREZWYucmVjaXBpZW50XG4gICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgZmxhc2hQYXkuZmVlUGN0XyA9IGZsYXNoTG9hbi5mZWVQY3Q7XG4gICAgICAgICAgICAgICAgZmxhc2hQYXkuZmVlQW10XyA9IGZsYXNoTG9hbi5mZWVBbXQ7XG4gICAgICAgICAgICAgICAgZmxhc2hQYXkucHJpY2VfID0gMS4wOyAvLyBJZiBpdCdzIGEgbG9hbiwgcHJpY2UgaXMgMS4gVGhlcmUgaXMgbm8gZXhjaGFuZ2VcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc3QgcXVvdGUgPSBhd2FpdCBFdWxpdGguVW5pc3dhcC5nZXRCZXN0UHJpY2VRdW90ZSh7XG4gICAgICAgICAgICAgICAgICAgIHN3YXBRdW90ZVJlcXVlc3Q6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGxUb2tlbjogcGF5bWVudERlZi5wYXksXG4gICAgICAgICAgICAgICAgICAgICAgICBidXlUb2tlbjogcGF5bWVudERlZi50YWtlLFxuICAgICAgICAgICAgICAgICAgICAgICAgYW1vdW50OiBwYXltZW50RGVmLnRha2VBbW91bnQsXG4gICAgICAgICAgICAgICAgICAgICAgICB0cnVlRm9yQW1vdW50SW46IGZhbHNlXG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIHJlY2lwaWVudDogcGF5bWVudERlZi5yZWNpcGllbnQsXG4gICAgICAgICAgICAgICAgICAgIGZpbGxPcktpbGw6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgIHBheVRyYW5zZmVyRnJvbTogcGF5bWVudERlZi5wYXlUcmFuc2ZlckZyb20sXG4gICAgICAgICAgICAgICAgICAgIHByb3ZpZGVyOiBmbGFzaFBheS5wcm92aWRlclxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGNvbnN0IHN3YXBBdG9taWNUeDogRXVsaXRoLkF0b21pY1R4Lk5lc3RlZFRyYW5zYWN0aW9uID0gYXdhaXQgRXVsaXRoLlVuaXN3YXAuc3RhcnRTd2FwKHtcbiAgICAgICAgICAgICAgICAgICAgcmVxdWVzdDogcXVvdGUuc3dhcFJlcXVlc3QsXG4gICAgICAgICAgICAgICAgICAgIHBhcmVudFR4XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgLy8gQHRvZG8gQ0xFQU5VUCBLTFVHRSAoYXMgcGFydCBvZiBjbGVhbmluZyB1cCBzdWJ0eCBvYmplY3RzKS5cbiAgICAgICAgICAgICAgICAvLyBVbmlzd2FwLnN0YXJ0U3dhcCBjcmVhdGVzIGEgc3ViQXRvbWljVHggKE5lc3RlZFRyYW5zYWN0aW9uKSwgYnV0IHRoYXQgZG9lc24ndCBtYXR0ZXIgLSBkcm9wIGl0IG9uIHRoZSBmbG9vciBhbmQgcmV0dXJuXG4gICAgICAgICAgICAgICAgLy8gdGhpcyBhcyB0aGUgTmVzdGVkVHJhbnNhY3Rpb24gKHNpbmNlIGl0cyBhIHN1YmNsYXNzKS5cbiAgICAgICAgICAgICAgICAvLyBTdGlsbCBnZXRzIG9uZSBjYWxsIHRvIHN1YmF0b21pY3R4LmNvbW1pdCgpXG4gICAgICAgICAgICAgICAgLy9cbiAgICAgICAgICAgICAgICAvLyBOT1RFIEJPVEggRmxhc2hMaXF1aWRpdHkgYW5kIHRoZSByZXN1bHQgb2YgVW5pdHN3YXAuc3RhcnRTd2FwKCkgYXJlIGF0b21pY1R4IG9iamVjdHMuIHRoZSAnZGF0YSdcbiAgICAgICAgICAgICAgICAvLyBmb3IgZWFjaCBpcyBlc3NlbnRpYWxseSBqdXN0IGEgcHJvdmlkZXIgd2l0aCB0ZWggcmlnaHQgVVJMIChhdG9taWN0eCkgZmxhZy4gQW5kIHRoZXkgc2hhcmUgdGhlIHNhbWVcbiAgICAgICAgICAgICAgICAvLyBpbXBsbWVudGF0aW9uIChubyBvdmVycmlkZXMpLlxuICAgICAgICAgICAgICAgIC8vIFNvIHRoaXMgaXMgYSBDSEVBVC5cbiAgICAgICAgICAgICAgICAvL1xuICAgICAgICAgICAgICAgIC8vIFRoZSBMT0dJQ0FMTFkgQ09SUkVDVCB0aGluZyB0b2RvIGhlcmUgd291bGQgYmUgdG8gcmV0dXJuIGFuIGF0b21pY1R4IChvciBtb3JlIHByZWNpc2VseSBmbGFzaExpcXVpZGl0eSBzdWJjYWxzcyBvZiBhdG9taWMgdHgpXG4gICAgICAgICAgICAgICAgLy8gdGhhdCBERUxFR0FURUQgdG8gdGhlIGFib3ZlIHN3YXBBdG9taWNUeC4gQnV0IHRoYXRzIGFsb3Qgb2YgdHlwaW5nIGZvciBub3cgY2hhbmdlIHRvIHdoYXQgZ29lcyBvdmVyIHRoZSB3aXJlLlxuICAgICAgICAgICAgICAgIC8vICAgICAgLS1MR1AgMjAyMy0wNC0wNVxuICAgICAgICAgICAgICAgIGZsYXNoUGF5LmZlZVBjdF8gPSBxdW90ZS5mZWVQY3Q7XG4gICAgICAgICAgICAgICAgZmxhc2hQYXkuZmVlQW10XyA9IFtxdW90ZS5mZWVBbXRdO1xuICAgICAgICAgICAgICAgIGZsYXNoUGF5LnByaWNlXyA9IHF1b3RlLnByaWNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGZsYXNoUGF5O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBwcmljZV86IG51bWJlcjtcbiAgICBwcml2YXRlIGZlZVBjdF86IG51bWJlcjtcbiAgICBwcml2YXRlIGZlZUFtdF86IEV1bGl0aC5Ub2tlbnMuVmFsdWUuSVRva2VuVmFsdWVbXTtcbn1cblxuZXhwb3J0IGRlY2xhcmUgbW9kdWxlIEZsYXNoTGlxdWlkaXR5IHtcbiAgICBleHBvcnQgdHlwZSBJRmxhc2hMb2FuYWJsZSA9IElGbGFzaExvYW5hYmxlWDtcbn1cbiJdfQ==