send-crypto
Version:
A minimal JavaScript library / wallet for sending crypto assets
167 lines • 19.8 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 __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ZECHandler = exports._apiFallbacks = void 0;
const bignumber_js_1 = __importDefault(require("bignumber.js"));
const bitcoin = __importStar(require("bitgo-utxo-lib"));
const immutable_1 = require("immutable");
const insight_1 = require("../../common/apis/insight");
const jsonrpc_1 = require("../../common/apis/jsonrpc");
const sochain_1 = require("../../common/apis/sochain");
const bitgoUtxoLib_1 = require("../../common/libraries/bitgoUtxoLib");
const confirmations_1 = require("../../lib/confirmations");
const promiEvent_1 = require("../../lib/promiEvent");
const retry_1 = require("../../lib/retry");
const utils_1 = require("../../lib/utils");
var InsightEndpoints;
(function (InsightEndpoints) {
// Testnet
InsightEndpoints["TestnetZCash"] = "https://explorer.testnet.z.cash/api/";
// Mainnet
InsightEndpoints["ZCash"] = "https://explorer.z.cash/api/";
InsightEndpoints["ZecBlockExplorer"] = "https://zecblockexplorer.com/api/";
InsightEndpoints["ZecChain"] = "https://zechain.net/api/v1/";
InsightEndpoints["BlockExplorer"] = "https://zcash.blockexplorer.com/api/";
})(InsightEndpoints || (InsightEndpoints = {}));
exports._apiFallbacks = {
fetchUTXO: (testnet, txHash, vOut) => testnet
? [
...(0, utils_1.shuffleArray)(() => insight_1.Insight.fetchUTXO(InsightEndpoints.TestnetZCash)(txHash, vOut)),
() => sochain_1.Sochain.fetchUTXO("ZECTEST")(txHash, vOut),
]
: [
...(0, utils_1.shuffleArray)(() => insight_1.Insight.fetchUTXO(InsightEndpoints.ZCash)(txHash, vOut), () => insight_1.Insight.fetchUTXO(InsightEndpoints.ZecBlockExplorer)(txHash, vOut)),
() => insight_1.Insight.fetchUTXO(InsightEndpoints.ZecChain)(txHash, vOut),
() => insight_1.Insight.fetchUTXO(InsightEndpoints.BlockExplorer)(txHash, vOut),
],
fetchUTXOs: (testnet, address, confirmations) => testnet
? [
...(0, utils_1.shuffleArray)(() => insight_1.Insight.fetchUTXOs(InsightEndpoints.TestnetZCash)(address, confirmations)),
() => sochain_1.Sochain.fetchUTXOs("ZECTEST")(address, confirmations),
]
: [
...(0, utils_1.shuffleArray)(() => insight_1.Insight.fetchUTXOs(InsightEndpoints.ZCash)(address, confirmations), () => insight_1.Insight.fetchUTXOs(InsightEndpoints.ZecBlockExplorer)(address, confirmations)),
() => sochain_1.Sochain.fetchUTXOs("ZEC")(address, confirmations),
() => insight_1.Insight.fetchUTXOs(InsightEndpoints.ZecChain)(address, confirmations),
() => insight_1.Insight.fetchUTXOs(InsightEndpoints.BlockExplorer)(address, confirmations),
],
fetchTXs: (testnet, address, confirmations = 0) => testnet
? [
...(0, utils_1.shuffleArray)(() => insight_1.Insight.fetchTXs(InsightEndpoints.TestnetZCash)(address, confirmations)),
() => sochain_1.Sochain.fetchTXs("ZECTEST")(address, confirmations),
]
: [
...(0, utils_1.shuffleArray)(() => insight_1.Insight.fetchTXs(InsightEndpoints.ZCash)(address, confirmations), () => insight_1.Insight.fetchTXs(InsightEndpoints.ZecBlockExplorer)(address, confirmations)),
() => sochain_1.Sochain.fetchTXs("ZEC")(address, confirmations),
() => insight_1.Insight.fetchTXs(InsightEndpoints.ZecChain)(address, confirmations),
() => insight_1.Insight.fetchTXs(InsightEndpoints.BlockExplorer)(address, confirmations),
],
broadcastTransaction: (testnet, hex) => testnet
? [
() => jsonrpc_1.JSONRPC.broadcastTransaction(jsonrpc_1.MULTICHAIN_URLS.ZECTEST)(hex),
() => insight_1.Insight.broadcastTransaction(InsightEndpoints.TestnetZCash)(hex),
() => sochain_1.Sochain.broadcastTransaction("ZECTEST")(hex),
]
: [
...(0, utils_1.shuffleArray)(() => insight_1.Insight.broadcastTransaction(InsightEndpoints.ZCash)(hex), () => insight_1.Insight.broadcastTransaction(InsightEndpoints.ZecBlockExplorer)(hex), () => sochain_1.Sochain.broadcastTransaction("ZEC")(hex)),
() => insight_1.Insight.broadcastTransaction(InsightEndpoints.ZecChain)(hex),
() => insight_1.Insight.broadcastTransaction(InsightEndpoints.BlockExplorer)(hex),
() => jsonrpc_1.JSONRPC.broadcastTransaction(jsonrpc_1.MULTICHAIN_URLS.ZEC)(hex),
],
};
class ZECHandler {
constructor(privateKey, network) {
this.decimals = 8;
// Returns whether or not this can handle the asset
this.handlesAsset = (asset) => typeof asset === "string" &&
["ZEC", "ZCASH"].indexOf(asset.toUpperCase()) !== -1;
this.address = async (asset, options) => this.privateKey.getAddress();
// Balance
this.getBalance = async (asset, options) => (await this.getBalanceInSats(asset, options)).dividedBy(new bignumber_js_1.default(10).exponentiatedBy(this.decimals));
this.getBalanceInSats = async (asset, options) => {
const utxos = await ZECHandler.getUTXOs(this.testnet, Object.assign(Object.assign({}, options), { address: (options && options.address) || (await this.address(asset)) }));
return utxos.reduce((sum, utxo) => sum.plus(utxo.amount), new bignumber_js_1.default(0));
};
// Transfer
this.send = (to, value, asset, options) => this.sendSats(to, value.times(new bignumber_js_1.default(10).exponentiatedBy(this.decimals)), asset, options);
this.sendSats = (to, valueIn, asset, options) => {
const promiEvent = (0, promiEvent_1.newPromiEvent)();
let txHash;
let errored;
(async () => {
const fromAddress = await this.address(asset);
const changeAddress = fromAddress;
const utxos = (0, immutable_1.List)(await ZECHandler.getUTXOs(this.testnet, Object.assign(Object.assign({}, options), { address: fromAddress })))
.sortBy((utxo) => utxo.amount)
.reverse()
.toArray();
if (this.testnet) {
// tslint:disable-next-line: no-object-mutation
bitcoin.networks.zcashTest.consensusBranchId["4"] = 37519621;
}
const built = await bitgoUtxoLib_1.BitgoUTXOLib.buildUTXO(this.testnet
? bitcoin.networks.zcashTest
: bitcoin.networks.zcash, this.privateKey, changeAddress, to, valueIn, utxos, Object.assign(Object.assign({}, options), { version: 4, versionGroupID: 0x892f2085, consensusBranchId: 0x37519621 }));
txHash = await (0, retry_1.retryNTimes)(() => (0, retry_1.fallback)(exports._apiFallbacks.broadcastTransaction(this.testnet, built.toHex())), 3);
promiEvent.emit("transactionHash", txHash);
promiEvent.resolve(txHash);
})().catch((error) => {
errored = true;
promiEvent.reject(error);
});
(0, confirmations_1.subscribeToConfirmations)(promiEvent, () => errored, async () => (txHash ? this._getConfirmations(txHash) : 0));
return promiEvent;
};
this._getConfirmations = async (txHash) => (await (0, retry_1.fallback)(
// Fetch confirmations for first output of transaction.
exports._apiFallbacks.fetchUTXO(this.testnet, txHash, 0))).confirmations;
this.testnet = network !== "mainnet";
this.privateKey = bitgoUtxoLib_1.BitgoUTXOLib.loadPrivateKey(this.testnet ? bitcoin.networks.zcashTest : bitcoin.networks.zcash, privateKey);
}
}
exports.ZECHandler = ZECHandler;
_a = ZECHandler;
ZECHandler.getUTXOs = async (testnet, options) => {
const confirmations = options && options.confirmations !== undefined
? options.confirmations
: 0;
return (0, retry_1.fallback)(exports._apiFallbacks.fetchUTXOs(testnet, options.address, confirmations));
};
ZECHandler.getUTXO = async (testnet, txHash, vOut) => {
const endpoints = exports._apiFallbacks.fetchUTXO(testnet, txHash, vOut);
return (0, retry_1.fallback)(endpoints);
};
ZECHandler.getTransactions = async (testnet, options) => {
const confirmations = options && options.confirmations !== undefined
? options.confirmations
: 0;
const endpoints = exports._apiFallbacks.fetchTXs(testnet, options.address, confirmations);
return (0, retry_1.fallback)(endpoints);
};
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiWkVDSGFuZGxlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9oYW5kbGVycy9aRUMvWkVDSGFuZGxlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSxnRUFBcUM7QUFDckMsd0RBQTBDO0FBQzFDLHlDQUFpQztBQUVqQyx1REFBb0Q7QUFDcEQsdURBQXFFO0FBQ3JFLHVEQUFvRDtBQUNwRCxzRUFBbUU7QUFDbkUsMkRBQW1FO0FBQ25FLHFEQUFpRTtBQUNqRSwyQ0FBd0Q7QUFDeEQsMkNBQStDO0FBYy9DLElBQUssZ0JBUUo7QUFSRCxXQUFLLGdCQUFnQjtJQUNqQixVQUFVO0lBQ1YseUVBQXFELENBQUE7SUFDckQsVUFBVTtJQUNWLDBEQUFzQyxDQUFBO0lBQ3RDLDBFQUFzRCxDQUFBO0lBQ3RELDREQUF3QyxDQUFBO0lBQ3hDLDBFQUFzRCxDQUFBO0FBQzFELENBQUMsRUFSSSxnQkFBZ0IsS0FBaEIsZ0JBQWdCLFFBUXBCO0FBRVksUUFBQSxhQUFhLEdBQUc7SUFDekIsU0FBUyxFQUFFLENBQUMsT0FBZ0IsRUFBRSxNQUFjLEVBQUUsSUFBWSxFQUFFLEVBQUUsQ0FDMUQsT0FBTztRQUNILENBQUMsQ0FBQztZQUNJLEdBQUcsSUFBQSxvQkFBWSxFQUFDLEdBQUcsRUFBRSxDQUNqQixpQkFBTyxDQUFDLFNBQVMsQ0FBQyxnQkFBZ0IsQ0FBQyxZQUFZLENBQUMsQ0FDNUMsTUFBTSxFQUNOLElBQUksQ0FDUCxDQUNKO1lBQ0QsR0FBRyxFQUFFLENBQUMsaUJBQU8sQ0FBQyxTQUFTLENBQUMsU0FBUyxDQUFDLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQztTQUNuRDtRQUNILENBQUMsQ0FBQztZQUNJLEdBQUcsSUFBQSxvQkFBWSxFQUNYLEdBQUcsRUFBRSxDQUNELGlCQUFPLENBQUMsU0FBUyxDQUFDLGdCQUFnQixDQUFDLEtBQUssQ0FBQyxDQUNyQyxNQUFNLEVBQ04sSUFBSSxDQUNQLEVBQ0wsR0FBRyxFQUFFLENBQ0QsaUJBQU8sQ0FBQyxTQUFTLENBQUMsZ0JBQWdCLENBQUMsZ0JBQWdCLENBQUMsQ0FDaEQsTUFBTSxFQUNOLElBQUksQ0FDUCxDQUNSO1lBQ0QsR0FBRyxFQUFFLENBQ0QsaUJBQU8sQ0FBQyxTQUFTLENBQUMsZ0JBQWdCLENBQUMsUUFBUSxDQUFDLENBQ3hDLE1BQU0sRUFDTixJQUFJLENBQ1A7WUFDTCxHQUFHLEVBQUUsQ0FDRCxpQkFBTyxDQUFDLFNBQVMsQ0FBQyxnQkFBZ0IsQ0FBQyxhQUFhLENBQUMsQ0FDN0MsTUFBTSxFQUNOLElBQUksQ0FDUDtTQUNSO0lBRVgsVUFBVSxFQUFFLENBQUMsT0FBZ0IsRUFBRSxPQUFlLEVBQUUsYUFBcUIsRUFBRSxFQUFFLENBQ3JFLE9BQU87UUFDSCxDQUFDLENBQUM7WUFDSSxHQUFHLElBQUEsb0JBQVksRUFBQyxHQUFHLEVBQUUsQ0FDakIsaUJBQU8sQ0FBQyxVQUFVLENBQUMsZ0JBQWdCLENBQUMsWUFBWSxDQUFDLENBQzdDLE9BQU8sRUFDUCxhQUFhLENBQ2hCLENBQ0o7WUFDRCxHQUFHLEVBQUUsQ0FBQyxpQkFBTyxDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUMsQ0FBQyxPQUFPLEVBQUUsYUFBYSxDQUFDO1NBQzlEO1FBQ0gsQ0FBQyxDQUFDO1lBQ0ksR0FBRyxJQUFBLG9CQUFZLEVBQ1gsR0FBRyxFQUFFLENBQ0QsaUJBQU8sQ0FBQyxVQUFVLENBQUMsZ0JBQWdCLENBQUMsS0FBSyxDQUFDLENBQ3RDLE9BQU8sRUFDUCxhQUFhLENBQ2hCLEVBRUwsR0FBRyxFQUFFLENBQ0QsaUJBQU8sQ0FBQyxVQUFVLENBQUMsZ0JBQWdCLENBQUMsZ0JBQWdCLENBQUMsQ0FDakQsT0FBTyxFQUNQLGFBQWEsQ0FDaEIsQ0FDUjtZQUNELEdBQUcsRUFBRSxDQUFDLGlCQUFPLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDLE9BQU8sRUFBRSxhQUFhLENBQUM7WUFDdkQsR0FBRyxFQUFFLENBQ0QsaUJBQU8sQ0FBQyxVQUFVLENBQUMsZ0JBQWdCLENBQUMsUUFBUSxDQUFDLENBQ3pDLE9BQU8sRUFDUCxhQUFhLENBQ2hCO1lBQ0wsR0FBRyxFQUFFLENBQ0QsaUJBQU8sQ0FBQyxVQUFVLENBQUMsZ0JBQWdCLENBQUMsYUFBYSxDQUFDLENBQzlDLE9BQU8sRUFDUCxhQUFhLENBQ2hCO1NBQ1I7SUFFWCxRQUFRLEVBQUUsQ0FBQyxPQUFnQixFQUFFLE9BQWUsRUFBRSxnQkFBd0IsQ0FBQyxFQUFFLEVBQUUsQ0FDdkUsT0FBTztRQUNILENBQUMsQ0FBQztZQUNJLEdBQUcsSUFBQSxvQkFBWSxFQUFDLEdBQUcsRUFBRSxDQUNqQixpQkFBTyxDQUFDLFFBQVEsQ0FBQyxnQkFBZ0IsQ0FBQyxZQUFZLENBQUMsQ0FDM0MsT0FBTyxFQUNQLGFBQWEsQ0FDaEIsQ0FDSjtZQUNELEdBQUcsRUFBRSxDQUFDLGlCQUFPLENBQUMsUUFBUSxDQUFDLFNBQVMsQ0FBQyxDQUFDLE9BQU8sRUFBRSxhQUFhLENBQUM7U0FDNUQ7UUFDSCxDQUFDLENBQUM7WUFDSSxHQUFHLElBQUEsb0JBQVksRUFDWCxHQUFHLEVBQUUsQ0FDRCxpQkFBTyxDQUFDLFFBQVEsQ0FBQyxnQkFBZ0IsQ0FBQyxLQUFLLENBQUMsQ0FDcEMsT0FBTyxFQUNQLGFBQWEsQ0FDaEIsRUFFTCxHQUFHLEVBQUUsQ0FDRCxpQkFBTyxDQUFDLFFBQVEsQ0FBQyxnQkFBZ0IsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUMvQyxPQUFPLEVBQ1AsYUFBYSxDQUNoQixDQUNSO1lBQ0QsR0FBRyxFQUFFLENBQUMsaUJBQU8sQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUMsT0FBTyxFQUFFLGFBQWEsQ0FBQztZQUNyRCxHQUFHLEVBQUUsQ0FDRCxpQkFBTyxDQUFDLFFBQVEsQ0FBQyxnQkFBZ0IsQ0FBQyxRQUFRLENBQUMsQ0FDdkMsT0FBTyxFQUNQLGFBQWEsQ0FDaEI7WUFDTCxHQUFHLEVBQUUsQ0FDRCxpQkFBTyxDQUFDLFFBQVEsQ0FBQyxnQkFBZ0IsQ0FBQyxhQUFhLENBQUMsQ0FDNUMsT0FBTyxFQUNQLGFBQWEsQ0FDaEI7U0FDUjtJQUVYLG9CQUFvQixFQUFFLENBQUMsT0FBZ0IsRUFBRSxHQUFXLEVBQUUsRUFBRSxDQUNwRCxPQUFPO1FBQ0gsQ0FBQyxDQUFDO1lBQ0ksR0FBRyxFQUFFLENBQ0QsaUJBQU8sQ0FBQyxvQkFBb0IsQ0FBQyx5QkFBZSxDQUFDLE9BQU8sQ0FBQyxDQUNqRCxHQUFHLENBQ047WUFDTCxHQUFHLEVBQUUsQ0FDRCxpQkFBTyxDQUFDLG9CQUFvQixDQUN4QixnQkFBZ0IsQ0FBQyxZQUFZLENBQ2hDLENBQUMsR0FBRyxDQUFDO1lBQ1YsR0FBRyxFQUFFLENBQUMsaUJBQU8sQ0FBQyxvQkFBb0IsQ0FBQyxTQUFTLENBQUMsQ0FBQyxHQUFHLENBQUM7U0FDckQ7UUFDSCxDQUFDLENBQUM7WUFDSSxHQUFHLElBQUEsb0JBQVksRUFDWCxHQUFHLEVBQUUsQ0FDRCxpQkFBTyxDQUFDLG9CQUFvQixDQUFDLGdCQUFnQixDQUFDLEtBQUssQ0FBQyxDQUNoRCxHQUFHLENBQ04sRUFDTCxHQUFHLEVBQUUsQ0FDRCxpQkFBTyxDQUFDLG9CQUFvQixDQUN4QixnQkFBZ0IsQ0FBQyxnQkFBZ0IsQ0FDcEMsQ0FBQyxHQUFHLENBQUMsRUFDVixHQUFHLEVBQUUsQ0FBQyxpQkFBTyxDQUFDLG9CQUFvQixDQUFDLEtBQUssQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUNqRDtZQUNELEdBQUcsRUFBRSxDQUNELGlCQUFPLENBQUMsb0JBQW9CLENBQUMsZ0JBQWdCLENBQUMsUUFBUSxDQUFDLENBQ25ELEdBQUcsQ0FDTjtZQUNMLEdBQUcsRUFBRSxDQUNELGlCQUFPLENBQUMsb0JBQW9CLENBQ3hCLGdCQUFnQixDQUFDLGFBQWEsQ0FDakMsQ0FBQyxHQUFHLENBQUM7WUFDVixHQUFHLEVBQUUsQ0FBQyxpQkFBTyxDQUFDLG9CQUFvQixDQUFDLHlCQUFlLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDO1NBQy9EO0NBQ2QsQ0FBQztBQUVGLE1BQWEsVUFBVTtJQTZDbkIsWUFBWSxVQUFrQixFQUFFLE9BQWU7UUF6QzlCLGFBQVEsR0FBRyxDQUFDLENBQUM7UUFpRDlCLG1EQUFtRDtRQUNuQyxpQkFBWSxHQUFHLENBQUMsS0FBWSxFQUFXLEVBQUUsQ0FDckQsT0FBTyxLQUFLLEtBQUssUUFBUTtZQUN6QixDQUFDLEtBQUssRUFBRSxPQUFPLENBQUMsQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLFdBQVcsRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7UUFFekMsWUFBTyxHQUFHLEtBQUssRUFDM0IsS0FBWSxFQUNaLE9BQXdCLEVBQ1QsRUFBRSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsVUFBVSxFQUFFLENBQUM7UUFFbkQsVUFBVTtRQUNNLGVBQVUsR0FBRyxLQUFLLEVBQzlCLEtBQVksRUFDWixPQUF3QixFQUNOLEVBQUUsQ0FDcEIsQ0FBQyxNQUFNLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxLQUFLLEVBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQ25ELElBQUksc0JBQVMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUNuRCxDQUFDO1FBRVUscUJBQWdCLEdBQUcsS0FBSyxFQUNwQyxLQUFZLEVBQ1osT0FBd0IsRUFDTixFQUFFO1lBQ3BCLE1BQU0sS0FBSyxHQUFHLE1BQU0sVUFBVSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsT0FBTyxrQ0FDN0MsT0FBTyxLQUNWLE9BQU8sRUFDSCxDQUFDLE9BQU8sSUFBSSxPQUFPLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxNQUFNLElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsSUFDakUsQ0FBQztZQUNILE9BQU8sS0FBSyxDQUFDLE1BQU0sQ0FDZixDQUFDLEdBQUcsRUFBRSxJQUFJLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUNwQyxJQUFJLHNCQUFTLENBQUMsQ0FBQyxDQUFDLENBQ25CLENBQUM7UUFDTixDQUFDLENBQUM7UUFFRixXQUFXO1FBQ0ssU0FBSSxHQUFHLENBQ25CLEVBQVUsRUFDVixLQUFnQixFQUNoQixLQUFZLEVBQ1osT0FBbUIsRUFDRCxFQUFFLENBQ3BCLElBQUksQ0FBQyxRQUFRLENBQ1QsRUFBRSxFQUNGLEtBQUssQ0FBQyxLQUFLLENBQUMsSUFBSSxzQkFBUyxDQUFDLEVBQUUsQ0FBQyxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsRUFDN0QsS0FBSyxFQUNMLE9BQU8sQ0FDVixDQUFDO1FBRVUsYUFBUSxHQUFHLENBQ3ZCLEVBQVUsRUFDVixPQUFrQixFQUNsQixLQUFZLEVBQ1osT0FBbUIsRUFDRCxFQUFFO1lBQ3BCLE1BQU0sVUFBVSxHQUFHLElBQUEsMEJBQWEsR0FBVSxDQUFDO1lBRTNDLElBQUksTUFBYyxDQUFDO1lBQ25CLElBQUksT0FBZ0IsQ0FBQztZQUVyQixDQUFDLEtBQUssSUFBSSxFQUFFO2dCQUNSLE1BQU0sV0FBVyxHQUFHLE1BQU0sSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQztnQkFDOUMsTUFBTSxhQUFhLEdBQUcsV0FBVyxDQUFDO2dCQUNsQyxNQUFNLEtBQUssR0FBRyxJQUFBLGdCQUFJLEVBQ2QsTUFBTSxVQUFVLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxPQUFPLGtDQUMvQixPQUFPLEtBQ1YsT0FBTyxFQUFFLFdBQVcsSUFDdEIsQ0FDTDtxQkFDSSxNQUFNLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUM7cUJBQzdCLE9BQU8sRUFBRTtxQkFDVCxPQUFPLEVBQUUsQ0FBQztnQkFFZixJQUFJLElBQUksQ0FBQyxPQUFPLEVBQUU7b0JBQ2QsK0NBQStDO29CQUMvQyxPQUFPLENBQUMsUUFBUSxDQUFDLFNBQVMsQ0FBQyxpQkFBaUIsQ0FBQyxHQUFHLENBQUMsR0FBRyxRQUFRLENBQUM7aUJBQ2hFO2dCQUVELE1BQU0sS0FBSyxHQUFHLE1BQU0sMkJBQVksQ0FBQyxTQUFTLENBQ3RDLElBQUksQ0FBQyxPQUFPO29CQUNSLENBQUMsQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLFNBQVM7b0JBQzVCLENBQUMsQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLEtBQUssRUFDNUIsSUFBSSxDQUFDLFVBQVUsRUFDZixhQUFhLEVBQ2IsRUFBRSxFQUNGLE9BQU8sRUFDUCxLQUFLLGtDQUVFLE9BQU8sS0FDVixPQUFPLEVBQUUsQ0FBQyxFQUNWLGNBQWMsRUFBRSxVQUFVLEVBQzFCLGlCQUFpQixFQUFFLFVBQVUsSUFFcEMsQ0FBQztnQkFFRixNQUFNLEdBQUcsTUFBTSxJQUFBLG1CQUFXLEVBQ3RCLEdBQUcsRUFBRSxDQUNELElBQUEsZ0JBQVEsRUFDSixxQkFBYSxDQUFDLG9CQUFvQixDQUM5QixJQUFJLENBQUMsT0FBTyxFQUNaLEtBQUssQ0FBQyxLQUFLLEVBQUUsQ0FDaEIsQ0FDSixFQUNMLENBQUMsQ0FDSixDQUFDO2dCQUVGLFVBQVUsQ0FBQyxJQUFJLENBQUMsaUJBQWlCLEVBQUUsTUFBTSxDQUFDLENBQUM7Z0JBQzNDLFVBQVUsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDL0IsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRTtnQkFDakIsT0FBTyxHQUFHLElBQUksQ0FBQztnQkFDZixVQUFVLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQzdCLENBQUMsQ0FBQyxDQUFDO1lBRUgsSUFBQSx3Q0FBd0IsRUFDcEIsVUFBVSxFQUNWLEdBQUcsRUFBRSxDQUFDLE9BQU8sRUFDYixLQUFLLElBQUksRUFBRSxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUM1RCxDQUFDO1lBRUYsT0FBTyxVQUFVLENBQUM7UUFDdEIsQ0FBQyxDQUFDO1FBRWUsc0JBQWlCLEdBQUcsS0FBSyxFQUN0QyxNQUFjLEVBQ0MsRUFBRSxDQUNqQixDQUNJLE1BQU0sSUFBQSxnQkFBUTtRQUNWLHVEQUF1RDtRQUN2RCxxQkFBYSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FDbkQsQ0FDSixDQUFDLGFBQWEsQ0FBQztRQXhJaEIsSUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLEtBQUssU0FBUyxDQUFDO1FBQ3JDLElBQUksQ0FBQyxVQUFVLEdBQUcsMkJBQVksQ0FBQyxjQUFjLENBQ3pDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLEtBQUssRUFDbEUsVUFBVSxDQUNiLENBQUM7SUFDTixDQUFDOztBQW5ETCxnQ0F1TEM7O0FBakxVLG1CQUFRLEdBQUcsS0FBSyxFQUNuQixPQUFnQixFQUNoQixPQUFvRCxFQUM1QixFQUFFO0lBQzFCLE1BQU0sYUFBYSxHQUNmLE9BQU8sSUFBSSxPQUFPLENBQUMsYUFBYSxLQUFLLFNBQVM7UUFDMUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxhQUFhO1FBQ3ZCLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDWixPQUFPLElBQUEsZ0JBQVEsRUFDWCxxQkFBYSxDQUFDLFVBQVUsQ0FBQyxPQUFPLEVBQUUsT0FBTyxDQUFDLE9BQU8sRUFBRSxhQUFhLENBQUMsQ0FDcEUsQ0FBQztBQUNOLENBQUUsQ0FBQTtBQUVLLGtCQUFPLEdBQUcsS0FBSyxFQUNsQixPQUFnQixFQUNoQixNQUFjLEVBQ2QsSUFBWSxFQUNDLEVBQUU7SUFDZixNQUFNLFNBQVMsR0FBRyxxQkFBYSxDQUFDLFNBQVMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQ2pFLE9BQU8sSUFBQSxnQkFBUSxFQUFDLFNBQVMsQ0FBQyxDQUFDO0FBQy9CLENBQUUsQ0FBQTtBQUVLLDBCQUFlLEdBQUcsS0FBSyxFQUMxQixPQUFnQixFQUNoQixPQUFvRCxFQUM1QixFQUFFO0lBQzFCLE1BQU0sYUFBYSxHQUNmLE9BQU8sSUFBSSxPQUFPLENBQUMsYUFBYSxLQUFLLFNBQVM7UUFDMUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxhQUFhO1FBQ3ZCLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFFWixNQUFNLFNBQVMsR0FBRyxxQkFBYSxDQUFDLFFBQVEsQ0FDcEMsT0FBTyxFQUNQLE9BQU8sQ0FBQyxPQUFPLEVBQ2YsYUFBYSxDQUNoQixDQUFDO0lBQ0YsT0FBTyxJQUFBLGdCQUFRLEVBQUMsU0FBUyxDQUFDLENBQUM7QUFDL0IsQ0FBRSxDQUFBIn0=